Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:20

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 #ifndef DDDIGI_DIGICONTAINERPROCESSOR_H
0014 #define DDDIGI_DIGICONTAINERPROCESSOR_H
0015 
0016 // Framework include files
0017 #include <DD4hep/Callback.h>
0018 #include <DDDigi/DigiData.h>
0019 #include <DDDigi/DigiEventAction.h>
0020 #include <DDDigi/DigiDepositMonitor.h>
0021 #include <DDDigi/DigiParallelWorker.h>
0022 
0023 /// C/C++ include files
0024 #include <set>
0025 
0026 /// Namespace for the AIDA detector description toolkit
0027 namespace dd4hep {
0028 
0029   /// Namespace for the Digitization part of the AIDA detector description toolkit
0030   namespace digi {
0031 
0032     /// Forward declarations
0033     class DigiDepositMonitor;
0034     class DigiSegmentContext;
0035     class DigiContainerSequence;
0036     class DigiContainerProcessor;
0037     class DigiContainerSequenceAction;
0038     class DigiMultiContainerProcessor;
0039     
0040     /// Worker base class to analyse containers from the input segment in parallel
0041     /**
0042      *
0043      *  \author  M.Frank
0044      *  \version 1.0
0045      *  \ingroup DD4HEP_DIGITIZATION
0046      */
0047     class DigiContainerProcessor : public DigiAction   {
0048     public:
0049       /// Structure imports
0050       using action_t       = DigiAction;
0051       using segment_t      = DataSegment;
0052       using property_t     = PropertyManager;
0053       using segmentation_t = DigiSegmentContext;
0054 
0055       /// Input definition
0056       struct input_t  {
0057         /// Input segment reference
0058         segment_t*      segment;
0059         /// Input data key
0060         Key             key;
0061         /// Input deposits
0062         std::any*       data;
0063       };
0064 
0065       /// Output handle definition
0066       struct output_t  {
0067         int             mask;
0068         segment_t&      data;
0069       };
0070 
0071       /// Hit processing predicate
0072       struct predicate_t  {
0073         using deposit_t  = std::pair<const CellID, EnergyDeposit>;
0074         using callback_t = std::function<bool(const deposit_t&)>;
0075         callback_t            callback      { };
0076         uint32_t              id            { 0 };
0077         const segmentation_t* segmentation  { nullptr };
0078 
0079         predicate_t() = default;
0080         predicate_t(std::function<bool(const deposit_t&)> func, uint32_t i, const segmentation_t* s)
0081           : callback(std::move(func)), id(i), segmentation(s) {}
0082         predicate_t(predicate_t&& copy) = default;
0083         predicate_t(const predicate_t& copy) = default;
0084         predicate_t& operator = (predicate_t&& copy) = default;
0085         predicate_t& operator = (const predicate_t& copy) = default;
0086         /// Check if a deposit should be processed
0087         bool operator()(const deposit_t& deposit)   const;
0088         static bool always_true(const deposit_t&)        { return true; }
0089         static bool not_killed (const deposit_t& depo)   { return 0 == (depo.second.flag&EnergyDeposit::KILLED); }
0090       };
0091 
0092       struct env_t   {
0093         /// Event processing context
0094         context_t&        context;
0095         /// Optional properties
0096         const property_t& properties;
0097         /// Output data
0098         output_t&         output;
0099       };
0100 
0101       /// Work definition
0102       struct work_t  {
0103         env_t             environ;
0104         /// Input data
0105         input_t           input;
0106 
0107         /// Basic check if input data are present
0108         bool has_input()  const    {  return this->input.data->has_value();  }
0109         /// Access key of input data
0110         Key  input_key()  const    {  return this->input.key;               }
0111         /// Access the input data type
0112         const std::type_info& input_type()  const;
0113         /// String form of the input data type
0114         std::string input_type_name()  const;
0115         /// Access input data by type
0116         template <typename DATA> DATA* get_input(bool exc=false);
0117         /// Access input data by type
0118         template <typename DATA> const DATA* get_input(bool exc=false)  const;
0119       };
0120 
0121       /// Monitoring object
0122       DigiDepositMonitor* m_monitor { nullptr };
0123 
0124     protected:
0125       /// Define standard assignments and constructors
0126       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerProcessor);
0127 
0128     public:
0129       /// Access to default deposit predicate accepting all
0130       static const predicate_t& accept_all();
0131       /// Access to default deposit predicate accepting all
0132       static const predicate_t& accept_not_killed();
0133 
0134       /// Standard constructor
0135       DigiContainerProcessor(const kernel_t& kernel, const std::string& name);
0136       /// Default destructor
0137       virtual ~DigiContainerProcessor();
0138       /// Adopt monitoring action
0139       virtual void adopt_monitor(DigiDepositMonitor* monitor);
0140       /// Main functional callback adapter
0141       virtual void execute(context_t& context, work_t& work, const predicate_t& predicate)  const;
0142     };
0143 
0144     /// Check if a deposit should be processed
0145     inline bool DigiContainerProcessor::predicate_t::operator()(const deposit_t& deposit)   const   {
0146       return this->callback(deposit);
0147     }
0148 
0149     /// Worker class act on ONLY act on energy deposit containers in an event
0150     /**
0151      *  Worker class act on ONLY act on energy deposit containers in an event.
0152      *  The deposit containers are identified by input masks and container name.
0153      *
0154      *  \author  M.Frank
0155      *  \version 1.0
0156      *  \ingroup DD4HEP_DIGITIZATION
0157      */
0158     class DigiDepositsProcessor : public DigiContainerProcessor  {
0159     protected:
0160       std::function<void(context_t& context, DepositVector& cont,  work_t& work, const predicate_t& predicate)> m_handleVector;
0161       std::function<void(context_t& context, DepositMapping& cont, work_t& work, const predicate_t& predicate)> m_handleMapping;
0162 
0163     public:
0164       /// Standard constructor
0165       using DigiContainerProcessor::DigiContainerProcessor;
0166 
0167       /// Main functional callback adapter
0168       virtual void execute(context_t& context, work_t& work, const predicate_t& predicate)  const;
0169     };
0170     
0171 #define DEPOSIT_PROCESSOR_BIND_HANDLERS(X)                              \
0172     this->m_handleVector  = std::bind( &X<DepositVector>,  this,        \
0173                                        std::placeholders::_1,           \
0174                                        std::placeholders::_2,           \
0175                                        std::placeholders::_3,           \
0176                                        std::placeholders::_4);          \
0177     this->m_handleMapping = std::bind( &X<DepositMapping>, this,        \
0178                                        std::placeholders::_1,           \
0179                                        std::placeholders::_2,           \
0180                                        std::placeholders::_3,           \
0181                                        std::placeholders::_4)
0182 
0183     /// Worker class act on containers in an event identified by input masks and container name
0184     /**
0185      *  The sequencer calls all registered processors for the contaiers registered.
0186      *
0187      *  \author  M.Frank
0188      *  \version 1.0
0189      *  \ingroup DD4HEP_DIGITIZATION
0190      */
0191     class DigiContainerSequence : public DigiContainerProcessor  {
0192     protected:
0193       /// Structure imports
0194       using self_t      = DigiContainerSequence;
0195       using processor_t = DigiContainerProcessor;
0196       using worker_t    = DigiParallelWorker<processor_t,work_t,std::size_t,self_t&>;
0197       using workers_t   = DigiParallelWorkers<worker_t>;
0198       friend class DigiParallelWorker<processor_t,work_t,std::size_t,self_t&>;
0199 
0200     protected:
0201       /**  Member variables                           */
0202       /// Property to steer parallel processing
0203       bool               m_parallel { false };
0204       /// Array of sub-workers
0205       workers_t          m_workers;
0206       /// Default Deposit predicate
0207       predicate_t        m_worker_predicate = processor_t::accept_all();
0208 
0209       /// Lock for output merging
0210       mutable std::mutex m_output_lock;
0211 
0212     protected:
0213       /// Define standard assignments and constructors
0214       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerSequence);
0215       /// Default destructor
0216       virtual ~DigiContainerSequence();
0217 
0218       /// Get hold of the registered processor for a given container
0219       worker_t* need_registered_worker(Key item_key)  const;
0220 
0221     public:
0222       /// Standard constructor
0223       DigiContainerSequence(const kernel_t& kernel, const std::string& name);
0224       /// Set the default predicate
0225       virtual void set_predicate(const predicate_t& predicate);
0226       /// Adopt new parallel worker
0227       virtual void adopt_processor(DigiContainerProcessor* action);
0228       /// Main functional callback adapter
0229       virtual void execute(context_t& context, work_t& work, const predicate_t& predicate)  const;
0230     };
0231 
0232 
0233     struct DigiMultiProcessorParent   {
0234     public:
0235       using action_t     = DigiAction;
0236       using processor_t  = DigiContainerProcessor;
0237       using env_t        = processor_t::env_t;
0238       using segment_t    = processor_t::segment_t;
0239       using predicate_t  = processor_t::predicate_t;
0240       using output_t     = processor_t::output_t;
0241       using property_t   = processor_t::property_t;
0242       using work_item_t  = processor_t::input_t;
0243       using work_items_t = std::vector<processor_t::input_t>;
0244     };
0245 
0246     /// Worker base class to analyse containers from the input segment in parallel
0247     /**
0248      *  Depending on the adopted processors, the full input record is scanned and
0249      *  the registered processors are called.
0250      *
0251      *  \author  M.Frank
0252      *  \version 1.0
0253      *  \ingroup DD4HEP_DIGITIZATION
0254      */
0255     class DigiContainerSequenceAction : public DigiEventAction, public DigiMultiProcessorParent  {
0256 
0257     protected:
0258       /// Structure imports
0259       using self_t      = DigiContainerSequenceAction;
0260       /// Work definition structure: Argument structure for client calls
0261       struct work_t  {
0262         env_t&        environ;
0263         work_items_t& input_items;
0264         const self_t& parent;
0265       };
0266 
0267       using worker_t         = DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>;
0268       using workers_t        = DigiParallelWorkers<worker_t>;
0269       using predicate_t      = processor_t::predicate_t;
0270       using reg_workers_t    = std::map<Key::key_type, worker_t*>;
0271       using reg_processors_t = std::map<Key::key_type, processor_t*>;
0272       friend class DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>;
0273 
0274       /// Property: Input data segment name
0275       std::string              m_input_segment         { "inputs" };
0276       /// Property: Input mask to be handled
0277       int                      m_input_mask            { 0x0 };
0278       /// Property: Input data segment name
0279       std::string              m_output_segment        { "outputs" };
0280       /// Property: event mask for output data
0281       int                      m_output_mask           { 0x0 };
0282 
0283       /// Array of sub-workers
0284       workers_t                m_workers               { };
0285       /// Registered action map
0286       reg_processors_t         m_registered_processors { };
0287       /// Registered worker map
0288       reg_workers_t            m_registered_workers    { };
0289       /// Default Deposit predicate
0290       predicate_t              m_worker_predicate      { processor_t::accept_all() };
0291 
0292       /// Lock for output merging
0293       mutable std::mutex       m_output_lock           { };
0294       
0295     protected:
0296       /// Define standard assignments and constructors
0297       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerSequenceAction);
0298 
0299       /// Default destructor
0300       virtual ~DigiContainerSequenceAction();
0301 
0302       /// Initialization callback
0303       virtual void initialize();
0304 
0305       /// Finalization callback
0306       virtual void finalize();
0307 
0308       /// Get hold of the registered processor for a given container
0309       worker_t* need_registered_worker(Key item_key, bool exc=true)  const;
0310 
0311     public:
0312       /// Standard constructor
0313       DigiContainerSequenceAction(const kernel_t& kernel, const std::string& name);
0314       /// Set the default predicate
0315       virtual void set_predicate(const predicate_t& predicate);
0316       /// Adopt new parallel worker acting on one single container
0317       virtual void adopt_processor(DigiContainerProcessor* action, const std::string& container);
0318       /// Adopt new parallel worker acting on multiple containers
0319       virtual void adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers);
0320       /// Main functional callback if specific work is known
0321       virtual void execute(context_t& context)  const override;
0322     };
0323 
0324     /// Sequencer class to analyse containers from the input segment in parallel
0325     /**
0326      *
0327      *  \author  M.Frank
0328      *  \version 1.0
0329      *  \ingroup DD4HEP_DIGITIZATION
0330      */
0331     class DigiMultiContainerProcessor : public DigiEventAction, public DigiMultiProcessorParent   {
0332     protected:
0333       using self_t        = DigiMultiContainerProcessor;
0334       using worker_keys_t = std::vector<std::vector<Key> >;
0335 
0336       /// Argument structure required to support multiple client calls
0337       struct work_t  {
0338         env_t&              environ;
0339         work_items_t&       items;
0340         const self_t&       parent;
0341       };
0342       using worker_t      = DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>;
0343       using workers_t     = DigiParallelWorkers<worker_t>;
0344       friend class DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>;
0345 
0346     protected:
0347       /// Property: Input data segment name
0348       std::string        m_input_segment  { "inputs" };
0349       /// Property: event masks to be handled
0350       std::vector<int>   m_input_masks    { };
0351       /// Property: Input data segment name
0352       std::string        m_output_segment { "outputs" };
0353       /// Property: event mask for output data
0354       int                m_output_mask    { 0x0 };
0355 
0356       /// Set of container names to be used by this processor
0357       std::map<std::string, std::vector<processor_t*> >    m_processors;
0358       std::map<Key::itemkey_type, std::vector<worker_t*> > m_worker_map;
0359 
0360       /// Set of work items to be processed and passed to clients
0361       std::set<Key>             m_work_items;
0362       /// Set of keys required by each worker
0363       worker_keys_t             m_worker_keys;
0364       /// Ordered list of actions registered
0365       std::vector<processor_t*> m_actions;
0366       /// Default Deposit predicate
0367       predicate_t               m_worker_predicate = processor_t::accept_all();
0368       /// Lock for output merging
0369       mutable std::mutex        m_output_lock;
0370 
0371       /// Array of sub-workers
0372       workers_t                 m_workers;
0373 
0374     protected:
0375       /// Define standard assignments and constructors
0376       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiMultiContainerProcessor);
0377       /// Default destructor
0378       virtual ~DigiMultiContainerProcessor();
0379       /// Initialize action object
0380       void initialize();
0381 
0382     public:
0383       /// Standard constructor
0384       DigiMultiContainerProcessor(const kernel_t& kernel, const std::string& name);
0385       const std::vector<Key>& worker_keys(size_t worker_id)  const  {
0386         return this->m_worker_keys.at(worker_id);
0387       }
0388       const std::vector<int>& input_masks()  const   {
0389         return this->m_input_masks;
0390       }
0391       /// Set the default predicate
0392       virtual void set_predicate(const predicate_t& predicate);
0393       /// Adopt new parallel worker
0394       virtual void adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers);
0395       /// Main functional callback
0396       virtual void execute(context_t& context)  const;
0397     };
0398   }    // End namespace digi
0399 }      // End namespace dd4hep
0400 #endif // DDDIGI_DIGICONTAINERPROCESSOR_H