All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LArPandoraHelper.cxx
Go to the documentation of this file.
1 /**
2  * @file larpandora/LArPandoraInterface/LArPandoraHelper.cxx
3  *
4  * @brief helper function for LArPandoraInterface producer module
5  *
6  */
7 
9 
10 #include "art/Framework/Principal/Event.h"
11 #include "art/Framework/Principal/Handle.h"
12 #include "art/Framework/Services/Registry/ServiceHandle.h"
13 #include "canvas/Persistency/Common/FindManyP.h"
14 #include "canvas/Persistency/Common/FindOneP.h"
15 #include "cetlib_except/exception.h"
16 #include "messagefacility/MessageLogger/MessageLogger.h"
17 
32 #include "nusimdata/SimulationBase/MCTruth.h"
33 
37 
38 #include "Objects/ParticleFlowObject.h"
39 #include "Pandora/PandoraInternal.h"
40 #include "Pandora/PdgTable.h"
41 
42 #include <iostream>
43 #include <limits>
44 
45 namespace lar_pandora {
46 
47  void
49  const std::string& label,
50  WireVector& wireVector)
51  {
52  art::Handle<std::vector<recob::Wire>> theWires;
53  evt.getByLabel(label, theWires);
54 
55  if (!theWires.isValid()) {
56  mf::LogDebug("LArPandora") << " Failed to find wires... " << std::endl;
57  return;
58  }
59  else {
60  mf::LogDebug("LArPandora") << " Found: " << theWires->size() << " Wires " << std::endl;
61  }
62 
63  for (unsigned int i = 0; i < theWires->size(); ++i) {
64  const art::Ptr<recob::Wire> wire(theWires, i);
65  wireVector.push_back(wire);
66  }
67  }
68 
69  //------------------------------------------------------------------------------------------------------------------------------------------
70 
71  void
73  const std::string& label,
74  HitVector& hitVector)
75  {
76  art::Handle<std::vector<recob::Hit>> theHits;
77  evt.getByLabel(label, theHits);
78 
79  if (!theHits.isValid()) {
80  mf::LogDebug("LArPandora") << " Failed to find hits... " << std::endl;
81  return;
82  }
83  else {
84  mf::LogDebug("LArPandora") << " Found: " << theHits->size() << " Hits " << std::endl;
85  }
86 
87  for (unsigned int i = 0; i < theHits->size(); ++i) {
88  const art::Ptr<recob::Hit> hit(theHits, i);
89  hitVector.push_back(hit);
90  }
91  }
92 
93  //------------------------------------------------------------------------------------------------------------------------------------------
94 
95  void
97  const std::string& label,
98  PFParticleVector& particleVector)
99  {
100  art::Handle<std::vector<recob::PFParticle>> theParticles;
101  evt.getByLabel(label, theParticles);
102 
103  if (!theParticles.isValid()) {
104  mf::LogDebug("LArPandora") << " Failed to find particles... " << std::endl;
105  return;
106  }
107  else {
108  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " PFParticles "
109  << std::endl;
110  }
111 
112  for (unsigned int i = 0; i < theParticles->size(); ++i) {
113  const art::Ptr<recob::PFParticle> particle(theParticles, i);
114  particleVector.push_back(particle);
115  }
116  }
117 
118  //------------------------------------------------------------------------------------------------------------------------------------------
119 
120  void
122  const std::string& label,
123  SpacePointVector& spacePointVector,
124  SpacePointsToHits& spacePointsToHits)
125  {
126  HitsToSpacePoints hitsToSpacePoints;
128  evt, label, spacePointVector, spacePointsToHits, hitsToSpacePoints);
129  }
130 
131  //------------------------------------------------------------------------------------------------------------------------------------------
132 
133  void
135  const std::string& label,
136  SpacePointVector& spacePointVector,
137  SpacePointsToHits& spacePointsToHits,
138  HitsToSpacePoints& hitsToSpacePoints)
139  {
140  art::Handle<std::vector<recob::SpacePoint>> theSpacePoints;
141  evt.getByLabel(label, theSpacePoints);
142 
143  if (!theSpacePoints.isValid()) {
144  mf::LogDebug("LArPandora") << " Failed to find spacepoints... " << std::endl;
145  return;
146  }
147  else {
148  mf::LogDebug("LArPandora") << " Found: " << theSpacePoints->size() << " SpacePoints "
149  << std::endl;
150  }
151 
152  art::FindOneP<recob::Hit> theHitAssns(theSpacePoints, evt, label);
153  for (unsigned int i = 0; i < theSpacePoints->size(); ++i) {
154  const art::Ptr<recob::SpacePoint> spacepoint(theSpacePoints, i);
155  spacePointVector.push_back(spacepoint);
156  const art::Ptr<recob::Hit> hit = theHitAssns.at(i);
157  spacePointsToHits[spacepoint] = hit;
158  hitsToSpacePoints[hit] = spacepoint;
159  }
160  }
161 
162  //------------------------------------------------------------------------------------------------------------------------------------------
163 
164  void
166  const std::string& label,
167  ClusterVector& clusterVector,
168  ClustersToHits& clustersToHits)
169  {
170  art::Handle<std::vector<recob::Cluster>> theClusters;
171  evt.getByLabel(label, theClusters);
172 
173  if (!theClusters.isValid()) {
174  mf::LogDebug("LArPandora") << " Failed to find clusters... " << std::endl;
175  return;
176  }
177  else {
178  mf::LogDebug("LArPandora") << " Found: " << theClusters->size() << " Clusters " << std::endl;
179  }
180 
181  art::FindManyP<recob::Hit> theHitAssns(theClusters, evt, label);
182  for (unsigned int i = 0; i < theClusters->size(); ++i) {
183  const art::Ptr<recob::Cluster> cluster(theClusters, i);
184  clusterVector.push_back(cluster);
185 
186  const std::vector<art::Ptr<recob::Hit>> hits = theHitAssns.at(i);
187  for (unsigned int j = 0; j < hits.size(); ++j) {
188  const art::Ptr<recob::Hit> hit = hits.at(j);
189  clustersToHits[cluster].push_back(hit);
190  }
191  }
192  }
193 
194  //------------------------------------------------------------------------------------------------------------------------------------------
195 
196  void
198  const std::string& label,
199  PFParticleVector& particleVector,
200  PFParticlesToSpacePoints& particlesToSpacePoints)
201  {
202  art::Handle<std::vector<recob::PFParticle>> theParticles;
203  evt.getByLabel(label, theParticles);
204 
205  if (!theParticles.isValid()) {
206  mf::LogDebug("LArPandora") << " Failed to find particles... " << std::endl;
207  return;
208  }
209  else {
210  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " PFParticles "
211  << std::endl;
212  }
213 
214  art::FindManyP<recob::SpacePoint> theSpacePointAssns(theParticles, evt, label);
215  for (unsigned int i = 0; i < theParticles->size(); ++i) {
216  const art::Ptr<recob::PFParticle> particle(theParticles, i);
217  particleVector.push_back(particle);
218 
219  const std::vector<art::Ptr<recob::SpacePoint>> spacepoints = theSpacePointAssns.at(i);
220  for (unsigned int j = 0; j < spacepoints.size(); ++j) {
221  const art::Ptr<recob::SpacePoint> spacepoint = spacepoints.at(j);
222  particlesToSpacePoints[particle].push_back(spacepoint);
223  }
224  }
225  }
226 
227  //------------------------------------------------------------------------------------------------------------------------------------------
228 
229  void
230  LArPandoraHelper::CollectPFParticles(const art::Event& evt,
231  const std::string& label,
232  PFParticleVector& particleVector,
233  PFParticlesToClusters& particlesToClusters)
234  {
235  art::Handle<std::vector<recob::PFParticle>> theParticles;
236  evt.getByLabel(label, theParticles);
237 
238  if (!theParticles.isValid()) {
239  mf::LogDebug("LArPandora") << " Failed to find particles... " << std::endl;
240  return;
241  }
242  else {
243  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " PFParticles "
244  << std::endl;
245  }
246 
247  art::FindManyP<recob::Cluster> theClusterAssns(theParticles, evt, label);
248  for (unsigned int i = 0; i < theParticles->size(); ++i) {
249  const art::Ptr<recob::PFParticle> particle(theParticles, i);
250  particleVector.push_back(particle);
251 
252  const std::vector<art::Ptr<recob::Cluster>> clusters = theClusterAssns.at(i);
253  for (unsigned int j = 0; j < clusters.size(); ++j) {
254  const art::Ptr<recob::Cluster> cluster = clusters.at(j);
255  particlesToClusters[particle].push_back(cluster);
256  }
257  }
258  }
259 
260  //------------------------------------------------------------------------------------------------------------------------------------------
261 
262  void
264  const std::string& label,
265  PFParticleVector& particleVector,
266  PFParticlesToMetadata& particlesToMetadata)
267  {
268  art::Handle<std::vector<recob::PFParticle>> theParticles;
269  evt.getByLabel(label, theParticles);
270 
271  if (!theParticles.isValid()) {
272  mf::LogDebug("LArPandora") << " Failed to find particles... " << std::endl;
273  return;
274  }
275  else {
276  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " PFParticles "
277  << std::endl;
278  }
279 
280  art::FindManyP<larpandoraobj::PFParticleMetadata> theMetadataAssns(theParticles, evt, label);
281  for (unsigned int i = 0; i < theParticles->size(); ++i) {
282  const art::Ptr<recob::PFParticle> particle(theParticles, i);
283  particleVector.push_back(particle);
284 
285  const std::vector<art::Ptr<larpandoraobj::PFParticleMetadata>> pfParticleMetadataList =
286  theMetadataAssns.at(i);
287  for (unsigned int j = 0; j < pfParticleMetadataList.size(); ++j) {
288  const art::Ptr<larpandoraobj::PFParticleMetadata> pfParticleMetadata =
289  pfParticleMetadataList.at(j);
290  particlesToMetadata[particle].push_back(pfParticleMetadata);
291  }
292  }
293  }
294 
295  //------------------------------------------------------------------------------------------------------------------------------------------
296 
297  void
298  LArPandoraHelper::CollectShowers(const art::Event& evt,
299  const std::string& label,
300  ShowerVector& showerVector,
301  PFParticlesToShowers& particlesToShowers)
302  {
303  art::Handle<std::vector<recob::Shower>> theShowers;
304  evt.getByLabel(label, theShowers);
305 
306  if (!theShowers.isValid()) {
307  mf::LogDebug("LArPandora") << " Failed to find showers... " << std::endl;
308  return;
309  }
310  else {
311  mf::LogDebug("LArPandora") << " Found: " << theShowers->size() << " Showers " << std::endl;
312  }
313 
314  art::FindManyP<recob::PFParticle> theShowerAssns(theShowers, evt, label);
315  for (unsigned int i = 0; i < theShowers->size(); ++i) {
316  const art::Ptr<recob::Shower> shower(theShowers, i);
317  showerVector.push_back(shower);
318 
319  const std::vector<art::Ptr<recob::PFParticle>> particles = theShowerAssns.at(i);
320  for (unsigned int j = 0; j < particles.size(); ++j) {
321  const art::Ptr<recob::PFParticle> particle = particles.at(j);
322  particlesToShowers[particle].push_back(shower);
323  }
324  }
325  }
326 
327  //------------------------------------------------------------------------------------------------------------------------------------------
328 
329  void
330  LArPandoraHelper::CollectTracks(const art::Event& evt,
331  const std::string& label,
332  TrackVector& trackVector,
333  PFParticlesToTracks& particlesToTracks)
334  {
335  art::Handle<std::vector<recob::Track>> theTracks;
336  evt.getByLabel(label, theTracks);
337 
338  if (!theTracks.isValid()) {
339  mf::LogDebug("LArPandora") << " Failed to find tracks... " << std::endl;
340  return;
341  }
342  else {
343  mf::LogDebug("LArPandora") << " Found: " << theTracks->size() << " Tracks " << std::endl;
344  }
345 
346  art::FindManyP<recob::PFParticle> theTrackAssns(theTracks, evt, label);
347  for (unsigned int i = 0; i < theTracks->size(); ++i) {
348  const art::Ptr<recob::Track> track(theTracks, i);
349  trackVector.push_back(track);
350 
351  const std::vector<art::Ptr<recob::PFParticle>> particles = theTrackAssns.at(i);
352  for (unsigned int j = 0; j < particles.size(); ++j) {
353  const art::Ptr<recob::PFParticle> particle = particles.at(j);
354  particlesToTracks[particle].push_back(track);
355  }
356  }
357  }
358 
359  //------------------------------------------------------------------------------------------------------------------------------------------
360 
361  void
362  LArPandoraHelper::CollectTracks(const art::Event& evt,
363  const std::string& label,
364  TrackVector& trackVector,
365  TracksToHits& tracksToHits)
366  {
367  art::Handle<std::vector<recob::Track>> theTracks;
368  evt.getByLabel(label, theTracks);
369 
370  if (!theTracks.isValid()) {
371  mf::LogDebug("LArPandora") << " Failed to find tracks... " << std::endl;
372  return;
373  }
374  else {
375  mf::LogDebug("LArPandora") << " Found: " << theTracks->size() << " Tracks " << std::endl;
376  }
377 
378  art::FindManyP<recob::Hit> theHitAssns(theTracks, evt, label);
379  for (unsigned int i = 0; i < theTracks->size(); ++i) {
380  const art::Ptr<recob::Track> track(theTracks, i);
381  trackVector.push_back(track);
382 
383  const std::vector<art::Ptr<recob::Hit>> hits = theHitAssns.at(i);
384  for (unsigned int j = 0; j < hits.size(); ++j) {
385  const art::Ptr<recob::Hit> hit = hits.at(j);
386  tracksToHits[track].push_back(hit);
387  }
388  }
389  }
390 
391  //------------------------------------------------------------------------------------------------------------------------------------------
392 
393  void
394  LArPandoraHelper::CollectShowers(const art::Event& evt,
395  const std::string& label,
396  ShowerVector& showerVector,
397  ShowersToHits& showersToHits)
398  {
399  art::Handle<std::vector<recob::Shower>> theShowers;
400  evt.getByLabel(label, theShowers);
401 
402  if (!theShowers.isValid()) {
403  mf::LogDebug("LArPandora") << " Failed to find showers... " << std::endl;
404  return;
405  }
406  else {
407  mf::LogDebug("LArPandora") << " Found: " << theShowers->size() << " Showers " << std::endl;
408  }
409 
410  art::FindManyP<recob::Hit> theHitAssns(theShowers, evt, label);
411  for (unsigned int i = 0; i < theShowers->size(); ++i) {
412  const art::Ptr<recob::Shower> shower(theShowers, i);
413  showerVector.push_back(shower);
414 
415  const std::vector<art::Ptr<recob::Hit>> hits = theHitAssns.at(i);
416  for (unsigned int j = 0; j < hits.size(); ++j) {
417  const art::Ptr<recob::Hit> hit = hits.at(j);
418  showersToHits[shower].push_back(hit);
419  }
420  }
421  }
422 
423  //------------------------------------------------------------------------------------------------------------------------------------------
424 
425  void
426  LArPandoraHelper::CollectSeeds(const art::Event& evt,
427  const std::string& label,
428  SeedVector& seedVector,
429  PFParticlesToSeeds& particlesToSeeds)
430  {
431  art::Handle<std::vector<recob::Seed>> theSeeds;
432  evt.getByLabel(label, theSeeds);
433 
434  if (!theSeeds.isValid()) {
435  mf::LogDebug("LArPandora") << " Failed to find seeds... " << std::endl;
436  return;
437  }
438  else {
439  mf::LogDebug("LArPandora") << " Found: " << theSeeds->size() << " Seeds " << std::endl;
440  }
441 
442  art::FindManyP<recob::PFParticle> theSeedAssns(theSeeds, evt, label);
443  for (unsigned int i = 0; i < theSeeds->size(); ++i) {
444  const art::Ptr<recob::Seed> seed(theSeeds, i);
445  seedVector.push_back(seed);
446 
447  const std::vector<art::Ptr<recob::PFParticle>> particles = theSeedAssns.at(i);
448  for (unsigned int j = 0; j < particles.size(); ++j) {
449  const art::Ptr<recob::PFParticle> particle = particles.at(j);
450  particlesToSeeds[particle].push_back(seed);
451  }
452  }
453  }
454 
455  //------------------------------------------------------------------------------------------------------------------------------------------
456 
457  void
458  LArPandoraHelper::CollectSeeds(const art::Event& evt,
459  const std::string& label,
460  SeedVector& seedVector,
461  SeedsToHits& seedsToHits)
462  {
463  art::Handle<std::vector<recob::Seed>> theSeeds;
464  evt.getByLabel(label, theSeeds);
465 
466  if (!theSeeds.isValid()) {
467  mf::LogDebug("LArPandora") << " Failed to find seeds... " << std::endl;
468  return;
469  }
470  else {
471  mf::LogDebug("LArPandora") << " Found: " << theSeeds->size() << " Seeds " << std::endl;
472  }
473 
474  art::FindOneP<recob::Hit> theHitAssns(theSeeds, evt, label);
475 
476  if (!theHitAssns.isValid()) {
477  mf::LogDebug("LArPandora") << " Failed to find seed associations... " << std::endl;
478  return;
479  }
480 
481  for (unsigned int i = 0; i < theSeeds->size(); ++i) {
482  const art::Ptr<recob::Seed> seed(theSeeds, i);
483  seedVector.push_back(seed);
484  const art::Ptr<recob::Hit> hit = theHitAssns.at(i);
485  seedsToHits[seed] = hit;
486  }
487  }
488 
489  //------------------------------------------------------------------------------------------------------------------------------------------
490 
491  void
492  LArPandoraHelper::CollectVertices(const art::Event& evt,
493  const std::string& label,
494  VertexVector& vertexVector,
495  PFParticlesToVertices& particlesToVertices)
496  {
497  art::Handle<std::vector<recob::Vertex>> theVertices;
498  evt.getByLabel(label, theVertices);
499 
500  if (!theVertices.isValid()) {
501  mf::LogDebug("LArPandora") << " Failed to find vertices... " << std::endl;
502  return;
503  }
504  else {
505  mf::LogDebug("LArPandora") << " Found: " << theVertices->size() << " Vertices " << std::endl;
506  }
507 
508  art::FindManyP<recob::PFParticle> theVerticesAssns(theVertices, evt, label);
509  for (unsigned int i = 0; i < theVertices->size(); ++i) {
510  const art::Ptr<recob::Vertex> vertex(theVertices, i);
511  vertexVector.push_back(vertex);
512 
513  const std::vector<art::Ptr<recob::PFParticle>> particles = theVerticesAssns.at(i);
514  for (unsigned int j = 0; j < particles.size(); ++j) {
515  const art::Ptr<recob::PFParticle> particle = particles.at(j);
516  particlesToVertices[particle].push_back(vertex);
517  }
518  }
519  }
520 
521  //------------------------------------------------------------------------------------------------------------------------------------------
522 
523  void
525  const PFParticlesToSpacePoints& particlesToSpacePoints,
526  const SpacePointsToHits& spacePointsToHits,
527  PFParticlesToHits& particlesToHits,
528  HitsToPFParticles& hitsToParticles,
529  const DaughterMode daughterMode)
530  {
531  // Build mapping from particle to particle ID for parent/daughter navigation
532  PFParticleMap particleMap;
533 
534  for (PFParticleVector::const_iterator iter1 = particleVector.begin(),
535  iterEnd1 = particleVector.end();
536  iter1 != iterEnd1;
537  ++iter1) {
538  const art::Ptr<recob::PFParticle> particle = *iter1;
539  particleMap[particle->Self()] = particle;
540  }
541 
542  // Loop over hits and build mapping between reconstructed final-state particles and reconstructed hits
543  for (PFParticlesToSpacePoints::const_iterator iter1 = particlesToSpacePoints.begin(),
544  iterEnd1 = particlesToSpacePoints.end();
545  iter1 != iterEnd1;
546  ++iter1) {
547  const art::Ptr<recob::PFParticle> thisParticle = iter1->first;
548  const art::Ptr<recob::PFParticle> particle(
549  (kAddDaughters == daughterMode) ?
550  LArPandoraHelper::GetFinalStatePFParticle(particleMap, thisParticle) :
551  thisParticle);
552 
553  if ((kIgnoreDaughters == daughterMode) &&
554  !LArPandoraHelper::IsFinalState(particleMap, particle))
555  continue;
556 
557  const SpacePointVector& spacePointVector = iter1->second;
558 
559  for (SpacePointVector::const_iterator iter2 = spacePointVector.begin(),
560  iterEnd2 = spacePointVector.end();
561  iter2 != iterEnd2;
562  ++iter2) {
563  const art::Ptr<recob::SpacePoint> spacepoint = *iter2;
564 
565  SpacePointsToHits::const_iterator iter3 = spacePointsToHits.find(spacepoint);
566  if (spacePointsToHits.end() == iter3)
567  throw cet::exception("LArPandora") << " PandoraCollector::BuildPFParticleHitMaps --- "
568  "Found a space point without an associated hit ";
569 
570  const art::Ptr<recob::Hit> hit = iter3->second;
571 
572  particlesToHits[particle].push_back(hit);
573  hitsToParticles[hit] = particle;
574  }
575  }
576  }
577 
578  //------------------------------------------------------------------------------------------------------------------------------------------
579 
580  void
582  const PFParticlesToClusters& particlesToClusters,
583  const ClustersToHits& clustersToHits,
584  PFParticlesToHits& particlesToHits,
585  HitsToPFParticles& hitsToParticles,
586  const DaughterMode daughterMode)
587  {
588  // Build mapping from particle to particle ID for parent/daughter navigation
589  PFParticleMap particleMap;
590 
591  for (PFParticleVector::const_iterator iter1 = particleVector.begin(),
592  iterEnd1 = particleVector.end();
593  iter1 != iterEnd1;
594  ++iter1) {
595  const art::Ptr<recob::PFParticle> particle = *iter1;
596  particleMap[particle->Self()] = particle;
597  }
598 
599  // Loop over hits and build mapping between reconstructed final-state particles and reconstructed hits
600  for (PFParticlesToClusters::const_iterator iter1 = particlesToClusters.begin(),
601  iterEnd1 = particlesToClusters.end();
602  iter1 != iterEnd1;
603  ++iter1) {
604  const art::Ptr<recob::PFParticle> thisParticle = iter1->first;
605  const art::Ptr<recob::PFParticle> particle(
606  (kAddDaughters == daughterMode) ?
607  LArPandoraHelper::GetFinalStatePFParticle(particleMap, thisParticle) :
608  thisParticle);
609 
610  if ((kIgnoreDaughters == daughterMode) &&
611  !LArPandoraHelper::IsFinalState(particleMap, particle))
612  continue;
613 
614  const ClusterVector& clusterVector = iter1->second;
615  for (ClusterVector::const_iterator iter2 = clusterVector.begin(),
616  iterEnd2 = clusterVector.end();
617  iter2 != iterEnd2;
618  ++iter2) {
619  const art::Ptr<recob::Cluster> cluster = *iter2;
620 
621  ClustersToHits::const_iterator iter3 = clustersToHits.find(cluster);
622  if (clustersToHits.end() == iter3)
623  throw cet::exception("LArPandora") << " PandoraCollector::BuildPFParticleHitMaps --- "
624  "Found a space point without an associated hit ";
625 
626  const HitVector& hitVector = iter3->second;
627  for (HitVector::const_iterator iter4 = hitVector.begin(), iterEnd4 = hitVector.end();
628  iter4 != iterEnd4;
629  ++iter4) {
630  const art::Ptr<recob::Hit> hit = *iter4;
631 
632  particlesToHits[particle].push_back(hit);
633  hitsToParticles[hit] = particle;
634  }
635  }
636  }
637  }
638 
639  //------------------------------------------------------------------------------------------------------------------------------------------
640 
641  void
643  const std::string& label,
644  PFParticlesToHits& particlesToHits,
645  HitsToPFParticles& hitsToParticles,
646  const DaughterMode daughterMode,
647  const bool useClusters)
648  {
650  evt, label, label, particlesToHits, hitsToParticles, daughterMode, useClusters);
651  }
652 
653  //------------------------------------------------------------------------------------------------------------------------------------------
654 
655  void
657  const std::string& label_pfpart,
658  const std::string& label_middle,
659  PFParticlesToHits& particlesToHits,
660  HitsToPFParticles& hitsToParticles,
661  const DaughterMode daughterMode,
662  const bool useClusters)
663  {
664  // Use intermediate clusters
665  if (useClusters) {
666  PFParticleVector particleVector;
667  PFParticlesToClusters particlesToClusters;
668 
669  ClusterVector clusterVector;
670  ClustersToHits clustersToHits;
671 
672  LArPandoraHelper::CollectPFParticles(evt, label_pfpart, particleVector, particlesToClusters);
673  LArPandoraHelper::CollectClusters(evt, label_middle, clusterVector, clustersToHits);
674 
676  particlesToClusters,
677  clustersToHits,
678  particlesToHits,
679  hitsToParticles,
680  daughterMode);
681  }
682 
683  // Use intermediate space points
684  else {
685  PFParticleVector particleVector;
686  PFParticlesToSpacePoints particlesToSpacePoints;
687 
688  SpacePointVector spacePointVector;
689  SpacePointsToHits spacePointsToHits;
690 
692  evt, label_pfpart, particleVector, particlesToSpacePoints);
693  LArPandoraHelper::CollectSpacePoints(evt, label_middle, spacePointVector, spacePointsToHits);
694 
696  particlesToSpacePoints,
697  spacePointsToHits,
698  particlesToHits,
699  hitsToParticles,
700  daughterMode);
701  }
702  }
703 
704  //------------------------------------------------------------------------------------------------------------------------------------------
705 
706  void
708  PFParticleVector& outputParticles)
709  {
710  for (PFParticleVector::const_iterator iter = inputParticles.begin(),
711  iterEnd = inputParticles.end();
712  iter != iterEnd;
713  ++iter) {
714  const art::Ptr<recob::PFParticle> particle = *iter;
715 
716  if (LArPandoraHelper::IsNeutrino(particle)) outputParticles.push_back(particle);
717  }
718  }
719 
720  //------------------------------------------------------------------------------------------------------------------------------------------
721 
722  void
724  PFParticleVector& outputParticles)
725  {
726  // Build mapping from particle to particle ID for parent/daughter navigation
727  PFParticleMap particleMap;
728 
729  for (PFParticleVector::const_iterator iter = inputParticles.begin(),
730  iterEnd = inputParticles.end();
731  iter != iterEnd;
732  ++iter) {
733  const art::Ptr<recob::PFParticle> particle = *iter;
734  particleMap[particle->Self()] = particle;
735  }
736 
737  // Select final-state particles
738  for (PFParticleVector::const_iterator iter = inputParticles.begin(),
739  iterEnd = inputParticles.end();
740  iter != iterEnd;
741  ++iter) {
742  const art::Ptr<recob::PFParticle> particle = *iter;
743 
744  if (LArPandoraHelper::IsFinalState(particleMap, particle))
745  outputParticles.push_back(particle);
746  }
747  }
748 
749  //------------------------------------------------------------------------------------------------------------------------------------------
750 
751  void
752  LArPandoraHelper::CollectCosmicTags(const art::Event& evt,
753  const std::string& label,
754  CosmicTagVector& cosmicTagVector,
755  TracksToCosmicTags& tracksToCosmicTags)
756  {
757  art::Handle<std::vector<anab::CosmicTag>> theCosmicTags;
758  evt.getByLabel(label, theCosmicTags);
759 
760  if (theCosmicTags.isValid()) {
761  art::FindOneP<recob::Track> theCosmicAssns(
762  theCosmicTags, evt, label); // We assume there is one tag per algorithm
763  for (unsigned int i = 0; i < theCosmicTags->size(); ++i) {
764  const art::Ptr<anab::CosmicTag> cosmicTag(theCosmicTags, i);
765  const art::Ptr<recob::Track> track = theCosmicAssns.at(i);
766  tracksToCosmicTags[track].push_back(
767  cosmicTag); // We assume there could be multiple algorithms
768  cosmicTagVector.push_back(cosmicTag);
769  }
770  }
771  }
772 
773  //------------------------------------------------------------------------------------------------------------------------------------------
774 
775  void
776  LArPandoraHelper::CollectT0s(const art::Event& evt,
777  const std::string& label,
778  T0Vector& t0Vector,
779  PFParticlesToT0s& particlesToT0s)
780  {
781  art::Handle<std::vector<anab::T0>> theT0s;
782  evt.getByLabel(label, theT0s);
783 
784  if (theT0s.isValid()) {
785  art::FindManyP<recob::PFParticle> theAssns(theT0s, evt, label);
786  for (unsigned int i = 0; i < theT0s->size(); ++i) {
787  const art::Ptr<anab::T0> theT0(theT0s, i);
788  t0Vector.push_back(theT0);
789 
790  const std::vector<art::Ptr<recob::PFParticle>> particles = theAssns.at(i);
791  for (unsigned int j = 0; j < particles.size(); ++j) {
792  const art::Ptr<recob::PFParticle> theParticle = particles.at(j);
793  particlesToT0s[theParticle].push_back(
794  theT0); // We assume there could be multiple T0s per PFParticle
795  }
796  }
797  }
798  }
799 
800  //------------------------------------------------------------------------------------------------------------------------------------------
801 
802  void
804  const std::string& label,
805  SimChannelVector& simChannelVector,
806  bool& areSimChannelsValid)
807  {
808  art::Handle<std::vector<sim::SimChannel>> theSimChannels;
809  evt.getByLabel(label, theSimChannels);
810 
811  if (!theSimChannels.isValid()) {
812  mf::LogDebug("LArPandora") << " Failed to find sim channels... " << std::endl;
813  areSimChannelsValid = false;
814  return;
815  }
816  else {
817  mf::LogDebug("LArPandora") << " Found: " << theSimChannels->size() << " SimChannels "
818  << std::endl;
819  areSimChannelsValid = true;
820  }
821 
822  for (unsigned int i = 0; i < theSimChannels->size(); ++i) {
823  const art::Ptr<sim::SimChannel> channel(theSimChannels, i);
824  simChannelVector.push_back(channel);
825  }
826  }
827 
828  //------------------------------------------------------------------------------------------------------------------------------------------
829 
830  void
832  const std::string& label,
833  MCParticleVector& particleVector)
834  {
835  art::Handle<RawMCParticleVector> theParticles;
836  evt.getByLabel(label, theParticles);
837 
838  if (!theParticles.isValid()) {
839  mf::LogDebug("LArPandora") << " Failed to find MC particles... " << std::endl;
840  return;
841  }
842  else {
843  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " MC particles "
844  << std::endl;
845  }
846 
847  for (unsigned int i = 0; i < theParticles->size(); ++i) {
848  const art::Ptr<simb::MCParticle> particle(theParticles, i);
849  particleVector.push_back(particle);
850  }
851  }
852 
853  //------------------------------------------------------------------------------------------------------------------------------------------
854 
855  void
857  const std::string& label,
858  RawMCParticleVector& particleVector)
859  {
860  art::Handle<std::vector<simb::MCTruth>> mcTruthBlocks;
861  evt.getByLabel(label, mcTruthBlocks);
862 
863  if (!mcTruthBlocks.isValid()) {
864  mf::LogDebug("LArPandora") << " Failed to find MC truth blocks from generator... "
865  << std::endl;
866  return;
867  }
868  else {
869  mf::LogDebug("LArPandora") << " Found: " << mcTruthBlocks->size() << " MC truth blocks "
870  << std::endl;
871  }
872 
873  if (mcTruthBlocks->size() != 1)
874  throw cet::exception("LArPandora") << " PandoraCollector::CollectGeneratorMCParticles --- "
875  "Unexpected number of MC truth blocks ";
876 
877  const art::Ptr<simb::MCTruth> mcTruth(mcTruthBlocks, 0);
878 
879  for (int i = 0; i < mcTruth->NParticles(); ++i) {
880  particleVector.push_back(mcTruth->GetParticle(i));
881  }
882  }
883 
884  //------------------------------------------------------------------------------------------------------------------------------------------
885 
886  void
888  const std::string& label,
889  MCTruthToMCParticles& truthToParticles,
890  MCParticlesToMCTruth& particlesToTruth)
891  {
892  art::Handle<RawMCParticleVector> theParticles;
893  evt.getByLabel(label, theParticles);
894 
895  if (!theParticles.isValid()) {
896  mf::LogDebug("LArPandora") << " Failed to find MC particles... " << std::endl;
897  return;
898  }
899  else {
900  mf::LogDebug("LArPandora") << " Found: " << theParticles->size() << " MC particles "
901  << std::endl;
902  }
903 
904  art::FindOneP<simb::MCTruth> theTruthAssns(theParticles, evt, label);
905 
906  for (unsigned int i = 0, iEnd = theParticles->size(); i < iEnd; ++i) {
907  const art::Ptr<simb::MCParticle> particle(theParticles, i);
908  const art::Ptr<simb::MCTruth> truth(theTruthAssns.at(i));
909  truthToParticles[truth].push_back(particle);
910  particlesToTruth[particle] = truth;
911  }
912  }
913 
914  //------------------------------------------------------------------------------------------------------------------------------------------
915 
916  void
918  const HitVector& hitVector,
919  const SimChannelVector& simChannelVector,
920  HitsToTrackIDEs& hitsToTrackIDEs)
921  {
922  auto const clock_data =
923  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
924 
925  SimChannelMap simChannelMap;
926 
927  for (SimChannelVector::const_iterator iter = simChannelVector.begin(),
928  iterEnd = simChannelVector.end();
929  iter != iterEnd;
930  ++iter) {
931  const art::Ptr<sim::SimChannel> simChannel = *iter;
932  simChannelMap.insert(SimChannelMap::value_type(simChannel->Channel(), simChannel));
933  }
934 
935  for (HitVector::const_iterator iter = hitVector.begin(), iterEnd = hitVector.end();
936  iter != iterEnd;
937  ++iter) {
938  const art::Ptr<recob::Hit> hit = *iter;
939 
940  SimChannelMap::const_iterator sIter = simChannelMap.find(hit->Channel());
941  if (simChannelMap.end() == sIter) continue; // Hit has no truth information [continue]
942 
943  // ATTN: Need to convert TDCtick (integer) to TDC (unsigned integer) before passing to simChannel
944  const raw::TDCtick_t start_tick(clock_data.TPCTick2TDC(hit->PeakTimeMinusRMS()));
945  const raw::TDCtick_t end_tick(clock_data.TPCTick2TDC(hit->PeakTimePlusRMS()));
946  const unsigned int start_tdc((start_tick < 0) ? 0 : start_tick);
947  const unsigned int end_tdc(end_tick);
948 
949  if (start_tdc > end_tdc) continue; // Hit undershoots the readout window [continue]
950 
951  const art::Ptr<sim::SimChannel> simChannel = sIter->second;
952  const TrackIDEVector trackCollection(simChannel->TrackIDEs(start_tdc, end_tdc));
953 
954  if (trackCollection.empty()) continue; // Hit has no truth information [continue]
955 
956  for (unsigned int iTrack = 0, iTrackEnd = trackCollection.size(); iTrack < iTrackEnd;
957  ++iTrack) {
958  const sim::TrackIDE trackIDE = trackCollection.at(iTrack);
959  hitsToTrackIDEs[hit].push_back(trackIDE);
960  }
961  }
962  }
963 
964  //------------------------------------------------------------------------------------------------------------------------------------------
965 
966  void
968  const MCTruthToMCParticles& truthToParticles,
969  MCParticlesToHits& particlesToHits,
970  HitsToMCParticles& hitsToParticles,
971  const DaughterMode daughterMode)
972  {
973  // Build mapping between particles and track IDs for parent/daughter navigation
974  MCParticleMap particleMap;
975 
976  for (MCTruthToMCParticles::const_iterator iter1 = truthToParticles.begin(),
977  iterEnd1 = truthToParticles.end();
978  iter1 != iterEnd1;
979  ++iter1) {
980  const MCParticleVector& particleVector = iter1->second;
981  for (MCParticleVector::const_iterator iter2 = particleVector.begin(),
982  iterEnd2 = particleVector.end();
983  iter2 != iterEnd2;
984  ++iter2) {
985  const art::Ptr<simb::MCParticle> particle = *iter2;
986  particleMap[particle->TrackId()] = particle;
987  }
988  }
989 
990  // Loop over hits and build mapping between reconstructed hits and true particles
991  for (HitsToTrackIDEs::const_iterator iter1 = hitsToTrackIDEs.begin(),
992  iterEnd1 = hitsToTrackIDEs.end();
993  iter1 != iterEnd1;
994  ++iter1) {
995  const art::Ptr<recob::Hit> hit = iter1->first;
996  const TrackIDEVector& trackCollection = iter1->second;
997 
998  int bestTrackID(-1);
999  float bestEnergyFrac(0.f);
1000 
1001  for (TrackIDEVector::const_iterator iter2 = trackCollection.begin(),
1002  iterEnd2 = trackCollection.end();
1003  iter2 != iterEnd2;
1004  ++iter2) {
1005  const sim::TrackIDE& trackIDE = *iter2;
1006  const int trackID(std::abs(trackIDE.trackID)); // TODO: Find out why std::abs is needed
1007  const float energyFrac(trackIDE.energyFrac);
1008 
1009  if (energyFrac > bestEnergyFrac) {
1010  bestEnergyFrac = energyFrac;
1011  bestTrackID = trackID;
1012  }
1013  }
1014 
1015  if (bestTrackID >= 0) {
1016  MCParticleMap::const_iterator iter3 = particleMap.find(bestTrackID);
1017  if (particleMap.end() == iter3)
1018  throw cet::exception("LArPandora") << " PandoraCollector::BuildMCParticleHitMaps --- "
1019  "Found a track ID without an MC Particle ";
1020 
1021  try {
1022  const art::Ptr<simb::MCParticle> thisParticle = iter3->second;
1023  const art::Ptr<simb::MCParticle> primaryParticle(
1024  LArPandoraHelper::GetFinalStateMCParticle(particleMap, thisParticle));
1025  const art::Ptr<simb::MCParticle> selectedParticle(
1026  (kAddDaughters == daughterMode) ? primaryParticle : thisParticle);
1027 
1028  if ((kIgnoreDaughters == daughterMode) && (selectedParticle != primaryParticle)) continue;
1029 
1030  if (!(LArPandoraHelper::IsVisible(selectedParticle))) continue;
1031 
1032  particlesToHits[selectedParticle].push_back(hit);
1033  hitsToParticles[hit] = selectedParticle;
1034  }
1035  catch (cet::exception& e) {
1036  }
1037  }
1038  }
1039  }
1040 
1041  //------------------------------------------------------------------------------------------------------------------------------------------
1042 
1043  void
1045  const std::string& label,
1046  const HitVector& hitVector,
1047  MCParticlesToHits& particlesToHits,
1048  HitsToMCParticles& hitsToParticles,
1049  const DaughterMode daughterMode)
1050  {
1051  SimChannelVector simChannelVector;
1052  MCTruthToMCParticles truthToParticles;
1053  MCParticlesToMCTruth particlesToTruth;
1054  HitsToTrackIDEs hitsToTrackIDEs;
1055 
1056  bool areSimChannelsValid(false);
1057  LArPandoraHelper::CollectSimChannels(evt, label, simChannelVector, areSimChannelsValid);
1058 
1059  LArPandoraHelper::CollectMCParticles(evt, label, truthToParticles, particlesToTruth);
1060  LArPandoraHelper::BuildMCParticleHitMaps(evt, hitVector, simChannelVector, hitsToTrackIDEs);
1062  hitsToTrackIDEs, truthToParticles, particlesToHits, hitsToParticles, daughterMode);
1063  }
1064 
1065  //------------------------------------------------------------------------------------------------------------------------------------------
1066 
1067  void
1069  const std::string& hitLabel,
1070  const std::string& backtrackLabel,
1071  HitsToTrackIDEs& hitsToTrackIDEs)
1072  {
1073  // Start by getting the collection of Hits
1074  art::Handle<std::vector<recob::Hit>> theHits;
1075  evt.getByLabel(hitLabel, theHits);
1076 
1077  if (!theHits.isValid()) {
1078  mf::LogDebug("LArPandora") << " Failed to find hits... " << std::endl;
1079  return;
1080  }
1081 
1082  HitVector hitVector;
1083 
1084  for (unsigned int i = 0; i < theHits->size(); ++i) {
1085  const art::Ptr<recob::Hit> hit(theHits, i);
1086  hitVector.push_back(hit);
1087  }
1088 
1089  // Now get the associations between Hits and MCParticles
1090  std::vector<anab::BackTrackerHitMatchingData const*> backtrackerVector;
1091 
1092  MCParticleVector particleVector;
1093 
1094  art::FindManyP<simb::MCParticle, anab::BackTrackerHitMatchingData> particles_per_hit(
1095  theHits, evt, backtrackLabel);
1096 
1097  if (!particles_per_hit.isValid()) {
1098  mf::LogDebug("LArPandora") << " Failed to find reco-truth matching... " << std::endl;
1099  return;
1100  }
1101 
1102  // Now loop over the hits and build a collection of IDEs
1103  for (HitVector::const_iterator iter = hitVector.begin(), iterEnd = hitVector.end();
1104  iter != iterEnd;
1105  ++iter) {
1106  const art::Ptr<recob::Hit> hit = *iter;
1107 
1108  particleVector.clear();
1109  backtrackerVector.clear();
1110  particles_per_hit.get(hit.key(), particleVector, backtrackerVector);
1111 
1112  for (unsigned int j = 0; j < particleVector.size(); ++j) {
1113  const art::Ptr<simb::MCParticle> particle = particleVector[j];
1114 
1115  sim::TrackIDE trackIDE;
1116  trackIDE.trackID = particle->TrackId();
1117  trackIDE.energy = backtrackerVector[j]->energy;
1118  trackIDE.energyFrac = backtrackerVector[j]->ideFraction;
1119 
1120  hitsToTrackIDEs[hit].push_back(trackIDE);
1121  }
1122  }
1123  }
1124 
1125  //------------------------------------------------------------------------------------------------------------------------------------------
1126 
1127  void
1129  const std::string& truthLabel,
1130  const std::string& hitLabel,
1131  const std::string& backtrackLabel,
1132  MCParticlesToHits& particlesToHits,
1133  HitsToMCParticles& hitsToParticles,
1134  const DaughterMode daughterMode)
1135  {
1136  MCTruthToMCParticles truthToParticles;
1137  MCParticlesToMCTruth particlesToTruth;
1138  HitsToTrackIDEs hitsToTrackIDEs;
1139 
1140  LArPandoraHelper::CollectMCParticles(evt, truthLabel, truthToParticles, particlesToTruth);
1141  LArPandoraHelper::BuildMCParticleHitMaps(evt, hitLabel, backtrackLabel, hitsToTrackIDEs);
1143  hitsToTrackIDEs, truthToParticles, particlesToHits, hitsToParticles, daughterMode);
1144  }
1145 
1146  //------------------------------------------------------------------------------------------------------------------------------------------
1147 
1148  template <typename T>
1149  void
1151  const std::string& label,
1152  const std::vector<art::Ptr<T>>& inputVector,
1153  HitVector& associatedHits,
1154  const pandora::IntVector* const indexVector)
1155  {
1156 
1157  art::Handle<std::vector<T>> handle;
1158  evt.getByLabel(label, handle);
1159  art::FindManyP<recob::Hit> hitAssoc(handle, evt, label);
1160 
1161  if (indexVector != nullptr) {
1162  if (inputVector.size() != indexVector->size())
1163  throw cet::exception("LArPandora") << " PandoraHelper::GetAssociatedHits --- trying to use "
1164  "an index vector not matching input vector";
1165 
1166  // If indexVector is filled, sort hits according to trajectory points order
1167  for (int index : (*indexVector)) {
1168  const art::Ptr<T>& element = inputVector.at(index);
1169  const HitVector& hits = hitAssoc.at(element.key());
1170  associatedHits.insert(associatedHits.end(), hits.begin(), hits.end());
1171  }
1172  }
1173  else {
1174  // If indexVector is empty just loop through inputSpacePoints
1175  for (const art::Ptr<T>& element : inputVector) {
1176  const HitVector& hits = hitAssoc.at(element.key());
1177  associatedHits.insert(associatedHits.end(), hits.begin(), hits.end());
1178  }
1179  }
1180  }
1181 
1182  //------------------------------------------------------------------------------------------------------------------------------------------
1183 
1184  void
1186  MCParticleMap& particleMap)
1187  {
1188  for (MCParticleVector::const_iterator iter = particleVector.begin(),
1189  iterEnd = particleVector.end();
1190  iter != iterEnd;
1191  ++iter) {
1192  const art::Ptr<simb::MCParticle> particle = *iter;
1193  particleMap[particle->TrackId()] = particle;
1194  particleMap[particle->TrackId()] = particle;
1195  }
1196  }
1197 
1198  //------------------------------------------------------------------------------------------------------------------------------------------
1199 
1200  void
1202  PFParticleMap& particleMap)
1203  {
1204  for (PFParticleVector::const_iterator iter = particleVector.begin(),
1205  iterEnd = particleVector.end();
1206  iter != iterEnd;
1207  ++iter) {
1208  const art::Ptr<recob::PFParticle> particle = *iter;
1209  particleMap[particle->Self()] = particle;
1210  }
1211  }
1212 
1213  //------------------------------------------------------------------------------------------------------------------------------------------
1214 
1215  art::Ptr<recob::PFParticle>
1217  const art::Ptr<recob::PFParticle> inputParticle)
1218  {
1219  // Navigate upward through PFO daughter/parent links - return the top-level PF Particle
1220  int primaryTrackID(inputParticle->Self());
1221 
1222  if (!inputParticle->IsPrimary()) {
1223  while (1) {
1224  PFParticleMap::const_iterator pIter1 = particleMap.find(primaryTrackID);
1225  if (particleMap.end() == pIter1)
1226  throw cet::exception("LArPandora") << " PandoraCollector::GetParentPFParticle --- Found "
1227  "a PFParticle without a particle ID ";
1228 
1229  const art::Ptr<recob::PFParticle> primaryParticle = pIter1->second;
1230  if (primaryParticle->IsPrimary()) break;
1231 
1232  primaryTrackID = primaryParticle->Parent();
1233  }
1234  }
1235 
1236  PFParticleMap::const_iterator pIter2 = particleMap.find(primaryTrackID);
1237  if (particleMap.end() == pIter2)
1238  throw cet::exception("LArPandora")
1239  << " PandoraCollector::GetParentPFParticle --- Found a PFParticle without a particle ID ";
1240 
1241  const art::Ptr<recob::PFParticle> outputParticle = pIter2->second;
1242  return outputParticle;
1243  }
1244 
1245  //------------------------------------------------------------------------------------------------------------------------------------------
1246 
1247  art::Ptr<recob::PFParticle>
1249  const art::Ptr<recob::PFParticle> inputParticle)
1250  {
1251  // Navigate upward through PFO daughter/parent links - return the top-level non-neutrino PF Particle
1252  int primaryTrackID(inputParticle->Self());
1253 
1254  if (!inputParticle->IsPrimary()) {
1255  int parentTrackID(inputParticle->Parent());
1256 
1257  while (1) {
1258  PFParticleMap::const_iterator pIter1 = particleMap.find(parentTrackID);
1259  if (particleMap.end() == pIter1)
1260  throw cet::exception("LArPandora") << " PandoraCollector::GetFinalStatePFParticle --- "
1261  "Found a PFParticle without a particle ID ";
1262 
1263  const art::Ptr<recob::PFParticle> parentParticle = pIter1->second;
1264  if (LArPandoraHelper::IsNeutrino(parentParticle)) break;
1265 
1266  primaryTrackID = parentTrackID;
1267 
1268  if (parentParticle->IsPrimary()) break;
1269 
1270  parentTrackID = parentParticle->Parent();
1271  }
1272  }
1273 
1274  PFParticleMap::const_iterator pIter2 = particleMap.find(primaryTrackID);
1275  if (particleMap.end() == pIter2)
1276  throw cet::exception("LArPandora") << " PandoraCollector::GetFinalStatePFParticle --- Found "
1277  "a PFParticle without a particle ID ";
1278 
1279  const art::Ptr<recob::PFParticle> outputParticle = pIter2->second;
1280  return outputParticle;
1281  }
1282 
1283  //------------------------------------------------------------------------------------------------------------------------------------------
1284 
1285  art::Ptr<simb::MCParticle>
1287  const art::Ptr<simb::MCParticle> inputParticle)
1288  {
1289  // Navigate upward through MC daughter/parent links - return the top-level MC particle
1290  int primaryTrackID(inputParticle->TrackId());
1291  int parentTrackID(inputParticle->Mother());
1292 
1293  while (1) {
1294  MCParticleMap::const_iterator pIter1 = particleMap.find(parentTrackID);
1295  if (particleMap.end() == pIter1) break; // Can't find MC Particle for this track ID [break]
1296 
1297  const art::Ptr<simb::MCParticle> particle = pIter1->second;
1298 
1299  primaryTrackID = parentTrackID;
1300  parentTrackID = particle->Mother();
1301  }
1302 
1303  MCParticleMap::const_iterator pIter2 = particleMap.find(primaryTrackID);
1304  if (particleMap.end() == pIter2)
1305  throw cet::exception("LArPandora")
1306  << " PandoraCollector::GetParentMCParticle --- Found a track ID without a MC particle ";
1307 
1308  const art::Ptr<simb::MCParticle> outputParticle = pIter2->second;
1309  return outputParticle;
1310  }
1311 
1312  //------------------------------------------------------------------------------------------------------------------------------------------
1313 
1314  art::Ptr<simb::MCParticle>
1316  const art::Ptr<simb::MCParticle> inputParticle)
1317  {
1318  // Navigate upward through MC daughter/parent links - collect this particle and all its parents
1319  MCParticleVector mcVector;
1320 
1321  int trackID(inputParticle->TrackId());
1322 
1323  while (1) {
1324  MCParticleMap::const_iterator pIter = particleMap.find(trackID);
1325  if (particleMap.end() == pIter) break; // Can't find MC Particle for this track ID [break]
1326 
1327  const art::Ptr<simb::MCParticle> particle = pIter->second;
1328  mcVector.push_back(particle);
1329 
1330  trackID = particle->Mother();
1331  }
1332 
1333  // Navigate downward through MC parent/daughter links - return the first long-lived charged particle
1334  for (MCParticleVector::const_reverse_iterator iter = mcVector.rbegin(),
1335  iterEnd = mcVector.rend();
1336  iter != iterEnd;
1337  ++iter) {
1338  const art::Ptr<simb::MCParticle> nextParticle = *iter;
1339 
1340  if (LArPandoraHelper::IsVisible(nextParticle)) return nextParticle;
1341  }
1342 
1343  throw cet::exception("LArPandora"); // need to catch this exception
1344  }
1345 
1346  //------------------------------------------------------------------------------------------------------------------------------------------
1347 
1348  art::Ptr<recob::Track>
1350  const art::Ptr<recob::PFParticle> particle)
1351  {
1352  PFParticlesToTracks::const_iterator tIter = particlesToTracks.find(particle);
1353 
1354  if (particlesToTracks.end() == tIter || tIter->second.empty())
1355  throw cet::exception("LArPandora")
1356  << " PandoraCollector::GetPrimaryTrack --- Failed to find associated track ";
1357 
1358  if (tIter->second.size() != 1)
1359  throw cet::exception("LArPandora")
1360  << " PandoraCollector::GetPrimaryTrack --- Found more than one associated track ";
1361 
1362  const art::Ptr<recob::Track> primaryTrack = *(tIter->second.begin());
1363  return primaryTrack;
1364  }
1365 
1366  //------------------------------------------------------------------------------------------------------------------------------------------
1367 
1368  int
1370  const art::Ptr<recob::PFParticle> inputParticle)
1371  {
1372  // Navigate upward through PFO daughter/parent links - return the top-level PF Particle
1373  int nGenerations(0);
1374  int primaryTrackID(inputParticle->Self());
1375 
1376  while (1) {
1377  PFParticleMap::const_iterator pIter = particleMap.find(primaryTrackID);
1378  if (particleMap.end() == pIter)
1379  throw cet::exception("LArPandora")
1380  << " PandoraCollector::GetGeneration --- Found a PFParticle without a particle ID ";
1381 
1382  ++nGenerations;
1383 
1384  const art::Ptr<recob::PFParticle> primaryParticle = pIter->second;
1385  if (primaryParticle->IsPrimary()) break;
1386 
1387  primaryTrackID = primaryParticle->Parent();
1388  }
1389 
1390  return nGenerations;
1391  }
1392 
1393  //------------------------------------------------------------------------------------------------------------------------------------------
1394 
1395  int
1397  const art::Ptr<recob::PFParticle> daughterParticle)
1398  {
1399  art::Ptr<recob::PFParticle> parentParticle =
1400  LArPandoraHelper::GetParentPFParticle(particleMap, daughterParticle);
1401 
1402  if (LArPandoraHelper::IsNeutrino(parentParticle)) return parentParticle->PdgCode();
1403 
1404  if (parentParticle->IsPrimary()) return 0;
1405 
1406  const int parentID(parentParticle->Parent());
1407 
1408  PFParticleMap::const_iterator pIter = particleMap.find(parentID);
1409  if (particleMap.end() == pIter)
1410  throw cet::exception("LArPandora")
1411  << " PandoraCollector::GetParentNeutrino --- Found a PFParticle without a particle ID ";
1412 
1413  const art::Ptr<recob::PFParticle> neutrinoParticle = pIter->second;
1414  return neutrinoParticle->PdgCode();
1415  }
1416 
1417  //------------------------------------------------------------------------------------------------------------------------------------------
1418 
1419  bool
1421  const art::Ptr<recob::PFParticle> daughterParticle)
1422  {
1423  if (LArPandoraHelper::IsNeutrino(daughterParticle)) return false;
1424 
1425  if (daughterParticle->IsPrimary()) return true;
1426 
1427  const int parentID(daughterParticle->Parent());
1428 
1429  PFParticleMap::const_iterator pIter = particleMap.find(parentID);
1430  if (particleMap.end() == pIter)
1431  throw cet::exception("LArPandora")
1432  << " PandoraCollector::IsFinalState --- Found a PFParticle without a particle ID ";
1433 
1434  const art::Ptr<recob::PFParticle> parentParticle = pIter->second;
1435 
1436  if (LArPandoraHelper::IsNeutrino(parentParticle)) return true;
1437 
1438  return false;
1439  }
1440 
1441  //------------------------------------------------------------------------------------------------------------------------------------------
1442 
1443  bool
1444  LArPandoraHelper::IsNeutrino(const art::Ptr<recob::PFParticle> particle)
1445  {
1446  const int pdg(particle->PdgCode());
1447 
1448  // electron, muon, tau (use Pandora PDG tables)
1449  return ((pandora::NU_E == std::abs(pdg)) || (pandora::NU_MU == std::abs(pdg)) ||
1450  (pandora::NU_TAU == std::abs(pdg)));
1451  }
1452 
1453  //------------------------------------------------------------------------------------------------------------------------------------------
1454 
1455  bool
1456  LArPandoraHelper::IsTrack(const art::Ptr<recob::PFParticle> particle)
1457  {
1458  const int pdg(particle->PdgCode());
1459 
1460  // muon, pion, proton, kaon (use Pandora PDG tables)
1461  return ((pandora::MU_MINUS == std::abs(pdg)) || (pandora::PI_PLUS == std::abs(pdg)) ||
1462  (pandora::PROTON == std::abs(pdg)) || (pandora::K_PLUS == std::abs(pdg)));
1463  }
1464 
1465  //------------------------------------------------------------------------------------------------------------------------------------------
1466 
1467  bool
1468  LArPandoraHelper::IsShower(const art::Ptr<recob::PFParticle> particle)
1469  {
1470  const int pdg(particle->PdgCode());
1471 
1472  // electron, photon (use Pandora PDG tables)
1473  return ((pandora::E_MINUS == std::abs(pdg)) || (pandora::PHOTON == std::abs(pdg)));
1474  }
1475 
1476  //------------------------------------------------------------------------------------------------------------------------------------------
1477 
1478  bool
1479  LArPandoraHelper::IsVisible(const art::Ptr<simb::MCParticle> particle)
1480  {
1481  // Include long-lived charged particles
1482  const int pdg(particle->PdgCode());
1483 
1484  if ((pandora::E_MINUS == std::abs(pdg)) || (pandora::MU_MINUS == std::abs(pdg)) ||
1485  (pandora::PROTON == std::abs(pdg)) || (pandora::PI_PLUS == std::abs(pdg)) ||
1486  (pandora::K_PLUS == std::abs(pdg)) || (pandora::SIGMA_MINUS == std::abs(pdg)) ||
1487  (pandora::SIGMA_PLUS == std::abs(pdg)) || (pandora::HYPERON_MINUS == std::abs(pdg)) ||
1488  (pandora::PHOTON == std::abs(pdg)) || (pandora::NEUTRON == std::abs(pdg)))
1489  return true;
1490 
1491  // TODO: What about ions, neutrons, photons? (Have included neutrons and photons for now)
1492 
1493  return false;
1494  }
1495 
1496  //------------------------------------------------------------------------------------------------------------------------------------------
1497 
1499  LArPandoraHelper::GetPFParticleMetadata(const pandora::ParticleFlowObject* const pPfo)
1500  {
1501  return larpandoraobj::PFParticleMetadata(pPfo->GetPropertiesMap());
1502  }
1503 
1504  //------------------------------------------------------------------------------------------------------------------------------------------
1505  //------------------------------------------------------------------------------------------------------------------------------------------
1506 
1507  template void LArPandoraHelper::GetAssociatedHits(const art::Event&,
1508  const std::string&,
1509  const std::vector<art::Ptr<recob::Cluster>>&,
1510  HitVector&,
1511  const pandora::IntVector* const);
1512 
1513  template void LArPandoraHelper::GetAssociatedHits(const art::Event&,
1514  const std::string&,
1515  const std::vector<art::Ptr<recob::SpacePoint>>&,
1516  HitVector&,
1517  const pandora::IntVector* const);
1518 
1519 } // namespace lar_pandora
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.
process_name vertex
Definition: cheaterreco.fcl:51
static void CollectClusters(const art::Event &evt, const std::string &label, ClusterVector &clusterVector, ClustersToHits &clustersToHits)
Collect the reconstructed Clusters and associated hits from the ART event record. ...
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCParticle > > HitsToMCParticles
static void BuildPFParticleMap(const PFParticleVector &particleVector, PFParticleMap &particleMap)
Build particle maps for reconstructed particles.
std::map< int, art::Ptr< sim::SimChannel > > SimChannelMap
var pdg
Definition: selectors.fcl:14
static int GetParentNeutrino(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the parent neutrino PDG code (or zero for cosmics) for a given reconstructed particle...
process_name cluster
Definition: cheaterreco.fcl:51
std::map< art::Ptr< recob::PFParticle >, ClusterVector > PFParticlesToClusters
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
Declaration of signal hit object.
std::map< art::Ptr< simb::MCParticle >, art::Ptr< simb::MCTruth > > MCParticlesToMCTruth
static art::Ptr< recob::PFParticle > GetFinalStatePFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the final-state parent particle by navigating up the chain of parent/daughter associations...
static void CollectWires(const art::Event &evt, const std::string &label, WireVector &wireVector)
Collect the reconstructed wires from the ART event record.
static bool IsShower(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as shower-like.
std::vector< art::Ptr< recob::Shower > > ShowerVector
process_name use argoneut_mc_hitfinder track
std::vector< int > IntVector
process_name hit
Definition: cheaterreco.fcl:51
std::vector< art::Ptr< anab::CosmicTag > > CosmicTagVector
float energy
energy from the particle with this trackID [MeV]
Definition: SimChannel.h:29
process_name shower
Definition: cheaterreco.fcl:51
static art::Ptr< recob::PFParticle > GetParentPFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
std::map< art::Ptr< recob::PFParticle >, TrackVector > PFParticlesToTracks
static void CollectGeneratorMCParticles(const art::Event &evt, const std::string &label, RawMCParticleVector &particleVector)
Collect a vector of MCParticle objects from the generator in the ART event record. ATTN: This function is needed as accessing generator (opposed to Geant4) level MCParticles requires use of MCTruth block.
std::map< art::Ptr< recob::PFParticle >, VertexVector > PFParticlesToVertices
std::map< int, art::Ptr< recob::PFParticle > > PFParticleMap
std::map< art::Ptr< recob::Track >, CosmicTagVector > TracksToCosmicTags
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
std::map< int, art::Ptr< simb::MCParticle > > MCParticleMap
std::map< art::Ptr< recob::Hit >, TrackIDEVector > HitsToTrackIDEs
static void GetAssociatedHits(const art::Event &evt, const std::string &label, const std::vector< art::Ptr< T >> &inputVector, HitVector &associatedHits, const pandora::IntVector *const indexVector=nullptr)
Get all hits associated with input clusters.
static void CollectSpacePoints(const art::Event &evt, const std::string &label, SpacePointVector &spacePointVector, SpacePointsToHits &spacePointsToHits)
Collect the reconstructed SpacePoints and associated hits from the ART event record.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< art::Ptr< recob::Seed > > SeedVector
static void CollectSeeds(const art::Event &evt, const std::string &label, SeedVector &seedVector, PFParticlesToSeeds &particlesToSeeds)
Collect the reconstructed PFParticles and associated Seeds from the ART event record.
T abs(T value)
static bool IsVisible(const art::Ptr< simb::MCParticle > particle)
Determine whether a particle is visible (i.e. long-lived charged particle)
std::map< art::Ptr< recob::PFParticle >, MetadataVector > PFParticlesToMetadata
std::map< art::Ptr< recob::PFParticle >, T0Vector > PFParticlesToT0s
std::map< art::Ptr< recob::PFParticle >, ShowerVector > PFParticlesToShowers
std::vector< simb::MCParticle > RawMCParticleVector
static art::Ptr< simb::MCParticle > GetParentMCParticle(const MCParticleMap &particleMap, const art::Ptr< simb::MCParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
Metadata associated to PFParticles.
std::map< art::Ptr< simb::MCParticle >, HitVector > MCParticlesToHits
std::map< art::Ptr< recob::PFParticle >, SeedVector > PFParticlesToSeeds
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::map< art::Ptr< recob::Cluster >, HitVector > ClustersToHits
std::map< art::Ptr< recob::Shower >, HitVector > ShowersToHits
std::map< art::Ptr< simb::MCTruth >, MCParticleVector > MCTruthToMCParticles
static void CollectShowers(const art::Event &evt, const std::string &label, ShowerVector &showerVector, PFParticlesToShowers &particlesToShowers)
Collect the reconstructed PFParticles and associated Showers from the ART event record.
std::vector< art::Ptr< recob::SpacePoint > > SpacePointVector
static art::Ptr< recob::Track > GetPrimaryTrack(const PFParticlesToTracks &particlesToTracks, const art::Ptr< recob::PFParticle > particle)
Return the primary track associated with a PFParticle.
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
static void CollectVertices(const art::Event &evt, const std::string &label, VertexVector &vertexVector, PFParticlesToVertices &particlesToVertices)
Collect the reconstructed PFParticles and associated Vertices from the ART event record.
float energyFrac
fraction of hit energy from the particle with this trackID
Definition: SimChannel.h:28
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::SpacePoint > > HitsToSpacePoints
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
unsigned int seed
std::vector< sim::TrackIDE > TrackIDEVector
static void CollectSimChannels(const art::Event &evt, const std::string &label, SimChannelVector &simChannelVector, bool &areSimChannelsValid)
Collect a vector of SimChannel objects from the ART event record.
static void SelectFinalStatePFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select final-state reconstructed particles from a list of all reconstructed particles.
std::vector< art::Ptr< recob::Track > > TrackVector
static void CollectPFParticleMetadata(const art::Event &evt, const std::string &label, PFParticleVector &particleVector, PFParticlesToMetadata &particlesToMetadata)
Collect the reconstructed PFParticle Metadata from the ART event record.
std::map< art::Ptr< recob::PFParticle >, SpacePointVector > PFParticlesToSpacePoints
Declaration of cluster object.
std::map< art::Ptr< recob::Track >, HitVector > TracksToHits
static void CollectTracks(const art::Event &evt, const std::string &label, TrackVector &trackVector, PFParticlesToTracks &particlesToTracks)
Collect the reconstructed PFParticles and associated Tracks from the ART event record.
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
Provides recob::Track data product.
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits from the ART event record.
DaughterMode
DaughterMode enumeration.
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
int trackID
Geant4 supplied trackID.
Definition: SimChannel.h:27
std::vector< art::Ptr< sim::SimChannel > > SimChannelVector
std::vector< art::Ptr< recob::Wire > > WireVector
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::PFParticle > > HitsToPFParticles
static bool IsTrack(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as track-like.
do i e
std::vector< art::Ptr< recob::Vertex > > VertexVector
Declaration of basic channel signal object.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
static int GetGeneration(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the generation of this particle (first generation if primary)
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< art::Ptr< anab::T0 > > T0Vector
static void CollectT0s(const art::Event &evt, const std::string &label, T0Vector &t0Vector, PFParticlesToT0s &particlesToT0s)
Collect a vector of T0s from the ART event record.
std::map< art::Ptr< recob::Seed >, art::Ptr< recob::Hit > > SeedsToHits
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
Ionization energy from a Geant4 track.
Definition: SimChannel.h:26
static art::Ptr< simb::MCParticle > GetFinalStateMCParticle(const MCParticleMap &particleMap, const art::Ptr< simb::MCParticle > daughterParticle)
Return the final-state parent particle by navigating up the chain of parent/daughter associations...
art framework interface to geometry description
static bool IsFinalState(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Determine whether a particle has been reconstructed as a final-state particle.
std::map< art::Ptr< recob::SpacePoint >, art::Ptr< recob::Hit > > SpacePointsToHits
static larpandoraobj::PFParticleMetadata GetPFParticleMetadata(const pandora::ParticleFlowObject *const pPfo)
Get metadata associated to a PFO.
static void CollectCosmicTags(const art::Event &evt, const std::string &label, CosmicTagVector &cosmicTagVector, TracksToCosmicTags &tracksToCosmicTags)
Collect a vector of cosmic tags from the ART event record.
static void BuildMCParticleMap(const MCParticleVector &particleVector, MCParticleMap &particleMap)
Build particle maps for true particles.