LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PFParticleValidation_module.cc
Go to the documentation of this file.
1 
10 
13 
14 #include <string>
15 
16 //------------------------------------------------------------------------------------------------------------------------------------------
17 
18 namespace lar_pandora {
19 
24  public:
31 
35  virtual ~PFParticleValidation();
36 
37  void beginJob();
38  void endJob();
39  void analyze(const art::Event& evt);
40  void reconfigure(fhicl::ParameterSet const& pset);
41 
42  private:
47  public:
52 
60  bool operator<(const SimpleMCPrimary& rhs) const;
61 
62  int m_id;
63  int m_pdgCode;
65  int m_nMCHitsU;
66  int m_nMCHitsV;
67  int m_nMCHitsW;
68  float m_energy;
71  };
72 
73  typedef std::vector<SimpleMCPrimary> SimpleMCPrimaryList;
74 
79  public:
84 
85  int m_id;
86  int m_parentId;
87  int m_pdgCode;
97  };
98 
99  typedef std::vector<SimpleMatchedPfo> SimpleMatchedPfoList;
100 
105  public:
109  MatchingDetails();
110 
114  };
115 
116  typedef std::map<int, MatchingDetails> MatchingDetailsMap;
117  typedef std::map<SimpleMCPrimary, SimpleMatchedPfoList>
118  MCPrimaryMatchingMap; // SimpleMCPrimary has a defined operator<
119 
120  typedef std::map<art::Ptr<recob::PFParticle>, HitVector> PFParticleToMatchedHits;
121  typedef std::map<art::Ptr<simb::MCParticle>, PFParticleToMatchedHits> MCParticleMatchingMap;
122 
131  void GetMCParticleMatchingMap(const PFParticlesToHits& recoParticlesToHits,
132  const MCParticlesToHits& trueParticlesToHits,
133  const HitsToMCParticles& hitsToTrueParticles,
134  MCParticleMatchingMap& mcParticleMatchingMap) const;
135 
145  void GetSimpleMCPrimaryList(const art::Event& evt,
146  const MCParticlesToHits& mcParticlesToHits,
147  const HitsToMCParticles& hitsToMCParticles,
148  const MCParticleMatchingMap& mcParticleMatchingMap,
149  SimpleMCPrimaryList& simpleMCPrimaryList) const;
150 
159  void GetMCPrimaryMatchingMap(const SimpleMCPrimaryList& simpleMCPrimaryList,
160  const MCParticleMatchingMap& mcParticleMatchingMap,
161  const PFParticlesToHits& pfParticlesToHits,
162  MCPrimaryMatchingMap& mcPrimaryMatchingMap) const;
163 
172  bool IsNeutrinoInduced(const art::Ptr<simb::MCParticle> pMCParticle,
173  const MCParticlesToMCTruth& artMCParticlesToMCTruth) const;
174 
181  void GetMCTruth(const art::Event& evt, MCTruthVector& mcTruthVector) const;
182 
189  void GetRecoNeutrinos(const art::Event& evt, PFParticleVector& recoNeutrinoVector) const;
190 
198  void PrintAllOutput(const MCTruthVector& mcTruthVector,
199  const PFParticleVector& recoNeutrinoVector,
200  const MCPrimaryMatchingMap& mcPrimaryMatchingMap) const;
201 
208  void PerformMatching(const MCPrimaryMatchingMap& mcPrimaryMatchingMap,
209  MatchingDetailsMap& matchingDetailsMap) const;
210 
211  typedef std::set<int> IntSet;
212 
221  bool GetStrongestPfoMatch(const MCPrimaryMatchingMap& mcPrimaryMatchingMap,
222  IntSet& usedMCIds,
223  IntSet& usedPfoIds,
224  MatchingDetailsMap& matchingDetailsMap) const;
225 
233  void GetRemainingPfoMatches(const MCPrimaryMatchingMap& mcPrimaryMatchingMap,
234  const IntSet& usedPfoIds,
235  MatchingDetailsMap& matchingDetailsMap) const;
236 
243  void PrintMatchingOutput(const MCPrimaryMatchingMap& mcPrimaryMatchingMap,
244  const MatchingDetailsMap& matchingDetailsMap) const;
245 
253  bool IsGoodMCPrimary(const SimpleMCPrimary& simpleMCPrimary) const;
254 
264  bool HasMatch(const SimpleMCPrimary& simpleMCPrimary,
265  const SimpleMatchedPfoList& simpleMatchedPfoList,
266  const MatchingDetailsMap& matchingDetailsMap) const;
267 
276  bool IsGoodMatch(const SimpleMCPrimary& simpleMCPrimary,
277  const SimpleMatchedPfo& simpleMatchedPfo) const;
278 
287  unsigned int CountHitsByType(const geo::View_t view, const HitVector& hitVector) const;
288 
297  static bool SortSimpleMCPrimaries(const SimpleMCPrimary& lhs, const SimpleMCPrimary& rhs);
298 
307  static bool SortSimpleMatchedPfos(const SimpleMatchedPfo& lhs, const SimpleMatchedPfo& rhs);
308 
309  std::string m_hitfinderLabel;
310  std::string m_particleLabel;
311  std::string m_geantModuleLabel;
312  std::string m_backtrackerLabel;
313 
316 
317  bool
319 
320  int
322  int
325 
326  bool
331  };
332 
334 
335 } // namespace lar_pandora
336 
337 //------------------------------------------------------------------------------------------------------------------------------------------
338 
340 
341 #include "fhiclcpp/ParameterSet.h"
342 
345 
346 #include "lardataobj/RecoBase/Hit.h"
348 
349 #include <algorithm>
350 #include <iostream>
351 
352 namespace lar_pandora {
353 
355  : art::EDAnalyzer(pset)
356  {
357  this->reconfigure(pset);
358  }
359 
360  //------------------------------------------------------------------------------------------------------------------------------------------
361 
363 
364  //------------------------------------------------------------------------------------------------------------------------------------------
365 
367  {
368  m_particleLabel = pset.get<std::string>("PFParticleModule", "pandoraNu");
369  m_hitfinderLabel = pset.get<std::string>("HitFinderModule", "gaushit");
370  m_geantModuleLabel = pset.get<std::string>("GeantModule", "largeant");
371  m_backtrackerLabel = pset.get<std::string>("BackTrackerModule", "gaushitTruthMatch");
372  m_printAllToScreen = pset.get<bool>("PrintAllToScreen", true);
373  m_printMatchingToScreen = pset.get<bool>("PrintMatchingToScreen", true);
374  m_neutrinoInducedOnly = pset.get<bool>("NeutrinoInducedOnly", true);
375  m_matchingMinPrimaryHits = pset.get<int>("MatchingMinPrimaryHits", 15);
376  m_matchingMinHitsForGoodView = pset.get<int>("MatchingMinHitsForGoodView", 5);
377  m_matchingMinPrimaryGoodViews = pset.get<int>("MatchingMinPrimaryGoodViews", 2);
378  m_useSmallPrimaries = pset.get<bool>("UseSmallPrimaries", true);
379  m_matchingMinSharedHits = pset.get<int>("MatchingMinSharedHits", 5);
380  m_matchingMinCompleteness = pset.get<float>("MatchingMinCompleteness", 0.1f);
381  m_matchingMinPurity = pset.get<float>("MatchingMinPurity", 0.5f);
382  }
383 
384  //------------------------------------------------------------------------------------------------------------------------------------------
385 
387 
388  //------------------------------------------------------------------------------------------------------------------------------------------
389 
391 
392  //------------------------------------------------------------------------------------------------------------------------------------------
393 
395  {
396  HitVector hitVector;
398 
399  PFParticlesToHits pfParticlesToHits;
400  HitsToPFParticles hitsToPfParticles;
402  evt, m_particleLabel, pfParticlesToHits, hitsToPfParticles, LArPandoraHelper::kAddDaughters);
403 
404  MCParticlesToHits mcParticlesToHits;
405  HitsToMCParticles hitsToMCParticles;
406 
409  hitVector,
410  mcParticlesToHits,
411  hitsToMCParticles,
413 
414  if (hitsToMCParticles.empty()) {
415  if (m_backtrackerLabel.empty())
416  throw cet::exception("LArPandora") << " PFParticleValidation::analyze - no sim channels "
417  "found, backtracker module must be set in FHiCL "
418  << std::endl;
419 
424  mcParticlesToHits,
425  hitsToMCParticles,
427  }
428 
429  MCParticleMatchingMap mcParticleMatchingMap;
431  pfParticlesToHits, mcParticlesToHits, hitsToMCParticles, mcParticleMatchingMap);
432 
433  SimpleMCPrimaryList simpleMCPrimaryList;
435  evt, mcParticlesToHits, hitsToMCParticles, mcParticleMatchingMap, simpleMCPrimaryList);
436 
437  MCPrimaryMatchingMap mcPrimaryMatchingMap;
439  simpleMCPrimaryList, mcParticleMatchingMap, pfParticlesToHits, mcPrimaryMatchingMap);
440 
441  MCTruthVector mcTruthVector;
442  this->GetMCTruth(evt, mcTruthVector);
443 
444  PFParticleVector recoNeutrinoVector;
445  this->GetRecoNeutrinos(evt, recoNeutrinoVector);
446 
447  if (m_printAllToScreen)
448  this->PrintAllOutput(mcTruthVector, recoNeutrinoVector, mcPrimaryMatchingMap);
449 
451  MatchingDetailsMap matchingDetailsMap;
452  this->PerformMatching(mcPrimaryMatchingMap, matchingDetailsMap);
453  this->PrintMatchingOutput(mcPrimaryMatchingMap, matchingDetailsMap);
454  }
455  }
456 
457  //------------------------------------------------------------------------------------------------------------------------------------------
458 
460  const PFParticlesToHits& pfParticlesToHits,
461  const MCParticlesToHits& mcParticlesToHits,
462  const HitsToMCParticles& hitsToMCParticles,
463  MCParticleMatchingMap& mcParticleMatchingMap) const
464  {
465  // Create a placeholder entry for all mc particles with >0 hits
466  for (const MCParticlesToHits::value_type& mcParticleToHitsEntry : mcParticlesToHits) {
467  if (!mcParticleToHitsEntry.second.empty())
468  (void)mcParticleMatchingMap.insert(MCParticleMatchingMap::value_type(
469  mcParticleToHitsEntry.first, PFParticleToMatchedHits()));
470  }
471 
472  // Store true to reco matching details
473  for (const PFParticlesToHits::value_type& recoParticleToHits : pfParticlesToHits) {
474  const art::Ptr<recob::PFParticle> pRecoParticle(recoParticleToHits.first);
475  const HitVector& hitVector(recoParticleToHits.second);
476 
477  for (const art::Ptr<recob::Hit> pHit : hitVector) {
478  HitsToMCParticles::const_iterator mcParticleIter = hitsToMCParticles.find(pHit);
479 
480  if (hitsToMCParticles.end() == mcParticleIter) continue;
481 
482  const art::Ptr<simb::MCParticle> pTrueParticle = mcParticleIter->second;
483  mcParticleMatchingMap[pTrueParticle][pRecoParticle].push_back(pHit);
484  }
485  }
486  }
487 
488  //------------------------------------------------------------------------------------------------------------------------------------------
489 
491  const art::Event& evt,
492  const MCParticlesToHits& mcParticlesToHits,
493  const HitsToMCParticles& hitsToMCParticles,
494  const MCParticleMatchingMap& mcParticleMatchingMap,
495  SimpleMCPrimaryList& simpleMCPrimaryList) const
496  {
497  MCTruthToMCParticles artMCTruthToMCParticles;
498  MCParticlesToMCTruth artMCParticlesToMCTruth;
500  evt, m_geantModuleLabel, artMCTruthToMCParticles, artMCParticlesToMCTruth);
501 
502  for (const MCParticlesToHits::value_type& mapEntry : mcParticlesToHits) {
503  const art::Ptr<simb::MCParticle> pMCPrimary(mapEntry.first);
504 
505  if (m_neutrinoInducedOnly && !this->IsNeutrinoInduced(pMCPrimary, artMCParticlesToMCTruth))
506  continue;
507 
508  SimpleMCPrimary simpleMCPrimary;
509  // ATTN simpleMCPrimary.m_id assigned later, after sorting
510  simpleMCPrimary.m_pAddress = pMCPrimary.get();
511  simpleMCPrimary.m_pdgCode = pMCPrimary->PdgCode();
512  simpleMCPrimary.m_energy = pMCPrimary->E();
513 
514  MCParticlesToHits::const_iterator trueHitsIter = mcParticlesToHits.find(pMCPrimary);
515 
516  if (mcParticlesToHits.end() != trueHitsIter) {
517  const HitVector& hitVector(trueHitsIter->second);
518  simpleMCPrimary.m_nMCHitsTotal = hitVector.size();
519  simpleMCPrimary.m_nMCHitsU = this->CountHitsByType(geo::kU, hitVector);
520  simpleMCPrimary.m_nMCHitsV = this->CountHitsByType(geo::kV, hitVector);
521  simpleMCPrimary.m_nMCHitsW = this->CountHitsByType(geo::kW, hitVector);
522  }
523 
524  MCParticleMatchingMap::const_iterator matchedPfoIter = mcParticleMatchingMap.find(pMCPrimary);
525 
526  if (mcParticleMatchingMap.end() != matchedPfoIter)
527  simpleMCPrimary.m_nMatchedPfos = matchedPfoIter->second.size();
528 
529  simpleMCPrimaryList.push_back(simpleMCPrimary);
530  }
531 
532  std::sort(simpleMCPrimaryList.begin(),
533  simpleMCPrimaryList.end(),
535 
536  int mcPrimaryId(0);
537  for (SimpleMCPrimary& simpleMCPrimary : simpleMCPrimaryList)
538  simpleMCPrimary.m_id = mcPrimaryId++;
539  }
540 
541  //------------------------------------------------------------------------------------------------------------------------------------------
542 
544  const art::Ptr<simb::MCParticle> pMCParticle,
545  const MCParticlesToMCTruth& artMCParticlesToMCTruth) const
546  {
547  MCParticlesToMCTruth::const_iterator iter = artMCParticlesToMCTruth.find(pMCParticle);
548 
549  if (artMCParticlesToMCTruth.end() == iter) return false;
550 
551  const art::Ptr<simb::MCTruth> pMCTruth = iter->second;
552  return (simb::kBeamNeutrino == pMCTruth->Origin());
553  }
554 
555  //------------------------------------------------------------------------------------------------------------------------------------------
556 
558  const SimpleMCPrimaryList& simpleMCPrimaryList,
559  const MCParticleMatchingMap& mcParticleMatchingMap,
560  const PFParticlesToHits& pfParticlesToHits,
561  MCPrimaryMatchingMap& mcPrimaryMatchingMap) const
562  {
563  for (const SimpleMCPrimary& simpleMCPrimary : simpleMCPrimaryList) {
564  SimpleMatchedPfoList simpleMatchedPfoList;
565  MCParticleMatchingMap::const_iterator matchedPfoIter = mcParticleMatchingMap.end();
566 
567  // ATTN Nasty workaround I
568  for (MCParticleMatchingMap::const_iterator iter = mcParticleMatchingMap.begin(),
569  iterEnd = mcParticleMatchingMap.end();
570  iter != iterEnd;
571  ++iter) {
572  if (simpleMCPrimary.m_pAddress == iter->first.get()) {
573  matchedPfoIter = iter;
574  break;
575  };
576  }
577 
578  if (mcParticleMatchingMap.end() != matchedPfoIter) {
579  for (const PFParticleToMatchedHits::value_type& contribution : matchedPfoIter->second) {
580  const art::Ptr<recob::PFParticle> pMatchedPfo(contribution.first);
581  const HitVector& matchedHitVector(contribution.second);
582 
583  SimpleMatchedPfo simpleMatchedPfo;
584  simpleMatchedPfo.m_pAddress = pMatchedPfo.get();
585  simpleMatchedPfo.m_id = pMatchedPfo->Self();
586 
587  // ATTN Assume pfos have either zero or one parents. Ignore parent neutrino.
588  PFParticlesToHits::const_iterator parentPfoIter = pfParticlesToHits.end();
589 
590  // ATTN Nasty workaround II, bad place for another loop.
591  for (PFParticlesToHits::const_iterator iter = pfParticlesToHits.begin(),
592  iterEnd = pfParticlesToHits.end();
593  iter != iterEnd;
594  ++iter) {
595  if (pMatchedPfo->Parent() == iter->first->Self()) {
596  parentPfoIter = iter;
597  break;
598  };
599  }
600 
601  if ((pfParticlesToHits.end() != parentPfoIter) &&
602  !LArPandoraHelper::IsNeutrino(parentPfoIter->first))
603  simpleMatchedPfo.m_parentId = parentPfoIter->first->Self();
604 
605  simpleMatchedPfo.m_pdgCode = pMatchedPfo->PdgCode();
606  simpleMatchedPfo.m_nMatchedHitsTotal = matchedHitVector.size();
607  simpleMatchedPfo.m_nMatchedHitsU = this->CountHitsByType(geo::kU, matchedHitVector);
608  simpleMatchedPfo.m_nMatchedHitsV = this->CountHitsByType(geo::kV, matchedHitVector);
609  simpleMatchedPfo.m_nMatchedHitsW = this->CountHitsByType(geo::kW, matchedHitVector);
610 
611  PFParticlesToHits::const_iterator pfoHitsIter = pfParticlesToHits.find(pMatchedPfo);
612 
613  if (pfParticlesToHits.end() == pfoHitsIter)
614  throw cet::exception("LArPandora")
615  << " PFParticleValidation::analyze --- Presence of PFParticle in map mandatory.";
616 
617  const HitVector& pfoHitVector(pfoHitsIter->second);
618 
619  simpleMatchedPfo.m_nPfoHitsTotal = pfoHitVector.size();
620  simpleMatchedPfo.m_nPfoHitsU = this->CountHitsByType(geo::kU, pfoHitVector);
621  simpleMatchedPfo.m_nPfoHitsV = this->CountHitsByType(geo::kV, pfoHitVector);
622  simpleMatchedPfo.m_nPfoHitsW = this->CountHitsByType(geo::kW, pfoHitVector);
623 
624  simpleMatchedPfoList.push_back(simpleMatchedPfo);
625  }
626  }
627 
628  // Store the ordered vectors of matched pfo details
629  std::sort(simpleMatchedPfoList.begin(),
630  simpleMatchedPfoList.end(),
632 
633  if (!mcPrimaryMatchingMap
634  .insert(MCPrimaryMatchingMap::value_type(simpleMCPrimary, simpleMatchedPfoList))
635  .second)
636  throw cet::exception("LArPandora")
637  << " PFParticleValidation::analyze --- Double-counting MC primaries.";
638  }
639  }
640 
641  //------------------------------------------------------------------------------------------------------------------------------------------
642 
644  {
645  MCTruthToMCParticles artMCTruthToMCParticles;
646  MCParticlesToMCTruth artMCParticlesToMCTruth;
648  evt, m_geantModuleLabel, artMCTruthToMCParticles, artMCParticlesToMCTruth);
649 
650  for (const auto& mapEntry : artMCTruthToMCParticles) {
651  const art::Ptr<simb::MCTruth> truth = mapEntry.first;
652 
653  if (!truth->NeutrinoSet()) continue;
654 
655  if (mcTruthVector.end() == std::find(mcTruthVector.begin(), mcTruthVector.end(), truth))
656  mcTruthVector.push_back(truth);
657  }
658  }
659 
660  //------------------------------------------------------------------------------------------------------------------------------------------
661 
663  PFParticleVector& recoNeutrinoVector) const
664  {
665  PFParticleVector allPFParticles;
667  LArPandoraHelper::SelectNeutrinoPFParticles(allPFParticles, recoNeutrinoVector);
668  }
669 
670  //------------------------------------------------------------------------------------------------------------------------------------------
671 
673  const PFParticleVector& recoNeutrinoVector,
674  const MCPrimaryMatchingMap& mcPrimaryMatchingMap) const
675  {
676  std::cout << "---RAW-MATCHING-OUTPUT-----------------------------------------------------------"
677  "---------------"
678  << std::endl;
679 
680  for (const art::Ptr<simb::MCTruth> pMCTruth : mcTruthVector) {
681  std::cout << "MCNeutrino, PDG " << pMCTruth->GetNeutrino().Nu().PdgCode()
682  << ", InteractionType " << pMCTruth->GetNeutrino().InteractionType() << std::endl;
683  }
684 
685  for (const art::Ptr<recob::PFParticle> pPfo : recoNeutrinoVector) {
686  std::cout << "RecoNeutrino, PDG " << pPfo->PdgCode() << ", nDaughters "
687  << pPfo->NumDaughters() << std::endl;
688  }
689 
690  for (const MCPrimaryMatchingMap::value_type& mapValue : mcPrimaryMatchingMap) {
691  const SimpleMCPrimary& simpleMCPrimary(mapValue.first);
692 
693  std::cout << std::endl
694  << "Primary " << simpleMCPrimary.m_id << ", PDG " << simpleMCPrimary.m_pdgCode
695  << ", nMCHits " << simpleMCPrimary.m_nMCHitsTotal << " ("
696  << simpleMCPrimary.m_nMCHitsU << ", " << simpleMCPrimary.m_nMCHitsV << ", "
697  << simpleMCPrimary.m_nMCHitsW << ")" << std::endl;
698 
699  for (const SimpleMatchedPfo& simpleMatchedPfo : mapValue.second) {
700  std::cout << "-MatchedPfo " << simpleMatchedPfo.m_id;
701 
702  if (simpleMatchedPfo.m_parentId >= 0)
703  std::cout << ", ParentPfo " << simpleMatchedPfo.m_parentId;
704 
705  std::cout << ", PDG " << simpleMatchedPfo.m_pdgCode << ", nMatchedHits "
706  << simpleMatchedPfo.m_nMatchedHitsTotal << " ("
707  << simpleMatchedPfo.m_nMatchedHitsU << ", " << simpleMatchedPfo.m_nMatchedHitsV
708  << ", " << simpleMatchedPfo.m_nMatchedHitsW << ")"
709  << ", nPfoHits " << simpleMatchedPfo.m_nPfoHitsTotal << " ("
710  << simpleMatchedPfo.m_nPfoHitsU << ", " << simpleMatchedPfo.m_nPfoHitsV << ", "
711  << simpleMatchedPfo.m_nPfoHitsW << ")" << std::endl;
712  }
713  }
714 
715  std::cout << "---------------------------------------------------------------------------------"
716  "---------------"
717  << std::endl;
718  }
719 
720  //------------------------------------------------------------------------------------------------------------------------------------------
721 
723  MatchingDetailsMap& matchingDetailsMap) const
724  {
725  // Get best matches, one-by-one, until no more strong matches possible
726  IntSet usedMCIds, usedPfoIds;
727  while (GetStrongestPfoMatch(mcPrimaryMatchingMap, usedMCIds, usedPfoIds, matchingDetailsMap)) {}
728 
729  // Assign any remaining pfos to primaries, based on number of matched hits
730  GetRemainingPfoMatches(mcPrimaryMatchingMap, usedPfoIds, matchingDetailsMap);
731  }
732 
733  //------------------------------------------------------------------------------------------------------------------------------------------
734 
736  IntSet& usedMCIds,
737  IntSet& usedPfoIds,
738  MatchingDetailsMap& matchingDetailsMap) const
739  {
740  int bestPfoMatchId(-1);
741  MatchingDetails bestMatchingDetails;
742 
743  for (const MCPrimaryMatchingMap::value_type& mapValue : mcPrimaryMatchingMap) {
744  const SimpleMCPrimary& simpleMCPrimary(mapValue.first);
745 
746  if (!m_useSmallPrimaries && !this->IsGoodMCPrimary(simpleMCPrimary)) continue;
747 
748  if (usedMCIds.count(simpleMCPrimary.m_id)) continue;
749 
750  for (const SimpleMatchedPfo& simpleMatchedPfo : mapValue.second) {
751  if (usedPfoIds.count(simpleMatchedPfo.m_id)) continue;
752 
753  if (!this->IsGoodMatch(simpleMCPrimary, simpleMatchedPfo)) continue;
754 
755  if (simpleMatchedPfo.m_nMatchedHitsTotal > bestMatchingDetails.m_nMatchedHits) {
756  bestPfoMatchId = simpleMatchedPfo.m_id;
757  bestMatchingDetails.m_matchedPrimaryId = simpleMCPrimary.m_id;
758  bestMatchingDetails.m_nMatchedHits = simpleMatchedPfo.m_nMatchedHitsTotal;
759  bestMatchingDetails.m_completeness =
760  static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) /
761  static_cast<float>(simpleMCPrimary.m_nMCHitsTotal);
762  }
763  }
764  }
765 
766  if (bestPfoMatchId > -1) {
767  matchingDetailsMap[bestPfoMatchId] = bestMatchingDetails;
768  usedMCIds.insert(bestMatchingDetails.m_matchedPrimaryId);
769  usedPfoIds.insert(bestPfoMatchId);
770  return true;
771  }
772 
773  return false;
774  }
775 
776  //------------------------------------------------------------------------------------------------------------------------------------------
777 
779  const MCPrimaryMatchingMap& mcPrimaryMatchingMap,
780  const IntSet& usedPfoIds,
781  MatchingDetailsMap& matchingDetailsMap) const
782  {
783  for (const MCPrimaryMatchingMap::value_type& mapValue : mcPrimaryMatchingMap) {
784  const SimpleMCPrimary& simpleMCPrimary(mapValue.first);
785 
786  if (!m_useSmallPrimaries && !this->IsGoodMCPrimary(simpleMCPrimary)) continue;
787 
788  for (const SimpleMatchedPfo& simpleMatchedPfo : mapValue.second) {
789  if (usedPfoIds.count(simpleMatchedPfo.m_id)) continue;
790 
791  MatchingDetails& matchingDetails(matchingDetailsMap[simpleMatchedPfo.m_id]);
792 
793  if (simpleMatchedPfo.m_nMatchedHitsTotal > matchingDetails.m_nMatchedHits) {
794  matchingDetails.m_matchedPrimaryId = simpleMCPrimary.m_id;
795  matchingDetails.m_nMatchedHits = simpleMatchedPfo.m_nMatchedHitsTotal;
796  matchingDetails.m_completeness =
797  static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) /
798  static_cast<float>(simpleMCPrimary.m_nMCHitsTotal);
799  }
800  }
801  }
802  }
803 
804  //------------------------------------------------------------------------------------------------------------------------------------------
805 
807  const MatchingDetailsMap& matchingDetailsMap) const
808  {
809  std::cout << "---PROCESSED-MATCHING-OUTPUT-----------------------------------------------------"
810  "---------------"
811  << std::endl;
812  std::cout << "MinPrimaryGoodHits " << m_matchingMinPrimaryHits << ", MinHitsForGoodView "
813  << m_matchingMinHitsForGoodView << ", MinPrimaryGoodViews "
814  << m_matchingMinPrimaryGoodViews << std::endl;
815  std::cout << "UseSmallPrimaries " << m_useSmallPrimaries << ", MinSharedHits "
816  << m_matchingMinSharedHits << ", MinCompleteness " << m_matchingMinCompleteness
817  << ", MinPurity " << m_matchingMinPurity << std::endl;
818 
819  bool isCorrect(true), isCalculable(false);
820 
821  for (const MCPrimaryMatchingMap::value_type& mapValue : mcPrimaryMatchingMap) {
822  const SimpleMCPrimary& simpleMCPrimary(mapValue.first);
823  const bool hasMatch(this->HasMatch(simpleMCPrimary, mapValue.second, matchingDetailsMap));
824  const bool isTargetPrimary(this->IsGoodMCPrimary(simpleMCPrimary) &&
825  (2112 != simpleMCPrimary.m_pdgCode));
826 
827  if (!hasMatch && !isTargetPrimary) continue;
828 
829  std::cout << std::endl
830  << (!isTargetPrimary ? "(Non target) " : "") << "Primary " << simpleMCPrimary.m_id
831  << ", PDG " << simpleMCPrimary.m_pdgCode << ", nMCHits "
832  << simpleMCPrimary.m_nMCHitsTotal << " (" << simpleMCPrimary.m_nMCHitsU << ", "
833  << simpleMCPrimary.m_nMCHitsV << ", " << simpleMCPrimary.m_nMCHitsW << ")"
834  << std::endl;
835 
836  if (2112 != simpleMCPrimary.m_pdgCode) isCalculable = true;
837 
838  unsigned int nMatches(0);
839 
840  for (const SimpleMatchedPfo& simpleMatchedPfo : mapValue.second) {
841  if (matchingDetailsMap.count(simpleMatchedPfo.m_id) &&
842  (simpleMCPrimary.m_id ==
843  matchingDetailsMap.at(simpleMatchedPfo.m_id).m_matchedPrimaryId)) {
844  const bool isGoodMatch(this->IsGoodMatch(simpleMCPrimary, simpleMatchedPfo));
845 
846  if (isGoodMatch) ++nMatches;
847  std::cout << "-" << (!isGoodMatch ? "(Below threshold) " : "") << "MatchedPfo "
848  << simpleMatchedPfo.m_id;
849 
850  if (simpleMatchedPfo.m_parentId >= 0)
851  std::cout << ", ParentPfo " << simpleMatchedPfo.m_parentId;
852 
853  std::cout << ", PDG " << simpleMatchedPfo.m_pdgCode << ", nMatchedHits "
854  << simpleMatchedPfo.m_nMatchedHitsTotal << " ("
855  << simpleMatchedPfo.m_nMatchedHitsU << ", " << simpleMatchedPfo.m_nMatchedHitsV
856  << ", " << simpleMatchedPfo.m_nMatchedHitsW << ")"
857  << ", nPfoHits " << simpleMatchedPfo.m_nPfoHitsTotal << " ("
858  << simpleMatchedPfo.m_nPfoHitsU << ", " << simpleMatchedPfo.m_nPfoHitsV << ", "
859  << simpleMatchedPfo.m_nPfoHitsW << ")" << std::endl;
860  }
861  }
862 
863  if (isTargetPrimary && (1 != nMatches)) isCorrect = false;
864  }
865 
866  std::cout << std::endl << "Is correct? " << (isCorrect && isCalculable) << std::endl;
867  std::cout << "---------------------------------------------------------------------------------"
868  "---------------"
869  << std::endl;
870  }
871 
872  //------------------------------------------------------------------------------------------------------------------------------------------
873 
874  bool PFParticleValidation::IsGoodMCPrimary(const SimpleMCPrimary& simpleMCPrimary) const
875  {
876  if (simpleMCPrimary.m_nMCHitsTotal < m_matchingMinPrimaryHits) return false;
877 
878  int nGoodViews(0);
879  if (simpleMCPrimary.m_nMCHitsU >= m_matchingMinHitsForGoodView) ++nGoodViews;
880  if (simpleMCPrimary.m_nMCHitsV >= m_matchingMinHitsForGoodView) ++nGoodViews;
881  if (simpleMCPrimary.m_nMCHitsW >= m_matchingMinHitsForGoodView) ++nGoodViews;
882 
883  if (nGoodViews < m_matchingMinPrimaryGoodViews) return false;
884 
885  return true;
886  }
887 
888  //------------------------------------------------------------------------------------------------------------------------------------------
889 
890  bool PFParticleValidation::HasMatch(const SimpleMCPrimary& simpleMCPrimary,
891  const SimpleMatchedPfoList& simpleMatchedPfoList,
892  const MatchingDetailsMap& matchingDetailsMap) const
893  {
894  for (const SimpleMatchedPfo& simpleMatchedPfo : simpleMatchedPfoList) {
895  if (matchingDetailsMap.count(simpleMatchedPfo.m_id) &&
896  (simpleMCPrimary.m_id == matchingDetailsMap.at(simpleMatchedPfo.m_id).m_matchedPrimaryId))
897  return true;
898  }
899 
900  return false;
901  }
902 
903  //------------------------------------------------------------------------------------------------------------------------------------------
904 
906  const SimpleMatchedPfo& simpleMatchedPfo) const
907  {
908  const float purity((simpleMatchedPfo.m_nPfoHitsTotal > 0) ?
909  static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) /
910  static_cast<float>(simpleMatchedPfo.m_nPfoHitsTotal) :
911  0.f);
912  const float completeness((simpleMCPrimary.m_nMCHitsTotal > 0) ?
913  static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) /
914  static_cast<float>(simpleMCPrimary.m_nMCHitsTotal) :
915  0.f);
916 
917  return ((simpleMatchedPfo.m_nMatchedHitsTotal >= m_matchingMinSharedHits) &&
918  (purity >= m_matchingMinPurity) && (completeness >= m_matchingMinCompleteness));
919  }
920 
921  //------------------------------------------------------------------------------------------------------------------------------------------
922 
924  const HitVector& hitVector) const
925  {
926  unsigned int nHitsOfSpecifiedType(0);
927 
928  for (const art::Ptr<recob::Hit> pHit : hitVector) {
929  if (view == pHit->View()) ++nHitsOfSpecifiedType;
930  }
931 
932  return nHitsOfSpecifiedType;
933  }
934 
935  //------------------------------------------------------------------------------------------------------------------------------------------
936 
938  const SimpleMCPrimary& rhs)
939  {
940  if (lhs.m_nMCHitsTotal != rhs.m_nMCHitsTotal) return (lhs.m_nMCHitsTotal > rhs.m_nMCHitsTotal);
941 
942  return (lhs.m_energy > rhs.m_energy);
943  }
944 
945  //------------------------------------------------------------------------------------------------------------------------------------------
946 
948  const SimpleMatchedPfo& rhs)
949  {
951  return (lhs.m_nMatchedHitsTotal > rhs.m_nMatchedHitsTotal);
952 
953  if (lhs.m_nPfoHitsTotal != rhs.m_nPfoHitsTotal)
954  return (lhs.m_nPfoHitsTotal > rhs.m_nPfoHitsTotal);
955 
956  return (lhs.m_id < rhs.m_id);
957  }
958 
959  //------------------------------------------------------------------------------------------------------------------------------------------
960  //------------------------------------------------------------------------------------------------------------------------------------------
961 
963  : m_id(-1)
964  , m_pdgCode(0)
965  , m_nMCHitsTotal(0)
966  , m_nMCHitsU(0)
967  , m_nMCHitsV(0)
968  , m_nMCHitsW(0)
969  , m_energy(0.f)
970  , m_nMatchedPfos(0)
971  , m_pAddress(nullptr)
972  {}
973 
974  //------------------------------------------------------------------------------------------------------------------------------------------
975 
977  {
978  if (this == &rhs) return false;
979 
980  return (m_id < rhs.m_id);
981  }
982 
983  //------------------------------------------------------------------------------------------------------------------------------------------
984  //------------------------------------------------------------------------------------------------------------------------------------------
985 
987  : m_id(-1)
988  , m_parentId(-1)
989  , m_pdgCode(0)
990  , m_nPfoHitsTotal(0)
991  , m_nPfoHitsU(0)
992  , m_nPfoHitsV(0)
993  , m_nPfoHitsW(0)
994  , m_nMatchedHitsTotal(0)
995  , m_nMatchedHitsU(0)
996  , m_nMatchedHitsV(0)
997  , m_nMatchedHitsW(0)
998  , m_pAddress(nullptr)
999  {}
1000 
1001  //------------------------------------------------------------------------------------------------------------------------------------------
1002  //------------------------------------------------------------------------------------------------------------------------------------------
1003 
1005  : m_matchedPrimaryId(-1), m_nMatchedHits(0), m_completeness(0.f)
1006  {}
1007 
1008 } //namespace lar_pandora
double E(const int i=0) const
Definition: MCParticle.h:234
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...
std::vector< art::Ptr< simb::MCTruth > > MCTruthVector
void GetMCParticleMatchingMap(const PFParticlesToHits &recoParticlesToHits, const MCParticlesToHits &trueParticlesToHits, const HitsToMCParticles &hitsToTrueParticles, MCParticleMatchingMap &mcParticleMatchingMap) const
Performing matching between true and reconstructed particles.
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCParticle > > HitsToMCParticles
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:213
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< SimpleMCPrimary, SimpleMatchedPfoList > MCPrimaryMatchingMap
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:88
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:136
void GetRecoNeutrinos(const art::Event &evt, PFParticleVector &recoNeutrinoVector) const
Obtain a vector of reco neutrinos.
Declaration of signal hit object.
bool m_neutrinoInducedOnly
Whether to consider only mc particles that were neutrino induced.
std::map< art::Ptr< simb::MCParticle >, art::Ptr< simb::MCTruth > > MCParticlesToMCTruth
simb::Origin_t Origin() const
Definition: MCTruth.h:74
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)
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticleToMatchedHits
int PdgCode() const
Return the type of particle as a PDG ID.
Definition: PFParticle.h:79
intermediate_table::const_iterator const_iterator
std::map< int, MatchingDetails > MatchingDetailsMap
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.cc:6
Particle class.
const recob::PFParticle * m_pAddress
The address of the pf primary.
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.
Planes which measure U.
Definition: geo_types.h:135
std::vector< SimpleMCPrimary > SimpleMCPrimaryList
if(nlines<=0)
bool m_printMatchingToScreen
Whether to print matching output to screen.
void GetMCTruth(const art::Event &evt, MCTruthVector &mcTruthVector) const
Obtain a vector of mc truth.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
bool IsGoodMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfo &simpleMatchedPfo) const
Whether a provided mc primary and pfo are deemed to be a good match.
std::map< art::Ptr< simb::MCParticle >, HitVector > MCParticlesToHits
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.
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
size_t Parent() const
Definition: PFParticle.h:92
std::map< art::Ptr< simb::MCTruth >, MCParticleVector > MCTruthToMCParticles
float m_matchingMinPurity
The minimum particle purity to declare a match.
T get(std::string const &key) const
Definition: ParameterSet.h:314
std::string m_backtrackerLabel
The name/label of the back-tracker module.
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
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.
std::vector< SimpleMatchedPfo > SimpleMatchedPfoList
static bool SortSimpleMatchedPfos(const SimpleMatchedPfo &lhs, const SimpleMatchedPfo &rhs)
Sort simple matched pfos by number of matched hits.
Definition of data types for geometry description.
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits from the ART event record.
static void SelectNeutrinoPFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select reconstructed neutrino particles from a list of all reconstructed particles.
std::vector< art::Ptr< recob::Hit > > HitVector
bool IsGoodMCPrimary(const SimpleMCPrimary &simpleMCPrimary) const
Whether a provided mc primary passes selection, based on number of "good" hits.
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.
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::PFParticle > > HitsToPFParticles
static bool SortSimpleMCPrimaries(const SimpleMCPrimary &lhs, const SimpleMCPrimary &rhs)
Sort simple mc primaries by number of mc hits.
void reconfigure(fhicl::ParameterSet const &pset)
Definition: MVAAlg.h:12
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:137
bool NeutrinoSet() const
Definition: MCTruth.h:78
bool operator<(const SimpleMCPrimary &rhs) const
operator <
TCEvent evt
Definition: DataStructs.cxx:8
T const * get() const
Definition: Ptr.h:138
std::string m_geantModuleLabel
The name/label of the geant module.
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.
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
std::map< art::Ptr< simb::MCParticle >, PFParticleToMatchedHits > MCParticleMatchingMap
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:26
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:23