1 #include "canvas/Persistency/Common/Assns.h"
2 #include "canvas/Persistency/Common/Ptr.h"
4 #include "lardataobj/Simulation/GeneratedParticleInfo.h"
5 #include "nug4/ParticleNavigation/EmEveIdCalculator.h"
6 #include "nug4/ParticleNavigation/EveIdCalculator.h"
10 //--------------------------------------------------------------------
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)
15 if (!(this->CanRun(evt))) {
16 throw cet::exception("ParticleInventory") << "Particle Inventory cannot function. "
17 << "Is this file real data?";
19 fParticleList.clear();
20 fMCTObj.fMCTruthList.clear();
21 fMCTObj.fTrackIdToMCTruthIndex.clear();
22 this->PrepParticleList(evt);
23 this->PrepMCTruthList(evt);
24 this->PrepTrackIdToMCTruthIndex(evt);
27 //--------------------------------------------------------------------
28 template <typename Evt>
29 void ParticleInventory::PrepParticleList(const Evt& evt) const
32 if (this->ParticleListReady()) { //The particle list already exists. Do nothing.
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.
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 "
43 // << ", return";*/ //Do this silently so we don't polute the logs. It is expected to fail for all gen and g4 jobs.
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.
52 if (fEveIdCalculator == "EmEveIdCalculator") {
53 fParticleList.AdoptEveIdCalculator(new sim::EmEveIdCalculator);
55 else if (fEveIdCalculator == "EveIdCalculator") {
56 fParticleList.AdoptEveIdCalculator(new sim::EveIdCalculator);
59 throw cet::exception("ParticleInventory3")
60 << "Particle Inventory cannot initialize the particle list.\n " << fEveIdCalculator
61 << " is not a known EveIdCalculator.\n";
65 //--------------------------------------------------------------------
66 template <typename Evt> //I may want to make this function private.
67 void ParticleInventory::PrepMCTruthListAndTrackIdToMCTruthIndex(const Evt& evt) const
69 if (this->TrackIdToMCTruthReady() && this->MCTruthListReady()) { return; }
70 this->PrepParticleList(evt); //Make sure we have built the particle list for this event
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) {
86 if (mctruth_idx == USHRT_MAX) {
87 fMCTObj.fMCTruthList.push_back(mct);
88 fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), fMCTObj.fMCTruthList.size() - 1);
91 fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), mctruth_idx);
97 // with more strict Assns lookup requiring the GeneratedParticleInfo
98 typename Evt::template HandleT<
99 art::Assns<simb::MCParticle, simb::MCTruth, sim::GeneratedParticleInfo>>
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) {
113 if (mctruth_idx == USHRT_MAX) {
114 fMCTObj.fMCTruthList.push_back(mct);
115 fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(),
116 fMCTObj.fMCTruthList.size() - 1);
119 fMCTObj.fTrackIdToMCTruthIndex.emplace(part->TrackId(), mctruth_idx);
124 throw cet::exception("PrepMCTruthListAndTrackIdToMCTruthIndex")
125 << "Could not get valid MCTruth, MCParticle Assciations!";
130 //--------------------------------------------------------------------
131 template <typename Evt>
132 void ParticleInventory::PrepMCTruthList(const Evt& evt) const
134 if (this->MCTruthListReady()) {
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.
141 //--------------------------------------------------------------------
142 template <typename Evt>
143 void ParticleInventory::PrepTrackIdToMCTruthIndex(const Evt& evt) const
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.
150 template <typename Evt>
151 bool ParticleInventory::CanRun(const Evt& evt) const
153 if (fOverrideRealData) { return true; }
154 return !(evt.isRealData());