10#include "lardataobj/RecoBase/Cluster.h"
11#include "lardataobj/RecoBase/Hit.h"
12#include "lardataobj/RecoBase/PFParticle.h"
13#include "nusimdata/SimulationBase/MCTruth.h"
15#include "art/Framework/Principal/Event.h"
16#include "art/Framework/Principal/Handle.h"
17#include "canvas/Persistency/Common/FindManyP.h"
22 const art::Event& evt,
23 const std::string& truthLabel,
24 const std::string& mcParticleLabel,
25 const std::string& hitLabel,
26 const std::string& backtrackLabel,
27 const std::string& pandoraLabel,
29 simb::MCNeutrino& mcNeutrino)
33 mcNeutrino = beamNuMCTruth->GetNeutrino();
38 evt, truthLabel, mcParticleLabel, beamNuMCTruth, mcParticles);
44 evt, hitLabel, backtrackLabel, mcParticles, hits, hitToIsNuInducedMap);
45 const unsigned int nNuHits(
54 slices, pfParticleToHitsMap, hitToIsNuInducedMap, nNuHits, sliceMetadata);
60 const art::Event& evt,
61 const std::string& truthLabel)
64 art::Handle<std::vector<simb::MCTruth>> mcTruthHandle;
65 evt.getByLabel(truthLabel, mcTruthHandle);
67 if (!mcTruthHandle.isValid())
68 throw cet::exception(
"LArPandora")
69 <<
" LArPandoraSliceIdHelper::GetBeamNeutrinoMCTruth - invalid MCTruth handle" << std::endl;
72 bool foundNeutrino(
false);
73 float maxNeutrinoEnergy(-std::numeric_limits<float>::max());
74 art::Ptr<simb::MCTruth> beamNuMCTruth;
75 for (
unsigned int i = 0; i < mcTruthHandle->size(); ++i) {
76 const art::Ptr<simb::MCTruth> mcTruth(mcTruthHandle, i);
78 if (mcTruth->Origin() != simb::kBeamNeutrino)
continue;
80 const float nuEnergy(mcTruth->GetNeutrino().Nu().E());
81 if (nuEnergy < maxNeutrinoEnergy)
continue;
84 maxNeutrinoEnergy = nuEnergy;
85 beamNuMCTruth = mcTruth;
90 throw cet::exception(
"LArPandora") <<
" LArPandoraSliceIdHelper::GetBeamNeutrinoMCTruth - "
91 "found no beam neutrino MCTruth blocks"
100 const art::Event& evt,
101 const std::string& truthLabel,
102 const std::string& mcParticleLabel,
103 const art::Ptr<simb::MCTruth>& beamNuMCTruth,
107 art::Handle<std::vector<simb::MCTruth>> mcTruthHandle;
108 evt.getByLabel(truthLabel, mcTruthHandle);
110 if (!mcTruthHandle.isValid())
111 throw cet::exception(
"LArPandora")
112 <<
" LArPandoraSliceIdHelper::CollectNeutrinoMCParticles - invalid MCTruth handle"
116 art::FindManyP<simb::MCParticle> truthToMCParticleAssns(mcTruthHandle, evt, mcParticleLabel);
117 mcParticles = truthToMCParticleAssns.at(
125 const std::string& hitLabel,
126 const std::string& backtrackLabel,
132 art::Handle<std::vector<recob::Hit>> hitHandle;
133 evt.getByLabel(hitLabel, hitHandle);
135 if (!hitHandle.isValid())
136 throw cet::exception(
"LArPandora")
137 <<
" LArPandoraSliceIdHelper::GetHitOrigins - invalid hit handle" << std::endl;
139 art::FindManyP<simb::MCParticle> hitToMCParticleAssns(hitHandle, evt, backtrackLabel);
142 for (
unsigned int i = 0; i < hitHandle->size(); ++i) {
143 const art::Ptr<recob::Hit> hit(hitHandle, i);
146 const auto& particles(hitToMCParticleAssns.at(hit.key()));
148 bool foundNuParticle(
false);
149 for (
const auto& part : particles) {
151 if (std::find(mcParticles.begin(), mcParticles.end(), part) == mcParticles.end())
continue;
153 foundNuParticle =
true;
157 if (!hitToIsNuInducedMap.emplace(hit, foundNuParticle).second)
158 throw cet::exception(
"LArPandora")
159 <<
" LArPandoraSliceIdHelper::GetHitOrigins - repeated hits in input collection"
169 unsigned int nNuHits(0);
170 for (
const auto& hit : hits) {
171 const auto it(hitToIsNuInducedMap.find(hit));
173 if (it == hitToIsNuInducedMap.end())
174 throw cet::exception(
"LArPandora")
175 <<
" LArPandoraSliceIdHelper::CountNeutrinoHits - can't find hit in hitToIsNuInducedMap"
178 nNuHits += it->second ? 1 : 0;
187 const std::string& pandoraLabel,
191 art::Handle<std::vector<recob::PFParticle>> pfParticleHandle;
192 evt.getByLabel(pandoraLabel, pfParticleHandle);
194 if (!pfParticleHandle.isValid())
195 throw cet::exception(
"LArPandora")
196 <<
" LArPandoraSliceIdHelper::GetPFParticleToHitsMap - invalid PFParticle handle"
200 art::Handle<std::vector<recob::Cluster>> clusterHandle;
201 evt.getByLabel(pandoraLabel, clusterHandle);
203 if (!clusterHandle.isValid())
204 throw cet::exception(
"LArPandora")
205 <<
" LArPandoraSliceIdHelper::GetPFParticleToHitsMap - invalid cluster handle" << std::endl;
208 art::FindManyP<recob::Cluster> pfParticleToClusterAssns(pfParticleHandle, evt, pandoraLabel);
209 art::FindManyP<recob::Hit> clusterToHitAssns(clusterHandle, evt, pandoraLabel);
212 for (
unsigned int iPart = 0; iPart < pfParticleHandle->size(); ++iPart) {
213 const art::Ptr<recob::PFParticle> part(pfParticleHandle, iPart);
216 for (
const auto&
cluster : pfParticleToClusterAssns.at(part.key())) {
217 for (
const auto& hit : clusterToHitAssns.at(
cluster.key())) {
218 if (std::find(hits.begin(), hits.end(), hit) != hits.end())
219 throw cet::exception(
"LArPandora")
220 <<
" LArPandoraSliceIdHelper::GetPFParticleToHitsMap - double counted hits!"
227 if (!pfParticleToHitsMap.emplace(part, hits).second)
228 throw cet::exception(
"LArPandora")
229 <<
" LArPandoraSliceIdHelper::GetPFParticleToHitsMap - repeated input PFParticles"
252 for (
const auto& part : pfParticles) {
253 const auto it(pfParticleToHitsMap.find(part));
254 if (it == pfParticleToHitsMap.end())
255 throw cet::exception(
"LArPandora") <<
" LArPandoraSliceIdHelper::CollectHits - can't find "
256 "any hits associated to input PFParticle"
259 for (
const auto& hit : it->second) {
261 if (std::find(hits.begin(), hits.end(), hit) == hits.end()) hits.push_back(hit);
271 const unsigned int nNuHits,
274 if (!sliceMetadata.empty())
275 throw cet::exception(
"LArPandora")
276 <<
" LArPandoraSliceIdHelper::GetSliceMetadata - non empty input metadata vector"
279 if (slices.empty())
return;
281 unsigned int mostCompleteSliceIndex(0);
282 unsigned int maxNuHits(0);
284 for (
unsigned int sliceIndex = 0; sliceIndex < slices.size(); ++sliceIndex) {
285 const Slice& slice(slices.at(sliceIndex));
289 const unsigned int nHitsInSlice(hits.size());
290 const unsigned int nNuHitsInSlice(
293 if (nNuHitsInSlice > maxNuHits) {
294 mostCompleteSliceIndex = sliceIndex;
295 maxNuHits = nNuHitsInSlice;
299 metadata.
m_nHits = nHitsInSlice;
300 metadata.
m_purity = ((nHitsInSlice == 0) ?
302 static_cast<float>(nNuHitsInSlice) /
static_cast<float>(nHitsInSlice));
304 ((nNuHits == 0) ? -1.f :
static_cast<float>(nNuHitsInSlice) /
static_cast<float>(nNuHits));
307 sliceMetadata.push_back(metadata);
310 sliceMetadata.at(mostCompleteSliceIndex).m_isMostComplete =
true;
317 : m_purity(-std::numeric_limits<float>::max())
318 , m_completeness(-std::numeric_limits<float>::max())
319 , m_nHits(std::numeric_limits<unsigned int>::max())
320 , m_isMostComplete(false)
helper class for slice id tools
static unsigned int CountNeutrinoHits(const HitVector &hits, const HitToBoolMap &hitToIsNuInducedMap)
Count the number of hits in an input vector that are neutrino induced.
static void GetSliceMetadata(const SliceVector &slices, const art::Event &evt, const std::string &truthLabel, const std::string &mcParticleLabel, const std::string &hitLabel, const std::string &backtrackLabel, const std::string &pandoraLabel, SliceMetadataVector &sliceMetadata, simb::MCNeutrino &mcNeutrino)
Get MC metadata about each slice.
std::unordered_map< art::Ptr< recob::Hit >, bool > HitToBoolMap
static void CollectHits(const PFParticleVector &pfParticles, const PFParticlesToHits &pfParticleToHitsMap, HitVector &hits)
Collect the hits in a given vector of PFParticles.
static void GetPFParticleToHitsMap(const art::Event &evt, const std::string &pandoraLabel, PFParticlesToHits &pfParticleToHitsMap)
Get the mapping from PFParticles to associated hits (via clusters)
static void CollectNeutrinoMCParticles(const art::Event &evt, const std::string &truthLabel, const std::string &mcParticleLabel, const art::Ptr< simb::MCTruth > &beamNuMCTruth, MCParticleVector &mcParticles)
Collect all MCParticles that come from the beam neutrino interaction.
static void GetHitOrigins(const art::Event &evt, const std::string &hitLabel, const std::string &backtrackLabel, const MCParticleVector &mcParticles, HitVector &hits, HitToBoolMap &hitToIsNuInducedMap)
For each hit in the event, determine if any of it's charge was deposited by a neutrino induced partic...
std::vector< SliceMetadata > SliceMetadataVector
static void GetReconstructedHitsInSlice(const Slice &slice, const PFParticlesToHits &pfParticleToHitsMap, HitVector &hits)
Collect the hits in the slice that have been added to a PFParticle (under either reconstruction hypot...
static art::Ptr< simb::MCTruth > GetBeamNeutrinoMCTruth(const art::Event &evt, const std::string &truthLabel)
Get the MCTruth block for the simulated beam neutrino.
const PFParticleVector & GetTargetHypothesis() const
Get the slice as reconstructed under the target hypothesis.
const PFParticleVector & GetCosmicRayHypothesis() const
Get the slice as reconstructed under the cosmic-ray hypothesis.
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
std::vector< art::Ptr< recob::Hit > > HitVector
std::vector< Slice > SliceVector
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector