File indexing completed on 2026-09-17 08:25:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/InstanceCount.h>
0016 #include <DDDigi/DigiContext.h>
0017 #include <DDDigi/DigiPlugins.h>
0018 #include <DDDigi/DigiKernel.h>
0019 #include "DigiEdm4hepOutput.h"
0020 #include "DigiIO.h"
0021
0022
0023 #include <podio/podioVersion.h>
0024 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0025 #include <podio/Writer.h>
0026 #elif PODIO_BUILD_VERSION >= PODIO_VERSION(0, 99, 0)
0027 #include <podio/ROOTWriter.h>
0028 #else
0029 #include <podio/ROOTFrameWriter.h>
0030 namespace podio {
0031 using ROOTWriter = podio::ROOTFrameWriter;
0032 }
0033 #endif
0034 #include <podio/Frame.h>
0035 #include <edm4hep/SimTrackerHit.h>
0036 #include <edm4hep/MCParticleCollection.h>
0037 #include <edm4hep/EventHeaderCollection.h>
0038 #include <edm4hep/CalorimeterHitCollection.h>
0039 #include <edm4hep/CaloHitContributionCollection.h>
0040
0041
0042
0043 namespace dd4hep {
0044
0045
0046 namespace digi {
0047
0048 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0049 using writer_t = podio::Writer;
0050 #else
0051 using writer_t = podio::ROOTWriter;
0052 #endif
0053
0054
0055
0056
0057
0058
0059
0060
0061 class DigiEdm4hepOutput::internals_t {
0062 public:
0063 using particlecollection_t = std::pair<std::string,std::unique_ptr<edm4hep::MCParticleCollection> >;
0064 using headercollection_t = std::pair<std::string,std::unique_ptr<edm4hep::EventHeaderCollection> >;
0065 DigiEdm4hepOutput* m_parent { nullptr };
0066
0067 std::unique_ptr<writer_t> m_writer { };
0068
0069 headercollection_t m_header { };
0070
0071 particlecollection_t m_particles { };
0072
0073 std::map<std::string, std::unique_ptr<edm4hep::TrackerHit3DCollection> > m_tracker_collections;
0074
0075 std::map<std::string, std::unique_ptr<edm4hep::CalorimeterHitCollection> > m_calo_collections;
0076
0077 std::string m_section_name{ "EVENT" };
0078
0079 std::mutex m_lock;
0080
0081 long num_events { -1 };
0082
0083 long event_count { 0 };
0084
0085 public:
0086
0087 internals_t(DigiEdm4hepOutput* parent);
0088
0089 ~internals_t();
0090
0091
0092 void clear();
0093
0094 void commit();
0095
0096 void open();
0097
0098 void close();
0099
0100
0101 void create_collections();
0102
0103 template <typename T> podio::CollectionBase* get_collection(const T&);
0104 };
0105
0106
0107 DigiEdm4hepOutput::internals_t::internals_t(DigiEdm4hepOutput* parent) : m_parent(parent)
0108 {
0109 }
0110
0111
0112 DigiEdm4hepOutput::internals_t::~internals_t() {
0113 if ( m_writer ) close();
0114 m_tracker_collections.clear();
0115 m_calo_collections.clear();
0116 m_particles.second.reset();
0117 m_header.second.reset();
0118 }
0119
0120
0121 void DigiEdm4hepOutput::internals_t::create_collections() {
0122 if ( !m_header.second ) {
0123 m_header = std::make_pair("EventHeader", std::make_unique<edm4hep::EventHeaderCollection>());
0124 for( auto& cont : m_parent->m_containers ) {
0125 const std::string& nam = cont.first;
0126 const std::string& typ = cont.second;
0127 if ( typ == "MCParticles" ) {
0128 m_particles = std::make_pair(nam, std::make_unique<edm4hep::MCParticleCollection>());
0129 }
0130 else if ( typ == "TrackerHits" ) {
0131 m_tracker_collections.emplace(nam, std::make_unique<edm4hep::TrackerHit3DCollection>());
0132 }
0133 else if ( typ == "CalorimeterHits" ) {
0134 m_calo_collections.emplace(nam, std::make_unique<edm4hep::CalorimeterHitCollection>());
0135 }
0136 }
0137 m_parent->info("+++ Will save %ld events to %s", num_events, m_parent->m_output.c_str());
0138 }
0139 }
0140
0141 template <typename T>
0142 podio::CollectionBase* DigiEdm4hepOutput::internals_t::get_collection(const T& cont) {
0143 switch(cont.data_type) {
0144 case SegmentEntry::TRACKER_HITS: {
0145 auto iter = m_tracker_collections.find(cont.name);
0146 if ( iter == m_tracker_collections.end() )
0147 m_parent->except("Error");
0148 return iter->second.get();
0149 }
0150 case SegmentEntry::CALORIMETER_HITS: {
0151 auto iter = m_calo_collections.find(cont.name);
0152 if ( iter == m_calo_collections.end() )
0153 m_parent->except("Error");
0154 return iter->second.get();
0155 }
0156 default:
0157 return nullptr;
0158 }
0159 };
0160
0161
0162 void DigiEdm4hepOutput::internals_t::clear() {
0163 #if 0
0164 m_header.second->clear();
0165 m_particles.second->clear();
0166 for( const auto& c : m_tracker_collections )
0167 c.second->clear();
0168 for( const auto& c : m_calo_collections )
0169 c.second->clear();
0170 #endif
0171 *m_header.second = {};
0172 *m_particles.second = {};
0173 for( const auto& c : m_tracker_collections )
0174 *c.second = {};
0175 for( const auto& c : m_calo_collections )
0176 *c.second = {};
0177 }
0178
0179
0180 void DigiEdm4hepOutput::internals_t::commit() {
0181 if ( m_writer ) {{
0182 std::lock_guard<std::mutex> protection(m_lock);
0183 podio::Frame frame { };
0184 frame.put( std::move(*m_header.second), m_header.first);
0185 frame.put( std::move(*m_particles.second), m_particles.first);
0186 for( const auto& c : m_tracker_collections )
0187 frame.put( std::move(*c.second), c.first);
0188 for( const auto& c : m_calo_collections )
0189 frame.put( std::move(*c.second), c.first);
0190
0191 m_writer->writeFrame(frame, m_section_name);
0192 }
0193 clear();
0194 return;
0195 }
0196 m_parent->except("+++ Failed to write output file. [Stream is not open]");
0197 }
0198
0199
0200 void DigiEdm4hepOutput::internals_t::open() {
0201 if ( m_writer ) {
0202 close();
0203 }
0204 clear();
0205 m_writer.reset();
0206 std::string fname = m_parent->next_stream_name();
0207 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0208 m_writer = std::make_unique<writer_t>(podio::makeWriter(fname));
0209 #else
0210 m_writer = std::make_unique<writer_t>(fname);
0211 #endif
0212 m_parent->info("+++ Opened EDM4HEP output file %s", fname.c_str());
0213 }
0214
0215
0216 void DigiEdm4hepOutput::internals_t::close() {
0217 m_parent->info("+++ Closing EDM4HEP output file.");
0218 if ( m_writer ) {
0219 m_writer->finish();
0220 }
0221 m_writer.reset();
0222 }
0223
0224
0225 DigiEdm4hepOutput::DigiEdm4hepOutput(const DigiKernel& krnl, const std::string& nam)
0226 : DigiOutputAction(krnl, nam)
0227 {
0228 internals = std::make_shared<internals_t>(this);
0229 InstanceCount::increment(this);
0230 }
0231
0232
0233 DigiEdm4hepOutput::~DigiEdm4hepOutput() {
0234 internals.reset();
0235 InstanceCount::decrement(this);
0236 }
0237
0238
0239 void DigiEdm4hepOutput::initialize() {
0240 this->DigiOutputAction::initialize();
0241 for ( auto& c : m_registered_processors ) {
0242 auto* act = dynamic_cast<DigiEdm4hepOutputProcessor*>(c.second);
0243 if ( act ) {
0244 act->internals = this->internals;
0245 continue;
0246 }
0247 except("Error: Invalid processor type for EDM4HEP output: %s", c.second->c_name());
0248 }
0249 m_parallel = false;
0250 internals->create_collections();
0251 }
0252
0253
0254 bool DigiEdm4hepOutput::have_output() const {
0255 return internals->m_writer.get() != nullptr;
0256 }
0257
0258
0259 void DigiEdm4hepOutput::open_output() const {
0260 internals->open();
0261 }
0262
0263
0264 void DigiEdm4hepOutput::close_output() const {
0265 internals->close();
0266 }
0267
0268
0269 void DigiEdm4hepOutput::commit_output() const {
0270 internals->commit();
0271 }
0272
0273
0274 DigiEdm4hepOutputProcessor::DigiEdm4hepOutputProcessor(const DigiKernel& krnl, const std::string& nam)
0275 : DigiContainerProcessor(krnl, nam)
0276 {
0277 declareProperty("point_resolution_RPhi", m_pointResoutionRPhi);
0278 declareProperty("point_resolution_Z", m_pointResoutionZ);
0279 declareProperty("hit_type", m_hit_type = 0);
0280 }
0281
0282 void DigiEdm4hepOutputProcessor::convert_particles(DigiContext& ctxt,
0283 const ParticleMapping& cont) const
0284 {
0285 auto& parts = internals->m_particles.second;
0286 data_io<edm4hep_input>::_to_edm4hep(cont, parts.get());
0287 info("%s+++ %-24s added %6ld entries from mask: %04X to %s",
0288 ctxt.event->id(), cont.name.c_str(), parts->size(), cont.key.mask(),
0289 parts->getTypeName().data());
0290 }
0291
0292 template <typename T> void
0293 DigiEdm4hepOutputProcessor::convert_depos(const T& cont,
0294 const predicate_t& predicate,
0295 edm4hep::TrackerHit3DCollection* collection) const
0296 {
0297 std::array<float,6> covMat = {0., 0., m_pointResoutionRPhi*m_pointResoutionRPhi,
0298 0., 0., m_pointResoutionZ*m_pointResoutionZ
0299 };
0300 for ( const auto& depo : cont ) {
0301 if ( predicate(depo) ) {
0302 data_io<edm4hep_input>::_to_edm4hep(depo, covMat, *collection, m_hit_type );
0303 }
0304 }
0305 }
0306
0307 template <typename T> void
0308 DigiEdm4hepOutputProcessor::convert_depos(const T& cont,
0309 const predicate_t& predicate,
0310 edm4hep::CalorimeterHitCollection* collection) const
0311 {
0312 for ( const auto& depo : cont ) {
0313 if ( predicate(depo) ) {
0314 data_io<edm4hep_input>::_to_edm4hep(depo, *collection, m_hit_type );
0315 }
0316 }
0317 }
0318
0319 template <typename T> void
0320 DigiEdm4hepOutputProcessor::convert_deposits(DigiContext& ctxt,
0321 const T& cont,
0322 const predicate_t& predicate) const
0323 {
0324 podio::CollectionBase* coll = internals->get_collection(cont);
0325 std::size_t start = coll->size();
0326 if ( !cont.empty() ) {
0327 switch(cont.data_type) {
0328 case SegmentEntry::TRACKER_HITS:
0329 convert_depos(cont, predicate, static_cast<edm4hep::TrackerHit3DCollection*>(coll));
0330 break;
0331 case SegmentEntry::CALORIMETER_HITS:
0332 convert_depos(cont, predicate, static_cast<edm4hep::CalorimeterHitCollection*>(coll));
0333 break;
0334 default:
0335 except("Error: Unknown energy deposit type: %d", int(cont.data_type));
0336 break;
0337 }
0338 }
0339 std::size_t end = coll->size();
0340 info("%s+++ %-24s added %6ld/%6ld entries from mask: %04X to %s",
0341 ctxt.event->id(), cont.name.c_str(), end-start, end, cont.key.mask(),
0342 coll->getTypeName().data());
0343 }
0344
0345 void DigiEdm4hepOutputProcessor::convert_history(DigiContext& ctxt,
0346 const DepositsHistory& cont,
0347 work_t& work,
0348 const predicate_t& predicate) const
0349 {
0350 info("%s+++ %-32s Segment: %d Predicate:%s Conversion to edm4hep not implemented!",
0351 ctxt.event->id(), cont.name.c_str(), int(work.input.segment->id),
0352 typeName(typeid(predicate)).c_str());
0353 }
0354
0355
0356 void DigiEdm4hepOutputProcessor::execute(DigiContext& ctxt, work_t& work, const predicate_t& predicate) const {
0357 if ( const auto* p = work.get_input<ParticleMapping>() )
0358 convert_particles(ctxt, *p);
0359 else if ( const auto* m = work.get_input<DepositMapping>() )
0360 convert_deposits(ctxt, *m, predicate);
0361 else if ( const auto* v = work.get_input<DepositVector>() )
0362 convert_deposits(ctxt, *v, predicate);
0363 else if ( const auto* h = work.get_input<DepositsHistory>() )
0364 convert_history(ctxt, *h, work, predicate);
0365 else
0366 except("Request to handle unknown data type: %s", work.input_type_name().c_str());
0367 }
0368
0369 }
0370 }
0371
0372
0373 #include <DDDigi/DigiFactories.h>
0374 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepOutput)
0375 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepOutputProcessor)