LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArPandoraSliceIdHelper.cxx
Go to the documentation of this file.
1 
9 
14 
18 
19 namespace lar_pandora {
20 
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,
28  SliceMetadataVector& sliceMetadata,
29  simb::MCNeutrino& mcNeutrino)
30  {
31  // Find the beam neutrino in MC
32  const auto beamNuMCTruth(LArPandoraSliceIdHelper::GetBeamNeutrinoMCTruth(evt, truthLabel));
33  mcNeutrino = beamNuMCTruth->GetNeutrino();
34 
35  // Collect all MC particles resulting from the beam neutrino
36  MCParticleVector mcParticles;
38  evt, truthLabel, mcParticleLabel, beamNuMCTruth, mcParticles);
39 
40  // Get the hits and determine which are neutrino induced
42  HitToBoolMap hitToIsNuInducedMap;
44  evt, hitLabel, backtrackLabel, mcParticles, hits, hitToIsNuInducedMap);
45  const unsigned int nNuHits(
46  LArPandoraSliceIdHelper::CountNeutrinoHits(hits, hitToIsNuInducedMap));
47 
48  // Get the mapping from PFParticle to hits through clusters
49  PFParticlesToHits pfParticleToHitsMap;
50  LArPandoraSliceIdHelper::GetPFParticleToHitsMap(evt, pandoraLabel, pfParticleToHitsMap);
51 
52  // Calculate the metadata for each slice
54  slices, pfParticleToHitsMap, hitToIsNuInducedMap, nNuHits, sliceMetadata);
55  }
56 
57  // -----------------------------------------------------------------------------------------------------------------------------------------
58 
60  const art::Event& evt,
61  const std::string& truthLabel)
62  {
63  // Get the MCTruth handle
65  evt.getByLabel(truthLabel, mcTruthHandle);
66 
67  if (!mcTruthHandle.isValid())
68  throw cet::exception("LArPandora")
69  << " LArPandoraSliceIdHelper::GetBeamNeutrinoMCTruth - invalid MCTruth handle" << std::endl;
70 
71  // Look for the truth block that is from the beam neutrino, and ensure we choose the one with the highest energy if there are multiple
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);
77 
78  if (mcTruth->Origin() != simb::kBeamNeutrino) continue;
79 
80  const float nuEnergy(mcTruth->GetNeutrino().Nu().E());
81  if (nuEnergy < maxNeutrinoEnergy) continue;
82 
83  // Select this as the beam neutrino
84  maxNeutrinoEnergy = nuEnergy;
85  beamNuMCTruth = mcTruth;
86  foundNeutrino = true;
87  }
88 
89  if (!foundNeutrino)
90  throw cet::exception("LArPandora") << " LArPandoraSliceIdHelper::GetBeamNeutrinoMCTruth - "
91  "found no beam neutrino MCTruth blocks"
92  << std::endl;
93 
94  return beamNuMCTruth;
95  }
96 
97  // -----------------------------------------------------------------------------------------------------------------------------------------
98 
100  const art::Event& evt,
101  const std::string& truthLabel,
102  const std::string& mcParticleLabel,
103  const art::Ptr<simb::MCTruth>& beamNuMCTruth,
104  MCParticleVector& mcParticles)
105  {
106  // Get the MCTruth handle
108  evt.getByLabel(truthLabel, mcTruthHandle);
109 
110  if (!mcTruthHandle.isValid())
111  throw cet::exception("LArPandora")
112  << " LArPandoraSliceIdHelper::CollectNeutrinoMCParticles - invalid MCTruth handle"
113  << std::endl;
114 
115  // Find MCParticles that are associated to the beam neutrino MCTruth block
116  art::FindManyP<simb::MCParticle> truthToMCParticleAssns(mcTruthHandle, evt, mcParticleLabel);
117  mcParticles = truthToMCParticleAssns.at(
118  beamNuMCTruth
119  .key()); // ATTN will throw if association from beamNuMCTruth doesn't exist. We want this!
120  }
121 
122  // -----------------------------------------------------------------------------------------------------------------------------------------
123 
125  const std::string& hitLabel,
126  const std::string& backtrackLabel,
127  const MCParticleVector& mcParticles,
128  HitVector& hits,
129  HitToBoolMap& hitToIsNuInducedMap)
130  {
131  // Collect the hits from the event
133  evt.getByLabel(hitLabel, hitHandle);
134 
135  if (!hitHandle.isValid())
136  throw cet::exception("LArPandora")
137  << " LArPandoraSliceIdHelper::GetHitOrigins - invalid hit handle" << std::endl;
138 
139  art::FindManyP<simb::MCParticle> hitToMCParticleAssns(hitHandle, evt, backtrackLabel);
140 
141  // Find the hits that are associated to a neutrino induced MCParticle using the Hit->MCParticle associations form the backtracker
142  for (unsigned int i = 0; i < hitHandle->size(); ++i) {
143  const art::Ptr<recob::Hit> hit(hitHandle, i);
144  hits.push_back(hit);
145 
146  const auto& particles(hitToMCParticleAssns.at(hit.key()));
147 
148  bool foundNuParticle(false);
149  for (const auto& part : particles) {
150  // If the MCParticles isn't in the list of neutrino particles
151  if (std::find(mcParticles.begin(), mcParticles.end(), part) == mcParticles.end()) continue;
152 
153  foundNuParticle = true;
154  break;
155  }
156 
157  if (!hitToIsNuInducedMap.emplace(hit, foundNuParticle).second)
158  throw cet::exception("LArPandora")
159  << " LArPandoraSliceIdHelper::GetHitOrigins - repeated hits in input collection"
160  << std::endl;
161  }
162  }
163 
164  // -----------------------------------------------------------------------------------------------------------------------------------------
165 
167  const HitToBoolMap& hitToIsNuInducedMap)
168  {
169  unsigned int nNuHits(0);
170  for (const auto& hit : hits) {
171  const auto it(hitToIsNuInducedMap.find(hit));
172 
173  if (it == hitToIsNuInducedMap.end())
174  throw cet::exception("LArPandora")
175  << " LArPandoraSliceIdHelper::CountNeutrinoHits - can't find hit in hitToIsNuInducedMap"
176  << std::endl;
177 
178  nNuHits += it->second ? 1 : 0;
179  }
180 
181  return nNuHits;
182  }
183 
184  // -----------------------------------------------------------------------------------------------------------------------------------------
185 
187  const std::string& pandoraLabel,
188  PFParticlesToHits& pfParticleToHitsMap)
189  {
190  // Get the PFParticles
192  evt.getByLabel(pandoraLabel, pfParticleHandle);
193 
194  if (!pfParticleHandle.isValid())
195  throw cet::exception("LArPandora")
196  << " LArPandoraSliceIdHelper::GetPFParticleToHitsMap - invalid PFParticle handle"
197  << std::endl;
198 
199  // Get the Clusters
201  evt.getByLabel(pandoraLabel, clusterHandle);
202 
203  if (!clusterHandle.isValid())
204  throw cet::exception("LArPandora")
205  << " LArPandoraSliceIdHelper::GetPFParticleToHitsMap - invalid cluster handle" << std::endl;
206 
207  // Get the associations between PFParticles -> Clusters -> Hits
208  art::FindManyP<recob::Cluster> pfParticleToClusterAssns(pfParticleHandle, evt, pandoraLabel);
209  art::FindManyP<recob::Hit> clusterToHitAssns(clusterHandle, evt, pandoraLabel);
210 
211  // Get the hits associated to each PFParticles
212  for (unsigned int iPart = 0; iPart < pfParticleHandle->size(); ++iPart) {
213  const art::Ptr<recob::PFParticle> part(pfParticleHandle, iPart);
214  HitVector hits;
215 
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!"
221  << std::endl;
222 
223  hits.push_back(hit);
224  }
225  }
226 
227  if (!pfParticleToHitsMap.emplace(part, hits).second)
228  throw cet::exception("LArPandora")
229  << " LArPandoraSliceIdHelper::GetPFParticleToHitsMap - repeated input PFParticles"
230  << std::endl;
231  }
232  }
233 
234  // -----------------------------------------------------------------------------------------------------------------------------------------
235 
237  const Slice& slice,
238  const PFParticlesToHits& pfParticleToHitsMap,
239  HitVector& hits)
240  {
241  // ATTN here we use the PFParticles from both hypotheses to collect the hits. Hits will not be double counted
242  LArPandoraSliceIdHelper::CollectHits(slice.GetTargetHypothesis(), pfParticleToHitsMap, hits);
244  }
245 
246  // -----------------------------------------------------------------------------------------------------------------------------------------
247 
249  const PFParticlesToHits& pfParticleToHitsMap,
250  HitVector& hits)
251  {
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"
257  << std::endl;
258 
259  for (const auto& hit : it->second) {
260  // ATTN here we ensure that we don't double count hits, even if the input PFParticles are from different Pandora instances
261  if (std::find(hits.begin(), hits.end(), hit) == hits.end()) hits.push_back(hit);
262  }
263  }
264  }
265 
266  // -----------------------------------------------------------------------------------------------------------------------------------------
267 
269  const PFParticlesToHits& pfParticleToHitsMap,
270  const HitToBoolMap& hitToIsNuInducedMap,
271  const unsigned int nNuHits,
272  SliceMetadataVector& sliceMetadata)
273  {
274  if (!sliceMetadata.empty())
275  throw cet::exception("LArPandora")
276  << " LArPandoraSliceIdHelper::GetSliceMetadata - non empty input metadata vector"
277  << std::endl;
278 
279  if (slices.empty()) return;
280 
281  unsigned int mostCompleteSliceIndex(0);
282  unsigned int maxNuHits(0);
283 
284  for (unsigned int sliceIndex = 0; sliceIndex < slices.size(); ++sliceIndex) {
285  const Slice& slice(slices.at(sliceIndex));
286  HitVector hits;
287  LArPandoraSliceIdHelper::GetReconstructedHitsInSlice(slice, pfParticleToHitsMap, hits);
288 
289  const unsigned int nHitsInSlice(hits.size());
290  const unsigned int nNuHitsInSlice(
291  LArPandoraSliceIdHelper::CountNeutrinoHits(hits, hitToIsNuInducedMap));
292 
293  if (nNuHitsInSlice > maxNuHits) {
294  mostCompleteSliceIndex = sliceIndex;
295  maxNuHits = nNuHitsInSlice;
296  }
297 
298  SliceMetadata metadata;
299  metadata.m_nHits = nHitsInSlice;
300  metadata.m_purity = ((nHitsInSlice == 0) ?
301  -1.f :
302  static_cast<float>(nNuHitsInSlice) / static_cast<float>(nHitsInSlice));
303  metadata.m_completeness =
304  ((nNuHits == 0) ? -1.f : static_cast<float>(nNuHitsInSlice) / static_cast<float>(nNuHits));
305  metadata.m_isMostComplete = false;
306 
307  sliceMetadata.push_back(metadata);
308  }
309 
310  sliceMetadata.at(mostCompleteSliceIndex).m_isMostComplete = true;
311  }
312 
313  // -----------------------------------------------------------------------------------------------------------------------------------------
314  // -----------------------------------------------------------------------------------------------------------------------------------------
315 
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)
321  {}
322 
323 } // namespace lar_pandora
double E(const int i=0) const
Definition: MCParticle.h:234
std::unordered_map< art::Ptr< recob::Hit >, bool > HitToBoolMap
Slice class.
Definition: Slice.h:17
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 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.
float m_purity
The fraction of hits in the slice that are neutrino induced.
const simb::MCNeutrino & GetNeutrino() const
Definition: MCTruth.h:77
static void CollectHits(const PFParticleVector &pfParticles, const PFParticlesToHits &pfParticleToHitsMap, HitVector &hits)
Collect the hits in a given vector of PFParticles.
const PFParticleVector & GetCosmicRayHypothesis() const
Get the slice as reconstructed under the cosmic-ray hypothesis.
Definition: Slice.h:100
Declaration of signal hit object.
const simb::MCParticle & Nu() const
Definition: MCNeutrino.h:146
simb::Origin_t Origin() const
Definition: MCTruth.h:74
unsigned int m_nHits
The number of hits in the slice.
STL namespace.
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 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&#39;s charge was deposited by a neutrino induced partic...
std::vector< SliceMetadata > SliceMetadataVector
Cluster finding and building.
helper class for slice id tools
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...
bool isValid() const noexcept
Definition: Handle.h:203
TFile f
Definition: plotHisto.C:6
float m_completeness
The fraction of all neutrino induced hits that are in the slice.
TString part[npart]
Definition: Style.C:32
void hits()
Definition: readHits.C:15
const PFParticleVector & GetTargetHypothesis() const
Get the slice as reconstructed under the target hypothesis.
Definition: Slice.h:93
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::vector< art::Ptr< recob::PFParticle > > PFParticleVector
key_type key() const noexcept
Definition: Ptr.h:166
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
Declaration of cluster object.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
Detector simulation of raw signals on wires.
std::vector< art::Ptr< recob::Hit > > HitVector
static art::Ptr< simb::MCTruth > GetBeamNeutrinoMCTruth(const art::Event &evt, const std::string &truthLabel)
Get the MCTruth block for the simulated beam neutrino.
std::vector< Slice > SliceVector
Definition: Slice.h:70
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
bool m_isMostComplete
If the slice has the highest completeness in the event.
TCEvent evt
Definition: DataStructs.cxx:8
Event generator information.
Definition: MCNeutrino.h:18
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Beam neutrinos.
Definition: MCTruth.h:23