Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:09

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 <DD4hep/InstanceCount.h>
0016 #include <DDDigi/DigiROOTInput.h>
0017 
0018 // ROOT include files
0019 #include <TROOT.h>
0020 #include <TFile.h>
0021 #include <TTree.h>
0022 
0023 using namespace dd4hep::digi;
0024 
0025 class DigiROOTInput::inputsource_t
0026   : public DigiInputAction::input_source, public DigiInputAction::event_frame  {
0027 public:
0028   /// Branches present in the current file
0029   std::map<Key, container_t> branches { };
0030   /// Reference to the current ROOT file to be read
0031   std::unique_ptr<TFile>     file     { nullptr };
0032   /// Reference to the ROOT tree to be read
0033   TTree*   tree   { nullptr };
0034   /// Current entry inside the current input source
0035   Long64_t entry  { -1 };
0036 
0037 public:
0038   /// Default constructor
0039   inputsource_t() = default;
0040   /// Default destructor
0041   ~inputsource_t() = default;
0042   /// Check if the input source is exhausted
0043   bool done()   const     {
0044     return (entry+1) >= tree->GetEntries();
0045   }
0046   inputsource_t& next()   {
0047     tree->LoadTree( ++entry );
0048     return *this;
0049   }
0050 };
0051 
0052 /// Helper class to hide internal ROOT stuff
0053 /**
0054  *
0055  *  \author  M.Frank
0056  *  \version 1.0
0057  *  \ingroup DD4HEP_DIGITIZATION
0058  */
0059 class DigiROOTInput::internals_t   {
0060 public:
0061   using source_t = std::unique_ptr<inputsource_t>;
0062   /// Reference to parent action
0063   DigiROOTInput* m_parent       { nullptr };
0064   /// Handle to input source
0065   source_t       m_source       { };
0066   /// Pointer to current input source
0067   int            m_curr_input   { INPUT_START };
0068 
0069 public:
0070   /// Default constructor
0071   internals_t (DigiROOTInput* p);
0072   /// Default destructor
0073   ~internals_t () = default;
0074   /// Access the next valid event entry
0075   inputsource_t& next();
0076   /// Open the next input source from the input list
0077   std::unique_ptr<inputsource_t> open_source();
0078 };
0079 
0080 /// Default constructor
0081 DigiROOTInput::internals_t::internals_t (DigiROOTInput* p)
0082   : m_parent(p)
0083 {
0084 }
0085 
0086 /// Open the next input source from the input list
0087 std::unique_ptr<DigiROOTInput::inputsource_t> DigiROOTInput::internals_t::open_source()   {
0088   const auto& inputs    = m_parent->inputs();
0089   const auto& tree_name = m_parent->input_section();
0090   int len = inputs.size();
0091 
0092   if ( inputs.empty() ) m_curr_input = 0;
0093   while ( (m_curr_input+1) < len )   {
0094     const auto& fname = inputs[++m_curr_input];
0095     std::unique_ptr<TFile> file(TFile::Open(fname.c_str()));
0096     if ( file && file->IsZombie() )  {
0097       file.reset();
0098       m_parent->error("OpenInput ++ Failed to open input source %s", fname.c_str());
0099     }
0100     else if ( file )  {
0101       auto* tree = (TTree*)file->Get(tree_name.c_str());
0102       if ( !tree )   {
0103     m_parent->error("OpenInput ++ Failed to access tree: %s in input: %s", 
0104             tree_name.c_str(), fname.c_str());
0105     continue;
0106       }
0107       Int_t total = tree->GetEntries();
0108       if ( total <= 0 )   {
0109     m_parent->error("OpenInput ++ TTree %s exists, but has no data. input: %s", 
0110             tree_name.c_str(), fname.c_str());
0111     continue;
0112       }
0113       auto source   = std::make_unique<inputsource_t>();
0114       source->file  = std::move(file);
0115       source->tree  = tree;
0116       auto* branches = tree->GetListOfBranches();
0117       int mask = m_parent->input_mask();
0118       TObjArrayIter it(branches);
0119       for(Int_t i=0; i < branches->GetEntriesFast(); ++i)   {
0120     TBranch*  b = (TBranch*)branches->At(i);
0121     if ( m_parent->object_loading_is_enabled(b->GetName()) )   {
0122       TClass* cls = gROOT->GetClass( b->GetClassName(), kTRUE );
0123       Key key(b->GetName(), mask);
0124       b->SetAutoDelete(kFALSE);
0125       source->branches.emplace(key, container_t(key, *b, *cls));
0126     }
0127       }
0128       if ( source->branches.empty() )    {
0129     m_parent->except("+++ No branches to be loaded. Configuration error!");
0130       }
0131       m_parent->onOpenFile(*source);
0132       return source;
0133     }
0134   }
0135   m_parent->except("+++ No open file present. Configuration error?");
0136   return {};
0137 }
0138 
0139 /// Access the next event from the sequence of input files
0140 DigiROOTInput::inputsource_t& DigiROOTInput::internals_t::next()   {
0141   if ( !m_source || m_source->done() || m_parent->fileLimitReached(*m_source) )    {
0142     m_source = open_source();
0143   }
0144   auto& src = m_source->next();
0145   m_parent->onProcessEvent(src, src);
0146   return src;
0147 }
0148 
0149 /// Standard constructor
0150 DigiROOTInput::DigiROOTInput(const DigiKernel& kernel, const std::string& nam)
0151   : DigiInputAction(kernel, nam)
0152 {
0153   imp = std::make_unique<internals_t>(this);
0154   InstanceCount::increment(this);
0155 }
0156 
0157 /// Default destructor
0158 DigiROOTInput::~DigiROOTInput()   {
0159   imp.reset();
0160   InstanceCount::decrement(this);
0161 }
0162 
0163 /// Pre-track action callback
0164 void DigiROOTInput::execute(DigiContext& context)  const   {
0165   //
0166   //  We have to lock all ROOT based actions. Consequences are SEGV otherwise.
0167   //
0168   std::lock_guard<std::mutex> lock(context.global_io_lock());
0169   auto& event = context.event;
0170   auto& source = imp->next();
0171   std::size_t input_len = 0;
0172 
0173   /// We only get here with a valid input
0174   DataSegment& segment = event->get_segment(m_input_segment);
0175   for( auto& b : source.branches )    {
0176     auto& ent = b.second;
0177     Long64_t bytes = ent.branch.GetEntry( source.entry );
0178     if ( bytes > 0 )  {
0179       work_t work { segment, ent };
0180       (*this)(context, work);
0181       input_len += bytes;
0182     }
0183     debug("%s+++ Loaded %8ld bytes from branch %s", event->id(), bytes, ent.branch.GetName());
0184   }
0185   info("%s+++ Read event %6ld [%ld bytes] from tree %s file: %s",
0186        event->id(), source.entry, input_len, source.tree->GetName(), source.file->GetName());
0187 }