Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
PFParticleValidation_module.cc
Go to the documentation of this file.
1
8#include "art/Framework/Core/EDAnalyzer.h"
9#include "art/Framework/Core/ModuleMacros.h"
10
11#include "larcoreobj/SimpleTypesAndConstants/geo_types.h"
13
14#include <string>
15
16//------------------------------------------------------------------------------------------------------------------------------------------
17
18namespace lar_pandora {
19
23 class PFParticleValidation : public art::EDAnalyzer {
24 public:
30 PFParticleValidation(fhicl::ParameterSet const& pset);
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;
68 float m_energy;
70 const simb::MCParticle* m_pAddress;
71 };
72
73 typedef std::vector<SimpleMCPrimary> SimpleMCPrimaryList;
74
98
99 typedef std::vector<SimpleMatchedPfo> SimpleMatchedPfoList;
100
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
333 DEFINE_ART_MODULE(PFParticleValidation)
334
335} // namespace lar_pandora
336
337//------------------------------------------------------------------------------------------------------------------------------------------
338
339#include "art/Framework/Principal/Event.h"
340
341#include "fhiclcpp/ParameterSet.h"
342
343#include "nusimdata/SimulationBase/MCParticle.h"
344#include "nusimdata/SimulationBase/MCTruth.h"
345
346#include "lardataobj/RecoBase/Hit.h"
347#include "lardataobj/RecoBase/PFParticle.h"
348
349#include <algorithm>
350#include <iostream>
351
352namespace lar_pandora {
353
354 PFParticleValidation::PFParticleValidation(fhicl::ParameterSet const& pset)
355 : art::EDAnalyzer(pset)
356 {
357 this->reconfigure(pset);
358 }
359
360 //------------------------------------------------------------------------------------------------------------------------------------------
361
363
364 //------------------------------------------------------------------------------------------------------------------------------------------
365
366 void PFParticleValidation::reconfigure(fhicl::ParameterSet const& pset)
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
394 void PFParticleValidation::analyze(const art::Event& evt)
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
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
643 void PFParticleValidation::GetMCTruth(const art::Event& evt, MCTruthVector& mcTruthVector) const
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
662 void PFParticleValidation::GetRecoNeutrinos(const art::Event& evt,
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
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
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
923 unsigned int PFParticleValidation::CountHitsByType(const geo::View_t view,
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
helper function for LArPandoraInterface producer module
static void SelectNeutrinoPFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select reconstructed neutrino particles from a list of all reconstructed particles.
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits 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.
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
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.
static void CollectMCParticles(const art::Event &evt, const std::string &label, MCParticleVector &particleVector)
Collect a vector of MCParticle objects from the ART event record.
int m_nMatchedHits
The number of times the primary has 0 pfo matches.
bool operator<(const SimpleMCPrimary &rhs) const
operator <
const simb::MCParticle * m_pAddress
The address of the mc primary.
int m_parentId
The unique identifier of the parent pfo (-1 if no parent set)
const recob::PFParticle * m_pAddress
The address of the pf primary.
std::string m_hitfinderLabel
The name/label of the hit producer module.
int m_matchingMinHitsForGoodView
The minimum number of good mc primary hits in given view to declare view to be good.
std::map< SimpleMCPrimary, SimpleMatchedPfoList > MCPrimaryMatchingMap
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.
bool m_useSmallPrimaries
Whether to consider matches to mc primaries with fewer than m_matchingMinPrimaryHits.
void GetMCTruth(const art::Event &evt, MCTruthVector &mcTruthVector) const
Obtain a vector of mc truth.
int m_matchingMinPrimaryHits
The minimum number of good mc primary hits used in matching scheme.
void PrintMatchingOutput(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const MatchingDetailsMap &matchingDetailsMap) const
Print the results of the matching procedure.
std::map< art::Ptr< simb::MCParticle >, PFParticleToMatchedHits > MCParticleMatchingMap
int m_matchingMinPrimaryGoodViews
The minimum number of good views for a mc primary.
void GetRecoNeutrinos(const art::Event &evt, PFParticleVector &recoNeutrinoVector) const
Obtain a vector of reco neutrinos.
std::vector< SimpleMCPrimary > SimpleMCPrimaryList
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.
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...
void PerformMatching(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, MatchingDetailsMap &matchingDetailsMap) const
Apply a well-defined matching procedure to the comprehensive matches in the provided mc primary match...
float m_matchingMinCompleteness
The minimum particle completeness to declare a match.
float m_matchingMinPurity
The minimum particle purity to declare a match.
bool m_neutrinoInducedOnly
Whether to consider only mc particles that were neutrino induced.
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< SimpleMatchedPfo > SimpleMatchedPfoList
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticleToMatchedHits
static bool SortSimpleMCPrimaries(const SimpleMCPrimary &lhs, const SimpleMCPrimary &rhs)
Sort simple mc primaries by number of mc hits.
void GetMCParticleMatchingMap(const PFParticlesToHits &recoParticlesToHits, const MCParticlesToHits &trueParticlesToHits, const HitsToMCParticles &hitsToTrueParticles, MCParticleMatchingMap &mcParticleMatchingMap) const
Performing matching between true and reconstructed particles.
bool m_printAllToScreen
Whether to print all/raw matching details to screen.
std::string m_backtrackerLabel
The name/label of the back-tracker module.
static bool SortSimpleMatchedPfos(const SimpleMatchedPfo &lhs, const SimpleMatchedPfo &rhs)
Sort simple matched pfos by number of matched hits.
std::string m_particleLabel
The name/label of the particle producer module.
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)
bool IsGoodMCPrimary(const SimpleMCPrimary &simpleMCPrimary) const
Whether a provided mc primary passes selection, based on number of "good" hits.
void PrintAllOutput(const MCTruthVector &mcTruthVector, const PFParticleVector &recoNeutrinoVector, const MCPrimaryMatchingMap &mcPrimaryMatchingMap) const
Print all the raw matching output to screen.
void reconfigure(fhicl::ParameterSet const &pset)
std::string m_geantModuleLabel
The name/label of the geant module.
bool IsGoodMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfo &simpleMatchedPfo) const
Whether a provided mc primary and pfo are deemed to be a good match.
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::map< int, MatchingDetails > MatchingDetailsMap
PFParticleValidation(fhicl::ParameterSet const &pset)
Constructor.
bool m_printMatchingToScreen
Whether to print matching output to screen.
int m_matchingMinSharedHits
The minimum number of shared hits used in matching scheme.
bool IsNeutrinoInduced(const art::Ptr< simb::MCParticle > pMCParticle, const MCParticlesToMCTruth &artMCParticlesToMCTruth) const
Whether a mc particle is neutrino induced.
std::map< art::Ptr< simb::MCParticle >, art::Ptr< simb::MCTruth > > MCParticlesToMCTruth
std::map< art::Ptr< simb::MCTruth >, MCParticleVector > MCTruthToMCParticles
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
std::vector< art::Ptr< recob::Hit > > HitVector
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::vector< art::Ptr< simb::MCTruth > > MCTruthVector
std::map< art::Ptr< simb::MCParticle >, HitVector > MCParticlesToHits
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::PFParticle > > HitsToPFParticles
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCParticle > > HitsToMCParticles