diff --git a/DDDigi/include/DDDigi/DigiAttenuator.h b/DDDigi/include/DDDigi/DigiAttenuator.h index 8ab5834986062324c7d2cfe725f6482fcb8a3dfd..4082a7084e8e8a560107313ec1916b44475b47d2 100644 --- a/DDDigi/include/DDDigi/DigiAttenuator.h +++ b/DDDigi/include/DDDigi/DigiAttenuator.h @@ -13,12 +13,8 @@ #ifndef DDDIGI_DIGIATTENUATOR_H #define DDDIGI_DIGIATTENUATOR_H -/// Framework include files -#include <DDDigi/DigiAction.h> -#include <DDDigi/DigiSignalProcessor.h> - -/// C/C++ include files -#include <functional> +// Framework include files +#include <DDDigi/DigiContainerProcessor.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -26,30 +22,85 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - /// Base class for attenuator actions to the digitization + /// Tool to compute decay time of the signal for spillover + /** + * The following signal decays are supported: + * -- Exponential decay depending on time offset(t0) and mean signal decay time + * -- more to be added + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiAttenuationTool { + public: + /// Exponential decay depending on time offset(t0) and mean signal decay time + double exponential(double t0, double decay_time) const; + }; + + /// Default base class for all Digitizer actions and derivates thereof. /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiAttenuator : public DigiSignalProcessor { + class DigiAttenuator : public DigiContainerProcessor { + protected: + /// Signal reduction factor + double m_factor { 1.0 }; + protected: /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuator); - /// Function object to be executed - std::function<double(const DigiCellData&)> processor; + /// Default destructor + virtual ~DigiAttenuator(); + /// Attenuator callback for single container + template <typename T> std::size_t attenuate(T& cont) const; + public: /// Standard constructor DigiAttenuator(const DigiKernel& kernel, const std::string& nam); - /// Default destructor - virtual ~DigiAttenuator(); - /// Callback to read event attenuator - virtual double operator()(const DigiCellData& data) const { - return processor(data); - } + /// Main functional callback adapter + virtual void execute(DigiContext& context, work_t& work) const override; }; + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiAttenuatorSequence : public DigiContainerSequenceAction { + protected: + /// Property: Data processor type + std::string m_processor_type { }; + /// Property: Signal decay algorithm + std::string m_signal_decay { }; + /// Property: Container names to be loaded + std::map<std::string, double> m_container_attenuation { }; + /// Property: T0 with respect to central crossing + double m_t0 { 0e0 }; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuatorSequence); + /// Default destructor + virtual ~DigiAttenuatorSequence(); + + public: + /// Standard constructor + DigiAttenuatorSequence(const DigiKernel& kernel, const std::string& nam); + /// Initialization callback + virtual void initialize(); + /// Main functional callback + virtual void execute(DigiContext& context) const; + }; } // End namespace digi } // End namespace dd4hep #endif // DDDIGI_DIGIATTENUATOR_H diff --git a/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h b/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h deleted file mode 100644 index 3e27c14bb596027546355a444e38606f83a0ea45..0000000000000000000000000000000000000000 --- a/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h +++ /dev/null @@ -1,66 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== -#ifndef DDDIGI_DIGIATTENUATORSEQUENCEACTION_H -#define DDDIGI_DIGIATTENUATORSEQUENCEACTION_H - -// Framework include files -#include <DDDigi/DigiEventAction.h> - -/// Namespace for the AIDA detector description toolkit -namespace dd4hep { - - /// Namespace for the Digitization part of the AIDA detector description toolkit - namespace digi { - - /// Default base class for all Digitizer actions and derivates thereof. - /** - * This is a utility class supporting properties, output and access to - * event and run objects through the context. - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class DigiAttenuatorSequenceAction : public DigiEventAction { - protected: - /// Property: Input data segment name - std::string m_processor_name { }; - /// Property: Input data segment name - std::string m_input_segment { }; - /// Property: Container names to be loaded - std::map<std::string, double> m_container_attenuation { }; - /// Property: event mask to be handled - int m_mask { 0 }; - /// Property: T0 with respect to central crossing - double m_t0 { 0e0 }; - - /// Keys of all containers to be manipulated - std::map<Key, double> m_attenuation { }; - - protected: - /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuatorSequenceAction); - /// Default destructor - virtual ~DigiAttenuatorSequenceAction(); - - public: - /// Standard constructor - DigiAttenuatorSequenceAction(const DigiKernel& kernel, const std::string& nam); - /// Initialization callback - virtual void initialize(); - /// Main functional callback - virtual void execute(DigiContext& context) const; - }; - } // End namespace digi -} // End namespace dd4hep -#endif // DDDIGI_DIGIATTENUATORSEQUENCEACTION_H diff --git a/DDDigi/include/DDDigi/DigiContainerProcessor.h b/DDDigi/include/DDDigi/DigiContainerProcessor.h index d90741c311f833da7c4ca7a56bc5f3bb580ff9a3..075848e245755e91def3e1e96a90c851de2f7d5b 100644 --- a/DDDigi/include/DDDigi/DigiContainerProcessor.h +++ b/DDDigi/include/DDDigi/DigiContainerProcessor.h @@ -42,22 +42,57 @@ namespace dd4hep { */ class DigiContainerProcessor : public DigiAction { public: - struct work_t { - /// Event processing context - DigiContext& context; + using segment_t = DataSegment; + struct input_t { /// Input data key Key key; /// Input deposits - std::any& input; + std::any& data; + }; + struct output_t { /// Lock for secure output merging - std::mutex& output_lock; + //std::mutex& lock; /// Handle to output - std::any& output; + //std::any& data; + int mask; + segment_t& data; + }; + + struct work_t { + /// Event processing context + DigiContext& context; + /// Input data + input_t input; + /// Output data + output_t& output; + + /// Basic check if input data are present + bool has_input() const { return this->input.data.has_value(); } + /// Access key of input data + Key input_key() const { return this->input.key; } + /// Access the input data type + const std::type_info& input_type() const; + /// String form of the input data type + std::string input_type_name() const; + /// Access input data by type + template <typename DATA> DATA* get_input(bool exc=false); + /// Access input data by type + template <typename DATA> const DATA* get_input(bool exc=false) const; +#if 0 + /// Basic check if input data are present + bool has_output() const { return this->output.data.has_value(); } + /// String form of the output data type + std::string output_type_name() const; + /// Access the output data type + const std::type_info& output_type() const; + /// Access output data by type + template <typename DATA> DATA* get_output(); /// Merge output data (thread safe, locked) void merge_output(DepositVector&& data); /// Merge output data (thread safe, locked) void emplace_output(CellID cell, EnergyDeposit&& deposit); +#endif }; protected: /// Define standard assignments and constructors @@ -86,21 +121,20 @@ namespace dd4hep { */ class DigiContainerSequence : public DigiContainerProcessor { protected: - /// Property to steer parallel processing - bool m_parallel { false }; - - protected: - using self_t = DigiContainerSequence; + using self_t = DigiContainerSequence; using processor_t = DigiContainerProcessor; - using worker_t = DigiParallelWorker<processor_t,work_t>; - using workers_t = DigiParallelWorkers<worker_t>; + using worker_t = DigiParallelWorker<processor_t,work_t>; + using workers_t = DigiParallelWorkers<worker_t>; friend class DigiParallelWorker<processor_t,work_t>; - /// Array of sub-workers - workers_t m_workers; + protected: + /// Property to steer parallel processing + bool m_parallel { false }; + /// Array of sub-workers + workers_t m_workers; /// Lock for output merging - mutable std::mutex m_output_lock; + mutable std::mutex m_output_lock; protected: /// Define standard assignments and constructors @@ -130,8 +164,9 @@ namespace dd4hep { protected: /// Argument structure for client calls - using self_t = DigiContainerSequenceAction; + using self_t = DigiContainerSequenceAction; using processor_t = DigiContainerProcessor; + using output_t = processor_t::output_t; struct work_item_t { Key key; std::any* data; @@ -139,9 +174,7 @@ namespace dd4hep { struct work_t { DigiContext& context; std::vector<work_item_t> input_items; - /// Lock for secure output merging - std::mutex& output_lock; - std::any output; + output_t& output; const self_t* parent; }; using worker_t = DigiParallelWorker<processor_t, work_t>; @@ -151,19 +184,23 @@ namespace dd4hep { friend class DigiParallelWorker<processor_t, work_t>; /// Array of sub-workers - workers_t m_workers; + workers_t m_workers; /// Registered action map - reg_processors_t m_registered_processors; + reg_processors_t m_registered_processors; /// Registered worker map - reg_workers_t m_registered_workers; + reg_workers_t m_registered_workers; /// Property: Input data segment name - std::string m_input_segment { "inputs" }; + std::string m_input_segment { "inputs" }; /// Property: Input mask to be handled - int m_mask { 0x0 }; + int m_input_mask { 0x0 }; + /// Property: Input data segment name + std::string m_output_segment { "outputs" }; + /// Property: event mask for output data + int m_output_mask { 0x0 }; /// Lock for output merging - mutable std::mutex m_output_lock; + mutable std::mutex m_output_lock; protected: /// Define standard assignments and constructors @@ -172,13 +209,15 @@ namespace dd4hep { /// Default destructor virtual ~DigiContainerSequenceAction(); /// Initialization callback - void initialize(); + virtual void initialize(); public: /// Standard constructor DigiContainerSequenceAction(const DigiKernel& kernel, const std::string& name); - /// Adopt new parallel worker + /// Adopt new parallel worker acting on one single container void adopt_processor(DigiContainerProcessor* action, const std::string& container); + /// Adopt new parallel worker acting on multiple containers + void adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers); /// Main functional callback if specific work is known virtual void execute(DigiContext& context) const override; }; @@ -192,36 +231,41 @@ namespace dd4hep { */ class DigiMultiContainerProcessor : virtual public DigiEventAction { protected: - using self_t = DigiMultiContainerProcessor; - using processor_t = DigiContainerProcessor; - using work_items_t = std::vector<std::pair<Key, std::any*> >; - /// Argument structure for client calls + using self_t = DigiMultiContainerProcessor; + using processor_t = DigiContainerProcessor; + using worker_keys_t = std::vector<std::vector<Key> >; + using work_items_t = std::vector<std::pair<Key, std::any*> >; + using output_t = processor_t::output_t; + + /// Argument structure required to support multiple client calls struct work_t { DigiContext& context; work_items_t& items; - std::mutex& output_lock; - std::any output; - const self_t* parent; + output_t& output; + const self_t& parent; }; - using worker_t = DigiParallelWorker<processor_t, work_t>; - using workers_t = DigiParallelWorkers<worker_t>; + using worker_t = DigiParallelWorker<processor_t, work_t>; + using workers_t = DigiParallelWorkers<worker_t>; friend class DigiParallelWorker<processor_t, work_t>; protected: /// Property: Input data segment name - std::string m_input_segment { "inputs" }; + std::string m_input_segment { "inputs" }; /// Property: event masks to be handled - std::vector<int> m_input_masks { }; + std::vector<int> m_input_masks { }; + /// Property: Input data segment name + std::string m_output_segment { "outputs" }; + /// Property: event mask for output data + int m_output_mask { 0x0 }; /// Set of work items to be processed and passed to clients - std::set<Key> m_work_items; - - std::vector<std::vector<Key> > m_worker_keys; + std::set<Key> m_work_items; + /// Set of keys required by each worker + worker_keys_t m_worker_keys; /// Array of sub-workers - workers_t m_workers; - + workers_t m_workers; /// Lock for output merging - mutable std::mutex m_output_lock; + mutable std::mutex m_output_lock; protected: /// Define standard assignments and constructors diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index 519f9210a78b668e0e99440350f1ebc18dfe8cd0..bf0f6a062255e5e3a73a220464d706851e423b3e 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -98,7 +98,7 @@ namespace dd4hep { } /// Project the item part of the key - mask_type mask() { + mask_type mask() const { return this->values.mask; } /// Set key mask @@ -119,7 +119,7 @@ namespace dd4hep { } /// Project the mask part of the key - itemkey_type item() { + itemkey_type item() const { return this->values.item; } /// Set key item identifier @@ -376,8 +376,8 @@ namespace dd4hep { */ class DepositVector : public SegmentEntry { public: - using container_t = std::vector<std::pair<CellID, EnergyDeposit> >; - using iterator = container_t::iterator; + using container_t = std::vector<std::pair<CellID, EnergyDeposit> >; + using iterator = container_t::iterator; using const_iterator = container_t::const_iterator; container_t data { }; @@ -397,10 +397,14 @@ namespace dd4hep { DepositVector& operator=(DepositVector&& copy) = default; /// Disable copy assignment DepositVector& operator=(const DepositVector& copy) = default; - /// Merge new deposit map onto existing map (not thread safe!) + /// Merge new deposit map onto existing vector (destroys inputs. not thread safe!) std::size_t merge(DepositVector&& updates); - /// Merge new deposit map onto existing map (keep inputs. not thread safe!) + /// Merge new deposit map onto existing map (destroys inputs. not thread safe!) + std::size_t merge(DepositMapping&& updates); + /// Merge new deposit map onto existing vector (keep inputs. not thread safe!) std::size_t insert(const DepositVector& updates); + /// Merge new deposit map onto existing map (keep inputs. not thread safe!) + std::size_t insert(const DepositMapping& updates); /// Emplace entry void emplace(CellID cell, EnergyDeposit&& deposit); @@ -440,8 +444,8 @@ namespace dd4hep { */ class DepositMapping : public SegmentEntry { public: - using container_t = std::multimap<CellID, EnergyDeposit>; - using iterator = container_t::iterator; + using container_t = std::multimap<CellID, EnergyDeposit>; + using iterator = container_t::iterator; using const_iterator = container_t::const_iterator; container_t data { }; @@ -508,8 +512,8 @@ namespace dd4hep { class DataSegment { public: using container_map_t = std::map<Key::key_type, std::any>; - using iterator = container_map_t::iterator; - using const_iterator = container_map_t::const_iterator; + using iterator = container_map_t::iterator; + using const_iterator = container_map_t::const_iterator; private: /// Call on failed any-casts @@ -545,6 +549,8 @@ namespace dd4hep { /** Locked operations */ /// Emplace data item (locked) bool emplace(Key key, std::any&& data); + /// Move data items other than std::any to the data segment + template <typename DATA> bool put(Key key, DATA&& data); /// Remove data item from segment (locked) bool erase(Key key); /// Remove data items from segment (locked) @@ -621,13 +627,27 @@ namespace dd4hep { */ class DigiEvent { private: + using segment_t = std::unique_ptr<DataSegment>; + /// Event lock std::mutex m_lock; + /// String identifier of this event (for debug printouts) std::string m_id; - DataSegment m_data { this->m_lock }; - DataSegment m_inputs { this->m_lock }; - DataSegment m_deposits { this->m_lock }; + /// Reference to the general purpose data segment + segment_t m_data; + /// Reference to the counts data segment + segment_t m_counts; + /// Reference to the input data segment + segment_t m_inputs; + /// Reference to the output data segment + segment_t m_outputs; + /// Reference to the deposit data segment + segment_t m_deposits; + + /// Helper: Save access with segment creation if it does not exist + DataSegment& access_segment(segment_t& seg); public: + /// Current event number int eventNumber { 0 }; public: diff --git a/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h b/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h deleted file mode 100644 index faadc0bff55f10b80ccee1402e8cbc0978253d78..0000000000000000000000000000000000000000 --- a/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h +++ /dev/null @@ -1,66 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== -#ifndef DDDIGI_DIGIHITATTENUATOREXP_H -#define DDDIGI_DIGIHITATTENUATOREXP_H - -// Framework include files -#include <DDDigi/DigiEventAction.h> - -/// Namespace for the AIDA detector description toolkit -namespace dd4hep { - - /// Namespace for the Digitization part of the AIDA detector description toolkit - namespace digi { - - /// Default base class for all Digitizer actions and derivates thereof. - /** - * This is a utility class supporting properties, output and access to - * event and run objects through the context. - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class DigiHitAttenuatorExp : public DigiEventAction { - protected: - /// Property: Input data segment name - std::string m_input_segment { }; - /// Property: Container names to be loaded - std::map<std::string, double> m_container_attenuation { }; - /// Property: event masks to be handled - std::vector<int> m_masks { }; - /// Property: T0 with respect to central crossing - double m_t0 { 0e0 }; - - /// Keys of all containers to be manipulated - std::map<unsigned long, double> m_attenuation { }; - - protected: - /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiHitAttenuatorExp); - /// Default destructor - virtual ~DigiHitAttenuatorExp(); - /// Attenuator callback for single container - template <typename T> std::size_t attenuate(T* cont, double factor) const; - - public: - /// Standard constructor - DigiHitAttenuatorExp(const DigiKernel& kernel, const std::string& nam); - /// Initialization callback - virtual void initialize(); - /// Main functional callback - virtual void execute(DigiContext& context) const; - }; - } // End namespace digi -} // End namespace dd4hep -#endif // DDDIGI_DIGIHITATTENUATOREXP_H diff --git a/DDDigi/include/DDDigi/DigiParallelWorker.h b/DDDigi/include/DDDigi/DigiParallelWorker.h index e22cba7800e0ffe179fc0e390f72a980abcd8fb4..ae1316f1ab1562c1e404d176bd1b508c4af9b2f3 100644 --- a/DDDigi/include/DDDigi/DigiParallelWorker.h +++ b/DDDigi/include/DDDigi/DigiParallelWorker.h @@ -13,6 +13,9 @@ #ifndef DDDIGI_DIGIPARALLELWORKER_H #define DDDIGI_DIGIPARALLELWORKER_H +/// C/C++ include files +#include <cstdint> + /// Namespace for the AIDA detector description toolkit namespace dd4hep { diff --git a/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h b/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h index ebebd2a56049dc907fd5998dede35c73d43d49e9..e9e51ad76d58142f0fb33e7700fe3bbdb69da266 100644 --- a/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h +++ b/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h @@ -14,8 +14,10 @@ #define DDDIGI_DIGIPARALLELWORKERGROUP_H /// Framework include files +#include <DDDigi/DigiParallelWorker.h> /// C/C++ include files +#include <cstdint> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -52,7 +54,7 @@ namespace dd4hep { /// Default destructor. Releasing semaphore ~DigiParallelWorkerGroup(); /// Access the worker array. As long as the object persists it shall not be altered - operator ParallelCall*const* (); + operator ParallelWorker*const* (); }; /// Initializin constructor: aquire worker's semaphore @@ -69,8 +71,8 @@ namespace dd4hep { } /// Access the worker array. As long as the object persists the array stays intact - template <typename T> inline DigiParallelWorkerGroup<T>::operator ParallelCall*const* () { - return (ParallelCall**)&this->workers.actors.at(0); + template <typename T> inline DigiParallelWorkerGroup<T>::operator ParallelWorker*const* () { + return (ParallelWorker**)&this->workers.actors.at(0); } } // End namespace digi diff --git a/DDDigi/include/DDDigi/DigiParallelWorkers.h b/DDDigi/include/DDDigi/DigiParallelWorkers.h index ea2cbd76f204599ea30a5228ba2cb55ba5e1a94b..18dea5ad8173c8d6a934eed0cbb09368e47e5a5f 100644 --- a/DDDigi/include/DDDigi/DigiParallelWorkers.h +++ b/DDDigi/include/DDDigi/DigiParallelWorkers.h @@ -18,6 +18,8 @@ #include <DDDigi/DigiParallelWorkerGroup.h> /// C/C++ include files +#include <vector> +#include <cstdint> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -73,7 +75,7 @@ namespace dd4hep { std::size_t size() const; bool empty() const; bool insert(worker_t* entry) const; - ParallelCall*const* get_calls() const; + ParallelWorker*const* get_calls() const; }; template <typename T> inline diff --git a/DDDigi/include/DDDigi/DigiSegmentSplitter.h b/DDDigi/include/DDDigi/DigiSegmentSplitter.h index 25c7a9fd971b3dfd68df20487e4fe4519a4744ce..df720166574d037e546b9dd8e30e78fb0bd24621 100644 --- a/DDDigi/include/DDDigi/DigiSegmentSplitter.h +++ b/DDDigi/include/DDDigi/DigiSegmentSplitter.h @@ -37,10 +37,6 @@ namespace dd4hep { class DigiSegmentSplitter : public DigiContainerSequence { protected: using self_t = DigiSegmentSplitter; - using processor_t = DigiSegmentProcessor; - using work_t = processor_t::work_t; - using worker_t = DigiParallelWorker<processor_t, work_t, VolumeID>; - using workers_t = DigiParallelWorkers<worker_t>; using split_t = std::pair<DetElement, VolumeID>; using splits_t = std::map<VolumeID, split_t>; friend class DigiParallelWorker<processor_t, work_t, VolumeID>; @@ -57,17 +53,13 @@ namespace dd4hep { /** Member variables */ /// Segmentation too instance - DigiSegmentationTool m_split_tool; + mutable DigiSegmentationTool m_split_tool; /// Segmentation split context DigiSegmentContext m_split_context; /// Data keys from the readout collection names std::vector<Key> m_keys; /// Split elements used to parallelize the processing splits_t m_splits; - /// Array of sub-workers - workers_t m_workers; - /// Need a lock for possible output merging - mutable std::mutex m_output_lock; protected: /// Default destructor @@ -81,6 +73,8 @@ namespace dd4hep { public: /// Standard constructor DigiSegmentSplitter(const DigiKernel& kernel, const std::string& name); + /// Access the readout collection keys + std::vector<std::string> collection_names() const; /// Main functional callback virtual void execute(DigiContext& context, work_t& work) const override; }; diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h index eb2702b343c7f5a2aba4d2f5aaef1e48e1118e7d..18db270fa71d8e4d19a2382ae56274e75d2ea413 100644 --- a/DDDigi/include/DDDigi/DigiSegmentationTool.h +++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h @@ -98,6 +98,8 @@ namespace dd4hep { /// Setup tool to handle a given detector of the geometry void set_detector(const std::string& det_name); + /// Access the readout collection keys + std::vector<std::string> collection_names() const; /// Access the readout collection keys (mask is empty!) std::vector<Key> collection_keys() const; /// Access the readout collection keys with predefined mask diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index 30a0234786375778fc8a63b2cdbd12e7c2b47ce2..abfe7880fc80658e1fc2a4a419a6817650d9fc98 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -47,8 +47,9 @@ DECLARE_DIGIACTION_NS(dd4hep::digi,DigiLockedAction) #include <DDDigi/DigiStoreDump.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiStoreDump) -#include <DDDigi/DigiHitAttenuatorExp.h> -DECLARE_DIGIACTION_NS(dd4hep::digi,DigiHitAttenuatorExp) +#include <DDDigi/DigiAttenuator.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiAttenuator) +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiAttenuatorSequence) #include <DDDigi/DigiContainerCombine.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerCombine) diff --git a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..843c735aade5540143eb4ba6dd75cbdcb30b5d3b --- /dev/null +++ b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp @@ -0,0 +1,62 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiContainerProcessor.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Actor to select energy deposits according to the supplied segmentation + /** Actor to select energy deposits according to the supplied segmentation + * + * The selected deposits are placed in the output container + * supplied by the arguments. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiCellMultiplicityCounter : public DigiContainerProcessor { + public: + /// Standard constructor + using DigiContainerProcessor::DigiContainerProcessor; + + template <typename T> void count_deposits(const T& cont) const { + std::map<CellID, std::size_t> entries; + for( const auto& dep : cont ) { + CellID cell = dep.first; + entries[cell] += 1; + } + info("+++ %-32s has %6ld entries and %6ld unique cells", + cont.name.c_str(), cont.size(), entries.size()); + } + /// Main functional callback + virtual void execute(DigiContext&, work_t& work) const override final { + if ( const auto* m = work.get_input<DepositMapping>() ) + count_deposits(*m); + else if ( const auto* v = work.get_input<DepositVector>() ) + count_deposits(*v); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiCellMultiplicityCounter) diff --git a/DDDigi/plugins/DigiDepositMapCreator.cpp b/DDDigi/plugins/DigiDepositMapCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d420822d33477f4dc8d8c87338ed3d3c4dbf686e --- /dev/null +++ b/DDDigi/plugins/DigiDepositMapCreator.cpp @@ -0,0 +1,68 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiContainerProcessor.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Actor to select energy deposits according to the supplied segmentation + /** Actor to select energy deposits according to the supplied segmentation + * + * The selected deposits are placed in the output container + * supplied by the arguments. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositMapCreator : public DigiContainerProcessor { + public: + /// Standard constructor + using DigiContainerProcessor::DigiContainerProcessor; + + template <typename T> void create_deposits(const T& cont, work_t& work) const { + Key key(cont.name, work.output.mask); + DepositMapping* mapping = work.output.data.pointer<DepositMapping>(key); + if ( !mapping ) { + DepositMapping m(cont.name, work.output.mask); + work.output.data.put(m.key, std::move(m)); + mapping = work.output.data.pointer<DepositMapping>(key); + } + std::size_t start = mapping->size(); + for( const auto& dep : cont ) + mapping->data.emplace(dep.first, EnergyDeposit()); + std::size_t end = mapping->size(); + info("+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", + cont.name.c_str(), end-start, end, cont.key.mask(), mapping->key.mask()); + } + /// Main functional callback + virtual void execute(DigiContext&, work_t& work) const override final { + if ( const auto* m = work.get_input<DepositMapping>() ) + create_deposits(*m, work); + else if ( const auto* v = work.get_input<DepositVector>() ) + create_deposits(*v, work); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositMapCreator) diff --git a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp index 2f0999ddfeb1531b5e6cfb7e9afdc5276d02662d..ac3788d30bb034868695a24b1c694c46f0ee5f08 100644 --- a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp +++ b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp @@ -37,14 +37,24 @@ namespace dd4hep { DigiSegmentDepositExtractor(const DigiKernel& kernel, const std::string& nam) : DigiSegmentProcessor(kernel, nam) {} + template <typename T> void copy_deposits(const T& cont, work_t& work) const { + DepositVector deposits(cont.name, work.output.mask); + for( const auto& dep : cont ) { + CellID cell = dep.first; + EnergyDeposit depo = dep.second; + deposits.data.emplace_back(cell, std::move(depo)); + } + work.output.data.put(deposits.key, std::move(deposits)); + } /// Main functional callback virtual void handle_segment(DigiContext&, work_t& work) const override final { - for( const auto& d : work.input ) { - if ( segment.matches(d.first) ) { - CellID cell = d.first; - EnergyDeposit depo = d.second; - work.emplace_output(cell, std::move(depo)); - } + if ( segment.matches(work.input.key.key) ) { + if ( const auto* m = work.get_input<DepositMapping>() ) + copy_deposits(*m, work); + else if ( const auto* v = work.get_input<DepositVector>() ) + copy_deposits(*v, work); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } } }; diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp index 6a5bd23cfc07b5ae6cc139031e55701cddd623ba..e4046cfe8feb851fc4eed362bea7fdfb71952de2 100644 --- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp +++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp @@ -46,21 +46,17 @@ namespace dd4hep { ::snprintf(format, sizeof(format), "%s[%s] %s-id: %%d [processor:%d] Cell: %%016lX mask: %016lX hist:%%4ld hits %%4ld parts. entries deposit: %%f", context.event->id(), segment.idspec.name(), segment.cname(), segment.id, segment.split_mask); - if ( const auto* m = std::any_cast<DepositMapping>(&work.input) ) { - for( const auto& d : *m ) { - if ( segment.matches(d.first) ) - print_deposit(format, d.first, d.second); - } - } - else if ( const auto* v = std::any_cast<DepositVector>(&work.input) ) { - for( const auto& d : *v ) { - if ( segment.matches(d.first) ) - print_deposit(format, d.first, d.second); - } - } - else { - error("+++ Request to dump an invalid container %s", Key::key_name(work.key.item())); - } + auto call = [this, format](const std::pair<CellID,EnergyDeposit>& d) { + if( this->segment.matches(d.first) ) + this->print_deposit(format, d.first, d.second); + }; + if ( const auto* m = work.get_input<DepositMapping>() ) + std::for_each(m->begin(), m->end(), call); + else if ( const auto* v = work.get_input<DepositVector>() ) + std::for_each(v->begin(), v->end(), call); + else + error("+++ Request to dump an invalid container %s", + Key::key_name(work.input.key.item())); } }; } // End namespace digi diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 83f196af506c48b90180ea77d618630db5a018f1..9ba59a6a1e40a066019a3b9e66d048ab1157c2a4 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -178,6 +178,7 @@ namespace dd4hep { #include <DDDigi/DigiSynchronize.h> #include <DDDigi/DigiInputAction.h> +#include <DDDigi/DigiSegmentSplitter.h> #include <DDDigi/DigiSegmentProcessor.h> #include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiSignalProcessor.h> @@ -203,14 +204,19 @@ using namespace std; #pragma link C++ class dd4hep::digi::DigiAction; #pragma link C++ class dd4hep::digi::DigiEventAction; #pragma link C++ class dd4hep::digi::DigiInputAction; -#pragma link C++ class dd4hep::digi::DigiSegmentProcessor; #pragma link C++ class dd4hep::digi::DigiActionSequence; #pragma link C++ class dd4hep::digi::DigiSynchronize; #pragma link C++ class dd4hep::digi::DigiSignalProcessor; + #pragma link C++ class dd4hep::digi::DigiContainerProcessor; #pragma link C++ class dd4hep::digi::DigiContainerSequence; +#pragma link C++ class dd4hep::digi::DigiContainerSequenceAction; #pragma link C++ class dd4hep::digi::DigiMultiContainerProcessor; +#pragma link C++ class dd4hep::digi::DigiSegmentProcessor; +#pragma link C++ class dd4hep::digi::DigiSegmentSequence; +#pragma link C++ class dd4hep::digi::DigiSegmentSplitter; + /// Digi data item wrappers #pragma link C++ class dd4hep::digi::Particle+; #pragma link C++ class dd4hep::digi::EnergyDeposit+; diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py index 1e45a0dbf47b2a7c358d4d61c1c13ed29b289759..323d6d9d0dd6a9b96682d14363cf0d5b2a5bd22b 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -201,13 +201,14 @@ def _adopt_processor_action(self, action, container): " Helper to convert DigiActions objects to DigiEventAction " print(str(action.__class__)) attr = getattr(self, 'adopt_processor') - if hasattr(action,'I_am_a_ROOT_interface_handle'): - print('Entering handle branch') + if hasattr(action, 'I_am_a_ROOT_interface_handle'): proc = Interface.toContainerProcessor(action.get()) attr(proc, container) else: - attr(action, container) - print('ContainerProcessor succesfully adopted') + proc = action ##Interface.toContainerProcessor(action) + print(str(proc.__class__)) + attr(proc, container) + # print('ContainerProcessor succesfully adopted') # --------------------------------------------------------------------------- diff --git a/DDDigi/python/digitize.py b/DDDigi/python/digitize.py index b22c00dbc25c45274fb4aaca323619b0df2a5e69..5ba9fa0eec3d988d55d0632ff11872be052ee571 100644 --- a/DDDigi/python/digitize.py +++ b/DDDigi/python/digitize.py @@ -136,7 +136,7 @@ class Digitize(dd4hep.Logger): self.kernel().configure() self.kernel().initialize() self.kernel().run() - done = krnl.events_done() + done = self.kernel().events_done() self.kernel().terminate() return done diff --git a/DDDigi/src/DigiAttenuator.cpp b/DDDigi/src/DigiAttenuator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3eb43cde4887b27a65f7898672ce6ae6dbfc05ba --- /dev/null +++ b/DDDigi/src/DigiAttenuator.cpp @@ -0,0 +1,114 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include <DD4hep/InstanceCount.h> +#include <DDDigi/DigiData.h> +#include <DDDigi/DigiKernel.h> +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiPlugins.h> +#include <DDDigi/DigiAttenuator.h> + +/// C/C++ include files +#include <cmath> + +using namespace dd4hep::digi; + +/// Exponential decay depending on time offset(t0) and mean signal decay time +double DigiAttenuationTool::exponential(double t0, double decay_time) const { + return std::exp(-1e0 * std::abs(t0)/decay_time); +} + +/// Standard constructor +DigiAttenuator::DigiAttenuator(const DigiKernel& krnl, const std::string& nam) + : DigiContainerProcessor(krnl, nam) +{ + declareProperty("factor", m_factor); + InstanceCount::increment(this); +} + +/// Default destructor +DigiAttenuator::~DigiAttenuator() { + InstanceCount::decrement(this); +} + +/// Attenuator callback for single container +template <typename T> std::size_t DigiAttenuator::attenuate(T& cont) const { + for( auto& c : cont ) + c.second.deposit *= m_factor; + return cont.size(); +} + +/// Main functional callback adapter +void DigiAttenuator::execute(DigiContext& context, work_t& work) const { + std::size_t count = 0; + if ( auto* m = work.get_input<DepositMapping>() ) + count = this->attenuate(*m); + else if ( auto* v = work.get_input<DepositVector>() ) + count = this->attenuate(*v); + Key key { work.input.key }; + std::string nam = Key::key_name(key)+":"; + info("%s+++ %-32s mask:%04X item: %08X Attenuated %6ld hits by %8.5f", + context.event->id(), nam.c_str(), key.mask(), key.item(), count, m_factor); +} + +/// Standard constructor +DigiAttenuatorSequence::DigiAttenuatorSequence(const DigiKernel& krnl, const std::string& nam) + : DigiContainerSequenceAction(krnl, nam) +{ + declareProperty("processor_type", m_processor_type = "DigiAttenuator"); + declareProperty("containers", m_container_attenuation); + declareProperty("signal_decay", m_signal_decay = "exponential"); + declareProperty("t0", m_t0); + InstanceCount::increment(this); +} + +/// Default destructor +DigiAttenuatorSequence::~DigiAttenuatorSequence() { + InstanceCount::decrement(this); +} + +/// Initialization callback +void DigiAttenuatorSequence::initialize() { + DigiAttenuationTool tool; + if ( m_container_attenuation.empty() ) { + warning("+++ No input containers given for attenuation action -- no action taken"); + return; + } + for ( const auto& c : m_container_attenuation ) { + std::string nam = name() + "." + c.first; + double factor = 0e0; + switch( ::toupper(m_signal_decay[0]) ) { + case 'E': + factor = tool.exponential(m_t0, c.second); + break; + default: + except("+++ The attenuation function '%s' is not supported ---> STOP", + m_signal_decay.c_str()); + break; + } + auto* att = createAction<DigiAttenuator>(m_processor_type, m_kernel, nam); + if ( !att ) { + except("+++ Failed to create signal attenuator: %s of type: %s", + nam.c_str(), m_processor_type.c_str()); + } + att->property("factor").set(factor); + adopt_processor(att, c.first); + } + this->DigiContainerSequenceAction::initialize(); +} + +/// Main functional callback +void DigiAttenuatorSequence::execute(DigiContext& context) const { + this->DigiContainerSequenceAction::execute(context); +} diff --git a/DDDigi/src/DigiAttenuatorSequenceAction.cpp b/DDDigi/src/DigiAttenuatorSequenceAction.cpp deleted file mode 100644 index 8df1448b9300e75ab723c71da5cb51bcf498f9eb..0000000000000000000000000000000000000000 --- a/DDDigi/src/DigiAttenuatorSequenceAction.cpp +++ /dev/null @@ -1,75 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== - - -/// TODO ! - - -// Framework include files -#include <DD4hep/InstanceCount.h> - -#include <DDDigi/DigiData.h> -#include <DDDigi/DigiKernel.h> -#include <DDDigi/DigiContext.h> -#include <DDDigi/DigiAttenuatorSequenceAction.h> - -/// C/C++ include files -#include <cmath> - -/// Standard constructor -dd4hep::digi::DigiAttenuatorSequenceAction::DigiAttenuatorSequenceAction(const DigiKernel& krnl, const std::string& nam) - : DigiEventAction(krnl, nam) -{ - declareProperty("input", m_input_segment = "inputs"); - declareProperty("processor", m_processor_name); - declareProperty("containers", m_container_attenuation); - declareProperty("mask", m_mask); - declareProperty("t0", m_t0); - m_kernel.register_initialize(Callback(this).make(&DigiAttenuatorSequenceAction::initialize)); - InstanceCount::increment(this); -} - -/// Default destructor -dd4hep::digi::DigiAttenuatorSequenceAction::~DigiAttenuatorSequenceAction() { - InstanceCount::decrement(this); -} - -/// Initialization callback -void dd4hep::digi::DigiAttenuatorSequenceAction::initialize() { - for ( const auto& c : m_container_attenuation ) { - double factor = std::exp(-1e0 * m_t0/c.second); - m_attenuation.emplace(Key(c.first, m_mask), factor); - } -} - -/// Main functional callback -void dd4hep::digi::DigiAttenuatorSequenceAction::execute(DigiContext& context) const { - std::size_t count = 0, cnt = 0, cont = 0; - auto& event = *context.event; - auto& inputs = event.get_segment(m_input_segment); - for ( const auto& k : m_attenuation ) { - Key key = k.first; - auto* data = inputs.entry(key); - if ( auto* m = std::any_cast<DepositMapping>(data) ) - ++cont; - else if ( auto* v = std::any_cast<DepositVector>(data) ) - cnt++, ++cont; - count += cnt; - std::string nam = Key::key_name(key)+":"; - debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f", - event.id(), nam.c_str(), key.mask(), key.item(), cnt, k.second); - } - info("%s+++ Attenuated exponentially %6ld hits from %4ld containers from segment %s", - event.id(), count, cont, m_input_segment.c_str()); -} - diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp index 0de723b764f6c285e59ffbe63b8678789cb1b7c3..8d9ec05859a6044c0564dd24e9af6a459306f52a 100644 --- a/DDDigi/src/DigiContainerCombine.cpp +++ b/DDDigi/src/DigiContainerCombine.cpp @@ -60,7 +60,7 @@ public: format[sizeof(format)-1] = 0; } - template<typename T> void merge_depos(DepositMapping& output, T& input, int thr) { + template<typename T> void merge_depos(DepositVector& output, T& input, int thr) { std::size_t cnt = 0; if ( combine->m_erase_combined ) cnt = output.merge(std::move(input)); @@ -73,7 +73,7 @@ public: void merge(const std::string& nam, size_t start, int thr) { Key key = keys[start]; - DepositMapping out(nam, combine->m_deposit_mask); + DepositVector out(nam, combine->m_deposit_mask); for( std::size_t j = start; j < keys.size(); ++j ) { if ( keys[j].item() == key.item() ) { if ( DepositMapping* m = std::any_cast<DepositMapping>(work[j]) ) @@ -157,7 +157,7 @@ DigiContainerCombine::DigiContainerCombine(const DigiKernel& krnl, const std::st declareProperty("input_masks", m_input_masks); declareProperty("input_segment", m_input = "inputs"); declareProperty("output_segment", m_output = "deposits"); - declareProperty("deposit_mask", m_deposit_mask); + declareProperty("output_mask", m_deposit_mask); declareProperty("output_name_flag", m_output_name_flag); declareProperty("erase_combined", m_erase_combined); m_kernel.register_initialize(Callback(this).make(&DigiContainerCombine::initialize)); diff --git a/DDDigi/src/DigiContainerProcessor.cpp b/DDDigi/src/DigiContainerProcessor.cpp index b3eaa9f10ce690952d4f77de43185f69f7256a24..fe22e51ed4c5bf18cbe6166d43444616aebd96d9 100644 --- a/DDDigi/src/DigiContainerProcessor.cpp +++ b/DDDigi/src/DigiContainerProcessor.cpp @@ -23,6 +23,105 @@ using namespace dd4hep::digi; +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + template <typename T> T* DigiContainerProcessor::work_t::get_input(bool exc) { + if ( input.data.has_value() ) { + T* object = std::any_cast<T>(&input.data); + if ( object ) { + return object; + } + } + if ( exc ) { + dd4hep::except("DigiContainerProcessor", + "+++ Cannot access input %s. Invalid data handle of type: %s", + Key::key_name(input.key).c_str(), input_type_name().c_str()); + } + return nullptr; + } + + template <typename T> const T* DigiContainerProcessor::work_t::get_input(bool exc) const { + if ( input.data.has_value() ) { + const T* object = std::any_cast<T>(&input.data); + if ( object ) { + return object; + } + } + if ( exc ) { + dd4hep::except("DigiContainerProcessor", + "+++ Cannot access input %s. Invalid data handle of type: %s", + Key::key_name(input.key).c_str(), input_type_name().c_str()); + } + return nullptr; + } +#if 0 + template <typename T> T* DigiContainerProcessor::work_t::get_output() { + if ( !output.data.has_value() ) { + T data; + output.data = std::move(data); + } + T* v = std::any_cast<T>(&output.data); + if ( v ) { + return v; + } + dd4hep::except("DigiContainerProcessor", + "+++ Cannot access output. Invalid data handle of type: %s", + output_type_name().c_str()); + return nullptr; + } +#endif + + } // End namespace digi +} // End namespace dd4hep + +template DepositVector* DigiContainerProcessor::work_t::get_input(bool exc); +template const DepositVector* DigiContainerProcessor::work_t::get_input(bool exc) const; +template DepositMapping* DigiContainerProcessor::work_t::get_input(bool exc); +template const DepositMapping* DigiContainerProcessor::work_t::get_input(bool exc) const; +template ParticleMapping* DigiContainerProcessor::work_t::get_input(bool exc); +template const ParticleMapping* DigiContainerProcessor::work_t::get_input(bool exc) const; + +/// input data type +const std::type_info& DigiContainerProcessor::work_t::input_type() const { + return input.data.type(); +} + +/// String form of the input data type +std::string DigiContainerProcessor::work_t::input_type_name() const { + return typeName(input.data.type()); +} + +#if 0 +template DepositVector* DigiContainerProcessor::work_t::get_output(); +template DepositMapping* DigiContainerProcessor::work_t::get_output(); +template ParticleMapping* DigiContainerProcessor::work_t::get_output(); + +/// output data type +const std::type_info& DigiContainerProcessor::work_t::output_type() const { + return output.data.type(); +} + +/// String form of the output data type +std::string DigiContainerProcessor::work_t::output_type_name() const { + return typeName(input.data.type()); +} + +/// Merge output data +void DigiContainerProcessor::work_t::merge_output(DepositVector&& data) { + std::lock_guard<std::mutex> lock(output.lock); + this->get_output<DepositVector>()->merge(std::move(data)); +} + +void DigiContainerProcessor::work_t::emplace_output(CellID cell, EnergyDeposit&& data) { + std::lock_guard<std::mutex> lock(output.lock); + this->get_output<DepositVector>()->emplace(cell, std::move(data)); +} +#endif + /// Standard constructor DigiContainerProcessor::DigiContainerProcessor(const DigiKernel& kernel, const std::string& name) : DigiAction(kernel, name) @@ -37,7 +136,7 @@ DigiContainerProcessor::~DigiContainerProcessor() { /// Main functional callback void DigiContainerProcessor::execute(DigiContext& context, work_t& work) const { - this->execute(context, work.key, work.input); + this->execute(context, work.input.key, work.input.data); } /// Main functional callback if specific work is known @@ -85,8 +184,10 @@ template <> void DigiParallelWorker<DigiContainerProcessor, DigiContainerSequenceAction::DigiContainerSequenceAction(const DigiKernel& krnl, const std::string& nam) : DigiEventAction(krnl, nam) { - declareProperty("mask", m_mask); + declareProperty("input_mask", m_input_mask); declareProperty("input_segment", m_input_segment); + declareProperty("output_mask", m_output_mask); + declareProperty("output_segment", m_output_segment); m_kernel.register_initialize(Callback(this).make(&DigiContainerSequenceAction::initialize)); InstanceCount::increment(this); } @@ -101,7 +202,7 @@ void dd4hep::digi::DigiContainerSequenceAction::initialize() { size_t count = 0; for( auto& ent : m_registered_processors ) { Key key = ent.first; - key.set_mask(m_mask); + key.set_mask(m_input_mask); worker_t* w = new worker_t(ent.second, count++); m_registered_workers.emplace(key, w); m_workers.insert(w); @@ -109,38 +210,63 @@ void dd4hep::digi::DigiContainerSequenceAction::initialize() { } /// Adopt new parallel worker -void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action, const std::string& container) { +void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action, + const std::string& container) +{ Key key(container, 0x0); auto it = m_registered_processors.find(key); if ( it != m_registered_processors.end() ) { - except("+++ The action %s was already registered to mask:%04X container:%s!", - action->c_name(), m_mask, container.c_str()); + if ( action != it->second ) { + except("+++ The action %s was already registered to mask:%04X container:%s!", + action->c_name(), m_input_mask, container.c_str()); + } + else { + warning("+++ The action %s was already registered to mask:%04X container:%s!", + action->c_name(), m_input_mask, container.c_str()); + } return; } action->addRef(); m_registered_processors.emplace(key, action); + info("+++ Adding processor: %s for container: [%016lX] %s", + action->c_name(), key.key, container.c_str()); +} + +/// Adopt new parallel worker acting on multiple containers +void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action, + const std::vector<std::string>& containers) +{ + info("+++ Adding bulk processor: %s for %ld container", action->c_name(), containers.size()); + for( const auto& cont : containers ) { + adopt_processor(action, cont); + } } /// Main functional callback if specific work is known void DigiContainerSequenceAction::execute(DigiContext& context) const { - auto& event = *context.event; - auto& inputs = event.get_segment(m_input_segment); + auto& event = *context.event; + auto& inputs = event.get_segment(m_input_segment); + auto& outputs = event.get_segment(m_output_segment); std::vector<ParallelWorker*> event_workers; - work_t args { context, {}, m_output_lock, {}, this }; + output_t output { m_output_mask, outputs }; + work_t args { context, {}, output, this }; args.input_items.resize(m_workers.size(), {0, nullptr}); event_workers.reserve(inputs.size()); for( auto& i : inputs ) { Key key(i.first); - auto it = m_registered_workers.find(key); - if ( it != m_registered_workers.end() ) { - worker_t* w = it->second; - //work_item_t itm { key, &(i.second) }; - event_workers.emplace_back(w); - args.input_items[w->options] = { key, &(i.second) }; + if ( key.mask() == m_input_mask ) { + auto it = m_registered_workers.find(key); + if ( it != m_registered_workers.end() ) { + worker_t* w = it->second; + event_workers.emplace_back(w); + args.input_items[w->options] = { key, &(i.second) }; + } } } - m_kernel.submit(&event_workers.at(0), event_workers.size(), &args, m_parallel); + if ( !event_workers.empty() ) { + m_kernel.submit(&event_workers.at(0), event_workers.size(), &args, m_parallel); + } } /// Worker adaptor for caller DigiContainerSequenceAction @@ -149,7 +275,7 @@ template <> void DigiParallelWorker<DigiContainerProcessor, std::size_t>::execute(void* data) const { calldata_t* args = reinterpret_cast<calldata_t*>(data); auto& item = args->input_items[this->options]; - DigiContainerProcessor::work_t work { args->context, item.key, *item.data, args->output_lock, args->output}; + DigiContainerProcessor::work_t work { args->context, { item.key, *item.data }, args->output }; action->execute(args->context, work); } @@ -159,6 +285,8 @@ DigiMultiContainerProcessor::DigiMultiContainerProcessor(const DigiKernel& krnl, { this->declareProperty("input_masks", m_input_masks); this->declareProperty("input_segment", m_input_segment); + this->declareProperty("output_mask", m_output_mask); + this->declareProperty("output_segment", m_output_segment); InstanceCount::increment(this); } @@ -208,7 +336,9 @@ void DigiMultiContainerProcessor::execute(DigiContext& context) const { } } if ( !work_items.empty() ) { - work_t args { context, work_items, m_output_lock, {}, this }; + auto& outputs = event.get_segment(m_output_segment); + output_t output { m_output_mask, outputs }; + work_t args { context, work_items, output, *this }; m_kernel.submit(m_workers.get_calls(), m_workers.size(), &args, m_parallel); } } @@ -217,19 +347,19 @@ void DigiMultiContainerProcessor::execute(DigiContext& context) const { template <> void DigiParallelWorker<DigiContainerProcessor, DigiMultiContainerProcessor::work_t, std::size_t>::execute(void* data) const { - calldata_t* arg = reinterpret_cast<calldata_t*>(data); - const auto& keys = arg->parent->worker_keys(this->options); - const auto& masks = arg->parent->input_masks(); + calldata_t* arg = reinterpret_cast<calldata_t*>(data); + const auto& keys = arg->parent.worker_keys(this->options); + const auto& masks = arg->parent.input_masks(); for( const auto& item : arg->items ) { Key key = item.first; if ( masks.empty() || std::find(masks.begin(), masks.end(), key.mask()) != masks.end() ) { if ( keys.empty() ) { - DigiContainerProcessor::work_t work {arg->context, key, *item.second, arg->output_lock, arg->output }; - action->execute(arg->context, work); + DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output }; + action->execute(work.context, work); } else if ( std::find(keys.begin(), keys.end(), Key(key.item())) != keys.end() ) { - DigiContainerProcessor::work_t work {arg->context, key, *item.second, arg->output_lock, arg->output }; - action->execute(arg->context, work); + DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output }; + action->execute(work.context, work); } } } diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index 2caea66de57ec34771106d2e7a2042d19915ccdb..b0038d7c9695faec00eee855025e14174150b01a 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -65,15 +65,37 @@ std::string Key::key_name(const Key& k) { /// Merge new deposit map onto existing map std::size_t DepositVector::merge(DepositVector&& updates) { std::size_t update_size = updates.size(); + data.reserve(data.size()+updates.size()); for( auto& c : updates ) { data.emplace_back(c); } return update_size; } +/// Merge new deposit map onto existing map (keep inputs) +std::size_t DepositVector::merge(DepositMapping&& updates) { + std::size_t update_size = updates.size(); + data.reserve(data.size()+updates.size()); + for( const auto& c : updates ) { + data.emplace_back(c); + } + return update_size; +} + /// Merge new deposit map onto existing map (keep inputs) std::size_t DepositVector::insert(const DepositVector& updates) { std::size_t update_size = updates.size(); + data.reserve(data.size()+updates.size()); + for( const auto& c : updates ) { + data.emplace_back(c); + } + return update_size; +} + +/// Merge new deposit map onto existing map (keep inputs) +std::size_t DepositVector::insert(const DepositMapping& updates) { + std::size_t update_size = updates.size(); + data.reserve(data.size()+updates.size()); for( const auto& c : updates ) { data.emplace_back(c); } @@ -85,7 +107,6 @@ std::size_t DepositMapping::merge(DepositVector&& updates) { std::size_t update_size = updates.size(); for( auto& c : updates ) { data.emplace(std::move(c)); -#if 0 CellID cell = c.first; EnergyDeposit& depo = c.second; auto iter = data.find(cell); @@ -101,7 +122,6 @@ std::size_t DepositMapping::merge(DepositVector&& updates) { to_update.particle_history.insert(to_update.particle_history.end(), depo.particle_history.begin(), depo.particle_history.end()); -#endif } return update_size; } @@ -206,6 +226,16 @@ bool DataSegment::emplace(Key key, std::any&& item) { return ret; } +/// Move data items other than std::any to the data segment +template <typename DATA> bool DataSegment::put(Key key, DATA&& value) { + std::any item = std::make_any<DATA>(std::move(value)); + return this->emplace(key, std::move(item)); +} + +template bool DataSegment::put(Key key, DepositVector&& data); +template bool DataSegment::put(Key key, DepositMapping&& data); +template bool DataSegment::put(Key key, ParticleMapping&& data); + /// Remove data item from segment bool DataSegment::erase(Key key) { std::lock_guard<std::mutex> l(lock); @@ -291,19 +321,35 @@ DigiEvent::~DigiEvent() InstanceCount::decrement(this); } +DataSegment& DigiEvent::access_segment(std::unique_ptr<DataSegment>& segment) { + if ( segment ) { + return *segment; + } + std::lock_guard<std::mutex> guard(m_lock); + /// Check again after holding the lock: + if ( !segment ) { + segment = std::make_unique<DataSegment>(this->m_lock); + } + return *segment; +} + /// Retrieve data segment from the event structure DataSegment& DigiEvent::get_segment(const std::string& name) { switch(::toupper(name[0])) { case 'I': - return this->m_inputs; + return access_segment(m_inputs); + case 'C': + return access_segment(m_counts); case 'D': switch(::toupper(name[1])) { case 'E': - return this->m_deposits; + return access_segment(m_deposits); default: - return this->m_data; + return access_segment(m_data); } break; + case 'O': + return access_segment(m_outputs); default: break; } diff --git a/DDDigi/src/DigiHitAttenuatorExp.cpp b/DDDigi/src/DigiHitAttenuatorExp.cpp deleted file mode 100644 index ffdae21a5cca9b1c3bfe382564193210a18d7ca0..0000000000000000000000000000000000000000 --- a/DDDigi/src/DigiHitAttenuatorExp.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== - -// Framework include files -#include <DD4hep/InstanceCount.h> - -#include <DDDigi/DigiData.h> -#include <DDDigi/DigiKernel.h> -#include <DDDigi/DigiContext.h> -#include <DDDigi/DigiHitAttenuatorExp.h> - -/// C/C++ include files -#include <cmath> - -/// Standard constructor -dd4hep::digi::DigiHitAttenuatorExp::DigiHitAttenuatorExp(const DigiKernel& krnl, const std::string& nam) - : DigiEventAction(krnl, nam) -{ - declareProperty("input", m_input_segment = "inputs"); - declareProperty("containers", m_container_attenuation); - declareProperty("masks", m_masks); - declareProperty("t0", m_t0); - m_kernel.register_initialize(Callback(this).make(&DigiHitAttenuatorExp::initialize)); - InstanceCount::increment(this); -} - -/// Default destructor -dd4hep::digi::DigiHitAttenuatorExp::~DigiHitAttenuatorExp() { - InstanceCount::decrement(this); -} - -/// Initialization callback -void dd4hep::digi::DigiHitAttenuatorExp::initialize() { - for ( const auto& c : m_container_attenuation ) { - Key key(c.first, 0x0); - for ( int m : m_masks ) { - double factor = std::exp(-1e0 * m_t0/c.second); - key.set_mask(m); - m_attenuation.emplace(key.key, factor); - } - } -} - -/// Attenuator callback for single container -template <typename T> std::size_t -dd4hep::digi::DigiHitAttenuatorExp::attenuate(T* cont, double factor) const { - for( auto& c : *cont ) - c.second.deposit *= factor; - return cont->size(); -} - -/// Main functional callback -void dd4hep::digi::DigiHitAttenuatorExp::execute(DigiContext& context) const { - std::size_t count = 0, cnt = 0, cont = 0; - auto& event = *context.event; - auto& inputs = event.get_segment(m_input_segment); - for ( const auto& k : m_attenuation ) { - Key key = k.first; - auto* data = inputs.entry(key); - if ( auto* m = std::any_cast<DepositMapping>(data) ) - cnt += this->attenuate(m, k.second), ++cont; - else if ( auto* v = std::any_cast<DepositVector>(data) ) - cnt += this->attenuate(v, k.second), ++cont; - count += cnt; - std::string nam = Key::key_name(key)+":"; - debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f", - event.id(), nam.c_str(), key.mask(), key.item(), cnt, k.second); - } - info("%s+++ Attenuated exponentially %6ld hits from %4ld containers from segment %s", - event.id(), count, cont, m_input_segment.c_str()); -} - diff --git a/DDDigi/src/DigiSegmentProcessor.cpp b/DDDigi/src/DigiSegmentProcessor.cpp index 07064d0cb6d64207fe2fe691278670d6d4116ba0..029753a8c2d1497d7af433a6e4a334e53d1a1387 100644 --- a/DDDigi/src/DigiSegmentProcessor.cpp +++ b/DDDigi/src/DigiSegmentProcessor.cpp @@ -18,28 +18,6 @@ using namespace dd4hep::digi; -void DigiSegmentProcessor::work_t::merge_output(DepositVector&& data) { - std::lock_guard<std::mutex> lock(output_lock); -#if 0 - if ( !output.get() ) { - output.reset(new DepositVector(std::move(data))); - } - else { - output->merge(std::move(data)); - } -#endif -} - -void DigiSegmentProcessor::work_t::emplace_output(CellID cell, EnergyDeposit&& data) { - std::lock_guard<std::mutex> lock(output_lock); -#if 0 - if ( !output.get() ) { - output.reset(new DepositVector()); - } - output->emplace(cell, std::move(data)); -#endif -} - /// Standard constructor DigiSegmentProcessor::DigiSegmentProcessor(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) diff --git a/DDDigi/src/DigiSegmentSplitter.cpp b/DDDigi/src/DigiSegmentSplitter.cpp index 7fbb9a5c332b2ea41be81f6eb84f205003c56fd4..f0cce33a9b094f7fb1b7cdc645db2578900579ec 100644 --- a/DDDigi/src/DigiSegmentSplitter.cpp +++ b/DDDigi/src/DigiSegmentSplitter.cpp @@ -39,6 +39,18 @@ DigiSegmentSplitter::~DigiSegmentSplitter() { InstanceCount::decrement(this); } +/// Retrieve the names of all collection to be accessed +std::vector<std::string> DigiSegmentSplitter::collection_names() const { + if ( !m_detector_name.empty() ) { + if ( m_splits.empty() ) { + m_split_tool.set_detector(m_detector_name); + } + return m_split_tool.collection_names(); + } + except("+++ collection_names: The detector name is not set. Unable to access readout properties."); + return {}; +} + /// Initialization function void DigiSegmentSplitter::initialize() { char text[256]; @@ -58,7 +70,7 @@ void DigiSegmentSplitter::initialize() { auto split_id = p.second.second; bool ok = false; for( const auto* w : workers ) { - if ( w->options == split_id ) { ok = true; break; } + if ( VolumeID(w->options) == split_id ) { ok = true; break; } } if ( !ok ) { error("+++ Missing processor for plit ID: %08ld", split_id); @@ -106,10 +118,10 @@ void DigiSegmentSplitter::adopt_processor(DigiContainerProcessor* action) { /// Main functional callback void DigiSegmentSplitter::execute(DigiContext& /* context */, work_t& work) const { - Key unmasked_key(work.key.item()); + Key key = work.input_key(); + Key unmasked_key(key.item()); if ( std::find(m_keys.begin(), m_keys.end(), unmasked_key) != m_keys.end() ) { - if ( work.input.has_value() ) { - Key key = work.key; + if ( work.has_input() ) { info("+++ Got hit collection %04X %08X. Prepare processors for %sparallel execution.", key.mask(), key.item(), m_parallel ? "" : "NON-"); m_kernel.submit(m_workers.get_group(), m_workers.size(), &work, m_parallel); diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp index 37026cfffad3f36f0b7f70378605dbdabcf5ec5b..be65a2afc2afdcf6ce4524169a56b315e09ef5b9 100644 --- a/DDDigi/src/DigiSegmentationTool.cpp +++ b/DDDigi/src/DigiSegmentationTool.cpp @@ -79,6 +79,19 @@ void DigiSegmentationTool::set_detector(const string& det_name) { } } +/// Access the readout collection keys +vector<string> DigiSegmentationTool::collection_names() const { + if ( this->sensitive.isValid() ) { + Readout rd = this->sensitive.readout(); + vector<string> names = rd.collectionNames(); + if ( names.empty() ) names.emplace_back(rd.name()); + return names; + } + except("DigiSegmentationTool", + "+++ collection_names: Readout not valid. Is the proper detector set ?"); + return {}; +} + /// Access the readout collection keys vector<Key> DigiSegmentationTool::collection_keys() const { return collection_keys(0x0); @@ -87,16 +100,9 @@ vector<Key> DigiSegmentationTool::collection_keys() const { /// Access the readout collection keys vector<Key> DigiSegmentationTool::collection_keys(Key::mask_type mask) const { vector<Key> keys; - if ( this->sensitive.isValid() ) { - Readout rd = this->sensitive.readout(); - auto collection_names = rd.collectionNames(); - if ( collection_names.empty() ) collection_names.emplace_back(rd.name()); - for( const auto& collection : collection_names ) - keys.emplace_back(Key(collection, mask)); - return keys; - } - except("DigiSegmentationTool", - "+++ collection_keys: Readout not valid. Is the proper detector set ?"); + vector<string> names = collection_names(); + for( const auto& collection : names ) + keys.emplace_back(Key(collection, mask)); return keys; } @@ -175,11 +181,12 @@ DigiSegmentationTool::split_segmentation(const string& split_by) const ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk); printout(INFO,"DigiSegmentationTool", - "%-24s has %ld parallel entries in when splitting by \"%s\"", + "%-24s has %ld parallel entries when splitting by \"%s\"", det, segmentation_splits.size(), split_by.c_str()); stringstream str; for( auto id : segmentation_splits ) str << setw(16) << hex << setfill('0') << id.first << " "; - printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s", det, str.str().c_str()); + printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s", + det, str.str().c_str()); return segmentation_splits; } diff --git a/DDDigi/src/DigiStoreDump.cpp b/DDDigi/src/DigiStoreDump.cpp index 168cc9002232492b1939731bc6e39a3e41521579..f01ae514524a98f17e73503c6e0637561096ed6a 100644 --- a/DDDigi/src/DigiStoreDump.cpp +++ b/DDDigi/src/DigiStoreDump.cpp @@ -23,11 +23,13 @@ dd4hep::digi::DigiStoreDump::DigiStoreDump(const DigiKernel& krnl, const std::string& nam) : DigiEventAction(krnl, nam) { - declareProperty("history", this->m_dump_history = false); - declareProperty("data_segments", this->m_data_segments); - this->m_data_segments.push_back("input"); - this->m_data_segments.push_back("deposits"); - this->m_data_segments.push_back("data"); + declareProperty("history", m_dump_history = false); + declareProperty("data_segments", m_data_segments); + m_data_segments.push_back("input"); + m_data_segments.push_back("deposits"); + m_data_segments.push_back("data"); + m_data_segments.push_back("counts"); + m_data_segments.push_back("output"); InstanceCount::increment(this); } @@ -80,7 +82,7 @@ void dd4hep::digi::DigiStoreDump::dump(const std::string& tag, } std::lock_guard<std::mutex> record_lock(m_kernel.global_output_lock()); for(const auto& s : records) - this->info(s.c_str()); + info(s.c_str()); } /// Main functional callback @@ -88,6 +90,6 @@ void dd4hep::digi::DigiStoreDump::execute(DigiContext& context) const { const auto& event = context.event; for(const auto& segment : this->m_data_segments) { std::string seg = detail::str_upper(segment); - this->dump(seg, *event, event->get_segment(segment)); + dump(seg, *event, event->get_segment(segment)); } } diff --git a/examples/DDDigi/scripts/DigiTest.py b/examples/DDDigi/scripts/DigiTest.py index 371608fda9a571bdb1bdbc52d65107182a5cb4b1..f0cfb73a3c7333d633d26973c56c983995319308 100644 --- a/examples/DDDigi/scripts/DigiTest.py +++ b/examples/DDDigi/scripts/DigiTest.py @@ -35,19 +35,19 @@ logger = logging.getLogger(__name__) F4183035 SiTrackerEndcapHits : map<long long, EnergyDeposit> """ -attenuation = {'SiVertexEndcapHits': 15 * ns, - 'SiVertexBarrelHits': 15 * ns, - 'SiTrackerForwardHits': 15 * ns, - 'SiTrackerEndcapHits': 15 * ns, - 'SiTrackerBarrelHits': 15 * ns, - 'HcalPlugHits': 15 * ns, - 'HcalEndcapHits': 15 * ns, - 'HcalBarrelHits': 15 * ns, - 'EcalEndcapHits': 15 * ns, - 'MuonEndcapHits': 15 * ns, - 'MuonBarrelHits': 15 * ns, - 'BeamCalHits': 15 * ns, - 'LumiCalHits': 15 * ns, +attenuation = {'SiVertexEndcapHits': 50 * ns, + 'SiVertexBarrelHits': 50 * ns, + 'SiTrackerForwardHits': 50 * ns, + 'SiTrackerEndcapHits': 50 * ns, + 'SiTrackerBarrelHits': 50 * ns, + 'HcalPlugHits': 50 * ns, + 'HcalEndcapHits': 50 * ns, + 'HcalBarrelHits': 50 * ns, + 'EcalEndcapHits': 50 * ns, + 'MuonEndcapHits': 50 * ns, + 'MuonBarrelHits': 50 * ns, + 'BeamCalHits': 50 * ns, + 'LumiCalHits': 50 * ns, } @@ -82,16 +82,19 @@ class Test(dddigi.Digitize): def data_containers(self): return list(self.attenuation.keys()) - def containers(self, count): - conts = [] - result = [] - for key in list(self.attenuation.keys()): - conts.append(key) - if len(conts) == count: + def containers(self, count=None): + if count: + conts = [] + result = [] + for key in list(self.attenuation.keys()): + conts.append(key) + if len(conts) == count: + result.append(conts) + conts = [] + if len(conts) > 0: result.append(conts) - conts = [] - if len(conts) > 0: - result.append(conts) + else: + result = list(self.attenuation.keys()) return result def check_creation(self, objs): diff --git a/examples/DDDigi/scripts/TestHitProcessing.py b/examples/DDDigi/scripts/TestHitProcessing.py new file mode 100644 index 0000000000000000000000000000000000000000..ea61322503284434e4a9f86e143ee22e123774fb --- /dev/null +++ b/examples/DDDigi/scripts/TestHitProcessing.py @@ -0,0 +1,66 @@ +# ========================================================================== +# AIDA Detector description implementation +# -------------------------------------------------------------------------- +# Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +# All rights reserved. +# +# For the licensing terms see $DD4hepINSTALL/LICENSE. +# For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +# +# ========================================================================== +from __future__ import absolute_import + + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + + input = digi.input_action('DigiParallelActionSequence/READER') + # ======================================================================================================== + digi.info('Created SIGNAL input') + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input=[digi.next_input()]) + digi.check_creation([signal]) + # ======================================================================================================== + digi.info('Creating collision overlays....') + # ======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1') + evtreader = overlay.adopt_action('DigiROOTInput/Read-1', mask=0x1, input=[digi.next_input()]) + hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-1', masks=[evtreader.mask]) + digi.check_creation([overlay, evtreader, hist_drop]) + digi.info('Created input.overlay-1') + # ======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-2') + evtreader = overlay.adopt_action('DigiROOTInput/Read-2', mask=0x2, input=[digi.next_input()]) + hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-2', masks=[evtreader.mask]) + digi.check_creation([overlay, evtreader, hist_drop]) + digi.info('Created input.overlay-2') + # ======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', + parallel=True, + input_masks=[0x0, 0x1, 0x2, 0x3], + output_mask=0xFEED, + output_segment='deposits', + erase_combined=False) + combine.erase_combined = True + dump = event.adopt_action('DigiStoreDump/StoreDump') + proc = event.adopt_action('DigiContainerSequenceAction/HitP1', parallel=True, input_mask=0xFEED, input_segment='deposits') + count = digi.create_action('DigiCellMultiplicityCounter/CellCounter') + proc.adopt_container_processor(count, digi.containers()) + proc = event.adopt_action('DigiContainerSequenceAction/HitP2', parallel=True, + input_mask=0xFEED, + input_segment='deposits', + output_mask = 0x0, + output_segment='output') + count = digi.create_action('DigiDepositMapCreator/CellCreator') + proc.adopt_container_processor(count, digi.containers()) + + digi.check_creation([combine, dump, proc]) + digi.info('Created event.dump') + + # ======================================================================================================== + digi.run_checked(num_events=5, num_threads=5, parallel=3) + + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/scripts/TestMultiContainerParallel.py b/examples/DDDigi/scripts/TestMultiContainerParallel.py index 33ded1c591a68eca15ffc0c483c29b12a26cfa6b..8934b1fb39a4e7089ee043f293a76f1fd7a78b43 100644 --- a/examples/DDDigi/scripts/TestMultiContainerParallel.py +++ b/examples/DDDigi/scripts/TestMultiContainerParallel.py @@ -29,10 +29,6 @@ def run(): for i in range(len(conts)): merge = dddigi.Action(digi.kernel(), 'DigiContainerProcessor/SegmentPrint_%03d' % (i,)) proc.adopt_processor(merge, conts[i]) - - # dump = event.adopt_action('DigiStoreDump/StoreDump') - # digi.check_creation([combine, dump, splitter]) - # digi.info('Created event.dump') # ======================================================================== digi.run_checked(num_events=5, num_threads=15, parallel=3) diff --git a/examples/DDDigi/scripts/TestMultiInteractions.py b/examples/DDDigi/scripts/TestMultiInteractions.py index 35f5152e3877bc7212aee1f6e2dada2640653259..b20a45553f06c12b9d93830499a55a45a9c0b87d 100644 --- a/examples/DDDigi/scripts/TestMultiInteractions.py +++ b/examples/DDDigi/scripts/TestMultiInteractions.py @@ -45,7 +45,8 @@ def run(): combine = event.adopt_action('DigiContainerCombine/Combine', parallel=True, input_masks=[0x0, 0x1, 0x2, 0x3], - deposit_mask=0xFEED, + output_mask=0xFEED, + output_segment='deposits', erase_combined=False) combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence dump = event.adopt_action('DigiStoreDump/StoreDump') diff --git a/examples/DDDigi/scripts/TestSegmentationSplit.py b/examples/DDDigi/scripts/TestSegmentationSplit.py index 5283350c200cb38b4f706d11718ade56e55e22d0..fde6a62666ffb1463a6c4d2734e8b0fb44026993 100644 --- a/examples/DDDigi/scripts/TestSegmentationSplit.py +++ b/examples/DDDigi/scripts/TestSegmentationSplit.py @@ -23,7 +23,7 @@ def run(): # ======================================================================== event = digi.event_action('DigiSequentialActionSequence/EventAction') combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0], deposit_mask=0xFEED) - combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence + combine.erase_combined = False # Not thread-safe! only do in SequentialActionSequence split_action = event.adopt_action('DigiContainerSequenceAction/SplitSequence', parallel=True, input_segment='deposits', @@ -33,7 +33,7 @@ def run(): split_by='layer', detector='SiTrackerBarrel', processor_type='DigiSegmentDepositPrint') - split_action.adopt_container_processor(splitter, 'SiTrackerBarrelHits') + split_action.adopt_container_processor(splitter, splitter.collection_names()) dump = event.adopt_action('DigiStoreDump/StoreDump') digi.check_creation([combine, dump, splitter]) diff --git a/examples/DDDigi/scripts/TestSpillover.py b/examples/DDDigi/scripts/TestSpillover.py index 59471682d41ee49e06197db70d77eff9b07153db..e3ef4562d806ede03f2fd1dbeb5a6b8447383775 100644 --- a/examples/DDDigi/scripts/TestSpillover.py +++ b/examples/DDDigi/scripts/TestSpillover.py @@ -27,24 +27,28 @@ def run(): # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-25') evtreader = spillover.adopt_action('DigiROOTInput/Reader-25ns', mask=0x1, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-25ns', - t0=-25 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-25ns', + t0=-25 * ns, + signal_decay='exponential', + processor_type='DigiAttenuator', + mask=evtreader.mask, + containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-25ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover25') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-50') evtreader = spillover.adopt_action('DigiROOTInput/Reader-50ns', mask=0x2, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-50ns', - t0=-50 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-50ns', + t0=-50 * ns, mask=evtreader.mask, containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-50ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover50') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-75') evtreader = spillover.adopt_action('DigiROOTInput/Reader-75ns', mask=0x3, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-75ns', - t0=-75 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-75ns', + t0=-75 * ns, mask=evtreader.mask, containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-75ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover75') @@ -53,24 +57,24 @@ def run(): # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+25') evtreader = spillover.adopt_action('DigiROOTInput/Reader+25ns', mask=0x4, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+25ns', - t0=25 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+25ns', + t0=25 * ns, mask=evtreader.mask, containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+25ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover25') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+50') evtreader = spillover.adopt_action('DigiROOTInput/Reader+50ns', mask=0x5, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+50ns', - t0=50 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+50ns', + t0=50 * ns, mask=evtreader.mask, containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop_50ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover50') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+75') evtreader = spillover.adopt_action('DigiROOTInput/Reader+75ns', mask=0x6, input=[digi.next_input()]) - attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+75ns', - t0=75 * ns, masks=[evtreader.mask], containers=attenuation) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+75ns', + t0=75 * ns, mask=evtreader.mask, containers=attenuation) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+75ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover75') @@ -78,7 +82,8 @@ def run(): event = digi.event_action('DigiSequentialActionSequence/EventAction') combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6], - deposit_mask=0xFEED) + output_mask=0xFEED, + output_segment='deposits') combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence evtdump = event.adopt_action('DigiStoreDump/StoreDump') digi.check_creation([combine, evtdump])