Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-22 08:03:05

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include "DigiEdm4hepInput.h"
0016 #include "DigiIO.h"
0017 
0018 // podio/edm4hep include files
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 /// Namespace for the AIDA detector description toolkit
0041 namespace dd4hep {
0042 
0043   /// Namespace for the Digitization part of the AIDA detector description toolkit
0044   namespace digi {
0045 
0046     /// EDM4HEP event frame wrapper
0047     /**
0048      *
0049      *  \author  M.Frank
0050      *  \version 1.0
0051      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Collection descriptor definition
0068     /**
0069      *
0070      *  \author  M.Frank
0071      *  \version 1.0
0072      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Work item definition
0082     /**
0083      *
0084      *  \author  M.Frank
0085      *  \version 1.0
0086      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Input source definition
0098     /**
0099      *
0100      *  \author  M.Frank
0101      *  \version 1.0
0102      *  \ingroup DD4HEP_DIGITIZATION
0103      */
0104     class DigiEdm4hepInput::source_t : public DigiInputAction::input_source   {
0105     public:
0106       /// Reference to the reader object
0107       std::unique_ptr<reader_t>   stream      { };
0108       /// Collections present in the current file
0109       std::map<Key, collection_t> collections { };
0110       /// Input source section
0111       std::string                 section     { };
0112       /// Current entry inside the current input source
0113       uint64_t                    entry       { 0 };
0114 
0115     public:
0116       /// Initializing constructor
0117       source_t(const std::string& s, std::unique_ptr<reader_t>&& str) 
0118     : stream(std::move(str)), section(s)  {
0119       }
0120       /// Default destructor
0121       ~source_t()   {
0122     if ( stream )    {
0123       stream.reset();
0124     }
0125       }
0126       /// Check for end of the event sequence
0127       bool done() const   {
0128     auto total = stream->getEntries(section);
0129     if ( (1+entry) >= total )   {
0130       return true;
0131     }
0132     return false;
0133       }
0134       /// Access the next data frame in the input sequence
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     /// EDM4HEP Digi input reader: Internal data definition
0152     /**
0153      *
0154      *  \author  M.Frank
0155      *  \version 1.0
0156      *  \ingroup DD4HEP_DIGITIZATION
0157      */
0158     class DigiEdm4hepInput::internals_t  {
0159     public:
0160       using input_t = std::unique_ptr<source_t>;
0161 
0162       /// Reference to the parent object
0163       DigiEdm4hepInput* parent { nullptr };
0164       /// Handle to input source
0165       input_t           m_source { };
0166       /// Pointer to current input source
0167       int               m_curr_input   { INPUT_START };
0168 
0169     public:
0170       /// Initializing constructor
0171       internals_t() = default;
0172       /// Open the next input source from the input list
0173       std::unique_ptr<source_t> open_source();
0174       /// Access the next event from the sequence of input files
0175       std::shared_ptr<frame_t> next();
0176     };
0177 
0178     /// Open the next input source from the input list
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     /// Access the next event record. If the courrent source is exhausted, open next source
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     /// Initializing constructor
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     /// Generic conversion function for MC particles
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     /// Generic conversion function for event parameter settings
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     /// Pre-track action callback
0304     void DigiEdm4hepInput::execute(DigiContext& context)  const   {
0305       //  Lock all ROOT based actions. SEGV otherwise.
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       /// Add frame to segment: Need to keep reference of the input data!
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     /// Callback to handle single branch
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   }    // End namespace digi
0348 }      // End namespace dd4hep
0349 
0350 /// Factory instantiation
0351 #include <DDDigi/DigiFactories.h>
0352 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepInput)