diff --git a/DDCore/include/DD4hep/Factories.h b/DDCore/include/DD4hep/Factories.h index 7be5a22c5b8372983cb178c16cd6ae0b6c8b4333..069fd2c0363d401587425a0904abefef723524a0 100644 --- a/DDCore/include/DD4hep/Factories.h +++ b/DDCore/include/DD4hep/Factories.h @@ -54,6 +54,10 @@ namespace dd4hep { * \date 2012/07/31 * \ingroup DD4HEP_CORE */ + template <typename T> class SimpleConstructionFactory { + public: + static void* create(); + }; template <typename T> class ConstructionFactory { public: static void* create(const char* arg); @@ -206,6 +210,9 @@ namespace { typedef dd4hep::DDSegmentation::BitFieldCoder BitFieldCoder; } + DD4HEP_PLUGIN_FACTORY_ARGS_0(void*) + { return dd4hep::SimpleConstructionFactory<P>::create(); } + DD4HEP_PLUGIN_FACTORY_ARGS_1(void*,const char*) { return dd4hep::ConstructionFactory<P>::create(a0); } @@ -265,6 +272,11 @@ namespace { DD4HEP_PLUGINSVC_FACTORY(name,segmentation_constructor__##name, \ SegmentationObject*(const DDSegmentation::BitFieldCoder*),__LINE__)} +// Call function of the type [void* (*func)()] +#define DECLARE_CREATE(name,func) DD4HEP_OPEN_PLUGIN(dd4hep,name) { \ + template <> void* SimpleConstructionFactory<name>::create() { return func(); } \ + DD4HEP_PLUGINSVC_FACTORY(name,name,void*(),__LINE__)} + // Call function of the type [long (*func)(const char* arg)] #define DECLARE_APPLY(name,func) DD4HEP_OPEN_PLUGIN(dd4hep,name) { \ template <> long ApplyFactory<name>::create(dd4hep::Detector& l,int n,char** a) {return func(l,n,a);} \ diff --git a/DDCore/include/Parsers/Primitives.h b/DDCore/include/Parsers/Primitives.h index 3494b4e0d05ded2fa7901b905506d35a6271ab6a..20afb2b27b169093466400cb6ad41c91efeb541a 100644 --- a/DDCore/include/Parsers/Primitives.h +++ b/DDCore/include/Parsers/Primitives.h @@ -143,6 +143,17 @@ namespace dd4hep { return reverse_num; } + /// C++ version to convert a string to lower case + std::string str_lower(const std::string& str); + /// C++ version to convert a string to upper case + std::string str_upper(const std::string& str); + /// Replace all occurrencies of a string + std::string str_replace(const std::string& source, const std::string& pattern, const std::string& replacement); + /// Replace all occurrencies of a string + std::string str_replace(const std::string& source, char pattern, const std::string& replacement); + /// Replace all occurrencies of a string + std::string str_replace(const std::string& source, char pattern, char replacement); + /// Convert date into epoch time (seconds since 1970) long int makeTime(int year, int month, int day, int hour=0, int minutes=0, int seconds=0); diff --git a/DDCore/python/dd4hep_base.py b/DDCore/python/dd4hep_base.py index 9985f4e91390a8748282e7a1d46b8f4f59c7fe8f..d2d8aaa75375e4feb9f571f4897f380a309922d9 100644 --- a/DDCore/python/dd4hep_base.py +++ b/DDCore/python/dd4hep_base.py @@ -72,7 +72,6 @@ def import_namespace_item(ns, nam): def import_root(nam): setattr(name_space, nam, getattr(ROOT, nam)) - # --------------------------------------------------------------------------- # try: @@ -97,6 +96,29 @@ class _Levels: self.FATAL = 6 self.ALWAYS = 7 +# --------------------------------------------------------------------------- +def unicode_2_string(value): + """Turn any unicode literal into str, needed when passing to c++. + + Recursively transverses dicts, lists, sets, tuples + + :return: always a str + """ + import ddsix as six + if isinstance(value, (bool, float, six.integer_types)): + value = value + elif isinstance(value, six.string_types): + value = str(value) + elif isinstance(value, (list, set, tuple)): + value = [unicode_2_string(x) for x in value] + elif isinstance(value, dict): + tempDict = {} + for key, val in value.items(): + key = unicode_2_string(key) + val = unicode_2_string(val) + tempDict[key] = val + value = tempDict + return str(value) OutputLevel = _Levels() # ------------------------Generic STL stuff can be accessed using std: ----- @@ -125,21 +147,30 @@ import_namespace_item('core', 'run_interpreter') # import_namespace_item('detail', 'interp') import_namespace_item('detail', 'eval') + # --------------------------------------------------------------------------- # def run_interpreter(name): detail.interp.run(name) # def evaluator(): return eval.instance() # def g4Evaluator(): return eval.g4instance() -# --------------------------------------------------------------------------- - +# --------------------------------------------------------------------------- def import_detail(): import_namespace_item('detail', 'DD4hepUI') - +# --------------------------------------------------------------------------- def import_geometry(): import_namespace_item('core', 'setPrintLevel') import_namespace_item('core', 'setPrintFormat') import_namespace_item('core', 'printLevel') + import_namespace_item('core', 'PrintLevel') + + import_namespace_item('core', 'debug') + import_namespace_item('core', 'info') + import_namespace_item('core', 'warning') + import_namespace_item('core', 'error') + import_namespace_item('core', 'fatal') + import_namespace_item('core', 'exception') + import_namespace_item('core', 'Detector') import_namespace_item('core', 'evaluator') import_namespace_item('core', 'g4Evaluator') @@ -157,10 +188,16 @@ def import_geometry(): import_namespace_item('core', 'VisAttr') import_namespace_item('core', 'Limit') import_namespace_item('core', 'LimitSet') + import_namespace_item('core', 'LimitSetObject') import_namespace_item('core', 'Region') + import_namespace_item('core', 'RegionObject') + import_namespace_item('core', 'HitCollection') # // Readout.h + import_namespace_item('core', 'Segmentation') + import_namespace_item('core', 'SegmentationObject') import_namespace_item('core', 'Readout') + import_namespace_item('core', 'ReadoutObject') # // Alignments.h import_namespace_item('core', 'Alignment') @@ -206,7 +243,7 @@ def import_geometry(): import_namespace_item('core', 'UnionSolid') import_namespace_item('core', 'IntersectionSolid') - +# --------------------------------------------------------------------------- def import_tgeo(): import_root('TGeoManager') import_root('TGeoNode') @@ -259,6 +296,55 @@ def import_tgeo(): import_tgeo() import_geometry() import_detail() + +# --------------------------------------------------------------------------- +class Logger: + """ + Helper class to use the dd4hep printout functions from python + + \author M.Frank + \version 1.0 + """ + + def __init__(self, name): + "Logger constructor" + self.name = name + + def always(self, msg): + "Call dd4hep printout function with level ALWAYS" + dd4hep.always(self.name, msg) + + def verbose(self, msg): + "Call dd4hep printout function with level VERBOSE" + dd4hep.verbose(self.name, msg) + + def debug(self, msg): + "Call dd4hep printout function with level DEBUG" + dd4hep.debug(self.name, msg) + + def info(self, msg): + "Call dd4hep printout function with level INFO" + dd4hep.info(self.name, msg) + + def warning(self, msg): + "Call dd4hep printout function with level WARNING" + dd4hep.warning(self.name, msg) + + def error(self, msg): + "Call dd4hep printout function with level ERROR" + dd4hep.error(self.name, msg) + + def fatal(self, msg): + "Call dd4hep printout function with level FATAL" + dd4hep.fatal(self.name, msg) + + def exception(self, msg): + "Call dd4hep exception function" + dd4hep.exception(self.name, msg) + +dd4hep_logger = Logger + +# --------------------------------------------------------------------------- # # Import units from TGeo. # Calling import_units makes all the units local to the dd4hep module. diff --git a/DDCore/src/InstanceCount.cpp b/DDCore/src/InstanceCount.cpp index f4632ee54a53ace9d170862bf580ba31586e827c..9b8fda016003352556d8e3c4acb464ff10091752 100644 --- a/DDCore/src/InstanceCount.cpp +++ b/DDCore/src/InstanceCount.cpp @@ -21,6 +21,7 @@ #include <cstdio> #include <cstdlib> #include <cstring> +#include <mutex> #include <map> using namespace std; @@ -45,6 +46,7 @@ namespace { } int s_global = 1; struct _Global { + std::mutex lock; _Global() {} ~_Global() { s_global = 0; } } s_globalObj; @@ -97,34 +99,44 @@ InstanceCount::Counter* InstanceCount::getCounter(const std::string& typ) { return (0 != cnt) ? cnt : strings()[&typ] = new Counter(); } +#define COUNTER_LOCK std::lock_guard<std::mutex> _counter_lock(s_globalObj.lock); + /// Increment count according to string information void InstanceCount::increment(const std::string& typ) { - if ( s_global ) + if ( s_global ) { + COUNTER_LOCK getCounter(typ)->increment(); + } else on_exit_destructors(); } /// Decrement count according to string information void InstanceCount::decrement(const std::string& typ) { - if ( s_global ) + if ( s_global ) { + COUNTER_LOCK getCounter(typ)->decrement(); + } else on_exit_destructors(); } /// Increment count according to type information void InstanceCount::increment(const std::type_info& typ) { - if ( s_global ) + if ( s_global ) { + COUNTER_LOCK getCounter(typ)->increment(); + } else on_exit_destructors(); } /// Decrement count according to type information void InstanceCount::decrement(const std::type_info& typ) { - if ( s_global ) + if ( s_global ) { + COUNTER_LOCK getCounter(typ)->decrement(); + } else on_exit_destructors(); } diff --git a/DDCore/src/Primitives.cpp b/DDCore/src/Primitives.cpp index eea237cfd8a90df605b0369194a892e98cd15dd5..29773362dc91cd9932f8d6dfa2eb866444d6c5ba 100644 --- a/DDCore/src/Primitives.cpp +++ b/DDCore/src/Primitives.cpp @@ -165,6 +165,50 @@ unsigned long long int dd4hep::detail::hash64(const std::string& key) { return std::accumulate(begin(key),end(key),FNV1a_64::hashinit,FNV1a_64::doByte); } +/// Replace all occurrencies of a string +std::string dd4hep::detail::str_replace(const std::string& str, + const std::string& pattern, + const std::string& replacement) { + std::string res = str; + for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) ) + res.replace(id, pattern.length(), replacement); + return res; +} + +/// Replace all occurrencies of a string +std::string dd4hep::detail::str_replace(const std::string& str, + char pattern, + const std::string& replacement) { + std::string res = str; + for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) ) + res.replace(id, 1, replacement); + return res; +} + +/// Replace all occurrencies of a string +std::string dd4hep::detail::str_replace(const std::string& str, + char pattern, + char replacement) { + std::string res = str; + for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) ) + res.replace(id, 1, 1, replacement); + return res; +} + +/// C++ version to convert a string to lower case +std::string dd4hep::detail::str_lower(const std::string& str) { + std::string res = str.c_str(); + std::transform(res.begin(), res.end(), res.begin(), ::tolower); + return res; +} + +/// C++ version to convert a string to upper case +std::string dd4hep::detail::str_upper(const std::string& str) { + std::string res = str.c_str(); + std::transform(res.begin(), res.end(), res.begin(), ::toupper); + return res; +} + long int dd4hep::detail::makeTime(int year, int month, int day, int hour, int minutes, int seconds) { diff --git a/DDCore/src/Printout.cpp b/DDCore/src/Printout.cpp index 69ca75ae3f8bce7288dd4ed10769bfe6406ea982..d0a6bfd15799d22127fd09dfd014d63af3dcb79f 100644 --- a/DDCore/src/Printout.cpp +++ b/DDCore/src/Printout.cpp @@ -371,7 +371,8 @@ string dd4hep::format(const string& src, const string& fmt, va_list& args) { */ string dd4hep::format(const char* src, const char* fmt, va_list& args) { char str[4096]; - size_t len1 = ::snprintf(str, sizeof(str), "%s: ", src); + size_t len1 = 0; + if ( src && *src ) ::snprintf(str, sizeof(str), "%s: ", src); size_t len2 = ::vsnprintf(str + len1, sizeof(str) - len1, fmt, args); if ( len2 > sizeof(str) - len1 ) { len2 = sizeof(str) - len1 - 1; diff --git a/DDCore/src/RootDictionary.h b/DDCore/src/RootDictionary.h index 02f28ec439083122078542afd1cb94127b350610..937dd746d3bfddacb952c9c71dd4d0e7ee3521b1 100644 --- a/DDCore/src/RootDictionary.h +++ b/DDCore/src/RootDictionary.h @@ -58,6 +58,15 @@ namespace dd4hep { tools::Evaluator& evaluator(); tools::Evaluator& g4Evaluator(); + std::size_t always (const std::string& src, const std::string& msg) { return printout(ALWAYS, src, msg); } + std::size_t verbose(const std::string& src, const std::string& msg) { return printout(VERBOSE, src, msg); } + std::size_t debug (const std::string& src, const std::string& msg) { return printout(DEBUG, src, msg); } + std::size_t info (const std::string& src, const std::string& msg) { return printout(INFO, src, msg); } + std::size_t warning(const std::string& src, const std::string& msg) { return printout(WARNING, src, msg); } + std::size_t error (const std::string& src, const std::string& msg) { return printout(ERROR, src, msg); } + std::size_t fatal (const std::string& src, const std::string& msg) { return printout(FATAL, src, msg); } + void exception(const std::string& src, const std::string& msg) { except(src, "%s", msg.c_str()); } + namespace detail { /// Helper to invoke the ROOT interpreter struct interp { @@ -111,6 +120,16 @@ namespace dd4hep { namespace Parsers { #pragma link C++ namespace dd4hep::DDSegmentation; #pragma link C++ enum dd4hep::PrintLevel; +#pragma link C++ function dd4hep::always; +#pragma link C++ function dd4hep::verbose; +#pragma link C++ function dd4hep::debug; +#pragma link C++ function dd4hep::info; +#pragma link C++ function dd4hep::warning; +#pragma link C++ function dd4hep::error; +#pragma link C++ function dd4hep::fatal; +#pragma link C++ function dd4hep::except; +#pragma link C++ function dd4hep::printout; +#pragma link C++ function dd4hep::exception; #ifndef __ROOTCLING__ template std::pair<unsigned int, std::string>; diff --git a/DDDigi/CMakeLists.txt b/DDDigi/CMakeLists.txt index 7f7c82d09fed7844d9c2de72866faf6c69842519..cc08ec210e03aaa5a2b66eb8ef7c1f9bcb3b1554 100644 --- a/DDDigi/CMakeLists.txt +++ b/DDDigi/CMakeLists.txt @@ -64,4 +64,3 @@ install(TARGETS DDDigi DDDigiPlugins EXPORT DD4hep LIBRARY DESTINATION lib ) install(DIRECTORY include/DDDigi DESTINATION include) - diff --git a/DDDigi/include/DDDigi/DigiAction.h b/DDDigi/include/DDDigi/DigiAction.h index d775da63fd537062eb53bbce0fc784bef0be1677..8559bc353928eb79fbe2ab851f7a40920c0b2096 100644 --- a/DDDigi/include/DDDigi/DigiAction.h +++ b/DDDigi/include/DDDigi/DigiAction.h @@ -99,6 +99,11 @@ namespace dd4hep { /// Reference to the Digi context #if defined(G__ROOT) || defined(__CLING__) || defined(__ROOTCLING__) const DigiKernel* m_kernel; + public: + const DigiKernel* kernel() const { + return m_kernel; + } + protected: #else const DigiKernel& m_kernel; #endif @@ -282,6 +287,8 @@ namespace dd4hep { /// Support for messages with variable output level using output level+2 void printP2(const char* fmt, ...) const; + /// Support for building formatted messages + std::string format(const char* fmt, ...) const; /// Support of debug messages. void debug(const char* fmt, ...) const; /// Support of info messages. diff --git a/DDDigi/include/DDDigi/DigiActionSequence.h b/DDDigi/include/DDDigi/DigiActionSequence.h index fed3b8bbf16d6b17596ea46bb9b1eddffe6e85bc..de1d9e08e353e958928ff1210eacedfed62b0192 100644 --- a/DDDigi/include/DDDigi/DigiActionSequence.h +++ b/DDDigi/include/DDDigi/DigiActionSequence.h @@ -72,6 +72,36 @@ namespace dd4hep { virtual void execute(DigiContext& context) const override; }; + /// Definitiaon of the sequential action sequence + /** Definitiaon of the sequential action sequence + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiSequentialActionSequence : public DigiActionSequence { + public: + /// Standard constructor + DigiSequentialActionSequence(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiSequentialActionSequence(); + }; + + /// Definitiaon of the parallel action sequence + /** Definitiaon of the parallel action sequence + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiParallelActionSequence : public DigiActionSequence { + public: + /// Standard constructor + DigiParallelActionSequence(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiParallelActionSequence(); + }; + } // End namespace digi } // End namespace dd4hep #endif // DDDIGI_DIGIACTIONSEQUENCE_H diff --git a/DDDigi/include/DDDigi/DigiContainerCombine.h b/DDDigi/include/DDDigi/DigiContainerCombine.h new file mode 100644 index 0000000000000000000000000000000000000000..76cda89f1176b057281b671f12d91a646db3d3c7 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiContainerCombine.h @@ -0,0 +1,65 @@ +//========================================================================== +// 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_DIGICONTAINERCOMBINE_H +#define DDDIGI_DIGICONTAINERCOMBINE_H + +// Framework include files +#include <DDDigi/DigiEventAction.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiContainerCombine : public DigiEventAction { + protected: + /// Implementation declaration + class internals_t; + + /// Reference to the implementation + std::unique_ptr<internals_t> internals; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerCombine); + + /// Default destructor + virtual ~DigiContainerCombine(); + + /// Combine selected containers to one single deposit container + template <typename PREDICATE> + std::size_t combine_containers(DigiEvent& event, + DigiEvent::container_map_t& inputs, + DigiEvent::container_map_t& outputs, + const PREDICATE& predicate) const; + + public: + /// Standard constructor + DigiContainerCombine(const DigiKernel& kernel, const std::string& name); + + /// Main functional callback + virtual void execute(DigiContext& context) const; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGICONTAINERCOMBINE_H diff --git a/DDDigi/include/DDDigi/DigiContext.h b/DDDigi/include/DDDigi/DigiContext.h index cfbd7e2e9c5eafe96b8273e0eef41288cbb3cf88..2a9150bfde32669cd1f4a09f9ad1bdb0645a76d6 100644 --- a/DDDigi/include/DDDigi/DigiContext.h +++ b/DDDigi/include/DDDigi/DigiContext.h @@ -20,6 +20,7 @@ /// C/C++ include files #include <memory> +#include <mutex> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -84,13 +85,19 @@ namespace dd4hep { friend class DigiKernel; public: typedef std::pair<void*, const std::type_info*> UserFramework; - protected: + + public: + /// Reference to the thread context + const DigiKernel& kernel; /// Transient context variable - depending on the thread context: event reference - const DigiKernel* m_kernel = 0; - /// Reference to transient event - DigiEvent* m_event = 0; + std::unique_ptr<DigiEvent> event { }; + + protected: /// Reference to the random engine for this event std::shared_ptr<DigiRandomGenerator> m_random; + + + protected: /// Inhibit default constructor DigiContext() = delete; /// Inhibit move constructor @@ -99,17 +106,19 @@ namespace dd4hep { DigiContext(const DigiContext&) = delete; public: + /// Initializing constructor - DigiContext(const DigiKernel* kernel_pointer, DigiEvent* event_pointer = 0); + DigiContext(const DigiKernel& kernel, std::unique_ptr<DigiEvent>&& event); /// Default destructor virtual ~DigiContext(); - /// Set the geant4 event reference - void setEvent(DigiEvent* new_event); - /// Access the geant4 event -- valid only between BeginEvent() and EndEvent()! - DigiEvent& event() const; - /// Access the geant4 event by ptr. Must be checked by clients! - DigiEvent* eventPtr() const { return m_event; } + /// Have a shared initializer lock + std::mutex& initializer_lock() const; + /// Have a global I/O lock (e.g. for ROOT) + std::mutex& global_io_lock() const; + /// Have a global output log lock + std::mutex& global_output_lock() const; + /// Access to the random engine for this event DigiRandomGenerator& randomGenerator() const { return *m_random; } /// Access to the user framework. Specialized function to be implemented by the client diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index d56781aca62634473bb6a869e63174094d85562f..f12ae3a035cab67b398a5f7d03dfa33c66490641 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -25,7 +25,12 @@ #include <stdexcept> #include <cstdint> #include <memory> +#include <mutex> #include <map> +#include <set> +#include <unordered_map> +#include <unordered_set> +#include <any> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -33,227 +38,201 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + /// Forward declarations class DigiEvent; + class Particle; + class ParticleMapping; + class EnergyDeposit; + class DepositMapping; - /// Container class to host energy deposits from simulation or noise processing - /* + /// Key defintion to access the event data + /** + * Helper to convert item and mask to a 64 bit integer * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - template <typename T> class DigiContainer : public std::vector<T> { - /// Unique name within the event - std::string name; - - public: - /// Default constructor - DigiContainer() = default; - /// Disable move constructor - DigiContainer(DigiContainer&& copy) = default; - /// Disable copy constructor - DigiContainer(const DigiContainer& copy) = default; - /// Default constructor - DigiContainer(const std::string& nam) : name(nam) {} - /// Default destructor - virtual ~DigiContainer() = default; - /// Disable move assignment - DigiContainer& operator=(DigiContainer&& copy) = delete; - /// Disable copy assignment - DigiContainer& operator=(const DigiContainer& copy) = delete; + union Key { + typedef std::uint64_t key_type; + typedef std::uint32_t itemkey_type; + typedef std::uint16_t mask_type; + + key_type key; + struct { + itemkey_type item; + mask_type mask; + mask_type spare; + } values; + Key(); + Key(const Key&); + Key(key_type full_mask); + Key(mask_type mask, const std::string& item); + Key& operator=(const Key&); + key_type toLong() const { return key; } + void set(const std::string& name, int mask); + /// Project the mask part of the key + static itemkey_type item(key_type k) { + return Key(k).values.item; + } + /// Project the item part of the key + static mask_type mask(key_type k) { + return Key(k).values.mask; + } + /// Access key name (if registered properly) + static std::string key_name(const Key& key); }; - - /// - /* + + /// Particle definition for digitization + /** Particle definition for digitization * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class EnergyDeposit { + class Particle { public: - class FunctionTable { - friend class EnergyDeposit; - public: - std::function<long long int(const void*)> cellID; - std::function<long(const void*)> flag; - FunctionTable() = default; - ~FunctionTable() = default; - }; - template <typename Q, typename T> static const Q* vtable(); - std::pair<const void*, const FunctionTable*> object; + /// Source contributing + std::any history; public: /// Initializing constructor - template <typename T> EnergyDeposit(const T* object); + Particle(std::any&& history); /// Default constructor - EnergyDeposit() = delete; + Particle() = default; /// Disable move constructor - EnergyDeposit(EnergyDeposit&& copy) = default; + Particle(Particle&& copy) = default; /// Disable copy constructor - EnergyDeposit(const EnergyDeposit& copy) = default; + Particle(const Particle& copy) = default; /// Default destructor - virtual ~EnergyDeposit() = default; + virtual ~Particle() = default; /// Disable move assignment - EnergyDeposit& operator=(EnergyDeposit&& copy) = default; + Particle& operator=(Particle&& copy) = default; /// Disable copy assignment - EnergyDeposit& operator=(const EnergyDeposit& copy) = default; - - long long int cellID() const { return object.second->cellID(object.first); } - long flag() const { return object.second->flag(object.first); } + Particle& operator=(const Particle& copy) = default; }; - template <typename T> inline EnergyDeposit::EnergyDeposit(const T* ptr) - : object(ptr, vtable<EnergyDeposit::FunctionTable,T>()) + /// Initializing constructor + inline Particle::Particle(std::any&& h) + : history(h) { } - /// - /* + /// Particle mapping definition for digitization + /** Particle mapping definition for digitization * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class TrackerDeposit : public EnergyDeposit { + class ParticleMapping : public std::map<Key::key_type, Particle> { public: - class FunctionTable : public EnergyDeposit::FunctionTable { - friend class TrackerDeposit; - friend class EnergyDeposit; - public: - std::function<const Position& (const void*)> position; - std::function<const Direction& (const void*)> momentum; - std::function<double(const void*)> deposit; - std::function<double(const void*)> length; - FunctionTable() = default; - ~FunctionTable() = default; - }; - std::pair<const void*, const FunctionTable*> object; + std::string name { }; + Key::mask_type mask { 0x0 }; - public: + public: /// Initializing constructor - template <typename T> TrackerDeposit(const T* object); + ParticleMapping(const std::string& name, Key::mask_type mask); /// Default constructor - TrackerDeposit() = delete; + ParticleMapping() = default; /// Disable move constructor - TrackerDeposit(TrackerDeposit&& copy) = default; + ParticleMapping(ParticleMapping&& copy) = default; /// Disable copy constructor - TrackerDeposit(const TrackerDeposit& copy) = default; + ParticleMapping(const ParticleMapping& copy) = default; /// Default destructor - virtual ~TrackerDeposit() = default; + virtual ~ParticleMapping() = default; /// Disable move assignment - TrackerDeposit& operator=(TrackerDeposit&& copy) = default; + ParticleMapping& operator=(ParticleMapping&& copy) = default; /// Disable copy assignment - TrackerDeposit& operator=(const TrackerDeposit& copy) = default; + ParticleMapping& operator=(const ParticleMapping& copy) = default; - const Position& position() const { return object.second->position(object.first); } - const Direction& momentum() const { return object.second->momentum(object.first); } - double deposit() const { return object.second->deposit(object.first); } - double length() const { return object.second->length(object.first); } + /// Merge new deposit map onto existing map + std::size_t merge(ParticleMapping&& updates); + void push(Key::key_type key, Particle&& particle); }; - template <typename T> inline TrackerDeposit::TrackerDeposit(const T* ptr) - : object(ptr, vtable<TrackerDeposit::FunctionTable,T>()) + /// Initializing constructor + inline ParticleMapping::ParticleMapping(const std::string& n, Key::mask_type m) + : name(n), mask(m) { } - /// - /* + /// Energy deposit definition for digitization + /** Energy deposit definition for digitization * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class CaloDeposit : public EnergyDeposit { + class EnergyDeposit { public: - class FunctionTable : public EnergyDeposit::FunctionTable { - friend class CaloDeposit; - friend class EnergyDeposit; - public: - std::function<const Position& (const void*)> position; - std::function<double(const void*)> deposit; - FunctionTable() = default; - ~FunctionTable() = default; - }; - std::pair<const void*, const FunctionTable*> object; + /// Total energy deposit + double deposit { 0 }; + /// Sources contributing to this deposit + std::vector<std::pair<std::any, Key::mask_type> > history; public: /// Initializing constructor - template <typename T> CaloDeposit(const T* object); + EnergyDeposit(double ene); /// Default constructor - CaloDeposit() = delete; + EnergyDeposit() = default; /// Disable move constructor - CaloDeposit(CaloDeposit&& copy) = default; + EnergyDeposit(EnergyDeposit&& copy) = default; /// Disable copy constructor - CaloDeposit(const CaloDeposit& copy) = default; + EnergyDeposit(const EnergyDeposit& copy) = default; /// Default destructor - virtual ~CaloDeposit() = default; + virtual ~EnergyDeposit() = default; /// Disable move assignment - CaloDeposit& operator=(CaloDeposit&& copy) = default; + EnergyDeposit& operator=(EnergyDeposit&& copy) = default; /// Disable copy assignment - CaloDeposit& operator=(const CaloDeposit& copy) = default; - - const Position& position() const { return object.second->position(object.first); } - double deposit() const { return object.second->deposit(object.first); } + EnergyDeposit& operator=(const EnergyDeposit& copy) = default; }; - template <typename T> inline CaloDeposit::CaloDeposit(const T* ptr) - : object(ptr, vtable<CaloDeposit::FunctionTable,T>()) + + /// Initializing constructor + inline EnergyDeposit::EnergyDeposit(double ene) + : deposit(ene) { } - - /// - /* + + /// Energy deposit mapping definition for digitization + /** Energy deposit mapping definition for digitization * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiCount { - public: + class DepositMapping : public std::map<CellID, EnergyDeposit> { + public: + std::string name { }; + Key::mask_type mask { 0x0 }; + + public: + /// Initializing constructor + DepositMapping(const std::string& name, Key::mask_type mask); /// Default constructor - DigiCount() = default; - /// Default move constructor - DigiCount(DigiCount&& copy) = default; - /// Default copy constructor - DigiCount(const DigiCount& copy) = default; + DepositMapping() = default; + /// Disable move constructor + DepositMapping(DepositMapping&& copy) = default; + /// Disable copy constructor + DepositMapping(const DepositMapping& copy) = default; /// Default destructor - virtual ~DigiCount() = default; - /// Default move assignment - DigiCount& operator=(DigiCount&& copy) = delete; - /// Default copy assignment - DigiCount& operator=(const DigiCount& copy) = delete; + virtual ~DepositMapping() = default; + /// Disable move assignment + DepositMapping& operator=(DepositMapping&& copy) = default; + /// Disable copy assignment + DepositMapping& operator=(const DepositMapping& copy) = default; + + /// Merge new deposit map onto existing map + std::size_t merge(DepositMapping&& updates); }; - typedef DigiContainer<EnergyDeposit*> DigiEnergyDeposits; - typedef DigiContainer<DigiCount*> DigiCounts; + /// Initializing constructor + inline DepositMapping::DepositMapping(const std::string& n, Key::mask_type m) + : name(n), mask(m) + { + } - /// Key defintion to access the event data - /** - * Helper to convert item and mask to a 64 bit integer - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - union Key { - typedef std::uint64_t key_type; - typedef std::uint32_t itemkey_type; - typedef std::uint8_t mask_type; - key_type key; - struct { - itemkey_type item; - mask_type mask; - mask_type spare[3]; - } values; - Key(); - Key(const Key&); - Key(mask_type mask, itemkey_type item); - Key(mask_type mask, const std::string& item); - Key& operator=(const Key&); - key_type toLong() const { return key; } - void set(const std::string& name, int mask); - }; } // End namespace digi } // End namespace dd4hep @@ -278,17 +257,24 @@ namespace dd4hep { * \ingroup DD4HEP_DIGITIZATION */ class DigiEvent : public ObjectExtensions { + private: + std::mutex m_lock; + std::string m_id; public: /// Forward definition of the key type typedef Key::key_type key_type; - std::map<unsigned long, std::shared_ptr<DigiEnergyDeposits> > energyDeposits; - std::map<unsigned long, std::shared_ptr<DigiCounts> > digitizations; int eventNumber = 0; #if defined(DD4HEP_INTERPRETER_MODE) std::map<key_type, long> data; + std::map<key_type, long> inputs; + std::map<key_type, long> deposits; #else - std::map<key_type, dd4hep::any> data; + typedef std::map<key_type, dd4hep::any> container_map_t; + protected: + container_map_t data; + container_map_t inputs; + container_map_t deposits; #endif public: #if defined(DD4HEP_INTERPRETER_MODE) || defined(G__ROOT) @@ -304,10 +290,22 @@ namespace dd4hep { /// Default destructor virtual ~DigiEvent(); + /// String identifier of this event + const char* id() const { return this->m_id.c_str(); } + #if !defined(DD4HEP_INTERPRETER_MODE) + /// Add item by key to the data segment + bool put_data(unsigned long key, std::any&& object); + + /// Add item by key to the input segment + bool put_input(unsigned long key, std::any&& object); + + /// Retrieve data segment from the event structure + container_map_t& get_segment(const std::string& name); + /// Add item by key to the data template<typename T> bool put(const Key& key, T&& object) { - bool ret = data.emplace(key.toLong(),make_any<T>(object)).second; + bool ret = this->inputs.emplace(key.toLong(),make_any<T>(object)).second; if ( ret ) return ret; except("DigiEvent","Invalid requested to store data in event container. Key:%ld",key.toLong()); throw std::runtime_error("DigiEvent"); // Will never get here! diff --git a/DDDigi/include/DDDigi/DigiEventAction.h b/DDDigi/include/DDDigi/DigiEventAction.h index f787ed286f8abcc9b64abeec53df5667ac168325..9611312e48565fe1634db13ad13e4c3cd886c690 100644 --- a/DDDigi/include/DDDigi/DigiEventAction.h +++ b/DDDigi/include/DDDigi/DigiEventAction.h @@ -14,8 +14,7 @@ #define DDDIGI_DIGIEVENTACTION_H // Framework include files -#include "DDDigi/DigiAction.h" - +#include <DDDigi/DigiAction.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -23,6 +22,9 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + /// Forward declarations + class DigiEvent; + /// Default base class for all Digitizer actions and derivates thereof. /** * This is a utility class supporting properties, output and access to diff --git a/DDDigi/include/DDDigi/DigiGrammars.h b/DDDigi/include/DDDigi/DigiGrammars.h new file mode 100644 index 0000000000000000000000000000000000000000..89e46dbef12911fc2bc67214eeabded270091632 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiGrammars.h @@ -0,0 +1,25 @@ +//========================================================================== +// 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_GRAMMARS_H +#define DDDIGI_GRAMMARS_H + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_GRAMMARS_H diff --git a/DDDigi/include/DDDigi/DigiHandle.h b/DDDigi/include/DDDigi/DigiHandle.h index 05359087f6bb1488a034a4fd52b64211850ae3c6..dbafaaeb3fe057c1d130c6199b7a26d72945be58 100644 --- a/DDDigi/include/DDDigi/DigiHandle.h +++ b/DDDigi/include/DDDigi/DigiHandle.h @@ -33,6 +33,36 @@ namespace dd4hep { class DigiEventAction; class DigiSignalProcessor; + /// Handle to Digi actions with built-in creation mechanism + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class KernelHandle { + public: + /// Pointer to referenced object + mutable DigiKernel* value; + /// Default constructor + explicit KernelHandle(); + /// Construction initialized with object pointer + explicit KernelHandle(DigiKernel* k); + /// Copy constructor + KernelHandle(const KernelHandle& k) : value(k.value) {} + /// Default destructor + ~KernelHandle() { } + /// Conversion operator + operator DigiKernel*() const { return value; } + /// Access to the underlying object + DigiKernel* get() const { return value; } + /// Access to the underlying object + DigiKernel* operator->() const { return value; } + /// Access to worker thread + KernelHandle worker(); + /// Destroy referenced object (program termination) + void destroy(); + }; + /// Handle to Digi actions with built-in creation mechanism /** * \author M.Frank @@ -86,36 +116,6 @@ namespace dd4hep { TYPE* release(); }; - /// Handle to Digi actions with built-in creation mechanism - /** - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_SIMULATION - */ - class KernelHandle { - public: - /// Pointer to referenced object - mutable DigiKernel* value; - /// Default constructor - explicit KernelHandle(); - /// Construction initialized with object pointer - explicit KernelHandle(DigiKernel* k); - /// Copy constructor - KernelHandle(const KernelHandle& k) : value(k.value) {} - /// Default destructor - ~KernelHandle() { } - /// Conversion operator - operator DigiKernel*() const { return value; } - /// Access to the underlying object - DigiKernel* get() const { return value; } - /// Access to the underlying object - DigiKernel* operator->() const { return value; } - /// Access to worker thread - KernelHandle worker(); - /// Destroy referenced object (program termination) - void destroy(); - }; - } // End namespace digi } // End namespace dd4hep diff --git a/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h b/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h new file mode 100644 index 0000000000000000000000000000000000000000..d4281fe7531e91090671fd0d6d7b3e80b2fcc721 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h @@ -0,0 +1,57 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DDDIGI_DIGIHITATTENUATOREXP_H +#define DDDIGI_DIGIHITATTENUATOREXP_H + +// Framework include files +#include "DDDigi/DigiEventAction.h" + + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiHitAttenuatorExp : public DigiEventAction { + protected: + /// Implementation declaration + class internals_t; + /// Reference to the actual implementation + std::unique_ptr<internals_t> internals; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiHitAttenuatorExp); + + /// Default destructor + virtual ~DigiHitAttenuatorExp(); + + public: + /// Standard constructor + DigiHitAttenuatorExp(const DigiKernel& kernel, const std::string& nam); + /// Main functional callback + virtual void execute(DigiContext& context) const; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGIHITATTENUATOREXP_H diff --git a/DDDigi/include/DDDigi/DigiInputAction.h b/DDDigi/include/DDDigi/DigiInputAction.h index 73d545b0d86349f32aadbda26e9ac37e3ef2f7e6..ab41c5e2bd2911be65e63078dee31dad701c5112 100644 --- a/DDDigi/include/DDDigi/DigiInputAction.h +++ b/DDDigi/include/DDDigi/DigiInputAction.h @@ -14,7 +14,10 @@ #define DDDIGI_DIGIINPUTACTION_H /// Framework include files -#include "DDDigi/DigiEventAction.h" +#include <DDDigi/DigiEventAction.h> + +/// C/C++ include files +#include <limits> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -34,9 +37,16 @@ namespace dd4hep { * \ingroup DD4HEP_DIGITIZATION */ class DigiInputAction : public DigiEventAction { + public: + enum { INPUT_START = -1 }; + enum { NO_MASK = 0x0 }; + protected: - /// Input data specification - std::vector<std::string> m_input; + /// Property: Input data specification + std::vector<std::string> m_inputs { }; + /// Property: Mask to flag input source items + int m_mask { NO_MASK }; + protected: /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiInputAction); diff --git a/DDDigi/include/DDDigi/DigiKernel.h b/DDDigi/include/DDDigi/DigiKernel.h index 74e282847b834b04409cc6fe202af33a393705d8..edd680220eefb361977bc585f5096dae662423b4 100644 --- a/DDDigi/include/DDDigi/DigiKernel.h +++ b/DDDigi/include/DDDigi/DigiKernel.h @@ -18,7 +18,7 @@ // C/C++ include files #include <mutex> -#include <atomic> +#include <memory> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -48,20 +48,20 @@ namespace dd4hep { class Wrapper; /// Internal only data structures; - Internals* internals = 0; + Internals* internals { nullptr }; protected: /// Detector description object - Detector* m_detDesc = 0; + Detector* m_detDesc { nullptr }; /// Reference to the user framework mutable UserFramework m_userFramework; /// Execute one single event - virtual void executeEvent(DigiContext* context); + virtual void executeEvent(std::unique_ptr<DigiContext>&& context); /// Notify kernel that the execution of one single event finished - void notify(DigiContext* context); + void notify(std::unique_ptr<DigiContext>&& context); /// Notify kernel that the execution of one single event finished - void notify(DigiContext* context, const std::exception& e); + void notify(std::unique_ptr<DigiContext>&&, const std::exception& e); protected: /// Define standard assignments and constructors @@ -87,6 +87,15 @@ namespace dd4hep { template <typename T> void setUserFramework(T* object) { m_userFramework = UserFramework(object,&typeid(T)); } + + /// Have a shared initializer lock + std::mutex& initializer_lock() const; + + /// Have a global I/O lock (e.g. for ROOT) + std::mutex& global_io_lock() const; + + /// Have a global output log lock + std::mutex& global_output_lock() const; /** Property access */ /// Access to the properties of the object @@ -112,6 +121,13 @@ namespace dd4hep { /// Retrieve the global output level of a named object. PrintLevel getOutputLevel(const std::string object) const; + /// Access current number of events still to process + std::size_t events_todo() const; + /// Access current number of events already processed + std::size_t events_done() const; + /// Access current number of events processing (events in flight) + std::size_t events_processing() const; + /// Construct detector geometry using description plugin virtual void loadGeometry(const std::string& compact_file); /// Load XML file diff --git a/DDDigi/include/DDDigi/DigiDDG4Input.h b/DDDigi/include/DDDigi/DigiROOTInput.h similarity index 57% rename from DDDigi/include/DDDigi/DigiDDG4Input.h rename to DDDigi/include/DDDigi/DigiROOTInput.h index 5c19d3a3874beec277be94a4b967a254087d812c..da30a24056ef59f53bd3d88274b5a73ac3ecb357 100644 --- a/DDDigi/include/DDDigi/DigiDDG4Input.h +++ b/DDDigi/include/DDDigi/DigiROOTInput.h @@ -10,16 +10,18 @@ // Author : M.Frank // //========================================================================== -#ifndef DDDIGI_DIGIDDG4INPUT_H -#define DDDIGI_DIGIDDG4INPUT_H +#ifndef DDDIGI_DIGIROOTINPUT_H +#define DDDIGI_DIGIROOTINPUT_H /// Framework include files -#include "DDDigi/DigiInputAction.h" +#include <DDDigi/DigiInputAction.h> + +// C/C++ include files +#include <memory> +#include <mutex> // Forward declarations -class TFile; -class TTree; -class TBranch; +class TClass; /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -28,7 +30,7 @@ namespace dd4hep { namespace digi { // Forward declarations - class DigiDDG4Input; + class DigiROOTInput; /// Base class for input actions to the digitization /** @@ -37,26 +39,36 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiDDG4Input : public DigiInputAction { + class DigiROOTInput : public DigiInputAction { + protected: - /// Reference to the current ROOT file to be read - TFile* m_current { nullptr }; - /// List of input sources to be worked down - std::vector<std::string> m_todo { }; + /// Helper classes + class internals_t; + /// Property: Name of the tree to connect to + std::string m_tree_name { }; + /// Property: Container names to be loaded + std::vector<std::string> m_containers { }; + + mutable int m_curr_input { 0 }; + /// Connection parameters to the "current" input source + mutable std::unique_ptr<internals_t> imp { }; + + /// Open new input file + void open_new_file() const; protected: /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiDDG4Input); + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiROOTInput); public: /// Standard constructor - DigiDDG4Input(const DigiKernel& kernel, const std::string& nam); + DigiROOTInput(const DigiKernel& kernel, const std::string& nam); /// Default destructor - virtual ~DigiDDG4Input(); + virtual ~DigiROOTInput(); /// Callback to read event input virtual void execute(DigiContext& context) const override; }; } // End namespace digi } // End namespace dd4hep -#endif // DDDIGI_DIGIDDG4INPUT_H +#endif // DDDIGI_DIGIROOTINPUT_H diff --git a/DDDigi/include/DDDigi/DigiSegmentation.h b/DDDigi/include/DDDigi/DigiSegmentation.h index 3f4f82ff4a39ff31450bc9dcf660ceb4d8741630..3507a2b9a7a8981e756b84c6d368aa61df3e5b48 100644 --- a/DDDigi/include/DDDigi/DigiSegmentation.h +++ b/DDDigi/include/DDDigi/DigiSegmentation.h @@ -31,7 +31,7 @@ namespace dd4hep { class DigiContext; class DigiSegmentation; template <typename SEGMENTATION> class cell_data; - template <typename SEGMENTATION> class segmentation_data; + template <typename SEGMENTATION> class segmentation_data; /// /* @@ -59,7 +59,7 @@ namespace dd4hep { /// Default move assignment DigiCellData& operator=(DigiCellData&& copy) = delete; /// Default copy assignment - DigiCellData& operator=(const DigiCellData& copy) = delete; + DigiCellData& operator=(const DigiCellData& copy) = delete; }; template <typename SEGMENTATION> diff --git a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h new file mode 100644 index 0000000000000000000000000000000000000000..fac34979d1f14c533f1f546a84938a6e6fdd106a --- /dev/null +++ b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h @@ -0,0 +1,61 @@ +//========================================================================== +// 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_DIGISEGMENTATIONSPLITTER_H +#define DDDIGI_DIGISEGMENTATIONSPLITTER_H + +// Framework include files +#include <DDDigi/DigiEventAction.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiSegmentationSplitter : public DigiEventAction { + protected: + /// Implementation declaration + class internals_t; + + /// Reference to the implementation + std::unique_ptr<internals_t> internals; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentationSplitter); + + /// Default destructor + virtual ~DigiSegmentationSplitter(); + + /// Split actions according to the segmentation + void split_segments(DigiEvent& event, DigiEvent::container_map_t& data) const; + + public: + /// Standard constructor + DigiSegmentationSplitter(const DigiKernel& kernel, const std::string& name); + + /// Main functional callback + virtual void execute(DigiContext& context) const; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGISEGMENTATIONSPLITTER_H diff --git a/DDDigi/include/DDDigi/DigiStoreDump.h b/DDDigi/include/DDDigi/DigiStoreDump.h new file mode 100644 index 0000000000000000000000000000000000000000..2cbf1e89ab9fdc45096dbf6dab294aaa82f611bf --- /dev/null +++ b/DDDigi/include/DDDigi/DigiStoreDump.h @@ -0,0 +1,64 @@ +//========================================================================== +// 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_DIGISTOREDUMP_H +#define DDDIGI_DIGISTOREDUMP_H + +/// Framework include files +#include "DDDigi/DigiEventAction.h" + +/// C/C++ include files +#include <mutex> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiStoreDump : public DigiEventAction { + protected: + /// Property: Flag to check history record + bool m_dump_history { false }; + /// Property: Data segments to be dumped + std::vector<std::string> m_data_segments { }; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiStoreDump); + + /// Default destructor + virtual ~DigiStoreDump(); + + /// Dump hit container + template <typename CONTAINER> void dump(const std::string& tag, + const DigiEvent& event, + const CONTAINER& cont) const; + + public: + /// Standard constructor + DigiStoreDump(const DigiKernel& kernel, const std::string& nam); + /// Main functional callback + virtual void execute(DigiContext& context) const; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGISTOREDUMP_H diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index e7080658446eaa3408a9b452b5503079dc8dda48..b36856ca8ccbbcbeb9e908990657f1e03e3c6cb2 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -24,14 +24,16 @@ #include "DDDigi/DigiInputAction.h" DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiInputAction) -#include "DDDigi/DigiDDG4Input.h" -DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiDDG4Input) +#include "DDDigi/DigiROOTInput.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiROOTInput) #include "DDDigi/DigiSynchronize.h" DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSynchronize) #include "DDDigi/DigiActionSequence.h" DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiActionSequence) +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiParallelActionSequence) +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSequentialActionSequence) #include "DDDigi/DigiSubdetectorSequence.h" DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSubdetectorSequence) @@ -42,6 +44,19 @@ DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiLockedAction) #include "DDDigi/DigiSignalProcessorSequence.h" DECLARE_DIGISIGNALPROCESSOR_NS(dd4hep::digi,DigiSignalProcessorSequence) +#include "DDDigi/DigiStoreDump.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiStoreDump) + +#include "DDDigi/DigiHitAttenuatorExp.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiHitAttenuatorExp) + +#include "DDDigi/DigiContainerCombine.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiContainerCombine) + +#include "DDDigi/DigiSegmentationSplitter.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSegmentationSplitter) + + using namespace std; using namespace dd4hep; diff --git a/DDDigi/plugins/DigiDDG4Input.cpp b/DDDigi/plugins/DigiDDG4Input.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a50fbdaa0564e9c1a2826eea760c5e60dda16f76 --- /dev/null +++ b/DDDigi/plugins/DigiDDG4Input.cpp @@ -0,0 +1,103 @@ +//========================================================================== +// 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 <DD4hep/Factories.h> +#include <DD4hep/DD4hepUnits.h> +#include <DDG4/Geant4Data.h> +#include <DDG4/Geant4Particle.h> +#include <DDDigi/DigiData.h> +#include <CLHEP/Units/SystemOfUnits.h> + +// ROOT include files + +// C/C++ include files +#include <stdexcept> +#include <any> + +using namespace dd4hep; + +typedef std::function<std::any(int, const char*, void*)> func_t; + +namespace { + + template <typename T> union input_data { + const void* raw; + std::vector<T*>* items; + input_data(const void* p) { this->raw = p; } + }; + + template <typename T> void* ddg4_hit_convert_function(const char* desc) { + std::string tag = desc; + func_t* cnv = new func_t([tag] (int mask, const char* name, void* ptr) { + using wrap_t = std::shared_ptr<sim::Geant4HitData>; + std::size_t len = 0; + digi::DepositMapping out(name, mask); + if ( ptr ) { + input_data<T> data(ptr); + digi::Key::mask_type msk = digi::Key::mask_type(mask); + for( auto* p : *data.items ) { + auto it = out.find(p->cellID); + if ( it == out.end() ) { + digi::EnergyDeposit dep(p->energyDeposit); + dep.history.emplace_back(std::any(wrap_t(p)), msk); + out.emplace(p->cellID, std::move(dep)); + continue; + } + (*it).second.history.emplace_back(std::any(wrap_t(p)), msk); + (*it).second.deposit += p->energyDeposit; + } + len = data.items->size(); + data.items->clear(); + } + printout(DEBUG,"DDG4Converter","++ Converted %ld %s to %ld cell deposits", + len, tag.c_str(), out.size()); + return std::make_any<digi::DepositMapping>(std::move(out)); + }); + return cnv; + } +} + +static void* convert_sim_geant4calorimeter_hits() { + return ddg4_hit_convert_function<sim::Geant4Calorimeter::Hit>("DDG4 calorimeter hits"); +} +DECLARE_CREATE(DD4hep_DDDigiConverter_vector_dd4hep_sim_Geant4Calorimeter_Hit_,convert_sim_geant4calorimeter_hits); + +static void* convert_sim_geant4tracker_hits() { + return ddg4_hit_convert_function<sim::Geant4Tracker::Hit>("DDG4 tracker hits"); +} +DECLARE_CREATE(DD4hep_DDDigiConverter_vector_dd4hep_sim_Geant4Tracker_Hit_,convert_sim_geant4tracker_hits); + +static void* convert_sim_geant4particles() { + func_t* cnv = new func_t([] (int mask, const char* name, void* ptr) { + std::any res = std::make_any<digi::ParticleMapping>(name, mask); + digi::ParticleMapping* out = std::any_cast<digi::ParticleMapping>(&res); + if ( ptr ) { + using wrap_t = std::shared_ptr<sim::Geant4Particle>; + auto* items = (std::vector<sim::Geant4Particle*>*)ptr; + for( auto* p : *items ) { + digi::Key key(0); + key.values.mask = mask; + key.values.item = out->size(); + p->mask = mask; + out->push(key.key, {std::make_any<wrap_t>(p)}); + } + items->clear(); + } + printout(DEBUG,"DDG4Converter","++ Converted %ld DDG4 particles", out->size()); + return res; + }); + return cnv; +} +DECLARE_CREATE(DD4hep_DDDigiConverter_vector_dd4hep_sim_Geant4Particle_,convert_sim_geant4particles); diff --git a/DDDigi/plugins/DigiHitHistoryDrop.cpp b/DDDigi/plugins/DigiHitHistoryDrop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04d1e694cdf6c76f915324ababf0649bdc7a3c7b --- /dev/null +++ b/DDDigi/plugins/DigiHitHistoryDrop.cpp @@ -0,0 +1,88 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiEventAction.h" + + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Default base class for all Digitizer actions and derivates thereof. + /** + * This is a utility class supporting properties, output and access to + * event and run objects through the context. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiHitHistoryDrop : public DigiEventAction { + protected: + /// Property: Masks to act on + std::vector<int> m_masks { }; + /// Property: Input data segment name + std::string m_input { }; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiHitHistoryDrop); + + /// Default destructor + virtual ~DigiHitHistoryDrop() { + InstanceCount::decrement(this); + } + + public: + /// Standard constructor + DigiHitHistoryDrop(const DigiKernel& krnl, const std::string& nam) + : DigiEventAction(krnl, nam) + { + declareProperty("masks", m_masks); + declareProperty("input", m_input = "inputs"); + InstanceCount::increment(this); + } + + /// Main functional callback + virtual void execute(DigiContext& context) const final { + auto& inputs = context.event->get_segment(m_input); + std::size_t num_drop = 0; + for ( auto& i : inputs ) { + Key key(i.first); + auto im = std::find(m_masks.begin(), m_masks.end(), key.values.mask); + if ( im != m_masks.end() ) { + std::any& obj = i.second; + DepositMapping* m = std::any_cast<DepositMapping>(&obj); + if ( m ) { + for( auto& c : *m ) { + num_drop += c.second.history.size(); + c.second.history.clear(); + } + } + } + } + info("%s+++ Dropped history of %6ld hits", context.event->id(), num_drop); + } + }; + } // End namespace digi +} // End namespace dd4hep + + +#include "DDDigi/DigiFactories.h" +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiHitHistoryDrop) diff --git a/DDDigi/plugins/DigiRandomNoise.cpp b/DDDigi/plugins/DigiRandomNoise.cpp index 93427ae893aa097efbcbc89cc744652349df3e39..a0b013a91ca0b87010793b1769404cea36047b36 100644 --- a/DDDigi/plugins/DigiRandomNoise.cpp +++ b/DDDigi/plugins/DigiRandomNoise.cpp @@ -14,7 +14,7 @@ #define DD4HEP_DDDIGI_DIGIRANDOMNOISE_H // Framework include files -#include "DDDigi/DigiEventAction.h" +#include <DDDigi/DigiEventAction.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 3edc28d41c1fd8d2779bee82646cf5cf8d4fa41e..7b39474324e4e1aebdf58a4326f53015f41fb12b 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -35,7 +35,10 @@ #include "DDDigi/DigiHandle.h" #include "DDDigi/DigiKernel.h" #include "DDDigi/DigiContext.h" +#include "DDDigi/DigiAction.h" #include "DDDigi/DigiSynchronize.h" +#include "DDDigi/DigiEventAction.h" +#include "DDDigi/DigiInputAction.h" #include "DDDigi/DigiActionSequence.h" #include "DDDigi/DigiSignalProcessor.h" @@ -57,11 +60,16 @@ namespace dd4hep { operator dd4hep::digi::Digi##x* () const { return action; } \ Digi##x* operator->() const { return action; } \ Digi##x* get() const { return action; } \ + KernelHandle kernel() const { \ + auto* k = const_cast<DigiKernel*>(action->kernel()); \ + return KernelHandle(k); \ + } \ } ACTIONHANDLE(SignalProcessor); ACTIONHANDLE(Action); ACTIONHANDLE(EventAction); + ACTIONHANDLE(InputAction); ACTIONHANDLE(ActionSequence); ACTIONHANDLE(Synchronize); @@ -81,21 +89,35 @@ namespace dd4hep { H handle(action.get()); return handle; } + static KernelHandle createKernel(DigiAction* action) { + auto* k = const_cast<DigiKernel*>(action->kernel()); + return KernelHandle(k); + } static ActionHandle createAction(KernelHandle& kernel, const std::string& name_type) { return cr<ActionHandle,DigiHandle<DigiAction> >(kernel,name_type); } + static EventActionHandle createEventAction(KernelHandle& kernel, const std::string& name_type) { return cr<EventActionHandle,DigiHandle<DigiEventAction> >(kernel,name_type); } + + static InputActionHandle createInputAction(KernelHandle& kernel, const std::string& name_type) + { return cr<InputActionHandle,DigiHandle<DigiInputAction> >(kernel,name_type); } + static ActionSequenceHandle createSequence(KernelHandle& kernel, const std::string& name_type) { return cr<ActionSequenceHandle,DigiHandle<DigiActionSequence> >(kernel,name_type); } + static SynchronizeHandle createSync(KernelHandle& kernel, const std::string& name_type) { return cr<SynchronizeHandle,DigiHandle<DigiSynchronize> >(kernel,name_type); } static DigiAction* toAction(DigiAction* f) { return f; } + static DigiAction* toAction(DigiEventAction* f) { return f; } + static DigiAction* toAction(DigiInputAction* f) { return f; } static DigiAction* toAction(DigiActionSequence* f) { return f; } static DigiAction* toAction(DigiSynchronize* f) { return f; } static DigiAction* toAction(DigiSignalProcessor* f) { return f; } static DigiAction* toAction(ActionHandle f) { return f.action; } + static DigiAction* toAction(EventActionHandle f) { return f.action; } + static DigiAction* toAction(InputActionHandle f) { return f.action; } static DigiAction* toAction(ActionSequenceHandle f) { return f.action; } static DigiAction* toAction(SynchronizeHandle f) { return f.action; } static DigiAction* toAction(SignalProcessorHandle f) { return f.action; } @@ -154,6 +176,9 @@ using namespace std; #pragma link C++ class dd4hep::digi::DigiEventAction; #pragma link C++ class dd4hep::digi::EventActionHandle; +#pragma link C++ class dd4hep::digi::DigiInputAction; +#pragma link C++ class dd4hep::digi::InputActionHandle; + #pragma link C++ class dd4hep::digi::DigiActionSequence; #pragma link C++ class dd4hep::digi::ActionSequenceHandle; @@ -165,7 +190,7 @@ using namespace std; /// Digi data item wrappers #pragma link C++ class dd4hep::digi::DigiEvent; -#pragma link C++ class dd4hep::digi::DigiEnergyDeposits+; -#pragma link C++ class dd4hep::digi::DigiCounts+; +#pragma link C++ class dd4hep::digi::EnergyDeposit+; +#pragma link C++ class dd4hep::digi::DepositMapping+; #endif diff --git a/DDDigi/python/DDDigi.py b/DDDigi/python/dddigi.py similarity index 55% rename from DDDigi/python/DDDigi.py rename to DDDigi/python/dddigi.py index d78afcff9e4bfa694c840d2b3a9501789de4caf1..f5d111c7aa605e5182f6b024883a4de951929759 100644 --- a/DDDigi/python/DDDigi.py +++ b/DDDigi/python/dddigi.py @@ -9,11 +9,9 @@ # # ========================================================================== from __future__ import absolute_import, unicode_literals -import logging from dd4hep_base import * # noqa: F403 -logger = logging.getLogger(__name__) - +logger = dd4hep_logger('dddigi') def loadDDDigi(): import ROOT @@ -27,27 +25,29 @@ def loadDDDigi(): gSystem.Load("libglapi") ROOT.gErrorIgnoreLevel = orgLevel - import platform import os + import platform if platform.system() == "Darwin": gSystem.SetDynamicPath(os.environ['DD4HEP_LIBRARY_PATH']) result = gSystem.Load("libDDDigiPlugins") if result < 0: raise Exception('DDDigi.py: Failed to load the DDDigi library libDDDigiPlugins: ' + gSystem.GetErrorStr()) + logger.info('DDDigi.py: Successfully loaded DDDigi plugin library libDDDigiPlugins!') + result = gSystem.Load("libDDG4Plugins") + if result < 0: + raise Exception('DDDigi.py: Failed to load the DDG4 library libDDG4Plugins: ' + gSystem.GetErrorStr()) + logger.info('DDDigi.py: Successfully loaded DDG4 plugin library libDDG4Plugins!') from ROOT import dd4hep as module return module - # We are nearly there .... current = __import__(__name__) - def _import_class(ns, nam): scope = getattr(current, ns) setattr(current, nam, getattr(scope, nam)) - # --------------------------------------------------------------------------- # try: @@ -63,29 +63,24 @@ core = dd4hep digi = dd4hep.digi Kernel = digi.KernelHandle Interface = digi.DigiActionCreation -Detector = core.Detector +Detector = core.Detector # # # --------------------------------------------------------------------------- - - def _constant(self, name): return self.constantAsString(name) - Detector.globalVal = _constant # --------------------------------------------------------------------------- """ - Import the Detector constants into the DDDigi namespace + Import the Detector constants into the dddigi namespace """ - - def importConstants(description, namespace=None, debug=False): ns = current if namespace is not None and not hasattr(current, namespace): import imp - m = imp.new_module('DDDigi.' + namespace) + m = imp.new_module('dddigi.' + namespace) setattr(current, namespace, m) ns = m evaluator = dd4hep.g4Evaluator() @@ -126,8 +121,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: @@ -140,8 +133,6 @@ def _getKernelProperty(self, name): raise KeyError(msg) # --------------------------------------------------------------------------- - - def _setKernelProperty(self, name, value): if Interface.setPropertyKernel(self.get(), str(name), str(value)): return @@ -149,8 +140,6 @@ def _setKernelProperty(self, name, value): raise KeyError(msg) # --------------------------------------------------------------------------- - - def _kernel_terminate(self): return self.get().terminate() @@ -162,8 +151,6 @@ Kernel.terminate = _kernel_terminate # --------------------------------------------------------------------------- ActionHandle = digi.ActionHandle # --------------------------------------------------------------------------- - - def Action(kernel, nam, parallel=False): obj = Interface.createAction(kernel, str(nam)) obj.parallel = parallel @@ -204,23 +191,13 @@ def _setup(obj): def _adopt(self, action): self.__adopt(action.get()) _import_class('digi', obj) - o = getattr(current, obj) - setattr(o, '__adopt', getattr(o, 'adopt')) - setattr(o, 'adopt', _adopt) - # setattr(o,'add',_adopt) - - -# --------------------------------------------------------------------------- -_setup('DigiActionSequence') -_setup('DigiSynchronize') -_import_class('digi', 'DigiKernel') -_import_class('digi', 'DigiContext') -_import_class('digi', 'DigiAction') - + cls = getattr(current, obj) + setattr(cls, '__adopt', getattr(cls, 'adopt')) + setattr(cls, 'adopt', _adopt) + # setattr(cls,'add',_adopt) + return cls -# --------------------------------------------------------------------------- def _get(self, name): - # import traceback a = Interface.toAction(self) ret = Interface.getProperty(a, name) if ret.status > 0: @@ -229,188 +206,55 @@ def _get(self, name): return getattr(self.action, name) elif hasattr(a, name): return getattr(a, name) - # elif hasattr(self,name): - # return getattr(self,name) - # traceback.print_stack() - msg = 'DigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name + msg = 'DDDigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name raise KeyError(msg) - def _set(self, name, value): + """This function is called when properties are passed to the c++ objects.""" a = Interface.toAction(self) - if Interface.setProperty(a, name, str(value)): + name = unicode_2_string(name) + value = unicode_2_string(value) + if Interface.setProperty(a, name, value): return - msg = 'DigiAction::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + str(value) + msg = 'DDDigiAction::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + value raise KeyError(msg) - -def _props(obj): +def _props(obj, **extensions): _import_class('digi', obj) - cl = getattr(current, obj) - cl.__getattr__ = _get - cl.__setattr__ = _set + cls = getattr(current, obj) + for extension in extensions.items(): + setattr(cls, extension[0], extension[1]) + cls.__getattr__ = _get + cls.__setattr__ = _set + return cls +_setup('DigiActionSequence') +_setup('DigiSynchronize') + +_import_class('digi', 'DigiKernel') +_import_class('digi', 'DigiContext') +_import_class('digi', 'DigiAction') +_import_class('digi', 'DigiEventAction') +_import_class('digi', 'DigiInputAction') _props('ActionHandle') +_props('EventActionHandle') +_props('InputActionHandle') _props('ActionSequenceHandle') _props('SynchronizeHandle') -""" - Helper object to perform stuff, which occurs very often. - I am sick of typing the same over and over again. - Hence, I grouped often used python fragments to this small - class to re-usage. - - Long live laziness! - - - \author M.Frank - \version 1.0 - -""" - - -class Digitize: - def __init__(self, kernel=None): - kernel.printProperties() - self._kernel = kernel - if kernel is None: - self._kernel = Kernel() - self.description = self._kernel.detectorDescription() - - """ - Access the worker kernel object. - - \author M.Frank - """ - - def kernel(self): - return self._kernel - - """ - Execute the Geant 4 program with all steps. - - \author M.Frank - """ - - def execute(self): - self.kernel().configure() - self.kernel().initialize() - self.kernel().run() - self.kernel().terminate() - return self - - def activeDetectors(self): - detectors = [] - for i in self.description.detectors(): - o = DetElement(i.second.ptr()) # noqa: F405 - sd = self.description.sensitiveDetector(o.name()) - if sd.isValid(): - d = {'name': o.name(), 'type': sd.type(), 'detector': o, 'sensitive': sd} - detectors.append(d) - return detectors - - def printDetectors(self): - logger.info('+++ List of sensitive detectors:') - dets = self.activeDetectors() - for d in dets: - logger.info('+++ %-32s ---> type:%-12s', d['name'], d['type']) - - def setupDetector(self, name, collections=None, modules=None): - seq = ActionSequence(self.kernel(), 'DigiActionSequence/' + name) - actions = [] - if isinstance(modules, tuple) or isinstance(modules, list): - for m in modules: - if isinstance(m, str): - a = Action(self.kernel(), m) - actions.append(a) - elif isinstance(m, tuple) or isinstance(m, list): - a = Action(self.kernel(), m[0]) - actions.append(a) - if len(m) > 1: - params = m[1] - for k, v in params.items(): - setattr(a, k, v) - else: - actions.append(m) - for a in actions: - seq.adopt(a) - return (seq, actions) - - """ - Configure ROOT output for the event digitization - - \author M.Frank - """ - - def setupROOTOutput(self, name, output, mc_truth=True): - evt_root = EventAction(self.kernel(), 'DigiOutput2ROOT/' + name, True) # noqa: F405 - evt_root.HandleMCTruth = mc_truth - evt_root.Control = True - if not output.endswith('.root'): - output = output + '.root' - evt_root.Output = output - evt_root.enableUI() - self.kernel().eventAction().add(evt_root) - return evt_root - - """ - Generic build of the input stage with multiple input modules. - - Actions executed are: - 1) Register Generation initialization action - 2) Append all modules to build the complete input record - These modules are readers/particle sources, boosters and/or smearing actions. - 3) Merge all existing interaction records - 4) Add the MC truth handler - - \author M.Frank - """ - - def buildInputStage(self, generator_input_modules, output_level=None, have_mctruth=True): - ga = self.kernel().generatorAction() - # Register Generation initialization action - gen = GeneratorAction(self.kernel(), "DigiGeneratorActionInit/GenerationInit") # noqa: F405 - if output_level is not None: - gen.OutputLevel = output_level - ga.adopt(gen) - - # Now append all modules to build the complete input record - # These modules are readers/particle sources, boosters and/or smearing actions - for gen in generator_input_modules: - gen.enableUI() - if output_level is not None: - gen.OutputLevel = output_level - ga.adopt(gen) - - # Merge all existing interaction records - gen = GeneratorAction(self.kernel(), "DigiInteractionMerger/InteractionMerger") # noqa: F405 - gen.enableUI() - if output_level is not None: - gen.OutputLevel = output_level - ga.adopt(gen) - - # Finally generate Digi primaries - if have_mctruth: - gen = GeneratorAction(self.kernel(), "DigiPrimaryHandler/PrimaryHandler") # noqa: F405 - gen.RejectPDGs = "{1,2,3,4,5,6,21,23,24}" - gen.enableUI() - if output_level is not None: - gen.OutputLevel = output_level - ga.adopt(gen) - # Puuuhh! All done. - return self - - """ - Execute the main Digi action - \author M.Frank - """ - - def run(self): - # self.kernel().configure() - # self.kernel().initialize() - # self.kernel().run() - # self.kernel().terminate() - from ROOT import PyDDDigi - PyDDDigi.run(self.kernel().get()) - return self +def adopt_sequence_action(self, name, **options): + kernel = Interface.createKernel(Interface.toAction(self)) + action = EventAction(kernel, name) + for option in options.items(): + setattr(action, option[0], option[1]) + self.adopt(action) + return action + +_props('DigiSynchronize') +_props('DigiActionSequence', adopt_action = adopt_sequence_action) +_props('DigiParallelActionSequence', adopt_action = adopt_sequence_action) +_props('DigiSequentialActionSequence', adopt_action = adopt_sequence_action) + +import digitize +Digitize = digitize.Digitize diff --git a/DDDigi/python/digitize.py b/DDDigi/python/digitize.py new file mode 100644 index 0000000000000000000000000000000000000000..a6511e30910cab6ac63f1610fe20b70ad67a96f0 --- /dev/null +++ b/DDDigi/python/digitize.py @@ -0,0 +1,201 @@ +# ========================================================================== +# 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. +# +# ========================================================================== +import dd4hep +import dddigi + +""" + Helper object to perform stuff, which occurs very often. + I am sick of typing the same over and over again. + Hence, I grouped often used python fragments to this small + class to re-usage. + + Long live laziness! + + + \author M.Frank + \version 1.0 + + #import pdb + #pdb.set_trace() + +""" +class Digitize(dd4hep.Logger): + def __init__(self, kernel=None): + dd4hep.Logger.__init__(self, 'dddigi') + self._kernel = kernel + self._main_processor = None + self._input_processor = None + self._event_processor = None + self._parallel = True + self.description = self._kernel.detectorDescription() + + """ + Access the worker kernel object. + + \author M.Frank + """ + + def kernel(self): + return self._kernel + + def main_sequencer(self): + if not self._main_processor: + self._main_processor = dddigi.Synchronize(self._kernel, 'DigiSynchronize/MainDigitizer', self._parallel) + self._main_processor.parallel = self._parallel + return self._main_processor + + def new_action(self, name, **options): + action = dddigi.EventAction(self._kernel, name) + for option in options.items(): + setattr(action, option[0], option[1]) + return action + + def input_action(self, name=None, **options): + """ + Append a new action to the kernel's main input action sequence + """ + if not self._input_processor: + self._input_processor = self._kernel.inputAction() + self._input_processor.parallel = self._parallel + + if not name: + return self._input_processor + + act = self.new_action(name, **options) + self._input_processor.adopt(act) + return act + + def event_action(self, name=None, **options): + """ + Append a new action to the kernel's main event action sequence + """ + if not self._event_processor: + self._event_processor = self._kernel.eventAction() + self._event_processor.parallel = self._parallel + + if not name: + return self._event_processor + + action = self.new_action(name, **options) + self._event_processor.adopt(action) + return action + + def output_action(self, name=None, **options): + """ + Append a new action to the kernel's main output action sequence + """ + if not self._output_processor: + self._output_processor = self._kernel.outputAction() + self._output_processor.parallel = self._parallel + + if not name: + return self._output_processor + + act = self.new_action(name, **options) + self._output_processor.adopt(act) + return act + + def events_done(self): + """ + Access the number of events which finished processing + """ + return self.kernel().events_done() + + def events_submitted(self): + """ + Access the number of submitted events + """ + return self.kernel().events_submitted() + + def events_processing(self): + """ + Access the currently number of processing events (events in-flight) + """ + return self.kernel().events_processing() + + + + """ + Execute the Geant 4 program with all steps. + + \author M.Frank + """ + def execute(self): + self.kernel().configure() + self.kernel().initialize() + self.kernel().run() + self.kernel().terminate() + return self + + def activeDetectors(self): + detectors = [] + for i in self.description.detectors(): + o = DetElement(i.second.ptr()) # noqa: F405 + sd = self.description.sensitiveDetector(o.name()) + if sd.isValid(): + d = {'name': o.name(), 'type': sd.type(), 'detector': o, 'sensitive': sd} + detectors.append(d) + return detectors + + def printDetectors(self): + logger.info('+++ List of sensitive detectors:') + dets = self.activeDetectors() + for d in dets: + logger.info('+++ %-32s ---> type:%-12s', d['name'], d['type']) + + def setupDetector(self, name, collections=None, modules=None): + seq = ActionSequence(self.kernel(), 'DigiActionSequence/' + name) + actions = [] + if isinstance(modules, tuple) or isinstance(modules, list): + for m in modules: + if isinstance(m, str): + a = Action(self.kernel(), m) + actions.append(a) + elif isinstance(m, tuple) or isinstance(m, list): + a = Action(self.kernel(), m[0]) + actions.append(a) + if len(m) > 1: + params = m[1] + for k, v in params.items(): + setattr(a, k, v) + else: + actions.append(m) + for a in actions: + seq.adopt(a) + return (seq, actions) + + """ + Configure ROOT output for the event digitization + + \author M.Frank + """ + def setupROOTOutput(self, name, output, mc_truth=True): + evt_root = EventAction(self.kernel(), 'DigiOutput2ROOT/' + name, True) # noqa: F405 + evt_root.HandleMCTruth = mc_truth + evt_root.Control = True + if not output.endswith('.root'): + output = output + '.root' + evt_root.Output = output + evt_root.enableUI() + self.kernel().eventAction().add(evt_root) + return evt_root + + """ + Execute the main Digi action + \author M.Frank + """ + def run(self, num_events, num_threads, parallel): + krnl = self.kernel() + krnl.numEvents = num_events + krnl.numThreads = num_threads # = number of concurrent threads + krnl.maxEventsParallel = parallel + krnl.run() + return krnl.events_done() diff --git a/DDDigi/src/DigiAction.cpp b/DDDigi/src/DigiAction.cpp index 401e27fe8e95ece6924295e8839954997ea20e2d..4e1aaee7ab5492ed41a7c64bb8c7440d94fc6cee 100644 --- a/DDDigi/src/DigiAction.cpp +++ b/DDDigi/src/DigiAction.cpp @@ -12,33 +12,31 @@ //========================================================================== // Framework include files -#include "DD4hep/Printout.h" -#include "DD4hep/InstanceCount.h" -#include "DDDigi/DigiAction.h" +#include <DD4hep/Printout.h> +#include <DD4hep/InstanceCount.h> +#include <DDDigi/DigiAction.h> // C/C++ include files #include <algorithm> -using namespace std; -using namespace dd4hep; using namespace dd4hep::digi; -TypeName TypeName::split(const string& type_name, const string& delim) { - size_t idx = type_name.find(delim); - string typ = type_name, nam = type_name; - if (idx != string::npos) { +TypeName TypeName::split(const std::string& type_name, const std::string& delim) { + std::size_t idx = type_name.find(delim); + std::string typ = type_name, nam = type_name; + if (idx != std::string::npos) { typ = type_name.substr(0, idx); nam = type_name.substr(idx + 1); } return TypeName(typ, nam); } -TypeName TypeName::split(const string& type_name) { +TypeName TypeName::split(const std::string& type_name) { return split(type_name,"/"); } /// Standard constructor -DigiAction::DigiAction(const DigiKernel& krnl, const string& nam) +DigiAction::DigiAction(const DigiKernel& krnl, const std::string& nam) : m_kernel(krnl), m_name(nam), m_outputLevel(INFO) { InstanceCount::increment(this); @@ -69,25 +67,25 @@ long DigiAction::release() { } /// Set the output level; returns previous value -PrintLevel DigiAction::setOutputLevel(PrintLevel new_level) { +dd4hep::PrintLevel DigiAction::setOutputLevel(PrintLevel new_level) { int old = m_outputLevel; m_outputLevel = new_level; return (PrintLevel)old; } /// Check property for existence -bool DigiAction::hasProperty(const string& nam) const { +bool DigiAction::hasProperty(const std::string& nam) const { return m_properties.exists(nam); } /// Access single property -Property& DigiAction::property(const string& nam) { +dd4hep::Property& DigiAction::property(const std::string& nam) { return properties()[nam]; } /// Support for messages with variable output level using output level void DigiAction::print(const char* fmt, ...) const { - int level = max(int(outputLevel()),(int)VERBOSE); + int level = std::max(int(outputLevel()),(int)VERBOSE); if ( level >= printLevel() ) { va_list args; va_start(args, fmt); @@ -98,7 +96,7 @@ void DigiAction::print(const char* fmt, ...) const { /// Support for messages with variable output level using output level-1 void DigiAction::printM1(const char* fmt, ...) const { - int level = max(outputLevel()-1,(int)VERBOSE); + int level = std::max(outputLevel()-1,(int)VERBOSE); if ( level >= printLevel() ) { va_list args; va_start(args, fmt); @@ -109,7 +107,7 @@ void DigiAction::printM1(const char* fmt, ...) const { /// Support for messages with variable output level using output level-2 void DigiAction::printM2(const char* fmt, ...) const { - int level = max(outputLevel()-2,(int)VERBOSE); + int level = std::max(outputLevel()-2,(int)VERBOSE); if ( level >= printLevel() ) { va_list args; va_start(args, fmt); @@ -120,7 +118,7 @@ void DigiAction::printM2(const char* fmt, ...) const { /// Support for messages with variable output level using output level-1 void DigiAction::printP1(const char* fmt, ...) const { - int level = min(outputLevel()+1,(int)FATAL); + int level = std::min(outputLevel()+1,(int)FATAL); if ( level >= printLevel() ) { va_list args; va_start(args, fmt); @@ -131,7 +129,7 @@ void DigiAction::printP1(const char* fmt, ...) const { /// Support for messages with variable output level using output level-2 void DigiAction::printP2(const char* fmt, ...) const { - int level = min(outputLevel()+2,(int)FATAL); + int level = std::min(outputLevel()+2,(int)FATAL); if ( level >= printLevel() ) { va_list args; va_start(args, fmt); @@ -140,6 +138,15 @@ void DigiAction::printP2(const char* fmt, ...) const { } } +/// 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 of debug messages. void DigiAction::debug(const char* fmt, ...) const { va_list args; @@ -193,10 +200,10 @@ void DigiAction::fatal(const char* fmt, ...) const { void DigiAction::except(const char* fmt, ...) const { va_list args; va_start(args, fmt); - string err = dd4hep::format(m_name, fmt, args); + std::string err = dd4hep::format(m_name, fmt, args); dd4hep::printout(dd4hep::FATAL, m_name, err.c_str()); va_end(args); - throw runtime_error(err); + throw std::runtime_error(err); } /// Optional action initialization if required diff --git a/DDDigi/src/DigiActionSequence.cpp b/DDDigi/src/DigiActionSequence.cpp index b98370dcf4d598a25fe4dc94b777df9e9eff9312..b705e4953ff8841088ecb3e6c507ae84d126e64f 100644 --- a/DDDigi/src/DigiActionSequence.cpp +++ b/DDDigi/src/DigiActionSequence.cpp @@ -45,6 +45,32 @@ void DigiActionSequence::execute(DigiContext& context) const { m_begin(&context); this->DigiSynchronize::execute(context); debug("+++ Event: %8d (DigiActionSequence) Parallel: %s Done.", - context.event().eventNumber, yes_no(m_parallel)); + context.event->eventNumber, yes_no(m_parallel)); m_end(&context); } + +/// Standard constructor +DigiSequentialActionSequence::DigiSequentialActionSequence(const DigiKernel& kernel, const string& nam) + : DigiActionSequence(kernel, nam) +{ + this->m_parallel = false; + InstanceCount::increment(this); +} + +/// Default destructor +DigiSequentialActionSequence::~DigiSequentialActionSequence() { + InstanceCount::decrement(this); +} + +/// Standard constructor +DigiParallelActionSequence::DigiParallelActionSequence(const DigiKernel& kernel, const string& nam) + : DigiActionSequence(kernel, nam) +{ + this->m_parallel = true; + InstanceCount::increment(this); +} + +/// Default destructor +DigiParallelActionSequence::~DigiParallelActionSequence() { + InstanceCount::decrement(this); +} diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5d4065d53302337c98e32d27eaa5aaba3399dd2 --- /dev/null +++ b/DDDigi/src/DigiContainerCombine.cpp @@ -0,0 +1,194 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" + +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiContainerCombine.h" + +using dd4hep::digi::DigiContainerCombine; + +class DigiContainerCombine::internals_t { +public: + /// Property: Container names to be loaded + std::vector<std::string> containers { }; + /// Property: event masks to be handled + std::vector<int> masks { }; + /// Property: Output container dressing + std::string output_name_flag; + /// Property: Input data segment name + std::string input; + /// Property: Output data segment name + std::string output; + /// Property: mask of the deposit + int deposit_mask { 0 }; + /// Property: Flag to erase already combined containers (not thread-safe!!!) + bool erase_combined { false }; + + /// Fully qualified keys of all containers to be manipulated + std::set<Key::key_type> keys { }; + /// Container keys of all containers to be manipulated + std::set<Key::key_type> cont_keys { }; + /// Predicate function to select containers for merging + std::function<bool(Key::key_type)> container_selector; + /// Flag to check the initialization + bool inited { false }; + /// Initializing function: compute values which depend on properties + void initialize(DigiContext& context) { + if ( !this->inited ) { + std::lock_guard<std::mutex> lock(context.initializer_lock()); + if ( !this->inited ) { + this->inited = true; + + this->container_selector = [this](Key::key_type k) { + const auto& m = this->masks; + bool use = m.empty() || this->keys.empty(); + if ( !use ) { + use = std::find(m.begin(), m.end(), Key::mask(k)) != m.end(); + if ( !use ) { + return this->cont_keys.find(Key::item(k)) != this->cont_keys.end(); + } + } + return true; + }; + for ( const auto& c : this->containers ) { + Key key(0x0, c); + this->cont_keys.emplace(key.key); + if ( this->masks.empty() ) { + this->keys.emplace(key.key); + continue; + } + for ( int m : this->masks ) { + key.values.mask = m; + this->keys.emplace(key.key); + } + } + } + } + } +}; + +/// Standard constructor +dd4hep::digi::DigiContainerCombine::DigiContainerCombine(const DigiKernel& krnl, const std::string& nam) + : DigiEventAction(krnl, nam) +{ + this->internals = std::make_unique<internals_t>(); + this->declareProperty("containers", this->internals->containers); + this->declareProperty("masks", this->internals->masks); + this->declareProperty("input_segment", this->internals->input = "inputs"); + this->declareProperty("output_segment", this->internals->output = "deposits"); + this->declareProperty("deposit_mask", this->internals->deposit_mask); + this->declareProperty("output_name_flag", this->internals->output_name_flag); + this->declareProperty("erase_combined", this->internals->erase_combined); + InstanceCount::increment(this); +} + +/// Default destructor +dd4hep::digi::DigiContainerCombine::~DigiContainerCombine() { + InstanceCount::decrement(this); +} + +/// Combine selected containers to one single deposit container +template <typename PREDICATE> std::size_t +dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event, + DigiEvent::container_map_t& inputs, + DigiEvent::container_map_t& outputs, + const PREDICATE& predicate) const +{ + std::size_t cnt_depos = 0; + std::size_t cnt_parts = 0; + std::size_t cnt_conts = 0; + std::vector<Key::key_type> to_erase; + + for( auto& i : inputs ) { + if ( predicate(i.first) ) { + Key depo_key(i.first); + Key input_key(i.first); + DepositMapping* din = std::any_cast<DepositMapping>(&i.second); + if ( din ) { + depo_key.values.mask = internals->deposit_mask; + cnt_depos += din->size(); + cnt_conts++; + auto iter = outputs.find(depo_key.key); + if ( iter == outputs.end() ) { + this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits", + event.id(), din->name.c_str(), depo_key.values.mask, + input_key.values.mask, din->size()); + if ( !internals->output_name_flag.empty() ) { + din->name = din->name+"/"+internals->output_name_flag; + } + outputs.emplace(depo_key.key, std::move(i.second)); + to_erase.emplace_back(i.first); + continue; + } + DepositMapping* out = std::any_cast<DepositMapping>(&iter->second); + std::size_t cnt = out->merge(std::move(*din)); + this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits", + event.id(), out->name.c_str(), depo_key.values.mask, + input_key.values.mask, cnt); + i.second.reset(); + to_erase.emplace_back(i.first); + continue; + } + ParticleMapping* pin = std::any_cast<ParticleMapping>(&i.second); + if ( pin ) { + depo_key.values.mask = internals->deposit_mask; + cnt_parts += pin->size(); + cnt_conts++; + auto iter = outputs.find(depo_key.key); + if ( iter == outputs.end() ) { + this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles", + event.id(), pin->name.c_str(), depo_key.values.mask, + input_key.values.mask, pin->size()); + if ( !internals->output_name_flag.empty() ) { + pin->name = pin->name+"/"+internals->output_name_flag; + } + outputs.emplace(depo_key.key, std::move(i.second)); + to_erase.emplace_back(i.first); + continue; + } + ParticleMapping* out = std::any_cast<ParticleMapping>(&iter->second); + std::size_t cnt = out->merge(std::move(*pin)); + this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles", + event.id(), out->name.c_str(), depo_key.values.mask, + input_key.values.mask, cnt); + i.second.reset(); + to_erase.emplace_back(i.first); + continue; + } + } + } + if ( this->internals->erase_combined ) { + for(auto key : to_erase) { + auto iter = inputs.find(key); + if ( iter != inputs.end() ) { + inputs.erase(iter); + } + } + } + this->info("%s+++ Merged %ld particles and %ld deposits from %ld containers", + event.id(), cnt_parts, cnt_depos, cnt_conts); + return cnt_depos; +} + +/// Main functional callback +void dd4hep::digi::DigiContainerCombine::execute(DigiContext& context) const { + this->internals->initialize(context); + auto& event = *context.event; + auto& inputs = event.get_segment(this->internals->input); + auto& outputs = event.get_segment(this->internals->output); + auto& selector = this->internals->container_selector; + this->combine_containers(event, inputs, outputs, selector); +} diff --git a/DDDigi/src/DigiContext.cpp b/DDDigi/src/DigiContext.cpp index 3575def8f6db8c9b8051e87658bf418401fdb415..84f659f49a2519268c37e5555b51daf1a284a665 100644 --- a/DDDigi/src/DigiContext.cpp +++ b/DDDigi/src/DigiContext.cpp @@ -12,25 +12,20 @@ //========================================================================== // Framework include files -#include "DD4hep/Printout.h" -#include "DD4hep/InstanceCount.h" -#include "DDDigi/DigiContext.h" -#include "DDDigi/DigiKernel.h" +#include <DD4hep/Printout.h> +#include <DD4hep/InstanceCount.h> +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiKernel.h> // C/C++ include files #include <algorithm> -using namespace std; -using namespace dd4hep; using namespace dd4hep::digi; /// Default constructor -DigiContext::DigiContext(const DigiKernel* k, DigiEvent* e) - : m_kernel(k), m_event(e) +DigiContext::DigiContext(const DigiKernel& k, std::unique_ptr<DigiEvent>&& e) + : kernel(k), event(std::move(e)) { - if ( !m_kernel ) { - except("DigiContext","Cannot initialize Digitization context with invalid DigiKernel!"); - } InstanceCount::increment(this); } @@ -40,40 +35,43 @@ DigiContext::~DigiContext() { InstanceCount::decrement(this); } -/// Set the geant4 event reference -void DigiContext::setEvent(DigiEvent* new_event) { - m_event = new_event; +/// Have a shared initializer lock +std::mutex& DigiContext::initializer_lock() const { + return kernel.initializer_lock(); } -/// Access the geant4 event -- valid only between BeginEvent() and EndEvent()! -DigiEvent& DigiContext::event() const { - if ( m_event ) return *m_event; - invalidHandleError<DigiEvent>(); - return *m_event; +/// Have a global I/O lock (e.g. for ROOT) +std::mutex& DigiContext::global_io_lock() const { + return kernel.global_io_lock(); +} + +/// Have a global output log lock +std::mutex& DigiContext::global_output_lock() const { + return kernel.global_output_lock(); } /// Access to detector description -Detector& DigiContext::detectorDescription() const { - return m_kernel->detectorDescription(); +dd4hep::Detector& DigiContext::detectorDescription() const { + return kernel.detectorDescription(); } /// Generic framework access DigiContext::UserFramework& DigiContext::userFramework() const { - return m_kernel->userFramework(); + return kernel.userFramework(); } /// Access to the main input action sequence from the kernel object DigiActionSequence& DigiContext::inputAction() const { - return m_kernel->inputAction(); + return kernel.inputAction(); } /// Access to the main event action sequence from the kernel object DigiActionSequence& DigiContext::eventAction() const { - return m_kernel->eventAction(); + return kernel.eventAction(); } /// Access to the main output action sequence from the kernel object DigiActionSequence& DigiContext::outputAction() const { - return m_kernel->outputAction(); + return kernel.outputAction(); } diff --git a/DDDigi/src/DigiDDG4Input.cpp b/DDDigi/src/DigiDDG4Input.cpp deleted file mode 100644 index c39ed2ba1c4c753945bf6dc109f181d6550d154d..0000000000000000000000000000000000000000 --- a/DDDigi/src/DigiDDG4Input.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== - -// Framework include files -#include "DD4hep/InstanceCount.h" -#include "DDDigi/DigiDDG4Input.h" - -// C/C++ include files -#include <stdexcept> -#include <unistd.h> - -using namespace std; -using namespace dd4hep::digi; - -/// Standard constructor -DigiDDG4Input::DigiDDG4Input(const DigiKernel& kernel, const string& nam) - : DigiInputAction(kernel, nam) -{ - InstanceCount::increment(this); -} - -/// Default destructor -DigiDDG4Input::~DigiDDG4Input() { - InstanceCount::decrement(this); -} - -/// Pre-track action callback -void DigiDDG4Input::execute(DigiContext& /* context */) const { - ::sleep(1); - info("+++ Virtual method execute()"); - return; - //except("DigiDDG4Input","+++ Virtual method execute() MUST be overloaded!"); -} diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index dc70a2aef7e18ae626e6a323b4b2fa614e2da993..b3586757e2f6983a8bc79d1a2650ef4af10d94bc 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -21,61 +21,167 @@ // C/C++ include files #include <mutex> -using namespace std; -using namespace dd4hep; -using namespace dd4hep::digi; +namespace { + struct digi_keys { + std::mutex lock; + std::map<unsigned long, std::string> map; + }; + digi_keys& keys() { + static digi_keys k; + return k; + } +} -Key::Key() { - key = 0; +dd4hep::digi::Key::Key() { + this->key = 0; } -Key::Key(const Key& copy) { - key = copy.key; +dd4hep::digi::Key::Key(const Key& copy) { + this->key = copy.key; } -Key::Key(mask_type mask, itemkey_type item) { - key = 0; - values.mask = mask; - values.item = item; +dd4hep::digi::Key::Key(key_type full_mask) { + this->key = full_mask; } -Key::Key(mask_type mask, const std::string& item) { - key = 0; - values.mask = mask; - values.item = detail::hash32(item); +dd4hep::digi::Key::Key(mask_type mask, const std::string& item) { + auto& _k = keys(); + this->key = 0; + this->values.mask = mask; + this->values.item = detail::hash32(item); + std::lock_guard<std::mutex> lock(_k.lock); + _k.map[key] = item; } -Key& Key::operator=(const Key& copy) { - key = copy.key; +dd4hep::digi::Key& dd4hep::digi::Key::operator=(const Key& copy) { + this->key = copy.key; return *this; } -void Key::set(const std::string& name, int mask) { - static std::mutex mtx; - std::lock_guard<std::mutex> lock(mtx); +void dd4hep::digi::Key::set(const std::string& name, int mask) { + auto& _k = keys(); if ( name.empty() ) { + std::lock_guard<std::mutex> lock(_k.lock); except("DDDigi::Key", "+++ No key name was specified -- this is illegal!"); } - values.mask = (unsigned char)(0xFF&mask); - values.item = detail::hash32(name); + this->values.mask = (unsigned char)(0xFF&mask); + this->values.item = detail::hash32(name); + std::lock_guard<std::mutex> lock(_k.lock); + _k.map[this->key] = name; +} + +/// Access key name (if registered properly) +std::string dd4hep::digi::Key::key_name(const Key& k) { + auto& _k = keys(); + std::lock_guard<std::mutex> lock(_k.lock); + std::map<unsigned long, std::string>::const_iterator it = _k.map.find(k.key); + if ( it != _k.map.end() ) return it->second; + Key kk; + kk.values.item = ~0x0; + for( const auto& e : _k.map ) { + if ( (e.first & kk.key) == k.values.item ) + return e.second; + } + return "UNKNOWN"; +} + +/// Merge new deposit map onto existing map +std::size_t dd4hep::digi::DepositMapping::merge(DepositMapping&& updates) { + std::size_t update_size = updates.size(); + for( auto& c : updates ) { + CellID cell = c.first; + EnergyDeposit& depo = c.second; + auto iter = this->find(cell); + if ( iter == this->end() ) { + this->emplace(cell, std::move(depo)); + continue; + } + auto& to_update = iter->second; + to_update.deposit += depo.deposit; + to_update.history.insert(to_update.history.end(), depo.history.begin(), depo.history.end()); + } + return update_size; +} + +/// Merge new deposit map onto existing map +std::size_t dd4hep::digi::ParticleMapping::merge(ParticleMapping&& updates) { + std::size_t update_size = updates.size(); + for( ParticleMapping::value_type& c : updates ) { + Particle part(std::move(c.second)); + this->push(c.first, std::move(part)); + } + return update_size; +} + +void dd4hep::digi::ParticleMapping::push(Key::key_type k, Particle&& part) { + auto ret = this->emplace(k, std::move(part)).second; + if ( !ret ) { + Key key(k); + except("ParticleMapping","Error in particle map. Duplicate ID: mask:%04X Number:%d", + key.values.mask, key.values.item); + } } /// Intializing constructor -DigiEvent::DigiEvent() +dd4hep::digi::DigiEvent::DigiEvent() : ObjectExtensions(typeid(DigiEvent)) { InstanceCount::increment(this); } /// Intializing constructor -DigiEvent::DigiEvent(int ev_num) +dd4hep::digi::DigiEvent::DigiEvent(int ev_num) : ObjectExtensions(typeid(DigiEvent)), eventNumber(ev_num) { + char text[32]; + ::snprintf(text, sizeof(text), "Ev:%06d ", ev_num); + m_id = text; InstanceCount::increment(this); } /// Default destructor -DigiEvent::~DigiEvent() +dd4hep::digi::DigiEvent::~DigiEvent() { InstanceCount::decrement(this); } + +/// Retrieve data segment from the event structure +dd4hep::digi::DigiEvent::container_map_t& +dd4hep::digi::DigiEvent::get_segment(const std::string& name) { + switch(::toupper(name[0])) { + case 'I': + return this->inputs; + case 'D': + return this->deposits; + case 'O': + return this->data; + } + throw std::runtime_error("Invalid segment name: "+name); +} + +/// Add item by key to the data +bool dd4hep::digi::DigiEvent::put_data(unsigned long key, std::any&& object) { + std::lock_guard<std::mutex> lock(m_lock); + bool ret = data.emplace(key,object).second; + if ( ret ) return ret; + + std::string name = Key::key_name(key); + uint32_t mask = Key::mask(key); + except("DigiEvent","%s+++ Invalid requested to store object in data container [key present]." + " Key:%ld [Mask:%04X, name:%s]", this->id(), key, mask, name.c_str()); + throw std::runtime_error("DigiEvent"); // Will never get here! +} + +/// Add item by key to the data +bool dd4hep::digi::DigiEvent::put_input(unsigned long key, std::any&& object) { + std::lock_guard<std::mutex> lock(m_lock); + bool ret = inputs.emplace(key,object).second; + if ( ret ) return ret; + + std::string name = Key::key_name(key); + uint32_t mask = Key::mask(key); + except("DigiEvent","%s+++ Invalid requested to store object in input container [key present]." + " Key:%ld [Mask:%04X, name:%s]", this->id(), key, mask, name.c_str()); + throw std::runtime_error("DigiEvent"); // Will never get here! +} + diff --git a/DDDigi/src/DigiHandle.cpp b/DDDigi/src/DigiHandle.cpp index 4dc7bf3eb37eecfa37609e226af4bd7fd492f295..2b6156331ef7416c074341d76583873b4ac54be9 100644 --- a/DDDigi/src/DigiHandle.cpp +++ b/DDDigi/src/DigiHandle.cpp @@ -18,6 +18,7 @@ #include "DDDigi/DigiHandle.h" #include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiInputAction.h" #include "DDDigi/DigiEventAction.h" #include "DDDigi/DigiSignalProcessor.h" @@ -62,12 +63,15 @@ namespace dd4hep { DigiEventAction* object = PluginService::Create<DigiEventAction*>(t, &kernel, n); return object ? dynamic_cast<T*>(object) : nullptr; } + template <> DigiAction* _raw_create<DigiAction>(const std::string& t, const DigiKernel& kernel, const std::string& n) { return PluginService::Create<DigiAction*>(t, &kernel, n); } + template <> DigiSignalProcessor* _raw_create<DigiSignalProcessor>(const std::string& t, const DigiKernel& kernel, const std::string& n) { return PluginService::Create<DigiSignalProcessor*>(t, &kernel, n); } + template <typename TYPE> TYPE* _create_object(const DigiKernel& kernel, const TypeName& typ) { TYPE* object = _raw_create<TYPE>(typ.first, kernel, typ.second); if (!object && typ.first == typ.second) { @@ -177,6 +181,7 @@ namespace dd4hep { KernelHandle::KernelHandle() { value = &DigiKernel::instance(Detector::getInstance()); } + KernelHandle::KernelHandle(DigiKernel* k) : value(k) { } } @@ -190,6 +195,7 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { template class DigiHandle<DigiAction>; + template class DigiHandle<DigiInputAction>; template class DigiHandle<DigiEventAction>; template class DigiHandle<DigiSynchronize>; template class DigiHandle<DigiActionSequence>; diff --git a/DDDigi/src/DigiHitAttenuatorExp.cpp b/DDDigi/src/DigiHitAttenuatorExp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b88fa2e22c92a1ebff298091249de499315f4f4 --- /dev/null +++ b/DDDigi/src/DigiHitAttenuatorExp.cpp @@ -0,0 +1,96 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" + +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiHitAttenuatorExp.h" + +class dd4hep::digi::DigiHitAttenuatorExp::internals_t { +public: + /// Property: Input data segment name + std::string input { }; + /// Property: Container names to be loaded + std::map<std::string, double> container_attenuation { }; + /// Property: event masks to be handled + std::vector<int> masks { }; + /// Property: T0 with respect to central crossing + double t0 { 0e0 }; + + /// Keys of all containers to be manipulated + std::map<unsigned long, double> attenuation { }; + + void initialize(DigiContext& context) { + if ( this->attenuation.empty() ) { + std::lock_guard<std::mutex> lock(context.initializer_lock()); + if ( this->attenuation.empty() ) { + for ( const auto& c : this->container_attenuation ) { + Key key(0x0, c.first); + for ( int m : this->masks ) { + double factor = std::exp(-1e0 * this->t0/c.second); + key.values.mask = m; + this->attenuation.emplace(key.key, factor); + } + } + } + } + } +}; + +/// Standard constructor +dd4hep::digi::DigiHitAttenuatorExp::DigiHitAttenuatorExp(const DigiKernel& krnl, const std::string& nam) + : DigiEventAction(krnl, nam) +{ + internals = std::make_unique<internals_t>(); + declareProperty("input", internals->input = "inputs"); + declareProperty("containers", internals->container_attenuation); + declareProperty("masks", internals->masks); + declareProperty("t0", internals->t0); + InstanceCount::increment(this); +} + +/// Default destructor +dd4hep::digi::DigiHitAttenuatorExp::~DigiHitAttenuatorExp() { + InstanceCount::decrement(this); +} + +/// Main functional callback +void dd4hep::digi::DigiHitAttenuatorExp::execute(DigiContext& context) const { + internals->initialize(context); + std::size_t count = 0; + auto& event = context.event; + auto& inputs = event->get_segment(internals->input); + for ( const auto& k : internals->attenuation ) { + auto iter = inputs.find(k.first); + if ( iter != inputs.end() ) { + std::any& obj = (*iter).second; + DepositMapping* m = std::any_cast<DepositMapping>(&obj); + double factor = k.second; + if ( m ) { + for( auto& c : *m ) { + c.second.deposit *= factor; + } + count += m->size(); + std::string nam = Key::key_name(k.first)+":"; + debug("%s+++ %-32s Mask: %06X Attenuated exponentially %6ld hits by %8.5f", + event->id(), nam.c_str(), m->mask, m->size(), factor); + continue; + } + error("Invalid data type in container"); + } + } + info("%s+++ Attenuated exponentially %6ld hits", event->id(), count); +} + diff --git a/DDDigi/src/DigiInputAction.cpp b/DDDigi/src/DigiInputAction.cpp index 98b1589a5e3fffb0b4e17e7b8e77b31e35826384..2352bed75e12d793e1aaa22484e39bd2c435d5ec 100644 --- a/DDDigi/src/DigiInputAction.cpp +++ b/DDDigi/src/DigiInputAction.cpp @@ -26,7 +26,8 @@ using namespace dd4hep::digi; DigiInputAction::DigiInputAction(const DigiKernel& kernel, const string& nam) : DigiEventAction(kernel, nam) { - declareProperty("Input", m_input); + declareProperty("input", m_inputs); + declareProperty("mask", m_mask); InstanceCount::increment(this); } @@ -37,8 +38,6 @@ DigiInputAction::~DigiInputAction() { /// Pre-track action callback void DigiInputAction::execute(DigiContext& /* context */) const { + info("+++ Virtual method execute() --- Should not be called"); ::sleep(1); - info("+++ Virtual method execute()"); - return; - //except("DigiInputAction","+++ Virtual method execute() MUST be overloaded!"); } diff --git a/DDDigi/src/DigiKernel.cpp b/DDDigi/src/DigiKernel.cpp index f168ef9b6998d4f5b90bdde925ee89fe72521121..995f054596daf18c3607a3d5015d9c1f65075ad9 100644 --- a/DDDigi/src/DigiKernel.cpp +++ b/DDDigi/src/DigiKernel.cpp @@ -33,7 +33,6 @@ #include <memory> #include <chrono> -using namespace std; using namespace dd4hep; using namespace dd4hep::digi; namespace { @@ -55,6 +54,22 @@ public: ClientOutputLevels clientLevels; /// Atomic counter: Number of events still to be processed in this run std::atomic_int eventsToDo; + /// Atomic counter: Number of events still to be processed in this run + std::atomic_int eventsFinished; + /// Atomic counter: Number of events still to be processed in this run + std::size_t eventsSubmitted; + + /// Lock to ensure counter safety + std::mutex counter_lock { }; + + /// Lock to ensure initialization safetyp + std::mutex initializer_lock { }; + + /// Lock for global I/O dependencies + std::mutex global_io_lock { }; + + /// Lock for global output logging + std::mutex global_output_lock { }; /// The main data input action sequence DigiActionSequence* inputAction = 0; @@ -118,16 +133,15 @@ public: while( todo >= 0 ) { todo = -1; { - std::lock_guard<std::mutex> lock(kernel_mutex); + std::lock_guard<std::mutex> lock(kernel.internals->counter_lock); if( !kernel.internals->stop && kernel.internals->eventsToDo > 0) todo = --kernel.internals->eventsToDo; } if ( todo >= 0 ) { int ev_num = kernel.internals->numEvents - todo; - unique_ptr<DigiContext> c(new DigiContext(&kernel)); - unique_ptr<DigiEvent> e(new DigiEvent(ev_num)); - c->setEvent(e.release()); - kernel.executeEvent(c.release()); + std::unique_ptr<DigiContext> context = + std::make_unique<DigiContext>(this->kernel,std::make_unique<DigiEvent>(ev_num)); + kernel.executeEvent(std::move(context)); } } } @@ -161,6 +175,7 @@ DigiKernel::DigiKernel(Detector& description_ref) /// Default destructor DigiKernel::~DigiKernel() { + std::lock_guard<std::mutex> lock(kernel_mutex); #ifdef DD4HEP_USE_TBB tbb::task_scheduler_init* init = (tbb::task_scheduler_init*)internals->tbbInit; if ( init ) delete init; @@ -184,6 +199,21 @@ DigiKernel& DigiKernel::instance(Detector& description) { return *(s_main_instance.get()); } +/// Have a shared initializer lock +std::mutex& DigiKernel::initializer_lock() const { + return internals->initializer_lock; +} + +/// Have a global output log lock +std::mutex& DigiKernel::global_output_lock() const { + return internals->global_output_lock; +} + +/// Have a global I/O lock (e.g. for ROOT) +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; @@ -191,9 +221,9 @@ PropertyManager& DigiKernel::properties() { /// Print the property values void DigiKernel::printProperties() const { - printout(ALWAYS,"DigiKernel","OutputLevel: %d", internals->outputLevel); - for(ClientOutputLevels::const_iterator i=internals->clientLevels.begin(); i!=internals->clientLevels.end();++i) { - printout(ALWAYS,"DigiKernel","OutputLevel[%s]: %d",(*i).first.c_str(),(*i).second); + printout(ALWAYS, "DigiKernel", "OutputLevel: %d", internals->outputLevel); + for( const auto& cl : internals->clientLevels ) { + printout(ALWAYS, "DigiKernel", "OutputLevel[%s]: %d", cl.first.c_str(), cl.second); } } @@ -231,6 +261,27 @@ dd4hep::PrintLevel DigiKernel::setOutputLevel(PrintLevel 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->eventsToDo; + 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->eventsToDo; + 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->eventsSubmitted - this->internals->eventsFinished; + return evts; +} + /// Construct detector geometry using description plugin void DigiKernel::loadGeometry(const std::string& compact_file) { char* arg = (char*) compact_file.c_str(); @@ -267,7 +318,7 @@ DigiActionSequence& DigiKernel::outputAction() const { } void DigiKernel::submit(const DigiAction::Actors<DigiEventAction>& actions, DigiContext& context) const { - chrono::system_clock::time_point start = chrono::system_clock::now(); + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); bool parallel = 0 != internals->tbbInit && internals->numThreads>0; #ifdef DD4HEP_USE_TBB if ( parallel ) { @@ -282,9 +333,9 @@ void DigiKernel::submit(const DigiAction::Actors<DigiEventAction>& actions, Digi goto print_stamp; print_stamp: - chrono::duration<double> secs = chrono::system_clock::now() - start; - printout(DEBUG,"DigiKernel","+++ Event: %8d Executed %s task group with %3ld members [%8.3g sec]", - context.event().eventNumber, parallel ? "parallel" : "serial", actions.size(), + std::chrono::duration<double> secs = std::chrono::system_clock::now() - start; + printout(DEBUG, "DigiKernel", "+++ Event: %8d Executed %s task group with %3ld members [%8.3g sec]", + context.event->eventNumber, parallel ? "parallel" : "serial", actions.size(), secs.count()); } @@ -293,44 +344,43 @@ void DigiKernel::execute(const DigiAction::Actors<DigiEventAction>& actions, Dig } void DigiKernel::wait(DigiContext& context) const { - if ( context.eventPtr() ) {} + if ( context.event ) {} } /// Execute one single event -void DigiKernel::executeEvent(DigiContext* context) { +void DigiKernel::executeEvent(std::unique_ptr<DigiContext>&& context) { DigiContext& refContext = *context; try { inputAction().execute(refContext); eventAction().execute(refContext); outputAction().execute(refContext); - notify(context); + notify(std::move(context)); } - catch(const exception& e) { - notify(context, e); + catch(const std::exception& e) { + notify(std::move(context), e); } } -void DigiKernel::notify(DigiContext* context) { +void DigiKernel::notify(std::unique_ptr<DigiContext>&& context) { if ( context ) { - DigiEvent* event = context->eventPtr(); - if ( event ) { - context->setEvent(0); - detail::deletePtr(event); - } - delete context; + context->event.reset(); } + context.reset(); + ++internals->eventsFinished; } -void DigiKernel::notify(DigiContext* context, const std::exception& e) { +void DigiKernel::notify(std::unique_ptr<DigiContext>&& context, const std::exception& e) { internals->stop = true; - printout(ERROR,"DigiKernel","+++ Exception during event processing: %s. [%s]", - e.what(), "Shall stop the event loop!"); - notify(context); + printout(ERROR,"DigiKernel","+++ Exception during event processing [Shall stop the event loop]"); + printout(ERROR,"DigiKernel"," -> %s", e.what()); + notify(std::move(context)); } int DigiKernel::run() { - chrono::system_clock::time_point start = chrono::system_clock::now(); + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); internals->stop = false; + internals->eventsFinished = 0; + internals->eventsSubmitted = 0; internals->eventsToDo = internals->numEvents; printout(INFO, "DigiKernel","+++ Total number of events: %d",internals->numEvents); @@ -338,10 +388,8 @@ int DigiKernel::run() { if ( 0 == internals->tbbInit && internals->numThreads>=0 ) { if ( 0 == internals->numThreads ) internals->numThreads = tbb::task_scheduler_init::default_num_threads(); - printout(INFO, - "DigiKernel","+++ Number of TBB threads to: %d",internals->numThreads); - printout(INFO, - "DigiKernel","+++ Number of parallel events: %d",internals->maxEventsParallel); + printout(INFO, "DigiKernel", "+++ Number of TBB threads to: %d",internals->numThreads); + printout(INFO, "DigiKernel", "+++ Number of parallel events: %d",internals->maxEventsParallel); internals->tbbInit = new tbb::task_scheduler_init(internals->numThreads); if ( internals->maxEventsParallel > 1 ) { int todo_evt = internals->eventsToDo; @@ -350,25 +398,26 @@ int DigiKernel::run() { for(int i=0; i < num_proc; ++i) main_group.run(Processor(*this)); main_group.wait(); - printout(DEBUG,"DigiKernel","+++ All event processing threads Synchronized --- Done!"); + printout(DEBUG, "DigiKernel", "+++ All event processing threads Synchronized --- Done!"); } } #endif while ( internals->eventsToDo > 0 && !internals->stop ) { Processor proc(*this); proc(); + ++internals->eventsSubmitted; } - chrono::duration<double> duration = chrono::system_clock::now() - start; - double sec = chrono::duration_cast<chrono::seconds>(duration).count(); - printout(DEBUG,"DigiKernel","+++ %d Events out of %d processed. " + 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, internals->numEvents-int(internals->eventsToDo), + internals->numEvents-int(internals->eventsToDo), internals->numEvents, sec, sec/double(std::max(1,internals->numEvents))); return 1; } int DigiKernel::terminate() { - printout(INFO,"DigiKernel","++ Terminate Digi and delete associated actions."); + printout(INFO, "DigiKernel", "++ Terminate Digi and delete associated actions."); m_detDesc->destroyInstance(); m_detDesc = 0; return 1; diff --git a/DDDigi/src/DigiROOTInput.cpp b/DDDigi/src/DigiROOTInput.cpp new file mode 100644 index 0000000000000000000000000000000000000000..670bce10118903e3174019f3b589d7166764d751 --- /dev/null +++ b/DDDigi/src/DigiROOTInput.cpp @@ -0,0 +1,207 @@ +//========================================================================== +// 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/DigiROOTInput.h> +#include <DD4hep/Printout.h> +#include <DD4hep/Factories.h> + +// ROOT include files +#include <TROOT.h> +#include <TFile.h> +#include <TTree.h> + +// C/C++ include files +#include <stdexcept> +#include <map> + +using namespace dd4hep::digi; + +/// Helper class to hide connection parameters +/** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ +class DigiROOTInput::internals_t { +public: + typedef std::function<std::any(int, const char*, void*)> func_t; + + class converter_t { + public: + TBranch* branch { nullptr }; + TClass* cls { nullptr }; + std::unique_ptr<func_t> call { }; + }; + + /// Mutex to allow re-use of a single source for multiple input streams + std::mutex m_lock { }; + std::map<unsigned long, converter_t> branches; + /// Reference to the current ROOT file to be read + TFile* file { }; + /// Reference to the ROOT tree to be read + TTree* tree { nullptr }; + /// Pointer to current input source + int input { INPUT_START }; + /// Current entry inside the current input source + Long64_t entry { -1 }; + +public: + /// Default constructor + internals_t () = default; + /// Default destructor + ~internals_t () { + if ( file ) { + file->Close(); + delete file; + file = nullptr; + } + } + /// Coverter function from input data to DDDige data + std::unique_ptr<func_t> input_converter(TClass* cl) const { + using detail::str_replace; + std::string cln = str_replace(cl->GetName(),"::","_"); + cln = str_replace(str_replace(str_replace(cln,'<','_'),'>','_'),'*',""); + std::string factory = "DD4hep_DDDigiConverter_"+cln; + func_t *fptr = (func_t*)PluginService::Create<void*>(factory.c_str()); + if ( 0 == fptr ) { + dd4hep::except("DigiROOTInput","Failed to access function pointer to read ROOT datatype: %s",cl->GetName()); + } + return std::unique_ptr<func_t>(fptr); + } +}; + + +/// Standard constructor +DigiROOTInput::DigiROOTInput(const DigiKernel& kernel, const std::string& nam) + : DigiInputAction(kernel, nam) +{ + declareProperty("tree", m_tree_name = "EVENT"); + declareProperty("containers", m_containers); + InstanceCount::increment(this); +} + +/// Default destructor +DigiROOTInput::~DigiROOTInput() { + InstanceCount::decrement(this); +} + +/// Open new input file +void DigiROOTInput::open_new_file() const { + int len = this->m_inputs.size(); + imp = std::make_unique<internals_t>(); + if ( this->m_inputs.empty() ) imp->input = 0; + while ( (imp->input+1) < len ) { + const auto& fname = m_inputs[++imp->input]; + imp->file = TFile::Open(fname.c_str()); + if ( imp->file && imp->file->IsZombie() ) { + delete imp->file; + imp->file = nullptr; + error("OpenInput ++ Failed to open input source %s", fname.c_str()); + } + else if ( imp->file ) { + imp->tree = (TTree*)imp->file->Get(this->m_tree_name.c_str()); + if ( !imp->tree ) { + error("OpenInput ++ Failed to access tree: %s in input: %s", + this->m_tree_name.c_str(), fname.c_str()); + continue; + } + imp->branches.clear(); + auto* branches = imp->tree->GetListOfBranches(); + TObjArrayIter it(branches); + for(Int_t i=0; i<branches->GetEntriesFast(); ++i) { + TBranch* b = (TBranch*)branches->At(i); + TClass* cls = gROOT->GetClass( b->GetClassName(), kTRUE ); + /// If there are no required branches, we convert everything + if ( this->m_containers.empty() ) { + Key key(this->m_mask, b->GetName()); + b->SetAutoDelete( kFALSE ); + imp->branches[key.key] = {b, cls, imp->input_converter(cls)}; + continue; + } + /// Otherwise only the entities asked for + for( const auto& bname : this->m_containers ) { + if ( bname == b->GetName() ) { + Key key(this->m_mask, b->GetName()); + b->SetAutoDelete( kFALSE ); + imp->branches[key.key] = {b, cls, imp->input_converter(cls)}; + break; + } + } + } + break; + } + else { + error("OpenInput ++ Failed to open input source %s", fname.c_str()); + } + imp->file = nullptr; + } + if ( imp->input >= len ) { + imp.reset(); + except("OpenInput ++ Failed to open NEW input source"); + } +} + +/// Pre-track action callback +void DigiROOTInput::execute(DigiContext& context) const { + if ( imp ) { + std::lock_guard<std::mutex> lock(context.global_io_lock()); + Int_t total = imp->tree->GetEntries(); + if ( (1+imp->entry) >= total ) { + imp.reset(); + } + } + /// If necessary open a new file + if ( !imp ) { + std::lock_guard<std::mutex> lock(context.global_io_lock()); + open_new_file(); + } + + if ( nullptr == imp->file ) { + except("+++ No open file present. Configuration error?"); + } + if ( imp->branches.empty() ) { + except("+++ No branches to be loaded. Configuration error!"); + } + std::size_t input_len = 0; + // + // We have to lock all ROOT based actions. Consequences are SEGV otherwise. + // + auto& event = context.event; + std::lock_guard<std::mutex> lock(context.global_io_lock()); + ++imp->entry; + imp->tree->LoadTree( imp->entry ); + + /// We only get here with a valid input + for( const auto& br : imp->branches ) { + void* obj = br.second.cls->New(); + br.second.branch->SetAddress(&obj); + } + for( const auto& br : imp->branches ) { + TBranch* b = br.second.branch; + int nb = b->GetEntry( imp->entry ); + if ( nb < 0 ) { // This is definitely an error...ROOT says if reads fail, -1 is issued. + continue; + } + debug("%s+++ Loaded %8d bytes from branch %s", event->id(), nb, b->GetName()); + input_len += nb; + const auto& func = *br.second.call; + void** addr = (void**)b->GetAddress(); + auto data = func(this->m_mask, b->GetName(), *addr); + event->put_input(br.first, std::move(data)); + } + info("%s+++ Read event %6ld [%ld bytes] from tree %s file: %s", + event->id(), imp->entry, input_len, imp->tree->GetName(), imp->file->GetName()); +} diff --git a/DDDigi/src/DigiSegmentationSplitter.cpp b/DDDigi/src/DigiSegmentationSplitter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b94a2556bc5dc9457151c7280eacdf1e570df01b --- /dev/null +++ b/DDDigi/src/DigiSegmentationSplitter.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 "DD4hep/InstanceCount.h" + +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiSegmentationSplitter.h" + +using dd4hep::digi::DigiSegmentationSplitter; + +class DigiSegmentationSplitter::internals_t { +public: + /// Property: Identifier of the input repository + std::string input_id; + /// Property: Subdetector to handle + std::string detector_name; + /// Property: Input masks in the repository + std::vector<int> masks; + + /// Flag to check the initialization + bool inited { false }; + + /// Initializing function: compute values which depend on properties + void initialize(DigiContext& context) { + if ( !this->inited ) { + std::lock_guard<std::mutex> lock(context.initializer_lock()); + if ( !this->inited ) { + this->inited = true; + } + } + } +}; + +/// Standard constructor +dd4hep::digi::DigiSegmentationSplitter::DigiSegmentationSplitter(const DigiKernel& krnl, const std::string& nam) + : DigiEventAction(krnl, nam) +{ + this->internals = std::make_unique<internals_t>(); + declareProperty("input", this->internals->input_id = "deposits"); + declareProperty("detector", this->internals->detector_name); + declareProperty("masks", this->internals->masks); + InstanceCount::increment(this); +} + +/// Default destructor +dd4hep::digi::DigiSegmentationSplitter::~DigiSegmentationSplitter() { + InstanceCount::decrement(this); +} + +/// Split actions according to the segmentation +void dd4hep::digi::DigiSegmentationSplitter::split_segments(DigiEvent& event, + DigiEvent::container_map_t& data) const +{ + +} + +/// Main functional callback +void dd4hep::digi::DigiSegmentationSplitter::execute(DigiContext& context) const { + this->internals->initialize(context); + auto& data = context.event->get_segment(this->internals->input_id); + this->split_segments(*context.event, data); +} diff --git a/DDDigi/src/DigiStoreDump.cpp b/DDDigi/src/DigiStoreDump.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e15199e9ce6152fdce6af02c5889b89b650c08ff --- /dev/null +++ b/DDDigi/src/DigiStoreDump.cpp @@ -0,0 +1,86 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" + +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiStoreDump.h" + +/// Standard constructor +dd4hep::digi::DigiStoreDump::DigiStoreDump(const DigiKernel& krnl, const std::string& nam) + : DigiEventAction(krnl, nam) +{ + declareProperty("history", this->m_dump_history = false); + declareProperty("data_segments", this->m_data_segments); + this->m_data_segments.push_back("input"); + this->m_data_segments.push_back("deposits"); + this->m_data_segments.push_back("data"); + InstanceCount::increment(this); +} + +/// Default destructor +dd4hep::digi::DigiStoreDump::~DigiStoreDump() { + InstanceCount::decrement(this); +} + +/// Dump hit container +template <typename CONTAINER> +void dd4hep::digi::DigiStoreDump::dump(const std::string& tag, + const DigiEvent& event, + const CONTAINER& data_segment) const +{ + std::string str; + std::vector<std::string> records; + using detail::str_replace; + info("%s+---- %s segment: %ld entries", event.id(), tag.c_str(), data_segment.size()); + for ( const auto& e : data_segment ) { + Key key {e.first}; + const std::any& data = e.second; + std::string nam = Key::key_name(key); + std::string typ = typeName(data.type()); + std::size_t idx = typ.find(", std::less<long long>, std::allocator<std::pair"); + if ( idx != std::string::npos ) typ = str_replace(typ, typ.substr(idx), ">"); + typ = str_replace(str_replace(typ,"std::",""),"dd4hep::digi::",""); + if ( const auto* hits = std::any_cast<DepositMapping>(&data) ) { + str = this->format("%s|---- %4X %08X %-32s: %6ld hits [%s]", + event.id(), key.values.mask, key.values.item, + nam.c_str(), hits->size(), typ.c_str()); + } + else if ( const auto* parts = std::any_cast<ParticleMapping>(&data) ) { + str = this->format("%s|---- %4X %08X %-32s: %6ld particles [%s]", + event.id(), key.values.mask, key.values.item, + nam.c_str(), parts->size(), typ.c_str()); + } + else { + str = this->format("%s|---- %4X %08X %-32s: %s", + event.id(), key.values.mask, key.values.item, + nam.c_str(), typ.c_str()); + } + records.push_back(str); + } + std::lock_guard<std::mutex> record_lock(m_kernel.global_output_lock()); + for(const auto& s : records) + this->info(s.c_str()); +} + +/// Main functional callback +void dd4hep::digi::DigiStoreDump::execute(DigiContext& context) const { + const auto& event = context.event; + for(const auto& segment : this->m_data_segments) { + std::string seg = detail::str_upper(segment); + this->dump(seg, *event, event->get_segment(segment)); + } +} diff --git a/DDDigi/src/DigiSubdetectorSequence.cpp b/DDDigi/src/DigiSubdetectorSequence.cpp index d2018ac2bf91ecc5fa6d62bff8a8a67d94fc5fe6..5ca83e495bddcc3b4cf318938a3b08cac9429493 100644 --- a/DDDigi/src/DigiSubdetectorSequence.cpp +++ b/DDDigi/src/DigiSubdetectorSequence.cpp @@ -159,7 +159,7 @@ void DigiSubdetectorSequence::execute(DigiContext& context) const { } this->DigiSynchronize::execute(context); debug("+++ Event: %8d (DigiSubdetectorSequence) Parallel: %s Done.", - context.event().eventNumber, yes_no(m_parallel)); + context.event->eventNumber, yes_no(m_parallel)); } /// Access subdetector from the detector description diff --git a/DDDigi/src/DigiSynchronize.cpp b/DDDigi/src/DigiSynchronize.cpp index 49a9660fe696bdbd85e4d484127a6a1d8d9bfe62..bc836d85f04bb970fa8b3789bc2bfafa66d83af8 100644 --- a/DDDigi/src/DigiSynchronize.cpp +++ b/DDDigi/src/DigiSynchronize.cpp @@ -51,7 +51,7 @@ void DigiSynchronize::execute(DigiContext& context) const { m_kernel.execute(m_actors, context); chrono::duration<double> secs = chrono::high_resolution_clock::now() - start; debug("+++ Event: %8d (DigiSynchronize) Parallel: %-4s %3ld actions [%8.3g sec]", - context.event().eventNumber, yes_no(m_parallel), m_actors.size(), + context.event->eventNumber, yes_no(m_parallel), m_actors.size(), secs.count()); } diff --git a/DDEve/src/DDG4EventHandler.cpp b/DDEve/src/DDG4EventHandler.cpp index dc61e5f3f20ce379fdd6ea43be6c15ea4ee900e3..2268fe25f802d4e436143d328b63494ec508c162 100644 --- a/DDEve/src/DDG4EventHandler.cpp +++ b/DDEve/src/DDG4EventHandler.cpp @@ -12,14 +12,14 @@ //========================================================================== // Framework include files -#include "DDEve/DDG4EventHandler.h" -#include "DD4hep/Printout.h" -#include "DD4hep/Objects.h" -#include "DD4hep/Factories.h" - -#include "TFile.h" -#include "TTree.h" -#include "TBranch.h" +#include <DDEve/DDG4EventHandler.h> +#include <DD4hep/Printout.h> +#include <DD4hep/Objects.h> +#include <DD4hep/Factories.h> + +#include <TFile.h> +#include <TTree.h> +#include <TBranch.h> // C/C++ include files #include <stdexcept> diff --git a/DDG4/include/DDG4/Geant4Data.h b/DDG4/include/DDG4/Geant4Data.h index f2d53e14c961ba7ea511a7a959367492e7c65d0c..7e88e7aac384b22a6d9aeac94f42122b8aecf7c4 100644 --- a/DDG4/include/DDG4/Geant4Data.h +++ b/DDG4/include/DDG4/Geant4Data.h @@ -234,6 +234,8 @@ namespace dd4hep { */ class Hit : public Geant4HitData { public: + typedef Geant4HitData base_t; + /// Hit position Position position; /// Hit direction @@ -290,6 +292,8 @@ namespace dd4hep { */ class Hit : public Geant4HitData { public: + typedef Geant4HitData base_t; + /// Hit position Position position; /// Hit contributions by individual particles diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index eefe6b9c6351706183182f61b3666d4970ec4d3c..6e4edad150da2e9919122d947293ebdc51095361 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -279,7 +279,6 @@ _import_class('Sim', 'Geant4Random') _import_class('CLHEP', 'HepRandom') _import_class('CLHEP', 'HepRandomEngine') - def _get(self, name): a = Interface.toAction(self) ret = Interface.getProperty(a, name) @@ -292,48 +291,22 @@ def _get(self, name): msg = 'Geant4Action::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name raise KeyError(msg) - -def _deUnicode(value): - """Turn any unicode literal into str, needed when passing to c++. - - Recursively transverses dicts, lists, sets, tuples - - :return: always a str - """ - if isinstance(value, (bool, float, six.integer_types)): - value = value - elif isinstance(value, six.string_types): - value = str(value) - elif isinstance(value, (list, set, tuple)): - value = [_deUnicode(x) for x in value] - elif isinstance(value, dict): - tempDict = {} - for key, val in value.items(): - key = _deUnicode(key) - val = _deUnicode(val) - tempDict[key] = val - value = tempDict - return str(value) - - def _set(self, name, value): """This function is called when properties are passed to the c++ objects.""" a = Interface.toAction(self) - name = _deUnicode(name) - value = _deUnicode(value) + name = unicode_2_string(name) + value = unicode_2_string(value) if Interface.setProperty(a, name, value): return msg = 'Geant4Action::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + value raise KeyError(msg) - def _props(obj): _import_class('Sim', obj) cl = getattr(current, obj) cl.__getattr__ = _get cl.__setattr__ = _set - _props('FilterHandle') _props('ActionHandle') _props('PhaseActionHandle') diff --git a/examples/DDDigi/scripts/DigiTest.py b/examples/DDDigi/scripts/DigiTest.py new file mode 100644 index 0000000000000000000000000000000000000000..290acb45c3e8238f044913d3655d2f25acda27ff --- /dev/null +++ b/examples/DDDigi/scripts/DigiTest.py @@ -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. +# +# ========================================================================== + +import dddigi +import logging +from g4units import ns +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) + +""" + 00C7A3C1 SiVertexEndcapHits : map<long long, EnergyDeposit> + 00D16F45 EcalBarrelHits : map<long long, EnergyDeposit> + 0D3C3803 MCParticles : vector<shared_ptr<dd4hep::sim::Geant4Particle>, allocator<shared_ptr<dd4hep::sim::Geant4Particle> > > + 2E9082A9 HcalPlugHits : map<long long, EnergyDeposit> + 3A89E02E HcalEndcapHits : map<long long, EnergyDeposit> + 569C1C49 HcalBarrelHits : map<long long, EnergyDeposit> + 62AD0218 EcalEndcapHits : map<long long, EnergyDeposit> + 7FBC6131 SiTrackerBarrelHits : map<long long, EnergyDeposit> + A239CB2E LumiCalHits : map<long long, EnergyDeposit> + B5CD88D8 MuonBarrelHits : map<long long, EnergyDeposit> + BDB9AD3E SiVertexBarrelHits : map<long long, EnergyDeposit> + C84DE2C2 MuonEndcapHits : map<long long, EnergyDeposit> + CB57C6D0 SiTrackerForwardHits : map<long long, EnergyDeposit> + D108063E BeamCalHits : map<long long, EnergyDeposit> + F4183035 SiTrackerEndcapHits : map<long long, EnergyDeposit> +""" + +attenuation = { 'SiVertexEndcapHits': 15 * ns, + 'SiVertexBarrelHits': 15 * ns, + 'SiTrackerForwardHits': 15 * ns, + 'SiTrackerEndcapHits': 15 * ns, + 'SiTrackerBarrelHits': 15 * ns, + 'HcalPlugHits': 15 * ns, + 'HcalEndcapHits': 15 * ns, + 'HcalBarrelHits': 15 * ns, + 'EcalEndcapHits': 15 * ns, + 'MuonEndcapHits': 15 * ns, + 'MuonBarrelHits': 15 * ns, + 'BeamCalHits': 15 * ns, + 'LumiCalHits': 15 * ns, +} + + +class Test(dddigi.Digitize): + + def __init__(self, geometry=None): + global attenuation + dddigi.Digitize.__init__(self, dddigi.Kernel()) + dddigi.setPrintFormat(str('%-32s %5s %s')) + dddigi.setPrintLevel(dddigi.OutputLevel.INFO) + self.kernel().printProperties() + self.geometry = geometry + self.input = None + self.main_sequencer() + self.attenuation = attenuation + self.inputs = [ + 'CLICSiD_2022-10-05_13-21.root', + 'CLICSiD_2022-10-05_13-52.root', + 'CLICSiD_2022-10-05_14-16.root', + 'CLICSiD_2022-10-05_14-40.root' + ] + self.used_inputs = [] + + def declare_input(self, name, input, parallel=True): + if not self.input: + self.input = dddigi.Synchronize(self.kernel(), 'DigiParallelActionSequence/READER') + self.input.parallel = True + + def next_input(self): + if len(self.used_inputs) == len(self.inputs): + self.used_inputs = [] + next = self.inputs[len(self.used_inputs)] + self.used_inputs.append(next) + return next diff --git a/examples/DDDigi/scripts/TestFramework.py b/examples/DDDigi/scripts/TestFramework.py index 78fc46a747eba91410e89a928baebea05e6c9635..1ff0a061f309a15660190d7df3a48f217338833b 100644 --- a/examples/DDDigi/scripts/TestFramework.py +++ b/examples/DDDigi/scripts/TestFramework.py @@ -9,15 +9,14 @@ # # ========================================================================== from __future__ import absolute_import, unicode_literals +import dddigi import os -import DDDigi - def make_input(kernel): - input_1 = DDDigi.TestAction(kernel, 'input_01', 100) - input_2 = DDDigi.TestAction(kernel, 'input_02', 200) - input_3 = DDDigi.TestAction(kernel, 'input_03', 150) - input_4 = DDDigi.TestAction(kernel, 'input_04', 60) + input_1 = dddigi.TestAction(kernel, 'input_01', 100) + input_2 = dddigi.TestAction(kernel, 'input_02', 200) + input_3 = dddigi.TestAction(kernel, 'input_03', 150) + input_4 = dddigi.TestAction(kernel, 'input_04', 60) seq = kernel.inputAction() seq.adopt(input_1) seq.adopt(input_2) @@ -27,12 +26,12 @@ def make_input(kernel): def make_subdetector(kernel, name): - action_1 = DDDigi.TestAction(kernel, name + '_deposits', 150) - action_2 = DDDigi.TestAction(kernel, name + '_rndmNoise', 100) - action_3 = DDDigi.TestAction(kernel, name + '_deadChan', 100) - action_4 = DDDigi.TestAction(kernel, name + '_noiseChan', 50) - action_5 = DDDigi.TestAction(kernel, name + '_merge', 200) - seq = DDDigi.ActionSequence(kernel, 'DigiActionSequence/' + name + '_sequence', True) + action_1 = dddigi.TestAction(kernel, name + '_deposits', 150) + action_2 = dddigi.TestAction(kernel, name + '_rndmNoise', 100) + action_3 = dddigi.TestAction(kernel, name + '_deadChan', 100) + action_4 = dddigi.TestAction(kernel, name + '_noiseChan', 50) + action_5 = dddigi.TestAction(kernel, name + '_merge', 200) + seq = dddigi.ActionSequence(kernel, 'DigiActionSequence/' + name + '_sequence', True) seq.adopt(action_1) seq.adopt(action_2) seq.adopt(action_3) @@ -44,16 +43,16 @@ def make_subdetector(kernel, name): def run(): # import pdb # pdb.set_trace() - DDDigi.setPrintFormat(str('%-32s %5s %s')) - kernel = DDDigi.Kernel() + dddigi.setPrintFormat(str('%-32s %5s %s')) + kernel = dddigi.Kernel() install_dir = os.environ['DD4hepExamplesINSTALL'] fname = "file:" + install_dir + "/examples/ClientTests/compact/MiniTel.xml" kernel.loadGeometry(str(fname)) kernel.printProperties() - digi = DDDigi.Digitize(kernel) + digi = dddigi.Digitize(kernel) digi.printDetectors() - event_processor = DDDigi.Synchronize(kernel, 'DigiSynchronize/MainDigitizer', True) + event_processor = dddigi.Synchronize(kernel, 'DigiSynchronize/MainDigitizer', True) event_processor.parallel = True # input make_input(kernel) @@ -64,15 +63,15 @@ def run(): event_processor.adopt(seq) kernel.eventAction().adopt(event_processor) # Output - output = DDDigi.TestAction(kernel, 'output_01', 200) + output = dddigi.TestAction(kernel, 'output_01', 200) kernel.outputAction().adopt(output) - DDDigi.setPrintLevel(DDDigi.OutputLevel.DEBUG) + dddigi.setPrintLevel(dddigi.OutputLevel.DEBUG) kernel.numThreads = 0 # = number of concurrent threads kernel.numEvents = 10 kernel.maxEventsParallel = 3 kernel.run() - DDDigi.setPrintLevel(DDDigi.OutputLevel.INFO) + dddigi.setPrintLevel(dddigi.OutputLevel.INFO) if __name__ == '__main__': diff --git a/examples/DDDigi/scripts/TestInput.py b/examples/DDDigi/scripts/TestInput.py new file mode 100644 index 0000000000000000000000000000000000000000..9cf47bb900e7f94041015c42499f7e4e6f1a9dbb --- /dev/null +++ b/examples/DDDigi/scripts/TestInput.py @@ -0,0 +1,20 @@ +# ========================================================================== +# 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. +# +# ========================================================================== + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + reader = digi.input_action('DigiROOTInput/SignalReader', mask=0x1, input=['CLICSiD_2022-10-05_13-21.root']) + dump = digi.event_action('DigiStoreDump/StoreDump') + digi.run(num_events = 5, num_threads = 5, parallel = 3) + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/scripts/TestMultiInteractions.py b/examples/DDDigi/scripts/TestMultiInteractions.py new file mode 100644 index 0000000000000000000000000000000000000000..18cf7ebbfc4f7156ba27330b8da0368d5a79f7e7 --- /dev/null +++ b/examples/DDDigi/scripts/TestMultiInteractions.py @@ -0,0 +1,55 @@ +# ========================================================================== +# 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 g4units import ns + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + attenuation = digi.attenuation + + input = digi.input_action('DigiParallelActionSequence/READER') + #======================================================================================================== + digi.info('Created SIGNAL input') + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input = [digi.next_input()]) + #======================================================================================================== + digi.info('Creating collision overlays....') + #======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1') + evtreader = overlay.adopt_action('DigiROOTInput/Reader-1', mask=0x1, input = [digi.next_input()]) + hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-1', masks = [evtreader.mask]) + digi.info('Created input.overlay25') + #======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-2') + evtreader = overlay.adopt_action('DigiROOTInput/Reader-2', mask=0x2, input = [digi.next_input()]) + hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-2', masks = [evtreader.mask]) + digi.info('Created input.overlay50') + #======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-3') + evtreader = overlay.adopt_action('DigiROOTInput/Reader-3', mask=0x3, input = [digi.next_input()]) + hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-3', masks = [evtreader.mask]) + digi.info('Created input.overlay75') + #======================================================================================================== + + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', masks=[0x0, 0x1, 0x2, 0x3], deposit_mask=0xFEED) + combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence + dump = event.adopt_action('DigiStoreDump/StoreDump') + digi.info('Created event.dump') + #======================================================================================================== + evt_todo = 5 + evt_done = digi.run(num_events = evt_todo, num_threads = 5, parallel = 3) + if evt_done == evt_todo: result = "PASSED" + else: result = "FAILED" + digi.always('%s Test finished after processing %d events.'%(result, digi.events_done(),)) + digi.always('Test done. Exiting') + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/scripts/TestSegmentationSplit.py b/examples/DDDigi/scripts/TestSegmentationSplit.py new file mode 100644 index 0000000000000000000000000000000000000000..a72f728e73f007c9d38f709dcb67bbbb09333717 --- /dev/null +++ b/examples/DDDigi/scripts/TestSegmentationSplit.py @@ -0,0 +1,43 @@ +# ========================================================================== +# 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 g4units import ns + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + attenuation = digi.attenuation + + input = digi.input_action('DigiParallelActionSequence/READER') + #======================================================================================================== + digi.info('Created SIGNAL input') + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input = [digi.next_input()]) + #======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', masks=[0x0, 0x1, 0x2, 0x3], deposit_mask=0xFEED) + combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence + dump = event.adopt_action('DigiStoreDump/StoreDump') + + splitter = event.adopt_action('DigiSegmentationSplitter/Splitter', + input='deposits', + masks=[0xFEED], + detector='SiTrackerBarrel'); + + digi.info('Created event.dump') + #======================================================================================================== + evt_todo = 5 + evt_done = digi.run(num_events = evt_todo, num_threads = 5, parallel = 3) + if evt_done == evt_todo: result = "PASSED" + else: result = "FAILED" + digi.always('%s Test finished after processing %d events.'%(result, digi.events_done(),)) + digi.always('Test done. Exiting') + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/scripts/TestSpillover.py b/examples/DDDigi/scripts/TestSpillover.py new file mode 100644 index 0000000000000000000000000000000000000000..cf86dfd8ff0a517df94ac8ce35ac5601986b96c7 --- /dev/null +++ b/examples/DDDigi/scripts/TestSpillover.py @@ -0,0 +1,83 @@ +# ========================================================================== +# 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 g4units import ns + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + attenuation = digi.attenuation + + input = digi.input_action('DigiParallelActionSequence/READER') + #======================================================================================================== + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input = [digi.next_input()]) + 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('DigiROOTInput/Reader-25ns', mask=0x1, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-25ns', + t0 = -25 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-25ns', masks = [evtreader.mask]) + digi.info('Created input.spillover25') + #======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-50') + evtreader = spillover.adopt_action('DigiROOTInput/Reader-50ns', mask=0x2, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-50ns', + t0 = -50 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-50ns', masks = [evtreader.mask]) + digi.info('Created input.spillover50') + #======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-75') + evtreader = spillover.adopt_action('DigiROOTInput/Reader-75ns', mask=0x3, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-75ns', + t0 = -75 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-75ns', masks = [evtreader.mask]) + digi.info('Created input.spillover75') + #======================================================================================================== + digi.info('Creating spillover sequence for LATER bunch crossings.....') + #======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+25') + evtreader = spillover.adopt_action('DigiROOTInput/Reader+25ns', mask=0x4, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+25ns', + t0 = 25 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+25ns', masks = [evtreader.mask]) + digi.info('Created input.spillover25') + #======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+50') + evtreader = spillover.adopt_action('DigiROOTInput/Reader+50ns', mask=0x5, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+50ns', + t0 = 50 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop_50ns', masks = [evtreader.mask]) + digi.info('Created input.spillover50') + #======================================================================================================== + spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+75') + evtreader = spillover.adopt_action('DigiROOTInput/Reader+75ns', mask=0x6, input = [digi.next_input()]) + attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+75ns', + t0 = 75 * ns, masks = [evtreader.mask], containers = attenuation) + hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+75ns', masks = [evtreader.mask]) + digi.info('Created input.spillover75') + #======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', masks=[0x0, 0x1, 0x2, 0x3], deposit_mask=0xFEED) + combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence + evtdump = event.adopt_action('DigiStoreDump/StoreDump') + digi.info('Created event.dump') + #======================================================================================================== + evt_todo = 5 + evt_done = digi.run(num_events = evt_todo, num_threads = 5, parallel = 3) + if evt_done == evt_todo: result = "PASSED" + else: result = "FAILED" + digi.always('%s Test finished after processing %d events.'%(result, digi.events_done(),)) + digi.always('Test done. Exiting') + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/src/DigiTestAction.cpp b/examples/DDDigi/src/DigiTestAction.cpp index b7888f99a77acb0578caa0bd4e2b7971056b9cd2..b798cf74ef7286d991d9587229e42177efee8984 100644 --- a/examples/DDDigi/src/DigiTestAction.cpp +++ b/examples/DDDigi/src/DigiTestAction.cpp @@ -103,6 +103,6 @@ DigiTestAction::~DigiTestAction() { /// Pre-track action callback void DigiTestAction::execute(DigiContext& context) const { debug("+++ Event: %8d (DigiTestAction) %d msec", - context.event().eventNumber, m_sleep); + context.event->eventNumber, m_sleep); if ( m_sleep > 0 ) ::usleep(1000*m_sleep); }