LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ParticleInventory.tcc
Go to the documentation of this file.
1 #include "canvas/Persistency/Common/Assns.h"
2 #include "canvas/Persistency/Common/Ptr.h"
3 
4 #include "lardataobj/Simulation/GeneratedParticleInfo.h"
5 #include "nug4/ParticleNavigation/EmEveIdCalculator.h"
6 #include "nug4/ParticleNavigation/EveIdCalculator.h"
7 
8 namespace cheat {
9 
10  //--------------------------------------------------------------------
11  template <
12  typename Evt> //DO NOT USE THIS FUNCTION FROM WITHIN ART! The ParticleInventoryService is designed to impliment these methods as cleanly as possible within the art framework.
13  void ParticleInventory::PrepEvent(const Evt& evt)
14  {
15  if (!(this->CanRun(evt))) {
16  throw cet::exception("ParticleInventory") << "Particle Inventory cannot function. "
17  << "Is this file real data?";
18  }
19  fParticleList.clear();
20  fMCTObj.fMCTruthList.clear();
21  fMCTObj.fTrackIdToMCTruthIndex.clear();
22  this->PrepParticleList(evt);
23  this->PrepMCTruthList(evt);
24  this->PrepTrackIdToMCTruthIndex(evt);
25  }
26 
27  //--------------------------------------------------------------------
28  template <typename Evt>
29  void ParticleInventory::PrepParticleList(const Evt& evt) const
30  {
31 
32  if (this->ParticleListReady()) { //The particle list already exists. Do nothing.
33  return;
34  }
35  //The particle list needs to be built
36  //We use auto so that we(the compiler) can determine which type we need for either art or gallery.
37  const auto& pHandle =
38  evt.template getValidHandle<std::vector<simb::MCParticle>>(fG4ModuleLabel);
39  // const auto& partVecIn = evt.template getValidHandle<std::vector<simb::MCParticle>>(fG4ModuleLabel);
40  // if(pHandle.failedToGet()){
41  // /*mf::LogWarning("BackTracker") << "failed to get handle to simb::MCParticle from "
42  // << fG4ModuleLabel
43  // << ", return";*/ //Do this silently so we don't polute the logs. It is expected to fail for all gen and g4 jobs.
44  // return;
45  // }
46 
47  const auto& partVecIn = *pHandle;
48  for (const auto& partIn : partVecIn) {
49  fParticleList.Add(new simb::MCParticle(
50  partIn)); //Is this still doing a copy? If so, another method should be used.
51  }
52  if (fEveIdCalculator == "EmEveIdCalculator") {
53  fParticleList.AdoptEveIdCalculator(new sim::EmEveIdCalculator);
54  }
55  else if (fEveIdCalculator == "EveIdCalculator") {
56  fParticleList.AdoptEveIdCalculator(new sim::EveIdCalculator);
57  }
58  else {
59  throw cet::exception("ParticleInventory3")
60  << "Particle Inventory cannot initialize the particle list.\n " << fEveIdCalculator
61  << " is not a known EveIdCalculator.\n";
62  }
63  }
64 
65  //--------------------------------------------------------------------
66  template <typename Evt> //I may want to make this function private.
67  void ParticleInventory::PrepMCTruthListAndTrackIdToMCTruthIndex(const Evt& evt) const
68  {
69  if (this->TrackIdToMCTruthReady() && this->MCTruthListReady()) { return; }
70  this->PrepParticleList(evt); //Make sure we have built the particle list for this event
71 
72  // relaxed Assns lookup
73  typename Evt::template HandleT<art::Assns<simb::MCParticle, simb::MCTruth>> mcpmctAssnsHandle;
74  if (evt.getByLabel(fG4ModuleLabel, mcpmctAssnsHandle)) { // Product fetch successful
75  for (const auto& mcpmctAssnIn :
76  *mcpmctAssnsHandle) { //Assns are themselves a container. Loop over entries.
77  const art::Ptr<simb::MCParticle>& part = mcpmctAssnIn.first;
78  const art::Ptr<simb::MCTruth>& mct = mcpmctAssnIn.second;
79  unsigned short mctruth_idx = USHRT_MAX;
80  for (size_t i = 0; i < fMCTObj.fMCTruthList.size(); ++i) {
81  if (fMCTObj.fMCTruthList[i] == mct) {
82  mctruth_idx = i;
83  break;
84  }
85  }
86  if (mctruth_idx == USHRT_MAX) {
87  fMCTObj.fMCTruthList.push_back(mct);
88  fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), fMCTObj.fMCTruthList.size() - 1);
89  }
90  else {
91  fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), mctruth_idx);
92  }
93  }
94  }
95  else {
96 
97  // with more strict Assns lookup requiring the GeneratedParticleInfo
98  typename Evt::template HandleT<
99  art::Assns<simb::MCParticle, simb::MCTruth, sim::GeneratedParticleInfo>>
100  mcpmctAssnsHandle;
101  if (evt.getByLabel(fG4ModuleLabel, mcpmctAssnsHandle)) { // Product fetch successful
102  for (const auto& mcpmctAssnIn :
103  *mcpmctAssnsHandle) { //Assns are themselves a container. Loop over entries.
104  const art::Ptr<simb::MCParticle>& part = mcpmctAssnIn.first;
105  const art::Ptr<simb::MCTruth>& mct = mcpmctAssnIn.second;
106  unsigned short mctruth_idx = USHRT_MAX;
107  for (size_t i = 0; i < fMCTObj.fMCTruthList.size(); ++i) {
108  if (fMCTObj.fMCTruthList[i] == mct) {
109  mctruth_idx = i;
110  break;
111  }
112  }
113  if (mctruth_idx == USHRT_MAX) {
114  fMCTObj.fMCTruthList.push_back(mct);
115  fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(),
116  fMCTObj.fMCTruthList.size() - 1);
117  }
118  else {
119  fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), mctruth_idx);
120  }
121  }
122  }
123  else {
124  throw cet::exception("PrepMCTruthListAndTrackIdToMCTruthIndex")
125  << "Could not get valid MCTruth, MCParticle Assciations!";
126  }
127  }
128  }
129 
130  //--------------------------------------------------------------------
131  template <typename Evt>
132  void ParticleInventory::PrepMCTruthList(const Evt& evt) const
133  {
134  if (this->MCTruthListReady()) {
135  return;
136  } //If the event is data or if the truth list is already built there is nothing for us to do.
137  PrepMCTruthListAndTrackIdToMCTruthIndex(
138  evt); //TrackIdToMCTruthIndex and MCTruthList are prepared at the same time. The access of information makes this the most convenient way to do so. It is only somewhat more expensive for the memory, but significantly less expensive for time.
139  }
140 
141  //--------------------------------------------------------------------
142  template <typename Evt>
143  void ParticleInventory::PrepTrackIdToMCTruthIndex(const Evt& evt) const
144  {
145  if (this->TrackIdToMCTruthReady()) { return; } //The list already exists. Do nothing.
146  PrepMCTruthListAndTrackIdToMCTruthIndex(
147  evt); //TrackIdToMCTruthIndex and MCTruthList are prepared at the same time. The access of information makes this the most convenient way to do so. It is only somewhat more expensive for the memory, but significantly less expensive for time.
148  }
149 
150  template <typename Evt>
151  bool ParticleInventory::CanRun(const Evt& evt) const
152  {
153  if (fOverrideRealData) { return true; }
154  return !(evt.isRealData());
155  }
156 
157 } //end namespace