diff --git a/DDCore/include/DD4hep/ComponentProperties.h b/DDCore/include/DD4hep/ComponentProperties.h index bb354cb40bc619525af0cdbd79374d6e65967c45..cce28c8b713ad0fd6df759a6cb14d4b9b16c6f73 100644 --- a/DDCore/include/DD4hep/ComponentProperties.h +++ b/DDCore/include/DD4hep/ComponentProperties.h @@ -268,7 +268,7 @@ namespace dd4hep { template <typename FUNCTOR> void for_each(const FUNCTOR& func) { std::for_each(m_properties.begin(), m_properties.end(), func); } - /// Export properties of another instance + /// Import properties of another instance void adopt(const PropertyManager& copy); /// Dump string values void dump() const; diff --git a/DDCore/include/Parsers/Printout.h b/DDCore/include/Parsers/Printout.h index 98b3fbd43e0dfa788376bdf5f473de524a19bb99..6a96d5a98f21131f11ee2a89fcf098877fb75c72 100644 --- a/DDCore/include/Parsers/Printout.h +++ b/DDCore/include/Parsers/Printout.h @@ -44,7 +44,19 @@ namespace dd4hep { WARNING = 4, ERROR = 5, FATAL = 6, - ALWAYS = 7 + ALWAYS = 7, + + /// Forced printout levels if the output level is handled + /// e.g. by a Geant4Action or DigiAction. These always pass + /// The default DD4hep print level restrictions. + FORCE_LEVEL = 0x10, + FORCE_VERBOSE = FORCE_LEVEL + 1, + FORCE_DEBUG = FORCE_LEVEL + 2, + FORCE_INFO = FORCE_LEVEL + 3, + FORCE_WARNING = FORCE_LEVEL + 4, + FORCE_ERROR = FORCE_LEVEL + 5, + FORCE_FATAL = FORCE_LEVEL + 6, + FORCE_ALWAYS = FORCE_LEVEL + 7 }; #ifndef __CINT__ diff --git a/DDCore/python/dd4hep_base.py b/DDCore/python/dd4hep_base.py index b0921a864722b3aa0dc12a73372755d97878cd3b..713f057e36bb71a4cc98d651d8c1dbe8ef292ed8 100644 --- a/DDCore/python/dd4hep_base.py +++ b/DDCore/python/dd4hep_base.py @@ -124,6 +124,14 @@ def unicode_2_string(value): OutputLevel = _Levels() +VERBOSE = OutputLevel.VERBOSE +DEBUG = OutputLevel.DEBUG +INFO = OutputLevel.INFO +WARNING = OutputLevel.WARNING +ERROR = OutputLevel.ERROR +FATAL = OutputLevel.FATAL + + # ------------------------Generic STL stuff can be accessed using std: ----- # # -- e.g. Create an instance of std::vector<dd4hep::sim::Geant4Vertex*>: @@ -149,7 +157,8 @@ import_namespace_item('core', 'NamedObject') import_namespace_item('core', 'run_interpreter') # import_namespace_item('detail', 'interp') -import_namespace_item('detail', 'eval') +# No: This inhibits the usage of native python eval! +# import_namespace_item('detail', 'eval') # --------------------------------------------------------------------------- # def run_interpreter(name): detail.interp.run(name) diff --git a/DDCore/src/ComponentProperties.cpp b/DDCore/src/ComponentProperties.cpp index 92b5d2f82b7fc99d64bed40b7abca9561cdb019f..867c314d030323104f278528763c5736df78de48 100644 --- a/DDCore/src/ComponentProperties.cpp +++ b/DDCore/src/ComponentProperties.cpp @@ -135,7 +135,7 @@ size_t PropertyManager::size() const { return m_properties.size(); } -/// Export properties of another instance +/// Import properties of another instance void PropertyManager::adopt(const PropertyManager& copy) { m_properties = copy.m_properties; } diff --git a/DDCore/src/Printout.cpp b/DDCore/src/Printout.cpp index d0a6bfd15799d22127fd09dfd014d63af3dcb79f..79b49f467ba7d0f15c9ee3d8d4b57e0d130fbe17 100644 --- a/DDCore/src/Printout.cpp +++ b/DDCore/src/Printout.cpp @@ -242,7 +242,7 @@ int dd4hep::printout(PrintLevel severity, const string& src, const string& fmt, */ int dd4hep::printout(PrintLevel severity, const char* src, const char* fmt, va_list& args) { if (severity >= print_lvl) { - print_func_2(print_arg, severity,src,fmt,args); + print_func_2(print_arg, PrintLevel(severity&(~FORCE_LEVEL)), src, fmt, args); } return 1; } diff --git a/DDDigi/ddg4/DigiDDG4Input.cpp b/DDDigi/ddg4/DigiDDG4Input.cpp index 9c9c5101fe92ada613847a3905352d23f8251824..5aeb34738ba53947ab553672e55d059b92cc6969 100644 --- a/DDDigi/ddg4/DigiDDG4Input.cpp +++ b/DDDigi/ddg4/DigiDDG4Input.cpp @@ -37,8 +37,11 @@ namespace dd4hep { class DigiDDG4ROOT : public DigiROOTInput { public: static constexpr double epsilon = std::numeric_limits<double>::epsilon(); + /// Property to generate extra history records - bool m_seperate_history { false }; + bool m_seperate_history { true }; + bool m_keep_raw { false }; + mutable TClass* m_trackerHitClass { nullptr }; mutable TClass* m_caloHitClass { nullptr }; mutable TClass* m_particlesClass { nullptr }; @@ -77,11 +80,15 @@ namespace dd4hep { : DigiROOTInput(krnl, nam) { declareProperty("seperate_history", m_seperate_history); + declareProperty("keep_raw", m_keep_raw); } template <typename T> - void conv_hits(DataSegment& segment, const std::string& tag, int mask, const char* name, void* ptr) const { + void conv_hits(DigiContext& context, DataSegment& segment, + const std::string& tag, int mask, const char* name, void* ptr) const + { using wrap_t = std::shared_ptr<sim::Geant4HitData>; + bool sep_history = m_seperate_history; std::size_t len = 0; std::string nam = name; std::vector<wrap_t> geant4_hits; @@ -93,6 +100,8 @@ namespace dd4hep { auto* p = (*data.items)[i]; if ( p->energyDeposit > epsilon ) { Key history_key; + CellID cell = p->cellID; + wrap_t raw(p); EnergyDeposit dep { }; Position pos = p->position; pos *= 1./dd4hep::mm; @@ -102,34 +111,41 @@ namespace dd4hep { dep.position = pos; history_key.set_mask(Key::mask_type(mask)); - history_key.set_item(geant4_hits.size()); + history_key.set_item(out.size()); history_key.set_segment(segment.id); - dep.history.hits.emplace_back(history_key, dep.deposit); - add_particle_history(p, history_key, dep.history); - - out.emplace(p->cellID, std::move(dep)); - if ( m_seperate_history ) { - hist.insert(p->cellID, dep.history); + if ( sep_history ) { + History entry { }; + entry.hits.emplace_back(history_key, dep.deposit); + add_particle_history(p, history_key, entry); + hist.emplace(cell, std::move(entry)); + } + out.emplace(cell, std::move(dep)); + if ( m_keep_raw ) { + geant4_hits.emplace_back(std::move(raw)); } - geant4_hits.emplace_back(wrap_t(p)); } } len = data.items->size(); data.items->clear(); } - debug("++ Converted %ld %s to %ld cell deposits", len, tag.c_str(), out.size()); + info("%s++ %-24s Converted %6ld DDG4 %-14s hits to %6ld cell deposits", + context.event->id(), name, len, tag.c_str(), out.size()); Key depo_key(out.name, mask); segment.emplace(depo_key, std::make_any<DepositVector>(std::move(out))); - Key src_key(nam+".ddg4", mask); - segment.emplace(src_key, std::make_any<std::vector<wrap_t>>(std::move(geant4_hits))); - if ( m_seperate_history ) { + if ( m_keep_raw ) { + Key src_key(nam+".ddg4", mask); + segment.emplace(src_key, std::make_any<std::vector<wrap_t>>(std::move(geant4_hits))); + } + if ( sep_history ) { Key hist_key(hist.name, mask); segment.emplace(hist_key, std::make_any<DetectorHistory>(std::move(hist))); } } - void conv_particles(DataSegment& segment, int mask, const char* name, void* ptr) const { + void conv_particles(DigiContext& context, DataSegment& segment, + int mask, const char* name, void* ptr) const + { using wrap_t = std::shared_ptr<sim::Geant4Particle>; ParticleMapping out(name, mask); std::map<Key, wrap_t> source; @@ -156,15 +172,17 @@ namespace dd4hep { } items->clear(); } - debug("++ Converted %ld DDG4 particles", out.size()); + debug("%s++ Converted %ld DDG4 particles", context.event->id(), out.size()); std::string nam = name; segment.emplace(part_key, std::make_any<ParticleMapping>(std::move(out))); - Key src_key(nam+".ddg4", mask); - segment.emplace(src_key, std::make_any<std::map<Key, wrap_t> >(std::move(source))); + if ( m_keep_raw ) { + Key src_key(nam+".ddg4", mask); + segment.emplace(src_key, std::make_any<std::map<Key, wrap_t> >(std::move(source))); + } } /// Callback to handle single branch - virtual void operator()(DigiContext& /* context */, work_t& work) const override { + virtual void operator()(DigiContext& context, work_t& work) const override { TBranch& br = work.branch; TClass& cl = work.cl; TClass* c = get_class_pointers(&cl, br.GetClassName()); @@ -173,11 +191,11 @@ namespace dd4hep { int mask = work.input_key.mask(); auto& seg = work.input_segment; if ( c == m_caloHitClass ) - conv_hits<sim::Geant4Calorimeter::Hit>(seg, "DDG4 calorimeter hits", mask, nam, *addr); + conv_hits<sim::Geant4Calorimeter::Hit>(context, seg, "calorimeter", mask, nam, *addr); else if ( c == m_trackerHitClass ) - conv_hits<sim::Geant4Tracker::Hit>(seg, "DDG4 tracker hits", mask, nam, *addr); + conv_hits<sim::Geant4Tracker::Hit>(context, seg, "tracker", mask, nam, *addr); else if ( c == m_particlesClass ) - conv_particles(seg, mask, nam, *addr); + conv_particles(context, seg, mask, nam, *addr); else except("Unknown data type encountered in branch: %s", nam); } diff --git a/DDDigi/include/DDDigi/DigiAction.h b/DDDigi/include/DDDigi/DigiAction.h index d6c8ec41d0016269dd32b174ceeb9fdc1283f073..583f8c772c284d9f3dbc261afff843a8388029ad 100644 --- a/DDDigi/include/DDDigi/DigiAction.h +++ b/DDDigi/include/DDDigi/DigiAction.h @@ -102,7 +102,7 @@ namespace dd4hep { protected: #else - const kernel_t& m_kernel; + const kernel_t& m_kernel; #endif /// Action name std::string m_name; @@ -156,6 +156,7 @@ namespace dd4hep { /// Set the output level; returns previous value PrintLevel setOutputLevel(PrintLevel new_level); + /** Property access */ /// Declare property template <typename T> DigiAction& declareProperty(const std::string& nam, T& val); /// Declare property @@ -170,6 +171,8 @@ namespace dd4hep { Property& property(const std::string& name); /// Access single property (CONST) const Property& property(const std::string& name) const; + /// Print the property values + virtual std::size_t printProperties() const; /// Adopt named property of another action for data processing virtual void adopt_property(DigiAction* action, const std::string& foreign_name, const std::string& local_name); @@ -177,10 +180,13 @@ namespace dd4hep { /// Adopt named tool to delegate actions virtual void adopt_tool(DigiAction* action, const std::string& typ); + /** Support for output messages */ /// Support for messages with variable output level using output level void print(const char* fmt, ...) const; /// Support for building formatted messages std::string format(const char* fmt, ...) const; + /// Support of messages always printed. + void always(const char* fmt, ...) const; /// Support of debug messages. void debug(const char* fmt, ...) const; /// Support of info messages. diff --git a/DDDigi/include/DDDigi/DigiAttenuator.h b/DDDigi/include/DDDigi/DigiAttenuator.h index a5d85b88689e16b1ef083d3201581d008a43abc4..f492d48b49e0184c7e602164e6e46c4428b1aef4 100644 --- a/DDDigi/include/DDDigi/DigiAttenuator.h +++ b/DDDigi/include/DDDigi/DigiAttenuator.h @@ -87,6 +87,10 @@ namespace dd4hep { std::map<std::string, double> m_container_attenuation { }; /// Property: T0 with respect to central crossing double m_t0 { 0e0 }; + /// Property: Flag to act on hit input data + bool m_attenuate_data { true }; + /// Property: Flag to act on history objects as well + bool m_attenuate_history { true }; protected: /// Define standard assignments and constructors diff --git a/DDDigi/include/DDDigi/DigiContainerDrop.h b/DDDigi/include/DDDigi/DigiContainerDrop.h index 6083701174a12d89f95d1f4b1111cc684b53806a..9be69945344f48a5ea1ecaed0f8e3956cefb6092 100644 --- a/DDDigi/include/DDDigi/DigiContainerDrop.h +++ b/DDDigi/include/DDDigi/DigiContainerDrop.h @@ -35,9 +35,9 @@ namespace dd4hep { class DigiContainerDrop : public DigiEventAction { public: class work_definition_t; - using self_t = DigiContainerDrop; - using Worker = DigiParallelWorker<self_t,work_definition_t>; - using Workers = DigiParallelWorkers<Worker>; + using self_t = DigiContainerDrop; + using worker_t = DigiParallelWorker<self_t,work_definition_t>; + using workers_t = DigiParallelWorkers<worker_t>; protected: /// Property: Container names to be loaded @@ -52,7 +52,7 @@ namespace dd4hep { std::set<Key::itemkey_type> m_cont_keys { }; /// Worker objects to be submitted to TBB each performing part of the job - Workers m_workers; + workers_t m_workers; protected: /// Define standard assignments and constructors diff --git a/DDDigi/include/DDDigi/DigiContainerProcessor.h b/DDDigi/include/DDDigi/DigiContainerProcessor.h index 9be4485e7f907546178cffaeecbd3039479f87bb..5c83cfcf381f7e80c0ef0f2da341bec9a216a4d2 100644 --- a/DDDigi/include/DDDigi/DigiContainerProcessor.h +++ b/DDDigi/include/DDDigi/DigiContainerProcessor.h @@ -17,6 +17,7 @@ #include <DD4hep/Callback.h> #include <DDDigi/DigiData.h> #include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiDepositMonitor.h> #include <DDDigi/DigiParallelWorker.h> /// C/C++ include files @@ -29,6 +30,7 @@ namespace dd4hep { namespace digi { /// Forward declarations + class DigiDepositMonitor; class DigiSegmentContext; class DigiContainerSequence; class DigiContainerProcessor; @@ -52,10 +54,12 @@ namespace dd4hep { /// Input definition struct input_t { + /// Input segment reference + segment_t* segment; /// Input data key Key key; /// Input deposits - std::any& data; + std::any* data; }; /// Output handle definition @@ -66,11 +70,12 @@ namespace dd4hep { /// Hit processing predicate struct predicate_t { - using deposit_t = std::pair<const CellID, EnergyDeposit>; + using deposit_t = std::pair<const CellID, EnergyDeposit>; using callback_t = std::function<bool(const deposit_t&)>; callback_t callback { }; uint32_t id { 0 }; const segmentation_t* segmentation { nullptr }; + predicate_t() = default; predicate_t(std::function<bool(const deposit_t&)> func, uint32_t i, const segmentation_t* s) : callback(func), id(i), segmentation(s) {} @@ -80,22 +85,27 @@ namespace dd4hep { predicate_t& operator = (const predicate_t& copy) = default; /// Check if a deposit should be processed bool operator()(const deposit_t& deposit) const; - static bool always_true(const deposit_t&) { return true; } + static bool always_true(const deposit_t&) { return true; } + static bool not_killed (const deposit_t& depo) { return 0 == (depo.second.flag&EnergyDeposit::KILLED); } }; - /// Work definition - struct work_t { + struct env_t { /// Event processing context context_t& context; - /// Input data - input_t input; - /// Output data - output_t& output; /// Optional properties const property_t& properties; + /// Output data + output_t& output; + }; + + /// Work definition + struct work_t { + env_t environ; + /// Input data + input_t input; /// Basic check if input data are present - bool has_input() const { return this->input.data.has_value(); } + 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 @@ -106,20 +116,29 @@ namespace dd4hep { 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; + /// Access the deposit history of a deposit container + const DepositsHistory* get_history(const std::string& container, bool exc=false) const; }; + /// Monitoring object + DigiDepositMonitor* m_monitor { nullptr }; + protected: /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerProcessor); public: - /// Access to default callback + /// Access to default deposit predicate accepting all static const predicate_t& accept_all(); + /// Access to default deposit predicate accepting all + static const predicate_t& accept_not_killed(); /// Standard constructor DigiContainerProcessor(const kernel_t& kernel, const std::string& name); /// Default destructor virtual ~DigiContainerProcessor(); + /// Adopt monitoring action + void adopt_monitor(DigiDepositMonitor* monitor); /// Main functional callback adapter virtual void execute(context_t& context, work_t& work, const predicate_t& predicate) const; }; @@ -168,9 +187,9 @@ namespace dd4hep { /// Structure imports using self_t = DigiContainerSequence; using processor_t = DigiContainerProcessor; - using worker_t = DigiParallelWorker<processor_t,work_t>; + using worker_t = DigiParallelWorker<processor_t,work_t,std::size_t,self_t&>; using workers_t = DigiParallelWorkers<worker_t>; - friend class DigiParallelWorker<processor_t,work_t>; + friend class DigiParallelWorker<processor_t,work_t,std::size_t,self_t&>; protected: /** Member variables */ @@ -178,6 +197,9 @@ namespace dd4hep { bool m_parallel { false }; /// Array of sub-workers workers_t m_workers; + /// Default Deposit predicate + predicate_t m_worker_predicate = processor_t::accept_all(); + /// Lock for output merging mutable std::mutex m_output_lock; @@ -193,12 +215,28 @@ namespace dd4hep { public: /// Standard constructor DigiContainerSequence(const kernel_t& kernel, const std::string& name); + /// Set the default predicate + void set_predicate(const predicate_t& predicate); /// Adopt new parallel worker virtual void adopt_processor(DigiContainerProcessor* action); /// Main functional callback adapter virtual void execute(context_t& context, work_t& work, const predicate_t& predicate) const; }; + + struct DigiMultiProcessorParent { + public: + using action_t = DigiAction; + using processor_t = DigiContainerProcessor; + using env_t = processor_t::env_t; + using segment_t = processor_t::segment_t; + using predicate_t = processor_t::predicate_t; + using output_t = processor_t::output_t; + using property_t = processor_t::property_t; + using work_item_t = processor_t::input_t; + using work_items_t = std::vector<processor_t::input_t>; + }; + /// Worker base class to analyse containers from the input segment in parallel /** * Depending on the adopted processors, the full input record is scanned and @@ -208,55 +246,45 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiContainerSequenceAction : public DigiEventAction { + class DigiContainerSequenceAction : public DigiEventAction, public DigiMultiProcessorParent { protected: /// Structure imports - using action_t = DigiAction; using self_t = DigiContainerSequenceAction; - using processor_t = DigiContainerProcessor; - using output_t = processor_t::output_t; - using property_t = processor_t::property_t; - - /// Single worker work item definition - struct work_item_t { - Key key; - std::any* data; - }; - /// Work definition structure - /// Argument structure for client calls + /// Work definition structure: Argument structure for client calls struct work_t { - context_t& context; - std::vector<work_item_t> input_items; - output_t& output; - const property_t& properties; - const self_t& parent; + env_t& environ; + work_items_t& input_items; + const self_t& parent; }; - using worker_t = DigiParallelWorker<processor_t, work_t>; + using worker_t = DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>; using workers_t = DigiParallelWorkers<worker_t>; + using predicate_t = processor_t::predicate_t; using reg_workers_t = std::map<Key, worker_t*>; using reg_processors_t = std::map<Key, processor_t*>; - friend class DigiParallelWorker<processor_t, work_t>; - - /// Array of sub-workers - workers_t m_workers; - /// Registered action map - reg_processors_t m_registered_processors; - /// Registered worker map - reg_workers_t m_registered_workers; + friend class DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>; /// 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_input_mask { 0x0 }; + int m_input_mask { 0x0 }; /// Property: Input data segment name - std::string m_output_segment { "outputs" }; + std::string m_output_segment { "outputs" }; /// Property: event mask for output data - int m_output_mask { 0x0 }; + int m_output_mask { 0x0 }; + + /// Array of sub-workers + workers_t m_workers { }; + /// Registered action map + reg_processors_t m_registered_processors { }; + /// Registered worker map + reg_workers_t m_registered_workers { }; + /// Default Deposit predicate + predicate_t m_worker_predicate { processor_t::accept_all() }; /// Lock for output merging - mutable std::mutex m_output_lock; + mutable std::mutex m_output_lock { }; protected: /// Define standard assignments and constructors @@ -273,6 +301,8 @@ namespace dd4hep { public: /// Standard constructor DigiContainerSequenceAction(const kernel_t& kernel, const std::string& name); + /// Set the default predicate + void set_predicate(const predicate_t& predicate); /// 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 @@ -288,36 +318,30 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiMultiContainerProcessor : virtual public DigiEventAction { + class DigiMultiContainerProcessor : public DigiEventAction, public DigiMultiProcessorParent { protected: 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; - using property_t = processor_t::property_t; /// Argument structure required to support multiple client calls struct work_t { - context_t& context; - work_items_t& items; - output_t& output; - const property_t& properties; - const self_t& parent; + env_t& environ; + work_items_t& items; + const self_t& parent; }; - using worker_t = DigiParallelWorker<processor_t, work_t>; + using worker_t = DigiParallelWorker<processor_t, work_t, std::size_t, self_t&>; using workers_t = DigiParallelWorkers<worker_t>; - friend class DigiParallelWorker<processor_t, work_t>; + friend class DigiParallelWorker<processor_t, work_t, std::size_t, self_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 }; + int m_output_mask { 0x0 }; /// Set of container names to be used by this processor std::map<std::string, std::vector<processor_t*> > m_processors; @@ -329,11 +353,13 @@ namespace dd4hep { worker_keys_t m_worker_keys; /// Ordered list of actions registered std::vector<processor_t*> m_actions; + /// Default Deposit predicate + predicate_t m_worker_predicate = processor_t::accept_all(); /// Lock for output merging mutable std::mutex m_output_lock; /// Array of sub-workers - workers_t m_workers; + workers_t m_workers; protected: /// Define standard assignments and constructors @@ -352,6 +378,8 @@ namespace dd4hep { const std::vector<int>& input_masks() const { return this->m_input_masks; } + /// Set the default predicate + void set_predicate(const predicate_t& predicate); /// Adopt new parallel worker void adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers); /// Main functional callback diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index 4937b1753ed351c9c395eba6e084a93b19280a04..016f17d65a84477b87978fad0d32275a7944ed09 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -472,7 +472,8 @@ namespace dd4hep { POSITION_SMEARED = 1 << 2, TIME_SMEARED = 1 << 3, ZERO_SUPPRESSED = 1 << 4, - RECALIBRATED = 1 << 5 + DEPOSIT_NOISE = 1 << 5, + RECALIBRATED = 1 << 6 }; /// Hit position @@ -490,9 +491,6 @@ namespace dd4hep { /// Source mask of this deposit Key::mask_type mask { 0 }; - /// Sources contributing to this deposit - History history; - public: /// Default constructor EnergyDeposit() = default; @@ -807,6 +805,7 @@ namespace dd4hep { inline void DetectorHistory::insert(CellID cell, const History& value) { this->data.emplace_back(cell, value); } + typedef DetectorHistory DepositsHistory; /// Data segment definition (locked map) diff --git a/DDDigi/include/DDDigi/DigiDepositMonitor.h b/DDDigi/include/DDDigi/DigiDepositMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..1a4a15d818f79478de23bf154b2b87912724e00a --- /dev/null +++ b/DDDigi/include/DDDigi/DigiDepositMonitor.h @@ -0,0 +1,231 @@ +//========================================================================== +// 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_DIGIDEPOSITMONITOR_H +#define DDDIGI_DIGIDEPOSITMONITOR_H + +/// Framework include files +#include <DDDigi/DigiData.h> +#include <DDDigi/DigiAction.h> +#include <DDDigi/DigiMonitorOptions.h> + +/// Forward declarations +class TH1; +class TH2; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + template <typename HISTO> class Histogram { + friend class DigiKernel; + friend class DigiDepositMonitor; + protected: + HISTO* hist { nullptr }; + public: + Histogram(HISTO* h) : hist(h) {} + }; + + /// Wrapper for 1 dimensional monitoring histograms + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class Histo1D : public Histogram<TH1> { + public: + /// Add 1D histogram entry with weight + void fill(double x, double weight=1.0); + }; + + /// Wrapper for 2 dimensional monitoring histograms + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class Histo2D : public Histogram<TH2> { + public: + /// Add 2D histogram entry with weight + void fill(double x, double y, double weight=1.0); + }; + + /// Monitor base class to histogram deposit property changes + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositMonitor : public DigiAction { + + protected: + using deposit_t = std::pair<CellID, EnergyDeposit>; + + std::function<void(std::size_t, std::size_t )> count_shift_monitor + { [](std::size_t, std::size_t) {} }; + std::function<void(const deposit_t& , double )> time_shift_monitor + { [](const deposit_t&, double) {} }; + std::function<void(const deposit_t& , double )> energy_shift_monitor + { [](const deposit_t&, double) {} }; + std::function<void(const deposit_t& , const Position&, const Position& )> position_shift_monitor + { [](const deposit_t&, const Position&, const Position&) {} }; + + template <typename T> void declare_monitor_time(T* object, void (T::*pmf)(const deposit_t& , double)) { + time_shift_monitor = std::bind(pmf, object, std::placeholders::_1, std::placeholders::_2); + } + template <typename T> void declare_monitor_energy(T* object, void (T::*pmf)(const deposit_t& , double)) { + energy_shift_monitor = std::bind(pmf, object, std::placeholders::_1, std::placeholders::_2); + } + template <typename T> void declare_monitor_count(T* object, void (T::*pmf)(std::size_t, std::size_t)) { + count_shift_monitor = std::bind(pmf, object, std::placeholders::_1, std::placeholders::_2); + } + template <typename T> void declare_monitor_position(T* object, void (T::*pmf)(const deposit_t& , const Position&, const Position&)) { + position_shift_monitor = std::bind(pmf, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + } + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiDepositMonitor); + + /// Default destructor + virtual ~DigiDepositMonitor(); + + /// Initializing function: overload for sub-classes to e.g. book histograms + virtual void initialize(); + + /// Book 1D histogram and register it to the kernel for output handling + Histo1D book1D(const std::string& name, const std::string& title, + std::size_t nbin_x, double min_x, double max_x); + + /// Book 1D histogram and register it to the kernel for output handling + Histo2D book2D(const std::string& name, const std::string& title, + std::size_t nbin_x, double min_x, double max_x, + std::size_t nbin_y, double min_y, double max_y); + + public: + /// Standard constructor + DigiDepositMonitor(const kernel_t& kernel, const std::string& name); + + inline void time_shift(const deposit_t& deposit, double change) { + time_shift_monitor(deposit, change); + } + inline void energy_shift(const deposit_t& deposit, double change) { + energy_shift_monitor(deposit, change); + } + inline void position_shift(const deposit_t& deposit, const Position& position, const Position& change) { + position_shift_monitor(deposit, position, change); + } + inline void count_shift(std::size_t start_value, std::size_t change) { + count_shift_monitor(start_value, change); + } + }; + + /// Monitor base class to histogram the changes of the proper time of energy deposits + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositTimeMonitor : public DigiDepositMonitor { + + protected: + /// Property with the 1D histogram parameters to fill the histogram with deposits + H1DParams histo1D_deposits { "", "", -1, 0e0, 0e0 }; + /// Property with the 1D histogram parameters to fill the histogram with deposit deltas + H1DParams histo1D_delta { "", "", -1, 0e0, 0e0 }; + + /// Pointer to deposit histogram + Histo1D m_deposits { nullptr }; + /// Pointer to delta histogram + Histo1D m_deltas { nullptr }; + + /// Initializing function: overload for sub-classes to e.g. book histograms + virtual void initialize(); + + /// Fill the monitoring histograms + void monitor_time_shift(const deposit_t& deposit, double change); + + public: + /// Standard constructor + DigiDepositTimeMonitor(const kernel_t& kernel, const std::string& name); + }; + + /// Monitor base class to histogram energy deposit changes + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositEnergyMonitor : public DigiDepositMonitor { + protected: + /// Property with the 1D histogram parameters to fill the histogram with deposits + H1DParams histo1D_deposits { "", "", -1, 0e0, 0e0 }; + /// Property with the 1D histogram parameters to fill the histogram with deposit deltas + H1DParams histo1D_delta { "", "", -1, 0e0, 0e0 }; + + /// Pointer to deposit histogram + Histo1D m_deposits { nullptr }; + /// Pointer to delta histogram + Histo1D m_deltas { nullptr }; + + /// Initializing function: overload for sub-classes to e.g. book histograms + virtual void initialize(); + + /// Fill the monitoring histograms + void monitor_energy_shift(const deposit_t& deposit, double change); + + public: + /// Standard constructor + DigiDepositEnergyMonitor(const kernel_t& kernel, const std::string& name); + }; + + /// Monitor base class to histogram the changes of the position of energy deposits + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositPositionMonitor : public DigiDepositMonitor { + + protected: + /// Property with the 1D histogram parameters to fill the histogram with deposits + H1DParams histo1D_deposits { "", "", -1, 0e0, 0e0 }; + /// Property with the 1D histogram parameters to fill the histogram with deposit deltas + H1DParams histo1D_delta { "", "", -1, 0e0, 0e0 }; + + /// Pointer to deposit histogram + Histo1D m_deposits { nullptr }; + /// Pointer to delta histogram + Histo1D m_deltas { nullptr }; + + /// Initializing function: overload for sub-classes to e.g. book histograms + virtual void initialize(); + + /// Fill the monitoring histograms + void monitor_position_shift(const deposit_t& deposit, const Position& position, const Position& change); + + public: + /// Standard constructor + DigiDepositPositionMonitor(const kernel_t& kernel, const std::string& name); + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGIDEPOSITMONITOR_H diff --git a/DDDigi/include/DDDigi/DigiHandle.h b/DDDigi/include/DDDigi/DigiHandle.h index b2fedc28350560b5f7ba0232ae6d4e14d24ab1ad..3be1457d87fb503c8f7477db389381438e4cd9e3 100644 --- a/DDDigi/include/DDDigi/DigiHandle.h +++ b/DDDigi/include/DDDigi/DigiHandle.h @@ -57,6 +57,8 @@ namespace dd4hep { DigiKernel* get() const { return value; } /// Access to the underlying object DigiKernel* operator->() const { return value; } + /// Property accessor + Property& operator[](const std::string& property_name) const; /// Access to worker thread KernelHandle worker(); /// Destroy referenced object (program termination) diff --git a/DDDigi/include/DDDigi/DigiKernel.h b/DDDigi/include/DDDigi/DigiKernel.h index 85b374db36d6c713603aab255ec56796319ff96c..1250477789219b7209ae7296339c437dc8fe86b2 100644 --- a/DDDigi/include/DDDigi/DigiKernel.h +++ b/DDDigi/include/DDDigi/DigiKernel.h @@ -13,14 +13,17 @@ #ifndef DDDIGI_DIGIKERNEL_H #define DDDIGI_DIGIKERNEL_H -// Framework include files -#include <DDDigi/DigiEventAction.h> +/// Framework include files +#include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiParallelWorker.h> -// C/C++ include files +/// C/C++ include files #include <mutex> #include <memory> +/// Forward declarations +class TH1; + /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -39,7 +42,7 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiKernel { + class DigiKernel : public DigiAction { public: typedef std::map<std::string,int> ClientOutputLevels; typedef std::pair<void*, const std::type_info*> UserFramework; @@ -100,24 +103,10 @@ namespace dd4hep { std::mutex& global_output_lock() const; /** Property access */ - /// Access to the properties of the object - PropertyManager& properties(); /// Print the property values - void printProperties() const; - /// Declare property - template <typename T> DigiKernel& declareProperty(const std::string& nam, T& val); - /// Declare property - template <typename T> DigiKernel& declareProperty(const char* nam, T& val); - /// Check property for existence - bool hasProperty(const std::string& name) const; - /// Access single property - Property& property(const std::string& name); - - /** Output level settings */ - /// Access the output level - PrintLevel outputLevel() const; - /// Set the global output level of the kernel object; returns previous value - PrintLevel setOutputLevel(PrintLevel new_level); + virtual std::size_t printProperties() const override; + + /** Client output level settings */ /// Fill cache with the global output level of a named object. Must be set before instantiation void setOutputLevel(const std::string object, PrintLevel new_level); /// Retrieve the global output level of a named object. @@ -141,6 +130,9 @@ namespace dd4hep { /// Register end event callback. Signature: (function)(DigiContext*) void register_end_event(const std::function<void(DigiContext&)>& callback) const; + /// Registration of monitoring objects eventually saved by the handler + void register_monitor(DigiAction* action, TNamed* histo) const; + /// Construct detector geometry using description plugin virtual void loadGeometry(const std::string& compact_file); /// Load XML file @@ -172,18 +164,6 @@ namespace dd4hep { virtual void wait(DigiContext& context) const; }; - - /// Declare property - template <typename T> inline DigiKernel& DigiKernel::declareProperty(const std::string& nam, T& val) { - properties().add(nam, val); - return *this; - } - - /// Declare property - template <typename T> inline DigiKernel& DigiKernel::declareProperty(const char* nam, T& val) { - properties().add(nam, val); - return *this; - } } // End namespace digi } // End namespace dd4hep #endif // DDDIGI_DIGIKERNEL_H diff --git a/DDDigi/include/DDDigi/DigiMonitorHandler.h b/DDDigi/include/DDDigi/DigiMonitorHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..9e12a285610015203cf90760488fa5d2b162d53e --- /dev/null +++ b/DDDigi/include/DDDigi/DigiMonitorHandler.h @@ -0,0 +1,59 @@ +//========================================================================== +// 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_DIGIMONITORHANDLER_H +#define DDDIGI_DIGIMONITORHANDLER_H + +/// Framework include files +#include <DDDigi/DigiAction.h> + +/// C/C++ include files +class TNamed; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + // Forward declarations + class DigiMonitorHandler; + + /// Class to execute non-reentrant subhandler in wrapped mode + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiMonitorHandler : public DigiAction { + protected: + /// Property: output file name if monitor saving is desired (delegated to kernel) + std::string m_output_file; + + /// Map of monitoring items + std::map<DigiAction*, std::set<TNamed*> > m_monitors; + + public: + /// Standard constructor + DigiMonitorHandler(const kernel_t& kernel, const std::string& nam); + /// Standard destructor + virtual ~DigiMonitorHandler(); + /// Adopt monitor and keep reference for saving + void adopt(DigiAction* source, TNamed* object); + /// Save monitors + void save(); + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGIMONITORHANDLER_H diff --git a/DDDigi/include/DDDigi/DigiMonitorOptions.h b/DDDigi/include/DDDigi/DigiMonitorOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..d3ecf519db956f0d38240ccf053674a46b93aaa5 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiMonitorOptions.h @@ -0,0 +1,59 @@ +//========================================================================== +// 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_DIGIMONITOROPTIONS_H +#define DDDIGI_DIGIMONITOROPTIONS_H + +/// Framework include files +#include <DDDigi/DigiAction.h> +#include <DDDigi/DigiData.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Property to parse 1D histogram options + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class H1DParams { + public: + std::string name; + std::string title; + int nbin_x; + double min_x, max_x; + }; + + /// Property to parse 2D histogram options + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class H2DParams { + public: + std::string name; + std::string title; + int nbin_x; + double min_x, max_x; + int nbin_y; + double min_y, max_y; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGIMONITOROPTIONS_H diff --git a/DDDigi/include/DDDigi/DigiParallelWorker.h b/DDDigi/include/DDDigi/DigiParallelWorker.h index ae1316f1ab1562c1e404d176bd1b508c4af9b2f3..4d6eab39707b2a53006baf040b497d48041d846d 100644 --- a/DDDigi/include/DDDigi/DigiParallelWorker.h +++ b/DDDigi/include/DDDigi/DigiParallelWorker.h @@ -22,6 +22,9 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + /// Forward declarations + class WorkerPredicate; + /// Wrapper class to submit bulk actions /** * @@ -48,19 +51,21 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS=std::size_t> + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS=std::size_t, typename PREDICATE=std::size_t> class DigiParallelWorker : public ParallelWorker { public: using action_t = ACTION_TYPE; using options_t = OPTIONS; using calldata_t = CALLDATA; - - action_t* action { nullptr }; - options_t options { nullptr }; + using predicate_t = PREDICATE; + + action_t* action { nullptr }; + options_t options { nullptr }; + predicate_t predicate { nullptr }; public: /// Initializing constructor - DigiParallelWorker(ACTION_TYPE* p, const OPTIONS& opts); + DigiParallelWorker(action_t* a, const options_t& opts, const predicate_t& p={}); /// Default constructor DigiParallelWorker() = delete; /// Move constructor @@ -80,16 +85,16 @@ namespace dd4hep { }; /// Initializing constructor - template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS> - DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS>::DigiParallelWorker(ACTION_TYPE* proc, const OPTIONS& opts) - : ParallelWorker(), action(proc), options(opts) + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS, typename PREDICATE> + DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS, PREDICATE>::DigiParallelWorker(action_t* a, const options_t& o, const predicate_t& p) + : ParallelWorker(), action(a), options(o), predicate(p) { if ( action ) action->addRef(); } /// Default destructor - template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS> - DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS>::~DigiParallelWorker() { + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS, typename PREDICATE> + DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS, PREDICATE>::~DigiParallelWorker() { if ( action ) { action->release(); action = nullptr; diff --git a/DDDigi/include/DDDigi/DigiParallelWorkers.h b/DDDigi/include/DDDigi/DigiParallelWorkers.h index a078abe4cdc3fa7d67bb89015e4a6c86d56c04a6..72c8c4d0421aadb2f6b75f36b639b8b54ddad320 100644 --- a/DDDigi/include/DDDigi/DigiParallelWorkers.h +++ b/DDDigi/include/DDDigi/DigiParallelWorkers.h @@ -29,7 +29,6 @@ namespace dd4hep { /// Forward declarations class ParallelWorker; - template <typename T, typename A, typename O> class DigiParallelWorker; template <typename T> class DigiParallelWorkers; template <typename T> class DigiParallelWorkerGroup; diff --git a/DDDigi/include/DDDigi/DigiSegmentSplitter.h b/DDDigi/include/DDDigi/DigiSegmentSplitter.h index 0c59ba13e5fa8ba95eef4d8129e0c868fa7e8fb8..a433e060351db480a2c5922a69c756ba861d4b93 100644 --- a/DDDigi/include/DDDigi/DigiSegmentSplitter.h +++ b/DDDigi/include/DDDigi/DigiSegmentSplitter.h @@ -111,7 +111,7 @@ namespace dd4hep { using segment_t = DigiSegmentProcessContext; using processor_t = DigiContainerProcessor; - using worker_t = DigiParallelWorker<processor_t,work_t, segment_t>; + using worker_t = DigiParallelWorker<processor_t, work_t, segment_t>; using workers_t = DigiParallelWorkers<worker_t>; friend class DigiParallelWorker<processor_t, work_t, segment_t>; @@ -138,6 +138,7 @@ namespace dd4hep { splits_t m_splits; /// Array of sub-workers workers_t m_workers; + /// Lock for output merging mutable std::mutex m_output_lock; /// Segmentation too instance diff --git a/DDDigi/include/DDDigi/DigiSynchronize.h b/DDDigi/include/DDDigi/DigiSynchronize.h index 6a16e2b4547c748ba1c557705790bfd78c64cae2..e4c5cbee780231f58892b826647c6fb0e5388bd0 100644 --- a/DDDigi/include/DDDigi/DigiSynchronize.h +++ b/DDDigi/include/DDDigi/DigiSynchronize.h @@ -34,10 +34,14 @@ namespace dd4hep { */ class DigiSynchronize : public DigiEventAction { protected: - using Worker = DigiParallelWorker<DigiEventAction,context_t,int>; - using Workers = DigiParallelWorkers<Worker>; + using work_t = context_t; + using self_t = DigiSynchronize; + using worker_t = DigiParallelWorker<DigiEventAction, work_t, std::size_t, self_t&>; + using workers_t = DigiParallelWorkers<worker_t>; + friend class DigiParallelWorker<DigiEventAction, work_t, std::size_t, self_t&>; + /// The list of action objects to be called - Workers m_actors; + workers_t m_actors; protected: /// Define standard assignments and constructors diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index c375684435a55aaf68fddf16422a047919bf9219..c976ba968796a886bbcded903e4045214a3e9094 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -69,6 +69,11 @@ DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerSequence) DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerProcessor) DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerSequenceAction) +#include <DDDigi/DigiDepositMonitor.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositTimeMonitor) +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositEnergyMonitor) +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositPositionMonitor) + /// Basic entry point static long dummy(dd4hep::Detector&, int, char**) { return 0; diff --git a/DDDigi/plugins/DigiDepositDropKilled.cpp b/DDDigi/plugins/DigiDepositDropKilled.cpp index 60ba5b2e61af6e36641b1dc7c03f1c0041233255..e9c115ce7241c946bbc52f9eedc4711a8875a615 100644 --- a/DDDigi/plugins/DigiDepositDropKilled.cpp +++ b/DDDigi/plugins/DigiDepositDropKilled.cpp @@ -13,11 +13,6 @@ // Framework include files #include <DDDigi/DigiContainerProcessor.h> -#include <DD4hep/InstanceCount.h> -#include <DD4hep/DD4hepUnits.h> - -/// C/C++ include files -#include <limits> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -25,49 +20,34 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - /// Actor to drop energy deposits of a container having the "KILLED" flag + /// Actor to drop energy deposits of a container having deposits with the "KILLED" flag set /** - * * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ class DigiDepositDropKilled : public DigiContainerProcessor { - protected: - /// Property: Flag to update existing container in-place or create a new container - bool m_update_in_place { true }; - public: /// Standard constructor - DigiDepositDropKilled(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) - { - declareProperty("update_in_place", m_update_in_place = true); - InstanceCount::increment(this); - } + using DigiContainerProcessor::DigiContainerProcessor; - /// Default destructor - virtual ~DigiDepositDropKilled() { - InstanceCount::decrement(this); - } - template <typename T> std::size_t length(const T* m) const { return m->size(); } /// Main functional callback virtual void execute(DigiContext& context, work_t& work, const predicate_t&) const override final { std::size_t killed = 0, total = 0, i = 0; if ( auto* v = work.get_input<DepositVector>() ) { - total = length(v); + total = v->size(); for( auto iter = v->begin(); iter != v->end(); ++iter, ++i ) { if ( v->at(i).flag&EnergyDeposit::KILLED ) { v->remove(iter); iter = v->begin() + (--i); } } - killed = total - length(v); + killed = total - v->size(); } else if ( auto* m = work.get_input<DepositMapping>() ) { CellID last_cell = ~0x0LL; - total = length(m); + total = m->size(); for( auto iter = m->begin(); iter != m->end(); ++iter ) { if ( iter->second.flag&EnergyDeposit::KILLED ) { m->remove(iter); @@ -76,11 +56,12 @@ namespace dd4hep { } last_cell = iter->first; } - killed = total - length(v); + killed = total - m->size(); } else { except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } + if ( m_monitor ) m_monitor->count_shift(total, killed); info("%s+++ Killed %6ld out of %6ld deposit entries from container: %s",context.event->id(), killed, total); } }; diff --git a/DDDigi/plugins/DigiDepositEnergyCut.cpp b/DDDigi/plugins/DigiDepositEnergyCut.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c695f9015457bd51893cc1dce94ec9c98ab655c4 --- /dev/null +++ b/DDDigi/plugins/DigiDepositEnergyCut.cpp @@ -0,0 +1,73 @@ +//========================================================================== +// 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/DigiContainerProcessor.h> + +/// C/C++ include files +#include <limits> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Actor to merge energy deposits weighted with their energy deposit + /** + * The selected deposits are placed in the output container + * supplied by the arguments. Multiple CellIDs will be merged to one single + * deposit, where the merge computes the resulting position and + * momentum according to the contribution of the hits. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositEnergyCut : public DigiDepositsProcessor { + protected: + /// Property: Energy cutoff. No hits will be merged with a deposit smaller + double m_cutoff { -std::numeric_limits<double>::epsilon() }; + + public: + /// Create deposit mapping with updates on same cellIDs + template <typename T> void + cut_energy(context_t& context, T& cont, work_t& /* work */, const predicate_t& predicate) const { + std::size_t dropped = 0UL; + for( auto& dep : cont ) { + if ( predicate(dep) ) { + EnergyDeposit& depo = dep.second; + if ( depo.deposit < m_cutoff ) { + depo.flag |= EnergyDeposit::KILLED; + ++dropped; + } + } + } + if ( m_monitor ) m_monitor->count_shift(cont.size(), dropped); + info("%s+++ %-32s dropped %6ld out of %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), dropped, cont.size(), cont.key.mask()); + } + + /// Standard constructor + DigiDepositEnergyCut(const DigiKernel& krnl, const std::string& nam) + : DigiDepositsProcessor(krnl, nam) + { + declareProperty("deposit_cutoff", m_cutoff); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositEnergyCut::cut_energy) + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositEnergyCut) diff --git a/DDDigi/plugins/DigiDepositMapCreator.cpp b/DDDigi/plugins/DigiDepositMapCreator.cpp index 86765d0e18e4d0edbce90f55f1e3340b5ec3f9dc..19fcf5180ef4f582df3cf190a8b7afc6b9e42eff 100644 --- a/DDDigi/plugins/DigiDepositMapCreator.cpp +++ b/DDDigi/plugins/DigiDepositMapCreator.cpp @@ -37,8 +37,8 @@ namespace dd4hep { template <typename T> void create_deposits(const char* tag, const T& cont, work_t& work, const predicate_t& predicate) const { - Key key(cont.name, work.output.mask); - DepositMapping m(cont.name, work.output.mask); + Key key(cont.name, work.environ.output.mask); + DepositMapping m(cont.name, work.environ.output.mask); std::size_t start = m.size(); for( const auto& dep : cont ) { if ( predicate(dep) ) { @@ -46,7 +46,7 @@ namespace dd4hep { } } std::size_t end = m.size(); - work.output.data.put(m.key, std::move(m)); + work.environ.output.data.put(m.key, std::move(m)); info("%s+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", tag, cont.name.c_str(), end-start, end, cont.key.mask(), m.key.mask()); } diff --git a/DDDigi/plugins/DigiDepositNoiseOnSignal.cpp b/DDDigi/plugins/DigiDepositNoiseOnSignal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62d63043505d3c258f9419dc035c13dd25aa474e --- /dev/null +++ b/DDDigi/plugins/DigiDepositNoiseOnSignal.cpp @@ -0,0 +1,74 @@ +//========================================================================== +// 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/DigiContainerProcessor.h> +#include <DD4hep/DD4hepUnits.h> + +/// C/C++ include files +#include <limits> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Actor to smear timing information of energy deposits + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositNoiseOnSignal : public DigiDepositsProcessor { + protected: + /// Property: Mean of the added noise on signal in absolute values + double m_mean { 0e0 }; + /// Property: Sigma of the noise in absolute values + double m_sigma { 0e0 }; + + public: + /// Create deposit mapping with updates on same cellIDs + template <typename T> void + create_noise(DigiContext& context, T& cont, work_t& /* work */, const predicate_t& predicate) const { + auto& random = context.randomGenerator(); + std::size_t updated = 0UL; + for( auto& dep : cont ) { + if ( predicate(dep) ) { + int flag = EnergyDeposit::DEPOSIT_NOISE; + double delta_E = random.gaussian(m_mean, m_sigma); + if ( m_monitor ) m_monitor->energy_shift(dep, delta_E); + dep.second.deposit += delta_E; + dep.second.flag |= flag; + ++updated; + } + } + info("%s+++ %-32s Noise on signal: %6ld entries, updated %6ld entries. mask: %04X", + context.event->id(), cont.name.c_str(), cont.size(), updated, cont.key.mask()); + } + + /// Standard constructor + DigiDepositNoiseOnSignal(const DigiKernel& krnl, const std::string& nam) + : DigiDepositsProcessor(krnl, nam) + { + declareProperty("mean", m_mean); + declareProperty("sigma", m_sigma); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositNoiseOnSignal::create_noise) + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositNoiseOnSignal) diff --git a/DDDigi/plugins/DigiDepositRecalibEnergy.cpp b/DDDigi/plugins/DigiDepositRecalibEnergy.cpp index 490a23b1fbdcad1a08e4ac7b6bc24529f833c50d..8d61d232301444e017b2e76cdabf0866ae410dbf 100644 --- a/DDDigi/plugins/DigiDepositRecalibEnergy.cpp +++ b/DDDigi/plugins/DigiDepositRecalibEnergy.cpp @@ -32,42 +32,27 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiDepositRecalibEnergy : public DigiContainerProcessor { + class DigiDepositRecalibEnergy : public DigiDepositsProcessor { protected: /// Property: Polynomial parameters to recalibrate the energy std::vector<double> m_polynomial { }; /// Property: Energy base point to compute delta(energy) double m_e0 { 0e0 }; - /// Property: Flag to update existing container in-place or create a new container - bool m_update_in_place { true }; public: /// Standard constructor DigiDepositRecalibEnergy(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) + : DigiDepositsProcessor(krnl, nam) { declareProperty("e0", m_e0); declareProperty("parameters" , m_polynomial); - InstanceCount::increment(this); - } - - /// Default destructor - virtual ~DigiDepositRecalibEnergy() { - InstanceCount::decrement(this); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositRecalibEnergy::recalibrate_deposit_energy) } /// Create deposit mapping with updates on same cellIDs - template <typename T> void recalibrate_deposit_energy(DigiContext& context, - T& cont, - work_t& work, - const predicate_t& predicate) const { - T output_cont(cont.name, work.output.mask); + template <typename T> void + recalibrate_deposit_energy(DigiContext& context, T& cont, work_t& /* work */, const predicate_t& predicate) const { std::size_t updated = 0UL; - std::size_t created = 0UL; - std::size_t killed = 0UL; - - info("%s+++ Recalibrarting deposit container: %s %6ld entries", - context.event->id(), cont.name.c_str(), cont.size()); for( auto& dep : cont ) { if ( predicate(dep) ) { double deposit = dep.second.deposit; @@ -77,39 +62,14 @@ namespace dd4hep { deposit += param * fac; fac *= delta_E; } - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.deposit = deposit; - d.flag |= EnergyDeposit::RECALIBRATED; - ++updated; - } - else if ( !(dep.second.flag&EnergyDeposit::KILLED) ) { - EnergyDeposit d(dep.second); - d.deposit = deposit; - d.flag |= EnergyDeposit::RECALIBRATED; - output_cont.emplace(dep.first, std::move(d)); - ++created; - } - else { - ++killed; - } + if ( m_monitor ) m_monitor->energy_shift(dep, delta_E); + dep.second.deposit = deposit; + dep.second.flag |= EnergyDeposit::RECALIBRATED; + ++updated; } } - if ( !m_update_in_place ) { - work.output.data.put(output_cont.key, std::move(output_cont)); - } - info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", - context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); - } - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { - if ( auto* v = work.get_input<DepositVector>() ) - recalibrate_deposit_energy(context, *v, work, predicate); - else if ( auto* m = work.get_input<DepositMapping>() ) - recalibrate_deposit_energy(context, *m, work, predicate); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + info("%s+++ %-32s Recalibrating: updated %6ld out of %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), updated, cont.size(), cont.key.mask()); } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiDepositSmearEnergy.cpp b/DDDigi/plugins/DigiDepositSmearEnergy.cpp index 3aaa47538d5c18ebb90e77ae61e436930ca0a40a..d7d97aa6a96f9511dd0f771e18564a61bc3652cf 100644 --- a/DDDigi/plugins/DigiDepositSmearEnergy.cpp +++ b/DDDigi/plugins/DigiDepositSmearEnergy.cpp @@ -13,7 +13,6 @@ // Framework include files #include <DDDigi/DigiContainerProcessor.h> -#include <DD4hep/InstanceCount.h> #include <DD4hep/DD4hepUnits.h> /// C/C++ include files @@ -61,10 +60,8 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiDepositSmearEnergy : public DigiContainerProcessor { + class DigiDepositSmearEnergy : public DigiDepositsProcessor { protected: - /// Property: Energy cutoff. No hits will be merged with a deposit smaller - double m_deposit_cutoff { std::numeric_limits<double>::epsilon() }; /// Property: Intrinsic energy resolution constant (gaussian ~ std::sqrt(energy)) double m_intrinsic_fluctuation { 0e0 }; /// Property: Systematic energy resolution constant (gaussian ~deposit energy) @@ -75,115 +72,67 @@ namespace dd4hep { double m_pair_ionization_energy { 0e0 }; /// Property: Flag to use ionization fluctuation smearing (poisson ~ # e-ion-pairs) bool m_ionization_fluctuation { false }; - /// Property: Flag to update existing container in-place or create a new container - bool m_update_in_place { true }; public: /// Standard constructor DigiDepositSmearEnergy(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) + : DigiDepositsProcessor(krnl, nam) { - declareProperty("deposit_cutoff", m_deposit_cutoff); declareProperty("intrinsic_fluctuation", m_intrinsic_fluctuation = 0e0); declareProperty("instrumentation_resolution", m_instrumentation_resolution = 0e0); declareProperty("systematic_resolution", m_systematic_resolution = 0e0); declareProperty("pair_ionisation_energy", m_pair_ionization_energy = 3.6*dd4hep::eV); declareProperty("ionization_fluctuation", m_ionization_fluctuation = false); - declareProperty("update_in_place", m_update_in_place = true); - InstanceCount::increment(this); - } - - /// Default destructor - virtual ~DigiDepositSmearEnergy() { - InstanceCount::decrement(this); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositSmearEnergy::smear) } /// Create deposit mapping with updates on same cellIDs template <typename T> void - smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { + smear(DigiContext& context, T& cont, work_t& /* work */, const predicate_t& predicate) const { auto& random = context.randomGenerator(); - T output_cont(cont.name, work.output.mask); - std::size_t killed = 0UL; std::size_t updated = 0UL; - std::size_t created = 0UL; - if ( dd4hep::isActivePrintLevel(outputLevel()) ) { - print("%s+++ Smearing container: %s %6ld entries", - context.event->id(), cont.name.c_str(), cont.size()); - } for( auto& dep : cont ) { if ( predicate(dep) ) { CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; + EnergyDeposit& depo = dep.second; double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - double delta_E = 0e0; - double energy = deposit / dd4hep::GeV; // E in units of GeV - double sigma_E_systematic = m_systematic_resolution * energy; - double sigma_E_intrin_fluct = m_intrinsic_fluctuation * std::sqrt(energy); - double sigma_E_instrument = m_instrumentation_resolution / dd4hep::GeV; - double delta_ion = 0e0, num_pairs = 0e0; - constexpr static double eps = std::numeric_limits<double>::epsilon(); - if ( sigma_E_systematic > eps ) { - delta_E += sigma_E_systematic * random.gaussian(0e0, 1e0); - } - if ( sigma_E_intrin_fluct > eps ) { - delta_E += sigma_E_intrin_fluct * random.gaussian(0e0, 1e0); - } - if ( sigma_E_instrument > eps ) { - delta_E += sigma_E_instrument * random.gaussian(0e0, 1e0); - } - if ( m_ionization_fluctuation ) { - num_pairs = energy / (m_pair_ionization_energy/dd4hep::GeV); - delta_ion = energy * (random.poisson(num_pairs)/num_pairs); - delta_E += delta_ion; - } - if ( dd4hep::isActivePrintLevel(outputLevel()) ) { - print("+++ %016lX [GeV] E:%9.2e [%9.2e %9.2e] intrin_fluct:%9.2e systematic:%9.2e instrument:%9.2e ioni:%9.2e/%.0f %s", - cell, energy, deposit/dd4hep::GeV, delta_E, - sigma_E_intrin_fluct, sigma_E_systematic, sigma_E_instrument, delta_ion, num_pairs, - deposit < m_deposit_cutoff ? "KILLED" : ""); - } - /// delta_E is in GeV - if ( deposit > m_deposit_cutoff ) { - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.deposit = deposit + (delta_E * dd4hep::GeV); - d.flag |= EnergyDeposit::ENERGY_SMEARED; - ++updated; - } - else { - EnergyDeposit d(depo); - d.deposit = deposit + (delta_E * dd4hep::GeV); - d.flag |= EnergyDeposit::ENERGY_SMEARED; - output_cont.emplace(cell, EnergyDeposit(depo)); - ++created; - } - continue; - } + double delta_E = 0e0; + double energy = deposit / dd4hep::GeV; // E in units of GeV + double sigma_E_systematic = m_systematic_resolution * energy; + double sigma_E_intrin_fluct = m_intrinsic_fluctuation * std::sqrt(energy); + double sigma_E_instrument = m_instrumentation_resolution / dd4hep::GeV; + double delta_ion = 0e0, num_pairs = 0e0; + constexpr static double eps = std::numeric_limits<double>::epsilon(); + if ( sigma_E_systematic > eps ) { + delta_E += sigma_E_systematic * random.gaussian(0e0, 1e0); + } + if ( sigma_E_intrin_fluct > eps ) { + delta_E += sigma_E_intrin_fluct * random.gaussian(0e0, 1e0); + } + if ( sigma_E_instrument > eps ) { + delta_E += sigma_E_instrument * random.gaussian(0e0, 1e0); } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; + if ( m_ionization_fluctuation ) { + num_pairs = energy / (m_pair_ionization_energy/dd4hep::GeV); + delta_ion = energy * (random.poisson(num_pairs)/num_pairs); + delta_E += delta_ion; } + if ( dd4hep::isActivePrintLevel(outputLevel()) ) { + print("%s+++ %016lX [GeV] E:%9.2e [%9.2e %9.2e] intrin_fluct:%9.2e systematic:%9.2e instrument:%9.2e ioni:%9.2e/%.0f", + context.event->id(), cell, energy, deposit/dd4hep::GeV, delta_E, + sigma_E_intrin_fluct, sigma_E_systematic, sigma_E_instrument, delta_ion, num_pairs); + } + /// delta_E is in GeV + delta_E *= dd4hep::GeV; + if ( m_monitor ) m_monitor->energy_shift(dep, delta_E); + depo.deposit = deposit + (delta_E); + depo.flag |= EnergyDeposit::ENERGY_SMEARED; + ++updated; } } - if ( !m_update_in_place ) { - work.output.data.put(output_cont.key, std::move(output_cont)); - } - info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", - context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); - } - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { - if ( auto* v = work.get_input<DepositVector>() ) - smear(context, *v, work, predicate); - else if ( auto* m = work.get_input<DepositMapping>() ) - smear(context, *m, work, predicate); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + info("%s+++ %-32s Smear energy: updated %6ld out of %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), updated, cont.size(), cont.key.mask()); } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp b/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp index 5c82012e054bddaa3e0219d6268cc44a8087421a..3946c530463e5c0ce07c4e152987966b9828e195 100644 --- a/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp +++ b/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp @@ -15,7 +15,6 @@ #include <DDDigi/DigiContainerProcessor.h> #include <DDDigi/DigiKernel.h> -#include <DD4hep/InstanceCount.h> #include <DD4hep/DD4hepUnits.h> #include <DD4hep/Detector.h> #include <DD4hep/VolumeManager.h> @@ -36,104 +35,60 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiDepositSmearPositionResolution : public DigiContainerProcessor { + class DigiDepositSmearPositionResolution : public DigiDepositsProcessor { protected: - /// Property: Energy cutoff. No hits will be merged with a deposit smaller - double m_deposit_cutoff { detail::numeric_epsilon }; /// Property: Resolution in loacl sensor's U coordinates along (1, 0, 0) double m_resolution_u { 0e0 * dd4hep::mm }; /// Property: Resolution in loacl sensor's V coordinates along (0, 1, 0) double m_resolution_v { 0e0 * dd4hep::mm }; - /// Property: Flag to update existing container in-place or create a new container - bool m_update_in_place { true }; + + /// Optional local position monitor + DigiDepositMonitor* m_local_monitor { nullptr }; public: /// Standard constructor DigiDepositSmearPositionResolution(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) + : DigiDepositsProcessor(krnl, nam) { - declareProperty("deposit_cutoff", m_deposit_cutoff); - declareProperty("update_in_place", m_update_in_place = true); declareProperty("resolution_u", m_resolution_u); declareProperty("resolution_v", m_resolution_v); - InstanceCount::increment(this); - } - - /// Default destructor - virtual ~DigiDepositSmearPositionResolution() { - InstanceCount::decrement(this); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositSmearPositionResolution::smear) } /// Create deposit mapping with updates on same cellIDs template <typename T> void - smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { - T output_cont(cont.name, work.output.mask); + smear(DigiContext& context, T& cont, work_t& /* work */, const predicate_t& predicate) const { + VolumeManager volMgr = m_kernel.detectorDescription().volumeManager(); auto& random = context.randomGenerator(); - std::size_t killed = 0UL; std::size_t updated = 0UL; - std::size_t created = 0UL; - if ( dd4hep::isActivePrintLevel(outputLevel()) ) { - print("%s+++ Smearing container: %s %6ld entries", - context.event->id(), cont.name.c_str(), cont.size()); - } - VolumeManager volMgr = m_kernel.detectorDescription().volumeManager(); for( auto& dep : cont ) { if ( predicate(dep) ) { CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; - double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - auto* ctxt = volMgr.lookupContext(cell); - Position local_pos = ctxt->worldToLocal(depo.position); - double delta_u = m_resolution_u * random.gaussian(); - double delta_v = m_resolution_v * random.gaussian(); - Position delta_pos(delta_u, delta_v, 0e0); - Position oldpos = depo.position; - Position newpos = ctxt->localToWorld(local_pos + delta_pos); + EnergyDeposit& depo = dep.second; + auto* ctxt = volMgr.lookupContext(cell); + Position local_pos = ctxt->worldToLocal(depo.position); + double delta_u = m_resolution_u * random.gaussian(); + double delta_v = m_resolution_v * random.gaussian(); + Position delta_pos(delta_u, delta_v, 0e0); + Position oldpos = depo.position; + Position newpos = ctxt->localToWorld(local_pos + delta_pos); + + if ( m_local_monitor ) m_local_monitor->position_shift(dep, local_pos, delta_pos); + delta_pos = newpos - oldpos; + if ( m_monitor ) m_monitor->position_shift(dep, oldpos, delta_pos); - delta_pos = newpos - oldpos; - info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", - oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), - newpos.X(), newpos.Y(), newpos.Z()); + info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", + oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), + newpos.X(), newpos.Y(), newpos.Z()); - /// Update / create deposit with smeared position - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - ++updated; - } - else { - EnergyDeposit d(depo); - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - output_cont.emplace(cell, std::move(d)); - ++created; - } - } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; - } + depo.position = newpos; + depo.flag |= EnergyDeposit::POSITION_SMEARED; + ++updated; } } - if ( !m_update_in_place ) { - work.output.data.put(output_cont.key, std::move(output_cont)); - } - info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", - context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); - } - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { - if ( auto* v = work.get_input<DepositVector>() ) - smear(context, *v, work, predicate); - else if ( auto* m = work.get_input<DepositMapping>() ) - smear(context, *m, work, predicate); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + info("%s+++ %-32s Smear position(resolution): updated %6ld out of %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), updated, cont.size(), cont.key.mask()); } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp b/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp index 25aad28fedea174844a58d4a01afdf9ac897c684..0cd9ff32415ab5b0a6e4b650982c634b48b11858 100644 --- a/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp +++ b/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp @@ -15,7 +15,6 @@ #include <DDDigi/DigiContainerProcessor.h> #include <DDDigi/DigiKernel.h> -#include <DD4hep/InstanceCount.h> #include <DD4hep/DD4hepUnits.h> #include <DD4hep/Detector.h> #include <DD4hep/VolumeManager.h> @@ -36,116 +35,77 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiDepositSmearPositionTrack : public DigiContainerProcessor { + class DigiDepositSmearPositionTrack : public DigiDepositsProcessor { protected: - /// Property: Energy cutoff. No hits will be merged with a deposit smaller - double m_deposit_cutoff { detail::numeric_epsilon }; /// Property: Resolution in loacl sensor's U coordinates along (1, 0, 0) double m_resolution_u { 0e0 * dd4hep::mm }; /// Property: Resolution in loacl sensor's V coordinates along (0, 1, 0) double m_resolution_v { 0e0 * dd4hep::mm }; - /// Property: Flag to update existing container in-place or create a new container - bool m_update_in_place { true }; + + /// Optional local position monitor + DigiDepositMonitor* m_local_monitor { nullptr }; public: /// Standard constructor DigiDepositSmearPositionTrack(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) + : DigiDepositsProcessor(krnl, nam) { - declareProperty("deposit_cutoff", m_deposit_cutoff); - declareProperty("update_in_place", m_update_in_place = true); declareProperty("resolution_u", m_resolution_u); declareProperty("resolution_v", m_resolution_v); - InstanceCount::increment(this); - } - - /// Default destructor - virtual ~DigiDepositSmearPositionTrack() { - InstanceCount::decrement(this); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositSmearPositionTrack::smear) } /// Create deposit mapping with updates on same cellIDs template <typename T> void smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { constexpr double eps = detail::numeric_epsilon; - T output_cont(cont.name, work.output.mask); auto& random = context.randomGenerator(); const auto& ev = *(context.event); - std::size_t killed = 0UL; std::size_t updated = 0UL; - std::size_t created = 0UL; + auto* h = work.get_history(cont.name); - if ( dd4hep::isActivePrintLevel(outputLevel()) ) { - print("%s+++ Smearing container: %s %6ld entries", - context.event->id(), cont.name.c_str(), cont.size()); - } VolumeManager volMgr = m_kernel.detectorDescription().volumeManager(); for( auto& dep : cont ) { if ( predicate(dep) ) { CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; - double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - auto* ctxt = volMgr.lookupContext(cell); - Direction part_momentum = depo.history.average_particle_momentum(ev); - Position local_pos = ctxt->worldToLocal(depo.position); - Position local_dir = ctxt->worldToLocal(part_momentum).unit(); - double cos_u = local_dir.Dot(Position(1,0,0)); - double sin_u = std::sqrt(1e0 - cos_u*cos_u); - double tan_u = sin_u/(std::abs(cos_u)>eps ? cos_u : eps); - double delta_u = tan_u * m_resolution_u * random.gaussian(); + EnergyDeposit& depo = dep.second; + auto* ctxt = volMgr.lookupContext(cell); +#ifdef DDDIGI_INPLACE_HISTORY + Direction part_momentum = depo.history.average_particle_momentum(ev); +#else + Direction part_momentum = depo.momentum; +#endif + Position local_pos = ctxt->worldToLocal(depo.position); + Position local_dir = ctxt->worldToLocal(part_momentum).unit(); + double cos_u = local_dir.Dot(Position(1,0,0)); + double sin_u = std::sqrt(1e0 - cos_u*cos_u); + double tan_u = sin_u/(std::abs(cos_u)>eps ? cos_u : eps); + double delta_u = tan_u * m_resolution_u * random.gaussian(); - double cos_v = local_dir.Dot(Position(0,1,0)); - double sin_v = std::sqrt(1e0 - cos_v*cos_v); - double tan_v = sin_v/(std::abs(cos_v)>eps ? cos_v : eps); - double delta_v = tan_v * m_resolution_v * random.gaussian(); + double cos_v = local_dir.Dot(Position(0,1,0)); + double sin_v = std::sqrt(1e0 - cos_v*cos_v); + double tan_v = sin_v/(std::abs(cos_v)>eps ? cos_v : eps); + double delta_v = tan_v * m_resolution_v * random.gaussian(); - Position delta_pos(delta_u, delta_v, 0e0); - Position oldpos = depo.position; - Position newpos = ctxt->localToWorld(local_pos + delta_pos); + Position delta_pos(delta_u, delta_v, 0e0); + Position oldpos = depo.position; + Position newpos = ctxt->localToWorld(local_pos + delta_pos); - delta_pos = newpos - oldpos; - info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", - oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), - newpos.X(), newpos.Y(), newpos.Z()); + if ( m_local_monitor ) m_local_monitor->position_shift(dep, local_pos, delta_pos); + delta_pos = newpos - oldpos; + if ( m_monitor ) m_monitor->position_shift(dep, oldpos, delta_pos); - /// Update / create deposit with smeared position - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - ++updated; - } - else { - EnergyDeposit d(depo); - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - output_cont.emplace(cell, std::move(d)); - ++created; - } - } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; - } + info("%s+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", + ev.id(), oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), + newpos.X(), newpos.Y(), newpos.Z()); + + depo.position = newpos; + depo.flag |= EnergyDeposit::POSITION_SMEARED; + ++updated; } } - if ( !m_update_in_place ) { - work.output.data.put(output_cont.key, std::move(output_cont)); - } - info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", - context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); - } - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { - if ( auto* v = work.get_input<DepositVector>() ) - smear(context, *v, work, predicate); - else if ( auto* m = work.get_input<DepositMapping>() ) - smear(context, *m, work, predicate); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + info("%s+++ %-32s Smear position(track): updated %6ld out of %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), updated, cont.size(), cont.key.mask()); } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiDepositSmearTime.cpp b/DDDigi/plugins/DigiDepositSmearTime.cpp index e3e208de30a412dcfa3ee0c56efac508fbc8af14..ff782129608cb34aaeaf1478c4efb9d777ef505e 100644 --- a/DDDigi/plugins/DigiDepositSmearTime.cpp +++ b/DDDigi/plugins/DigiDepositSmearTime.cpp @@ -55,11 +55,13 @@ namespace dd4hep { flag |= EnergyDeposit::KILLED; ++killed; } + if ( m_monitor ) m_monitor->time_shift(dep, delta_T); dep.second.time += delta_T; dep.second.flag |= flag; ++updated; } } + if ( m_monitor ) m_monitor->count_shift(cont.size(), -killed); info("%s+++ %-32s Smeared time resolution: %6ld entries, updated %6ld killed %6ld entries from mask: %04X", context.event->id(), cont.name.c_str(), cont.size(), updated, killed, cont.key.mask()); } diff --git a/DDDigi/plugins/DigiDepositWeightedPosition.cpp b/DDDigi/plugins/DigiDepositWeightedPosition.cpp index 36e1f1ed04da3fd7110532b8cf93dac6f6843ff0..6fdd9bc6fc1ed0d9464ad510d32fa0eb9e935de2 100644 --- a/DDDigi/plugins/DigiDepositWeightedPosition.cpp +++ b/DDDigi/plugins/DigiDepositWeightedPosition.cpp @@ -13,7 +13,6 @@ // Framework include files #include <DDDigi/DigiContainerProcessor.h> -#include <DD4hep/InstanceCount.h> /// C/C++ include files #include <limits> @@ -44,8 +43,8 @@ namespace dd4hep { /// Create deposit mapping with updates on same cellIDs template <typename T> void create_deposits(context_t& context, const T& cont, work_t& work, const predicate_t& predicate) const { - Key key(cont.name, work.output.mask); - DepositMapping m(cont.name, work.output.mask); + Key key(cont.name, work.environ.output.mask); + DepositMapping m(cont.name, work.environ.output.mask); std::size_t dropped = 0UL, updated = 0UL, added = 0UL; for( const auto& dep : cont ) { if ( predicate(dep) ) { @@ -64,22 +63,16 @@ namespace dd4hep { } info("%s+++ %-32s added %6ld updated %6ld dropped %6ld entries (now: %6ld) from mask: %04X to mask: %04X", context.event->id(), cont.name.c_str(), added, updated, dropped, m.size(), cont.key.mask(), m.key.mask()); - work.output.data.put(m.key, std::move(m)); + work.environ.output.data.put(m.key, std::move(m)); } /// Standard constructor DigiDepositWeightedPosition(const DigiKernel& krnl, const std::string& nam) : DigiDepositsProcessor(krnl, nam) { - InstanceCount::increment(this); declareProperty("deposit_cutoff", m_cutoff); DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiDepositWeightedPosition::create_deposits) } - - /// Default destructor - virtual ~DigiDepositWeightedPosition() { - InstanceCount::decrement(this); - } }; } // End namespace digi } // End namespace dd4hep diff --git a/DDDigi/plugins/DigiHitHistoryDrop.cpp b/DDDigi/plugins/DigiHitHistoryDrop.cpp index 5b3c663dc064e47c7f1b786c4e39b568e1e1ea9d..e30bcd61ec185dbf554425d1893f1b867d212902 100644 --- a/DDDigi/plugins/DigiHitHistoryDrop.cpp +++ b/DDDigi/plugins/DigiHitHistoryDrop.cpp @@ -59,12 +59,11 @@ namespace dd4hep { InstanceCount::increment(this); } - template <typename T> - std::pair<std::size_t, std::size_t> drop_history(T& cont) const { + std::pair<std::size_t, std::size_t> drop_history(DetectorHistory& cont) const { std::size_t num_drop_hit = 0; std::size_t num_drop_particle = 0; for( auto& dep : cont ) { - auto ret = dep.second.history.drop(); + auto ret = dep.second.drop(); num_drop_hit += ret.first; num_drop_particle += ret.second; } @@ -80,15 +79,10 @@ namespace dd4hep { Key key(i.first); auto im = std::find(m_masks.begin(), m_masks.end(), key.mask()); if( im != m_masks.end() ) { - if( DepositMapping* m = std::any_cast<DepositMapping>(&i.second) ) { - auto ret = drop_history(*m); - num_drop_hit += ret.first; - num_drop_particle += ret.second; - } - if( DepositVector* m = std::any_cast<DepositVector>(&i.second) ) { - auto ret = drop_history(*m); - num_drop_hit += ret.first; - num_drop_particle += ret.second; + if( DetectorHistory* h = std::any_cast<DetectorHistory>(&i.second) ) { + auto [nhit, npart] = drop_history(*h); + num_drop_hit += nhit; + num_drop_particle += npart; } } } diff --git a/DDDigi/plugins/DigiResegment.cpp b/DDDigi/plugins/DigiResegment.cpp index 70faf83aa7711dee7cc1362cdfe4f76d9ddfef17..6a4d3df9b1e2fdd4df1ee9a2931fdec6a1f2acbb 100644 --- a/DDDigi/plugins/DigiResegment.cpp +++ b/DDDigi/plugins/DigiResegment.cpp @@ -105,8 +105,8 @@ namespace dd4hep { template <typename T> void resegment_deposits(const T& cont, work_t& work, const predicate_t& predicate) const { - Key key(cont.name, work.output.mask); - DepositVector m(cont.name, work.output.mask); + Key key(cont.name, work.environ.output.mask); + DepositVector m(cont.name, key.mask()); std::size_t start = m.size(); for( const auto& dep : cont ) { if( predicate(dep) ) { @@ -138,7 +138,7 @@ namespace dd4hep { } } std::size_t end = m.size(); - work.output.data.put(m.key, std::move(m)); + work.environ.output.data.put(m.key, std::move(m)); info("+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", cont.name.c_str(), end-start, end, cont.key.mask(), m.key.mask()); } diff --git a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp index 5039e39eb3a4e0137b3c9ed61bf68d7a99742685..baa9ab1c7ec40feff8e4dfcbea6cda01eb22f8a8 100644 --- a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp +++ b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp @@ -38,7 +38,7 @@ namespace dd4hep { : DigiContainerProcessor(kernel, nam) {} template <typename T> void copy_deposits(const T& cont, work_t& work, const predicate_t& predicate) const { - DepositVector deposits(cont.name, work.output.mask); + DepositVector deposits(cont.name, work.environ.output.mask); for( const auto& dep : cont ) { if( predicate(dep) ) { CellID cell = dep.first; @@ -46,7 +46,7 @@ namespace dd4hep { deposits.data.emplace_back(cell, std::move(depo)); } } - work.output.data.put(deposits.key, std::move(deposits)); + work.environ.output.data.put(deposits.key, std::move(deposits)); } /// Main functional callback virtual void execute(DigiContext&, work_t& work, const predicate_t& predicate) const override final { diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp index 5a17bf7da66f0fd98f4aa4b48835e07d10327ba1..d4e72a230898c99f364d4e98913b1e21e9290dce 100644 --- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp +++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp @@ -41,8 +41,10 @@ namespace dd4hep { for( const auto& dep : cont ) { if( predicate(dep) ) { info(fmt, predicate.segmentation->split_id(dep.first), dep.first, +#ifdef DDDIGI_INPLACE_HISTORY dep.second.history.hits.size(), dep.second.history.particles.size(), +#endif dep.second.deposit); } } @@ -53,7 +55,10 @@ namespace dd4hep { char format[256]; ::snprintf(format, sizeof(format), "%s[%s] %s-id: %%d [processor:%d] Cell: %%016lX mask: %016lX " - "hist:%%4ld hits %%4ld parts. entries deposit: %%f", +#ifdef DDDIGI_INPLACE_HISTORY + "hist:%%4ld hits %%4ld parts. " +#endif + "entries deposit: %%f", context.event->id(), predicate.segmentation->idspec.name(), predicate.segmentation->cname(), predicate.id, predicate.segmentation->split_mask); diff --git a/DDDigi/plugins/DigiSimpleADCResponse.cpp b/DDDigi/plugins/DigiSimpleADCResponse.cpp index 564756338dcc91ca2cc6b7814893f658513e48d1..a6adf2c53d8d9c180586fc6ac82cc5aadade6d2b 100644 --- a/DDDigi/plugins/DigiSimpleADCResponse.cpp +++ b/DDDigi/plugins/DigiSimpleADCResponse.cpp @@ -25,11 +25,10 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - class DigiSimpleADCResponse : public DigiContainerProcessor { + class DigiSimpleADCResponse : public DigiDepositsProcessor { using segmentation_t = DigiSegmentProcessContext; std::string m_response_postfix { ".adc" }; std::string m_history_postfix { ".hist" }; - double m_signal_cutoff { std::numeric_limits<double>::epsilon() }; double m_signal_saturation { std::numeric_limits<double>::max() }; double m_adc_offset { 0e0 }; std::size_t m_adc_resolution { 1024 }; @@ -37,23 +36,22 @@ namespace dd4hep { public: /// Standard constructor DigiSimpleADCResponse(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) + : DigiDepositsProcessor(krnl, nam) { - declareProperty("cutoff", m_signal_cutoff); declareProperty("saturation", m_signal_saturation); declareProperty("adc_resolution", m_adc_resolution); declareProperty("response_postfix", m_response_postfix); declareProperty("history_postfix", m_history_postfix); + DEPOSIT_PROCESSOR_BIND_HANDLERS(DigiSimpleADCResponse::emulate_adc) } /// Create container with ADC counts and register it to the output segment - template <typename T, typename P> - void emulate_adc(const char* tag, const T& input, work_t& work, const P& predicate) const { + template <typename T> + void emulate_adc(DigiContext& context, const T& input, work_t& work, const predicate_t& predicate) const { + const char* tag = context.event->id(); std::string postfix = predicate.segmentation ? "."+predicate.segmentation->identifier(predicate.id) : std::string(); - std::string history_name = input.name + postfix + m_history_postfix; std::string response_name = input.name + postfix + m_response_postfix; - DetectorHistory history (history_name, work.output.mask); - DetectorResponse response(response_name, work.output.mask); + DetectorResponse response(response_name, work.environ.output.mask); for( const auto& dep : input ) { if ( predicate(dep) ) { CellID cell = dep.first; @@ -62,31 +60,21 @@ namespace dd4hep { ADCValue::value_t adc_count = std::round(((offset_ene) * m_adc_resolution) / m_signal_saturation); adc_count = std::min(adc_count, ADCValue::value_t(m_adc_resolution)); response.emplace(cell, {adc_count, ADCValue::address_t(cell)}); - history.insert(cell, depo.history); } } +#ifdef DDDIGI_INPLACE_HISTORY + std::string history_name = input.name + postfix + m_history_postfix; + DetectorHistory history (history_name, work.output.mask); + for( const auto& dep : input ) { + if ( predicate(dep) ) { + history.insert(dep.first, dep.second.history); + } + } + work.output.data.put(history.key, std::move(history)); +#endif info("%s+++ %-32s %6ld ADC values. Input: %-32s %6ld deposits", tag, response_name.c_str(), response.size(), input.name.c_str(), input.size()); - work.output.data.put(response.key, std::move(response)); - work.output.data.put(history.key, std::move(history)); - } - - /// Create container with ADC counts and register it to the output segment - template <typename P> - void emulate_adc(DigiContext& context, work_t& work, const P& predicate) const { - const char* tag = context.event->id(); - if ( const auto* m = work.get_input<DepositMapping>() ) - emulate_adc(tag, *m, work, predicate); - else if ( const auto* v = work.get_input<DepositVector>() ) - emulate_adc(tag, *v, work, predicate); - else - except("%s+++ Request to handle unknown data type: %s", - tag, work.input_type_name().c_str()); - } - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const final { - emulate_adc(context, work, predicate); + work.environ.output.data.put(response.key, std::move(response)); } }; } // End namespace digi diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 56b77864a307bd4254354c302d8f20bd174caae6..87270724102bf321a24ae2860d08b8c60014a50d 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -84,8 +84,8 @@ namespace dd4hep { struct PropertyResult { public: - std::string data {}; - int status { 0 }; + std::string data { }; + int status { 0 }; PropertyResult() = default; PropertyResult(const std::string& d, int s); PropertyResult(const PropertyResult& c) = default; @@ -118,29 +118,15 @@ namespace dd4hep { DigiHandle<DigiAction> action(*kernel.get(),name_type); return ActionHandle(action.get()); } + static DigiAction* toAction(DigiKernel* f) { return f; } static DigiAction* toAction(DigiAction* f) { return f; } + static DigiAction* toAction(KernelHandle f) { return f.value; } static DigiAction* toAction(ActionHandle f) { return f.action; } static DigiEventAction* toEventAction(DigiAction* a) { return cst<DigiEventAction>(a); } + static DigiDepositMonitor* toDepositMonitor(DigiAction* a) { return cst<DigiDepositMonitor>(a); } static DigiContainerProcessor* toContainerProcessor(DigiAction* a) { return cst<DigiContainerProcessor>(a); } - /// Access kernel property - static PropertyResult getPropertyKernel(DigiKernel* kernel, const std::string& name) { - if ( kernel->hasProperty(name) ) { - return PropertyResult(kernel->property(name).str(),1); - } - return PropertyResult("",0); - } - - /// Set kernel property - static int setPropertyKernel(DigiKernel* kernel, const std::string& name, const std::string& value) { - if ( kernel->hasProperty(name) ) { - kernel->property(name).str(value); - return 1; - } - return 0; - } - /// Access DigiAction property static PropertyResult getProperty(DigiAction* action, const std::string& name) { if ( action->hasProperty(name) ) { @@ -193,6 +179,7 @@ namespace dd4hep { #include <DDDigi/DigiSegmentSplitter.h> #include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiSignalProcessor.h> +#include <DDDigi/DigiDepositMonitor.h> // CINT configuration #if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) @@ -226,6 +213,8 @@ using namespace std; #pragma link C++ class dd4hep::digi::DigiSegmentSplitter; +#pragma link C++ class dd4hep::digi::DigiDepositMonitor; + /// 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 2f53ab5ad35577face9a1db7846a38fd429cbc8c..bd20465893d4a8426c860618f43bc7bc3af0f9c8 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -14,7 +14,6 @@ from dd4hep_base import * # noqa: F401, F403 logger = None - def loadDDDigi(): global logger import ROOT @@ -137,28 +136,6 @@ def importConstants(description, namespace=None, debug=False): logger.info('+++ Imported %d global values to namespace:%s' % (num, ns.__name__),) -# --------------------------------------------------------------------------- -def _getKernelProperty(self, name): - ret = Interface.getPropertyKernel(self.get(), name) - if ret.status > 0: - return ret.data - elif hasattr(self.get(), name): - return getattr(self.get(), name) - elif hasattr(self, name): - return getattr(self, name) - msg = 'DigiKernel::GetProperty [Unhandled]: Cannot access Kernel.' + name - raise KeyError(msg) - - -# --------------------------------------------------------------------------- -def _setKernelProperty(self, name, value): - if Interface.setPropertyKernel(self.get(), str(name), str(value)): - return - msg = 'DigiKernel::SetProperty [Unhandled]: Cannot set Kernel.' + name + ' = ' + str(value) - raise KeyError(msg) -# --------------------------------------------------------------------------- - - def TestAction(kernel, nam, sleep=0): obj = Interface.createAction(kernel, str('DigiTestAction/' + nam)) if sleep != 0: @@ -176,57 +153,51 @@ def Action(kernel, nam, **options): def _get_action(self): + " Convert handles to action references to access underlying properties provided a dictionary exists. " return Interface.toAction(self) - # if hasattr(self, 'I_am_a_ROOT_interface_handle'): - # return Interface.toAction(self.get()) - # return self -# --------------------------------------------------------------------------- -def _adopt_property(self, action, foreign_name, local_name): +# --------------------------------------------------------------------------- +def _adopt_property(self, action, foreign_name, local_name=None): proc = _get_action(action) + if not local_name: + local_name = foreign_name _get_action(self).adopt_property(proc, str(foreign_name), str(local_name)) # --------------------------------------------------------------------------- -def _add_property(self, name, value): +def _add_new_property(self, name, value): Interface.addProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- -def _add_position_property(self, name, value): +def _add_new_position_property(self, name, value): Interface.addPositionProperty(_get_action(self), str(name), str(value)) # --------------------------------------------------------------------------- -def _add_set_property(self, name, value): +def _add_new_set_property(self, name, value): Interface.addSetProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- -def _add_list_property(self, name, value): +def _add_new_list_property(self, name, value): Interface.addListProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- -def _add_vector_property(self, name, value): +def _add_new_vector_property(self, name, value): Interface.addVectorProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- -def _add_mapped_property(self, name, value): +def _add_new_mapped_property(self, name, value): Interface.addMappedProperty(_get_action(self), str(name), value) +# --------------------------------------------------------------------------- -# --------------------------------------------------------------------------- def _kernel_terminate(self): return self.get().terminate() - - -# --------------------------------------------------------------------------- -Kernel.__getattr__ = _getKernelProperty -Kernel.__setattr__ = _setKernelProperty -Kernel.terminate = _kernel_terminate # --------------------------------------------------------------------------- @@ -281,11 +252,17 @@ def _get(self, name): a = Interface.toAction(self) ret = Interface.getProperty(a, name) if ret.status > 0: - return ret.data - elif hasattr(self.action, name): - return getattr(self.action, name) - elif a.__class__ != self.__class__ and hasattr(a, name): + # print('Property: %s = %s [%s]' % (name, str(ret.data), str(ret.data.__class__),)) + v = ret.data + try: + v = eval(v) + except: + pass + return v + elif hasattr(a, name): return getattr(a, name) + # elif a.__class__ != self.__class__ and hasattr(a, name): + # return getattr(a, name) msg = 'DigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name raise KeyError(msg) # --------------------------------------------------------------------------- @@ -294,12 +271,15 @@ def _get(self, name): def _set(self, name, value): """This function is called when properties are passed to the c++ objects.""" import dd4hep as dd4hep - action = _get_action(self) - name = dd4hep.unicode_2_string(name) - value = dd4hep.unicode_2_string(value) - if Interface.setProperty(action, name, value): + act = _get_action(self) + nam = dd4hep.unicode_2_string(name) + if isinstance(value,str): + val = dd4hep.unicode_2_string(value) + else: + val = str(value) + if Interface.setProperty(act, nam, val): return - msg = 'DigiAction::SetProperty [Unhandled]: Cannot set ' + action.name() + '.' + name + ' = ' + value + msg = 'DigiAction::SetProperty [Unhandled]: Cannot set ' + act.name() + '.' + name + ' = ' + value raise KeyError(msg) # --------------------------------------------------------------------------- @@ -314,7 +294,7 @@ def _props(obj, **extensions): # print('Overloading: ' + str(cls) + ' ' + call + ' to __' + call) setattr(cls, '__' + call, getattr(cls, call)) else: - print('FAILED: Overloading: ' + str(cls) + ' ' + call + ' to __' + call + ' ' + str(hasattr(cls, call))) + debug('FAILED','Overloading: ' + str(cls) + ' ' + call + ' to __' + call + ' ' + str(hasattr(cls, call))) setattr(cls, call, extension[1]) cls.__getattr__ = _get cls.__setattr__ = _set @@ -324,21 +304,25 @@ def _props(obj, **extensions): # # Import unmodified classes from C++ -_import_class('digi', 'DigiKernel') _import_class('digi', 'DigiContext') -_import_class('digi', 'DigiAction') + + +# --------------------------------------------------------------------------- +Kernel = _props('KernelHandle') +_props('DigiKernel') +_props('DigiAction') _import_class('digi', 'DigiEventAction') _import_class('digi', 'DigiInputAction') # # Import classes with specialized python extensions _props('ActionHandle', adopt_property=_adopt_property, - add_property=_add_property, - add_position_property=_add_position_property, - add_set_property=_add_set_property, - add_list_property=_add_list_property, - add_vector_property=_add_vector_property, - add_mapped_property=_add_mapped_property) + add_property=_add_new_property, + add_position_property=_add_new_position_property, + add_set_property=_add_new_set_property, + add_list_property=_add_new_list_property, + add_vector_property=_add_new_vector_property, + add_mapped_property=_add_new_mapped_property) _props('DigiSynchronize', adopt=_adopt_event_action, adopt_action=_adopt_sequence_action) _props('DigiActionSequence', adopt=_adopt_event_action, adopt_action=_adopt_sequence_action) _props('DigiParallelActionSequence', adopt_action=_adopt_sequence_action) @@ -346,11 +330,17 @@ _props('DigiSequentialActionSequence', adopt_action=_adopt_sequence_action) _props('DigiContainerSequenceAction', adopt_container_processor=_adopt_container_processor) _props('DigiMultiContainerProcessor', adopt_processor=_adopt_processor) _props('DigiSegmentSplitter', adopt_segment_processor=_adopt_segment_processor) +# --------------------------------------------------------------------------- + + +# --------------------------------------------------------------------------- # # Need to import digitize late, since it cross includes dddigi +# --------------------------------------------------------------------------- Digitize = None try: import digitize Digitize = digitize.Digitize except Exception as X: - logger.error('Failed to import digitize: ' + str(X)) + logger.error('Failed to import digitize application: ' + str(X)) +# --------------------------------------------------------------------------- diff --git a/DDDigi/src/DigiAction.cpp b/DDDigi/src/DigiAction.cpp index f68f560caf4a22dff707370448382b8895e1e06c..b76216bab256d27dfdf99b1c2341cb5de356f7cd 100644 --- a/DDDigi/src/DigiAction.cpp +++ b/DDDigi/src/DigiAction.cpp @@ -40,9 +40,8 @@ DigiAction::DigiAction(const DigiKernel& krnl, const std::string& nam) : m_kernel(krnl), m_name(nam), m_outputLevel(INFO) { InstanceCount::increment(this); - declareProperty("Name", m_name); declareProperty("name", m_name); - declareProperty("OutputLevel", m_outputLevel); + declareProperty("OutputLevel", m_outputLevel=printLevel()); } /// Default destructor @@ -62,13 +61,23 @@ long DigiAction::addRef() { long DigiAction::release() { long count = --m_refCount; if (m_refCount <= 0) { - info("Deleting object %s of type %s Pointer:%p", - m_name.c_str(),typeName(typeid(*this)).c_str(),(void*)this); + debug("Deleting object %s of type %s Pointer:%p", + m_name.c_str(),typeName(typeid(*this)).c_str(),(void*)this); delete this; } return count; } +/// Set DigiAction property +std::size_t DigiAction::printProperties() const { + const auto& props = properties().properties(); + for( const auto& p : props ) { + std::string pn = name()+"."+p.first; + always("+++ %-32s = %-42s [%s]", pn.c_str(), p.second.str().c_str(), p.second.type().c_str()); + } + return props.size(); +} + /// Adopt named property of another action for data processing void DigiAction::adopt_property(DigiAction* action, const std::string& foreign_name, const std::string& local_name) { if ( action ) { @@ -108,6 +117,15 @@ const dd4hep::Property& DigiAction::property(const std::string& nam) const { return properties()[nam]; } +/// Support of debug messages. +std::string DigiAction::format(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + std::string str = dd4hep::format(nullptr, fmt, args); + va_end(args); + return str; +} + /// Support for messages with variable output level using output level void DigiAction::print(const char* fmt, ...) const { int level = std::max(int(outputLevel()),(int)VERBOSE); @@ -120,60 +138,66 @@ void DigiAction::print(const char* fmt, ...) const { } /// Support of debug messages. -std::string DigiAction::format(const char* fmt, ...) const { +void DigiAction::always(const char* fmt, ...) const { va_list args; va_start(args, fmt); - std::string str = dd4hep::format(nullptr, fmt, args); + dd4hep::printout(dd4hep::FORCE_ALWAYS, m_name, fmt, args); va_end(args); - return str; } /// Support of debug messages. void DigiAction::debug(const char* fmt, ...) const { - if ( std::max(int(outputLevel()),(int)VERBOSE) >= DEBUG ) { + int level = std::max(int(outputLevel()),(int)VERBOSE); + if ( level <= DEBUG ) { va_list args; va_start(args, fmt); - dd4hep::printout(dd4hep::DEBUG, m_name, fmt, args); + dd4hep::printout(dd4hep::FORCE_DEBUG, m_name, fmt, args); va_end(args); } } /// Support of info messages. void DigiAction::info(const char* fmt, ...) const { - if ( std::max(int(outputLevel()),(int)VERBOSE) >= INFO ) { + int level = std::max(int(outputLevel()),(int)VERBOSE); + if ( level <= INFO ) { va_list args; va_start(args, fmt); - dd4hep::printout(dd4hep::INFO, m_name, fmt, args); + dd4hep::printout(dd4hep::FORCE_INFO, m_name, fmt, args); va_end(args); } } /// Support of warning messages. void DigiAction::warning(const char* fmt, ...) const { - if ( std::max(int(outputLevel()),(int)VERBOSE) >= WARNING ) { + int level = std::max(int(outputLevel()),(int)VERBOSE); + if ( level <= WARNING ) { va_list args; va_start(args, fmt); - dd4hep::printout(dd4hep::WARNING, m_name, fmt, args); + dd4hep::printout(dd4hep::FORCE_WARNING, m_name, fmt, args); va_end(args); } } /// Action to support error messages. void DigiAction::error(const char* fmt, ...) const { - if ( std::max(int(outputLevel()),(int)VERBOSE) >= ERROR ) { + int level = std::max(int(outputLevel()),(int)VERBOSE); + if ( level <= ERROR ) { va_list args; va_start(args, fmt); - dd4hep::printout(dd4hep::ERROR, m_name, fmt, args); + dd4hep::printout(dd4hep::FORCE_ERROR, m_name, fmt, args); va_end(args); } } /// Action to support error messages. bool DigiAction::return_error(bool return_value, const char* fmt, ...) const { - va_list args; - va_start(args, fmt); - dd4hep::printout(dd4hep::ERROR, m_name, fmt, args); - va_end(args); + int level = std::max(int(outputLevel()),(int)VERBOSE); + if ( level <= ERROR ) { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::FORCE_ERROR, m_name, fmt, args); + va_end(args); + } return return_value; } @@ -181,7 +205,7 @@ bool DigiAction::return_error(bool return_value, const char* fmt, ...) const { void DigiAction::fatal(const char* fmt, ...) const { va_list args; va_start(args, fmt); - dd4hep::printout(dd4hep::FATAL, m_name, fmt, args); + dd4hep::printout(dd4hep::FORCE_FATAL, m_name, fmt, args); va_end(args); } @@ -190,7 +214,7 @@ void DigiAction::except(const char* fmt, ...) const { va_list args; va_start(args, fmt); std::string err = dd4hep::format(m_name, fmt, args); - dd4hep::printout(dd4hep::FATAL, m_name, err.c_str()); + dd4hep::printout(dd4hep::FORCE_FATAL, m_name, err.c_str()); va_end(args); throw std::runtime_error(err); } @@ -202,7 +226,8 @@ namespace dd4hep { namespace digi { template <typename VAL> int add_action_property(DigiAction* action, const std::string& name, VAL value) { - action->addProperty(name, value); + VAL* new_val = new VAL(value); + action->addProperty(name, *(new_val)); printout(INFO, "addProperty", "+++ Added property %s of type %s", name.c_str(), typeName(typeid(VAL)).c_str()); return 1; diff --git a/DDDigi/src/DigiAttenuator.cpp b/DDDigi/src/DigiAttenuator.cpp index df9c9a12e3d984b9f105b75d2fa3c6d27e31dc90..cd9c7421a29dff41a1b4b92519866f7332d382b4 100644 --- a/DDDigi/src/DigiAttenuator.cpp +++ b/DDDigi/src/DigiAttenuator.cpp @@ -47,15 +47,23 @@ template <typename T> std::size_t DigiAttenuator::attenuate(T& cont, const predicate_t& predicate) const { for( auto& dep : cont ) { if ( predicate(dep) ) { - auto& depo = dep.second; - depo.deposit *= m_factor; - for( auto& h : depo.history.hits ) h.weight *= m_factor; - for( auto& h : depo.history.particles ) h.weight *= m_factor; + dep.second.deposit *= m_factor; } } return cont.size(); } +/// Attenuator callback for single container +template <> std::size_t +DigiAttenuator::attenuate<DetectorHistory>(DetectorHistory& cont, const predicate_t& /* predicate */) const { + for( auto& history : cont ) { + auto& entry = history.second; + for( auto& h : entry.hits ) h.weight *= m_factor; + for( auto& h : entry.particles ) h.weight *= m_factor; + } + return cont.size(); +} + /// Main functional callback adapter void DigiAttenuator::execute(DigiContext& context, work_t& work, const predicate_t& predicate) const { std::size_t count = 0; @@ -63,6 +71,8 @@ void DigiAttenuator::execute(DigiContext& context, work_t& work, const predicate count = this->attenuate(*m, predicate); else if ( auto* v = work.get_input<DepositVector>() ) count = this->attenuate(*v, predicate); + else if ( auto* h = work.get_input<DetectorHistory>() ) + count = this->attenuate(*h, predicate); 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", @@ -73,10 +83,12 @@ void DigiAttenuator::execute(DigiContext& context, work_t& work, const predicate 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); + declareProperty("attenuate_history", m_attenuate_history); + declareProperty("attenuate_data", m_attenuate_data); + 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); } @@ -93,7 +105,6 @@ void DigiAttenuatorSequence::initialize() { 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': @@ -104,13 +115,30 @@ void DigiAttenuatorSequence::initialize() { 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()); + // First bunch of processors: Attenuate the signal + if ( m_attenuate_data ) { + std::string nam = name() + ".D." + c.first; + 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); + att->property("OutputLevel").set(int(outputLevel())); + adopt_processor(att, c.first); + } + // Second bunch of processors: Attenuate the history weights accordingly + if ( m_attenuate_history ) { + std::string nam = name() + ".H." + c.first; + 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+".hist"); + att->property("OutputLevel").set(int(outputLevel())); } - att->property("factor").set(factor); - adopt_processor(att, c.first); } this->DigiContainerSequenceAction::initialize(); } diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp index 22939f5a5cdef5e8d43a75aae9fa1a382c0c2127..a68e6f53915829aa79362093b7349af8a4580229 100644 --- a/DDDigi/src/DigiContainerCombine.cpp +++ b/DDDigi/src/DigiContainerCombine.cpp @@ -71,7 +71,7 @@ public: } } ::snprintf(format, sizeof(format), - "%s+++%%2d++ %%-32s Mask: $%04X Input: $%%04X Merged %%6ld %%s", + "%s Thread:%%2d+++ %%-32s Out-Mask: $%04X In-Mask: $%%04X Merged %%6ld %%s", event.id(), combine->m_deposit_mask); format[sizeof(format)-1] = 0; } @@ -90,7 +90,7 @@ public: cnt = output.merge(std::move(input)); else cnt = output.insert(input); - combine->debug(this->format, thr, nam.c_str(), mask, cnt, "deposits"); + combine->info(this->format, thr, nam.c_str(), mask, cnt, "deposits"); this->cnt_depos += cnt; this->cnt_conts++; } @@ -105,7 +105,7 @@ public: DetectorHistory* next = std::any_cast<DetectorHistory>(work[j]); std::string next_name = next->name; cnt = (combine->m_erase_combined) ? out.merge(std::move(*next)) : out.insert(*next); - combine->debug(format, thr, next_name.c_str(), keys[j].mask(), cnt, "histories"); + combine->info(format, thr, next_name.c_str(), keys[j].mask(), cnt, "histories"); used_keys_insert(keys[j]); cnt_hist += cnt; cnt_conts++; @@ -124,7 +124,7 @@ public: DetectorResponse* next = std::any_cast<DetectorResponse>(work[j]); std::string next_name = next->name; cnt = (combine->m_erase_combined) ? out.merge(std::move(*next)) : out.insert(*next); - combine->debug(format, thr, next_name.c_str(), keys[j].mask(), cnt, "histories"); + combine->info(format, thr, next_name.c_str(), keys[j].mask(), cnt, "responses"); used_keys_insert(keys[j]); cnt_response += cnt; cnt_conts++; @@ -143,7 +143,7 @@ public: ParticleMapping* next = std::any_cast<ParticleMapping>(work[j]); std::string next_name = next->name; cnt = (combine->m_erase_combined) ? out.merge(std::move(*next)) : out.insert(*next); - combine->debug(format, thr, next_name.c_str(), keys[j].mask(), cnt, "particles"); + combine->info(format, thr, next_name.c_str(), keys[j].mask(), cnt, "particles"); used_keys_insert(keys[j]); cnt_parts += cnt; cnt_conts++; diff --git a/DDDigi/src/DigiContainerDrop.cpp b/DDDigi/src/DigiContainerDrop.cpp index efdcd5f3a6d56a72dde8e1378ff1daf8410ddd75..d88b8e6271fda46b0c9900257f5ba12b4094a86b 100644 --- a/DDDigi/src/DigiContainerDrop.cpp +++ b/DDDigi/src/DigiContainerDrop.cpp @@ -151,7 +151,7 @@ void DigiContainerDrop::execute(DigiContext& context) const { if ( m_workers.size() < count ) { auto group = m_workers.get_group(); // Lock worker group for(size_t i=m_workers.size(); i <= count; ++i) - m_workers.insert(new Worker(nullptr, i)); + m_workers.insert(new worker_t(nullptr, i)); } m_kernel.submit(context, m_workers.get_group(), def.items.size(), &def); } diff --git a/DDDigi/src/DigiContainerProcessor.cpp b/DDDigi/src/DigiContainerProcessor.cpp index 0fe42335f6bbb21e6aba1a75a943e55f5c94deca..7c87f6ef5dc58368988f844ec8226692abce3fa2 100644 --- a/DDDigi/src/DigiContainerProcessor.cpp +++ b/DDDigi/src/DigiContainerProcessor.cpp @@ -31,8 +31,8 @@ namespace dd4hep { 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 ( input.data->has_value() ) { + T* object = std::any_cast<T>(input.data); if ( object ) { return object; } @@ -46,8 +46,8 @@ namespace dd4hep { } 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 ( input.data->has_value() ) { + const T* object = std::any_cast<T>(input.data); if ( object ) { return object; } @@ -62,21 +62,36 @@ namespace dd4hep { } // 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; +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; +template DetectorHistory* DigiContainerProcessor::work_t::get_input(bool exc); +template const DetectorHistory* DigiContainerProcessor::work_t::get_input(bool exc) const; +template DetectorResponse* DigiContainerProcessor::work_t::get_input(bool exc); +template const DetectorResponse* DigiContainerProcessor::work_t::get_input(bool exc) const; + +/// Access the deposit history of a deposit container +const DepositsHistory* +DigiContainerProcessor::work_t::get_history(const std::string& container, bool exc) const { + std::string hist_name = container+".hist"; + if ( exc ) { + dd4hep::except("DigiContainerProcessor", "+++ Cannot access history %s.", hist_name.c_str()); + } + return nullptr; +} + /// input data type const std::type_info& DigiContainerProcessor::work_t::input_type() const { - return input.data.type(); + 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()); + return typeName(input.data->type()); } /// Access to default callback @@ -85,6 +100,12 @@ const DigiContainerProcessor::predicate_t& DigiContainerProcessor::accept_all() return s_pred; } +/// Access to default callback +const DigiContainerProcessor::predicate_t& DigiContainerProcessor::accept_not_killed() { + static predicate_t s_pred { std::bind(predicate_t::not_killed, std::placeholders::_1), 0, nullptr }; + return s_pred; +} + /// Standard constructor DigiContainerProcessor::DigiContainerProcessor(const kernel_t& kernel, const std::string& name) : DigiAction(kernel, name) @@ -97,8 +118,15 @@ DigiContainerProcessor::~DigiContainerProcessor() { InstanceCount::decrement(this); } +/// Adopt monitoring action +void DigiContainerProcessor::adopt_monitor(DigiDepositMonitor* monitor) { + if ( monitor ) monitor->addRef(); + if ( m_monitor ) m_monitor->release(); + m_monitor = monitor; +} + /// Main functional callback if specific work is known -void DigiContainerProcessor::execute(context_t& /* context */, +void DigiContainerProcessor::execute(context_t& /* context */, work_t& /* work */, const predicate_t& /* predicate */) const { } @@ -132,7 +160,7 @@ void DigiContainerSequence::adopt_processor(DigiContainerProcessor* action) { except("+++ FAILED: attempt to add invalid processor!"); return; } - m_workers.insert(new worker_t(action, m_workers.size())); + m_workers.insert(new worker_t(action, m_workers.size(), *this)); } /// Main functional callback if specific work is known @@ -144,9 +172,10 @@ void DigiContainerSequence::execute(context_t& context, work_t& work, const pred /// Worker adaptor for caller DigiContainerSequence template <> void DigiParallelWorker<DigiContainerProcessor, DigiContainerSequence::work_t, - std::size_t>::execute(void* data) const { + std::size_t, + DigiContainerSequence&>::execute(void* data) const { calldata_t* arg = reinterpret_cast<calldata_t*>(data); - action->execute(arg->context, *arg, action->accept_all()); + action->execute(arg->environ.context, *arg, predicate.m_worker_predicate); } /// Standard constructor @@ -169,13 +198,18 @@ DigiContainerSequenceAction::~DigiContainerSequenceAction() { /// Initialization callback void dd4hep::digi::DigiContainerSequenceAction::initialize() { for( auto& ent : m_registered_processors ) { - worker_t* w = new worker_t(ent.second, m_registered_workers.size()); + worker_t* w = new worker_t(ent.second, m_registered_workers.size(), *this); m_registered_workers.emplace(ent.first, w); m_workers.insert(w); ent.second->release(); } } +/// Set the default predicate +void DigiContainerSequenceAction::set_predicate(const predicate_t& predicate) { + m_worker_predicate = predicate; +} + /// Adopt new parallel worker void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action, const std::string& container) @@ -230,16 +264,19 @@ void DigiContainerSequenceAction::execute(context_t& context) const { auto& input = event.get_segment(m_input_segment); auto& output = event.get_segment(m_output_segment); output_t out { m_output_mask, output }; - work_t arg { context, { }, out, m_properties, *this }; + env_t env { context, m_properties, out }; + work_items_t items; + work_t arg { env, items, *this }; + work_item_t itm { nullptr, { }, nullptr }; - arg.input_items.resize(m_workers.size(), { { }, nullptr }); + arg.input_items.resize(m_workers.size(), itm); event_workers.reserve(input.size()); for( auto& i : input ) { Key key(i.first); if ( key.mask() == m_input_mask ) { if ( worker_t* w = need_registered_worker(key, false) ) { event_workers.emplace_back(w); - arg.input_items[w->options] = { key, &i.second }; + arg.input_items[w->options] = { &input, key, &i.second }; } } } @@ -251,11 +288,12 @@ void DigiContainerSequenceAction::execute(context_t& context) const { /// Worker adaptor for caller DigiContainerSequenceAction template <> void DigiParallelWorker<DigiContainerProcessor, DigiContainerSequenceAction::work_t, - 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, args->properties }; - action->execute(args->context, work, action->accept_all()); + std::size_t, + DigiContainerSequenceAction&>::execute(void* data) const { + auto* args = reinterpret_cast<calldata_t*>(data); + auto& item = args->input_items[this->options]; + DigiContainerProcessor::work_t work { args->environ, item }; + action->execute(args->environ.context, work, predicate.m_worker_predicate); } /// Standard constructor @@ -303,7 +341,7 @@ void DigiMultiContainerProcessor::initialize() { w = iw->second; } else { - w = new worker_t(action, m_workers.size()); + w = new worker_t(action, m_workers.size(), *this); m_worker_keys.emplace_back(worker_keys); m_workers.insert(w); action_workers[action] = w; @@ -326,6 +364,11 @@ void DigiMultiContainerProcessor::initialize() { action->release(); } +/// Set the default predicate +void DigiMultiContainerProcessor::set_predicate(const predicate_t& predicate) { + m_worker_predicate = predicate; +} + /// Adopt new parallel worker void DigiMultiContainerProcessor::adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers) { if ( !action ) { @@ -345,12 +388,12 @@ void DigiMultiContainerProcessor::adopt_processor(DigiContainerProcessor* action /// Main functional callback void DigiMultiContainerProcessor::execute(context_t& context) const { - work_items_t work_items; + work_items_t items; auto& mask = m_input_masks; auto& event = *context.event; auto& input = event.get_segment(m_input_segment); - work_items.reserve(input.size()); + items.reserve(input.size()); for( auto& i : input ) { Key key(i.first); key.set_mask(0); @@ -358,14 +401,15 @@ void DigiMultiContainerProcessor::execute(context_t& context) const { if ( use ) { use = m_work_items.empty() || m_work_items.find(key) != m_work_items.end(); if ( use ) { - work_items.emplace_back(std::make_pair(i.first, &i.second)); + items.push_back({ &input, i.first, &i.second}); } } } - if ( !work_items.empty() ) { + if ( !items.empty() ) { auto& output = event.get_segment(m_output_segment); output_t out { m_output_mask, output }; - work_t arg { context, work_items, out, properties(), *this }; + env_t env { context, properties(), out }; + work_t arg { env, items, *this }; m_kernel.submit(context, m_workers.get_group(), m_workers.size(), &arg, m_parallel); } } @@ -373,25 +417,26 @@ void DigiMultiContainerProcessor::execute(context_t& context) const { /// Worker adaptor for caller DigiMultiContainerProcessor template <> void DigiParallelWorker<DigiContainerProcessor, DigiMultiContainerProcessor::work_t, - std::size_t>::execute(void* data) const { + std::size_t, + DigiMultiContainerProcessor&>::execute(void* data) const { calldata_t* arg = reinterpret_cast<calldata_t*>(data); const auto& par = arg->parent; const auto& keys = par.worker_keys(this->options); const auto& masks = par.input_masks(); for( const auto& item : arg->items ) { - Key key(item.first); + Key key(item.key); key.set_mask(0); const char* tag = ""; if ( masks.empty() || std::find(masks.begin(), masks.end(), key.mask()) != masks.end() ) { tag = "mask accepted"; if ( keys.empty() ) { - DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output, arg->properties }; - action->execute(work.context, work, action->accept_all()); + DigiContainerProcessor::work_t work { arg->environ, item }; + action->execute(work.environ.context, work, predicate.m_worker_predicate); continue; } else if ( std::find(keys.begin(), keys.end(), key) != keys.end() ) { - DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output, arg->properties }; - action->execute(work.context, work, action->accept_all()); + DigiContainerProcessor::work_t work { arg->environ, item }; + action->execute(work.environ.context, work, predicate.m_worker_predicate); continue; } tag = "no keys matching"; diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index 9f40c8773052702cc4d847c02103fded09895d9a..bbe18cd3ebcadb2eaeb5d69939edb80c6d404367 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -155,7 +155,6 @@ void EnergyDeposit::update_deposit_weighted(const EnergyDeposit& upda) { position = pos; momentum = mom; deposit = sum; - history.update(upda.history); } /// Update the deposit using deposit weighting @@ -166,7 +165,6 @@ void EnergyDeposit::update_deposit_weighted(EnergyDeposit&& upda) { position = pos; momentum = mom; deposit = sum; - history.update(upda.history); } /// Merge new deposit map onto existing map diff --git a/DDDigi/src/DigiDepositMonitor.cpp b/DDDigi/src/DigiDepositMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40acfdf34497178a3eb6478ca646a865722ba839 --- /dev/null +++ b/DDDigi/src/DigiDepositMonitor.cpp @@ -0,0 +1,138 @@ +//========================================================================== +// 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/DigiKernel.h> +#include <DDDigi/DigiDepositMonitor.h> + +/// ROOT include filess +#include <TH1F.h> +#include <TH2F.h> + +/// C/C++ include files + +using namespace dd4hep::digi; + +/// Add 1D histogram entry with weight +void Histo1D::fill(double x, double weight) { + hist->Fill(x, weight); +} + +/// Add 2D histogram entry with weight +void Histo2D::fill(double x, double y, double weight) { + hist->Fill(x, y, weight); +} + +/// Standard constructor +DigiDepositMonitor::DigiDepositMonitor(const DigiKernel& krnl, const std::string& nam) + : DigiAction(krnl, nam) +{ + m_kernel.register_initialize(std::bind(&DigiDepositMonitor::initialize,this)); + InstanceCount::increment(this); +} + +/// Default destructor +DigiDepositMonitor::~DigiDepositMonitor() { + InstanceCount::decrement(this); +} + +/// Initializing function: compute values which depend on properties +void DigiDepositMonitor::initialize() { +} + +/// Book 1D histogram and register it to the kernel for output handling +Histo1D DigiDepositMonitor::book1D(const std::string& name, const std::string& title, + std::size_t nbin_x, double min_x, double max_x) { + auto* h = new TH1F(name.c_str(), title.c_str(), nbin_x, min_x, max_x); + m_kernel.register_monitor(this, h); + return { h }; +} + +/// Book 1D histogram and register it to the kernel for output handling +Histo2D DigiDepositMonitor::book2D(const std::string& name, const std::string& title, + std::size_t nbin_x, double min_x, double max_x, + std::size_t nbin_y, double min_y, double max_y) { + auto* h = new TH2F(name.c_str(), title.c_str(), nbin_x, min_x, max_x, nbin_y, min_y, max_y); + m_kernel.register_monitor(this, h); + return { h }; +} + +/// Standard constructor +DigiDepositEnergyMonitor::DigiDepositEnergyMonitor(const kernel_t& kernel, const std::string& name) + : DigiDepositMonitor(kernel, name) +{ + declareProperty("histo1D_deposits", histo1D_deposits); + declareProperty("histo1D_delta", histo1D_delta); +} + +/// Initializing function: overload for sub-classes to e.g. book histograms +void DigiDepositEnergyMonitor::initialize() { + declare_monitor_energy(this, &DigiDepositEnergyMonitor::monitor_energy_shift); + m_deltas = book1D(histo1D_delta.name.c_str(), histo1D_delta.title.c_str(), + histo1D_delta.nbin_x, histo1D_delta.min_x, histo1D_delta.max_x); + m_deposits = book1D(histo1D_deposits.name.c_str(), histo1D_deposits.title.c_str(), + histo1D_deposits.nbin_x, histo1D_deposits.min_x, histo1D_deposits.max_x); +} + +/// Fill the monitoring histograms +void DigiDepositEnergyMonitor::monitor_energy_shift(const deposit_t& deposit, double change) { + m_deposits.fill(deposit.second.deposit, 1e0); + m_deltas.fill(change, 1e0); +} + +/// Standard constructor +DigiDepositTimeMonitor::DigiDepositTimeMonitor(const kernel_t& kernel, const std::string& name) + : DigiDepositMonitor(kernel, name) +{ + declareProperty("histo1D_deposits", histo1D_deposits); + declareProperty("histo1D_delta", histo1D_delta); +} + +/// Initializing function: overload for sub-classes to e.g. book histograms +void DigiDepositTimeMonitor::initialize() { + declare_monitor_time(this, &DigiDepositTimeMonitor::monitor_time_shift); + m_deltas = book1D(histo1D_delta.name.c_str(), histo1D_delta.title.c_str(), + histo1D_delta.nbin_x, histo1D_delta.min_x, histo1D_delta.max_x); + m_deposits = book1D(histo1D_deposits.name.c_str(), histo1D_deposits.title.c_str(), + histo1D_deposits.nbin_x, histo1D_deposits.min_x, histo1D_deposits.max_x); +} + +/// Fill the monitoring histograms +void DigiDepositTimeMonitor::monitor_time_shift(const deposit_t& deposit, double change) { + m_deposits.fill(deposit.second.time, 1e0); + m_deltas.fill(change, 1e0); +} + +/// Standard constructor +DigiDepositPositionMonitor::DigiDepositPositionMonitor(const kernel_t& kernel, const std::string& name) + : DigiDepositMonitor(kernel, name) +{ + declareProperty("histo1D_deposits", histo1D_deposits); + declareProperty("histo1D_delta", histo1D_delta); +} + +/// Initializing function: overload for sub-classes to e.g. book histograms +void DigiDepositPositionMonitor::initialize() { + declare_monitor_position(this, &DigiDepositPositionMonitor::monitor_position_shift); + m_deltas = book1D(histo1D_delta.name.c_str(), histo1D_delta.title.c_str(), + histo1D_delta.nbin_x, histo1D_delta.min_x, histo1D_delta.max_x); + m_deposits = book1D(histo1D_deposits.name.c_str(), histo1D_deposits.title.c_str(), + histo1D_deposits.nbin_x, histo1D_deposits.min_x, histo1D_deposits.max_x); +} + +/// Fill the monitoring histograms +void DigiDepositPositionMonitor::monitor_position_shift(const deposit_t&, const Position& position, const Position& change) { + m_deposits.fill(std::sqrt(position.Mag2()), 1e0); + m_deltas.fill(std::sqrt(change.Mag2()), 1e0); +} diff --git a/DDDigi/src/DigiHandle.cpp b/DDDigi/src/DigiHandle.cpp index 1099d011d975f2741a0e9e615d60c79b26370ec5..f115968eea1aae5405d81f6e25f2572891e48252 100644 --- a/DDDigi/src/DigiHandle.cpp +++ b/DDDigi/src/DigiHandle.cpp @@ -184,6 +184,12 @@ namespace dd4hep { KernelHandle::KernelHandle(DigiKernel* k) : value(k) { } + + Property& KernelHandle::operator[](const string& property_name) const { + PropertyManager& pm = checked_value(value)->properties(); + return pm[property_name]; + } + } } diff --git a/DDDigi/src/DigiKernel.cpp b/DDDigi/src/DigiKernel.cpp index cbf1a625624b580b97628b741334629c986f7bad..ff508c2d095226e25f1833b65e6f420e5c467e67 100644 --- a/DDDigi/src/DigiKernel.cpp +++ b/DDDigi/src/DigiKernel.cpp @@ -22,6 +22,7 @@ #include <DDDigi/DigiKernel.h> #include <DDDigi/DigiContext.h> #include <DDDigi/DigiActionSequence.h> +#include <DDDigi/DigiMonitorHandler.h> #ifdef DD4HEP_USE_TBB #include <tbb/task_group.h> @@ -53,8 +54,6 @@ namespace { */ class DigiKernel::Internals { public: - /// Property pool - PropertyManager properties; /// Property: Client output levels ClientOutputLevels clientLevels; /// Atomic counter: Number of events still to be processed in this run @@ -76,15 +75,16 @@ public: /// Lock for global output logging std::mutex global_output_lock { }; - using callbacks_t = std::vector<std::function<void()> >; + using callbacks_t = std::vector<std::function<void()> >; using ev_callbacks_t = std::vector<std::function<void(DigiContext&)> >; + /// Configure callbacks callbacks_t configurators { }; /// Initialize callbacks callbacks_t initializers { }; - //// Termination callback + /// Termination callback callbacks_t terminators { }; - /// Register start event callback + /// Register start event callback ev_callbacks_t start_event { }; /// Register end event callback ev_callbacks_t end_event { }; @@ -95,9 +95,12 @@ public: DigiActionSequence* event_action { nullptr }; /// The main data output action sequence DigiActionSequence* output_action { nullptr }; + /// The histogram handler entity + DigiMonitorHandler* monitor_handler { nullptr }; /// Random generator TRandom* root_random; + /// Shared random number generator std::shared_ptr<DigiRandomGenerator> random { }; /// TBB initializer (If TBB is used) std::unique_ptr<tbb::global_control> tbb_init { }; @@ -111,7 +114,11 @@ public: int num_threads; /// Property: Allow to stop execution from interactive prompt bool stop = false; + +public: + /// Default constructor Internals() = default; + /// Default destructor ~Internals() = default; }; @@ -171,7 +178,7 @@ public: /// Standard constructor DigiKernel::DigiKernel(Detector& description_ref) - : m_detDesc(&description_ref) + : DigiAction(*this, "DigiKernel"), m_detDesc(&description_ref) { internals = new Internals(); internals->num_threads = tbb::global_control::max_allowed_parallelism; @@ -179,8 +186,11 @@ DigiKernel::DigiKernel(Detector& description_ref) declareProperty("numThreads", internals->num_threads); declareProperty("numEvents", internals->numEvents = 10); declareProperty("stop", internals->stop = false); - declareProperty("OutputLevel", internals->outputLevel = DEBUG); declareProperty("OutputLevels", internals->clientLevels); + auto* h = new DigiMonitorHandler(*this, "MonitorData"); + properties().add("MonitorOutput", h->property("MonitorOutput")); + internals->monitor_handler = h; + internals->input_action = new DigiActionSequence(*this, "InputAction"); internals->event_action = new DigiActionSequence(*this, "EventAction"); internals->output_action = new DigiActionSequence(*this, "OutputAction"); @@ -189,7 +199,7 @@ DigiKernel::DigiKernel(Detector& description_ref) internals->output_action->setExecuteParallel(false); internals->root_random = new TRandom(); internals->random = std::make_shared<DigiRandomGenerator>(); - internals->random->engine = [this] { return this->internals->root_random->Uniform(1.0); }; + internals->random->engine = [this] { return internals->root_random->Uniform(1.0); }; InstanceCount::increment(this); } @@ -197,9 +207,12 @@ DigiKernel::DigiKernel(Detector& description_ref) DigiKernel::~DigiKernel() { std::lock_guard<std::mutex> lock(kernel_mutex); internals->tbb_init.reset(); + detail::releasePtr(internals->monitor_handler); detail::releasePtr(internals->output_action); detail::releasePtr(internals->event_action); detail::releasePtr(internals->input_action); + detail::deletePtr(internals->root_random); + internals->random.reset(); detail::deletePtr(internals); InstanceCount::decrement(this); } @@ -231,32 +244,14 @@ std::mutex& DigiKernel::global_io_lock() const { return internals->global_io_lock; } -/// Access to the properties of the object -PropertyManager& DigiKernel::properties() { - return internals->properties; -} - /// Print the property values -void DigiKernel::printProperties() const { - printout(ALWAYS, "DigiKernel", "OutputLevel: %d", internals->outputLevel); +std::size_t DigiKernel::printProperties() const { + std::size_t count = this->DigiAction::printProperties(); for( const auto& cl : internals->clientLevels ) { - printout(ALWAYS, "DigiKernel", "OutputLevel[%s]: %d", cl.first.c_str(), cl.second); + always("OutputLevel[%s]: %d", cl.first.c_str(), cl.second); + ++count; } -} - -/// Check property for existence -bool DigiKernel::hasProperty(const std::string& name) const { - return internals->properties.exists(name); -} - -/// Access single property -dd4hep::Property& DigiKernel::property(const std::string& name) { - return internals->properties[name]; -} - -/// Access the output level -PrintLevel DigiKernel::outputLevel() const { - return (PrintLevel)internals->outputLevel; + return count; } /// Fill cache with the global output level of a named object. Must be set before instantiation @@ -271,31 +266,24 @@ dd4hep::PrintLevel DigiKernel::getOutputLevel(const std::string object) const return dd4hep::PrintLevel(dd4hep::printLevel()-1); } -/// Set the output level; returns previous value -dd4hep::PrintLevel DigiKernel::setOutputLevel(PrintLevel new_level) { - int old = internals->outputLevel; - internals->outputLevel = new_level; - return (PrintLevel)old; -} - /// Access current number of events still to process std::size_t DigiKernel::events_todo() const { - std::lock_guard<std::mutex> lock(this->internals->counter_lock); - std::size_t evts = this->internals->events_todo; + std::lock_guard<std::mutex> lock(internals->counter_lock); + std::size_t evts = internals->events_todo; return evts; } /// Access current number of events already processed std::size_t DigiKernel::events_done() const { - std::lock_guard<std::mutex> lock(this->internals->counter_lock); - std::size_t evts = this->internals->numEvents - this->internals->events_todo; + std::lock_guard<std::mutex> lock(internals->counter_lock); + std::size_t evts = internals->numEvents - internals->events_todo; return evts; } /// Access current number of events processing (events in flight) std::size_t DigiKernel::events_processing() const { - std::lock_guard<std::mutex> lock(this->internals->counter_lock); - std::size_t evts = this->internals->events_submitted - this->internals->events_finished; + std::lock_guard<std::mutex> lock(internals->counter_lock); + std::size_t evts = internals->events_submitted - internals->events_finished; return evts; } @@ -323,6 +311,21 @@ int DigiKernel::initialize() { return 1; } +/// Access to the main input action sequence from the kernel object +DigiActionSequence& DigiKernel::inputAction() const { + return *internals->input_action; +} + +/// Access to the main event action sequence from the kernel object +DigiActionSequence& DigiKernel::eventAction() const { + return *internals->event_action; +} + +/// Access to the main output action sequence from the kernel object +DigiActionSequence& DigiKernel::outputAction() const { + return *internals->output_action; +} + /// Register configure callback void DigiKernel::register_configure(const std::function<void()>& callback) const { std::lock_guard<std::mutex> lock(initializer_lock()); @@ -330,7 +333,7 @@ void DigiKernel::register_configure(const std::function<void()>& callback) con } /// Register initialize callback -void DigiKernel::register_initialize(const std::function<void()>& callback) const { +void DigiKernel::register_initialize(const std::function<void()>& callback) const { std::lock_guard<std::mutex> lock(initializer_lock()); internals->initializers.push_back(callback); } @@ -351,19 +354,17 @@ void DigiKernel::register_end_event(const std::function<void(DigiContext&)>& cal internals->end_event.push_back(callback); } -/// Access to the main input action sequence from the kernel object -DigiActionSequence& DigiKernel::inputAction() const { - return *internals->input_action; -} - -/// Access to the main event action sequence from the kernel object -DigiActionSequence& DigiKernel::eventAction() const { - return *internals->event_action; -} - -/// Access to the main output action sequence from the kernel object -DigiActionSequence& DigiKernel::outputAction() const { - return *internals->output_action; +/// Registration of monitoring objects eventually saved by the handler +void DigiKernel::register_monitor(DigiAction* action, TNamed* object) const { + if ( action && object ) { + std::lock_guard<std::mutex> lock(internals->counter_lock); + internals->monitor_handler->adopt(action, object); + return; + } + except("DigiKernel","+++ Invalid monitor request from action %s with object %s: %s", + action ? action->name().c_str() : "[Invalid]", + object ? object->GetName() : "[Invalid]", + object ? object->GetTitle() : ""); } /// Submit a bunch of actions to be executed in parallel @@ -373,21 +374,21 @@ void DigiKernel::submit (DigiContext& context, ParallelCall*const algorithms[], bool para = parallel && (internals->tbb_init && internals->num_threads > 0); if ( para ) { tbb::task_group que; - printout(INFO,"DigiKernel","%s+++ Executing chunk of %ld execution entries in parallel", tag, count); + info("%s+++ Executing chunk of %3ld execution entries in parallel", tag, count); for( std::size_t i=0; i<count; ++i) que.run( Wrapper<ParallelCall,void*>(algorithms[i], data) ); que.wait(); return; } #endif - printout(INFO,"DigiKernel","%s+++ Executing chunk of %ld execution entries sequentially", tag, count); + info("%s+++ Executing chunk of %3ld execution entries sequentially", tag, count); for( std::size_t i=0; i<count; ++i) algorithms[i]->execute(data); } /// Submit a bunch of actions to be executed in parallel void DigiKernel::submit (DigiContext& context, const std::vector<ParallelCall*>& algorithms, void* data, bool parallel) const { - this->submit(context, &algorithms[0], algorithms.size(), data, parallel); + submit(context, &algorithms[0], algorithms.size(), data, parallel); } void DigiKernel::wait(DigiContext& context) const { @@ -423,8 +424,8 @@ void DigiKernel::notify(std::unique_ptr<DigiContext>&& context) { void DigiKernel::notify(std::unique_ptr<DigiContext>&& context, const std::exception& e) { const char* tag = context->event->id(); internals->stop = true; - printout(ERROR,"DigiKernel","%s+++ Exception during event processing [Shall stop the event loop]", tag); - printout(ERROR,"DigiKernel","%s -> %s", tag, e.what()); + error("%s+++ Exception during event processing [Shall stop the event loop]", tag); + error("%s -> %s", tag, e.what()); notify(std::move(context)); } @@ -435,15 +436,15 @@ int DigiKernel::run() { internals->events_finished = 0; internals->events_submitted = 0; internals->events_todo = internals->numEvents; - printout(INFO,"DigiKernel","+++ Total number of events: %d",internals->numEvents); + info("+++ Total number of events: %d",internals->numEvents); #ifdef DD4HEP_USE_TBB if ( !internals->tbb_init && internals->num_threads > 0 ) { using ctrl_t = tbb::global_control; if ( 0 == internals->num_threads ) { internals->num_threads = ctrl_t::max_allowed_parallelism; } - printout(INFO, "DigiKernel", "+++ Number of TBB threads to: %d",internals->num_threads); - printout(INFO, "DigiKernel", "+++ Number of parallel events: %d",internals->maxEventsParallel); + info("+++ Number of TBB threads to: %d",internals->num_threads); + info("+++ Number of parallel events: %d",internals->maxEventsParallel); internals->tbb_init = std::make_unique<ctrl_t>(ctrl_t::max_allowed_parallelism,internals->num_threads+1); if ( internals->maxEventsParallel >= 0 ) { int todo_evt = internals->events_todo; @@ -453,7 +454,7 @@ int DigiKernel::run() { main_group.run(Processor(*this)); main_group.wait(); } - printout(DEBUG, "DigiKernel", "+++ All event processing threads Synchronized --- Done!"); + debug("+++ All event processing threads Synchronized --- Done!"); } else #endif @@ -466,16 +467,18 @@ int DigiKernel::run() { } std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; double sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); - printout(DEBUG, "DigiKernel", "+++ %d Events out of %d processed. " - "Total: %7.1f seconds %7.3f seconds/event", - internals->numEvents-int(internals->events_todo), internals->numEvents, - sec, sec/double(std::max(1,internals->numEvents))); + debug("+++ %d Events out of %d processed. " + "Total: %7.1f seconds %7.3f seconds/event", + internals->numEvents-int(internals->events_todo), internals->numEvents, + sec, sec/double(std::max(1,internals->numEvents))); return 1; } /// Terminate the digitization: call all registered terminators and release the allocated resources int DigiKernel::terminate() { - printout(INFO, "DigiKernel", "++ Terminate Digi and delete associated actions."); + info("++ Saving monitoring quantities."); + internals->monitor_handler->save(); + info("++ Terminate Digi and delete associated actions."); for(auto& call : internals->terminators) call(); m_detDesc->destroyInstance(); m_detDesc = 0; diff --git a/DDDigi/src/DigiMonitorHandler.cpp b/DDDigi/src/DigiMonitorHandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31abb1180ab2cc446eed54a7169c6df51df41a43 --- /dev/null +++ b/DDDigi/src/DigiMonitorHandler.cpp @@ -0,0 +1,82 @@ +//========================================================================== +// 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/Printout.h> +#include <DDDigi/DigiMonitorHandler.h> + +/// ROOT include files +#include <TFile.h> + +/// C/C++ include files + +using namespace std; +using namespace dd4hep::digi; + +/// Standard constructor +DigiMonitorHandler::DigiMonitorHandler(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + declareProperty("MonitorOutput", m_output_file); +} + +/// Default destructor +DigiMonitorHandler::~DigiMonitorHandler() { + for( auto& m : m_monitors ) { + m.first->release(); + for( auto* itm : m.second ) { + detail::deletePtr(itm); + } + m.second.clear(); + } + m_monitors.clear(); +} + +/// Adopt monitor and keep reference for saving +void DigiMonitorHandler::adopt(DigiAction* source, TNamed* object) { + source->addRef(); + m_monitors[source].insert(object); +} + +/// Save monitors +void DigiMonitorHandler::save() { + if ( !m_output_file.empty() ) { + TFile* output = TFile::Open(m_output_file.c_str(), + "DD4hep Digitization monitoring information", + "RECREATE"); + TDirectory::TContext top_context(output); + if ( output && !output->IsZombie() ) { + for( const auto& m : m_monitors ) { + const auto* act = m.first; + const auto& items = m.second; + const auto& nam = act->name(); + std::string title = "Monitor items of digitization action "+nam; + TDirectory* direc = output->mkdir(nam.c_str(), title.c_str(), kTRUE); + TDirectory::TContext action_context(direc); + for( const auto* itm : items ) { + Int_t nbytes = direc->WriteTObject(itm); + if ( nbytes <= 0 ) { + error("+++ Failed to write object: %s -> %s", nam.c_str(), itm->GetName()); + } + } + direc->Write(); + } + output->Write(); + output->Close(); + delete output; + return; + } + except("+++ Failed to open monitoring output file: %s", m_output_file.c_str()); + } +} + diff --git a/DDDigi/src/DigiMonitorParser.cpp b/DDDigi/src/DigiMonitorParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0103ee38c56d9c291bd50ca6326fbd3e2200a26f --- /dev/null +++ b/DDDigi/src/DigiMonitorParser.cpp @@ -0,0 +1,209 @@ +//========================================================================== +// 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 <Parsers/spirit/ParsersFactory.h> +#include <DDDigi/DigiMonitorOptions.h> + +// ============================================================================ +namespace dd4hep { + // ========================================================================== + namespace Parsers { + + // ======================================================================== + // 1D histogram parameters + // ======================================================================== + std::ostream& toStream(const dd4hep::digi::H1DParams& o, std::ostream& s) { + return s << "( " + << '"' << o.name << '"' << " , " + << '"' << o.title << '"' << " , " + << o.nbin_x << " , " + << o.min_x << " , " + << o.max_x + << " )" ; + } + + // ======================================================================== + template< typename Iterator, typename Skipper> + class H1DParamsGrammar : public qi::grammar<Iterator, dd4hep::digi::H1DParams(), Skipper> + { + public: + // ====================================================================== + typedef dd4hep::digi::H1DParams ResultT; + // ====================================================================== + public: + struct tag_name{}; + struct tag_title{}; + struct tag_nbin_x{}; + struct tag_min_x{}; + struct tag_max_x{}; + struct Operations { + // Some magic: + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + // Actions: + // -------------------------------------------------------------------- + void operator()(dd4hep::digi::H1DParams& val, const int bin, tag_nbin_x) const { + val.nbin_x = bin; + } + + void operator()(dd4hep::digi::H1DParams& val, const float x, tag_min_x) const { + val.min_x = x; + } + + void operator()(dd4hep::digi::H1DParams& val, const float x, tag_max_x) const { + val.max_x = x; + } + + void operator()(dd4hep::digi::H1DParams& val, const std::string& name, tag_name) const { + val.name = name; + } + + void operator()(dd4hep::digi::H1DParams& val, const std::string& title, tag_title) const { + val.title = title; + } + + }; + public: + H1DParamsGrammar() : H1DParamsGrammar::base_type(para) { + para = qi::lit('(') + >> name[op(qi::_val, qi::_1, tag_name())] + >> ',' + >> title[op(qi::_val, qi::_1, tag_title())] + >> ',' + >> qi::int_[op(qi::_val, qi::_1, tag_nbin_x())] + >> ',' + >> qi::double_[op(qi::_val, qi::_1, tag_min_x())] + >> ',' + >> qi::double_[op(qi::_val, qi::_1, tag_max_x())] + >> ')'; + } + qi::rule<Iterator, dd4hep::digi::H1DParams(), Skipper> para; + StringGrammar<Iterator, Skipper> name; + StringGrammar<Iterator, Skipper> title; + ph::function<Operations> op; + // ====================================================================== + }; + REGISTER_GRAMMAR(dd4hep::digi::H1DParams, H1DParamsGrammar); + // ======================================================================== + int parse(dd4hep::digi::H1DParams& result, const std::string& input) { + return parse_(result, input); + } + + // ======================================================================== + // 2D histogram parameters + // ======================================================================== + std::ostream& toStream(const dd4hep::digi::H2DParams& o, std::ostream& s) { + return s << "[ " + << '"' << o.name << "\" , " + << '"' << o.title << "\" , " + << o.nbin_x << " , " + << o.min_x << " , " + << o.max_x << " , " + << o.nbin_y << " , " + << o.min_y << " , " + << o.max_y + << " ]" ; + } + // ======================================================================== + template< typename Iterator, typename Skipper> + class H2DParamsGrammar : public qi::grammar<Iterator, dd4hep::digi::H2DParams(), Skipper> + { + public: + // ====================================================================== + typedef dd4hep::digi::H2DParams ResultT; + // ====================================================================== + public: + struct tag_name{}; + struct tag_title{}; + struct tag_nbin_x{}; + struct tag_min_x{}; + struct tag_max_x{}; + struct tag_nbin_y{}; + struct tag_min_y{}; + struct tag_max_y{}; + struct Operations { + // Some magic: + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + // Actions: + // -------------------------------------------------------------------- + void operator()(dd4hep::digi::H2DParams& val, const int bin, tag_nbin_x) const { + val.nbin_x = bin; + } + void operator()(dd4hep::digi::H2DParams& val, const float x, tag_min_x) const { + val.min_x = x; + } + void operator()(dd4hep::digi::H2DParams& val, const float x, tag_max_x) const { + val.max_x = x; + } + void operator()(dd4hep::digi::H2DParams& val, const int bin, tag_nbin_y) const { + val.nbin_y = bin; + } + void operator()(dd4hep::digi::H2DParams& val, const float y, tag_min_y) const { + val.min_y = y; + } + void operator()(dd4hep::digi::H2DParams& val, const float y, tag_max_y) const { + val.max_y = y; + } + void operator()(dd4hep::digi::H2DParams& val, const std::string& name, tag_name) const { + val.name = name; + } + void operator()(dd4hep::digi::H2DParams& val, const std::string& title, tag_title) const { + val.title = title; + } + + }; + public: + H2DParamsGrammar() : H2DParamsGrammar::base_type(para) { + para = qi::lit('[') + >> name[op(qi::_val, qi::_1, tag_name())] + >> ',' + >> title[op(qi::_val, qi::_1, tag_title())] + >> ',' + >> qi::int_[op(qi::_val, qi::_1, tag_nbin_x())] + >> ',' + >> qi::float_[op(qi::_val, qi::_1, tag_min_x())] + >> ',' + >> qi::float_[op(qi::_val, qi::_1, tag_max_x())] + >> ',' + >> qi::int_[op(qi::_val, qi::_1, tag_nbin_y())] + >> ',' + >> qi::float_[op(qi::_val, qi::_1, tag_min_y())] + >> ',' + >> qi::float_[op(qi::_val, qi::_1, tag_max_y())] + >> ']' ; + } + qi::rule<Iterator, dd4hep::digi::H2DParams(), Skipper> para; + StringGrammar<Iterator, Skipper> name; + StringGrammar<Iterator, Skipper> title; + ph::function<Operations> op; + // ====================================================================== + }; + REGISTER_GRAMMAR(dd4hep::digi::H2DParams, H2DParamsGrammar); + // ======================================================================== + int parse(dd4hep::digi::H2DParams& result, const std::string& input) { + return parse_(result, input); + } + // ======================================================================== + } // end of namespace dd4hep::Parsers + // ========================================================================== +} // end of namespace dd4hep +// ============================================================================ +#include "DD4hep/GrammarParsed.h" +static auto s_registry = dd4hep::GrammarRegistry::pre_note<dd4hep::digi::H1DParams>() + .pre_note<dd4hep::digi::H2DParams>(); diff --git a/DDDigi/src/DigiSegmentSplitter.cpp b/DDDigi/src/DigiSegmentSplitter.cpp index 0b25a61e3fc4b533c6638c0bbe3717e92c14b918..c3486b780bb0c31a7ace6608c1458400b09bafa1 100644 --- a/DDDigi/src/DigiSegmentSplitter.cpp +++ b/DDDigi/src/DigiSegmentSplitter.cpp @@ -50,7 +50,7 @@ template <> void DigiParallelWorker<DigiContainerProcessor, DigiContainerProcessor::work_t, DigiSegmentProcessContext>::execute(void* ptr) const { calldata_t* args = reinterpret_cast<calldata_t*>(ptr); - action->execute(args->context, *args, this->options.predicate); + action->execute(args->environ.context, *args, this->options.predicate); } /// Standard constructor diff --git a/DDDigi/src/DigiStoreDump.cpp b/DDDigi/src/DigiStoreDump.cpp index c0e1d07efa5c26e7767771f331934b445d0db1a8..84ab134c1e9ee0b8e604302295aeab20b0e2ddf8 100644 --- a/DDDigi/src/DigiStoreDump.cpp +++ b/DDDigi/src/DigiStoreDump.cpp @@ -70,7 +70,6 @@ template <> std::string DigiStoreDump::data_header(Key key, const std::string& t return data_header(key, tag, data.type()); } - template <> std::vector<std::string> DigiStoreDump::dump_history(DigiContext& context, Key key, @@ -101,6 +100,7 @@ DigiStoreDump::dump_history(DigiContext& context, return records; } +#ifdef DDDIGI_INPLACE_HISTORY template <> std::vector<std::string> DigiStoreDump::dump_history(DigiContext& context, Key container_key, @@ -151,13 +151,65 @@ DigiStoreDump::dump_history(DigiContext& context, } return records; } +#endif + +template <> std::vector<std::string> +DigiStoreDump::dump_history(DigiContext& context, + Key container_key, + const std::pair<const CellID, History>& data, + std::size_t seq_no) const +{ + std::string line; + std::stringstream str; + auto& ev = *(context.event); + const auto& history = data.second; + const CellID cell = data.first; + std::vector<std::string> records; + + str << Key::key_name(container_key) << "[" << seq_no << "]:"; + line = format("+----- %-30s Container: Segment:%04X Mask:%04X Item:%08X Cell:%016X Hist: Hits:%ld Parts:%ld", + str.str().c_str(), container_key.segment(), container_key.mask(), container_key.item(), + cell, history.hits.size(), history.particles.size()); + records.emplace_back(line); + for( std::size_t i=0; i<history.hits.size(); ++i ) { + const auto& entry = history.hits[i]; + const EnergyDeposit& dep = entry.get_deposit(ev, container_key.item()); + const Position& pos = dep.position; + const Position& mom = dep.momentum; + Key k = entry.source; + str.str(""); + str << "| Hit-history[" << i << "]:"; + line = format("%-30s Segment:%04X Mask:%04X Cell:%08X %.8g", + str.str().c_str(), k.segment(), k.mask(), k.item(), entry.weight); + records.emplace_back(line); + line = format("| pos: %7.3f %7.3f %7.3f p: %7.3f %7.3f %7.3f deposit: %7.3f", + pos.X(), pos.Y(), pos.Z(), mom.X(), mom.Y(), mom.Z(), dep.deposit); + records.emplace_back(line); + } + for( std::size_t i=0; i<history.particles.size(); ++i ) { + const auto& ent = history.particles[i]; + const Particle& par = ent.get_particle(ev); + const Direction& mom = par.momentum; + const Position& vtx = par.start_position; + Key key = ent.source; + str.str(""); + str << "| Part-history[" << i << "]:"; + line = format("%-30s Segment:%04X Mask:%04X Key: %08X %.8g", + str.str().c_str(), key.segment(), key.mask(), key.item(), ent.weight); + records.emplace_back(line); + line = format("| PDG:%6d Charge:%-2d Mass:%7.3f v:%7.3f %7.3f %7.3f p:%7.3f %7.3f %7.3f", + par.pdgID, int(par.charge), par.mass, vtx.X(), vtx.Y(), vtx.Z(), mom.X(), mom.Y(), mom.Z()); + records.emplace_back(line); + } + return records; +} template <typename T> std::vector<std::string> DigiStoreDump::dump_history(DigiContext& context, Key container_key, const T& container) const { std::size_t count = 0; std::vector<std::string> records; for( const auto& item : container ) { - auto rec = ump_history(context, container_key, item, count++); + auto rec = dump_history(context, container_key, item, count++); records.insert(records.end(), rec.begin(), rec.end()); } return records; @@ -169,10 +221,12 @@ DigiStoreDump::dump_deposit_history(DigiContext& context, Key container_key, con std::vector<std::string> records; auto line = format("|---- %s", data_header(container_key, "deposits", container).c_str()); records.emplace_back(line); +#ifdef DDDIGI_INPLACE_HISTORY for( const auto& item : container ) { auto rec = dump_history(context, container_key, item, count++); records.insert(records.end(), rec.begin(), rec.end()); } +#endif return records; } @@ -182,10 +236,12 @@ DigiStoreDump::dump_deposit_history(DigiContext& context, Key container_key, con std::vector<std::string> records; auto line = format("|---- %s", data_header(container_key, "deposits", container).c_str()); records.emplace_back(line); +#ifdef DDDIGI_INPLACE_HISTORY for( const auto& item : container ) { auto rec = dump_history(context, container_key, item, count++); records.insert(records.end(), rec.begin(), rec.end()); } +#endif return records; } diff --git a/DDDigi/src/DigiSynchronize.cpp b/DDDigi/src/DigiSynchronize.cpp index e29262286ab0b3e11f7bbdbfcdad84ba7dff12d6..4729c818e0c139c9c7c7ab6451f67d549a3250fe 100644 --- a/DDDigi/src/DigiSynchronize.cpp +++ b/DDDigi/src/DigiSynchronize.cpp @@ -25,7 +25,7 @@ using namespace dd4hep::digi; template <> void -DigiParallelWorker<DigiEventAction, DigiContext, int>::execute(void* data) const { +DigiParallelWorker<DigiEventAction, DigiSynchronize::work_t, std::size_t, DigiSynchronize&>::execute(void* data) const { calldata_t* args = reinterpret_cast<calldata_t*>(data); action->execute(*args); } @@ -58,7 +58,7 @@ void DigiSynchronize::execute(DigiContext& context) const { /// Add an actor responding to all callbacks. Sequence takes ownership. void DigiSynchronize::adopt(DigiEventAction* action) { if (action) { - m_actors.insert(new Worker(action, 0)); + m_actors.insert(new worker_t(action, m_actors.size(), *this)); return; } except("DigiSynchronize","++ Attempt to add invalid actor!"); diff --git a/DDG4/include/DDG4/Geant4Kernel.h b/DDG4/include/DDG4/Geant4Kernel.h index 2736fd970c34c5413f113e79fa88e30634ab0389..7032959b33b45a4b889cdf3634ac3a73fd13b0a3 100644 --- a/DDG4/include/DDG4/Geant4Kernel.h +++ b/DDG4/include/DDG4/Geant4Kernel.h @@ -19,6 +19,7 @@ // C/C++ include files #include <map> #include <typeinfo> +#include <functional> class DD4hep_End_Of_File : public std::exception { public: @@ -56,6 +57,7 @@ namespace dd4hep { typedef std::map<std::string, Geant4Action*> GlobalActions; typedef std::map<std::string,int> ClientOutputLevels; typedef std::pair<void*, const std::type_info*> UserFramework; + using UserCallbacks = std::vector<std::function<void()> >; protected: /// Reference to the run manager @@ -100,6 +102,15 @@ namespace dd4hep { //bool m_multiThreaded; /// Master property: Number of execution threads in multi threaded mode. int m_numThreads; + + /// Registered action callbacks on configure + UserCallbacks m_actionConfigure; + /// Registered action callbacks on initialize + UserCallbacks m_actionInitialize; + /// Registered action callbacks on terminate + UserCallbacks m_actionTerminate; + + /// Flag: Master instance (id<0) or worker (id >= 0) unsigned long m_id, m_ident; /// Access to geometry world @@ -223,6 +234,13 @@ namespace dd4hep { /// Retrieve the global output level of a named object. PrintLevel getOutputLevel(const std::string object) const; + /// Register configure callback. Signature: (function)() + void register_configure(const std::function<void()>& callback); + /// Register initialize callback. Signature: (function)() + void register_initialize(const std::function<void()>& callback); + /// Register terminate callback. Signature: (function)() + void register_terminate(const std::function<void()>& callback); + /// Register action by name to be retrieved when setting up and connecting action objects /** Note: registered actions MUST be unique. * However, not all actions need to registered.... diff --git a/DDG4/include/DDG4/Geant4UIManager.h b/DDG4/include/DDG4/Geant4UIManager.h index 50d2bda572574f15a7536fb599c3c594847a4f22..b696a7cdea88660739b6067ce8091b6da964200f 100644 --- a/DDG4/include/DDG4/Geant4UIManager.h +++ b/DDG4/include/DDG4/Geant4UIManager.h @@ -58,8 +58,14 @@ namespace dd4hep { std::string m_uiSetup; /// Property: Name of the visualization macro file std::string m_visSetup; - /// Property: Array of macro files to be chained - std::vector<std::string> m_commands; + /// Property: Array of macro files to be chained and executed when the Geant4Kernel gets configured + std::vector<std::string> m_configureCommands; + /// Property: Array of macro files to be chained and executed when the Geant4Kernel gets initialized + std::vector<std::string> m_initializeCommands; + /// Property: Array of macro files to be chained and executed when the Geant4Kernel gets terminated + std::vector<std::string> m_terminateCommands; + /// Property: Array of macro files to be chained and executed BEFORE running + std::vector<std::string> m_preRunCommands; /// Property: Array of macro files to be chained and executed AFTER running std::vector<std::string> m_postRunCommands; /// Property: Array of commands to be chained @@ -74,11 +80,20 @@ namespace dd4hep { G4VisManager* m_vis; /// Reference to Geant4 UI manager G4UIExecutive* m_ui; + public: /// Initializing constructor Geant4UIManager(Geant4Context* context, const std::string& name); /// Default destructor virtual ~Geant4UIManager(); + + /// Configure the object. Callback registered to the Geant4Kernel. + void configure(); + /// Initialize the object. Callback registered to the Geant4Kernel. + void initialize(); + /// Callback on terminate. Callback registered to the Geant4Kernel. + void terminate(); + /// Install command control messenger to write GDML file from command prompt. void installCommandMessenger(); /// Start visualization @@ -93,7 +108,9 @@ namespace dd4hep { void forceExit(); /// Regularly exiting this process without calling atexit handlers void regularExit(); - /// Run UI + /// Apply single command + void applyCommand(const std::string& command); + /// Run UI virtual void operator()(void* param); }; diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index 7d000ba214537578fd594a870143a325777b0568..bfc40a5096af297f259868e319ad42a280029236 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -131,14 +131,27 @@ def _registerGlobalFilter(self, filter): self.get().registerGlobalFilter(Interface.toAction(filter)) +def _evalProperty(data): + """ + Function necessary to extract real strings from the property value. + Strings may be emraced by quotes: '<value>' + """ + try: + if isinstance(data,str): + return eval(data) + except: + pass + return data + + def _getKernelProperty(self, name): ret = Interface.getPropertyKernel(self.get(), name) if ret.status > 0: - return ret.data + return _evalProperty(ret.data) elif hasattr(self.get(), name): - return getattr(self.get(), name) + return _evalProperty(getattr(self.get(), name)) elif hasattr(self, name): - return getattr(self, name) + return _evalProperty(getattr(self, name)) msg = 'Geant4Kernel::GetProperty [Unhandled]: Cannot access Kernel.' + name raise KeyError(msg) @@ -447,6 +460,15 @@ class Geant4: """ return self.setupUI(typ='csh', vis=vis, ui=ui, macro=macro) + def ui(self): + """ + Access UI manager action from the kernel object + + \author M.Frank + """ + ui_name = getattr(self.master(),'UI') + return self.master().globalAction(ui_name) + def addUserInitialization(self, worker, worker_args=None, master=None, master_args=None): """ Configure Geant4 user initialization for optionasl multi-threading mode diff --git a/DDG4/python/DDG4Dict.C b/DDG4/python/DDG4Dict.C index ec18b78c4f97f4d454afde772fa247c9b2b6d7ae..cd9925d657fd878a4b81fd05bc499b031562ba34 100644 --- a/DDG4/python/DDG4Dict.C +++ b/DDG4/python/DDG4Dict.C @@ -17,13 +17,13 @@ //==================================================================== // Framework include files -#include "DDG4/DDG4Dict.h" -#include "DDG4/Geant4Config.h" -#include "DDG4/Geant4Primary.h" -#include "DDG4/Geant4Random.h" -#include "DDG4/Geant4DataDump.h" -#include "DDG4/Geant4InputAction.h" -#include "DDG4/Geant4GeneratorWrapper.h" +#include <DDG4/DDG4Dict.h> +#include <DDG4/Geant4Config.h> +#include <DDG4/Geant4Primary.h> +#include <DDG4/Geant4Random.h> +#include <DDG4/Geant4DataDump.h> +#include <DDG4/Geant4InputAction.h> +#include <DDG4/Geant4GeneratorWrapper.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -205,7 +205,8 @@ namespace dd4hep { typedef dd4hep::sim::Geant4ActionCreation Geant4ActionCreation; -#include "DD4hep/detail/DetectorInterna.h" +#include <DD4hep/detail/DetectorInterna.h> +#include <DDG4/Geant4UIManager.h> // CINT configuration #if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) @@ -325,6 +326,7 @@ typedef dd4hep::sim::Geant4ActionCreation Geant4ActionCreation; #pragma link C++ class dd4hep::sim::Geant4DataDump; #pragma link C++ class dd4hep::sim::Geant4Random; #pragma link C++ class dd4hep::sim::Geant4ParticleHandler; +#pragma link C++ class dd4hep::sim::Geant4UIManager; #pragma link C++ class dd4hep::sim::Geant4UserParticleHandler; @@ -335,7 +337,7 @@ typedef dd4hep::sim::Geant4ActionCreation Geant4ActionCreation; #endif // CLHEP stuff -#include "CLHEP/Random/Random.h" +#include <CLHEP/Random/Random.h> #if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) #pragma link C++ namespace CLHEP; diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index 949d6aa0860fd1869a49da4dd8584fdea3821275..1a7ac3b34f33cfce61a7710ddb9ccf5a49714293 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -419,9 +419,9 @@ namespace dd4hep { /// Construct electro magnetic field entity from the dd4hep field G4VPhysicalVolume* Geant4UserDetectorConstruction::Construct() { - // The G4TransportationManager is thread-local. - // Thus, regardless of whether the field class object is global or local - // to a certain volume, a field object must be assigned to G4FieldManager. + /// The G4TransportationManager is thread-local. + /// Thus, regardless of whether the field class object is global or local + /// to a certain volume, a field object must be assigned to G4FieldManager. G4AutoLock protection_lock(&action_mutex); updateContext(m_sequence->context()); m_sequence->constructGeo(&m_ctxt); @@ -447,33 +447,33 @@ namespace dd4hep { m_sequence->build(); m_sequence->updateContext(old); } - // Set user generator action sequence. Not optional, since event context is defined inside + /// Set user generator action sequence. Not optional, since event context is defined inside Geant4UserGeneratorAction* gen_action = new Geant4UserGeneratorAction(ctx,krnl.generatorAction(false)); SetUserAction(gen_action); - // Set the run action sequence. Not optional, since run context is defined/destroyed inside + /// Set the run action sequence. Not optional, since run context is defined/destroyed inside Geant4UserRunAction* run_action = new Geant4UserRunAction(ctx,krnl.runAction(false)); SetUserAction(run_action); - // Set the event action sequence. Not optional, since event context is destroyed inside + /// Set the event action sequence. Not optional, since event context is destroyed inside Geant4UserEventAction* evt_action = new Geant4UserEventAction(ctx,krnl.eventAction(false)); run_action->eventAction = evt_action; evt_action->runAction = run_action; SetUserAction(evt_action); - // Set the tracking action sequence + /// Set the tracking action sequence Geant4TrackingActionSequence* trk_action = krnl.trackingAction(false); if ( trk_action ) { Geant4UserTrackingAction* action = new Geant4UserTrackingAction(ctx, trk_action); SetUserAction(action); } - // Set the stepping action sequence + /// Set the stepping action sequence Geant4SteppingActionSequence* stp_action = krnl.steppingAction(false); if ( stp_action ) { Geant4UserSteppingAction* action = new Geant4UserSteppingAction(ctx, stp_action); SetUserAction(action); } - // Set the stacking action sequence + /// Set the stacking action sequence Geant4StackingActionSequence* stk_action = krnl.stackingAction(false); if ( stk_action ) { Geant4UserStackingAction* action = new Geant4UserStackingAction(ctx, stk_action); @@ -530,14 +530,14 @@ Geant4DetectorConstructionSequence* Geant4Compatibility::buildDefaultDetectorCon Geant4DetectorConstructionSequence* seq = kernel.detectorConstruction(true); printout(WARNING, "Geant4Exec", "+++ Building default Geant4DetectorConstruction for single threaded compatibility."); - // Attach first the geometry converter from dd4hep to Geant4 + /// Attach first the geometry converter from dd4hep to Geant4 cr = PluginService::Create<Geant4Action*>("Geant4DetectorGeometryConstruction",ctx,string("ConstructGeometry")); det_cr = dynamic_cast<Geant4DetectorConstruction*>(cr); if ( det_cr ) seq->adopt(det_cr); else throw runtime_error("Panic! Failed to build Geant4DetectorGeometryConstruction."); - // Attach the sensitive detector manipulator: + /// Attach the sensitive detector manipulator: cr = PluginService::Create<Geant4Action*>("Geant4DetectorSensitivesConstruction",ctx,string("ConstructSensitives")); det_cr = dynamic_cast<Geant4DetectorConstruction*>(cr); if ( det_cr ) @@ -561,17 +561,17 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { Geant4Random::setMainInstance(rndm); kernel.executePhase("configure",0); - // Construct the default run manager + /// Construct the default run manager G4RunManager& runManager = kernel.runManager(); - // Check if the geometry was loaded + /// Check if the geometry was loaded if (description.sensitiveDetectors().size() <= 1) { printout(WARNING, "Geant4Exec", "+++ Only %d subdetectors present. " "You sure you loaded the geometry properly?", int(description.sensitiveDetectors().size())); } - // Get the detector constructed + /// Get the detector constructed Geant4DetectorConstructionSequence* user_det = kernel.detectorConstruction(false); if ( 0 == user_det && kernel.isMultiThreaded() ) { throw runtime_error("Panic! No valid detector construction sequencer present. [Mandatory MT]"); @@ -582,7 +582,7 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { Geant4UserDetectorConstruction* det_seq = new Geant4UserDetectorConstruction(ctx,user_det); runManager.SetUserInitialization(det_seq); - // Get the physics list constructed + /// Get the physics list constructed Geant4PhysicsListActionSequence* phys_seq = kernel.physicsList(false); if ( 0 == phys_seq ) { string phys_model = "QGSP_BERT"; @@ -603,13 +603,13 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { phys_seq->enable(physics); runManager.SetUserInitialization(physics); - // Construct the remaining user initialization in multi-threaded mode + /// Construct the remaining user initialization in multi-threaded mode Geant4UserInitializationSequence* user_init = kernel.userInitialization(false); if ( 0 == user_init && kernel.isMultiThreaded() ) { throw runtime_error("Panic! No valid user initialization sequencer present. [Mandatory MT]"); } else if ( 0 == user_init && !kernel.isMultiThreaded() ) { - // Use default actions registered to the default kernel. Will do the right thing... + /// Use default actions registered to the default kernel. Will do the right thing... user_init = kernel.userInitialization(true); } Geant4UserActionInitialization* init = new Geant4UserActionInitialization(ctx,user_init); @@ -619,11 +619,11 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { /// Initialize the simulation int Geant4Exec::initialize(Geant4Kernel& kernel) { - // Construct the default run manager + /// Construct the default run manager G4RunManager& runManager = kernel.runManager(); - // - // Initialize G4 engine - // + /// + /// Initialize G4 engine + /// kernel.executePhase("initialize",0); runManager.Initialize(); return 1; @@ -640,7 +640,7 @@ int Geant4Exec::run(Geant4Kernel& kernel) { if ( ui ) { Geant4Call* c = dynamic_cast<Geant4Call*>(ui); if ( c ) { - (*c)(0); + (*c)(nullptr); kernel.executePhase("stop",0); return 1; } diff --git a/DDG4/src/Geant4Kernel.cpp b/DDG4/src/Geant4Kernel.cpp index f3bcc53909ad04413eca9640d57478f38313db02..bc42fb39fb4dca32ca0ff783022f038901963a61 100644 --- a/DDG4/src/Geant4Kernel.cpp +++ b/DDG4/src/Geant4Kernel.cpp @@ -307,14 +307,44 @@ void Geant4Kernel::loadXML(const char* fname) { m_detDesc->apply("DD4hep_XMLLoader", 1, (char**) args); } +/// Register configure callback +void Geant4Kernel::register_configure(const std::function<void()>& callback) { + m_actionConfigure.push_back(callback); +} + +/// Register initialize callback +void Geant4Kernel::register_initialize(const std::function<void()>& callback) { + m_actionInitialize.push_back(callback); +} + +/// Register terminate callback +void Geant4Kernel::register_terminate(const std::function<void()>& callback) { + m_actionTerminate.push_back(callback); +} + +/// Configure Geant4 kernel object int Geant4Kernel::configure() { - return Geant4Exec::configure(*this); + int status = Geant4Exec::configure(*this); + if ( status ) { + for(auto& call : m_actionConfigure) call(); + return status; + } + except("Geant4Kernel","++ FAILED to configure DDG4 executive"); + return status; } +/// Initialize Geant4 kernel object int Geant4Kernel::initialize() { - return Geant4Exec::initialize(*this); + int status = Geant4Exec::initialize(*this); + if ( status ) { + for(auto& call : m_actionInitialize) call(); + return status; + } + except("Geant4Kernel","++ FAILED to initialize DDG4 executive"); + return status; } +/// Run Geant4 int Geant4Kernel::run() { try { auto result = Geant4Exec::run(*this); @@ -340,7 +370,10 @@ int Geant4Kernel::terminate() { const Geant4Kernel* ptr = s_main_instance.get(); printout(INFO,"Geant4Kernel","++ Terminate Geant4 and delete associated actions."); if ( ptr == this ) { + auto calls = std::move(m_actionTerminate); + for(auto& call : calls) call(); Geant4Exec::terminate(*this); + m_actionTerminate = std::move(calls); } destroyPhases(); detail::releaseObjects(m_globalFilters); diff --git a/DDG4/src/Geant4UIManager.cpp b/DDG4/src/Geant4UIManager.cpp index 307c561c8e1974c13e4a8c1ae53e26faaaadf96d..c02e8dd71afe9e2e9e8d227d602f5df03644dd3c 100644 --- a/DDG4/src/Geant4UIManager.cpp +++ b/DDG4/src/Geant4UIManager.cpp @@ -11,23 +11,24 @@ // //========================================================================== -// Framework include files -#include "DDG4/Geant4UIManager.h" -#include "DDG4/Geant4Kernel.h" -#include "DDG4/Geant4UIMessenger.h" -#include "DD4hep/Primitives.h" -#include "DD4hep/Printout.h" - -// Geant4 include files -#include "G4Version.hh" -#include "G4VisExecutive.hh" -#include "G4UImanager.hh" -#include "G4UIsession.hh" -#include "G4VisExecutive.hh" -#include "G4UIExecutive.hh" -#include "G4RunManager.hh" - +/// Framework include files +#include <DDG4/Geant4UIManager.h> +#include <DDG4/Geant4Kernel.h> +#include <DDG4/Geant4UIMessenger.h> +#include <DD4hep/Primitives.h> + +/// Geant4 include files +#include <G4Version.hh> +#include <G4VisExecutive.hh> +#include <G4UImanager.hh> +#include <G4UIsession.hh> +#include <G4VisExecutive.hh> +#include <G4UIExecutive.hh> +#include <G4RunManager.hh> + +/// C/C++ include files #include <cstdlib> +#include <functional> using namespace dd4hep::sim; using namespace std; @@ -39,18 +40,25 @@ namespace { } /// Initializing constructor -Geant4UIManager::Geant4UIManager(Geant4Context* ctxt, const std::string& nam) +Geant4UIManager::Geant4UIManager(Geant4Context* ctxt, const string& nam) : Geant4Action(ctxt,nam), m_vis(0), m_ui(0) { - declareProperty("SetupUI", m_uiSetup=""); - declareProperty("SetupVIS", m_visSetup=""); - declareProperty("SessionType", m_sessionType="tcsh"); - declareProperty("Macros", m_macros); - declareProperty("Commands", m_commands); - declareProperty("PostRunCommands",m_postRunCommands); - declareProperty("HaveVIS", m_haveVis=false); - declareProperty("HaveUI", m_haveUI=true); - declareProperty("Prompt", m_prompt); + declareProperty("SetupUI", m_uiSetup=""); + declareProperty("SetupVIS", m_visSetup=""); + declareProperty("SessionType", m_sessionType="tcsh"); + declareProperty("Macros", m_macros); + declareProperty("ConfigureCommands", m_configureCommands); + declareProperty("InitializeCommands", m_initializeCommands); + declareProperty("TerminateCommands", m_terminateCommands); + declareProperty("Commands", m_preRunCommands); + declareProperty("PreRunCommands", m_preRunCommands); + declareProperty("PostRunCommands", m_postRunCommands); + declareProperty("HaveVIS", m_haveVis=false); + declareProperty("HaveUI", m_haveUI=true); + declareProperty("Prompt", m_prompt); + context()->kernel().register_configure(bind(&Geant4UIManager::configure,this)); + context()->kernel().register_initialize(bind(&Geant4UIManager::initialize,this)); + context()->kernel().register_terminate(bind(&Geant4UIManager::terminate,this)); enableUI(); } @@ -58,6 +66,55 @@ Geant4UIManager::Geant4UIManager(Geant4Context* ctxt, const std::string& nam) Geant4UIManager::~Geant4UIManager() { } +/// Configure the object +void Geant4UIManager::configure() { + /// Get the pointer to the User Interface manager + G4UImanager* mgr = G4UImanager::GetUIpointer(); + /// Start UI instance + if ( m_haveUI ) { + m_ui = startUI(); + } + /// Execute the chained command statements + for(const auto& c : m_configureCommands) { + info("++ Executing configure command:%s",c.c_str()); + mgr->ApplyCommand(c.c_str()); + } +} + +/// Initialize the object +void Geant4UIManager::initialize() { + /// Get the pointer to the User Interface manager + G4UImanager* mgr = G4UImanager::GetUIpointer(); + /// Execute the chained command statements + for(const auto& c : m_initializeCommands) { + info("++ Executing initialization command:%s",c.c_str()); + mgr->ApplyCommand(c.c_str()); + } +} + +/// Callback on terminate +void Geant4UIManager::terminate() { + /// Get the pointer to the User Interface manager + G4UImanager* mgr = G4UImanager::GetUIpointer(); + /// Execute the chained command statements + for(const auto& c : m_terminateCommands) { + info("++ Executing finalization command:%s",c.c_str()); + mgr->ApplyCommand(c.c_str()); + } +} + +/// Apply single command +void Geant4UIManager::applyCommand(const string& command) { + /// Get the pointer to the User Interface manager + G4UImanager* mgr = G4UImanager::GetUIpointer(); + if ( mgr ) { + info("++ Executing G4 command: %s",command.c_str()); + mgr->ApplyCommand(command.c_str()); + return; + } + except("No UI reference present. Too early to interact with Geant4!"); +} + /// Install command control messenger to write GDML file from command prompt. void Geant4UIManager::installCommandMessenger() { m_control->addCall("exit", "Force exiting this process", @@ -73,15 +130,15 @@ void Geant4UIManager::forceExit() { /// Regularly exiting this process without calling atexit handlers void Geant4UIManager::regularExit() { - printout(INFO,"Geant4UIManager","++ End of processing requested."); - this->context()->kernel().terminate(); - this->forceExit(); + info("++ End of processing requested."); + context()->kernel().terminate(); + forceExit(); } /// Start visualization G4VisManager* Geant4UIManager::startVis() { - // Initialize visualization - printout(INFO,"Geant4UIManager","+++ Starting G4VisExecutive ...."); + /// Initialize visualization + info("+++ Starting G4VisExecutive ...."); G4VisManager* vis = new G4VisExecutive(); vis->Initialize(); return vis; @@ -91,9 +148,7 @@ G4VisManager* Geant4UIManager::startVis() { G4UIExecutive* Geant4UIManager::startUI() { G4UIExecutive* ui = 0; const char* args[] = {"DDG4","",""}; - printout(INFO,"Geant4UIManager","+++ Starting G4UIExecutive '%s' of type %s....", - args[0], m_sessionType.c_str()); - + info("+++ Starting G4UIExecutive '%s' of type %s....", args[0], m_sessionType.c_str()); #if (G4VERSION_NUMBER >= 960) ui = new G4UIExecutive(1,(char**)args,m_sessionType.c_str()); #else @@ -113,70 +168,71 @@ void Geant4UIManager::operator()(void* ) { /// Start manager & session void Geant4UIManager::start() { - // Get the pointer to the User Interface manager + /// Get the pointer to the User Interface manager G4UImanager* mgr = G4UImanager::GetUIpointer(); bool executed_statements = false; - // Start visualization + /// Start visualization if ( m_haveVis || !m_visSetup.empty() ) { m_vis = startVis(); - m_haveVis = true; // If graphics setup, vis is always true - m_haveUI = true; // No graphics without UI! - } - // Start UI instance - if ( m_haveUI ) { - m_ui = startUI(); + m_haveVis = true; /// If graphics setup, vis is always true + m_haveUI = true; /// No graphics without UI! } - // Configure visualization instance + /// Configure visualization instance if ( !m_visSetup.empty() ) { - printout(INFO,"Geant4UIManager","++ Executing visualization setup:%s",m_visSetup.c_str()); + info("++ Executing visualization setup:%s",m_visSetup.c_str()); mgr->ApplyCommand(make_cmd(m_visSetup).c_str()); } - // Configure UI instance + /// Configure UI instance if ( !m_uiSetup.empty() ) { - printout(INFO,"Geant4UIManager","++ Executing UI setup:%s",m_uiSetup.c_str()); + info("++ Executing UI setup:%s",m_uiSetup.c_str()); mgr->ApplyCommand(make_cmd(m_uiSetup).c_str()); executed_statements = true; } - // Execute the chained macro files + /// Execute the chained macro files for(const auto& m : m_macros) { - printout(INFO,"Geant4UIManager","++ Executing Macro file:%s",m.c_str()); + info("++ Executing Macro file:%s",m.c_str()); mgr->ApplyCommand(make_cmd(m.c_str())); executed_statements = true; } - // Execute the chained command statements - for(const auto& c : m_commands) { - printout(INFO,"Geant4UIManager","++ Executing Command statement:%s",c.c_str()); + /// Execute the chained pre-run command statements + for(const auto& c : m_preRunCommands) { + info("++ Executing pre-run statement:%s",c.c_str()); mgr->ApplyCommand(c.c_str()); executed_statements = true; } - // Start UI session if present + /// Start UI session if present if ( m_haveUI && m_ui ) { m_ui->SessionStart(); - // Execute the chained command statements + /// Execute the chained post-run command statements for(const auto& c : m_postRunCommands) { - printout(INFO,"Geant4UIManager","++ Executing Command statement:%s",c.c_str()); + info("++ Executing post-run statement:%s",c.c_str()); mgr->ApplyCommand(c.c_str()); executed_statements = true; } return; } else if ( m_haveUI ) { - printout(WARNING,"Geant4UIManager","++ No UI manager found. Exit."); + warning("++ No UI manager found. Exit."); return; } else if ( executed_statements ) { + /// Execute the chained post-run command statements + for(const auto& c : m_postRunCommands) { + info("++ Executing post-run statement:%s",c.c_str()); + mgr->ApplyCommand(c.c_str()); + } return; } - // No UI. Pure batch mode: Simply execute requested number of events + /// No UI. Pure batch mode: Simply execute requested number of events long numEvent = context()->kernel().property("NumEvents").value<long>(); - if(numEvent < 0) numEvent = std::numeric_limits<int>::max(); - printout(INFO,"Geant4UIManager","++ Start run with %d events.",numEvent); + if(numEvent < 0) numEvent = numeric_limits<int>::max(); + info("++ Start run with %d events.",numEvent); try { context()->kernel().runManager().BeamOn(numEvent); } catch (DD4hep_End_Of_File& e) { - printout(INFO,"Geant4UIManager","++ End of file reached, ending run..."); + info("++ End of file reached, ending run..."); context()->kernel().runManager().RunTermination(); } } diff --git a/examples/DDDigi/scripts/DigiTest.py b/examples/DDDigi/scripts/DigiTest.py index 9b0c5b298bb20ec70488375c434a204adb768244..d356a212c1ca308dad81ce5b23f94431a8cf899b 100644 --- a/examples/DDDigi/scripts/DigiTest.py +++ b/examples/DDDigi/scripts/DigiTest.py @@ -13,6 +13,7 @@ import os import dddigi import logging from dd4hep import units +from dddigi import DEBUG, INFO, WARNING, ERROR logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) @@ -126,7 +127,7 @@ class Test(dddigi.Digitize): # ========================================================================================================== -def test_setup_1(digi): +def test_setup_1(digi, print_level=WARNING, parallel=True): """ Create default setup for tests. Simply too bad to repeat the same lines over and over again. @@ -136,28 +137,29 @@ def test_setup_1(digi): # ======================================================================================================== digi.info('Created SIGNAL input') input = digi.input_action('DigiParallelActionSequence/READER') - input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0xCBAA, input=[digi.next_input()]) + input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0xCBAA, input=[digi.next_input()], OutputLevel=print_level, keep_raw=False) # ======================================================================================================== digi.info('Creating collision overlay....') # ======================================================================================================== overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1') - overlay.adopt_action('DigiDDG4ROOT/Read-1', mask=0xCBEE, input=[digi.next_input()]) + overlay.adopt_action('DigiDDG4ROOT/Read-1', mask=0xCBEE, input=[digi.next_input()], OutputLevel=print_level, keep_raw=False) digi.info('Created input.overlay-1') # ======================================================================================================== event = digi.event_action('DigiSequentialActionSequence/EventAction') combine = event.adopt_action('DigiContainerCombine/Combine', - parallel=False, + OutputLevel=print_level, + parallel=parallel, input_masks=[0xCBAA, 0xCBEE], output_mask=0xAAA0, output_segment='deposits') - combine.erase_combined = False - proc = event.adopt_action('DigiContainerSequenceAction/HitP2', - parallel=False, + combine.erase_combined = True + proc = event.adopt_action('DigiContainerSequenceAction/HitP1', + parallel=parallel, input_mask=0xAAA0, input_segment='deposits', output_mask=0xEEE5, output_segment='deposits') - combine = digi.create_action('DigiDepositWeightedPosition/DepoCombine') + combine = digi.create_action('DigiDepositWeightedPosition/WeightedPosition', OutputLevel=print_level) proc.adopt_container_processor(combine, digi.containers()) conts = [c for c in digi.containers()] event.adopt_action('DigiContainerDrop/Drop', diff --git a/examples/DDDigi/scripts/TestAttenuate.py b/examples/DDDigi/scripts/TestAttenuate.py new file mode 100644 index 0000000000000000000000000000000000000000..5f857e446a7685c4fcbb4b562c85996d1174c9ba --- /dev/null +++ b/examples/DDDigi/scripts/TestAttenuate.py @@ -0,0 +1,49 @@ +# ========================================================================== +# 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 +from g4units import ns + + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + attenuation = digi.attenuation + + input = digi.input_action('DigiParallelActionSequence/READER') + # ======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-25') + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-25ns', mask=0x1, input=[digi.next_input()], keep_raw=False) + attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-25ns', + t0=-25 * ns, + signal_decay='exponential', + processor_type='DigiAttenuator', + input_mask=evtreader.mask, + input_segment='inputs', + 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.spillover-25') + # ======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', + input_masks=[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6], + input_segment='inputs', + output_mask=0xFEED, + output_segment='deposits') + evtdump = event.adopt_action('DigiStoreDump/StoreDump') + digi.check_creation([evtdump]) + 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/TestDepositSmearEnergy.py b/examples/DDDigi/scripts/TestDepositSmearEnergy.py index cb375d6f623028628acef0d920c6954cbbc788fa..52622580d16e22243490b482ee9200c9a052f8a5 100644 --- a/examples/DDDigi/scripts/TestDepositSmearEnergy.py +++ b/examples/DDDigi/scripts/TestDepositSmearEnergy.py @@ -24,8 +24,7 @@ def run(): input_segment='deposits', output_mask=0xFFF0, output_segment='outputs') - smear = digi.create_action('DigiDepositSmearing/Smear') - smear.deposit_cutoff = 1e-55 + smear = digi.create_action('DigiDepositSmearEnergy/Smear') # sigma(E)[GeV]/E[GeV] = 0.02 (systematic) + 0.005 / sqrt(E[GeV]) (intrinsic) + 1keV/E[GeV] (instrumentation) # sigma(E)[GeV] = 0.02*E[GeV] (systematic) + 0.005 * sqrt(E[GeV]) (intrinsic) + 1keV (instrumentation) smear.intrinsic_fluctuation = 0.005 / math.sqrt(units.GeV) @@ -33,7 +32,6 @@ def run(): smear.instrumentation_resolution = 1 * units.keV smear.pair_ionisation_energy = 10 * units.eV smear.ionization_fluctuation = True - smear.update_in_place = False # proc.adopt_container_processor(smear, conts) proc.adopt_container_processor(smear, ['EcalBarrelHits', 'EcalEndcapHits', 'HcalBarrelHits']) diff --git a/examples/DDDigi/scripts/TestDepositSmearTime.py b/examples/DDDigi/scripts/TestDepositSmearTime.py index 48b68cc5c8347acb1b98d461406839755dc05b0e..81b98bd7b46a13864647ff95c4948b7463b1e30e 100644 --- a/examples/DDDigi/scripts/TestDepositSmearTime.py +++ b/examples/DDDigi/scripts/TestDepositSmearTime.py @@ -15,6 +15,7 @@ def run(): import DigiTest from dd4hep import units digi = DigiTest.Test(geometry=None) + digi.kernel().OutputLevel = DigiTest.INFO digi.load_geo(volume_manager=True) event = DigiTest.test_setup_1(digi) @@ -26,8 +27,7 @@ def run(): smear = digi.create_action('DigiDepositSmearTime/Smear', resolution_time=1e-6 * units.second) proc.adopt_container_processor(smear, ['SiVertexEndcapHits', 'SiVertexBarrelHits']) - - event.adopt_action('DigiStoreDump/HeaderDump') + event.adopt_action('DigiStoreDump/HeaderDump', OutputLevel=DigiTest.INFO) # ======================================================================================================== digi.info('Starting digitization core') digi.run_checked(num_events=3, num_threads=10, parallel=5) diff --git a/examples/DDDigi/scripts/TestDepositWeighted.py b/examples/DDDigi/scripts/TestDepositWeighted.py index 067eab2140dffcc6dca9799f9ea000899a988971..75e31f1f8ac39883cf61da845b4915fd43c4b8e0 100644 --- a/examples/DDDigi/scripts/TestDepositWeighted.py +++ b/examples/DDDigi/scripts/TestDepositWeighted.py @@ -15,21 +15,22 @@ def run(): import DigiTest digi = DigiTest.Test(geometry=None) + rdr_output = DigiTest.DEBUG input = digi.input_action('DigiParallelActionSequence/READER') # ======================================================================================================== digi.info('Created SIGNAL input') - signal = input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0x0, input=[digi.next_input()]) + signal = input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0x0, input=[digi.next_input()], OutputLevel=rdr_output) digi.check_creation([signal]) # ======================================================================================================== digi.info('Creating collision overlays....') # ======================================================================================================== overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1') - evtreader = overlay.adopt_action('DigiDDG4ROOT/Read-1', mask=0x1, input=[digi.next_input()]) + evtreader = overlay.adopt_action('DigiDDG4ROOT/Read-1', mask=0x1, input=[digi.next_input()], OutputLevel=rdr_output) digi.check_creation([overlay, evtreader]) digi.info('Created input.overlay-1') # ======================================================================================================== overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-2') - evtreader = overlay.adopt_action('DigiDDG4ROOT/Read-2', mask=0x2, input=[digi.next_input()]) + evtreader = overlay.adopt_action('DigiDDG4ROOT/Read-2', mask=0x2, input=[digi.next_input()], OutputLevel=rdr_output) digi.check_creation([overlay, evtreader]) digi.info('Created input.overlay-2') # ======================================================================================================== diff --git a/examples/DDDigi/scripts/TestPositionSmearTrack.py b/examples/DDDigi/scripts/TestPositionSmearTrack.py index 4b5a0b3d33f57acb615cd33b3fb9a81d12e8d1d7..17c5b01857b8c5417ba156e7f73bb1c90039f26f 100644 --- a/examples/DDDigi/scripts/TestPositionSmearTrack.py +++ b/examples/DDDigi/scripts/TestPositionSmearTrack.py @@ -17,14 +17,13 @@ def run(): digi = DigiTest.Test(geometry=None) digi.load_geo(volume_manager=True) - event = DigiTest.test_setup_1(digi) + event = DigiTest.test_setup_1(digi, print_level=DigiTest.INFO, parallel=False) # ======================================================================================================== proc = event.adopt_action('DigiContainerSequenceAction/Smearing', parallel=False, input_mask=0xEEE5, input_segment='deposits') smear = digi.create_action('DigiDepositSmearPositionTrack/Smear', - deposit_cutoff=1e-55 * units.MeV, resolution_u=1e-2 * units.mm, resolution_v=1e-2 * units.mm) proc.adopt_container_processor(smear, ['SiVertexEndcapHits', 'SiVertexBarrelHits', diff --git a/examples/DDDigi/scripts/TestProperties.py b/examples/DDDigi/scripts/TestProperties.py index b0d2cce05f4d29c8fa7d81bc820c7d765af82469..caf1a67cc2eb0f8799df0eca646258ceb1b6ff95 100644 --- a/examples/DDDigi/scripts/TestProperties.py +++ b/examples/DDDigi/scripts/TestProperties.py @@ -20,74 +20,122 @@ def yes_no(val): def run(): import DigiTest digi = DigiTest.Test(geometry=None) + info = digi.info + num_tests = 0 + histo = digi.create_action('DigiDepositEnergyMonitor/TestHisto') + histo.histo1D_deposits = ("Energy", u"Some main deposit Title", 101, -0.5, 100.5) + num_tests = num_tests + 1 + histo.histo1D_delta = ("Delta", u"Some delta Title", 50, -5, 5) + num_tests = num_tests + 1 + histo.printProperties() + info('property: histo1D_deposits = %s [%s]' % + (str(histo.histo1D_deposits), str(histo.histo1D_deposits.__class__),)) + num_tests = num_tests + 1 + input = digi.input_action('DigiParallelActionSequence/Test') input.add_property('property_int', 1) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_int')),)) - print('property: property_int = %s' % (str(input.property_int),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_int')), str(input.property_int.__class__),)) + info('property: property_int = %s' % (str(input.property_int),)) input.property_int = 123456 - print('property: property_int = %s' % (str(input.property_int),)) + info('property: property_int = %s' % (str(input.property_int),)) + if input.hasProperty('property_int'): + num_tests = num_tests + 1 input.add_vector_property('property_vector_int', [1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_vector_int')),)) - print('property: property_vector_int = %s' % (str(input.property_vector_int),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_vector_int')), str(input.property_vector_int.__class__), )) + info('property: property_vector_int = %s' % (str(input.property_vector_int),)) input.property_vector_int = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_vector_int = %s' % (str(input.property_vector_int),)) + info('property: property_vector_int = %s' % (str(input.property_vector_int),)) + if input.hasProperty('property_vector_int'): + num_tests = num_tests + 1 input.add_list_property('property_list_int', [1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_list_int')),)) - print('property: property_list_int = %s' % (str(input.property_list_int),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_list_int')), str(input.property_list_int.__class__),)) + info('property: property_list_int = %s' % (str(input.property_list_int),)) input.property_list_int = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_list_int = %s' % (str(input.property_list_int),)) + info('property: property_list_int = %s' % (str(input.property_list_int),)) + if input.hasProperty('property_list_int'): + num_tests = num_tests + 1 input.add_set_property('property_set_int', [1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_set_int')),)) - print('property: property_set_int = %s' % (str(input.property_set_int),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_set_int')), str(input.property_set_int.__class__),)) + info('property: property_set_int = %s' % (str(input.property_set_int),)) input.property_set_int = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_set_int = %s' % (str(input.property_set_int),)) + info('property: property_set_int = %s' % (str(input.property_set_int),)) + if input.hasProperty('property_set_int'): + num_tests = num_tests + 1 input.add_property('property_double', 1.0) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_double')),)) - print('property: property_double = %s' % (str(input.property_double),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_double')), str(input.property_double.__class__),)) + info('property: property_double = %s' % (str(input.property_double),)) input.property_double = 123456.7 - print('property: property_double = %s' % (str(input.property_double),)) + info('property: property_double = %s' % (str(input.property_double),)) + if input.hasProperty('property_double'): + num_tests = num_tests + 1 input.add_vector_property('property_vector_double', [1.1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_vector_double')),)) - print('property: property_vector_double = %s' % (str(input.property_vector_double),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_vector_double')), str(input.property_vector_double.__class__),)) + info('property: property_vector_double = %s' % (str(input.property_vector_double),)) input.property_vector_double = [1.5, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_vector_double = %s' % (str(input.property_vector_double),)) + info('property: property_vector_double = %s' % (str(input.property_vector_double),)) + if input.hasProperty('property_vector_double'): + num_tests = num_tests + 1 input.add_list_property('property_list_double', [1.1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_list_double')),)) - print('property: property_list_double = %s' % (str(input.property_list_double),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_list_double')), str(input.property_list_double.__class__), )) + info('property: property_list_double = %s' % (str(input.property_list_double),)) input.property_list_double = [1.5, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_list_double = %s' % (str(input.property_list_double),)) + info('property: property_list_double = %s' % (str(input.property_list_double),)) + if input.hasProperty('property_list_double'): + num_tests = num_tests + 1 input.add_set_property('property_set_double', [1.1, 2, 3]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_set_double')),)) - print('property: property_set_double = %s' % (str(input.property_set_double),)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_set_double')), str(input.property_set_double.__class__),)) + info('property: property_set_double = %s' % (str(input.property_set_double),)) input.property_set_double = [1.5, 2, 3, 4, 5, 6, 7, 8, 9, 0] - print('property: property_set_double = %s' % (str(input.property_set_double),)) + info('property: property_set_double = %s' % (str(input.property_set_double),)) + if input.hasProperty('property_set_double'): + num_tests = num_tests + 1 input.add_property('property_string', "string_1") - print('property: has_property = %s' % (yes_no(input.hasProperty('property_string')),)) - print('property: property_string = %s' % (input.property_string,)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_string')), str(input.property_string.__class__),)) + info('property: property_string = %s' % (input.property_string,)) input.property_string = "string_1123456" - print('property: property_string = %s' % (input.property_string,)) + info('property: property_string = %s' % (input.property_string,)) + if input.hasProperty('property_string'): + num_tests = num_tests + 1 input.add_vector_property('property_vector_string', ["string1", "string2", "string3"]) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_vector_string')),)) - print('property: property_vector_string = %s' % (input.property_vector_string,)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_vector_string')), str(input.property_vector_string.__class__),)) + info('property: property_vector_string = %s' % (input.property_vector_string,)) input.property_vector_string = ["string1", "string2", "string3", "string4", "string5", "string6"] - print('property: property_vector_string = %s' % (input.property_vector_string,)) + info('property: property_vector_string = %s' % (input.property_vector_string,)) + if input.hasProperty('property_vector_string'): + num_tests = num_tests + 1 input.add_position_property('property_position', (1., 2., 3.)) - print('property: has_property = %s' % (yes_no(input.hasProperty('property_position')),)) - print('property: property_position = %s' % (input.property_position,)) + info('property: has_property = %s [%s]' % + (yes_no(input.hasProperty('property_position')), str(input.property_position.__class__),)) + info('property: property_position = %s' % (input.property_position,)) input.property_position = (111.1, 222.2, 333.3) - print('property: property_position = %s' % (input.property_position,)) + info('property: property_position = %s' % (input.property_position,)) + if input.hasProperty('property_position'): + num_tests = num_tests + 1 + info('We checked %d properties interactions.' % (num_tests,)) + if num_tests == 14: + info('Property test PASSED') if __name__ == '__main__': run() diff --git a/examples/DDDigi/scripts/TestSpillover.py b/examples/DDDigi/scripts/TestSpillover.py index dd3a9a4b3c1c0845ecb95bd07229e731484cf2bf..4379c5177c1490918a0660c80f2b6f78901820d5 100644 --- a/examples/DDDigi/scripts/TestSpillover.py +++ b/examples/DDDigi/scripts/TestSpillover.py @@ -16,16 +16,16 @@ def run(): import DigiTest digi = DigiTest.Test(geometry=None) attenuation = digi.attenuation - + rdr_output = DigiTest.DEBUG input = digi.input_action('DigiParallelActionSequence/READER') # ======================================================================================================== - input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0x0, input=[digi.next_input()]) + input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0x0, input=[digi.next_input()], OutputLevel=rdr_output) digi.info('Created input.signal') # ======================================================================================================== digi.info('Creating spillover sequence for EARLIER bunch crossings.....') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-25') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-25ns', mask=0x1, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-25ns', mask=0x1, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-25ns', t0=-25 * ns, signal_decay='exponential', @@ -38,17 +38,17 @@ def run(): digi.info('Created input.spillover-25') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-50') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-50ns', mask=0x2, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-50ns', mask=0x2, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-50ns', - t0=-50 * ns, input_mask=evtreader.mask, containers=attenuation) + t0=-50 * ns, input_mask=evtreader.mask, containers=attenuation, OutputLevel=rdr_output) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-50ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover-50') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-75') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-75ns', mask=0x3, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader-75ns', mask=0x3, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-75ns', - t0=-75 * ns, input_mask=evtreader.mask, containers=attenuation) + t0=-75 * ns, input_mask=evtreader.mask, containers=attenuation, OutputLevel=rdr_output) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-75ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover-75') @@ -56,25 +56,25 @@ def run(): digi.info('Creating spillover sequence for LATER bunch crossings.....') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+25') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+25ns', mask=0x4, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+25ns', mask=0x4, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+25ns', - t0=25 * ns, input_mask=evtreader.mask, containers=attenuation) + t0=25 * ns, input_mask=evtreader.mask, containers=attenuation, OutputLevel=rdr_output) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+25ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover+25') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+50') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+50ns', mask=0x5, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+50ns', mask=0x5, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+50ns', - t0=50 * ns, input_mask=evtreader.mask, containers=attenuation) + t0=50 * ns, input_mask=evtreader.mask, containers=attenuation, OutputLevel=rdr_output) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop_50ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover+50') # ======================================================================================================== spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+75') - evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+75ns', mask=0x6, input=[digi.next_input()]) + evtreader = spillover.adopt_action('DigiDDG4ROOT/Reader+75ns', mask=0x6, input=[digi.next_input()], OutputLevel=rdr_output) attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+75ns', - t0=75 * ns, input_mask=evtreader.mask, containers=attenuation) + t0=75 * ns, input_mask=evtreader.mask, containers=attenuation, OutputLevel=rdr_output) hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+75ns', masks=[evtreader.mask]) digi.check_creation([spillover, evtreader, attenuate, hist_drop]) digi.info('Created input.spillover+75') diff --git a/examples/DDG4/CMakeLists.txt b/examples/DDG4/CMakeLists.txt index 4634ff08eeef2f2d75de239bd38f85be3b9b2280..8ca826955779edcc01d7bd5b16835b030202295b 100644 --- a/examples/DDG4/CMakeLists.txt +++ b/examples/DDG4/CMakeLists.txt @@ -95,4 +95,12 @@ if (DD4HEP_USE_GEANT4) REGEX_PASS " \\[2\\] Calling classifyNewTrack. StackManager" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) + # + # Test G4 command UI + dd4hep_add_test_reg( DDG4_UIManager + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDG4.sh" + EXEC_ARGS ${Python_EXECUTABLE} ${DDG4examples_INSTALL}/scripts/TestUserCommands.py + REGEX_PASS " Parameter value at call 13 is 'terminate-command-2'" + REGEX_FAIL " ERROR ;EXCEPTION;Exception" + ) endif() diff --git a/examples/DDG4/scripts/TestUserCommands.py b/examples/DDG4/scripts/TestUserCommands.py new file mode 100644 index 0000000000000000000000000000000000000000..04a9dafa48b67b91c9677065ffc85e4f793f238e --- /dev/null +++ b/examples/DDG4/scripts/TestUserCommands.py @@ -0,0 +1,117 @@ +# ========================================================================== +# 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, unicode_literals +import logging +# +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) +# +# +""" + + dd4hep simulation example setup using the python configuration + + @author M.Frank + @version 1.0 + +""" + + +def run(): + import os + import DDG4 + from DDG4 import OutputLevel as Output + from g4units import keV + + args = DDG4.CommandLine() + if args.help: + import sys + logger.info(""" + python <dir>/TestUserCommands.py -option [-option] + -vis Enable visualization + -macro Pass G4 macro file to UI executive + """) + sys.exit(0) + + + kernel = DDG4.Kernel() + kernel.loadGeometry(str("file:" + os.environ['DD4hepExamplesINSTALL'] + "/examples/ClientTests/compact/BoxTrafos.xml")) + geant4 = DDG4.Geant4(kernel) + # Configure UI + if args.macro: + ui = geant4.setupCshUI(macro=args.macro, vis=args.vis) + else: + ui = geant4.setupCshUI(vis=args.vis) + + ui.HaveUI = False + + ui.ConfigureCommands = [ + '/ddg4/Print/param configure-command-1', + '/ddg4/Print/print_param', + '/ddg4/Print/param configure-command-2', + '/ddg4/Print/print_param' + ] + ui.InitializeCommands = [ + '/ddg4/Print/param initialize-command-1', + '/ddg4/Print/print_param', + '/ddg4/Print/param initialize-command-2', + '/ddg4/Print/print_param' + ] + ui.PreRunCommands = [ + '/ddg4/Print/param pre-run-command-1', + '/ddg4/Print/print_param', + '/ddg4/Print/param pre-run-command-2', + '/ddg4/Print/print_param' + ] + ui.TerminateCommands = [ + '/ddg4/Print/param terminate-command-1', + '/ddg4/Print/print_param', + '/ddg4/Print/param terminate-command-2', + '/ddg4/Print/print_param', + '/ddg4/UI/terminate'] + # Post-run commands are only executed in interactive mode! + ui.PostRunCommands = [ + '/ddg4/Print/param post-run-command-1', + '/ddg4/Print/print_param', + '/ddg4/Print/param post-run-command-2', + '/ddg4/Print/print_param' + ] + + prt = DDG4.Action(kernel, 'TestPrintAction/Print') + prt.enableUI() + kernel.registerGlobalAction(prt) + + ui.applyCommand('/ddg4/Print/param interactive-1') + ui.applyCommand('/ddg4/Print/print_param') + + # Now build the physics list: + phys = geant4.setupPhysics('QGSP_BERT') + logger.info('# Execute some G4 action using the UI handle from DDG4....') + geant4.ui().applyCommand('/ddg4/Print/param interactive-2') + geant4.ui().applyCommand('/ddg4/Print/print_param') + + # Start the engine... + logger.info("# No we should see the configuration commands:") + kernel.configure() + logger.info("# No we should see the initialization commands:") + kernel.initialize() + kernel.NumEvents = 0 + logger.info("# No we should see the pre-run commands:") + kernel.run() + logger.info("# No we should see the termination commands:") + ui.applyCommand('/ddg4/Print/param interactive-3') + ui.applyCommand('/ddg4/Print/print_param') + kernel.terminate() + + +if __name__ == "__main__": + run() diff --git a/examples/DDG4/src/TestPrintAction.cpp b/examples/DDG4/src/TestPrintAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a7ca844a5592bb97fbbdf41a62628b59b6ff921 --- /dev/null +++ b/examples/DDG4/src/TestPrintAction.cpp @@ -0,0 +1,58 @@ +//========================================================================== +// 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 "DDG4/Geant4Action.h" +#include "DDG4/Geant4UIMessenger.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace sim { + + /// Class to print message for debugging + /** Class to print message for debugging + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class TestPrintAction : public Geant4Action { + int num_calls { 0 }; + std::string param { "Uninitalized" }; + public: + /// Standard constructor + TestPrintAction(Geant4Context* context, const std::string& nam) + : Geant4Action(context, nam) + { + declareProperty("param", param); + } + /// Default destructor + virtual ~TestPrintAction() { + } + /// Messenger callback + void print_par() { + always("Parameter value at call %d is '%s'", ++num_calls, param.c_str()); + } + /// Install command control messenger to write GDML file from command prompt. + virtual void installCommandMessenger() override { + m_control->addCall("print_param", "Printing some increasing parameter", + Callback(this).make(&TestPrintAction::print_par),0); + } + }; + } // End namespace sim +} // End namespace dd4hep + +#include "DDG4/Factories.h" +DECLARE_GEANT4ACTION_NS(dd4hep::sim,TestPrintAction)