From 9f22427f35be1cbd9a80e581bd69aa9ed7b62e6d Mon Sep 17 00:00:00 2001 From: tmadlener Date: Mon, 3 Jul 2023 21:16:37 +0200 Subject: [PATCH] Store the CellIDEncoding strings in the metadata Frame --- DDG4/edm4hep/Geant4Output2EDM4hep.cpp | 38 +++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp index 8d80de675..f043add61 100644 --- a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp +++ b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp @@ -60,6 +60,7 @@ namespace dd4hep { stringmap_t m_eventParametersInt; stringmap_t m_eventParametersFloat; stringmap_t m_eventParametersString; + stringmap_t m_cellIDEncodingStrings{}; std::string m_section_name { "events" }; int m_runNo { 0 }; int m_runNumberOffset { 0 }; @@ -67,10 +68,10 @@ namespace dd4hep { int m_eventNumberOffset { 0 }; bool m_filesByRun { false }; - /// create the podio collections for the particles and hits - void createCollections(OutputContext& ctxt) ; /// Data conversion interface for MC particles to EDM4hep format void saveParticles(Geant4ParticleMap* particles); + /// Store the metadata frame with e.g. the cellID encoding strings + void saveFileMetaData(); public: /// Standard constructor Geant4Output2EDM4hep(Geant4Context* ctxt, const std::string& nam); @@ -223,12 +224,22 @@ void Geant4Output2EDM4hep::beginRun(const G4Run* run) { /// Callback to store the Geant4 run information void Geant4Output2EDM4hep::endRun(const G4Run* run) { saveRun(run); + saveFileMetaData(); if ( m_file ) { m_file->finish(); m_file.reset(); } } +void Geant4Output2EDM4hep::saveFileMetaData() { + podio::Frame metaFrame{}; + for (const auto& [name, encodingStr] : m_cellIDEncodingStrings) { + metaFrame.putParameter(name + "__CellIDEncoding", encodingStr); + } + + m_file->writeFrame(metaFrame, "metadata"); +} + /// Commit data at end of filling procedure void Geant4Output2EDM4hep::commit( OutputContext& /* ctxt */) { if ( m_file ) { @@ -428,6 +439,25 @@ void Geant4Output2EDM4hep::saveEvent(OutputContext& ctxt) { } } +/** + * Helper struct that can be used together with map::try_emplace to construct + * the encoding only once per collection (name). + */ +struct LazyEncodingExtraction { + /// Constructor that does effectively nothing. This will be called in every + /// try_emplace call + LazyEncodingExtraction(Geant4HitCollection* coll) : m_coll(coll) {} + /// Defer the real work to the implicit conversion to std::string that will + /// only be called if the value is actually emplaced into the map + operator std::string() const { + const auto* sd = m_coll->sensitive(); + return dd4hep::sim::Geant4ConversionHelper::encoding(sd->sensitiveDetector()); + } +private: + Geant4HitCollection* m_coll{nullptr}; +}; + + /// Callback to store each Geant4 hit collection void Geant4Output2EDM4hep::saveCollection(OutputContext& /*ctxt*/, G4VHitsCollection* collection) { Geant4HitCollection* coll = dynamic_cast(collection); @@ -439,6 +469,10 @@ void Geant4Output2EDM4hep::saveCollection(OutputContext& /*ctxt*/, G4VH size_t nhits = collection->GetSize(); Geant4ParticleMap* pm = context()->event().extension(false); debug("+++ Saving EDM4hep collection %s with %d entries.", colName.c_str(), int(nhits)); + + // Using try_emplace here to only fill this the first time we come across + m_cellIDEncodingStrings.try_emplace(colName, LazyEncodingExtraction{coll}); + //------------------------------------------------------------------- if( typeid( Geant4Tracker::Hit ) == coll->type().type() ){ // Create the hit container even if there are no entries!