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