Back to home page

EIC code displayed by LXR

 
 

    


Warning, /eic-spack/packages/dd4hep/revert-Geant4Output2EDM4hep-dd4hep-1-24-to-1-23.patch is written in an unsupported language. File is not indexed.

0001 diff --git a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp
0002 index 950f3e20..2bafbdbd 100644
0003 --- a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp
0004 +++ b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp
0005 @@ -10,19 +10,40 @@
0006  // Author     : F.Gaede, DESY
0007  //
0008  //==========================================================================
0009 +
0010  #ifndef DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
0011  #define DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
0012  
0013 -///  Framework include files
0014 -#include <DD4hep/Detector.h>
0015 -#include <DDG4/EventParameters.h>
0016 -#include <DDG4/Geant4OutputAction.h>
0017 -
0018 -/// edm4hep include files
0019 -#include <edm4hep/MCParticleCollection.h>
0020 -/// podio include files
0021 -#include <podio/Frame.h>
0022 -#include <podio/ROOTFrameWriter.h>
0023 +//  Framework include files
0024 +#include "DD4hep/Detector.h"
0025 +#include "DD4hep/VolumeManager.h"
0026 +#include "DDG4/Geant4HitCollection.h"
0027 +#include "DDG4/Geant4OutputAction.h"
0028 +#include "DDG4/Geant4SensDetAction.h"
0029 +#include "DDG4/Geant4DataConversion.h"
0030 +#include "DDG4/EventParameters.h"
0031 +
0032 +// Geant4 headers
0033 +#include "G4Threading.hh"
0034 +#include "G4AutoLock.hh"
0035 +#include "G4Version.hh"
0036 +
0037 +// use the Geant4 units in namespace CLHEP
0038 +#include "CLHEP/Units/SystemOfUnits.h"
0039 +
0040 +// edm4hep include files
0041 +#include "edm4hep/EventHeaderCollection.h"
0042 +#include "edm4hep/MCParticleCollection.h"
0043 +#include "edm4hep/SimTrackerHitCollection.h"
0044 +#include "edm4hep/CaloHitContributionCollection.h"
0045 +#include "edm4hep/SimCalorimeterHitCollection.h"
0046 +#include "podio/EventStore.h"
0047 +#include "podio/ROOTWriter.h"
0048 +
0049 +#include <typeinfo>
0050 +#include <iostream>
0051 +#include <ctime>
0052 +#include <unordered_map>
0053  
0054  /// Namespace for the AIDA detector description toolkit
0055  namespace dd4hep {
0056 @@ -32,6 +53,20 @@ namespace dd4hep {
0057    /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0058    namespace sim {
0059  
0060 +    template <class T=podio::EventStore> void EventParameters::extractParameters(T& event){
0061 +      auto& lcparameters = event.getEventMetaData();
0062 +
0063 +      for(auto const& ival: this->intParameters()) {
0064 +        lcparameters.setValue(ival.first, ival.second);
0065 +      }
0066 +      for(auto const& ival: this->fltParameters()) {
0067 +        lcparameters.setValue(ival.first, ival.second);
0068 +      }
0069 +      for(auto const& ival: this->strParameters()) {
0070 +        lcparameters.setValue(ival.first, ival.second);
0071 +      }
0072 +    }
0073 +
0074      class  Geant4ParticleMap;
0075  
0076      /// Base class to output Geant4 event data to EDM4hep
0077 @@ -42,22 +77,19 @@ namespace dd4hep {
0078       */
0079      class Geant4Output2EDM4hep : public Geant4OutputAction  {
0080      protected:
0081 -      using writer_t = podio::ROOTFrameWriter;
0082 -      using stringmap_t = std::map< std::string, std::string >;
0083 -      std::unique_ptr<writer_t>     m_file  { };
0084 -      podio::Frame                  m_frame { };
0085 -      edm4hep::MCParticleCollection m_particles { };
0086 -      stringmap_t                   m_runHeader;
0087 -      stringmap_t                   m_eventParametersInt;
0088 -      stringmap_t                   m_eventParametersFloat;
0089 -      stringmap_t                   m_eventParametersString;
0090 -      std::string                   m_section_name      { "events" };
0091 -      int                           m_runNo             { 0 };
0092 -      int                           m_runNumberOffset   { 0 };
0093 -      int                           m_eventNo           { 0 };
0094 -      int                           m_eventNumberOffset { 0 };
0095 -      bool                          m_filesByRun        { false };
0096 -      
0097 +      podio::EventStore*  m_store;
0098 +      podio::ROOTWriter*  m_file;
0099 +      int              m_runNo;
0100 +      int              m_runNumberOffset;
0101 +      int              m_eventNumberOffset;
0102 +      std::map< std::string, std::string > m_runHeader;
0103 +      std::map< std::string, std::string > m_eventParametersInt;
0104 +      std::map< std::string, std::string > m_eventParametersFloat;
0105 +      std::map< std::string, std::string > m_eventParametersString;
0106 +      bool m_FirstEvent =  true  ;
0107 +
0108 +      std::unordered_map<std::string, podio::CollectionBase*> m_collections;
0109 +
0110        /// create the podio collections for the particles and hits
0111        void createCollections(OutputContext<G4Event>& ctxt) ;
0112        /// Data conversion interface for MC particles to EDM4hep format
0113 @@ -86,28 +118,33 @@ namespace dd4hep {
0114      protected:
0115        /// Fill event parameters in EDM4hep event
0116        template <typename T>
0117 -      void saveEventParameters(const std::map<std::string, std::string >& parameters)   {
0118 -       for(const auto& p : parameters)   {
0119 -         info("Saving event parameter: %-32s = %s", p.first.c_str(), p.second.c_str());
0120 -         m_frame.putParameter(p.first, p.second);
0121 -       }
0122 -      }
0123 +      void saveEventParameters(const std::map<std::string, std::string >& parameters);
0124      };
0125      
0126 -    template <> void EventParameters::extractParameters(podio::Frame& frame)   {
0127 -      for(auto const& p: this->intParameters()) {
0128 -       std::cout << "Saving event parameter: " << p.first << std::endl;
0129 -        frame.putParameter(p.first, p.second);
0130 -      }
0131 -      for(auto const& p: this->fltParameters()) {
0132 -       std::cout << "Saving event parameter: " << p.first << std::endl;
0133 -        frame.putParameter(p.first, p.second);
0134 +    /// Fill event parameters in EDM4hep event
0135 +    template <typename T>
0136 +    inline void Geant4Output2EDM4hep::saveEventParameters(const std::map<std::string, std::string >& parameters)  {
0137 +      for(std::map<std::string, std::string >::const_iterator iter = parameters.begin(), endIter = parameters.end() ; iter != endIter ; ++iter)  {
0138 +        T parameter;
0139 +        std::istringstream iss(iter->second);
0140 +        if ( (iss >> parameter).fail() )  {
0141 +          printout(FATAL,"saveEventParameters","+++ Event parameter %s: FAILED to convert to type :%s",iter->first.c_str(),typeid(T).name());
0142 +          continue;
0143 +        }
0144 +       auto& evtMD = m_store->getEventMetaData();
0145 +       evtMD.setValue(iter->first,parameter);
0146        }
0147 -      for(auto const& p: this->strParameters()) {
0148 -       std::cout << "Saving event parameter: " << p.first << std::endl;
0149 -        frame.putParameter(p.first, p.second);
0150 +    }
0151 +
0152 +    /// Fill event parameters in EDM4hep event - std::string specialization
0153 +    template <>
0154 +    inline void Geant4Output2EDM4hep::saveEventParameters<std::string>(const std::map<std::string, std::string >& parameters)  {
0155 +      for(std::map<std::string, std::string >::const_iterator iter = parameters.begin(), endIter = parameters.end() ; iter != endIter ; ++iter)  {
0156 +       auto& evtMD = m_store->getEventMetaData();
0157 +       evtMD.setValue(iter->first,iter->second);
0158        }
0159      }
0160 +
0161    }    // End namespace sim
0162  }      // End namespace dd4hep
0163  #endif // DD4HEP_DDG4_GEANT4OUTPUT2EDM4hep_H
0164 @@ -125,136 +162,111 @@ namespace dd4hep {
0165  //
0166  //==========================================================================
0167  
0168 -/// Framework include files
0169 -#include <DD4hep/InstanceCount.h>
0170 -#include <DD4hep/VolumeManager.h>
0171 -
0172 -#include <DDG4/Geant4HitCollection.h>
0173 -#include <DDG4/Geant4DataConversion.h>
0174 -#include <DDG4/Geant4SensDetAction.h>
0175 -#include <DDG4/Geant4Context.h>
0176 -#include <DDG4/Geant4Particle.h>
0177 -#include <DDG4/Geant4Data.h>
0178 -
0179 -///#include <DDG4/Geant4Output2EDM4hep.h>
0180 -/// Geant4 headers
0181 -#include <G4Threading.hh>
0182 -#include <G4AutoLock.hh>
0183 -#include <G4Version.hh>
0184 -#include <G4ParticleDefinition.hh>
0185 -#include <G4VProcess.hh>
0186 -#include <G4Event.hh>
0187 -#include <G4Run.hh>
0188 -/// use the Geant4 units in namespace CLHEP
0189 -#include <CLHEP/Units/SystemOfUnits.h>
0190 -
0191 -/// edm4hep include files
0192 -#include <edm4hep/EventHeaderCollection.h>
0193 -#include <edm4hep/SimTrackerHitCollection.h>
0194 -#include <edm4hep/CaloHitContributionCollection.h>
0195 -#include <edm4hep/SimCalorimeterHitCollection.h>
0196 +// Framework include files
0197 +#include "DD4hep/InstanceCount.h"
0198 +#include "DD4hep/Detector.h"
0199 +#include "DDG4/Geant4HitCollection.h"
0200 +#include "DDG4/Geant4DataConversion.h"
0201 +#include "DDG4/Geant4Context.h"
0202 +#include "DDG4/Geant4Particle.h"
0203 +#include "DDG4/Geant4Data.h"
0204 +#include "DDG4/Geant4Action.h"
0205 +
0206 +//#include "DDG4/Geant4Output2EDM4hep.h"
0207 +#include "G4ParticleDefinition.hh"
0208 +#include "G4VProcess.hh"
0209 +#include "G4Event.hh"
0210 +#include "G4Run.hh"
0211 +
0212  
0213  using namespace dd4hep::sim;
0214  using namespace dd4hep;
0215 -
0216 +using namespace std;
0217  namespace {
0218    G4Mutex action_mutex=G4MUTEX_INITIALIZER;
0219  }
0220  
0221 -#include <DDG4/Factories.h>
0222 +#include "DDG4/Factories.h"
0223  DECLARE_GEANT4ACTION(Geant4Output2EDM4hep)
0224  
0225  /// Standard constructor
0226 -Geant4Output2EDM4hep::Geant4Output2EDM4hep(Geant4Context* ctxt, const std::string& nam)
0227 -: Geant4OutputAction(ctxt,nam), m_runNo(0), m_runNumberOffset(0), m_eventNumberOffset(0)
0228 +Geant4Output2EDM4hep::Geant4Output2EDM4hep(Geant4Context* ctxt, const string& nam)
0229 +: Geant4OutputAction(ctxt,nam), m_store(0), m_file(0), m_runNo(0), m_runNumberOffset(0), m_eventNumberOffset(0)
0230  {
0231 -  declareProperty("RunHeader",             m_runHeader);
0232 +  declareProperty("RunHeader", m_runHeader);
0233    declareProperty("EventParametersInt",    m_eventParametersInt);
0234    declareProperty("EventParametersFloat",  m_eventParametersFloat);
0235    declareProperty("EventParametersString", m_eventParametersString);
0236 -  declareProperty("RunNumberOffset",       m_runNumberOffset);
0237 -  declareProperty("EventNumberOffset",     m_eventNumberOffset);
0238 -  declareProperty("SectionName",           m_section_name);
0239 -  declareProperty("FilesByRun",            m_filesByRun);
0240 -  info("Writer is now instantiated ..." );
0241 +  declareProperty("RunNumberOffset", m_runNumberOffset);
0242 +  declareProperty("EventNumberOffset", m_eventNumberOffset);
0243 +  printout( INFO, "Geant4Output2EDM4hep" ," instantiated ..." ) ;
0244    InstanceCount::increment(this);
0245  }
0246  
0247  /// Default destructor
0248  Geant4Output2EDM4hep::~Geant4Output2EDM4hep()  {
0249    G4AutoLock protection_lock(&action_mutex);
0250 -  m_file.reset();
0251 +  if ( m_file )  {
0252 +    m_file->finish();
0253 +    detail::deletePtr(m_file);
0254 +  }
0255 +  if (nullptr != m_store) {
0256 +    delete m_store;
0257 +  }
0258    InstanceCount::decrement(this);
0259  }
0260  
0261  // Callback to store the Geant4 run information
0262  void Geant4Output2EDM4hep::beginRun(const G4Run* run)  {
0263    G4AutoLock protection_lock(&action_mutex);
0264 -  std::string fname = m_output;
0265 -  m_runNo = run->GetRunID();
0266 -  if ( m_filesByRun )    {
0267 -    std::size_t idx = m_output.rfind(".");
0268 -    if ( idx != std::string::npos )   {
0269 -      fname = m_output.substr(0, idx) + _toString(m_runNo, ".run%08d") + m_output.substr(idx);
0270 -    }
0271 -  }
0272 -  if ( !m_file && !fname.empty() )   {
0273 -    m_file = std::make_unique<podio::ROOTFrameWriter>(fname);
0274 -    if ( !m_file )   {
0275 -      fatal("+++ Failed to open output file: %s", fname.c_str());
0276 -    }
0277 -    printout( INFO, "Geant4Output2EDM4hep" ,"Opened %s for output", fname.c_str() ) ;
0278 +  if ( 0 == m_file && !m_output.empty() )   {
0279 +    m_store = new podio::EventStore ;
0280 +    m_file = new podio::ROOTWriter(m_output, m_store);
0281 +
0282 +    printout( INFO, "Geant4Output2EDM4hep" ," opened %s for output", m_output.c_str() ) ;
0283    }
0284 +  
0285 +  saveRun(run);
0286  }
0287  
0288  /// Callback to store the Geant4 run information
0289 -void Geant4Output2EDM4hep::endRun(const G4Run* run)  {
0290 -  saveRun(run);
0291 -  if ( m_file )   {
0292 -    m_file->finish();
0293 -    m_file.reset();
0294 -  }
0295 +void Geant4Output2EDM4hep::endRun(const G4Run* /*run*/)  {
0296 +  // saveRun(run);
0297  }
0298  
0299  /// Commit data at end of filling procedure
0300  void Geant4Output2EDM4hep::commit( OutputContext<G4Event>& /* ctxt */)   {
0301    if ( m_file )   {
0302      G4AutoLock protection_lock(&action_mutex);
0303 -    m_frame.put( std::move(m_particles), "MCParticles");
0304 -    m_file->writeFrame(m_frame, m_section_name);
0305 -    m_particles.clear();
0306 -    m_frame = {};
0307 +    m_file->writeEvent();
0308 +    m_store->clearCollections();
0309      return;
0310    }
0311    except("+++ Failed to write output file. [Stream is not open]");
0312  }
0313  
0314  /// Callback to store the Geant4 run information
0315 -void Geant4Output2EDM4hep::saveRun(const G4Run* run)   {
0316 +void Geant4Output2EDM4hep::saveRun(const G4Run* /*run*/)  {
0317    //G4AutoLock protection_lock(&action_mutex);
0318  
0319 -  warning("saveRun: RunHeader not implemented in EDM4hep, nothing written for run: %d", run->GetRunID());
0320 +  printout( WARNING, "Geant4Output2EDM4hep" ,"saveRun(): RunHeader not implemented in EDM4hep, nothing written ..." ) ;
0321  
0322    // --- write an edm4hep::RunHeader ---------
0323    //FIXME: need a suitable Runheader object in EDM4hep
0324 -  //  edm4hep::LCRunHeaderImpl* rh =  new edm4hep::LCRunHeaderImpl;
0325 -  //  for (stringmap_t::iterator it = m_runHeader.begin(); it != m_runHeader.end(); ++it) {
0326 -  //    rh->parameters().setValue( it->first, it->second );
0327 -  //  }
0328 -  //  m_runNo = m_runNumberOffset > 0 ? m_runNumberOffset + run->GetRunID() : run->GetRunID();
0329 -  //  rh->parameters().setValue("GEANT4Version", G4Version);
0330 -  //  rh->parameters().setValue("DD4HEPVersion", versionString());
0331 -  //  rh->setRunNumber(m_runNo);
0332 -  //  rh->setDetectorName(context()->detectorDescription().header().name());
0333 -  //  m_file->writeRunHeader(rh);
0334 +
0335 +//  edm4hep::LCRunHeaderImpl* rh =  new edm4hep::LCRunHeaderImpl;
0336 +//  for (std::map< std::string, std::string >::iterator it = m_runHeader.begin(); it != m_runHeader.end(); ++it) {
0337 +//    rh->parameters().setValue( it->first, it->second );
0338 +//  }
0339 +//  m_runNo = m_runNumberOffset > 0 ? m_runNumberOffset + run->GetRunID() : run->GetRunID();
0340 +//  rh->parameters().setValue("GEANT4Version", G4Version);
0341 +//  rh->parameters().setValue("DD4HEPVersion", versionString());
0342 +//  rh->setRunNumber(m_runNo);
0343 +//  rh->setDetectorName(context()->detectorDescription().header().name());
0344 +//  m_file->writeRunHeader(rh);
0345  }
0346  
0347 -void Geant4Output2EDM4hep::begin(const G4Event* event)  {
0348 -  /// Create event frame object
0349 -  m_eventNo = event->GetEventID();
0350 -  m_particles.clear();
0351 -  m_particles = {};
0352 -  m_frame = {};
0353 +void Geant4Output2EDM4hep::begin(const G4Event* /* event */)  {
0354  }
0355  
0356  /// Data conversion interface for MC particles to EDM4hep format
0357 @@ -262,13 +274,13 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0358    typedef detail::ReferenceBitMask<const int> PropertyMask;
0359    typedef Geant4ParticleMap::ParticleMap ParticleMap;
0360    const ParticleMap& pm = particles->particleMap;
0361 +  auto mcpc = static_cast<edm4hep::MCParticleCollection*>(m_collections["MCParticles"]);
0362  
0363 -  m_particles.clear();
0364    if ( pm.size() > 0 )  {
0365      size_t cnt = 0;
0366      // Mapping of ids in the ParticleMap to indices in the MCParticle collection
0367 -    std::map<int,int> p_ids;
0368 -    std::vector<const Geant4Particle*> p_part;
0369 +    map<int,int> p_ids;
0370 +    vector<const Geant4Particle*> p_part;
0371      p_part.reserve(pm.size());
0372      // First create the particles
0373      for (const auto& iParticle : pm) {
0374 @@ -277,7 +289,7 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0375        PropertyMask mask(p->status);
0376        //      std::cout << " ********** mcp status : 0x" << std::hex << p->status << ", mask.isSet(G4PARTICLE_GEN_STABLE) x" << std::dec << mask.isSet(G4PARTICLE_GEN_STABLE)  <<std::endl ;
0377        const G4ParticleDefinition* def = p.definition();
0378 -      auto mcp = m_particles.create();
0379 +      auto mcp = mcpc->create();
0380        mcp.setPDG(p->pdgID);
0381  
0382        float ps_fa[3] = {float(p->psx/CLHEP::GeV),float(p->psy/CLHEP::GeV),float(p->psz/CLHEP::GeV)};
0383 @@ -299,13 +311,13 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0384        // Set generator status
0385        mcp.setGeneratorStatus(0);
0386        if( p->genStatus ) {
0387 -       mcp.setGeneratorStatus( p->genStatus ) ;
0388 +        mcp.setGeneratorStatus( p->genStatus ) ;
0389        } else {
0390 -       if ( mask.isSet(G4PARTICLE_GEN_STABLE) )             mcp.setGeneratorStatus(1);
0391 -       else if ( mask.isSet(G4PARTICLE_GEN_DECAYED) )       mcp.setGeneratorStatus(2);
0392 -       else if ( mask.isSet(G4PARTICLE_GEN_DOCUMENTATION) ) mcp.setGeneratorStatus(3);
0393 -       else if ( mask.isSet(G4PARTICLE_GEN_BEAM) )          mcp.setGeneratorStatus(4);
0394 -       else if ( mask.isSet(G4PARTICLE_GEN_OTHER) )         mcp.setGeneratorStatus(9);
0395 +        if ( mask.isSet(G4PARTICLE_GEN_STABLE) )             mcp.setGeneratorStatus(1);
0396 +        else if ( mask.isSet(G4PARTICLE_GEN_DECAYED) )       mcp.setGeneratorStatus(2);
0397 +        else if ( mask.isSet(G4PARTICLE_GEN_DOCUMENTATION) ) mcp.setGeneratorStatus(3);
0398 +        else if ( mask.isSet(G4PARTICLE_GEN_BEAM) )          mcp.setGeneratorStatus(4);
0399 +        else if ( mask.isSet(G4PARTICLE_GEN_OTHER) )         mcp.setGeneratorStatus(9);
0400        }
0401  
0402        // Set simulation status
0403 @@ -320,7 +332,7 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0404  
0405        //fg: if simstatus !=0 we have to set the generator status to 0:
0406        if( mcp.isCreatedInSimulation() )
0407 -       mcp.setGeneratorStatus( 0 )  ;
0408 +        mcp.setGeneratorStatus( 0 )  ;
0409  
0410        mcp.setSpin(p->spin);
0411        mcp.setColorFlow(p->colorFlow);
0412 @@ -332,30 +344,30 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0413      // Now establish parent-daughter relationships
0414      for(size_t i=0; i < p_ids.size(); ++i)   {
0415        const Geant4Particle* p = p_part[i];
0416 -      auto q = m_particles[i];
0417 +      auto q = (*mcpc)[i];
0418  
0419        for (const auto& idau : p->daughters) {
0420 -       const auto k = p_ids.find(idau);
0421 -       if (k == p_ids.end()) {
0422 -         fatal("+++ Particle %d: FAILED to find daughter with ID:%d",p->id,idau);
0423 -         continue;
0424 -       }
0425 -       int iqdau = (*k).second;
0426 -       auto qdau = m_particles[iqdau];
0427 -       q.addToDaughters(qdau);
0428 +        const auto k = p_ids.find(idau);
0429 +        if (k == p_ids.end()) {
0430 +          printout(FATAL,"Geant4Conversion","+++ Particle %d: FAILED to find daughter with ID:%d",p->id,idau);
0431 +          continue;
0432 +        }
0433 +        int iqdau = (*k).second;
0434 +        auto qdau = (*mcpc)[iqdau];
0435 +        q.addToDaughters(qdau);
0436        }
0437  
0438        for (const auto& ipar : p->parents) {
0439 -       if (ipar >= 0) { // A parent ID of -1 means NO parent, because a base of 0 is perfectly legal
0440 -         const auto k = p_ids.find(ipar);
0441 -         if (k == p_ids.end()) {
0442 -           fatal("+++ Particle %d: FAILED to find parent with ID:%d",p->id,ipar);
0443 -           continue;
0444 -         }
0445 -         int iqpar = (*k).second;
0446 -         auto qpar = m_particles[iqpar];
0447 -         q.addToParents(qpar);
0448 -       }
0449 +        if (ipar >= 0) { // A parent ID of -1 means NO parent, because a base of 0 is perfectly legal
0450 +          const auto k = p_ids.find(ipar);
0451 +          if (k == p_ids.end()) {
0452 +            printout(FATAL,"Geant4Conversion","+++ Particle %d: FAILED to find parent with ID:%d",p->id,ipar);
0453 +            continue;
0454 +          }
0455 +          int iqpar = (*k).second;
0456 +          auto qpar = (*mcpc)[iqpar];
0457 +          q.addToParents(qpar);
0458 +        }
0459        }
0460      }
0461    }
0462 @@ -363,6 +375,12 @@ void Geant4Output2EDM4hep::saveParticles(Geant4ParticleMap* particles)    {
0463  
0464  /// Callback to store the Geant4 event
0465  void Geant4Output2EDM4hep::saveEvent(OutputContext<G4Event>& ctxt)  {
0466 +
0467 +  if( m_FirstEvent ){
0468 +    createCollections( ctxt ) ;
0469 +    m_FirstEvent = false ;
0470 +  }
0471 +
0472    EventParameters* parameters = context()->event().extension<EventParameters>(false);
0473    int runNumber(0), eventNumber(0);
0474    const int eventNumberOffset(m_eventNumberOffset > 0 ? m_eventNumberOffset : 0);
0475 @@ -371,7 +389,7 @@ void Geant4Output2EDM4hep::saveEvent(OutputContext<G4Event>& ctxt)  {
0476    if ( parameters ) {
0477      runNumber = parameters->runNumber() + runNumberOffset;
0478      eventNumber = parameters->eventNumber() + eventNumberOffset;
0479 -    parameters->extractParameters(m_frame);
0480 +    parameters->extractParameters(*m_store);
0481    } else { // ... or from DD4hep framework
0482      runNumber = m_runNo + runNumberOffset;
0483      eventNumber = ctxt.context->GetEventID() + eventNumberOffset;
0484 @@ -379,13 +397,15 @@ void Geant4Output2EDM4hep::saveEvent(OutputContext<G4Event>& ctxt)  {
0485    printout(INFO,"Geant4Output2EDM4hep","+++ Saving EDM4hep event %d run %d.", eventNumber, runNumber);
0486  
0487    // this does not compile as create() is we only get a const ref - need to review PODIO EventStore API
0488 -  edm4hep::EventHeaderCollection header_collection;
0489 -  auto header = header_collection.create();
0490 -  header.setRunNumber(runNumber);
0491 -  header.setEventNumber(eventNumber);
0492 -  //not implemented in EDM4hep ?  header.setDetectorName(context()->detectorDescription().header().name());
0493 -  header.setTimeStamp( std::time(nullptr) ) ;
0494 -  m_frame.put( std::move(header_collection), "EventHeader");
0495 +  // auto& evtHCol = m_store->get<edm4hep::EventHeaderCollection>("EventHeader") ;
0496 +// auto evtHdr = evtHCol.create() ;
0497 +  auto* evtHCol = static_cast<edm4hep::EventHeaderCollection*>(m_collections["EventHeader"]);
0498 +  auto evtHdr = evtHCol->create() ;
0499 +
0500 +  evtHdr.setRunNumber(runNumber);
0501 +  evtHdr.setEventNumber(eventNumber);
0502 +//not implemented in EDM4hep ?  evtHdr.setDetectorName(context()->detectorDescription().header().name());
0503 +  evtHdr.setTimeStamp( std::time(nullptr) ) ;
0504  
0505    saveEventParameters<int>(m_eventParametersInt);
0506    saveEventParameters<float>(m_eventParametersFloat);
0507 @@ -402,34 +422,49 @@ void Geant4Output2EDM4hep::saveEvent(OutputContext<G4Event>& ctxt)  {
0508  
0509  /// Callback to store each Geant4 hit collection
0510  void Geant4Output2EDM4hep::saveCollection(OutputContext<G4Event>& /*ctxt*/, G4VHitsCollection* collection)  {
0511 -  Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection);
0512 +
0513 +  size_t nhits = collection->GetSize();
0514    std::string colName = collection->GetName();
0515 +
0516 +  printout(DEBUG,"Geant4Output2EDM4hep","+++ Saving EDM4hep collection %s with %d entries.",
0517 +     colName.c_str(),int(nhits));
0518 +
0519 +  Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection);
0520    if( coll == nullptr ){
0521 -    error(" no Geant4HitCollection:  %s ", colName.c_str());
0522 +    printout(ERROR, "Geant4Output2EDM4hep" , " no Geant4HitCollection:  %s ", colName.c_str() );
0523      return ;
0524    }
0525 -  size_t nhits = collection->GetSize();
0526 +
0527    Geant4ParticleMap* pm = context()->event().extension<Geant4ParticleMap>(false);
0528 -  debug("+++ Saving EDM4hep collection %s with %d entries.", colName.c_str(), int(nhits));
0529 +
0530 +  auto* mcpc = static_cast<edm4hep::MCParticleCollection*>(m_collections["MCParticles"]);
0531 +
0532    //-------------------------------------------------------------------
0533    if( typeid( Geant4Tracker::Hit ) == coll->type().type()  ){
0534 -    edm4hep::SimTrackerHitCollection sthc;
0535 +
0536 +    auto* sthc = static_cast<edm4hep::SimTrackerHitCollection*>(m_collections[colName]);
0537 +
0538      for(unsigned i=0 ; i < nhits ; ++i){
0539 -      auto sth = sthc->create();
0540 +      auto sth = sthc->create() ;
0541 +
0542        const Geant4Tracker::Hit* hit = coll->hit(i);
0543        const Geant4Tracker::Hit::Contribution& t = hit->truth;
0544 -      int   trackID   = pm->particleID(t.trackID);
0545 -      auto  mcp       = m_particles.at(trackID);
0546 -      const auto& mom = hit->momentum;
0547 -      const auto& pos = hit->position;
0548 -      edm4hep::Vector3f();
0549 +      int trackID = pm->particleID(t.trackID);
0550 +
0551 +      auto mcp = mcpc->at(trackID);
0552 +
0553        sth.setCellID( hit->cellID ) ;
0554        sth.setEDep(hit->energyDeposit/CLHEP::GeV);
0555        sth.setPathLength(hit->length/CLHEP::mm);
0556        sth.setTime(hit->truth.time/CLHEP::ns);
0557        sth.setMCParticle(mcp);
0558 -      sth.setPosition( {pos.x()/CLHEP::mm, pos.y()/CLHEP::mm, pos.z()/CLHEP::mm} );
0559 -      sth.setMomentum( {float(mom.x()/CLHEP::GeV),float(mom.y()/CLHEP::GeV),float(mom.z()/CLHEP::GeV)} );
0560 +      sth.setPosition({hit->position.x()/CLHEP::mm,
0561 +           hit->position.y()/CLHEP::mm,
0562 +           hit->position.z()/CLHEP::mm});
0563 +      sth.setMomentum(edm4hep::Vector3f(hit->momentum.x()/CLHEP::GeV,
0564 +          hit->momentum.y()/CLHEP::GeV,
0565 +          hit->momentum.z()/CLHEP::GeV ));
0566 +
0567        auto particleIt = pm->particles().find(trackID);
0568        if( ( particleIt != pm->particles().end()) ){
0569          // if the original track ID of the particle is not the same as the
0570 @@ -438,49 +473,139 @@ void Geant4Output2EDM4hep::saveCollection(OutputContext<G4Event>& /*ctxt*/, G4VH
0571          sth.setProducedBySecondary( (particleIt->second->originalG4ID != t.trackID) );
0572        }
0573      }
0574 -    m_frame.put(std::move(sthc), colName);
0575 -    //-------------------------------------------------------------------
0576 +  //-------------------------------------------------------------------
0577    }
0578    else if( typeid( Geant4Calorimeter::Hit ) == coll->type().type() ){
0579 -    Geant4Sensitive* sd = coll->sensitive();
0580 +
0581 +    Geant4Sensitive*       sd      = coll->sensitive();
0582      int hit_creation_mode = sd->hitCreationMode();
0583  
0584 -    edm4hep::SimCalorimeterHitCollection sCaloHitColl;
0585 -    edm4hep::CaloHitContributionCollection sCaloHitContColl;
0586 +    auto* sCaloHitColl = static_cast<edm4hep::SimCalorimeterHitCollection*>(m_collections[colName]);
0587 +
0588 +    colName += "Contributions"  ;
0589 +
0590 +    auto* sCaloHitContColl = static_cast<edm4hep::CaloHitContributionCollection*>(m_collections[colName]);
0591 +
0592 +
0593      for(unsigned i=0 ; i < nhits ; ++i){
0594        auto sch = sCaloHitColl->create() ;
0595 +
0596        const Geant4Calorimeter::Hit* hit = coll->hit(i);
0597 -      const auto& pos = hit->position;
0598 +
0599        sch.setCellID( hit->cellID );
0600 -      sch.setPosition({float(pos.x()/CLHEP::mm), float(pos.y()/CLHEP::mm), float(pos.z()/CLHEP::mm)});
0601 +      sch.setPosition({
0602 +           float(hit->position.x()/CLHEP::mm),
0603 +           float(hit->position.y()/CLHEP::mm),
0604 +           float(hit->position.z()/CLHEP::mm)});
0605        sch.setEnergy( hit->energyDeposit/CLHEP::GeV );
0606  
0607 -
0608        // now add the individual step contributions
0609 -      for(auto ci=hit->truth.begin(); ci != hit->truth.end(); ++ci){
0610 +      for(Geant4HitData::Contributions::const_iterator ci=hit->truth.begin();
0611 +        ci!=hit->truth.end(); ++ci){
0612  
0613          auto sCaloHitCont = sCaloHitContColl->create();
0614          sch.addToContributions( sCaloHitCont );
0615  
0616          const Geant4HitData::Contribution& c = *ci;
0617          int trackID = pm->particleID(c.trackID);
0618 -        auto mcp = m_particles.at(trackID);
0619 +        auto mcp = mcpc->at(trackID);
0620 +
0621          sCaloHitCont.setEnergy( c.deposit/CLHEP::GeV );
0622          sCaloHitCont.setTime( c.time/CLHEP::ns );
0623          sCaloHitCont.setParticle( mcp );
0624  
0625          if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE )     {
0626 -         edm4hep::Vector3f p(c.x/CLHEP::mm, c.y/CLHEP::mm, c.z/CLHEP::mm);
0627            sCaloHitCont.setPDG( c.pdgID );
0628 -          sCaloHitCont.setStepPosition( p );
0629 +          sCaloHitCont.setStepPosition( edm4hep::Vector3f(
0630 +            c.x/CLHEP::mm,
0631 +            c.y/CLHEP::mm, 
0632 +            c.z/CLHEP::mm) );
0633          }
0634        }
0635      }
0636 -    m_frame.put(std::move(sCaloHitColl), colName);
0637 -    m_frame.put(std::move(sCaloHitContColl), colName + "Contributions");
0638 -    //-------------------------------------------------------------------
0639 +  //-------------------------------------------------------------------
0640    } else {
0641 -    error("+++ unknown type in Geant4HitCollection %s ", coll->type().type().name());
0642 +
0643 +    printout(ERROR, "Geant4Output2EDM4hep" , " unknown type in Geant4HitCollection  %s ",
0644 +            coll->type().type().name() );
0645    }
0646  }
0647  
0648 +void Geant4Output2EDM4hep::createCollections(OutputContext<G4Event>& ctxt){
0649 +
0650 +  auto* mcColl = new edm4hep::MCParticleCollection();
0651 +  m_collections.emplace("MCParticles", mcColl);
0652 +  m_store->registerCollection("MCParticles", mcColl);
0653 +  m_file->registerForWrite("MCParticles");
0654 +  printout(DEBUG,"Geant4Output2EDM4hep","+++ created collection MCParticles" );
0655 +
0656 +  auto* evtHeader = new edm4hep::EventHeaderCollection();
0657 +  m_collections.emplace("EventHeader", evtHeader);
0658 +  m_store->registerCollection("EventHeader", evtHeader);
0659 +  m_file->registerForWrite("EventHeader");
0660 +  printout(DEBUG,"Geant4Output2EDM4hep","+++ created collection EventHeader" );
0661 +
0662 +
0663 +  const G4Event* evt = ctxt.context ;
0664 +  G4HCofThisEvent* hce = evt->GetHCofThisEvent();
0665 +  int nCol = hce->GetNumberOfCollections();
0666 +
0667 +  for (int i = 0; i < nCol; ++i) {
0668 +    G4VHitsCollection* hc = hce->GetHC(i);
0669 +    std::string colName =  hc->GetName() ;
0670 +    Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(hc);
0671 +    if( coll == nullptr ){
0672 +      printout(WARNING, "Geant4Output2EDM4hep" , " no Geant4HitCollection:  %s ", colName.c_str() );
0673 +      continue ;
0674 +    }
0675 +
0676 +    Geant4Sensitive* sd = coll->sensitive();
0677 +    string sd_enc = dd4hep::sim::Geant4ConversionHelper::encoding(sd->sensitiveDetector());
0678 +
0679 +    if( typeid( Geant4Tracker::Hit ) == coll->type().type()  ){
0680 +
0681 +      auto* sthc = new edm4hep::SimTrackerHitCollection();
0682 +      auto pairColCheck = m_collections.emplace(colName, sthc);
0683 +      if ( pairColCheck.second ) {
0684 +        m_store->registerCollection(colName, sthc);
0685 +        m_file->registerForWrite(colName);
0686 +        auto& sthc_md = m_store->getCollectionMetaData( sthc->getID() );
0687 +        sthc_md.setValue("CellIDEncodingString", sd_enc);
0688 +        printout(DEBUG,"Geant4Output2EDM4hep","+++ created collection %s",colName.c_str() );
0689 +      } else {
0690 +        delete sthc;
0691 +      }
0692 +      printout(DEBUG,"Geant4Output2EDM4hep","+++ re-using collection %s",colName.c_str() );
0693 +
0694 +    }
0695 +    else if( typeid( Geant4Calorimeter::Hit ) == coll->type().type() ){
0696 +
0697 +      auto* schc = new edm4hep::SimCalorimeterHitCollection();
0698 +      auto pairColCheck = m_collections.emplace(colName, schc);
0699 +      if ( pairColCheck.second ) {
0700 +        m_store->registerCollection(colName, schc);
0701 +        m_file->registerForWrite(colName);
0702 +        auto& schc_md = m_store->getCollectionMetaData( schc->getID() );
0703 +        schc_md.setValue("CellIDEncodingString", sd_enc);
0704 +        printout(DEBUG,"Geant4Output2EDM4hep","+++ created collection %s",colName.c_str() );
0705 +
0706 +        colName += "Contributions"  ;
0707 +        auto* chContribColl = new edm4hep::CaloHitContributionCollection();
0708 +        m_collections.emplace(colName, chContribColl);
0709 +        m_store->registerCollection(colName, chContribColl);
0710 +        m_file->registerForWrite(colName);
0711 +        printout(DEBUG,"Geant4Output2EDM4hep","+++ created collection %s",colName.c_str() );
0712 +      } else {
0713 +        delete schc;
0714 +        printout(DEBUG,"Geant4Output2EDM4hep","+++ re-using collection %s",colName.c_str() );
0715 +      }
0716 +
0717 +    } else {
0718 +
0719 +      printout(WARNING, "Geant4Output2EDM4hep" ,
0720 +              " unknown type in Geant4HitCollection  %s ", coll->type().type().name() );
0721 +    }
0722 +  }
0723 +
0724 +
0725 +}