Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:17:10

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(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 /// Namespace for the AIDA detector description toolkit
0039 namespace dd4hep {
0040 
0041   /// Namespace for the Digitization part of the AIDA detector description toolkit
0042   namespace digi {
0043 
0044     /// EDM4HEP event frame wrapper
0045     /**
0046      *
0047      *  \author  M.Frank
0048      *  \version 1.0
0049      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Collection descriptor definition
0062     /**
0063      *
0064      *  \author  M.Frank
0065      *  \version 1.0
0066      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Work item definition
0076     /**
0077      *
0078      *  \author  M.Frank
0079      *  \version 1.0
0080      *  \ingroup DD4HEP_DIGITIZATION
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     /// EDM4HEP Digi input reader: Input source definition
0092     /**
0093      *
0094      *  \author  M.Frank
0095      *  \version 1.0
0096      *  \ingroup DD4HEP_DIGITIZATION
0097      */
0098     class DigiEdm4hepInput::source_t : public DigiInputAction::input_source   {
0099     public:
0100       /// Reference to the reader object
0101       std::unique_ptr<reader_t>   stream      { };
0102       /// Collections present in the current file
0103       std::map<Key, collection_t> collections { };
0104       /// Input source section
0105       std::string                 section     { };
0106       /// Current entry inside the current input source
0107       uint64_t                    entry       { 0 };
0108 
0109     public:
0110       /// Initializing constructor
0111       source_t(const std::string& s, std::unique_ptr<reader_t>&& str) 
0112     : stream(std::move(str)), section(s)  {
0113       }
0114       /// Default destructor
0115       ~source_t()   {
0116     if ( stream )    {
0117       stream.reset();
0118     }
0119       }
0120       /// Check for end of the event sequence
0121       bool done() const   {
0122     auto total = stream->getEntries(section);
0123     if ( (1+entry) >= total )   {
0124       return true;
0125     }
0126     return false;
0127       }
0128       /// Access the next data frame in the input sequence
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     /// EDM4HEP Digi input reader: Internal data definition
0140     /**
0141      *
0142      *  \author  M.Frank
0143      *  \version 1.0
0144      *  \ingroup DD4HEP_DIGITIZATION
0145      */
0146     class DigiEdm4hepInput::internals_t  {
0147     public:
0148       using input_t = std::unique_ptr<source_t>;
0149 
0150       /// Reference to the parent object
0151       DigiEdm4hepInput* parent { nullptr };
0152       /// Handle to input source
0153       input_t           m_source { };
0154       /// Pointer to current input source
0155       int               m_curr_input   { INPUT_START };
0156 
0157     public:
0158       /// Initializing constructor
0159       internals_t() = default;
0160       /// Open the next input source from the input list
0161       std::unique_ptr<source_t> open_source();
0162       /// Access the next event from the sequence of input files
0163       std::shared_ptr<frame_t> next();
0164     };
0165 
0166     /// Open the next input source from the input list
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     /// Access the next event record. If the courrent source is exhausted, open next source
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     /// Initializing constructor
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     /// Generic conversion function for MC particles
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     /// Generic conversion function for event parameter settings
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     /// Pre-track action callback
0288     void DigiEdm4hepInput::execute(DigiContext& context)  const   {
0289       //  Lock all ROOT based actions. SEGV otherwise.
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       /// Add frame to segment: Need to keep reference of the input data!
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     /// Callback to handle single branch
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   }    // End namespace digi
0332 }      // End namespace dd4hep
0333 
0334 /// Factory instantiation
0335 #include <DDDigi/DigiFactories.h>
0336 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepInput)