File indexing completed on 2026-09-08 08:23:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
0014 #define DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
0015
0016
0017 #include <DD4hep/Detector.h>
0018 #include <DDG4/EventParameters.h>
0019 #include <DDG4/FileParameters.h>
0020 #include <DDG4/Geant4OutputAction.h>
0021 #include <DDG4/RunParameters.h>
0022
0023
0024 #include <edm4hep/MCParticleCollection.h>
0025 #include <edm4hep/SimTrackerHitCollection.h>
0026 #include <edm4hep/CaloHitContributionCollection.h>
0027 #include <edm4hep/SimCalorimeterHitCollection.h>
0028 #include <edm4hep/EDM4hepVersion.h>
0029 #include <edm4hep/Constants.h>
0030 #if EDM4HEP_BUILD_VERSION < EDM4HEP_VERSION(0, 99, 0)
0031 using edm4hep::CellIDEncoding;
0032 #else
0033 using edm4hep::labels::CellIDEncoding;
0034 #endif
0035 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 3)
0036 #include <edm4hep/GeneratorEventParametersCollection.h>
0037 #endif
0038
0039
0040 #include <podio/CollectionBase.h>
0041 #include <podio/podioVersion.h>
0042 #include <podio/Frame.h>
0043 #include <podio/FrameCategories.h>
0044 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0045 #include <podio/Writer.h>
0046 #else
0047 #if PODIO_BUILD_VERSION >= PODIO_VERSION(0, 99, 0)
0048 #include <podio/ROOTWriter.h>
0049 #else
0050 #include <podio/ROOTFrameWriter.h>
0051 namespace podio {
0052 using ROOTWriter = podio::ROOTFrameWriter;
0053 }
0054 #endif
0055 #endif
0056
0057 #include <atomic>
0058
0059
0060 namespace dd4hep {
0061
0062 class ComponentCast;
0063
0064
0065 namespace sim {
0066
0067 class Geant4ParticleMap;
0068
0069
0070
0071
0072
0073
0074
0075 class Geant4Output2EDM4hep : public Geant4OutputAction {
0076 protected:
0077 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0078 using writer_t = podio::Writer;
0079 #else
0080 using writer_t = podio::ROOTWriter;
0081 #endif
0082 using floatmap_t = std::map< std::string, float >;
0083 using intmap_t = std::map< std::string, int >;
0084 using stringmap_t = std::map< std::string, std::string >;
0085 using trackermap_t = std::map< std::string, edm4hep::SimTrackerHitCollection >;
0086 using calorimeterpair_t = std::pair< edm4hep::SimCalorimeterHitCollection, edm4hep::CaloHitContributionCollection >;
0087 using calorimetermap_t = std::map< std::string, calorimeterpair_t >;
0088 std::unique_ptr<writer_t> m_file { };
0089 std::atomic_size_t m_fileUseCount { 0 };
0090 podio::Frame m_frame { };
0091 edm4hep::MCParticleCollection m_particles { };
0092 trackermap_t m_trackerHits;
0093 calorimetermap_t m_calorimeterHits;
0094 stringmap_t m_runHeader;
0095 intmap_t m_eventParametersInt;
0096 floatmap_t m_eventParametersFloat;
0097 stringmap_t m_eventParametersString;
0098 intmap_t m_runParametersInt;
0099 floatmap_t m_runParametersFloat;
0100 stringmap_t m_runParametersString;
0101 stringmap_t m_cellIDEncodingStrings{};
0102 std::string m_section_name { "events" };
0103 int m_runNo { 0 };
0104 int m_runNumberOffset { 0 };
0105 int m_eventNo { 0 };
0106 int m_eventNumberOffset { 0 };
0107 bool m_filesByRun { false };
0108 bool m_rntuple { false };
0109
0110
0111 void saveParticles(Geant4ParticleMap* particles);
0112
0113 void saveFileMetaData();
0114 public:
0115
0116 Geant4Output2EDM4hep(Geant4Context* ctxt, const std::string& nam);
0117
0118 virtual ~Geant4Output2EDM4hep();
0119
0120 virtual void beginRun(const G4Run* run);
0121
0122 virtual void endRun(const G4Run* run);
0123
0124
0125 virtual void saveRun(const G4Run* run);
0126
0127 virtual void saveEvent( OutputContext<G4Event>& ctxt);
0128
0129 virtual void saveCollection( OutputContext<G4Event>& ctxt, G4VHitsCollection* collection);
0130
0131 virtual void commit( OutputContext<G4Event>& ctxt);
0132
0133
0134 virtual void begin(const G4Event* event);
0135 protected:
0136
0137 template <typename T>
0138 void saveEventParameters(const std::map<std::string, T >& parameters) {
0139 for(const auto& p : parameters) {
0140 std::stringstream output;
0141 output << "Saving event parameter: "
0142 << std::setw(32) << p.first
0143 << std::setw(20) << p.second;
0144 info(output.str().c_str());
0145 m_frame.putParameter(p.first, p.second);
0146 }
0147 }
0148 };
0149
0150 template <> void EventParameters::extractParameters(podio::Frame& frame) {
0151 for(auto const& p: this->intParameters()) {
0152 printout(DEBUG, "Geant4OutputEDM4hep", "Saving event parameter: %s", p.first.c_str());
0153 frame.putParameter(p.first, p.second);
0154 }
0155 for(auto const& p: this->fltParameters()) {
0156 printout(DEBUG, "Geant4OutputEDM4hep", "Saving event parameter: %s", p.first.c_str());
0157 frame.putParameter(p.first, p.second);
0158 }
0159 for(auto const& p: this->strParameters()) {
0160 printout(DEBUG, "Geant4OutputEDM4hep", "Saving event parameter: %s", p.first.c_str());
0161 frame.putParameter(p.first, p.second);
0162 }
0163
0164 for (auto const& p: this->dblParameters()) {
0165 printout(DEBUG, "Geant4OutputEDM4hep", "Saving event parameter: %s", p.first.c_str());
0166 frame.putParameter(p.first, p.second);
0167 }
0168 }
0169
0170 template <> void RunParameters::extractParameters(podio::Frame& frame) {
0171 for(auto const& p: this->intParameters()) {
0172 printout(DEBUG, "Geant4OutputEDM4hep", "Saving run parameter: %s", p.first.c_str());
0173 frame.putParameter(p.first, p.second);
0174 }
0175 for(auto const& p: this->fltParameters()) {
0176 printout(DEBUG, "Geant4OutputEDM4hep", "Saving run parameter: %s", p.first.c_str());
0177 frame.putParameter(p.first, p.second);
0178 }
0179 for(auto const& p: this->strParameters()) {
0180 printout(DEBUG, "Geant4OutputEDM4hep", "Saving run parameter: %s", p.first.c_str());
0181 frame.putParameter(p.first, p.second);
0182 }
0183
0184 for (auto const& p: this->dblParameters()) {
0185 printout(DEBUG, "Geant4OutputEDM4hep", "Saving run parameter: %s", p.first.c_str());
0186 frame.putParameter(p.first, p.second);
0187 }
0188 }
0189 template <> void FileParameters::extractParameters(podio::Frame& frame) {
0190 for(auto const& p: this->intParameters()) {
0191 printout(DEBUG, "Geant4OutputEDM4hep", "Saving meta parameter: %s", p.first.c_str());
0192 frame.putParameter(p.first, p.second);
0193 }
0194 for(auto const& p: this->fltParameters()) {
0195 printout(DEBUG, "Geant4OutputEDM4hep", "Saving meta parameter: %s", p.first.c_str());
0196 frame.putParameter(p.first, p.second);
0197 }
0198 for(auto const& p: this->strParameters()) {
0199 printout(DEBUG, "Geant4OutputEDM4hep", "Saving meta parameter: %s", p.first.c_str());
0200 frame.putParameter(p.first, p.second);
0201 }
0202
0203 for (auto const& p: this->dblParameters()) {
0204 printout(DEBUG, "Geant4OutputEDM4hep", "Saving meta parameter: %s", p.first.c_str());
0205 frame.putParameter(p.first, p.second);
0206 }
0207 }
0208
0209 }
0210 }
0211 #endif
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 #include <DD4hep/InstanceCount.h>
0228 #include <DD4hep/VolumeManager.h>
0229
0230 #include <DDG4/Geant4HitCollection.h>
0231 #include <DDG4/Geant4DataConversion.h>
0232 #include <DDG4/Geant4SensDetAction.h>
0233 #include <DDG4/Geant4Context.h>
0234 #include <DDG4/Geant4Particle.h>
0235 #include <DDG4/Geant4Data.h>
0236
0237
0238
0239 #include <G4Threading.hh>
0240 #include <G4AutoLock.hh>
0241 #include <G4Version.hh>
0242 #include <G4ParticleDefinition.hh>
0243 #include <G4VProcess.hh>
0244 #include <G4Event.hh>
0245 #include <G4Run.hh>
0246
0247 #include <CLHEP/Units/SystemOfUnits.h>
0248
0249
0250 #include <edm4hep/EventHeaderCollection.h>
0251
0252 using namespace dd4hep::sim;
0253 using namespace dd4hep;
0254
0255 namespace {
0256 G4Mutex action_mutex = G4MUTEX_INITIALIZER;
0257 }
0258
0259 #include <DDG4/Factories.h>
0260 DECLARE_GEANT4ACTION(Geant4Output2EDM4hep)
0261
0262
0263 Geant4Output2EDM4hep::Geant4Output2EDM4hep(Geant4Context* ctxt, const std::string& nam)
0264 : Geant4OutputAction(ctxt,nam), m_runNo(0), m_runNumberOffset(0), m_eventNumberOffset(0)
0265 {
0266 declareProperty("RunHeader", m_runHeader);
0267 declareProperty("EventParametersInt", m_eventParametersInt);
0268 declareProperty("EventParametersFloat", m_eventParametersFloat);
0269 declareProperty("EventParametersString", m_eventParametersString);
0270 declareProperty("RunParametersInt", m_runParametersInt);
0271 declareProperty("RunParametersFloat", m_runParametersFloat);
0272 declareProperty("RunParametersString", m_runParametersString);
0273 declareProperty("RunNumberOffset", m_runNumberOffset);
0274 declareProperty("EventNumberOffset", m_eventNumberOffset);
0275 declareProperty("SectionName", m_section_name);
0276 declareProperty("FilesByRun", m_filesByRun);
0277 declareProperty("RNTuple", m_rntuple);
0278
0279 info("Writer is now instantiated ..." );
0280 InstanceCount::increment(this);
0281 }
0282
0283
0284 Geant4Output2EDM4hep::~Geant4Output2EDM4hep() {
0285 G4AutoLock protection_lock(&action_mutex);
0286 InstanceCount::decrement(this);
0287 }
0288
0289
0290 void Geant4Output2EDM4hep::beginRun(const G4Run* run) {
0291 G4AutoLock protection_lock(&action_mutex);
0292 std::string fname = m_output;
0293 m_runNo = run->GetRunID();
0294 if ( m_filesByRun ) {
0295 std::size_t idx = m_output.rfind(".");
0296 if ( idx != std::string::npos ) {
0297 fname = m_output.substr(0, idx) + _toString(m_runNo, ".run%08d") + m_output.substr(idx);
0298 }
0299 }
0300
0301 if ( !fname.empty() && !m_file ) {
0302 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0303 m_file = std::make_unique<podio::Writer>(podio::makeWriter(fname, m_rntuple ? "rntuple" : "default"));
0304 #else
0305 m_file = std::make_unique<podio::ROOTWriter>(fname);
0306 #endif
0307 if ( !m_file ) {
0308 fatal("+++ Failed to open output file: %s", fname.c_str());
0309 }
0310 printout( INFO, "Geant4Output2EDM4hep" ,"Opened %s for output", fname.c_str() ) ;
0311 }
0312 m_fileUseCount++;
0313 }
0314
0315
0316 void Geant4Output2EDM4hep::endRun(const G4Run* run) {
0317 saveRun(run);
0318 saveFileMetaData();
0319
0320
0321
0322
0323 G4AutoLock protection_lock(&action_mutex);
0324 if ( m_file && m_fileUseCount == 1 ) {
0325 m_file->finish();
0326 m_file.reset();
0327 }
0328 m_fileUseCount--;
0329 }
0330
0331 void Geant4Output2EDM4hep::saveFileMetaData() {
0332 podio::Frame metaFrame{};
0333 for (const auto& [name, encodingStr] : m_cellIDEncodingStrings) {
0334 metaFrame.putParameter(podio::collMetadataParamName(name, CellIDEncoding), encodingStr);
0335 }
0336 G4AutoLock protection_lock(&action_mutex);
0337 m_file->writeFrame(metaFrame, "metadata");
0338 }
0339
0340
0341 void Geant4Output2EDM4hep::commit( OutputContext<G4Event>& ) {
0342 if ( m_file ) {
0343 G4AutoLock protection_lock(&action_mutex);
0344 m_frame.put( std::move(m_particles), "MCParticles");
0345 for (auto it = m_trackerHits.begin(); it != m_trackerHits.end(); ++it) {
0346 m_frame.put( std::move(it->second), it->first);
0347 }
0348 for (auto& [colName, calorimeterHits] : m_calorimeterHits) {
0349 m_frame.put( std::move(calorimeterHits.first), colName);
0350 m_frame.put( std::move(calorimeterHits.second), colName + "Contributions");
0351 }
0352 m_file->writeFrame(m_frame, m_section_name);
0353 m_particles = { };
0354 m_trackerHits.clear();
0355 m_calorimeterHits.clear();
0356 m_frame = {};
0357 return;
0358 }
0359 except("+++ Failed to write output file. [Stream is not open]");
0360 }
0361
0362
0363 void Geant4Output2EDM4hep::saveRun(const G4Run* run) {
0364 G4AutoLock protection_lock(&action_mutex);
0365
0366
0367
0368 podio::Frame runHeader {};
0369 for (const auto& [key, value] : m_runHeader)
0370 runHeader.putParameter(key, value);
0371
0372 for (const auto& [key, value] : m_runParametersInt)
0373 runHeader.putParameter(key, value);
0374
0375 for (const auto& [key, value] : m_runParametersFloat)
0376 runHeader.putParameter(key, value);
0377
0378 for (const auto& [key, value] : m_runParametersString)
0379 runHeader.putParameter(key, value);
0380
0381 m_runNo = m_runNumberOffset > 0 ? m_runNumberOffset + run->GetRunID() : run->GetRunID();
0382 runHeader.putParameter("runNumber", m_runNo);
0383 runHeader.putParameter("GEANT4Version", G4Version);
0384 runHeader.putParameter("DD4hepVersion", versionString());
0385 runHeader.putParameter("detectorName", context()->detectorDescription().header().name());
0386 {
0387
0388 if (context()->runPtr() != nullptr) {
0389 RunParameters* parameters = context()->run().extension<RunParameters>(false);
0390 if ( parameters ) {
0391 parameters->extractParameters(runHeader);
0392 }
0393 m_file->writeFrame(runHeader, "runs");
0394 }
0395 }
0396 {
0397
0398 if (context()->runPtr() != nullptr) {
0399 podio::Frame metaFrame {};
0400 FileParameters* parameters = context()->run().extension<FileParameters>(false);
0401 if ( parameters ) {
0402 parameters->extractParameters(metaFrame);
0403 }
0404 m_file->writeFrame(metaFrame, "meta");
0405 }
0406 }
0407 }
0408
0409 void Geant4Output2EDM4hep::begin(const G4Event* event) {
0410
0411 m_eventNo = event->GetEventID();
0412 m_frame = {};
0413 m_particles = {};
0414 m_trackerHits.clear();
0415 m_calorimeterHits.clear();
0416 }
0417
0418
0419 void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles) {
0420 typedef detail::ReferenceBitMask<const int> PropertyMask;
0421 typedef Geant4ParticleMap::ParticleMap ParticleMap;
0422 const ParticleMap& pm = particles->particleMap;
0423
0424 m_particles.clear();
0425 if ( pm.size() > 0 ) {
0426 size_t cnt = 0;
0427
0428 std::map<int,int> p_ids;
0429 std::vector<const Geant4Particle*> p_part;
0430 p_part.reserve(pm.size());
0431
0432 for (const auto& iParticle : pm) {
0433 int id = iParticle.first;
0434 const Geant4ParticleHandle p = iParticle.second;
0435 PropertyMask mask(p->status);
0436
0437 const G4ParticleDefinition* def = p.definition();
0438 auto mcp = m_particles.create();
0439 mcp.setPDG(p->pdgID);
0440
0441 using MT = decltype(std::declval<edm4hep::MCParticle>().getMomentum().x);
0442 mcp.setMomentum( {MT(p->psx/CLHEP::GeV),MT(p->psy/CLHEP::GeV),MT(p->psz/CLHEP::GeV)} );
0443 mcp.setMomentumAtEndpoint( {MT(p->pex/CLHEP::GeV),MT(p->pey/CLHEP::GeV),MT(p->pez/CLHEP::GeV)} );
0444
0445 double vs_fa[3] = { p->vsx/CLHEP::mm, p->vsy/CLHEP::mm, p->vsz/CLHEP::mm } ;
0446 mcp.setVertex( vs_fa );
0447
0448 double ve_fa[3] = { p->vex/CLHEP::mm, p->vey/CLHEP::mm, p->vez/CLHEP::mm } ;
0449 mcp.setEndpoint( ve_fa );
0450
0451 mcp.setTime(p->time/CLHEP::ns);
0452 mcp.setMass(p->mass/CLHEP::GeV);
0453 mcp.setCharge(def ? def->GetPDGCharge() : 0);
0454
0455
0456 mcp.setGeneratorStatus(0);
0457 if( p->genStatus ) {
0458 mcp.setGeneratorStatus( p->genStatus ) ;
0459 } else {
0460 if ( mask.isSet(G4PARTICLE_GEN_STABLE) ) mcp.setGeneratorStatus(1);
0461 else if ( mask.isSet(G4PARTICLE_GEN_DECAYED) ) mcp.setGeneratorStatus(2);
0462 else if ( mask.isSet(G4PARTICLE_GEN_DOCUMENTATION) ) mcp.setGeneratorStatus(3);
0463 else if ( mask.isSet(G4PARTICLE_GEN_BEAM) ) mcp.setGeneratorStatus(4);
0464 else if ( mask.isSet(G4PARTICLE_GEN_OTHER) ) mcp.setGeneratorStatus(9);
0465 }
0466
0467
0468 mcp.setCreatedInSimulation( mask.isSet(G4PARTICLE_SIM_CREATED) );
0469 mcp.setBackscatter( mask.isSet(G4PARTICLE_SIM_BACKSCATTER) );
0470 mcp.setVertexIsNotEndpointOfParent( mask.isSet(G4PARTICLE_SIM_PARENT_RADIATED) );
0471 mcp.setDecayedInTracker( mask.isSet(G4PARTICLE_SIM_DECAY_TRACKER) );
0472 mcp.setDecayedInCalorimeter( mask.isSet(G4PARTICLE_SIM_DECAY_CALO) );
0473 mcp.setHasLeftDetector( mask.isSet(G4PARTICLE_SIM_LEFT_DETECTOR) );
0474 mcp.setStopped( mask.isSet(G4PARTICLE_SIM_STOPPED) );
0475 mcp.setOverlay( false );
0476
0477
0478 if( mcp.isCreatedInSimulation() )
0479 mcp.setGeneratorStatus( 0 ) ;
0480
0481 #if EDM4HEP_MCPARTICLE_HAS_HELICITY
0482 mcp.setHelicity(p->spin[2]);
0483 #else
0484 mcp.setSpin(p->spin);
0485 #endif
0486
0487 p_ids[id] = cnt++;
0488 p_part.push_back(p);
0489 }
0490
0491
0492 for(size_t i=0; i < p_ids.size(); ++i) {
0493 const Geant4Particle* p = p_part[i];
0494 auto q = m_particles[i];
0495
0496 for (const auto& idau : p->daughters) {
0497 const auto k = p_ids.find(idau);
0498 if (k == p_ids.end()) {
0499 fatal("+++ Particle %d: FAILED to find daughter with ID:%d",p->id,idau);
0500 continue;
0501 }
0502 int iqdau = (*k).second;
0503 auto qdau = m_particles[iqdau];
0504 q.addToDaughters(qdau);
0505 }
0506
0507 for (const auto& ipar : p->parents) {
0508 if (ipar >= 0) {
0509 const auto k = p_ids.find(ipar);
0510 if (k == p_ids.end()) {
0511 fatal("+++ Particle %d: FAILED to find parent with ID:%d",p->id,ipar);
0512 continue;
0513 }
0514 int iqpar = (*k).second;
0515 auto qpar = m_particles[iqpar];
0516 q.addToParents(qpar);
0517 }
0518 }
0519 }
0520 }
0521 }
0522
0523
0524 void Geant4Output2EDM4hep::saveEvent(OutputContext<G4Event>& ctxt) {
0525 EventParameters* parameters = context()->event().extension<EventParameters>(false);
0526 int runNumber(0), eventNumber(0);
0527 const int eventNumberOffset(m_eventNumberOffset > 0 ? m_eventNumberOffset : 0);
0528 const int runNumberOffset(m_runNumberOffset > 0 ? m_runNumberOffset : 0);
0529 double eventWeight{0};
0530
0531 if ( parameters ) {
0532 runNumber = parameters->runNumber() + runNumberOffset;
0533 eventNumber = parameters->eventNumber() + eventNumberOffset;
0534 parameters->extractParameters(m_frame);
0535 #if PODIO_BUILD_VERSION > PODIO_VERSION(0, 99, 0)
0536 eventWeight = m_frame.getParameter<double>("EventWeights").value_or(0.0);
0537 #else
0538 eventWeight = m_frame.getParameter<double>("EventWeights");
0539 #endif
0540 } else {
0541 runNumber = m_runNo + runNumberOffset;
0542 eventNumber = ctxt.context->GetEventID() + eventNumberOffset;
0543 }
0544 printout(INFO,"Geant4Output2EDM4hep","+++ Saving EDM4hep event %d run %d.", eventNumber, runNumber);
0545
0546
0547 edm4hep::EventHeaderCollection header_collection;
0548
0549 auto header = header_collection.create();
0550 header.setRunNumber(runNumber);
0551 header.setEventNumber(eventNumber);
0552 header.setWeight(eventWeight);
0553
0554 header.setTimeStamp(std::time(nullptr));
0555
0556
0557 auto* meh = context()->event().extension<edm4hep::MutableEventHeader>(false);
0558 if(meh) {
0559 header.setTimeStamp(meh->getTimeStamp());
0560 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 0)
0561 for (auto const& weight: meh->getWeights()) {
0562 header.addToWeights(weight);
0563 }
0564 #endif
0565 }
0566
0567 m_frame.put(std::move(header_collection), "EventHeader");
0568
0569 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 3)
0570
0571 auto* genEvtParams = context()->event().extension<edm4hep::MutableGeneratorEventParameters>(false);
0572 if (genEvtParams) {
0573 edm4hep::GeneratorEventParametersCollection genEvtParamsColl{};
0574 genEvtParamsColl.push_back(*genEvtParams);
0575 m_frame.put(std::move(genEvtParamsColl), edm4hep::labels::GeneratorEventParameters);
0576 }
0577 #endif
0578
0579 saveEventParameters<int>(m_eventParametersInt);
0580 saveEventParameters<float>(m_eventParametersFloat);
0581 saveEventParameters<std::string>(m_eventParametersString);
0582
0583 Geant4ParticleMap* part_map = context()->event().extension<Geant4ParticleMap>(false);
0584 if ( part_map ) {
0585 print("+++ Saving %d EDM4hep particles....",int(part_map->particleMap.size()));
0586 if ( part_map->particleMap.size() > 0 ) {
0587 saveParticles(part_map);
0588 }
0589 }
0590 }
0591
0592
0593
0594
0595
0596 struct LazyEncodingExtraction {
0597
0598
0599 LazyEncodingExtraction(Geant4HitCollection* coll) : m_coll(coll) {}
0600
0601
0602 operator std::string() const {
0603 const auto* sd = m_coll->sensitive();
0604 return dd4hep::sim::Geant4ConversionHelper::encoding(sd->sensitiveDetector());
0605 }
0606 private:
0607 Geant4HitCollection* m_coll{nullptr};
0608 };
0609
0610
0611
0612 void Geant4Output2EDM4hep::saveCollection(OutputContext<G4Event>& , G4VHitsCollection* collection) {
0613 Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection);
0614 std::string colName = collection->GetName();
0615 if( coll == nullptr ){
0616 error(" no Geant4HitCollection: %s ", colName.c_str());
0617 return ;
0618 }
0619 size_t nhits = collection->GetSize();
0620 Geant4ParticleMap* pm = context()->event().extension<Geant4ParticleMap>(false);
0621 debug("+++ Saving EDM4hep collection %s with %d entries.", colName.c_str(), int(nhits));
0622
0623
0624 m_cellIDEncodingStrings.try_emplace(colName, LazyEncodingExtraction{coll});
0625
0626
0627 if( typeid( Geant4Tracker::Hit ) == coll->type().type() ){
0628
0629 auto& hits = m_trackerHits[colName];
0630 for(unsigned i=0 ; i < nhits ; ++i){
0631 auto sth = hits.create();
0632 const Geant4Tracker::Hit* hit = coll->hit(i);
0633 const Geant4Tracker::Hit::Contribution& t = hit->truth;
0634 int trackID = pm->particleID(t.trackID);
0635 auto mcp = m_particles.at(trackID);
0636 const auto& mom = hit->momentum;
0637 const auto& pos = hit->position;
0638 edm4hep::Vector3f();
0639 sth.setCellID( hit->cellID ) ;
0640 sth.setEDep(hit->energyDeposit/CLHEP::GeV);
0641 sth.setPathLength(hit->length/CLHEP::mm);
0642 sth.setTime(hit->truth.time/CLHEP::ns);
0643 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 10, 99)
0644 sth.setParticle(mcp);
0645 #else
0646 sth.setMCParticle(mcp);
0647 #endif
0648 sth.setPosition( {pos.x()/CLHEP::mm, pos.y()/CLHEP::mm, pos.z()/CLHEP::mm} );
0649 sth.setMomentum( {float(mom.x()/CLHEP::GeV),float(mom.y()/CLHEP::GeV),float(mom.z()/CLHEP::GeV)} );
0650 auto particleIt = pm->particles().find(trackID);
0651 if( ( particleIt != pm->particles().end()) ){
0652
0653
0654
0655 sth.setProducedBySecondary( (particleIt->second->originalG4ID != t.trackID) );
0656 }
0657 }
0658
0659 }
0660 else if( typeid( Geant4Calorimeter::Hit ) == coll->type().type() ){
0661 Geant4Sensitive* sd = coll->sensitive();
0662 int hit_creation_mode = sd->hitCreationMode();
0663
0664 auto& hits = m_calorimeterHits[colName];
0665 for(unsigned i=0 ; i < nhits ; ++i){
0666 auto sch = hits.first.create();
0667 const Geant4Calorimeter::Hit* hit = coll->hit(i);
0668 const auto& pos = hit->position;
0669 sch.setCellID( hit->cellID );
0670 sch.setPosition({float(pos.x()/CLHEP::mm), float(pos.y()/CLHEP::mm), float(pos.z()/CLHEP::mm)});
0671 sch.setEnergy( hit->energyDeposit/CLHEP::GeV );
0672
0673
0674
0675 for(auto ci=hit->truth.begin(); ci != hit->truth.end(); ++ci){
0676
0677 auto sCaloHitCont = hits.second.create();
0678 sch.addToContributions( sCaloHitCont );
0679
0680 const Geant4HitData::Contribution& c = *ci;
0681 int trackID = pm->particleID(c.trackID);
0682 auto mcp = m_particles.at(trackID);
0683 sCaloHitCont.setEnergy( c.deposit/CLHEP::GeV );
0684 sCaloHitCont.setTime( c.time/CLHEP::ns );
0685 sCaloHitCont.setParticle( mcp );
0686
0687 #if EDM4HEP_BUILD_VERSION > EDM4HEP_VERSION(1, 0, 0)
0688
0689
0690
0691
0692 if (c.length < 0) {
0693 mcp.setHandledByFastSim(true);
0694 }
0695 #endif
0696 if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE ) {
0697 edm4hep::Vector3f p(c.x/CLHEP::mm, c.y/CLHEP::mm, c.z/CLHEP::mm);
0698 sCaloHitCont.setPDG( c.pdgID );
0699 sCaloHitCont.setStepPosition( p );
0700 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 3)
0701 sCaloHitCont.setStepLength(c.length / CLHEP::mm);
0702 #endif
0703 }
0704 }
0705 }
0706
0707 } else {
0708 error("+++ unknown type in Geant4HitCollection %s ", coll->type().type().name());
0709 }
0710 }