File indexing completed on 2026-09-22 08:03:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "DigiEdm4hepInput.h"
0016 #include "DigiIO.h"
0017
0018
0019 #include <podio/podioVersion.h>
0020 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0021 #include <podio/Reader.h>
0022 #elif PODIO_BUILD_VERSION >= PODIO_VERSION(0, 99, 0)
0023 #include <podio/ROOTReader.h>
0024 #else
0025 #include <podio/ROOTFrameReader.h>
0026 namespace podio {
0027 using ROOTReader = podio::ROOTFrameReader;
0028 }
0029 #endif
0030 #include <podio/Frame.h>
0031
0032 #include <edm4hep/SimTrackerHit.h>
0033 #include <edm4hep/SimCalorimeterHit.h>
0034 #include <edm4hep/MCParticleCollection.h>
0035 #include <edm4hep/EventHeaderCollection.h>
0036 #include <edm4hep/SimTrackerHitCollection.h>
0037 #include <edm4hep/SimCalorimeterHitCollection.h>
0038 #include <edm4hep/CaloHitContributionCollection.h>
0039
0040
0041 namespace dd4hep {
0042
0043
0044 namespace digi {
0045
0046
0047
0048
0049
0050
0051
0052
0053 class edm4hep_read_frame_t : public DigiInputAction::event_frame {
0054 public:
0055 podio::Frame frame { };
0056 edm4hep_read_frame_t(podio::Frame&& frm) : frame(std::move(frm)) { }
0057 const podio::CollectionBase* get(const std::string& nam) const { return frame.get(nam); }
0058 };
0059
0060 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0061 using reader_t = podio::Reader;
0062 #else
0063 using reader_t = podio::ROOTReader;
0064 #endif
0065 using frame_t = edm4hep_read_frame_t;
0066
0067
0068
0069
0070
0071
0072
0073
0074 class DigiEdm4hepInput::collection_t {
0075 public:
0076 int id;
0077 std::string name;
0078 collection_t(int i, const std::string& n) : id(i), name(n) { }
0079 };
0080
0081
0082
0083
0084
0085
0086
0087
0088 class DigiEdm4hepInput::work_t {
0089 public:
0090 DigiContext& context;
0091 DataSegment& segment;
0092 frame_t& frame;
0093 descriptor_t& descriptor;
0094 podio_coll_t* collection;
0095 };
0096
0097
0098
0099
0100
0101
0102
0103
0104 class DigiEdm4hepInput::source_t : public DigiInputAction::input_source {
0105 public:
0106
0107 std::unique_ptr<reader_t> stream { };
0108
0109 std::map<Key, collection_t> collections { };
0110
0111 std::string section { };
0112
0113 uint64_t entry { 0 };
0114
0115 public:
0116
0117 source_t(const std::string& s, std::unique_ptr<reader_t>&& str)
0118 : stream(std::move(str)), section(s) {
0119 }
0120
0121 ~source_t() {
0122 if ( stream ) {
0123 stream.reset();
0124 }
0125 }
0126
0127 bool done() const {
0128 auto total = stream->getEntries(section);
0129 if ( (1+entry) >= total ) {
0130 return true;
0131 }
0132 return false;
0133 }
0134
0135 std::shared_ptr<frame_t> next() {
0136 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0137 auto data = stream->readNextFrame(section);
0138 ++entry;
0139 return std::make_shared<frame_t>(std::move(data));
0140 #else
0141 auto data = stream->readNextEntry(section);
0142 if ( data ) {
0143 ++entry;
0144 return std::make_shared<frame_t>(std::move(data));
0145 }
0146 return {};
0147 #endif
0148 }
0149 };
0150
0151
0152
0153
0154
0155
0156
0157
0158 class DigiEdm4hepInput::internals_t {
0159 public:
0160 using input_t = std::unique_ptr<source_t>;
0161
0162
0163 DigiEdm4hepInput* parent { nullptr };
0164
0165 input_t m_source { };
0166
0167 int m_curr_input { INPUT_START };
0168
0169 public:
0170
0171 internals_t() = default;
0172
0173 std::unique_ptr<source_t> open_source();
0174
0175 std::shared_ptr<frame_t> next();
0176 };
0177
0178
0179 std::unique_ptr<DigiEdm4hepInput::source_t>
0180 DigiEdm4hepInput::internals_t::open_source() {
0181 const auto& inputs = parent->inputs();
0182 int len = inputs.size();
0183 if ( inputs.empty() ) m_curr_input = 0;
0184 while ( (m_curr_input+1) < len ) {
0185 const auto& fname = inputs[++m_curr_input];
0186 try {
0187 auto sec = parent->input_section();
0188 #if PODIO_BUILD_VERSION >= PODIO_VERSION(1, 0, 0)
0189 auto stream = std::make_unique<reader_t>(podio::makeReader(fname));
0190 #else
0191 auto stream = std::make_unique<reader_t>();
0192 stream->openFile(fname);
0193 #endif
0194 auto source = std::make_unique<source_t>(sec, std::move(stream));
0195 parent->info("+++ Opened EDM4HEP input file %s.", fname.c_str());
0196 parent->onOpenFile(*source);
0197 return source;
0198 }
0199 catch (const std::runtime_error& e) {
0200 parent->error("OpenInput ++ Failed to open input source %s [%s]", fname.c_str(), e.what());
0201 }
0202 }
0203 parent->except("+++ No open file present. Configuration error?");
0204 throw std::runtime_error("+++ No open file present");
0205 }
0206
0207
0208 std::shared_ptr<frame_t> DigiEdm4hepInput::internals_t::next() {
0209 if ( !m_source || m_source->done() || parent->fileLimitReached(*m_source) ) {
0210 m_source = open_source();
0211 if ( m_source ) {
0212 auto frame = m_source->next();
0213 if ( frame ) {
0214 auto table = frame->frame.getAvailableCollections();
0215 int id = 0, mask = parent->input_mask();
0216 for( const auto& nam : table ) {
0217 parent->info("+++ Collection id: %04X --> '%s'", id, nam.c_str());
0218 if ( parent->object_loading_is_enabled(nam) ) {
0219 Key key(nam, mask);
0220 m_source->collections.emplace( key, collection_t(id, nam) );
0221 }
0222 ++id;
0223 }
0224 parent->onProcessEvent(*m_source, *frame);
0225 return frame;
0226 }
0227 parent->except("+++ No valid frame present in file.");
0228 }
0229 parent->except("+++ No open file present. Aborting processing");
0230 }
0231 auto frame = m_source->next();
0232 parent->onProcessEvent(*m_source, *frame);
0233 return frame;
0234 }
0235
0236
0237 DigiEdm4hepInput::DigiEdm4hepInput(const DigiKernel& krnl, const std::string& nam)
0238 : DigiInputAction(krnl, nam)
0239 {
0240 internals = std::make_unique<internals_t>();
0241 internals->parent = this;
0242 m_trackerHitType = typeName(typeid(edm4hep::SimTrackerHitCollection));
0243 m_caloHitType = typeName(typeid(edm4hep::SimCalorimeterHitCollection));
0244 m_particlesType = typeName(typeid(edm4hep::MCParticleCollection));
0245 m_evtHeaderType = typeName(typeid(edm4hep::EventHeaderCollection));
0246 declareProperty("tracker_hits_type", m_trackerHitType);
0247 declareProperty("calorimeter_hits_type", m_caloHitType);
0248 declareProperty("particles_hits_type", m_particlesType);
0249 declareProperty("event_header_type", m_evtHeaderType);
0250 m_input_section = "events";
0251 }
0252
0253 template <typename HIT_TYPE, typename EDM4HEP_COLLECTION_TYPE>
0254 void DigiEdm4hepInput::hits_from_edm4hep(DigiContext& context,
0255 DataSegment& segment,
0256 Key::mask_type mask,
0257 const std::string& nam,
0258 const EDM4HEP_COLLECTION_TYPE* collection) const
0259 {
0260 DepositVector out(nam, mask, SegmentEntry::UNKNOWN);
0261 std::map<CellID, HIT_TYPE> hits;
0262 std::size_t len = 0;
0263 const DepositPredicate<EnergyCut> predicate ( { this->epsilon } );
0264 len = collection->size();
0265 data_io<edm4hep_input>()._to_digi_if(*collection, hits, predicate);
0266 data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), hits, out);
0267 info("%s+++ %-24s Converted %6ld Edm4hep %-14s to %6ld cell deposits",
0268 context.event->id(), nam.c_str(), len, collection->getValueTypeName().data(), out.size());
0269 put_data(segment, Key(out.name, mask), std::move(out));
0270 if ( m_keep_raw ) {
0271 put_data(segment, Key(nam+".edm4hep", mask, segment.id), std::move(hits));
0272 }
0273 }
0274
0275
0276 void DigiEdm4hepInput::parts_from_edm4hep(DigiContext& context,
0277 DataSegment& segment,
0278 int mask,
0279 const std::string& nam,
0280 const edm4hep::MCParticleCollection* collection) const
0281 {
0282 ParticleMapping transient(nam, mask);
0283 data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, transient);
0284 debug("%s+++ Converted %ld Edm4hep transient", context.event->id(), transient.size());
0285 put_data(segment, Key(nam, mask), std::move(transient));
0286 }
0287
0288
0289 void DigiEdm4hepInput::params_from_edm4hep(DigiContext& context,
0290 DataSegment& segment,
0291 int mask,
0292 const std::string& nam,
0293 const podio::Frame& frame,
0294 const edm4hep::EventHeaderCollection* collection) const
0295 {
0296 DataParameters parameters(nam, mask);
0297 data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, parameters);
0298 data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), frame.getParameters(), parameters);
0299 debug("%s+++ Converted %ld Edm4hep transient", context.event->id(), parameters.size());
0300 put_data(segment, Key(nam, mask), std::move(parameters));
0301 }
0302
0303
0304 void DigiEdm4hepInput::execute(DigiContext& context) const {
0305
0306 std::lock_guard<std::mutex> lock(context.global_io_lock());
0307 auto& event = context.event;
0308 auto frame = internals->next();
0309 DataSegment& segment = event->get_segment(m_input_segment);
0310
0311 for( auto& coll : internals->m_source->collections ) {
0312 const auto& nam = coll.second.name;
0313 const podio::CollectionBase* collection = frame->get(nam);
0314 if ( collection ) {
0315 work_t work { context, segment, *frame, coll, collection };
0316 (*this)(context, work);
0317 continue;
0318 }
0319 error("%s+++ Failed to load collection %s from edm4hep frame.",
0320 event->id(), nam.c_str());
0321 }
0322
0323 std::any frm(std::move(frame));
0324 segment.emplace_any(Key("podio_frame", input_mask()), std::move(frm));
0325 info("%s+++ Read event ", event->id());
0326 }
0327
0328
0329 void DigiEdm4hepInput::operator()(DigiContext& context, work_t& work) const {
0330 auto& seg = work.segment;
0331 auto& nam = work.descriptor.second.name;
0332 int msk = work.descriptor.first.mask();
0333 const auto* col = work.collection;
0334 const auto& typ = col->getTypeName();
0335
0336 if ( typ == m_caloHitType )
0337 hits_from_edm4hep<edm4hep::SimCalorimeterHit>(context, seg, msk, nam, static_cast<const edm4hep::SimCalorimeterHitCollection*>(col));
0338 else if ( typ == m_trackerHitType )
0339 hits_from_edm4hep<edm4hep::SimTrackerHit>(context, seg, msk, nam, static_cast<const edm4hep::SimTrackerHitCollection*>(col));
0340 else if ( typ == m_particlesType )
0341 parts_from_edm4hep(context, seg, msk, nam, static_cast<const edm4hep::MCParticleCollection*>(col));
0342 else if ( typ == m_evtHeaderType )
0343 params_from_edm4hep(context, seg, msk, nam, work.frame.frame, static_cast<const edm4hep::EventHeaderCollection*>(col));
0344 else
0345 except("Unknown data type encountered in branch: %s", nam.c_str());
0346 }
0347 }
0348 }
0349
0350
0351 #include <DDDigi/DigiFactories.h>
0352 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepInput)