13 #ifndef DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
14 #define DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
24 #include <edm4hep/MCParticleCollection.h>
25 #include <edm4hep/SimTrackerHitCollection.h>
26 #include <edm4hep/CaloHitContributionCollection.h>
27 #include <edm4hep/SimCalorimeterHitCollection.h>
28 #include <edm4hep/EDM4hepVersion.h>
29 #include <edm4hep/Constants.h>
30 #if EDM4HEP_BUILD_VERSION < EDM4HEP_VERSION(0, 99, 0)
31 using edm4hep::CellIDEncoding;
33 using edm4hep::labels::CellIDEncoding;
35 #include <podio/CollectionBase.h>
37 #include <podio/podioVersion.h>
38 #include <podio/Frame.h>
39 #include <podio/FrameCategories.h>
40 #if PODIO_BUILD_VERSION >= PODIO_VERSION(0, 99, 0)
41 #include <podio/ROOTWriter.h>
43 #include <podio/ROOTFrameWriter.h>
45 using ROOTWriter = podio::ROOTFrameWriter;
69 using trackermap_t = std::map< std::string, edm4hep::SimTrackerHitCollection >;
70 using calorimeterpair_t = std::pair< edm4hep::SimCalorimeterHitCollection, edm4hep::CaloHitContributionCollection >;
72 std::unique_ptr<writer_t>
m_file { };
99 virtual void beginRun(
const G4Run* run);
101 virtual void endRun(
const G4Run* run);
104 virtual void saveRun(
const G4Run* run);
106 virtual void saveEvent( OutputContext<G4Event>& ctxt);
110 virtual void commit( OutputContext<G4Event>& ctxt);
113 virtual void begin(
const G4Event* event);
116 template <
typename T>
118 for(
const auto& p : parameters) {
119 info(
"Saving event parameter: %-32s = %s", p.first.c_str(), p.second.c_str());
120 m_frame.putParameter(p.first, p.second);
127 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving event parameter: %s", p.first.c_str());
128 frame.putParameter(p.first, p.second);
131 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving event parameter: %s", p.first.c_str());
132 frame.putParameter(p.first, p.second);
135 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving event parameter: %s", p.first.c_str());
136 frame.putParameter(p.first, p.second);
140 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving event parameter: %s", p.first.c_str());
141 frame.putParameter(p.first, p.second);
147 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving run parameter: %s", p.first.c_str());
148 frame.putParameter(p.first, p.second);
151 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving run parameter: %s", p.first.c_str());
152 frame.putParameter(p.first, p.second);
155 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving run parameter: %s", p.first.c_str());
156 frame.putParameter(p.first, p.second);
160 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving run parameter: %s", p.first.c_str());
161 frame.putParameter(p.first, p.second);
166 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving meta parameter: %s", p.first.c_str());
167 frame.putParameter(p.first, p.second);
170 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving meta parameter: %s", p.first.c_str());
171 frame.putParameter(p.first, p.second);
174 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving meta parameter: %s", p.first.c_str());
175 frame.putParameter(p.first, p.second);
179 printout(DEBUG,
"Geant4OutputEDM4hep",
"Saving meta parameter: %s", p.first.c_str());
180 frame.putParameter(p.first, p.second);
186 #endif // DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
214 #include <G4Threading.hh>
215 #include <G4AutoLock.hh>
216 #include <G4Version.hh>
217 #include <G4ParticleDefinition.hh>
218 #include <G4VProcess.hh>
219 #include <G4Event.hh>
222 #include <CLHEP/Units/SystemOfUnits.h>
225 #include <edm4hep/EventHeaderCollection.h>
231 G4Mutex action_mutex = G4MUTEX_INITIALIZER;
239 :
Geant4OutputAction(ctxt,nam), m_runNo(0), m_runNumberOffset(0), m_eventNumberOffset(0)
241 declareProperty(
"RunHeader", m_runHeader);
242 declareProperty(
"EventParametersInt", m_eventParametersInt);
243 declareProperty(
"EventParametersFloat", m_eventParametersFloat);
244 declareProperty(
"EventParametersString", m_eventParametersString);
245 declareProperty(
"RunNumberOffset", m_runNumberOffset);
246 declareProperty(
"EventNumberOffset", m_eventNumberOffset);
247 declareProperty(
"SectionName", m_section_name);
248 declareProperty(
"FilesByRun", m_filesByRun);
249 info(
"Writer is now instantiated ..." );
255 G4AutoLock protection_lock(&action_mutex);
262 G4AutoLock protection_lock(&action_mutex);
266 std::size_t idx =
m_output.rfind(
".");
267 if ( idx != std::string::npos ) {
271 if ( !fname.empty() ) {
272 m_file = std::make_unique<podio::ROOTWriter>(fname);
274 fatal(
"+++ Failed to open output file: %s", fname.c_str());
276 printout( INFO,
"Geant4Output2EDM4hep" ,
"Opened %s for output", fname.c_str() ) ;
291 podio::Frame metaFrame{};
293 metaFrame.putParameter(podio::collMetadataParamName(
name, CellIDEncoding), encodingStr);
296 m_file->writeFrame(metaFrame,
"metadata");
302 G4AutoLock protection_lock(&action_mutex);
305 m_frame.put( std::move(it->second), it->first);
308 m_frame.put( std::move(calorimeterHits.first), colName);
309 m_frame.put( std::move(calorimeterHits.second), colName +
"Contributions");
318 except(
"+++ Failed to write output file. [Stream is not open]");
323 G4AutoLock protection_lock(&action_mutex);
327 podio::Frame runHeader {};
329 runHeader.putParameter(
key, value);
332 runHeader.putParameter(
"runNumber",
m_runNo);
333 runHeader.putParameter(
"GEANT4Version", G4Version);
335 runHeader.putParameter(
"detectorName",
context()->detectorDescription().header().
name());
341 m_file->writeFrame(runHeader,
"runs");
344 podio::Frame metaFrame {};
349 m_file->writeFrame(metaFrame,
"meta");
364 typedef detail::ReferenceBitMask<const int>
PropertyMask;
369 if ( pm.size() > 0 ) {
372 std::map<int,int> p_ids;
373 std::vector<const Geant4Particle*> p_part;
374 p_part.reserve(pm.size());
376 for (
const auto& iParticle : pm) {
377 int id = iParticle.first;
381 const G4ParticleDefinition* def = p.
definition();
383 mcp.setPDG(p->
pdgID);
385 using MT = decltype(std::declval<edm4hep::MCParticle>().getMomentum().x);
386 mcp.setMomentum( {MT(p->
psx/CLHEP::GeV),MT(p->
psy/CLHEP::GeV),MT(p->
psz/CLHEP::GeV)} );
387 mcp.setMomentumAtEndpoint( {MT(p->
pex/CLHEP::GeV),MT(p->
pey/CLHEP::GeV),MT(p->
pez/CLHEP::GeV)} );
389 double vs_fa[3] = { p->
vsx/CLHEP::mm, p->
vsy/CLHEP::mm, p->
vsz/CLHEP::mm } ;
390 mcp.setVertex( vs_fa );
392 double ve_fa[3] = { p->
vex/CLHEP::mm, p->
vey/CLHEP::mm, p->
vez/CLHEP::mm } ;
393 mcp.setEndpoint( ve_fa );
395 mcp.setTime(p->
time/CLHEP::ns);
396 mcp.setMass(p->
mass/CLHEP::GeV);
397 mcp.setCharge(def ? def->GetPDGCharge() : 0);
400 mcp.setGeneratorStatus(0);
419 mcp.setOverlay(
false );
422 if( mcp.isCreatedInSimulation() )
423 mcp.setGeneratorStatus( 0 ) ;
425 mcp.setSpin(p->
spin);
432 for(
size_t i=0; i < p_ids.size(); ++i) {
437 const auto k = p_ids.find(idau);
438 if (k == p_ids.end()) {
439 fatal(
"+++ Particle %d: FAILED to find daughter with ID:%d",p->
id,idau);
442 int iqdau = (*k).second;
444 q.addToDaughters(qdau);
447 for (
const auto& ipar : p->
parents) {
449 const auto k = p_ids.find(ipar);
450 if (k == p_ids.end()) {
451 fatal(
"+++ Particle %d: FAILED to find parent with ID:%d",p->
id,ipar);
454 int iqpar = (*k).second;
456 q.addToParents(qpar);
466 int runNumber(0), eventNumber(0);
469 double eventWeight{0};
472 runNumber = parameters->
runNumber() + runNumberOffset;
473 eventNumber = parameters->
eventNumber() + eventNumberOffset;
475 #if PODIO_BUILD_VERSION > PODIO_VERSION(0, 99, 0)
476 eventWeight =
m_frame.getParameter<
double>(
"EventWeights").value_or(0.0);
478 eventWeight =
m_frame.getParameter<
double>(
"EventWeights");
481 runNumber =
m_runNo + runNumberOffset;
482 eventNumber = ctxt.
context->GetEventID() + eventNumberOffset;
484 printout(INFO,
"Geant4Output2EDM4hep",
"+++ Saving EDM4hep event %d run %d.", eventNumber, runNumber);
487 edm4hep::EventHeaderCollection header_collection;
489 auto header = header_collection.create();
490 header.setRunNumber(runNumber);
491 header.setEventNumber(eventNumber);
492 header.setWeight(eventWeight);
494 header.setTimeStamp(std::time(
nullptr));
499 header.setTimeStamp(meh->getTimeStamp());
500 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 0)
501 for (
auto const& weight: meh->getWeights()) {
502 header.addToWeights(weight);
507 m_frame.put(std::move(header_collection),
"EventHeader");
514 print(
"+++ Saving %d EDM4hep particles....",
int(part_map->
particleMap.size()));
531 operator std::string()
const {
532 const auto* sd = m_coll->sensitive();
543 std::string colName = collection->GetName();
544 if( coll ==
nullptr ){
545 error(
" no Geant4HitCollection: %s ", colName.c_str());
548 size_t nhits = collection->GetSize();
550 debug(
"+++ Saving EDM4hep collection %s with %d entries.", colName.c_str(),
int(nhits));
559 for(
unsigned i=0 ; i < nhits ; ++i){
560 auto sth = hits->create();
568 sth.setCellID( hit->
cellID ) ;
570 sth.setPathLength(hit->
length/CLHEP::mm);
572 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 10, 99)
573 sth.setParticle(mcp);
575 sth.setMCParticle(mcp);
577 sth.setPosition( {pos.x()/CLHEP::mm, pos.y()/CLHEP::mm, pos.z()/CLHEP::mm} );
578 sth.setMomentum( {float(mom.x()/CLHEP::GeV),float(mom.y()/CLHEP::GeV),float(mom.z()/CLHEP::GeV)} );
579 auto particleIt = pm->
particles().find(trackID);
580 if( ( particleIt != pm->
particles().end()) ){
584 sth.setProducedBySecondary( (particleIt->second->originalG4ID != t.
trackID) );
594 for(
unsigned i=0 ; i < nhits ; ++i){
595 auto sch = hits.first->create();
598 sch.setCellID( hit->
cellID );
599 sch.setPosition({float(pos.x()/CLHEP::mm), float(pos.y()/CLHEP::mm), float(pos.z()/CLHEP::mm)});
604 for(
auto ci=hit->
truth.begin(); ci != hit->
truth.end(); ++ci){
606 auto sCaloHitCont = hits.second->create();
607 sch.addToContributions( sCaloHitCont );
612 sCaloHitCont.setEnergy( c.
deposit/CLHEP::GeV );
613 sCaloHitCont.setTime( c.
time/CLHEP::ns );
614 sCaloHitCont.setParticle( mcp );
617 edm4hep::Vector3f p(c.
x/CLHEP::mm, c.
y/CLHEP::mm, c.
z/CLHEP::mm);
618 sCaloHitCont.setPDG( c.
pdgID );
619 sCaloHitCont.setStepPosition( p );
625 error(
"+++ unknown type in Geant4HitCollection %s ", coll->
type().type().name());