From 860de18f762ce6d299f45eb33ecedddb1218fdcc Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Thu, 4 Jul 2019 13:42:01 +0200 Subject: [PATCH] Prepare DD4hep for Geant4 units in TGeo; Start digitization package --- DDCore/include/DD4hep/Handle.h | 6 - DDCore/src/DetectorImp.cpp | 8 +- DDCore/src/MatrixHelpers.cpp | 8 + DDCore/src/Printout.cpp | 5 + DDCore/src/plugins/Compact2Objects.cpp | 29 +- DDCore/src/plugins/LCDDConverter.cpp | 3 +- DDDigi/CMakeLists.txt | 37 ++ DDDigi/include/DDDigi/DigiAction.h | 311 +++++++++++++++ DDDigi/include/DDDigi/DigiActionSequence.h | 81 ++++ DDDigi/include/DDDigi/DigiContext.h | 126 ++++++ DDDigi/include/DDDigi/DigiData.h | 149 +++++++ DDDigi/include/DDDigi/DigiFactories.h | 61 +++ DDDigi/include/DDDigi/DigiHandle.h | 120 ++++++ DDDigi/include/DDDigi/DigiInputAction.h | 59 +++ DDDigi/include/DDDigi/DigiKernel.h | 152 +++++++ DDDigi/include/DDDigi/DigiLockedAction.h | 66 ++++ DDDigi/include/DDDigi/DigiSynchronize.h | 61 +++ DDDigi/plugins/DigiRandomNoise.cpp | 107 +++++ DDDigi/plugins/DigiTestAction.cpp | 107 +++++ DDDigi/plugins/dummy.cpp | 53 +++ DDDigi/python/DDDigi.py | 372 ++++++++++++++++++ DDDigi/python/DDDigiDict.C | 155 ++++++++ DDDigi/src/DigiAction.cpp | 208 ++++++++++ DDDigi/src/DigiActionSequence.cpp | 50 +++ DDDigi/src/DigiContext.cpp | 79 ++++ DDDigi/src/DigiData.cpp | 44 +++ DDDigi/src/DigiHandle.cpp | 190 +++++++++ DDDigi/src/DigiInputAction.cpp | 44 +++ DDDigi/src/DigiKernel.cpp | 365 +++++++++++++++++ DDDigi/src/DigiLockedAction.cpp | 57 +++ DDDigi/src/DigiSynchronize.cpp | 71 ++++ DDDigi/test_task_queue.cpp | 41 ++ DDEve/src/HitActors.cpp | 6 + DDEve/src/ParticleActors.cpp | 17 +- DDG4/src/Geant4Converter.cpp | 2 + DDG4/src/Geant4SensDetAction.cpp | 6 + DDG4/src/Geant4SensitiveDetector.cpp | 6 + DDG4/src/Geant4StepHandler.cpp | 4 + DDParsers/include/Evaluator/DD4hepUnits.h | 316 ++++++++------- DDParsers/src/Evaluator/setSystemOfUnits.cpp | 5 + .../ClientTests/src/MaterialTester_geo.cpp | 39 +- 41 files changed, 3447 insertions(+), 179 deletions(-) create mode 100644 DDDigi/CMakeLists.txt create mode 100644 DDDigi/include/DDDigi/DigiAction.h create mode 100644 DDDigi/include/DDDigi/DigiActionSequence.h create mode 100644 DDDigi/include/DDDigi/DigiContext.h create mode 100644 DDDigi/include/DDDigi/DigiData.h create mode 100644 DDDigi/include/DDDigi/DigiFactories.h create mode 100644 DDDigi/include/DDDigi/DigiHandle.h create mode 100644 DDDigi/include/DDDigi/DigiInputAction.h create mode 100644 DDDigi/include/DDDigi/DigiKernel.h create mode 100644 DDDigi/include/DDDigi/DigiLockedAction.h create mode 100644 DDDigi/include/DDDigi/DigiSynchronize.h create mode 100644 DDDigi/plugins/DigiRandomNoise.cpp create mode 100644 DDDigi/plugins/DigiTestAction.cpp create mode 100644 DDDigi/plugins/dummy.cpp create mode 100644 DDDigi/python/DDDigi.py create mode 100644 DDDigi/python/DDDigiDict.C create mode 100644 DDDigi/src/DigiAction.cpp create mode 100644 DDDigi/src/DigiActionSequence.cpp create mode 100644 DDDigi/src/DigiContext.cpp create mode 100644 DDDigi/src/DigiData.cpp create mode 100644 DDDigi/src/DigiHandle.cpp create mode 100644 DDDigi/src/DigiInputAction.cpp create mode 100644 DDDigi/src/DigiKernel.cpp create mode 100644 DDDigi/src/DigiLockedAction.cpp create mode 100644 DDDigi/src/DigiSynchronize.cpp create mode 100644 DDDigi/test_task_queue.cpp diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index e41635869..32ff10a3b 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -28,12 +28,6 @@ #ifndef DEGREE_2_RAD #define DEGREE_2_RAD 0.0174532925199432957692369076848 #endif -#ifndef CM_2_MM -#define CM_2_MM 10.0 -#endif -#ifndef MM_2_CM -#define MM_2_CM 0.1 -#endif #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/DDCore/src/DetectorImp.cpp b/DDCore/src/DetectorImp.cpp index 2416ed3dd..9ea6437be 100644 --- a/DDCore/src/DetectorImp.cpp +++ b/DDCore/src/DetectorImp.cpp @@ -32,6 +32,7 @@ #include <mutex> // ROOT inlcude files +#include "TGeant4SystemOfUnits.h" #include "TGeoCompositeShape.h" #include "TGeoBoolNode.h" #include "TGeoManager.h" @@ -154,9 +155,10 @@ DetectorImp::DetectorImp() DetectorImp::DetectorImp(const string& name) : TNamed(), DetectorData(), DetectorLoad(this), m_buildType(BUILD_NONE) { + //TGeant4Unit::setUnitType(TGeant4Unit::kTGeant4Units); SetTitle("DD4hep detector description object"); - set_unexpected( description_unexpected ) ; - set_terminate( description_unexpected ) ; + set_unexpected( description_unexpected ); + set_terminate( description_unexpected ); InstanceCount::increment(this); //if ( gGeoManager ) delete gGeoManager; m_manager = new TGeoManager(name.c_str(), "Detector Geometry"); @@ -167,7 +169,7 @@ DetectorImp::DetectorImp(const string& name) table->TGeoElementTable::~TGeoElementTable(); new(table) TGeoElementTable(); // This will initialize the table without filling: - table->AddElement("VACUUM","VACUUM" ,0, 0, 0.0); + table->AddElement("VACUUM","VACUUM", 0, 0, 0.0); table->Print(); #endif } diff --git a/DDCore/src/MatrixHelpers.cpp b/DDCore/src/MatrixHelpers.cpp index 8b16d136e..1a70ccac0 100644 --- a/DDCore/src/MatrixHelpers.cpp +++ b/DDCore/src/MatrixHelpers.cpp @@ -13,12 +13,20 @@ // Framework include files #include "DD4hep/MatrixHelpers.h" +#include "DD4hep/DD4hepUnits.h" + +#ifdef HAVE_GEANT4_UNITS +#define MM_2_CM 1.0 +#else +#define MM_2_CM 0.1 +#endif // ROOT includes #include "TGeoMatrix.h" using namespace dd4hep; + TGeoIdentity* dd4hep::detail::matrix::_identity() { return gGeoIdentity; } diff --git a/DDCore/src/Printout.cpp b/DDCore/src/Printout.cpp index a9242f7d9..69ca75ae3 100644 --- a/DDCore/src/Printout.cpp +++ b/DDCore/src/Printout.cpp @@ -15,6 +15,7 @@ #include "DD4hep/Printout.h" // C/C++ include files +#include <mutex> #include <cstring> #include <cstdarg> #include <sstream> @@ -27,6 +28,8 @@ using namespace std; namespace { + std::mutex s_output_synchronization; + size_t _the_printer_1(void*, dd4hep::PrintLevel lvl, const char* src, const char* text); size_t _the_printer_2(void* par, dd4hep::PrintLevel lvl, const char* src, const char* fmt, va_list& args); @@ -54,6 +57,7 @@ namespace { } size_t _the_printer_1(void*, dd4hep::PrintLevel lvl, const char* src, const char* text) { + std::lock_guard<std::mutex> lock(s_output_synchronization); ::fflush(stdout); ::fflush(stderr); cout << flush; @@ -66,6 +70,7 @@ namespace { size_t _the_printer_2(void* par, dd4hep::PrintLevel lvl, const char* src, const char* fmt, va_list& args) { if ( !print_func_1 ) { char text[4096]; + std::lock_guard<std::mutex> lock(s_output_synchronization); ::fflush(stdout); ::fflush(stderr); cout << flush; diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 1950d6f37..99b9fef8e 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -363,7 +363,8 @@ template <> void Converter<Header>::operator()(xml_h e) const { h.setComment(e.child(_U(comment)).text()); description.setHeader(h); } - +#include "TGeoPhysicalConstants.h" +#include "TMath.h" /** Convert compact material/element description objects * * Materials: @@ -413,16 +414,6 @@ template <> void Converter<Material>::operator()(xml_h e) const { } printout(s_debug.materials ? ALWAYS : DEBUG, "Compact", "++ Converting material %-16s Density: %.3f.",matname, dens_val); -#if 0 - cout << "Gev " << xml::_toDouble(_Unicode(GeV)) << endl; - cout << "sec " << xml::_toDouble(_Unicode(second)) << endl; - cout << "nsec " << xml::_toDouble(_Unicode(nanosecond)) << endl; - cout << "kilo " << xml::_toDouble(_Unicode(kilogram)) << endl; - cout << "kilo " << xml::_toDouble(_Unicode(joule*s*s/(m*m))) << endl; - cout << "meter " << xml::_toDouble(_Unicode(meter)) << endl; - cout << "ampere " << xml::_toDouble(_Unicode(ampere)) << endl; - cout << "degree " << xml::_toDouble(_Unicode(degree)) << endl; -#endif //throw 1; mat = mix = new TGeoMixture(matname, composites.size(), dens_val); size_t ifrac = 0; @@ -462,7 +453,6 @@ template <> void Converter<Material>::operator()(xml_h e) const { #if ROOT_VERSION_CODE >= ROOT_VERSION(6,12,0) mix->ComputeDerivedQuantities(); #endif - #if ROOT_VERSION_CODE >= ROOT_VERSION(6,17,0) /// In case there were material properties specified: convert them here for(xml_coll_t properties(x_mat, _U(constant)); properties; ++properties) { @@ -1439,6 +1429,21 @@ template <> void Converter<Compact>::operator()(xml_h element) const { } } } + + if ( s_debug.materials || s_debug.elements ) { + printout(INFO,"Compact","+++ UNIT System:"); + printout(INFO,"Compact","+++ Density: %8.3g Units:%8.3g", + xml::_toDouble(_Unicode(gram/cm3)), dd4hep::gram/dd4hep::cm3); + printout(INFO,"Compact","+++ GeV: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(GeV)),dd4hep::GeV); + printout(INFO,"Compact","+++ sec: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(second)),dd4hep::second); + printout(INFO,"Compact","+++ nanosecond: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(nanosecond)),dd4hep::nanosecond); + printout(INFO,"Compact","+++ kilo: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(kilogram)),dd4hep::kilogram); + printout(INFO,"Compact","+++ kilo: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(joule*s*s/(m*m))), + dd4hep::joule*dd4hep::s*dd4hep::s/(dd4hep::meter*dd4hep::meter)); + printout(INFO,"Compact","+++ meter: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(meter)),dd4hep::meter); + printout(INFO,"Compact","+++ ampere: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(ampere)),dd4hep::ampere); + printout(INFO,"Compact","+++ degree: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(degree)),dd4hep::degree); + } xml_coll_t(compact, _U(define)).for_each(_U(include), Converter<DetElementInclude>(description)); xml_coll_t(compact, _U(define)).for_each(_U(constant), Converter<Constant>(description)); diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp index d1bdbb042..ecf007aec 100644 --- a/DDCore/src/plugins/LCDDConverter.cpp +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -16,6 +16,7 @@ #include "DD4hep/Printout.h" #include "DD4hep/Volumes.h" #include "DD4hep/FieldTypes.h" +#include "DD4hep/DD4hepUnits.h" #include "DD4hep/Segmentations.h" #include "DD4hep/detail/ObjectsInterna.h" #include "DD4hep/detail/DetectorInterna.h" @@ -882,7 +883,7 @@ xml_h LCDDConverter::handleSegmentation(Segmentation seg) const { } // translate from TGeo units to Geant4 units if necessary if (v->unitType() == DDSegmentation::SegmentationParameter::LengthUnit) { - double value = _toDouble(v->value()) * CM_2_MM; + double value = _toDouble(v->value()) / dd4hep::mm; xml.setAttr(Unicode(v->name()), value); } else if (v->unitType() == DDSegmentation::SegmentationParameter::AngleUnit) { double value = _toDouble(v->value()) * DEGREE_2_RAD; diff --git a/DDDigi/CMakeLists.txt b/DDDigi/CMakeLists.txt new file mode 100644 index 000000000..68e494588 --- /dev/null +++ b/DDDigi/CMakeLists.txt @@ -0,0 +1,37 @@ +#========================================================================== +# 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. +# +#========================================================================== +dd4hep_package( DDDigi + USES DDCore + [ROOT REQUIRED COMPONENTS Geom GenVector RIO] + TBB + INCLUDE_DIRS include + INSTALL_INCLUDES include/DDDigi ) + +#---Add Library--------------------------------------------------------------------- +dd4hep_add_package_library(DDDigi SOURCES src/*.cpp) +target_compile_definitions(DDDigi PUBLIC DD4HEP_USE_TBB) +message( STATUS "TBB_INCLUDE_DIR : ${TBB_INCLUDE_DIR}") +message( STATUS "TBB_LIBRARY : ${TBB_LIBRARY}") + +#--------------------------- Legacy libraries ------------------------------------- +dd4hep_add_dictionary( G__DDDigi + SOURCES ${DDCore_INCLUDE_DIRS}/include/ROOT/Warnings.h python/DDDigiDict.C + LINKDEF ${DDCore_INCLUDE_DIRS}/include/ROOT/LinkDef.h + ) +#--------------------------- Plugin library for the digitization framework ------- +dd4hep_add_plugin(DDDigiPlugins + GENERATED G__DDDigi.cxx + SOURCES plugins/*.cpp + ) +target_compile_definitions(DDDigiPlugins PUBLIC DD4HEP_USE_TBB) +#---Package installation procedure(s) ---------------------------------------------- +#d4hep_install_dir(examples DESTINATION examples/DDDigi) +dd4hep_install_files(FILES python/*.py python/*.C DESTINATION python) diff --git a/DDDigi/include/DDDigi/DigiAction.h b/DDDigi/include/DDDigi/DigiAction.h new file mode 100644 index 000000000..ff7b98976 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiAction.h @@ -0,0 +1,311 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIACTION_H +#define DD4HEP_DDDIGI_DIGIACTION_H + +// Framework include files +#include "DD4hep/Printout.h" +#include "DD4hep/Callback.h" +#include "DD4hep/ComponentProperties.h" +#include "DDDigi/DigiContext.h" + +// C/C++ include files +#include <string> +#include <cstdarg> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Cast operator + template <typename TO, typename FROM> TO fast_cast(FROM from) { +#ifdef USE_FASTCAST + return static_cast<TO>(from); +#else + return dynamic_cast<TO>(from); +#endif + } + + /// Helper class to handle strings of the format "type/name" + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class TypeName : public std::pair<std::string, std::string> { + public: + /// Default constructor + TypeName() = default; + /// Copy constructor + TypeName(const TypeName& copy) = default; + /// Copy constructor from pair + TypeName(const std::pair<std::string, std::string>& c) + : std::pair<std::string, std::string>(c) { } + /// Initializing constructor + TypeName(const std::string& typ, const std::string& nam) + : std::pair<std::string, std::string>(typ, nam) { } + /// Assignment operator + TypeName& operator=(const TypeName& copy) = default; + /// Split string pair according to default delimiter ('/') + static TypeName split(const std::string& type_name); + /// Split string pair according to custom delimiter + static TypeName split(const std::string& type_name, const std::string& delim); + }; + + /// 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 DigiAction { + friend class DigiKernel; + + protected: + /// Reference to the Digi context + const DigiKernel& m_kernel; + /// Action name + std::string m_name; + /// Property pool + PropertyManager m_properties; + /// Reference count. Initial value: 1 + long m_refCount = 1; + /// Default property: Output level + int m_outputLevel = 3; + /// + + /// Property: Support parallel execution + bool m_parallel = false; + protected: + + /// Functor to access elements by name + struct FindByName { + std::string _n; + FindByName(const std::string& n) : _n(n) {} + bool operator()(const DigiAction* a) { return a->name() == _n; } + }; + /// Actor class to manipulate action groups + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + template <typename T> class Actors { + public: + typedef typename std::vector<T*> _V; + _V m_v; + Actors() = default; + ~Actors() = default; + size_t size() const { return m_v.size(); } + void clear() { m_v.clear(); } + void add(T* obj) { m_v.push_back(obj); } + void add_front(T* obj) { m_v.insert(m_v.begin(), obj); } + const typename _V::value_type& operator[](size_t i) const + { return m_v[i];} + typename _V::value_type& operator[](size_t i) { return m_v[i];} + operator const _V&() const { return m_v; } + operator _V&() { return m_v; } + const _V* operator->() const { return &m_v; } + _V* operator->() { return &m_v; } + typename _V::iterator begin() { return m_v.begin(); } + typename _V::iterator end() { return m_v.end(); } + typename _V::const_iterator begin() const { return m_v.begin(); } + typename _V::const_iterator end() const { return m_v.end(); } + + /// Context updates + void updateContext(DigiContext* ctxt) { + (*this)(&T::updateContext,ctxt); + } + /// Element access by name + template <typename F> typename _V::value_type get(const F& f) const { + if (!m_v.empty()) { + typename _V::const_iterator i=std::find_if(m_v.begin(),m_v.end(),f); + return i==m_v.end() ? 0 : (*i); + } + return 0; + } + /// NON-CONST actions + template <typename R, typename Q> void operator()(R (Q::*pmf)()) { + if (m_v.empty()) + return; + for (typename _V::iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(); + } + template <typename R, typename Q, typename A0> void operator()(R (Q::*pmf)(A0&), A0& a0) { + if (m_v.empty()) + return; + for (typename _V::iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(a0); + } + template <typename R, typename Q, typename A0, typename A1> void operator()(R (Q::*pmf)(A0, A1), A0 a0, A1 a1) { + if (m_v.empty()) + return; + for (typename _V::iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(a0, a1); + } + /// CONST actions + template <typename R, typename Q> void operator()(R (Q::*pmf)() const) const { + if (m_v.empty()) + return; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(); + } + template <typename R, typename Q, typename A0> void operator()(R (Q::*pmf)(A0&) const, A0& a0) const { + if (m_v.empty()) + return; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(a0); + } + template <typename R, typename Q, typename A0, typename A1> void operator()(R (Q::*pmf)(A0, A1) const, A0 a0, + A1 a1) const { + if (m_v.empty()) + return; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + ((*i)->*pmf)(a0, a1); + } + /// CONST filters + template <typename Q> bool filter(bool (Q::*pmf)() const) const { + if (!m_v.empty()) + return true; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + if (!((*i)->*pmf)()) + return false; + return true; + } + template <typename Q, typename A0> bool filter(bool (Q::*pmf)(A0) const, A0 a0) const { + if (m_v.empty()) + return true; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + if (!((*i)->*pmf)(a0)) + return false; + return true; + } + template <typename Q, typename A0, typename A1> bool filter(bool (Q::*pmf)(A0, A1) const, A0 a0, A1 a1) const { + if (m_v.empty()) + return true; + for (typename _V::const_iterator i = m_v.begin(); i != m_v.end(); ++i) + if (!((*i)->*pmf)(a0, a1)) + return false; + return true; + } + }; + + protected: + /// Inhibit default constructor + DigiAction() = delete; + /// Inhibit copy constructor + DigiAction(const DigiAction& copy) = delete; + /// Inhibit move constructor + DigiAction(DigiAction&& copy) = delete; + /// Inhibit assignment operator + DigiAction& operator=(const DigiAction& copy) = delete; + /// Inhibit assignment operator + DigiAction& operator=(DigiAction&& copy) = delete; + + /// Default destructor + virtual ~DigiAction(); + + public: + /// Standard constructor + DigiAction(const DigiKernel& kernel, const std::string& nam); + /// Increase reference count + long addRef(); + /// Decrease reference count. Implicit destruction + long release(); + /// Access name of the action + const std::string& name() const { + return m_name; + } + /// Access name of the action + const char* c_name() const { + return m_name.c_str(); + } + /// Set the object name. + void setName(const std::string& new_name) { + m_name = new_name; + } + /// Access to the properties of the object + PropertyManager& properties() { + return m_properties; + } + /// Access the output level + PrintLevel outputLevel() const { + return (PrintLevel)m_outputLevel; + } + /// Set the output level; returns previous value + PrintLevel setOutputLevel(PrintLevel new_level); + /// Access parallization flag + bool executeParallel() const { + return m_parallel; + } + /// Set the parallization flag; returns previous value + bool setExecuteParallel(bool new_value); + + /// Declare property + template <typename T> DigiAction& declareProperty(const std::string& nam, T& val); + /// Declare property + template <typename T> DigiAction& declareProperty(const char* nam, T& val); + /// Check property for existence + bool hasProperty(const std::string& name) const; + /// Access single property + Property& property(const std::string& name); + /// Support for messages with variable output level using output level + void print(const char* fmt, ...) const; + /// Support for messages with variable output level using output level-1 + void printM1(const char* fmt, ...) const; + /// Support for messages with variable output level using output level-2 + void printM2(const char* fmt, ...) const; + /// Support for messages with variable output level using output level+1 + void printP1(const char* fmt, ...) const; + /// Support for messages with variable output level using output level+2 + void printP2(const char* fmt, ...) const; + + /// Support of debug messages. + void debug(const char* fmt, ...) const; + /// Support of info messages. + void info(const char* fmt, ...) const; + /// Support of warning messages. + void warning(const char* fmt, ...) const; + /// Support of error messages. + void error(const char* fmt, ...) const; + /// Action to support error messages. + bool return_error(bool return_value, const char* fmt, ...) const; + /// Support of fatal messages. Throws exception + void fatal(const char* fmt, ...) const; + /// Support of exceptions: Print fatal message and throw runtime_error. + void except(const char* fmt, ...) const; + + /// Main functional callback + virtual void execute(DigiContext& context) const = 0; + }; + + /// Declare property + template <typename T> DigiAction& DigiAction::declareProperty(const std::string& nam, T& val) { + m_properties.add(nam, val); + return *this; + } + + /// Declare property + template <typename T> DigiAction& DigiAction::declareProperty(const char* nam, T& val) { + m_properties.add(nam, val); + return *this; + } + } // End namespace digi +} // End namespace dd4hep + +#endif // DD4HEP_DDDIGI_DIGIACTION_H diff --git a/DDDigi/include/DDDigi/DigiActionSequence.h b/DDDigi/include/DDDigi/DigiActionSequence.h new file mode 100644 index 000000000..50f43710e --- /dev/null +++ b/DDDigi/include/DDDigi/DigiActionSequence.h @@ -0,0 +1,81 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIACTIONSEQUENCE_H +#define DD4HEP_DDDIGI_DIGIACTIONSEQUENCE_H + +// Framework include files +#include "DDDigi/DigiSynchronize.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + // Forward declarations + class DigiAction; + class DigiActionSequence; + + /// Concrete implementation of the Digitization event action sequence + /** + * The sequence dispatches the callbacks to all registered DigiAction + * members and all registered callbacks. + * + * Note Multi-Threading issue: + * Neither callbacks not the action list is protected against multiple + * threads calling the Digi callbacks! + * These must be protected in the user actions themselves. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiActionSequence : public DigiSynchronize { + protected: + /// Callback sequence before the digitization modules execute + CallbackSequence m_begin; + /// Callback sequence after the digitization modules executed + CallbackSequence m_end; + + protected: + /// Inhibit copy constructor + DigiActionSequence() = default; + /// Inhibit copy constructor + DigiActionSequence(const DigiActionSequence& copy) = delete; + /// Inhibit assignment operator + DigiActionSequence& operator=(const DigiActionSequence& copy) = delete; + + public: + /// Standard constructor + DigiActionSequence(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiActionSequence(); + /// Adopt a new action as part of the sequence. Sequence takes ownership. + void adopt(DigiAction* action); + /// Register external listener callbacks before starting the sequence + template <typename Q, typename T> + void begin(Q* p, void (T::*f)(DigiContext* context)) { + m_begin.add(p, f); + } + /// Register external listener callbacks after finishing the sequence + template <typename Q, typename T> + void end(Q* p, void (T::*f)(DigiContext* context)) { + m_end.add(p, f); + } + /// Begin-of-event callback + virtual void execute(DigiContext& context) const override; + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGIACTIONSEQUENCE_H diff --git a/DDDigi/include/DDDigi/DigiContext.h b/DDDigi/include/DDDigi/DigiContext.h new file mode 100644 index 000000000..aac4561ac --- /dev/null +++ b/DDDigi/include/DDDigi/DigiContext.h @@ -0,0 +1,126 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGICONTEXT_H +#define DD4HEP_DDDIGI_DIGICONTEXT_H + +// Framework incloude files +#include "DD4hep/Primitives.h" +#include "DDDigi/DigiData.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + // Forward declarations + class Detector; + class DetElement; + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Forward declarations + class DigiActionSequence; + class DigiKernel; + + /// Generic context to extend user, run and event information + /** + * A valid instance of the DigiContext is passed to every instance of a DigiAction at + * creation time. + * + * The DigiContext is the main thread specific accessor to the dd4hep, DDG4 and + * the user framework. + * - The access to the dd4hep objects is via the DigiContext::detectorDescription() call, + * - the access to DDG4 as a whole is supported via DigiContext::kernel() and + * - the access to the user gframework using a specialized implementation of: + * template <typename T> T& userFramework() const; + * + * A user defined implementations must be specialized somewhere in a compilation unit + * of the user framework, not in a header file. The framework object could host + * e.g. references for histogramming, logging, data access etc. + * + * This way any experiment/user related data processing framework can exhibit + * it's essential tools to DDG4 actions. + * + * A possible specialized implementations would look like the following: + * + * struct Gaudi { + * IMessageSvc* msg; + * IHistogramSvc* histos; + * .... + * }; + * + * template<> Gaudi& DigiContext::userFramework<Gaudi>() const { + * UserFramework& fw = m_kernel->userFramework(); + * if ( fw.first && &typeid(T) == fw.second ) return *(T*)fw.first; + * throw std::runtime_error("No user specified framework context present!"); + * } + * + * To access the user framework then use the following call: + * Gaudi* fw = context->userFramework<Gaudi>(); + * + * of course after having initialized it: + * Gaudi * fw = ...; + * GaudiKernel& kernel = ...; + * kernel.setUserFramework(fw); + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiContext { + friend class DigiKernel; + public: + typedef std::pair<void*, const std::type_info*> UserFramework; + protected: + /// Transient context variable - depending on the thread context: event reference + const DigiKernel* m_kernel = 0; + /// Reference to transient event + DigiEvent* m_event = 0; + + /// Inhibit default constructor + DigiContext() = delete; + /// Inhibit move constructor + DigiContext(DigiContext&&) = delete; + /// Inhibit copy constructor + DigiContext(const DigiContext&) = delete; + + public: + /// Initializing constructor + DigiContext(const DigiKernel* kernel_pointer, DigiEvent* event_pointer = 0); + /// 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; } + + /// Access to the user framework. Specialized function to be implemented by the client + template <typename T> T& framework() const; + /// Generic framework access + UserFramework& userFramework() const; + /// Access to detector description + Detector& detectorDescription() const; + /// Access to the main input action sequence from the kernel object + DigiActionSequence& inputAction() const; + /// Access to the main event action sequence from the kernel object + DigiActionSequence& eventAction() const; + /// Access to the main output action sequence from the kernel object + DigiActionSequence& outputAction() const; + }; + + } // End namespace digi +} // End namespace dd4hep + +#endif // DD4HEP_DDDIGI_DIGICONTEXT_H diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h new file mode 100644 index 000000000..cd4de7190 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiData.h @@ -0,0 +1,149 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIDATA_H +#define DD4HEP_DDDIGI_DIGIDATA_H + +/// Framework include files +#include "DD4hep/Primitives.h" +#include "DD4hep/ObjectExtensions.h" + +/// C/C++ include files +#include <memory> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + class DigiEvent; + + /// Container class to host energy deposits from simulation or noise processing + /* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + template <typename T> class DigiContainer { + public: + /// Default constructor + DigiContainer() = default; + /// Disable move constructor + DigiContainer(DigiContainer&& copy) = delete; + /// Disable copy constructor + DigiContainer(const DigiContainer& copy) = delete; + /// Default destructor + virtual ~DigiContainer() = default; + /// Disable move assignment + DigiContainer& operator=(DigiContainer&& copy) = delete; + /// Disable copy assignment + DigiContainer& operator=(const DigiContainer& copy) = delete; + }; + + + /// + /* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDeposit { + public: + /// Default constructor + DigiDeposit() = default; + /// Disable move constructor + DigiDeposit(DigiDeposit&& copy) = delete; + /// Disable copy constructor + DigiDeposit(const DigiDeposit& copy) = delete; + /// Default destructor + virtual ~DigiDeposit() = default; + /// Disable move assignment + DigiDeposit& operator=(DigiDeposit&& copy) = delete; + /// Disable copy assignment + DigiDeposit& operator=(const DigiDeposit& copy) = delete; + }; + + /// + /* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiCount { + public: + /// Default constructor + DigiCount() = default; + /// Disable move constructor + DigiCount(DigiCount&& copy) = delete; + /// Disable copy constructor + DigiCount(const DigiCount& copy) = delete; + /// Default destructor + virtual ~DigiCount() = default; + /// Disable move assignment + DigiCount& operator=(DigiCount&& copy) = delete; + /// Disable copy assignment + DigiCount& operator=(const DigiCount& copy) = delete; + }; + + typedef DigiContainer<DigiDeposit> DigiEnergyDeposits; + typedef DigiContainer<DigiCount> DigiCounts; + + /// User event data for DDDigi + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiEvent : public ObjectExtensions { + public: + std::map<unsigned long, std::shared_ptr<DigiEnergyDeposits> > energyDeposits; + std::map<unsigned long, std::shared_ptr<DigiCounts> > digitizations; + int eventNumber = 0; + public: +#if defined(G__ROOT) || defined(__CLING__) || defined(__ROOTCLING__) + /// Inhibit default constructor + DigiEvent(); +#endif + /// Inhibit move constructor + DigiEvent(DigiEvent&& copy) = delete; + /// Inhibit copy constructor + DigiEvent(const DigiEvent& copy) = delete; + /// Intializing constructor + DigiEvent(int num); + /// Default destructor + virtual ~DigiEvent(); + + /// Add an extension object to the detector element + void* addExtension(unsigned long long int k, ExtensionEntry* e) { + return ObjectExtensions::addExtension(k, e); + } + /// Add user extension object. Ownership is transferred and object deleted at the end of the event. + template <typename T> T* addExtension(T* ptr, bool take_ownership=true) { + ExtensionEntry* e = take_ownership + ? (ExtensionEntry*)new detail::DeleteExtension<T,T>(ptr) + : (ExtensionEntry*)new detail::SimpleExtension<T,T>(ptr); + return (T*)ObjectExtensions::addExtension(detail::typeHash64<T>(),e); + } + /// Access to type safe extension object. Exception is thrown if the object is invalid + template <typename T> T* extension(bool alert=true) { + return (T*)ObjectExtensions::extension(detail::typeHash64<T>(),alert); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#endif // DD4HEP_DDDIGI_DIGIDATA_H diff --git a/DDDigi/include/DDDigi/DigiFactories.h b/DDDigi/include/DDDigi/DigiFactories.h new file mode 100644 index 000000000..e7254dfdc --- /dev/null +++ b/DDDigi/include/DDDigi/DigiFactories.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 DDG4_DIGI_DIGIFACTORIES_H +#define DDG4_DIGI_DIGIFACTORIES_H + +// Framework include files +#include "DD4hep/Plugins.h" +#include "DD4hep/Detector.h" +#include "DD4hep/Primitives.h" + +// C/C++ include files +#include <string> +#include <map> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + class DetElement; + class Detector; + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + class DigiKernel; + class DigiAction; + } +} + +namespace { + + namespace DS = dd4hep::digi; + struct _ns { + typedef DS::DigiAction DA; + typedef DS::DigiKernel K; + typedef std::map<std::string,std::string> STRM; + }; + + /// Factory to create Digi action objects + DD4HEP_PLUGIN_FACTORY_ARGS_2(DS::DigiAction*,const _ns::K*, std::string) + { return new P(*a0,a1); } + +} + +/// Plugin defintion to create DigiAction objects +#define DECLARE_DIGIACTION_NS(name_space,name) namespace {\ + using name_space::name; \ + DD4HEP_PLUGINSVC_FACTORY(name,name,dd4hep::digi::DigiAction*(const _ns::K*,std::string),__LINE__) \ + } + +/// Plugin defintion to create DigiAction objects +#define DECLARE_DIGIACTION(name) DECLARE_DIGIACTION_NS(dd4hep::digi,name) + +#endif // DDG4_DIGI_DIGIFACTORIES_H diff --git a/DDDigi/include/DDDigi/DigiHandle.h b/DDDigi/include/DDDigi/DigiHandle.h new file mode 100644 index 000000000..13ec8cacd --- /dev/null +++ b/DDDigi/include/DDDigi/DigiHandle.h @@ -0,0 +1,120 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIHANDLE_H +#define DD4HEP_DDDIGI_DIGIHANDLE_H + +// Framework include files +#include "DD4hep/ComponentProperties.h" +#include "DD4hep/Detector.h" + +// C/C++ include files +#include <string> +#include <memory> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Forward declarations + class DigiKernel; + class DigiAction; + + /// Handle to Digi actions with built-in creation mechanism + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + template <typename TYPE> class DigiHandle { + protected: + void checked_assign(TYPE* p); + TYPE* null() { return 0; } + public: + /// Pointer to referenced object + mutable TYPE* value = 0; + /// Default constructor + explicit DigiHandle() = default; + /// Construction initialized with object pointer + DigiHandle(TYPE* typ); + /// Cross type initialization + template <typename T> DigiHandle(T* typ) : value(0) { + checked_assign(dynamic_cast<TYPE*>(typ)); + } + /// Copy constructor + DigiHandle(const DigiHandle& handle); + /// Move constructor + DigiHandle(DigiHandle&& handle); + /// Initializing constructor + DigiHandle(const DigiKernel&, const char* type_name); + /// Initializing constructor + DigiHandle(const DigiKernel&, const std::string& type_name); + /// Default destructor + ~DigiHandle(); + /// Property accessor + Property& operator[](const std::string& property_name) const; + /// Assignment operator + DigiHandle& operator=(const DigiHandle& handle); + /// Move assignment operator + DigiHandle& operator=(DigiHandle&& handle); + /// Assignment operator + DigiHandle& operator=(TYPE* ptr); + /// Validity check + bool operator!() const; + /// Access to the underlying object + DigiAction* action() const; + /// Access to the underlying object + TYPE* operator->() const; + /// Conversion operator + operator TYPE*() const; + /// Access to the underlying object + TYPE* get() const; + /// Release the underlying object + 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 + +#endif // DD4HEP_DDDIGI_DIGIHANDLE_H diff --git a/DDDigi/include/DDDigi/DigiInputAction.h b/DDDigi/include/DDDigi/DigiInputAction.h new file mode 100644 index 000000000..e43a17422 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiInputAction.h @@ -0,0 +1,59 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_DDDIGI_DIGIINPUTACTION_H +#define DD4HEP_DDDIGI_DIGIINPUTACTION_H + +/// Framework include files +#include "DDDigi/DigiAction.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + // Forward declarations + class DigiAction; + class DigiInputAction; + + /// Base class for input actions to the digitization + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiInputAction : public DigiAction { + protected: + std::vector<std::string> m_input; + + protected: + /// Inhibit copy constructor + DigiInputAction() = default; + /// Inhibit copy constructor + DigiInputAction(const DigiInputAction& copy) = delete; + /// Inhibit assignment operator + DigiInputAction& operator=(const DigiInputAction& copy) = delete; + + public: + /// Standard constructor + DigiInputAction(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiInputAction(); + /// Callback to read event input + virtual void execute(DigiContext& context) const override; + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGIINPUTACTION_H diff --git a/DDDigi/include/DDDigi/DigiKernel.h b/DDDigi/include/DDDigi/DigiKernel.h new file mode 100644 index 000000000..e6f265843 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiKernel.h @@ -0,0 +1,152 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIKERNEL_H +#define DD4HEP_DDDIGI_DIGIKERNEL_H + +// Framework include files +#include "DDDigi/DigiAction.h" + +// C/C++ include files +#include <map> +#include <mutex> +#include <atomic> +#include <typeinfo> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Forward declarations + class DigiActionSequence; + + /// Class, which allows all DigiAction derivatives to access the DDG4 kernel structures. + /** + * To implement access to a user specified framework please see class DigiContext. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiKernel { + public: + typedef std::map<std::string,int> ClientOutputLevels; + typedef std::pair<void*, const std::type_info*> UserFramework; + + private: + class Internals; + class Processor; + class Wrapper; + + /// Internal only data structures; + Internals* internals = 0; + + protected: + /// Detector description object + Detector* m_detDesc = 0; + /// Reference to the user framework + mutable UserFramework m_userFramework; + + /// Execute one single event + virtual void executeEvent(DigiContext* context); + /// Notify kernel that the execution of one single event finished + void notify(DigiContext* context); + /// Notify kernel that the execution of one single event finished + void notify(DigiContext* context, const std::exception& e); + + public: + /// Standard constructor for the master instance + DigiKernel(Detector& description); + + public: + /// Default destructor + virtual ~DigiKernel(); + +#ifndef __CINT__ + /// Instance accessor + static DigiKernel& instance(Detector& description); +#endif + /// Access to detector description + Detector& detectorDescription() const { return *m_detDesc; } + /// Generic framework access + UserFramework& userFramework() const { return m_userFramework; } + /// Set the framework context to the kernel object + template <typename T> void setUserFramework(T* object) { + m_userFramework = UserFramework(object,&typeid(T)); + } + + /** Property access */ + /// Access to the properties of the object + PropertyManager& properties(); + /// Print the property values + void printProperties() const; + /// Declare property + template <typename T> DigiKernel& declareProperty(const std::string& nam, T& val); + /// Declare property + template <typename T> DigiKernel& declareProperty(const char* nam, T& val); + /// Check property for existence + bool hasProperty(const std::string& name) const; + /// Access single property + Property& property(const std::string& name); + + /** Output level settings */ + /// Access the output level + PrintLevel outputLevel() const; + /// Set the global output level of the kernel object; returns previous value + PrintLevel setOutputLevel(PrintLevel new_level); + /// Fill cache with the global output level of a named object. Must be set before instantiation + void setOutputLevel(const std::string object, PrintLevel new_level); + /// Retrieve the global output level of a named object. + PrintLevel getOutputLevel(const std::string object) const; + + /// Construct detector geometry using description plugin + virtual void loadGeometry(const std::string& compact_file); + /// Load XML file + virtual void loadXML(const char* fname); + + /// Run the simulation: Configure Digi + virtual int configure(); + /// Run the simulation: Initialize Digi + virtual int initialize(); + /// Run the simulation: Simulate the number of events given by the property "NumEvents" + virtual int run(); + /// Run the simulation: Terminate Digi + virtual int terminate(); + + /// Access to the main input action sequence from the kernel object + DigiActionSequence& inputAction() const; + /// Access to the main event action sequence from the kernel object + DigiActionSequence& eventAction() const; + /// Access to the main output action sequence from the kernel object + DigiActionSequence& outputAction() const; + /// Submit a bunch of actions to be executed in parallel + virtual void submit (const DigiAction::Actors<DigiAction>& algorithms, DigiContext& context) const; + /// Submit a bunch of actions to be executed serially + virtual void execute(const DigiAction::Actors<DigiAction>& algorithms, DigiContext& context) const; + virtual void wait(DigiContext& context) const; + }; + /// Declare property + template <typename T> DigiKernel& DigiKernel::declareProperty(const std::string& nam, T& val) { + properties().add(nam, val); + return *this; + } + + /// Declare property + template <typename T> DigiKernel& DigiKernel::declareProperty(const char* nam, T& val) { + properties().add(nam, val); + return *this; + } + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGIKERNEL_H diff --git a/DDDigi/include/DDDigi/DigiLockedAction.h b/DDDigi/include/DDDigi/DigiLockedAction.h new file mode 100644 index 000000000..59e331503 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiLockedAction.h @@ -0,0 +1,66 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_DDDIGI_DIGILOCKEDACTION_H +#define DD4HEP_DDDIGI_DIGILOCKEDACTION_H + +/// Framework include files +#include "DDDigi/DigiAction.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 { + + // Forward declarations + class DigiAction; + class DigiLockedAction; + + /// Class to execute non-reentrant subaction in wrapped mode + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiLockedAction : public DigiAction { + protected: + /// Action lock to inhibit calling the non-reentrant underlying + std::mutex m_lock; + /// Reference to underlying action + DigiAction* m_action = 0; + protected: + /// Inhibit copy constructor + DigiLockedAction() = default; + /// Inhibit copy constructor + DigiLockedAction(const DigiLockedAction& copy) = delete; + /// Inhibit assignment operator + DigiLockedAction& operator=(const DigiLockedAction& copy) = delete; + + public: + /// Standard constructor + DigiLockedAction(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiLockedAction(); + /// Underlying object to be used during the locked execution + void use(DigiAction* action); + /// Callback to read event locked + virtual void execute(DigiContext& context) const override; + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGILOCKEDACTION_H diff --git a/DDDigi/include/DDDigi/DigiSynchronize.h b/DDDigi/include/DDDigi/DigiSynchronize.h new file mode 100644 index 000000000..cf4216d67 --- /dev/null +++ b/DDDigi/include/DDDigi/DigiSynchronize.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 DD4HEP_DDDIGI_DIGISYNCHRONIZE_H +#define DD4HEP_DDDIGI_DIGISYNCHRONIZE_H + +// Framework incloude files +#include "DDDigi/DigiAction.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + // Forward declarations + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiSynchronize : public DigiAction { + protected: + /// The list of action objects to be called + Actors<DigiAction> m_actors; + + public: + /// Standard constructor + DigiSynchronize(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiSynchronize(); + /// Get an action member by name + DigiAction* get(const std::string& name) const; + /// Access the children + const Actors<DigiAction>& children() const { + return m_actors; + } + /// Adopt a new action as part of the sequence. Sequence takes ownership. + void adopt(DigiAction* action); + /// Begin-of-event callback + virtual void execute(DigiContext& context) const override; + /// + void analyze(); + }; + + } // End namespace digi +} // End namespace dd4hep + +#endif // DD4HEP_DDDIGI_DIGISYNCHRONIZE_H diff --git a/DDDigi/plugins/DigiRandomNoise.cpp b/DDDigi/plugins/DigiRandomNoise.cpp new file mode 100644 index 000000000..f6cc0f8f4 --- /dev/null +++ b/DDDigi/plugins/DigiRandomNoise.cpp @@ -0,0 +1,107 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGIRANDOMNOISE_H +#define DD4HEP_DDDIGI_DIGIRANDOMNOISE_H + +// Framework include files +#include "DDDigi/DigiAction.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + // Forward declarations + class DigiAction; + class DigiRandomNoise; + + /// Class which applies random noise hits of a given amplitude + /** + * Class which applies random noise hits of a given amplitude + * to a segmented sensitive element. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiRandomNoise : public DigiAction { + protected: + double m_probability = 1.0; + double m_amplitude = 1.0; + + protected: + /// Inhibit copy constructor + DigiRandomNoise() = default; + /// Inhibit copy constructor + DigiRandomNoise(const DigiRandomNoise& copy) = delete; + /// Inhibit assignment operator + DigiRandomNoise& operator=(const DigiRandomNoise& copy) = delete; + + public: + /// Standard constructor + DigiRandomNoise(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiRandomNoise(); + /// Callback to read event input + virtual void execute(DigiContext& context) const override; + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGIRANDOMNOISE_H + +//========================================================================== +// 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/InstanceCount.h" +#include "DDDigi/DigiFactories.h" +//#include "DDDigi/DigiRandomNoise.h" + +// C/C++ include files + +using namespace std; +using namespace dd4hep::digi; + +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiRandomNoise) + +/// Standard constructor +DigiRandomNoise::DigiRandomNoise(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + declareProperty("Probability", m_probability); + declareProperty("Amplitude", m_amplitude); + InstanceCount::increment(this); +} + +/// Default destructor +DigiRandomNoise::~DigiRandomNoise() { + InstanceCount::decrement(this); +} + +/// Pre-track action callback +void DigiRandomNoise::execute(DigiContext& /* context */) const { + info("+++ Virtual method execute() MUST be overloaded!"); +} diff --git a/DDDigi/plugins/DigiTestAction.cpp b/DDDigi/plugins/DigiTestAction.cpp new file mode 100644 index 000000000..a9d404b95 --- /dev/null +++ b/DDDigi/plugins/DigiTestAction.cpp @@ -0,0 +1,107 @@ +//========================================================================== +// 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 DD4HEP_DDDIGI_DIGITESTACTION_H +#define DD4HEP_DDDIGI_DIGITESTACTION_H + +// Framework include files +#include "DDDigi/DigiAction.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + // Forward declarations + class DigiAction; + class DigiTestAction; + + /// Class which applies random noise hits of a given amplitude + /** + * Class which applies random noise hits of a given amplitude + * to a segmented sensitive element. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiTestAction : public DigiAction { + protected: + /// Sleep period to fake execution [milliseconds] + int m_sleep = 0; + protected: + /// Inhibit copy constructor + DigiTestAction() = default; + /// Inhibit copy constructor + DigiTestAction(const DigiTestAction& copy) = delete; + /// Inhibit assignment operator + DigiTestAction& operator=(const DigiTestAction& copy) = delete; + + public: + /// Standard constructor + DigiTestAction(const DigiKernel& kernel, const std::string& nam); + /// Default destructor + virtual ~DigiTestAction(); + /// Callback to read event input + virtual void execute(DigiContext& context) const override; + }; + + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGITESTACTION_H + +//========================================================================== +// 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/InstanceCount.h" +#include "DDDigi/DigiFactories.h" +//#include "DDDigi/DigiTestAction.h" + +// C/C++ include files + +using namespace std; +using namespace dd4hep::digi; + +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiTestAction) + +/// Standard constructor +DigiTestAction::DigiTestAction(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + declareProperty("sleep", m_sleep = 0); + InstanceCount::increment(this); +} + +/// Default destructor +DigiTestAction::~DigiTestAction() { + InstanceCount::decrement(this); +} + +/// Pre-track action callback +void DigiTestAction::execute(DigiContext& context) const { + debug("+++ Event: %8d (DigiTestAction) %d msec", + context.event().eventNumber, m_sleep); + if ( m_sleep > 0 ) ::usleep(1000*m_sleep); +} diff --git a/DDDigi/plugins/dummy.cpp b/DDDigi/plugins/dummy.cpp new file mode 100644 index 000000000..b34f3609e --- /dev/null +++ b/DDDigi/plugins/dummy.cpp @@ -0,0 +1,53 @@ +//========================================================================== +// 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 "DDDigi/DigiFactories.h" + +// C/C++ include files +#include <cerrno> +#include <cstdlib> +#include <sstream> + +#include "DDDigi/DigiInputAction.h" +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiInputAction) + +#include "DDDigi/DigiActionSequence.h" +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiActionSequence) + +#include "DDDigi/DigiSynchronize.h" +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSynchronize) + +#include "DDDigi/DigiLockedAction.h" +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiLockedAction) + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::detail; + + + +/// Basic entry point +/** + * Factory: DD4hep_GeometryDisplay + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2014 + */ +static long dummy(Detector&, int, char**) { + return 0; +} +DECLARE_APPLY(DDDigi_dummy,dummy) diff --git a/DDDigi/python/DDDigi.py b/DDDigi/python/DDDigi.py new file mode 100644 index 000000000..8f4879de9 --- /dev/null +++ b/DDDigi/python/DDDigi.py @@ -0,0 +1,372 @@ +#========================================================================== +# 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 logging +from dd4hep_base import * + +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) +def loadDDDigi(): + ## import ROOT ## done in import * above + from ROOT import gSystem + + ## Try to load libglapi to avoid issues with TLS Static + ## Turn off all errors from ROOT about the library missing + orgLevel = ROOT.gErrorIgnoreLevel + ROOT.gErrorIgnoreLevel=6000 + gSystem.Load("libglapi") + ROOT.gErrorIgnoreLevel=orgLevel + + import platform + import os + 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()) + 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: + dd4hep = loadDDDigi() +except Exception as X: + logging.info('+--%-100s--+',100*'-') + logging.info('| %-100s |','Failed to load DDDigi library:') + logging.info('| %-100s |',str(X)) + logging.info('+--%-100s--+',100*'-') + exit(1) + +core = dd4hep +digi = dd4hep.digi +Kernel = digi.KernelHandle +Interface = digi.DigiActionCreation +Detector = core.Detector +# +from dd4hep_base import std, std_vector, std_list, std_map, std_pair +# +#--------------------------------------------------------------------------- +def _constant(self,name): + return self.constantAsString(name) + +Detector.globalVal = _constant +#--------------------------------------------------------------------------- + +""" + Import the Detector constants into the DDDigi namespace +""" +def importConstants(description,namespace=None,debug=False): + scope = current + ns = current + if namespace is not None and not hasattr(current,namespace): + import imp + m = imp.new_module('DDDigi.'+namespace) + setattr(current,namespace,m) + ns = m + evaluator = dd4hep.g4Evaluator() + cnt = 0 + num = 0 + todo = {} + strings = {} + for c in description.constants(): + if c.second.dataType == 'string': + strings[c.first] = c.second.GetTitle() + else: + todo[c.first] = c.second.GetTitle().replace('(int)','') + while len(todo) and cnt<100: + cnt = cnt + 1 + if cnt == 100: + logging.info('%s %d out of %d %s "%s": [%s]\n+++ %s',\ + '+++ FAILED to import', + len(todo),len(todo)+num, + 'global values into namespace', + ns.__name__,'Try to continue anyway',100*'=') + for k,v in todo.items(): + if not hasattr(ns,k): + logging.info('+++ FAILED to import: "'+k+'" = "'+str(v)+'"') + logging.info('+++ %s',100*'=') + + for k,v in todo.items(): + if not hasattr(ns,k): + val = evaluator.evaluate(v) + status = evaluator.status() + if status == 0: + evaluator.setVariable(k,val) + setattr(ns,k,val) + if debug: logging.info('Imported global value: "'+k+'" = "'+str(val)+'" into namespace'+ns.__name__) + del todo[k] + num = num + 1 + if cnt<100: + logging.info('+++ Imported %d global values to namespace:%s',num,ns.__name__,) + +#--------------------------------------------------------------------------- +def _getKernelProperty(self, name): + #logging.info('_getKernelProperty: %s %s',str(type(self)),name) + ret = Interface.getPropertyKernel(self.get(),name) + if ret.status > 0: + return ret.data + elif hasattr(self.get(),name): + return getattr(self.get(),name) + elif hasattr(self,name): + return getattr(self,name) + msg = 'DigiKernel::GetProperty [Unhandled]: Cannot access Kernel.'+name + raise KeyError(msg) + +#--------------------------------------------------------------------------- +def _setKernelProperty(self, name, value): + #logging.info('_setKernelProperty: %s %s',name,str(value)) + if Interface.setPropertyKernel(self.get(),name,str(value)): + return + msg = 'DigiKernel::SetProperty [Unhandled]: Cannot set Kernel.'+name+' = '+str(value) + raise KeyError(msg) + +#--------------------------------------------------------------------------- +def _kernel_terminate(self): return self.get().terminate() +#--------------------------------------------------------------------------- +Kernel.__getattr__ = _getKernelProperty +Kernel.__setattr__ = _setKernelProperty +Kernel.terminate = _kernel_terminate +#--------------------------------------------------------------------------- +ActionHandle = digi.ActionHandle +#--------------------------------------------------------------------------- +def Action(kernel, nam, parallel=False): + obj = Interface.createAction(kernel,nam) + obj.parallel = parallel + return obj +#--------------------------------------------------------------------------- +def TestAction(kernel, nam, sleep=0): + obj = Interface.createAction(kernel,'DigiTestAction/'+nam) + if sleep != 0: + obj.sleep = sleep + return obj +#--------------------------------------------------------------------------- +def ActionSequence(kernel, nam, parallel=False): + obj = Interface.createSequence(kernel,nam) + obj.parallel = parallel + return obj +#--------------------------------------------------------------------------- +def Synchronize(kernel, nam, parallel=False): + obj = Interface.createSync(kernel,nam) + obj.parallel = parallel + return obj +#--------------------------------------------------------------------------- +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') + +#--------------------------------------------------------------------------- +def _get(self, name): + import traceback + #logging.info('_get: %s %s',str(type(self)),name) + a = Interface.toAction(self) + ret = Interface.getProperty(a,name) + if ret.status > 0: + return ret.data + elif hasattr(self.action,name): + return getattr(self.action,name) + elif 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 + raise KeyError(msg) + +def _set(self, name, value): + a = Interface.toAction(self) + if Interface.setProperty(a,name,str(value)): + return + msg = 'DigiAction::SetProperty [Unhandled]: Cannot set '+a.name()+'.'+name+' = '+str(value) + raise KeyError(msg) + +def _props(obj): + _import_class('digi',obj) + cl = getattr(current,obj) + cl.__getattr__ = _get + cl.__setattr__ = _set + +_props('ActionHandle') +_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()) + 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): + logging.info('+++ List of sensitive detectors:') + dets = self.activeDetectors() + for d in dets: + logging.info('+++ %-32s ---> type:%-12s', d['name'], d['type']) + + def setupDetector(self,name,collections=None,modules=None): + parameterDict = {} + 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: + ol = m.OutputLevel # Check if the object is a DigiAction.... + 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) + 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") + 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") + 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") + 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 + diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C new file mode 100644 index 000000000..7c4f8b9ad --- /dev/null +++ b/DDDigi/python/DDDigiDict.C @@ -0,0 +1,155 @@ +//========================================================================== +// 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. +// +//==================================================================== +// +// Define the ROOT dictionaries for all data classes to be saved +// which are created by the DDG4 examples. +// +// Author : M.Frank +// +//==================================================================== + +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wunused" +#pragma GCC diagnostic ignored "-Woverlength-strings" + +#elif defined(__llvm__) || defined(__APPLE__) + +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdeprecated" +#pragma clang diagnostic ignored "-Wunused" +#pragma clang diagnostic ignored "-Woverlength-strings" +#endif + +#include "DDDigi/DigiData.h" +#include "DDDigi/DigiHandle.h" +#include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiSynchronize.h" +#include "DDDigi/DigiActionSequence.h" + +struct DDDigiDict {}; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + +#define ACTIONHANDLE(x) \ + struct x##Handle { \ + Digi##x* action; \ + explicit x##Handle(Digi##x* a) : action(a) { if ( action ) action->addRef();} \ + x##Handle(const x##Handle& h) : action(h.action) { if ( action ) action->addRef();} \ + ~x##Handle() { if ( action) action->release();} \ + Digi##x* release() { Digi##x* tmp = action; action=0; return tmp; } \ + operator dd4hep::digi::Digi##x* () const { return action; } \ + Digi##x* operator->() const { return action; } \ + Digi##x* get() const { return action; } \ + } + + ACTIONHANDLE(Action); + ACTIONHANDLE(ActionSequence); + ACTIONHANDLE(Synchronize); + + struct PropertyResult { + std::string data; + int status; + PropertyResult() : status(0) {} + PropertyResult(const std::string& d, int s) : data(d), status(s) {} + PropertyResult(const PropertyResult& c) : data(c.data), status(c.status) {} + ~PropertyResult() {} + }; + + struct DigiActionCreation { + template <typename H,typename T> static + H cr(KernelHandle& kernel, const std::string& name_type) { + T action(*kernel.get(),name_type); + H handle(action.get()); + return handle; + } + static ActionHandle createAction(KernelHandle& kernel, const std::string& name_type) + { return cr<ActionHandle,DigiHandle<DigiAction> >(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(DigiActionSequence* f) { return f; } + static DigiAction* toAction(DigiSynchronize* f) { return f; } + + static DigiAction* toAction(ActionHandle f) { return f.action; } + static DigiAction* toAction(ActionSequenceHandle f) { return f.action; } + static DigiAction* toAction(SynchronizeHandle f) { return f.action; } + + static PropertyResult getProperty(DigiAction* action, const std::string& name) { + if ( action->hasProperty(name) ) { + return PropertyResult(action->property(name).str(),1); + } + return PropertyResult("",0); + } + static int setProperty(DigiAction* action, const std::string& name, const std::string& value) { + if ( action->hasProperty(name) ) { + action->property(name).str(value); + return 1; + } + return 0; + } + static PropertyResult getPropertyKernel(DigiKernel* kernel, const std::string& name) { + if ( kernel->hasProperty(name) ) { + return PropertyResult(kernel->property(name).str(),1); + } + return PropertyResult("",0); + } + static int setPropertyKernel(DigiKernel* kernel, const std::string& name, const std::string& value) { + if ( kernel->hasProperty(name) ) { + kernel->property(name).str(value); + return 1; + } + return 0; + } + }; + } +} + +// CINT configuration +#if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +using namespace std; + +#pragma link C++ namespace dd4hep; +#pragma link C++ namespace dd4hep::digi; + +#pragma link C++ class dd4hep::digi::DigiActionCreation; +#pragma link C++ class dd4hep::digi::KernelHandle; +#pragma link C++ class dd4hep::digi::DigiKernel; +#pragma link C++ class dd4hep::digi::DigiContext; + +#pragma link C++ class dd4hep::digi::DigiAction; +#pragma link C++ class dd4hep::digi::ActionHandle; + +#pragma link C++ class dd4hep::digi::DigiActionSequence; +#pragma link C++ class dd4hep::digi::ActionSequenceHandle; + +#pragma link C++ class dd4hep::digi::DigiSynchronize; +#pragma link C++ class dd4hep::digi::SynchronizeHandle; + +#pragma link C++ class dd4hep::digi::DigiEvent; +#pragma link C++ class dd4hep::digi::DigiEnergyDeposits+; +#pragma link C++ class dd4hep::digi::DigiCounts+; + +#endif diff --git a/DDDigi/src/DigiAction.cpp b/DDDigi/src/DigiAction.cpp new file mode 100644 index 000000000..adc16b1e2 --- /dev/null +++ b/DDDigi/src/DigiAction.cpp @@ -0,0 +1,208 @@ +//========================================================================== +// 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/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) { + typ = type_name.substr(0, idx); + nam = type_name.substr(idx + 1); + } + return TypeName(typ, nam); +} + +TypeName TypeName::split(const string& type_name) { + return split(type_name,"/"); +} + +/// Standard constructor +DigiAction::DigiAction(const DigiKernel& krnl, const string& nam) + : m_kernel(krnl), m_name(nam), m_outputLevel(INFO) +{ + InstanceCount::increment(this); + declareProperty("Name", m_name); + declareProperty("name", m_name); + declareProperty("parallel", m_parallel); + declareProperty("OutputLevel", m_outputLevel); +} + +/// Default destructor +DigiAction::~DigiAction() { + InstanceCount::decrement(this); +} + +/// Implicit destruction +long DigiAction::addRef() { + return ++m_refCount; +} + +/// Decrease reference count. Implicit destruction +long DigiAction::release() { + long count = --m_refCount; + if (m_refCount <= 0) { + printM1("DigiAction: Deleting object %s of type %s Pointer:%p", + m_name.c_str(),typeName(typeid(*this)).c_str(),(void*)this); + delete this; + } + return count; +} + +/// Set the output level; returns previous value +PrintLevel DigiAction::setOutputLevel(PrintLevel new_level) { + int old = m_outputLevel; + m_outputLevel = new_level; + return (PrintLevel)old; +} + +/// Set the parallization flag; returns previous value +bool DigiAction::setExecuteParallel(bool new_value) { + bool old = m_parallel; + m_parallel = new_value; + return old; +} + +/// Check property for existence +bool DigiAction::hasProperty(const string& nam) const { + return m_properties.exists(nam); +} + +/// Access single property +Property& DigiAction::property(const 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); + if ( level >= printLevel() ) { + va_list args; + va_start(args, fmt); + dd4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args); + va_end(args); + } +} + +/// 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); + if ( level >= printLevel() ) { + va_list args; + va_start(args, fmt); + dd4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args); + va_end(args); + } +} + +/// 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); + if ( level >= printLevel() ) { + va_list args; + va_start(args, fmt); + dd4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args); + va_end(args); + } +} + +/// 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); + if ( level >= printLevel() ) { + va_list args; + va_start(args, fmt); + dd4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args); + va_end(args); + } +} + +/// 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); + if ( level >= printLevel() ) { + va_list args; + va_start(args, fmt); + dd4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args); + va_end(args); + } +} + +/// Support of debug messages. +void DigiAction::debug(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::DEBUG, m_name, fmt, args); + va_end(args); +} + +/// Support of info messages. +void DigiAction::info(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::INFO, m_name, fmt, args); + va_end(args); +} + +/// Support of warning messages. +void DigiAction::warning(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::WARNING, m_name, fmt, args); + va_end(args); +} + +/// Action to support error messages. +void DigiAction::error(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::ERROR, m_name, fmt, args); + va_end(args); +} + +/// Action to support error messages. +bool DigiAction::return_error(bool return_value, const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::ERROR, m_name, fmt, args); + va_end(args); + return return_value; +} + +/// Support of fatal messages. Throws exception if required. +void DigiAction::fatal(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + dd4hep::printout(dd4hep::FATAL, m_name, fmt, args); + va_end(args); +} + +/// Support of exceptions: Print fatal message and throw runtime_error. +void DigiAction::except(const char* fmt, ...) const { + va_list args; + va_start(args, fmt); + string err = dd4hep::format(m_name, fmt, args); + dd4hep::printout(dd4hep::FATAL, m_name, err.c_str()); + va_end(args); + throw runtime_error(err); +} diff --git a/DDDigi/src/DigiActionSequence.cpp b/DDDigi/src/DigiActionSequence.cpp new file mode 100644 index 000000000..31cf428d2 --- /dev/null +++ b/DDDigi/src/DigiActionSequence.cpp @@ -0,0 +1,50 @@ +//========================================================================== +// 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/DigiActionSequence.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace dd4hep::digi; + +/// Standard constructor +DigiActionSequence::DigiActionSequence(const DigiKernel& kernel, const string& nam) + : DigiSynchronize(kernel, nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +DigiActionSequence::~DigiActionSequence() { + m_begin.clear(); + m_end.clear(); + InstanceCount::decrement(this); +} + +/// Adopt a new action as part of the sequence. Sequence takes ownership. +void DigiActionSequence::adopt(DigiAction* action) { + this->DigiSynchronize::adopt(action); +} + +/// Pre-track action callback +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)); + m_end(&context); +} diff --git a/DDDigi/src/DigiContext.cpp b/DDDigi/src/DigiContext.cpp new file mode 100644 index 000000000..3575def8f --- /dev/null +++ b/DDDigi/src/DigiContext.cpp @@ -0,0 +1,79 @@ +//========================================================================== +// 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/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) +{ + if ( !m_kernel ) { + except("DigiContext","Cannot initialize Digitization context with invalid DigiKernel!"); + } + InstanceCount::increment(this); +} + +/// Default destructor +DigiContext::~DigiContext() { + // Do not delete run and event structures here. This is done outside in the framework + InstanceCount::decrement(this); +} + +/// Set the geant4 event reference +void DigiContext::setEvent(DigiEvent* new_event) { + m_event = new_event; +} + +/// 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; +} + +/// Access to detector description +Detector& DigiContext::detectorDescription() const { + return m_kernel->detectorDescription(); +} + +/// Generic framework access +DigiContext::UserFramework& DigiContext::userFramework() const { + return m_kernel->userFramework(); +} + +/// Access to the main input action sequence from the kernel object +DigiActionSequence& DigiContext::inputAction() const { + return m_kernel->inputAction(); +} + +/// Access to the main event action sequence from the kernel object +DigiActionSequence& DigiContext::eventAction() const { + return m_kernel->eventAction(); +} + +/// Access to the main output action sequence from the kernel object +DigiActionSequence& DigiContext::outputAction() const { + return m_kernel->outputAction(); +} + diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp new file mode 100644 index 000000000..80c92748b --- /dev/null +++ b/DDDigi/src/DigiData.cpp @@ -0,0 +1,44 @@ +//========================================================================== +// 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/InstanceCount.h" +#define G__ROOT +#include "DDDigi/DigiData.h" + +// C/C++ include files + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::digi; + +/// Intializing constructor +DigiEvent::DigiEvent() + : ObjectExtensions(typeid(DigiEvent)) +{ + InstanceCount::increment(this); +} + +/// Intializing constructor +DigiEvent::DigiEvent(int ev_num) + : ObjectExtensions(typeid(DigiEvent)), eventNumber(ev_num) +{ + InstanceCount::increment(this); +} + +/// Default destructor +DigiEvent::~DigiEvent() +{ + InstanceCount::decrement(this); +} diff --git a/DDDigi/src/DigiHandle.cpp b/DDDigi/src/DigiHandle.cpp new file mode 100644 index 000000000..09500703d --- /dev/null +++ b/DDDigi/src/DigiHandle.cpp @@ -0,0 +1,190 @@ +//========================================================================== +// 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/Detector.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" + +#include "DDDigi/DigiHandle.h" +#include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiAction.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::digi; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + template <typename TYPE> static inline TYPE* checked_value(TYPE* p) { + if (p) { + return p; + } + except("DigiHandle","Attempt to access an invalid object of type:%s!", + typeName(typeid(TYPE)).c_str()); + return 0; + } + + template <typename TYPE> DigiHandle<TYPE>::DigiHandle(TYPE* typ) : value(typ) { + if (value) + value->addRef(); + } + + template <typename TYPE> DigiHandle<TYPE>::DigiHandle(const DigiHandle<TYPE>& handle) : value(handle.get()) + { + if (value) + value->addRef(); + } + + template <typename TYPE> DigiHandle<TYPE>::DigiHandle(DigiHandle<TYPE>&& handle) : value(handle.get()) + { + handle.value = 0; + } + + template <typename TYPE> TYPE* _create_object(const DigiKernel& kernel, const TypeName& typ) { + DigiAction* object = PluginService::Create<DigiAction*>(typ.first, &kernel, typ.second); + if (!object && typ.first == typ.second) { + string _t = typeName(typeid(TYPE)); + printout(DEBUG, "DigiHandle", "Object factory for %s not found. Try out %s", + typ.second.c_str(), _t.c_str()); + object = PluginService::Create<DigiAction*>(_t, &kernel, typ.second); + if (!object) { + size_t idx = _t.rfind(':'); + if (idx != string::npos) + _t = string(_t.substr(idx + 1)); + printout(DEBUG, "DigiHandle", "Try out object factory for %s",_t.c_str()); + object = PluginService::Create<DigiAction*>(_t, &kernel, typ.second); + } + } + if (object) { + TYPE* ptr = dynamic_cast<TYPE*>(object); + if (ptr) { + return ptr; + } + except("DigiHandle", "Failed to convert object of type %s to handle of type %s!", + typ.first.c_str(),typ.second.c_str()); + } + except("DigiHandle", "Failed to create object of type %s!", typ.first.c_str()); + return 0; + } + + template <typename TYPE> + DigiHandle<TYPE>::DigiHandle(const DigiKernel& kernel, const string& type_name) { + value = _create_object<TYPE>(kernel,TypeName::split(type_name)); + } + + template <typename TYPE> + DigiHandle<TYPE>::DigiHandle(const DigiKernel& kernel, const char* type_name_char) { + value = _create_object<TYPE>(kernel,TypeName::split(type_name_char ? type_name_char : "????")); + } + + template <typename TYPE> DigiHandle<TYPE>::~DigiHandle() { + if (value) + value->release(); + value = 0; + } + + template <typename TYPE> TYPE* DigiHandle<TYPE>::release() { + TYPE* temp = value; + value = 0; + return temp; + } + + template <typename TYPE> void DigiHandle<TYPE>::checked_assign(TYPE* p) { + if (value) + value->release(); + value = checked_value(p); + if (value) + value->addRef(); + } + + template <typename TYPE> Property& DigiHandle<TYPE>::operator[](const string& property_name) const { + PropertyManager& pm = checked_value(value)->properties(); + return pm[property_name]; + } + + template <typename TYPE> DigiHandle<TYPE>::operator TYPE*() const { + return checked_value(value); + } + + template <typename TYPE> bool DigiHandle<TYPE>::operator!() const { + return 0 == value; + } + + template <typename TYPE> TYPE* DigiHandle<TYPE>::get() const { + return checked_value(value); + } + + template <typename TYPE> TYPE* DigiHandle<TYPE>::operator->() const { + return checked_value(value); + } + + template <typename TYPE> DigiAction* DigiHandle<TYPE>::action() const { + return checked_value(value); + } + + /// Assignment operator + template <typename TYPE> DigiHandle<TYPE>& DigiHandle<TYPE>::operator=(const DigiHandle& handle) { + if ( &handle != this ) { + TYPE* point = value; + value = handle.get(); + if ( value ) value->addRef(); + if ( point ) point->release(); + } + return *this; + } + + /// Assignment move operator + template <typename TYPE> DigiHandle<TYPE>& DigiHandle<TYPE>::operator=(DigiHandle&& handle) { + if ( value ) value->release(); + value = handle.get(); + handle.value = 0; + return *this; + } + + template <typename TYPE> DigiHandle<TYPE>& DigiHandle<TYPE>::operator=(TYPE* pointer) { + if ( pointer != value ) { + TYPE* point = value; + value = pointer; + if ( value ) value->addRef(); + if ( point ) point->release(); + } + return *this; + } + + KernelHandle::KernelHandle() { + value = &DigiKernel::instance(Detector::getInstance()); + } + KernelHandle::KernelHandle(DigiKernel* k) : value(k) { + } + } +} + +#include "DDDigi/DigiSynchronize.h" +#include "DDDigi/DigiActionSequence.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + template class DigiHandle<DigiAction>; + template class DigiHandle<DigiSynchronize>; + template class DigiHandle<DigiActionSequence>; + } +} diff --git a/DDDigi/src/DigiInputAction.cpp b/DDDigi/src/DigiInputAction.cpp new file mode 100644 index 000000000..b3604b1f1 --- /dev/null +++ b/DDDigi/src/DigiInputAction.cpp @@ -0,0 +1,44 @@ +//========================================================================== +// 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/DigiInputAction.h" + +// C/C++ include files +#include <stdexcept> +#include <unistd.h> + +using namespace std; +using namespace dd4hep::digi; + +/// Standard constructor +DigiInputAction::DigiInputAction(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + declareProperty("Input", m_input); + InstanceCount::increment(this); +} + +/// Default destructor +DigiInputAction::~DigiInputAction() { + InstanceCount::decrement(this); +} + +/// Pre-track action callback +void DigiInputAction::execute(DigiContext& /* context */) const { + ::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 new file mode 100644 index 000000000..a3aab4ca6 --- /dev/null +++ b/DDDigi/src/DigiKernel.cpp @@ -0,0 +1,365 @@ +//========================================================================== +// 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/Detector.h" +#include "DD4hep/Memory.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Primitives.h" +#include "DD4hep/InstanceCount.h" + +#include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiActionSequence.h" + +#include "tbb/tbb.h" + +// C/C++ include files +#include <stdexcept> +#include <algorithm> +#include <memory> +#include <chrono> + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::digi; + +/// DigiKernel herlp class: Container of instance variabled +/* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ +class DigiKernel::Internals { +public: + /// Property pool + PropertyManager properties; + /// Property: Client output levels + ClientOutputLevels clientLevels; + /// Atomic counter: Number of events still to be processed in this run + std::atomic_int eventsToDo; + + /// The main data input action sequence + DigiActionSequence* inputAction = 0; + /// The main event action sequence + DigiActionSequence* eventAction = 0; + /// The main data output action sequence + DigiActionSequence* outputAction = 0; + /// TBB initializer (If TBB is used) + void* tbbInit = 0; + /// Property: Output level + int outputLevel; + /// Property: maximum number of events to be processed (if < 0: infinite) + int numEvents; + /// Property: maximum number of events to be processed in parallel (if TBB) + int maxEventsParallel; + /// Property: maximum number of threads to be used (if TBB) + int numThreads; + /// Property: Allow to stop execution from interactive prompt + bool stop = false; + Internals() = default; + ~Internals() = default; +}; + +/// DigiKernel herlp class: TBB wrapper to execute DigiAction instances +/* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ +class DigiKernel::Wrapper { +public: + DigiContext& context; + DigiAction* action = 0; + Wrapper(DigiContext& c, DigiAction* a) + : context(c), action(a) {} + Wrapper(Wrapper&& copy) = default; + Wrapper(const Wrapper& copy) = default; + Wrapper& operator=(Wrapper&& copy) = default; + Wrapper& operator=(const Wrapper& copy) = default; + void operator()() const { + action->execute(context); + } +}; + +/// DigiKernel herlp class: TBB wrapper to execute a full event +/* + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ +class DigiKernel::Processor { + DigiKernel& kernel; +public: + Processor(DigiKernel& k) : kernel(k) {} + Processor(Processor&& l) = default; + Processor(const Processor& l) = default; + void operator()() const { + int todo; + while( !kernel.internals->stop && + (todo = --kernel.internals->eventsToDo) >= 0 ) { + int ev_num = kernel.internals->numEvents - todo; + unique_ptr<DigiContext> c = make_unique<DigiContext>(&kernel); + unique_ptr<DigiEvent> e = make_unique<DigiEvent>(ev_num); + c->setEvent(e.release()); + kernel.executeEvent(c.release()); + } + } +}; + + +/// Standard constructor +DigiKernel::DigiKernel(Detector& description_ref) + : m_detDesc(&description_ref) +{ + internals = new Internals(); +#ifdef DD4HEP_USE_TBB + internals->numThreads = tbb::task_scheduler_init::default_num_threads(); +#else + internals->numThreads = -1; +#endif + declareProperty("maxEventsParallel",internals->maxEventsParallel = 1); + declareProperty("numThreads", internals->numThreads); + declareProperty("numEvents", internals->numEvents = 10); + declareProperty("stop", internals->stop = false); + declareProperty("OutputLevel", internals->outputLevel = DEBUG); + declareProperty("OutputLevels", internals->clientLevels); + internals->inputAction = new DigiActionSequence(*this, "InputAction"); + internals->eventAction = new DigiActionSequence(*this, "EventAction"); + internals->outputAction = new DigiActionSequence(*this, "OutputAction"); + internals->inputAction->setExecuteParallel(false); + internals->eventAction->setExecuteParallel(false); + internals->outputAction->setExecuteParallel(false); + InstanceCount::increment(this); +} + +/// Default destructor +DigiKernel::~DigiKernel() { +#ifdef DD4HEP_USE_TBB + tbb::task_scheduler_init* init = (tbb::task_scheduler_init*)internals->tbbInit; + if ( init ) delete init; +#endif + detail::releasePtr(internals->outputAction); + detail::releasePtr(internals->eventAction); + detail::releasePtr(internals->inputAction); + detail::deletePtr(internals); + InstanceCount::decrement(this); +} + +/// Instance accessor +DigiKernel& DigiKernel::instance(Detector& description) { + static dd4hep::dd4hep_ptr<DigiKernel> s_main_instance(0); + if ( 0 == s_main_instance.get() ) { + static std::mutex kernel_mutex; + std::lock_guard<std::mutex> lock(kernel_mutex); + if ( 0 == s_main_instance.get() ) { // Need to check again! + s_main_instance.adopt(new DigiKernel(description)); + } + } + return *(s_main_instance.get()); +} + +/// Access to the properties of the object +PropertyManager& DigiKernel::properties() { + return internals->properties; +} + +/// Print the property values +void DigiKernel::printProperties() const { + printout(ALWAYS,"DigiKernel","OutputLevel: %d", internals->outputLevel); + 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); + } +} + +/// Check property for existence +bool DigiKernel::hasProperty(const std::string& name) const { + return internals->properties.exists(name); +} + +/// Access single property +dd4hep::Property& DigiKernel::property(const std::string& name) { + return internals->properties[name]; +} + +/// Access the output level +PrintLevel DigiKernel::outputLevel() const { + return (PrintLevel)internals->outputLevel; +} + +/// Fill cache with the global output level of a named object. Must be set before instantiation +void DigiKernel::setOutputLevel(const std::string object, PrintLevel new_level) { + internals->clientLevels[object] = new_level; +} + +/// Retrieve the global output level of a named object. +dd4hep::PrintLevel DigiKernel::getOutputLevel(const std::string object) const { + ClientOutputLevels::const_iterator i=internals->clientLevels.find(object); + if ( i != internals->clientLevels.end() ) return (PrintLevel)(*i).second; + return dd4hep::PrintLevel(dd4hep::printLevel()-1); +} + +/// Set the output level; returns previous value +dd4hep::PrintLevel DigiKernel::setOutputLevel(PrintLevel new_level) { + int old = internals->outputLevel; + internals->outputLevel = new_level; + return (PrintLevel)old; +} + +/// Construct detector geometry using description plugin +void DigiKernel::loadGeometry(const std::string& compact_file) { + char* arg = (char*) compact_file.c_str(); + m_detDesc->apply("DD4hep_XMLLoader", 1, &arg); +} + +// Utility function to load XML files +void DigiKernel::loadXML(const char* fname) { + const char* args[] = { fname, 0 }; + m_detDesc->apply("DD4hep_XMLLoader", 1, (char**) args); +} + +int DigiKernel::configure() { + return 1;//DigiExec::configure(*this); +} + +int DigiKernel::initialize() { + return 1;//DigiExec::initialize(*this); +} + +/// Access to the main input action sequence from the kernel object +DigiActionSequence& DigiKernel::inputAction() const { + return *internals->inputAction; +} + +/// Access to the main event action sequence from the kernel object +DigiActionSequence& DigiKernel::eventAction() const { + return *internals->eventAction; +} + +/// Access to the main output action sequence from the kernel object +DigiActionSequence& DigiKernel::outputAction() const { + return *internals->outputAction; +} + +void DigiKernel::submit(const DigiAction::Actors<DigiAction>& actions, DigiContext& context) const { + chrono::system_clock::time_point start = chrono::system_clock::now(); + bool parallel = 0 != internals->tbbInit && internals->numThreads>0; +#ifdef DD4HEP_USE_TBB + if ( parallel ) { + tbb::task_group que; + for(auto i=actions.begin(); i!=actions.end(); ++i) + que.run(Wrapper(context, *i)); + que.wait(); + goto print_stamp; + } +#endif + actions(&DigiAction::execute,context); + + 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(), + secs.count()); +} + +void DigiKernel::execute(const DigiAction::Actors<DigiAction>& actions, DigiContext& context) const { + actions(&DigiAction::execute,context); +} + +void DigiKernel::wait(DigiContext& context) const { + if ( context.eventPtr() ) {} +} + +/// Execute one single event +void DigiKernel::executeEvent(DigiContext* context) { + DigiContext& refContext = *context; + try { + inputAction().execute(refContext); + eventAction().execute(refContext); + outputAction().execute(refContext); + notify(context); + } + catch(const exception& e) { + notify(context, e); + } +} + +void DigiKernel::notify(DigiContext* context) { + if ( context ) { + DigiEvent* event = context->eventPtr(); + if ( event ) { + context->setEvent(0); + detail::deletePtr(event); + } + delete context; + } +} + +void DigiKernel::notify(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); +} + +int DigiKernel::run() { + chrono::system_clock::time_point start = chrono::system_clock::now(); + internals->stop = false; + internals->eventsToDo = internals->numEvents; + printout(INFO, + "DigiKernel","+++ Total number of events: %d",internals->numEvents); +#ifdef DD4HEP_USE_TBB + 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); + internals->tbbInit = new tbb::task_scheduler_init(internals->numThreads); + if ( internals->maxEventsParallel > 1 ) { + int todo_evt = internals->eventsToDo; + int num_proc = std::min(todo_evt,internals->maxEventsParallel); + tbb::task_group main_group; + 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!"); + } + } +#endif + if ( internals->eventsToDo > 0 ) { + for(int i=0; i<internals->numEvents; ++i) { + unique_ptr<DigiContext> context = make_unique<DigiContext>(this); + ++internals->eventsToDo; + executeEvent(context.release()); + } + } + chrono::duration<double> duration = chrono::system_clock::now() - start; + double sec = chrono::duration_cast<chrono::seconds>(duration).count(); + printout(DEBUG,"DigiKernel","+++ Event processing finished. Total: %7.3f seconds %7.3f seconds/event", + sec, sec/double(std::max(1,internals->numEvents))); + return 1; +} + +int DigiKernel::terminate() { + printout(INFO,"DigiKernel","++ Terminate Digi and delete associated actions."); + m_detDesc->destroyInstance(); + m_detDesc = 0; + return 1; +} + diff --git a/DDDigi/src/DigiLockedAction.cpp b/DDDigi/src/DigiLockedAction.cpp new file mode 100644 index 000000000..21623e279 --- /dev/null +++ b/DDDigi/src/DigiLockedAction.cpp @@ -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 +// +//========================================================================== + +// Framework include files +#include "DD4hep/Printout.h" +#include "DD4hep/InstanceCount.h" +#include "DDDigi/DigiLockedAction.h" + +// C/C++ include files + +using namespace std; +using namespace dd4hep::digi; + + +/// Standard constructor +DigiLockedAction::DigiLockedAction(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +DigiLockedAction::~DigiLockedAction() { + dd4hep::detail::releasePtr(m_action); + InstanceCount::decrement(this); +} + +/// Underlying object to be used during the locked execution +void DigiLockedAction::use(DigiAction* action) { + if (action) { + action->addRef(); + m_properties.adopt(action->properties()); + m_action = action; + return; + } + fatal("DigiLockedAction: Attempt to use invalid actor!"); +} + +/// Pre-track action callback +void DigiLockedAction::execute(DigiContext& context) const { + if (m_action) { + m_action->execute(context); + return; + } + fatal("DigiLockedAction: Attempt to use invalid actor! " + "Did you call DigiLockedAction::use?"); +} diff --git a/DDDigi/src/DigiSynchronize.cpp b/DDDigi/src/DigiSynchronize.cpp new file mode 100644 index 000000000..23ff00f05 --- /dev/null +++ b/DDDigi/src/DigiSynchronize.cpp @@ -0,0 +1,71 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/InstanceCount.h" +#include "DDDigi/DigiKernel.h" +#include "DDDigi/DigiContext.h" +#include "DDDigi/DigiSynchronize.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace dd4hep::digi; + +/// Standard constructor +DigiSynchronize::DigiSynchronize(const DigiKernel& kernel, const string& nam) + : DigiAction(kernel, nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +DigiSynchronize::~DigiSynchronize() { + m_actors(&DigiAction::release); + m_actors.clear(); + InstanceCount::decrement(this); +} + +/// Get an action sequence member by name +DigiAction* DigiSynchronize::get(const string& nam) const { + return m_actors.get(FindByName(TypeName::split(nam).second)); +} + +/// Pre-track action callback +void DigiSynchronize::execute(DigiContext& context) const { + auto start = chrono::high_resolution_clock::now(); + if ( m_parallel ) + m_kernel.submit(m_actors, context); + else + 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(), + secs.count()); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void DigiSynchronize::adopt(DigiAction* action) { + if (action) { + action->addRef(); + m_actors.add(action); + return; + } + except("DigiSynchronize","++ Attempt to add invalid actor!"); +} + +/// Add an actor responding to all callbacks. Sequence takes ownership. +void DigiSynchronize::analyze() { + info("+++ Analyzing the algorithm sequence. Parallel: %s",yes_no(m_parallel)); +} diff --git a/DDDigi/test_task_queue.cpp b/DDDigi/test_task_queue.cpp new file mode 100644 index 000000000..345f1ebfb --- /dev/null +++ b/DDDigi/test_task_queue.cpp @@ -0,0 +1,41 @@ +//========================================================================== +// 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 +// +//========================================================================== +#include "tbb/tbb.h" +#include <iostream> +using namespace tbb; +using namespace std; + +class say_hello { + int cnt = 0; + const char* message; +public: + + say_hello(const char* str, int i) : message(str), cnt(i) { } + void operator( ) ( ) const { + cout << message << " " << cnt << endl; + } +}; + +int main( ) +{ + task_scheduler_init init(2); + task_group tg1, tg2, tg3; + for(int i=0; i<200; ++i) { + tg1.run(std::move(say_hello("child(1)",i))); + tg2.run(std::move(say_hello("child(2)",i))); + tg3.run(std::move(say_hello("child(3)",i))); + } + tg1.wait( ); // wait for tasks to complete + tg2.wait( ); // wait for tasks to complete + tg3.wait( ); // wait for tasks to complete +} diff --git a/DDEve/src/HitActors.cpp b/DDEve/src/HitActors.cpp index f5b4b551b..646cd1b83 100644 --- a/DDEve/src/HitActors.cpp +++ b/DDEve/src/HitActors.cpp @@ -14,6 +14,7 @@ // Framework include files #include "DDEve/HitActors.h" #include "DD4hep/Objects.h" +#include "DD4hep/DD4hepUnits.h" // ROOT include files #include "TH2.h" @@ -25,6 +26,11 @@ using namespace std; using namespace dd4hep; +#ifdef HAVE_GEANT4_UNITS +#define MM_2_CM 1.0 +#else +#define MM_2_CM 0.1 +#endif /// Action callback of this functor: void EtaPhiHistogramActor::operator()(const DDEveHit& hit) { diff --git a/DDEve/src/ParticleActors.cpp b/DDEve/src/ParticleActors.cpp index beb752b18..cd9b63176 100644 --- a/DDEve/src/ParticleActors.cpp +++ b/DDEve/src/ParticleActors.cpp @@ -14,6 +14,7 @@ // Framework include files #include "DDEve/ParticleActors.h" #include "DD4hep/Objects.h" +#include "DD4hep/DD4hepUnits.h" #include "TEveCompound.h" #include "TEveTrack.h" @@ -26,9 +27,19 @@ using namespace std; using namespace dd4hep; -static Color_t Colors[] = { - kRed, kBlue, kYellow, kGreen, kPink, kAzure, kOrange, kTeal, kViolet, kSpring, kMagenta, kCyan -}; +#ifdef HAVE_GEANT4_UNITS +#define CM_2_MM 1.0 +#define MM_2_CM 1.0 +#else +#define CM_2_MM 10.0 +#define MM_2_CM 0.1 +#endif + +namespace { + Color_t Colors[] = { + kRed, kBlue, kYellow, kGreen, kPink, kAzure, kOrange, kTeal, kViolet, kSpring, kMagenta, kCyan + }; +} /// Standard initializing constructor MCParticleCreator::MCParticleCreator(TEveTrackPropagator* p, TEveCompound* ps, const DisplayConfiguration::Config* cfg) diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 533587406..9de626bec 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -116,6 +116,8 @@ using namespace std; #include "G4VPhysicalVolume.hh" #include "G4ReflectionFactory.hh" +static constexpr double CM_2_MM = (CLHEP::centimeter/dd4hep::centimeter); + void Geant4AssemblyVolume::imprint(Geant4GeometryInfo& info, const TGeoNode* parent, Chain chain, diff --git a/DDG4/src/Geant4SensDetAction.cpp b/DDG4/src/Geant4SensDetAction.cpp index a2fb4b546..401489015 100644 --- a/DDG4/src/Geant4SensDetAction.cpp +++ b/DDG4/src/Geant4SensDetAction.cpp @@ -30,6 +30,12 @@ // C/C++ include files #include <stdexcept> +#ifdef HAVE_GEANT4_UNITS +#define MM_2_CM 1.0 +#else +#define MM_2_CM 0.1 +#endif + using namespace std; using namespace dd4hep; using namespace dd4hep::sim; diff --git a/DDG4/src/Geant4SensitiveDetector.cpp b/DDG4/src/Geant4SensitiveDetector.cpp index 2b0ecfbe0..f717d7ccf 100644 --- a/DDG4/src/Geant4SensitiveDetector.cpp +++ b/DDG4/src/Geant4SensitiveDetector.cpp @@ -16,6 +16,7 @@ #include "DDG4/Geant4Converter.h" #include "DDG4/Geant4Hits.h" #include "DD4hep/Segmentations.h" + #include "DD4hep/Printout.h" #include "DD4hep/Detector.h" @@ -26,6 +27,11 @@ // ROOT include files #include "TGeoNode.h" +#include "DD4hep/DD4hepUnits.h" +#include "CLHEP/Units/SystemOfUnits.h" + +static constexpr double MM_2_CM = (CLHEP::millimeter/dd4hep::millimeter); + #define DEBUG 0 // C/C++ include files diff --git a/DDG4/src/Geant4StepHandler.cpp b/DDG4/src/Geant4StepHandler.cpp index 3e8ed40af..79cff318c 100644 --- a/DDG4/src/Geant4StepHandler.cpp +++ b/DDG4/src/Geant4StepHandler.cpp @@ -15,6 +15,10 @@ #include "DDG4/Geant4StepHandler.h" #include "DDSegmentation/Segmentation.h" #include "DD4hep/DD4hepUnits.h" +#include "CLHEP/Units/SystemOfUnits.h" + +static constexpr double MM_2_CM = (CLHEP::millimeter/dd4hep::millimeter); + namespace units = dd4hep; using namespace dd4hep; using namespace dd4hep::sim; diff --git a/DDParsers/include/Evaluator/DD4hepUnits.h b/DDParsers/include/Evaluator/DD4hepUnits.h index f744148ec..b64e6f48b 100644 --- a/DDParsers/include/Evaluator/DD4hepUnits.h +++ b/DDParsers/include/Evaluator/DD4hepUnits.h @@ -29,6 +29,10 @@ #include "RVersion.h" +#ifndef HAVE_GEANT4_UNITS +// #define HAVE_GEANT4_UNITS +#endif + // We use the ROOT system units if they are avalible (FAILS SOME TESTS FOR NOW) #if 0 /// ROOT_VERSION_CODE >= ROOT_VERSION(6,12,0) @@ -46,245 +50,257 @@ namespace dd4hep { // // Length [L] // - static const double millimeter = 0.1; - static const double millimeter2 = millimeter * millimeter; - static const double millimeter3 = millimeter * millimeter * millimeter; +#ifdef HAVE_GEANT4_UNITS + static constexpr double millimeter = 1.0; +#else + static constexpr double millimeter = 0.1; +#endif + static constexpr double millimeter2 = millimeter * millimeter; + static constexpr double millimeter3 = millimeter * millimeter * millimeter; - static const double centimeter = 10. * millimeter; - static const double centimeter2 = centimeter * centimeter; - static const double centimeter3 = centimeter * centimeter * centimeter; + static constexpr double centimeter = 10. * millimeter; + static constexpr double centimeter2 = centimeter * centimeter; + static constexpr double centimeter3 = centimeter * centimeter * centimeter; - static const double meter = 1000. * millimeter; - static const double meter2 = meter * meter; - static const double meter3 = meter * meter * meter; + static constexpr double meter = 1000. * millimeter; + static constexpr double meter2 = meter * meter; + static constexpr double meter3 = meter * meter * meter; - static const double kilometer = 1000. * meter; - static const double kilometer2 = kilometer * kilometer; - static const double kilometer3 = kilometer * kilometer * kilometer; + static constexpr double kilometer = 1000. * meter; + static constexpr double kilometer2 = kilometer * kilometer; + static constexpr double kilometer3 = kilometer * kilometer * kilometer; - static const double parsec = 3.0856775807e+16 * meter; + static constexpr double parsec = 3.0856775807e+16 * meter; - static const double micrometer = 1.e-6 * meter; - static const double nanometer = 1.e-9 * meter; - static const double angstrom = 1.e-10 * meter; - static const double fermi = 1.e-15 * meter; + static constexpr double micrometer = 1.e-6 * meter; + static constexpr double nanometer = 1.e-9 * meter; + static constexpr double angstrom = 1.e-10 * meter; + static constexpr double fermi = 1.e-15 * meter; - static const double barn = 1.e-28 * meter2; - static const double millibarn = 1.e-3 * barn; - static const double microbarn = 1.e-6 * barn; - static const double nanobarn = 1.e-9 * barn; - static const double picobarn = 1.e-12 * barn; + static constexpr double barn = 1.e-28 * meter2; + static constexpr double millibarn = 1.e-3 * barn; + static constexpr double microbarn = 1.e-6 * barn; + static constexpr double nanobarn = 1.e-9 * barn; + static constexpr double picobarn = 1.e-12 * barn; // symbols - static const double nm = nanometer; - static const double um = micrometer; + static constexpr double nm = nanometer; + static constexpr double um = micrometer; - static const double mm = millimeter; - static const double mm2 = millimeter2; - static const double mm3 = millimeter3; + static constexpr double mm = millimeter; + static constexpr double mm2 = millimeter2; + static constexpr double mm3 = millimeter3; - static const double cm = centimeter; - static const double cm2 = centimeter2; - static const double cm3 = centimeter3; + static constexpr double cm = centimeter; + static constexpr double cm2 = centimeter2; + static constexpr double cm3 = centimeter3; - static const double m = meter; - static const double m2 = meter2; - static const double m3 = meter3; + static constexpr double m = meter; + static constexpr double m2 = meter2; + static constexpr double m3 = meter3; - static const double km = kilometer; - static const double km2 = kilometer2; - static const double km3 = kilometer3; + static constexpr double km = kilometer; + static constexpr double km2 = kilometer2; + static constexpr double km3 = kilometer3; - static const double pc = parsec; + static constexpr double pc = parsec; // // Angle // - // static const double radian = 180. / 3.14159265358979323846; // => degree=1 - // static const double milliradian = 1.e-3 * radian; - // static const double degree = 1.; //= (3.14159265358979323846/180.0)*radian; + // static constexpr double radian = 180. / 3.14159265358979323846; // => degree=1 + // static constexpr double milliradian = 1.e-3 * radian; + // static constexpr double degree = 1.; //= (3.14159265358979323846/180.0)*radian; //fg: use radians as default unit as this is needed for all math functions // and everywhere else, except in TGeo shapes -> this is taken care of in shape Handles .... - static const double radian = 1. ; - static const double milliradian = 1.e-3 * radian; - static const double degree = (3.14159265358979323846/180.0)*radian; + static constexpr double radian = 1. ; + static constexpr double milliradian = 1.e-3 * radian; + static constexpr double degree = (3.14159265358979323846/180.0)*radian; - static const double steradian = 1.; + static constexpr double steradian = 1.; // symbols - static const double rad = radian; - static const double mrad = milliradian; - static const double sr = steradian; - static const double deg = degree; + static constexpr double rad = radian; + static constexpr double mrad = milliradian; + static constexpr double sr = steradian; + static constexpr double deg = degree; // // Time [T] // - static const double nanosecond = 1.e-9; - static const double second = 1.e+9 * nanosecond; - static const double millisecond = 1.e-3 * second; - static const double microsecond = 1.e-6 * second; - static const double picosecond = 1.e-12 * second; +#ifdef HAVE_GEANT4_UNITS + static constexpr double nanosecond = 1.0; +#else + static constexpr double nanosecond = 1.e-9; +#endif + static constexpr double second = 1.e+9 * nanosecond; + static constexpr double millisecond = 1.e-3 * second; + static constexpr double microsecond = 1.e-6 * second; + static constexpr double picosecond = 1.e-12 * second; - static const double hertz = 1. / second; - static const double kilohertz = 1.e+3 * hertz; - static const double megahertz = 1.e+6 * hertz; + static constexpr double hertz = 1. / second; + static constexpr double kilohertz = 1.e+3 * hertz; + static constexpr double megahertz = 1.e+6 * hertz; // symbols - static const double ns = nanosecond; - static const double s = second; - static const double ms = millisecond; + static constexpr double ns = nanosecond; + static constexpr double s = second; + static constexpr double ms = millisecond; // // Electric charge [Q] // - static const double eplus = 1.; // positron charge - static const double e_SI = 1.602176487e-19; // positron charge in coulomb - static const double coulomb = eplus / e_SI; // coulomb = 6.24150 e+18 * eplus + static constexpr double eplus = 1.; // positron charge + static constexpr double e_SI = 1.602176487e-19; // positron charge in coulomb + static constexpr double coulomb = eplus / e_SI; // coulomb = 6.24150 e+18 * eplus // // Energy [E] // - static const double megaelectronvolt = 1.e-3; - static const double electronvolt = 1.e-6 * megaelectronvolt; - static const double kiloelectronvolt = 1.e-3 * megaelectronvolt; - static const double gigaelectronvolt = 1.e+3 * megaelectronvolt; - static const double teraelectronvolt = 1.e+6 * megaelectronvolt; - static const double petaelectronvolt = 1.e+9 * megaelectronvolt; +#ifdef HAVE_GEANT4_UNITS + static constexpr double megaelectronvolt = 1.0; +#else + static constexpr double megaelectronvolt = 1.e-3; +#endif + static constexpr double electronvolt = 1.e-6 * megaelectronvolt; + static constexpr double kiloelectronvolt = 1.e-3 * megaelectronvolt; + static constexpr double gigaelectronvolt = 1.e+3 * megaelectronvolt; + static constexpr double teraelectronvolt = 1.e+6 * megaelectronvolt; + static constexpr double petaelectronvolt = 1.e+9 * megaelectronvolt; - static const double joule = electronvolt / e_SI; // joule = 6.24150 e+12 * MeV + static constexpr double joule = electronvolt / e_SI; // joule = 6.24150 e+12 * MeV // symbols - static const double MeV = megaelectronvolt; - static const double eV = electronvolt; - static const double keV = kiloelectronvolt; - static const double GeV = gigaelectronvolt; - static const double TeV = teraelectronvolt; - static const double PeV = petaelectronvolt; + static constexpr double MeV = megaelectronvolt; + static constexpr double eV = electronvolt; + static constexpr double keV = kiloelectronvolt; + static constexpr double GeV = gigaelectronvolt; + static constexpr double TeV = teraelectronvolt; + static constexpr double PeV = petaelectronvolt; // // Mass [E][T^2][L^-2] // - static const double kilogram = joule * second * second / (meter * meter); - static const double gram = 1.e-3 * kilogram; - static const double milligram = 1.e-3 * gram; + static constexpr double kilogram = joule * second * second / (meter * meter); + static constexpr double gram = 1.e-3 * kilogram; + static constexpr double milligram = 1.e-3 * gram; // symbols - static const double kg = kilogram; - static const double g = gram; - static const double mg = milligram; + static constexpr double kg = kilogram; + static constexpr double g = gram; + static constexpr double mg = milligram; // // Power [E][T^-1] // - static const double watt = joule / second; // watt = 6.24150 e+3 * MeV/ns + static constexpr double watt = joule / second; // watt = 6.24150 e+3 * MeV/ns // // Force [E][L^-1] // - static const double newton = joule / meter; // newton = 6.24150 e+9 * MeV/mm + static constexpr double newton = joule / meter; // newton = 6.24150 e+9 * MeV/mm // // Pressure [E][L^-3] // #define pascal hep_pascal // a trick to avoid warnings - static const double hep_pascal = newton / m2; // pascal = 6.24150 e+3 * MeV/mm3 - static const double bar = 100000 * pascal; // bar = 6.24150 e+8 * MeV/mm3 - static const double atmosphere = 101325 * pascal; // atm = 6.32420 e+8 * MeV/mm3 + static constexpr double hep_pascal = newton / m2; // pascal = 6.24150 e+3 * MeV/mm3 + static constexpr double bar = 100000 * pascal; // bar = 6.24150 e+8 * MeV/mm3 + static constexpr double atmosphere = 101325 * pascal; // atm = 6.32420 e+8 * MeV/mm3 // // Electric current [Q][T^-1] // - static const double ampere = coulomb / second; // ampere = 6.24150 e+9 * eplus/ns - static const double milliampere = 1.e-3 * ampere; - static const double microampere = 1.e-6 * ampere; - static const double nanoampere = 1.e-9 * ampere; + static constexpr double ampere = coulomb / second; // ampere = 6.24150 e+9 * eplus/ns + static constexpr double milliampere = 1.e-3 * ampere; + static constexpr double microampere = 1.e-6 * ampere; + static constexpr double nanoampere = 1.e-9 * ampere; // // Electric potential [E][Q^-1] // - static const double megavolt = megaelectronvolt / eplus; - static const double kilovolt = 1.e-3 * megavolt; - static const double volt = 1.e-6 * megavolt; + static constexpr double megavolt = megaelectronvolt / eplus; + static constexpr double kilovolt = 1.e-3 * megavolt; + static constexpr double volt = 1.e-6 * megavolt; // // Electric resistance [E][T][Q^-2] // - static const double ohm = volt / ampere; // ohm = 1.60217e-16*(MeV/eplus)/(eplus/ns) + static constexpr double ohm = volt / ampere; // ohm = 1.60217e-16*(MeV/eplus)/(eplus/ns) // // Electric capacitance [Q^2][E^-1] // - static const double farad = coulomb / volt; // farad = 6.24150e+24 * eplus/Megavolt - static const double millifarad = 1.e-3 * farad; - static const double microfarad = 1.e-6 * farad; - static const double nanofarad = 1.e-9 * farad; - static const double picofarad = 1.e-12 * farad; + static constexpr double farad = coulomb / volt; // farad = 6.24150e+24 * eplus/Megavolt + static constexpr double millifarad = 1.e-3 * farad; + static constexpr double microfarad = 1.e-6 * farad; + static constexpr double nanofarad = 1.e-9 * farad; + static constexpr double picofarad = 1.e-12 * farad; // // Magnetic Flux [T][E][Q^-1] // - static const double weber = volt * second; // weber = 1000*megavolt*ns + static constexpr double weber = volt * second; // weber = 1000*megavolt*ns // // Magnetic Field [T][E][Q^-1][L^-2] // - static const double tesla = volt * second / meter2; // tesla =0.001*megavolt*ns/mm2 + static constexpr double tesla = volt * second / meter2; // tesla =0.001*megavolt*ns/mm2 - static const double gauss = 1.e-4 * tesla; - static const double kilogauss = 1.e-1 * tesla; + static constexpr double gauss = 1.e-4 * tesla; + static constexpr double kilogauss = 1.e-1 * tesla; // // Inductance [T^2][E][Q^-2] // - static const double henry = weber / ampere; // henry = 1.60217e-7*MeV*(ns/eplus)**2 + static constexpr double henry = weber / ampere; // henry = 1.60217e-7*MeV*(ns/eplus)**2 // // Temperature // - static const double kelvin = 1.; + static constexpr double kelvin = 1.; // // Amount of substance // - static const double mole = 1.; + static constexpr double mole = 1.; // // Activity [T^-1] // - static const double becquerel = 1. / second; - static const double curie = 3.7e+10 * becquerel; + static constexpr double becquerel = 1. / second; + static constexpr double curie = 3.7e+10 * becquerel; // // Absorbed dose [L^2][T^-2] // - static const double gray = joule / kilogram; - static const double kilogray = 1.e+3 * gray; - static const double milligray = 1.e-3 * gray; - static const double microgray = 1.e-6 * gray; + static constexpr double gray = joule / kilogram; + static constexpr double kilogray = 1.e+3 * gray; + static constexpr double milligray = 1.e-3 * gray; + static constexpr double microgray = 1.e-6 * gray; // // Luminous intensity [I] // - static const double candela = 1.; + static constexpr double candela = 1.; // // Luminous flux [I] // - static const double lumen = candela * steradian; + static constexpr double lumen = candela * steradian; // // Illuminance [I][L^-2] // - static const double lux = lumen / meter2; + static constexpr double lux = lumen / meter2; // // Miscellaneous // - static const double perCent = 0.01; - static const double perThousand = 0.001; - static const double perMillion = 0.000001; + static constexpr double perCent = 0.01; + static constexpr double perThousand = 0.001; + static constexpr double perMillion = 0.000001; // -*- C++ -*- // ---------------------------------------------------------------------- @@ -323,85 +339,85 @@ namespace dd4hep { // 29.04.08 use PDG 2006 values // 03.11.08 use PDG 2008 values - static const double pi = 3.14159265358979323846; - static const double twopi = 2 * pi; - static const double halfpi = pi / 2; - static const double pi2 = pi * pi; + static constexpr double pi = 3.14159265358979323846; + static constexpr double twopi = 2 * pi; + static constexpr double halfpi = pi / 2; + static constexpr double pi2 = pi * pi; // // // - static const double Avogadro = 6.02214179e+23 / mole; + static constexpr double Avogadro = 6.02214179e+23 / mole; // // c = 299.792458 mm/ns // c^2 = 898.7404 (mm/ns)^2 // - static const double c_light = 2.99792458e+8 * m / s; - static const double c_squared = c_light * c_light; + static constexpr double c_light = 2.99792458e+8 * m / s; + static constexpr double c_squared = c_light * c_light; // // h = 4.13566e-12 MeV*ns // hbar = 6.58212e-13 MeV*ns // hbarc = 197.32705e-12 MeV*mm // - static const double h_Planck = 6.62606896e-34 * joule * s; - static const double hbar_Planck = h_Planck / twopi; - static const double hbarc = hbar_Planck * c_light; - static const double hbarc_squared = hbarc * hbarc; + static constexpr double h_Planck = 6.62606896e-34 * joule * s; + static constexpr double hbar_Planck = h_Planck / twopi; + static constexpr double hbarc = hbar_Planck * c_light; + static constexpr double hbarc_squared = hbarc * hbarc; // // // - static const double electron_charge = -eplus; // see SystemOfUnits.h - static const double e_squared = eplus * eplus; + static constexpr double electron_charge = -eplus; // see SystemOfUnits.h + static constexpr double e_squared = eplus * eplus; // // amu_c2 - atomic equivalent mass unit // - AKA, unified atomic mass unit (u) // amu - atomic mass unit // - static const double electron_mass_c2 = 0.510998910 * MeV; - static const double proton_mass_c2 = 938.272013 * MeV; - static const double neutron_mass_c2 = 939.56536 * MeV; - static const double amu_c2 = 931.494028 * MeV; - static const double amu = amu_c2 / c_squared; + static constexpr double electron_mass_c2 = 0.510998910 * MeV; + static constexpr double proton_mass_c2 = 938.272013 * MeV; + static constexpr double neutron_mass_c2 = 939.56536 * MeV; + static constexpr double amu_c2 = 931.494028 * MeV; + static constexpr double amu = amu_c2 / c_squared; // // permeability of free space mu0 = 2.01334e-16 Mev*(ns*eplus)^2/mm // permittivity of free space epsil0 = 5.52636e+10 eplus^2/(MeV*mm) // - static const double mu0 = 4 * pi * 1.e-7 * henry / m; - static const double epsilon0 = 1. / (c_squared * mu0); + static constexpr double mu0 = 4 * pi * 1.e-7 * henry / m; + static constexpr double epsilon0 = 1. / (c_squared * mu0); // // electromagnetic coupling = 1.43996e-12 MeV*mm/(eplus^2) // - static const double elm_coupling = e_squared / (4 * pi * epsilon0); - static const double fine_structure_const = elm_coupling / hbarc; - static const double classic_electr_radius = elm_coupling / electron_mass_c2; - static const double electron_Compton_length = hbarc / electron_mass_c2; - static const double Bohr_radius = electron_Compton_length / fine_structure_const; + static constexpr double elm_coupling = e_squared / (4 * pi * epsilon0); + static constexpr double fine_structure_const = elm_coupling / hbarc; + static constexpr double classic_electr_radius = elm_coupling / electron_mass_c2; + static constexpr double electron_Compton_length = hbarc / electron_mass_c2; + static constexpr double Bohr_radius = electron_Compton_length / fine_structure_const; - static const double alpha_rcl2 = fine_structure_const * classic_electr_radius * classic_electr_radius; + static constexpr double alpha_rcl2 = fine_structure_const * classic_electr_radius * classic_electr_radius; - static const double twopi_mc2_rcl2 = twopi * electron_mass_c2 * classic_electr_radius * classic_electr_radius; + static constexpr double twopi_mc2_rcl2 = twopi * electron_mass_c2 * classic_electr_radius * classic_electr_radius; // // // - static const double k_Boltzmann = 8.617343e-11 * MeV / kelvin; + static constexpr double k_Boltzmann = 8.617343e-11 * MeV / kelvin; // // // - static const double STP_Temperature = 273.15 * kelvin; - static const double STP_Pressure = 1. * atmosphere; - static const double kGasThreshold = 10. * mg / cm3; + static constexpr double STP_Temperature = 273.15 * kelvin; + static constexpr double STP_Pressure = 1. * atmosphere; + static constexpr double kGasThreshold = 10. * mg / cm3; // // // - static const double universe_mean_density = 1.e-25 * g / cm3; + static constexpr double universe_mean_density = 1.e-25 * g / cm3; //} } #endif diff --git a/DDParsers/src/Evaluator/setSystemOfUnits.cpp b/DDParsers/src/Evaluator/setSystemOfUnits.cpp index 487849da3..57820eb76 100644 --- a/DDParsers/src/Evaluator/setSystemOfUnits.cpp +++ b/DDParsers/src/Evaluator/setSystemOfUnits.cpp @@ -29,6 +29,7 @@ namespace dd4hep { const double micro_ = 1.e-06; // micro (Latin) or mikros (Greek) "small" const double nano_ = 1.e-09; // nanus (Latin) or nanos (Greek) "dwarf" const double pico_ = 1.e-12; // pico (Spanish) "bit" + const double femto_ = 1.e-15; // femto // ====================================================================== // @@ -260,13 +261,17 @@ namespace dd4hep { setVariable("micrometer", micro_ * m); setVariable("micron", micro_ * m); + setVariable("mum", micro_ * m); setVariable("nanometer", nano_ * m); + setVariable("nm", nano_ * m); // --- honors Anders Jonas Angstrom (1814-1874) of Sweden setVariable("angstrom", 1.e-10 * m); // --- honors Enrico Fermi (1901-1954) of Italy setVariable("fermi", 1.e-15 * m); + setVariable("femtometer", femto_ * m); + setVariable("fm", femto_ * m); // Length^2 diff --git a/examples/ClientTests/src/MaterialTester_geo.cpp b/examples/ClientTests/src/MaterialTester_geo.cpp index 67b210cd1..2e29cff97 100644 --- a/examples/ClientTests/src/MaterialTester_geo.cpp +++ b/examples/ClientTests/src/MaterialTester_geo.cpp @@ -11,13 +11,19 @@ // //========================================================================== + // Framework include files #include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DD4hepUnits.h" #include "DD4hep/Printout.h" // ROOT include file #include "TGeoElement.h" +#include "TGeoPhysicalConstants.h" +#include "TGeant4PhysicalConstants.h" +#include "TMath.h" +namespace units = dd4hep; using namespace std; using namespace dd4hep; using namespace dd4hep::detail; @@ -33,10 +39,12 @@ static Ref_t create_element(Detector& description, xml_h xml_det, SensitiveDetec Material mat = description.material(c.nameStr()); TGeoMaterial* material = mat->GetMaterial(); printout(INFO,det_name,"+++ Material:%s [%p, %p] Z=%6.2f A=%6.2f D=%9.4f [g/cm3]", - material->GetName(), mat.ptr(), m, material->GetZ(), + material->GetName(), mat.ptr(), material, material->GetZ(), material->GetA(), material->GetDensity()); - printout(INFO,det_name,"+++ Radiation Length:%9.4f Interaction length:%9.4f Mixture:%s", - material->GetRadLen(), material->GetIntLen(), + + printout(INFO,det_name,"+++ Radiation Length:%9.4f [cm] Interaction length:%9.4f [cm] Mixture:%s", + material->GetRadLen()/TGeant4Unit::mm*units::cm, material->GetIntLen()/TGeant4Unit::mm*units::cm, + //material->GetRadLen(), material->GetIntLen(), yes_no(material->IsMixture())); printout(INFO,det_name,"+++ Elements:%d Index:%d", material->GetNelements(), material->GetIndex()); @@ -57,7 +65,30 @@ static Ref_t create_element(Detector& description, xml_h xml_det, SensitiveDetec } } - + printout(INFO,det_name,"+++ Basic units:"); + printout(INFO,det_name,"+++ Length: mm: %12.3f Geant4: %8.3f mm dd4hep: %8.3f mm TGeo: %8.3g", + units::mm, units::mm/TGeant4Unit::mm, units::mm/units::mm, units::mm/TGeoUnit::mm); + printout(INFO,det_name,"+++ Time: s: %12.0g Geant4: %8.3f s dd4hep: %8.3f s TGeo: %8.3g", + units::s , units::s /TGeant4Unit::s , units::s /units::s, units::s /TGeoUnit::s ); + printout(INFO,det_name,"+++ Energy: eV: %12.3g Geant4: %8.3f eV dd4hep: %8.3f eV TGeo: %8.3g", + units::eV, units::eV/TGeant4Unit::eV, units::eV/units::eV, units::eV/TGeoUnit::eV); + printout(INFO,det_name,"+++ Energy: MeV: %12.3f Geant4: %8.3f MeV dd4hep: %8.3f MeV TGeo: %8.3g", + units::MeV, units::MeV/TGeant4Unit::MeV, units::MeV /units::MeV, units::MeV /TGeoUnit::MeV); + printout(INFO,det_name,"+++ 1./Fine structure: %12.3f Geant4: %8.3f dd4hep: %8.3f TGeo: %8.3f", + 1./units::fine_structure_const, 1./TGeant4Unit::fine_structure_const, + 1./units::fine_structure_const, 1./TGeoUnit::fine_structure_const); + printout(INFO,det_name,"+++ Universe density: %12.3g Geant4: %8.3g g/cm3 dd4hep: %8.3g g/cm3 TGeo: %8.3g", + units::universe_mean_density, + units::universe_mean_density/TGeant4Unit::g*TGeant4Unit::cm3, + units::universe_mean_density/units::g*units::cm3, + units::universe_mean_density/TGeoUnit::g*TGeoUnit::cm3); + printout(INFO,det_name,"+++ STP_temperature: %12.3f Geant4: %8.3f K dd4hep: %8.3f K TGeo: %8.3f K", + STP_temperature, STP_temperature/TGeant4Unit::kelvin, + STP_temperature/units::kelvin, STP_temperature/TGeoUnit::kelvin); + printout(INFO,det_name,"+++ STP_pressure: %12.0f Geant4: %8.3f hPa dd4hep: %8.3f hPa TGeo: %8.3f hPa", + STP_pressure, STP_pressure/TGeant4Unit::pascal/1e2, + STP_pressure/units::pascal/1e2,STP_pressure/TGeoUnit::pascal/1e2); + PlacedVolume pv = description.pickMotherVolume(det).placeVolume(assembly); pv.addPhysVolID("system",x_det.id()); det.setPlacement(pv); -- GitLab