Geant4Output2Podio.cxx
Go to the documentation of this file.
1 #include "Geant4Output2Podio.h"
2 #include "DD4hep/InstanceCount.h"
3 #include "DD4hep/Primitives.h"
4 #include "DD4hep/Printout.h"
5 #include "DDG4/Geant4Data.h"
6 #include "DDG4/Geant4HitCollection.h"
7 #include "DDG4/Geant4Particle.h"
8 #include "DD4hep/DD4hepUnits.h"
9 
10 #include "TBuffer.h"
11 
12 #include "CLHEP/Units/SystemOfUnits.h"
13 #include "G4ParticleDefinition.hh"
14 
15 #include "dd4pod/ThreeVector.h"
19 
21 #include "PMTHit.h"
22 
23 // Geant4 include files
24 #include "G4HCofThisEvent.hh"
25 using std::string;
26 
27 namespace dd4hep::sim {
28 
30  Geant4Output2Podio::Geant4Output2Podio(Geant4Context* ctxt, const string& nam)
31  : Geant4OutputAction(ctxt, nam) {
32  declareProperty("HandleMCTruth", m_handleMCTruth = true);
33  declareProperty("DisabledCollections", m_disabledCollections);
34  declareProperty("EnabledCollections", m_enabledCollections);
35  declareProperty("DisableParticles", m_disableParticles);
37  }
38 
41  std::cout << "deleting ouput2podio\n";
42  if (writer) {
43  writer->finish();
44  delete writer;
45  }
46  writer = nullptr;
48  // if (m_file) {
49  // TDirectory::TContext ctxt(m_file);
50  // m_tree->Write();
51  // m_file->Close();
52  // m_tree = 0;
53  // detail::deletePtr (m_file);
54  //}
55  }
56 
58  void Geant4Output2Podio::beginRun(const G4Run* run) {
59  std::cout << " Begin of run action \n";
60  if (!writer)
61  writer = new podio::ROOTWriter(m_output, &store);
62  Geant4OutputAction::beginRun(run);
63  }
65  void Geant4Output2Podio::endRun(const G4Run* run) {
66  std::cout << " end of run\n";
67  store.clearCollections();
68  //if (writer)
69  // writer->finish();
70  Geant4OutputAction::endRun(run);
71  }
72 
74  // int Geant4Output2Podio::fill(const string& nam, const ComponentCast& type,
75  // void* ptr) {
76  // if (m_file) {
77  // TBranch* b = 0;
78  // Branches::const_iterator i = m_branches.find(nam);
79  // if (i == m_branches.end()) {
80  // // create new branch if type exists
81  // TClass* cl = TBuffer::GetClass(type.type);
82  // if (cl) {
83  // b = m_tree->Branch(nam.c_str(), cl->GetName(), (void*) 0);
84  // b->SetAutoDelete(false);
85  // m_branches.emplace(nam, b);
86  // }
87  // else {
88  // throw runtime_error("No ROOT TClass object availible for object
89  // type:"
90  // + typeName(type.type));
91  // }
92  // }
93  // else {
94  // b = (*i).second;
95  // }
96  // Long64_t evt = b->GetEntries(), nevt = b->GetTree()->GetEntries(), num =
97  // nevt - evt; if (nevt > evt) {
98  // b->SetAddress(0);
99  // while (num > 0) {
100  // b->Fill();
101  // --num;
102  // }
103  // }
104  // b->SetAddress(&ptr);
105  // int nbytes = b->Fill();
106  // if (nbytes < 0) {
107  // throw runtime_error("Failed to write ROOT collection:" + nam + "!");
108  // }
109  // return nbytes;
110  // }
111  // return 0;
112  //}
113 
114  void Geant4Output2Podio::saveRun(const G4Run* /* run */) {
115  }
116 
118  void Geant4Output2Podio::commit(OutputContext<G4Event>& ctxt) {
119  if (writer) writer->writeEvent();
120  store.clearCollections();
121  }
122 
123 
125  void Geant4Output2Podio::saveEvent(OutputContext<G4Event>& /* ctxt */) {
126  if (!writer){
127  //std::cout << "creating writer in saveEVent\n";
128  writer = new podio::ROOTWriter(m_output, &store);
129  }
130  if (!m_disableParticles) {
131  Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>();
132  if (!(store.getCollectionIDTable()->present("mcparticles"))) {
133  //std::cout << " creating mcparticles\n";
134  auto& pcol = store.create<dd4pod::Geant4ParticleCollection>("mcparticles");
135  pcol.clear();
136  writer->registerForWrite("mcparticles");
137  }
138  podio::CollectionBase* podcol = nullptr;
139  if (store.get(store.getCollectionIDTable()->collectionID("mcparticles"), podcol)) {
140  auto podcol2 = dynamic_cast<dd4pod::Geant4ParticleCollection*>(podcol);
141  // copy all the hits
142  if (parts) {
143  using ParticleMap = Geant4ParticleMap::ParticleMap;
144  const ParticleMap& pm = parts->particles();
145  // loop over particle and copy them to podio data model
146  //std::cout << pm.size() << " particles\n";
147  for (const auto& i : pm) {
148  auto part = (dd4hep::sim::Geant4Particle*)(i.second);
149  dd4pod::Geant4Particle podpart(
150  (int)part->id, (int)part->g4Parent, (int)part->reason, (int)part->mask, (int)part->steps,
151  (int)part->secondaries, (int)part->pdgID, (int)part->status,
152  std::array<int, 2>{{part->colorFlow[0], part->colorFlow[1]}}, (int)part->genStatus, (int)part->charge,
153  std::array<int, 1>{{(int)part->_spare[0]}},
154  std::array<float, 3>{{(float)part->spin[0], (float)part->spin[1], (float)part->spin[2]}},
155  (double)part->vsx, (double)part->vsy, (double)part->vsz,
156  (double)part->vex, (double)part->vey, (double)part->vez,
157  (double)part->psx/1000.0, (double)part->psy/1000.0, (double)part->psz/1000.0,
158  (double)part->pex/1000.0, (double)part->pey/1000.0, (double)part->pez/1000.0,
159  (double)part->mass/1000.0, (double)part->time, (double)part->properTime);
160  for (const auto& ip : part->parents) {
161  podpart.addparents(ip);
162  }
163  for (const auto& ip : part->daughters) {
164  podpart.adddaughters(ip);
165  }
166  podcol2->push_back(podpart);
167  }
168  }
169  }
170  }
171  }
172 
174  void Geant4Output2Podio::saveCollection(OutputContext<G4Event>& /* ctxt */, G4VHitsCollection* collection) {
175  Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection);
176  std::string hc_name = collection->GetName();
177  for (const auto& n : m_disabledCollections) {
178  if (n == hc_name) {
179  return;
180  }
181  }
182  size_t nhits = coll->GetSize();
183  TClass* cl = TBuffer::GetClass(coll->vector_type().type);
184  auto cn = cl->GetName();
185  if (cl) {
186  // populate the collections
187  //std::cout << cl->GetName() << "\n";
188  // not ideal comparison
189  if (std::string("vector<dd4hep::sim::Geant4Calorimeter::Hit*>") == cn) {
190  if (!(store.getCollectionIDTable()->present(hc_name))) {
191  auto& pcol = store.create<dd4pod::CalorimeterHitCollection>(hc_name);
192  writer->registerForWrite(hc_name);
193  }
194  podio::CollectionBase* podcol = nullptr;
195  //std::cout << nhits << " cal hits\n";
196  if (store.get(store.getCollectionIDTable()->collectionID(hc_name),
197  podcol)) {
198  auto podcol2 =
199  dynamic_cast<dd4pod::CalorimeterHitCollection*>(podcol);
200  // copy all the hits
201  for (size_t i = 0; i < nhits; ++i) {
202  dd4hep::sim::Geant4HitData* h = coll->hit(i);
203 
204  auto cal_hit =
205  dynamic_cast<dd4hep::sim::Geant4Calorimeter::Hit*>(h);
206  //Geant4HitData::Contributions& c = cal_hit->truth;
207  //for (Geant4HitData::Contributions::iterator j = c.begin(); j != c.end(); ++j) {
208  // Geant4HitData::Contribution& t = *j;
209  // int trackID = t.trackID;
210  // t.trackID = m_truth->particleID(trackID);
211  //}
212  if (cal_hit) {
213  auto phit = podcol2->create();
214  phit.cellID(cal_hit->cellID);
215  phit.flag(cal_hit->flag);
216  phit.g4ID(cal_hit->g4ID);
217  phit.position({cal_hit->position.x(), cal_hit->position.y(),
218  cal_hit->position.z(), 0.0});
219  const auto& first_truth = cal_hit->truth[0];
220  phit.truth(dd4pod::MonteCarloContrib({
221  (int)first_truth.trackID,
222  (int)first_truth.pdgID,
223  (double)first_truth.deposit/1000.0,
224  (double)first_truth.time,
225  (double)first_truth.length,
226  (double)first_truth.x,
227  (double)first_truth.y,
228  (double)first_truth.z}));
229  //phit.truth({cal_hit->truth.trackID, cal_hit->truth.pdgID, cal_hit->truth.deposit, cal_hit->truth.time,
230  // cal_hit->truth.length, cal_hit->truth.x, cal_hit->truth.y, cal_hit->truth.z});
231  phit.energyDeposit(cal_hit->energyDeposit/1000.0);
232  }
233  }
234  }
235  } else if (std::string("vector<dd4hep::sim::Geant4Tracker::Hit*>") == cn) {
236  //std::cout << "track hit\n";
237  if (!(store.getCollectionIDTable()->present(hc_name))) {
238  auto& pcol = store.create<dd4pod::TrackerHitCollection>(hc_name);
239  writer->registerForWrite(hc_name);
240  }
241  podio::CollectionBase* podcol = nullptr;
242  //std::cout << nhits << " trk hits\n";
243  if (store.get(store.getCollectionIDTable()->collectionID(hc_name), podcol)) {
244  auto podcol2 =
245  dynamic_cast<dd4pod::TrackerHitCollection*>(podcol);
246  // copy all the hits
247  for (size_t i = 0; i < nhits; ++i) {
248  dd4hep::sim::Geant4HitData* h = coll->hit(i);
249  auto trk_hit = dynamic_cast<dd4hep::sim::Geant4Tracker::Hit*>(h);
250 
251  //Geant4HitData::Contribution& t = trk_hit->truth;
252  //int trackID = t.trackID;
253  //t.trackID = m_truth->particleID(trackID);
254  if (trk_hit) {
255  auto phit = podcol2->create();
256  phit.cellID(trk_hit->cellID);
257  phit.flag(trk_hit->flag);
258  phit.g4ID(trk_hit->g4ID);
259  phit.position({trk_hit->position.x(), trk_hit->position.y(),
260  trk_hit->position.z()});
261  phit.momentum({trk_hit->momentum.x()/1000.0, trk_hit->momentum.y()/1000.0,
262  trk_hit->momentum.z()/1000.0});
263  phit.length(trk_hit->length);
264  phit.truth(dd4pod::MonteCarloContrib({
265  (int)trk_hit->truth.trackID,
266  (int)trk_hit->truth.pdgID,
267  (double)trk_hit->truth.deposit/1000.0,
268  (double)trk_hit->truth.time,
269  (double)trk_hit->truth.length,
270  (double)trk_hit->truth.x,
271  (double)trk_hit->truth.y,
272  (double)trk_hit->truth.z}));
273  phit.energyDeposit(trk_hit->energyDeposit/1000.0);
274  }
275  }
276  }
277  } else if (std::string("vector<npdet::PMTHit*>") == cn) {
278  //std::cout << "track hit\n";
279  if (!(store.getCollectionIDTable()->present(hc_name))) {
280  auto& pcol = store.create<dd4pod::PhotoMultiplierHitCollection>(hc_name);
281  writer->registerForWrite(hc_name);
282  }
283  podio::CollectionBase* podcol = nullptr;
284  if (store.get(store.getCollectionIDTable()->collectionID(hc_name), podcol)) {
285  auto podcol2 =
286  dynamic_cast<dd4pod::PhotoMultiplierHitCollection*>(podcol);
287  // copy all the hits
288  for (size_t i = 0; i < nhits; ++i) {
289  //auto h = coll->hit(i);
290  dd4hep::sim::Geant4HitData* h = coll->hit(i);
291  auto trk_hit = dynamic_cast<npdet::PMTHit*>(h);
292  //Geant4HitData::Contribution& t = trk_hit->truth;
293  //int trackID = t.trackID;
294  //t.trackID = m_truth->particleID(trackID);
295  if (trk_hit) {
296  auto phit = podcol2->create();
297  phit.cellID(trk_hit->cellID);
298  phit.flag(trk_hit->flag);
299  phit.g4ID(trk_hit->g4ID);
300  phit.position({trk_hit->position.x(), trk_hit->position.y(),
301  trk_hit->position.z()});
302  phit.momentum({trk_hit->momentum.x()/1000.0, trk_hit->momentum.y()/1000.0,
303  trk_hit->momentum.z()/1000.0});
304  phit.length(trk_hit->length);
305  phit.truth({trk_hit->truth.trackID, trk_hit->truth.pdgID,
306  trk_hit->truth.deposit/1000.0,
307  trk_hit->truth.time, trk_hit->truth.length,
308  trk_hit->truth.x, trk_hit->truth.y,
309  trk_hit->truth.z});
310  phit.energy(trk_hit->energy/1000.0);
311  }
312  }
313  }
314  } else {
315  //std::cout << " unknown hit class name " << cn << "\n";
316  }
317  } else {
318  throw std::runtime_error("No ROOT TClass object availible for object type" );
319  }
320  //
321  // if (coll) {
322  // vector<void*> hits;
323  // coll->getHitsUnchecked(hits);
324  // size_t nhits = coll->GetSize();
325  // if (m_handleMCTruth && m_truth && nhits > 0) {
326  // hits.reserve(nhits);
327  // try {
328  // for (size_t i = 0; i < nhits; ++i) {
329  // auto h = coll->hit(i);
330  // auto trk_hit = dynamic_cast<dd4pod::TrackerHit*>(h);
331  // if (0 != trk_hit) {
332  // Geant4HitData::Contribution& t = trk_hit->truth;
333  // int trackID = t.trackID;
334  // t.trackID =
335  // m_truth->particleID(trackID);
336  // }
337  // auto cal_hit = dynamic_cast<dd4pod::CalorimeterHit*>(h);
338  // if (0 != cal_hit) {
339  // Geant4HitData::Contributions& c = cal_hit->truth;
340  // for (Geant4HitData::Contributions::iterator j = c.begin();
341  // j != c.end(); ++j) {
342  // Geant4HitData::Contribution& t = *j;
343  // int trackID = t.trackID;
344  // t.trackID = m_truth->particleID(trackID);
345  // }
346  // }
347  // }
348  // } catch (...) {
349  // printout(ERROR, name(), "+++ Exception while saving collection %s.",
350  // hc_nam.c_str());
351  // }
352  // }
353  // fill(hc_nam, coll->vector_type(), &hits);
354  // }
355  }
356 } // namespace dd4hep::sim
357 
358 using namespace dd4hep::sim;
359 
360 #include "DDG4/Factories.h"
361 
362 // clang-format off
363 DECLARE_GEANT4ACTION(Geant4Output2Podio)
Saves output to podio data model.
virtual void beginRun(const G4Run *run)
Callback to store the Geant4 run information.
A Collection is identified by an ID.
virtual void saveEvent(OutputContext< G4Event > &ctxt)
Callback to store the Geant4 event.
A Collection is identified by an ID.
virtual ~Geant4Output2Podio()
Default destructor.
detail::increment< T > increment(T &target)
makes function object that increments using operator ++
Definition: clipp.h:1119
bool m_handleMCTruth
Flag if Monte-Carlo truth should be followed and checked.
virtual void endRun(const G4Run *run)
Callback to store the Geant4 run information.
virtual void saveRun(const G4Run *run)
Callback to store the Geant4 run information.
Geant4Output2Podio(Geant4Context *context, const std::string &nam)
Standard constructor.
bool m_disableParticles
Property: vector with disabled collections.
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
PhotoMultiplier Hit definition.
Definition: PMTHit.h:38
std::vector< std::string > m_disabledCollections
Property: vector with disabled collections.
detail::decrement< T > decrement(T &target)
makes function object that increments by a fixed amount using operator +=
Definition: clipp.h:1141
A Collection is identified by an ID.
dd4hep::Position position
Hit position.
Definition: PMTHit.h:50
A Collection is identified by an ID.
std::vector< std::string > m_enabledCollections
Property: vector with disabled collections.
virtual void commit(OutputContext< G4Event > &ctxt)
Commit data at end of filling procedure.