From cc94e79295b67cb4ccef6175f283ee03bb2b09a9 Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Fri, 25 Apr 2014 08:07:22 +0000 Subject: [PATCH] Please see doc/release.notes for changes --- DDCore/CMakeLists.txt | 16 +- DDCore/include/DD4hep/BasicGrammar.h | 50 ++ DDCore/include/DD4hep/Callback.h | 372 ++++++++++ DDCore/include/DD4hep/ConditionTypes.h | 3 + DDCore/include/DD4hep/Conditions.h | 214 ++++++ DDCore/include/DD4hep/Detector.h | 218 +++--- DDCore/include/DD4hep/DetectorTools.h | 55 +- DDCore/include/DD4hep/Exceptions.h | 48 ++ DDCore/include/DD4hep/Handle.h | 7 - DDCore/include/DD4hep/LCDD.h | 4 +- DDCore/include/DD4hep/ObjectExtensions.h | 68 ++ DDCore/include/DD4hep/Parsers.h | 695 ++++++++++++++++++ DDCore/include/DD4hep/Primitives.h | 77 ++ DDCore/include/DD4hep/Printout.h | 3 + DDCore/include/DD4hep/Readout.h | 31 +- DDCore/include/DD4hep/Shapes.h | 159 +++- DDCore/include/DD4hep/ToStream.h | 302 ++++++++ DDCore/include/DD4hep/VolumeManager.h | 60 +- DDCore/include/DD4hep/Volumes.h | 7 - .../include/DD4hep/objects/BasicGrammar_inl.h | 266 +++++++ .../DD4hep/objects/ConditionsInterna.h | 251 +++++++ .../include/DD4hep/objects/DetectorInterna.h | 152 ++++ DDCore/include/DD4hep/objects/NamedObject.h | 71 ++ DDCore/include/XML/XMLDimension.h | 12 +- DDCore/include/XML/XMLElements.h | 75 +- DDCore/src/BasicGrammar.cpp | 42 ++ DDCore/src/BasicGrammarTypes.cpp | 58 ++ DDCore/src/Callback.cpp | 22 + DDCore/src/Conditions.cpp | 218 ++++++ DDCore/src/ConditionsInterna.cpp | 172 +++++ DDCore/src/ConditonsTypes.cpp | 44 ++ DDCore/src/Detector.cpp | 437 +++-------- DDCore/src/DetectorInterna.cpp | 233 ++++++ DDCore/src/DetectorTools.cpp | 239 ++++-- DDCore/src/Evaluator/setSystemOfUnits.cpp | 5 +- DDCore/src/Exceptions.cpp | 25 + DDCore/src/Handle.cpp | 146 +--- DDCore/src/LCDDImp.cpp | 66 +- DDCore/src/LCDDImp.h | 6 +- DDCore/src/NamedObject.cpp | 59 ++ DDCore/src/ObjectExtensions.cpp | 127 ++++ DDCore/src/Objects.cpp | 3 +- DDCore/src/Primitives.cpp | 277 +++++++ DDCore/src/Printout.cpp | 14 +- DDCore/src/Readout.cpp | 15 - DDCore/src/Shapes.cpp | 7 + DDCore/src/ToStream.cpp | 89 +++ DDCore/src/VolumeManager.cpp | 155 ++-- DDCore/src/Volumes.cpp | 21 +- DDCore/src/XML/DocumentHandler.cpp | 78 +- DDCore/src/XML/XMLDimension.cpp | 5 + DDCore/src/XML/XMLElements.cpp | 57 +- DDCore/src/parsers/Grammars.h | 530 +++++++++++++ DDCore/src/parsers/GrammarsV2.h | 471 ++++++++++++ DDCore/src/parsers/Parsers.icpp | 232 ++++++ DDCore/src/parsers/ParsersFactory.h | 53 ++ DDCore/src/parsers/ParsersObjects.cpp | 130 ++++ DDCore/src/parsers/ParsersStandardList1.cpp | 5 + DDCore/src/parsers/ParsersStandardList2.cpp | 5 + DDCore/src/parsers/ParsersStandardList3.cpp | 5 + DDCore/src/parsers/ParsersStandardList4.cpp | 5 + .../src/parsers/ParsersStandardListCommon.h | 18 + DDCore/src/parsers/ParsersStandardMisc1.cpp | 21 + DDCore/src/parsers/ParsersStandardMisc2.cpp | 17 + DDCore/src/parsers/ParsersStandardMisc3.cpp | 17 + DDCore/src/parsers/ParsersStandardMisc4.cpp | 13 + DDCore/src/parsers/ParsersStandardMisc5.cpp | 24 + .../src/parsers/ParsersStandardMiscCommon.h | 9 + DDCore/src/parsers/ParsersStandardSingle.cpp | 26 + DDCore/src/plugins/Compact2Objects.cpp | 11 +- DDCore/src/plugins/GeometryWalk.cpp | 47 +- DDCore/src/plugins/LCDDConverter.cpp | 1 + DDCore/src/plugins/LCDDConverter.h | 3 + DDCore/src/plugins/PluginInvoker.cpp | 110 +++ DDCore/src/plugins/StandardPlugins.cpp | 90 ++- 75 files changed, 6471 insertions(+), 1208 deletions(-) create mode 100644 DDCore/include/DD4hep/BasicGrammar.h create mode 100644 DDCore/include/DD4hep/Callback.h create mode 100644 DDCore/include/DD4hep/ConditionTypes.h create mode 100644 DDCore/include/DD4hep/Conditions.h create mode 100644 DDCore/include/DD4hep/Exceptions.h create mode 100644 DDCore/include/DD4hep/ObjectExtensions.h create mode 100644 DDCore/include/DD4hep/Parsers.h create mode 100644 DDCore/include/DD4hep/ToStream.h create mode 100644 DDCore/include/DD4hep/objects/BasicGrammar_inl.h create mode 100644 DDCore/include/DD4hep/objects/ConditionsInterna.h create mode 100644 DDCore/include/DD4hep/objects/DetectorInterna.h create mode 100644 DDCore/include/DD4hep/objects/NamedObject.h create mode 100644 DDCore/src/BasicGrammar.cpp create mode 100644 DDCore/src/BasicGrammarTypes.cpp create mode 100644 DDCore/src/Callback.cpp create mode 100644 DDCore/src/Conditions.cpp create mode 100644 DDCore/src/ConditionsInterna.cpp create mode 100644 DDCore/src/ConditonsTypes.cpp create mode 100644 DDCore/src/DetectorInterna.cpp create mode 100644 DDCore/src/Exceptions.cpp create mode 100644 DDCore/src/NamedObject.cpp create mode 100644 DDCore/src/ObjectExtensions.cpp create mode 100644 DDCore/src/Primitives.cpp create mode 100644 DDCore/src/ToStream.cpp create mode 100644 DDCore/src/parsers/Grammars.h create mode 100644 DDCore/src/parsers/GrammarsV2.h create mode 100644 DDCore/src/parsers/Parsers.icpp create mode 100644 DDCore/src/parsers/ParsersFactory.h create mode 100644 DDCore/src/parsers/ParsersObjects.cpp create mode 100644 DDCore/src/parsers/ParsersStandardList1.cpp create mode 100644 DDCore/src/parsers/ParsersStandardList2.cpp create mode 100644 DDCore/src/parsers/ParsersStandardList3.cpp create mode 100644 DDCore/src/parsers/ParsersStandardList4.cpp create mode 100644 DDCore/src/parsers/ParsersStandardListCommon.h create mode 100644 DDCore/src/parsers/ParsersStandardMisc1.cpp create mode 100644 DDCore/src/parsers/ParsersStandardMisc2.cpp create mode 100644 DDCore/src/parsers/ParsersStandardMisc3.cpp create mode 100644 DDCore/src/parsers/ParsersStandardMisc4.cpp create mode 100644 DDCore/src/parsers/ParsersStandardMisc5.cpp create mode 100644 DDCore/src/parsers/ParsersStandardMiscCommon.h create mode 100644 DDCore/src/parsers/ParsersStandardSingle.cpp create mode 100644 DDCore/src/plugins/PluginInvoker.cpp diff --git a/DDCore/CMakeLists.txt b/DDCore/CMakeLists.txt index b70bc0a9c..a21b875d9 100644 --- a/DDCore/CMakeLists.txt +++ b/DDCore/CMakeLists.txt @@ -8,6 +8,20 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${ROOT_INCLUDE_DIR} ${CM file(GLOB sources src/*.cpp src/Evaluator/*.cpp src/XML/*.cpp) file(GLOB plugin_sources src/plugins/*.cpp) +#---Add Library------------------------------------------------------------------- +if(DD4HEP_USE_BOOST) + #fg: canonical way of finding Boost w/ cmake uses + # -D Boost_DIR=_path_to_boost + # and then FindBoost.cmake sets the variable Boost_INCLUDE_DIR + FIND_PACKAGE( Boost REQUIRED) + include_directories( ${Boost_INCLUDE_DIR}) + #list(APPEND include_directories ${BOOST_INCLUDE_DIR}) + file(GLOB parser_sources src/parsers/*.cpp ) + add_definitions(-DDD4HEP_USE_BOOST) +else() + file(GLOB parser_sources ) +endif() + if(DD4HEP_USE_PYROOT) file(GLOB headers include/DD4hep/*.h) list(REMOVE_ITEM headers ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/DetFactoryHelper.h @@ -20,7 +34,7 @@ endif() include(DD4hep_XML_setup) -add_library(DD4hepCore SHARED ${sources} ) +add_library(DD4hepCore SHARED ${sources} ${parser_sources} ) target_link_libraries(DD4hepCore ${ROOT_LIBRARIES} ${XML_LIBRARIES} DDSegmentation Geom Reflex ${libraries}) diff --git a/DDCore/include/DD4hep/BasicGrammar.h b/DDCore/include/DD4hep/BasicGrammar.h new file mode 100644 index 000000000..fc701a5dd --- /dev/null +++ b/DDCore/include/DD4hep/BasicGrammar.h @@ -0,0 +1,50 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_BASICGRAMMAR_H +#define DD4HEP_DDG4_BASICGRAMMAR_H + +// C/C++ include files +#include <string> +#include <typeinfo> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /** @class BasicGrammar + * + * @author M.Frank + * @date 13.08.2013 + */ + class BasicGrammar { + public: + /// Default constructor + BasicGrammar(); + /// Default destructor + virtual ~BasicGrammar(); + + /// Instance factory + template <typename TYPE> static const BasicGrammar& instance(); + /// Error callback on invalid conversion + static void invalidConversion(const std::type_info& from, const std::type_info& to); + /// Error callback on invalid conversion + static void invalidConversion(const std::string& value, const std::type_info& to); + /// Access to the type information + virtual const std::type_info& type() const = 0; + /// Access the object size (sizeof operator) + virtual size_t sizeOf() const = 0; + /// Serialize an opaque value to a string + virtual std::string str(const void* ptr) const = 0; + /// Set value from serialized string. On successful data conversion TRUE is returned. + virtual bool fromString(void* ptr, const std::string& value) const = 0; + }; +} // End namespace DD4hep + +#endif /* DD4HEP_DDG4_BASICGRAMMAR_H */ diff --git a/DDCore/include/DD4hep/Callback.h b/DDCore/include/DD4hep/Callback.h new file mode 100644 index 000000000..ce1ef65eb --- /dev/null +++ b/DDCore/include/DD4hep/Callback.h @@ -0,0 +1,372 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDCORE_CALLBACK_H +#define DD4HEP_DDCORE_CALLBACK_H + +// C/C++ include files +#include <algorithm> +#include <typeinfo> +#include <vector> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /**@class Callback Callback.h CPP/Callback.h + * + * Definition of the generic callback structure for member functions + * + * @author M.Frank + * @date 01/03/2013 + * @version 0.1 + */ + struct Callback { + typedef unsigned long (*func_t)(void* obj, const void* fun, const void* args[]); + typedef struct { + void *first, *second; + } mfunc_t; + typedef unsigned long ulong; + + void* par; + func_t call; + mfunc_t func; + Callback() + : par(0), call(0) { + func.first = func.second = 0; + } + Callback(void* p) + : par(p), call(0) { + func.first = func.second = 0; + } + Callback(void* p, void* mf, func_t c) + : par(p), call(c) { + func = *(mfunc_t*) mf; + } + + operator bool() const { + return (call && par && func.first); + } + unsigned long execute(const void* user_param[]) const { + return (*this) ? call(par, &func, user_param) : 0; + } + + template <typename T> static T* cast(void* p) { + return (T*) p; + } + template <typename T> static const T* c_cast(const void* p) { + return (const T*) p; + } + template <typename T> struct Wrapper { + public: + typedef T pmf_t; + union Functor { + mfunc_t ptr; + pmf_t pmf; + Functor(const void* f) { + ptr = *(mfunc_t*) f; + } + Functor(pmf_t f) { + pmf = f; + } + }; + static mfunc_t pmf(pmf_t f) { + const Functor func(f); + return func.ptr; + } + }; + // + // Callback with no arguments + // + template <typename T> const Callback& _make(ulong (*fptr)(void* o, const void* f, const void* u[]), T pmf) { + typename Wrapper<T>::Functor f(pmf); + func = f.ptr; + call = fptr; + return *this; + } + template <typename R, typename T> const Callback& make(R (T::*pmf)()) { + typedef R (T::*pfunc_t)(); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T> const Callback& make(R (T::*pmf)() const) { + typedef R (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T> const Callback& make(void (T::*pmf)()) { + typedef void (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T> const Callback& make(void (T::*pmf)() const) { + typedef void (T::*pfunc_t)() const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void*[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))(); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 1 argument + // + template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A)) { + typedef R (T::*pfunc_t)(A); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A) const) { + typedef R (T::*pfunc_t)(A) const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A> const Callback& make(void (T::*pmf)(A)) { + typedef void (T::*pfunc_t)(const A); + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A> const Callback& make(void (T::*pmf)(A) const) { + typedef void (T::*pfunc_t)(const A) const; + struct _Wrapper : public Wrapper<pfunc_t> { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename Wrapper<pfunc_t>::Functor(f).pmf))((A) u[0]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 2 arguments + // + template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1)) { + typedef R (T::*pfunc_t)(A0, A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1) const) { + typedef R (T::*pfunc_t)(A0, A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1)) { + typedef void (T::*pfunc_t)(A0, A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1) const) { + typedef void (T::*pfunc_t)(A0, A1); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + // + // Callback with 3 arguments + // + template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2)) { + typedef R (T::*pfunc_t)(A0, A1, A2); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make( + R (T::*pmf)(A0, A1, A2) const) { + typedef R (T::*pfunc_t)(A0, A1, A2); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + return (ulong) (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]); + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2)) { + typedef void (T::*pfunc_t)(A0, A1, A2); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2) const) { + typedef void (T::*pfunc_t)(A0, A1, A2); + typedef Wrapper<pfunc_t> _W; + struct _Wrapper : public _W { + static ulong call(void* o, const void* f, const void* u[]) { + (cast<T>(o)->*(typename _W::Functor(f).pmf))((A0) u[0], (A1) u[1], (A2) u[2]); + return 1; + } + }; + return _make(_Wrapper::call, pmf); + } + + template <typename T> static Callback make(void* p, T pmf) { + return Callback(p).make(pmf); + } + + template <typename P, typename R, typename T> static T* dyn_cast(P* p, R (T::*)()) { + return dynamic_cast<T*>(p); + } + template <typename P, typename R, typename T> static const T* dyn_cast(const P* p, R (T::*)() const) { + return dynamic_cast<const T*>(p); + } + + template <typename P, typename R, typename T, typename A> static T* dyn_cast(P* p, R (T::*)(A)) { + return dynamic_cast<T*>(p); + } + template <typename P, typename R, typename T, typename A> static const T* dyn_cast(const P* p, R (T::*)(A) const) { + return dynamic_cast<const T*>(p); + } + }; + + struct CallbackSequence { + typedef std::vector<Callback> Callbacks; + enum Location { FRONT, END }; + Callbacks callbacks; + /// Default constructor + CallbackSequence() { + } + /// Copy constructor + CallbackSequence(const CallbackSequence& c) + : callbacks(c.callbacks) { + } + /// Assignment operator + CallbackSequence& operator=(const CallbackSequence& c) { + if ( this != & c ) callbacks = c.callbacks; + return *this; + } + + //template <typename TYPE, typename R, typename OBJECT> + // CallbackSequence(const std::vector<TYPE*>& objects, R (TYPE::value_type::*pmf)()) { + //} + bool empty() const { + return callbacks.empty(); + } + void clear() { + callbacks.clear(); + } + void add(const Callback& cb,Location where) { + if ( where == CallbackSequence::FRONT ) + callbacks.insert(callbacks.begin(),cb); + else + callbacks.insert(callbacks.end(),cb); + } + void operator()() const; + template <typename A0> void operator()(A0 a0) const; + template <typename A0, typename A1> void operator()(A0 a0, A1 a1) const; + template <typename A0, typename A1, typename A2> void operator()(A0 a0, A1 a1, A2 a2) const; + /// Check the compatibility of two typed objects. The test is the result of a dynamic_cast + static void checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test); + + template <typename TYPE, typename R, typename OBJECT> + void add(TYPE* pointer, R (OBJECT::*pmf)(),Location where=CallbackSequence::END) { + checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf),where); + } + template <typename TYPE, typename R, typename OBJECT, typename A> + void add(TYPE* pointer, R (OBJECT::*pmf)(A),Location where=CallbackSequence::END) { + checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf),where); + } + template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2> + void add(TYPE* pointer, R (OBJECT::*pmf)(A1, A2),Location where=CallbackSequence::END) { + checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer)); + add(Callback(pointer).make(pmf),where); + } + }; + + inline void CallbackSequence::operator()() const { + if (!callbacks.empty()) { + const void* args[1] = { 0 }; + for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0> inline + void CallbackSequence::operator()(A0 a0) const { + if (!callbacks.empty()) { + const void* args[1] = { a0 }; + for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0, typename A1> inline + void CallbackSequence::operator()(A0 a0, A1 a1) const { + if (!callbacks.empty()) { + const void* args[2] = { a0, a1 }; + for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + template <typename A0, typename A1, typename A2> inline + void CallbackSequence::operator()(A0 a0, A1 a1, A2 a2) const { + if (!callbacks.empty()) { + const void* args[3] = { a0, a1, a2 }; + for (Callbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) + (*i).execute(args); + } + } + +} // End namespace DD4hep +#endif // DD4HEP_DDCORE_CALLBACK_H diff --git a/DDCore/include/DD4hep/ConditionTypes.h b/DDCore/include/DD4hep/ConditionTypes.h new file mode 100644 index 000000000..3a69de4ac --- /dev/null +++ b/DDCore/include/DD4hep/ConditionTypes.h @@ -0,0 +1,3 @@ + +#define DD4HEP_INSTANTIATE_GRAMMAR_TYPE(x) namespace DD4hep { \ + template<> const BasicGrammar& BasicGrammar::instance<x>() { static Grammar<x> s; return s;}} diff --git a/DDCore/include/DD4hep/Conditions.h b/DDCore/include/DD4hep/Conditions.h new file mode 100644 index 000000000..42738ed14 --- /dev/null +++ b/DDCore/include/DD4hep/Conditions.h @@ -0,0 +1,214 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_CONDITION_H +#define DD4HEP_GEOMETRY_CONDITION_H + +// Framework include files +#include "DD4hep/Handle.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /// Grammar definition for type binding + class BasicGrammar; + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + // Forward declarations + class DetElement; + + namespace ConditionsInterna { + class Container; + class Object; + class Entry; + class IOV; + } + + /** @class Block ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * Class describing an opaque conditions data block + * + * @author M.Frank + * @version 1.0 + */ + class Block { + /// Access only through the conditions class! + friend class Condition; + private: + protected: + /// Standard initializing constructor + Block(); + /// Standard Destructor + virtual ~Block(); + protected: + /// Data type + const BasicGrammar* grammar; + /// Pointer to object data + void* pointer; + public: + /// Create data block from string representation + void fromString(const std::string& rep); + /// Create string representation of the data block + std::string str(); + /// Generic getter. Specify the exact type, not a polymorph type + template <typename T> inline T& get(); + /// Generic getter (const version). Specify the exact type, not a polymorph type + template <typename T> inline const T& get() const; + }; + + /** @class Condition Condition.h DD4hep/Condition.h + * + * See the documentation about the TGeoPhysicalNode for further + * details. + * + * + * @author M.Frank + * @version 1.0 + */ + class Condition: public Handle<ConditionsInterna::Object> { + public: + typedef ConditionsInterna::Object Object; + typedef ConditionsInterna::Entry Entry; + typedef ConditionsInterna::IOV IOV; + + /// Default constructor + Condition(); + /// Copy constructor + Condition(const Condition& c); + /// Initializing constructor + Condition(Object* p); + /// Constructor to be used when reading the already parsed object + template <typename Q> Condition(const Handle<Q>& e) + : Handle<Object>(e) { + } + /// Initializing constructor + Condition(const std::string& name); + /// Assignment operator + Condition& operator=(const Condition& c); + + /** Data block (bound type) */ + /// Access the data type + int dataType() const; + /// Access the IOV block + Block& block() const; + + /** Interval of validity */ + /// Access the IOV type + int iovType() const; + /// Access the IOV block + IOV& iov() const; + + /** Direct data items in string form */ + /// Access the name of the condition + const std::string& name() const; + /// Access the type field of the condition + const std::string& type() const; + /// Access the comment field of the condition + const std::string& comment() const; + /// Access the validity field of the condition as a string + const std::string& validity() const; + /// Access the value field of the condition as a string + const std::string& value() const; + /// Access the address string [e.g. database identifier] + const std::string& address() const; + /// Access the hosting detector element + DetElement detector() const; + + + /** Conditions meta-data */ + /// Access to the type information + const std::type_info& typeInfo() const; + /// Access to the grammar type + const BasicGrammar& descriptor() const; + + /** Conditions handling */ + /// Replace the data block of the condition with a new value. Free old data + Condition& replace(Entry* new_condition); + /// Re-evaluate the conditions data according to the previous bound type definition + Condition& rebind(); + + /** Bind the data of the conditions object to a given format. + * + * Note: The type definition is possible exactly once. + * Any further rebindings MUST match the identical type. + */ + template <typename T> Condition& bind(); + /// Generic getter. Specify the exact type, not a polymorph type + template <typename T> T& get(); + /// Generic getter (const version). Specify the exact type, not a polymorph type + template <typename T> const T& get() const; + }; + + /// Initializing constructor + inline Condition::Condition(Object* p) : Handle<Object>(p) { + } + + /// Copy constructor + inline Condition::Condition(const Condition& c) : Handle<Object>(c) { + } + + /// Default constructor + inline Condition::Condition() : Handle<Object>() { + } + + /** @class Conditions Conditions.h DD4hep/Conditions.h + * + * Note: The conditions container is owner by the detector element + * On deletion the detector element will destroy the container + * and all associated entries. + * + * @author M.Frank + * @version 1.0 + */ + struct Conditions : public Handle<ConditionsInterna::Container> { + /// Standard object type + typedef ConditionsInterna::Container Object; + /// Local helper definition + typedef ConditionsInterna::Entry Entry; + + /// Definition of the conditions container of this detector element + typedef std::map<std::string, Condition> Entries; + + /// Default constructor + Conditions() + : Handle<Object>() { + } + /// Constructor to be used when reading the already parsed object + template <typename Q> Conditions(const Conditions& c) + : Handle<Object>(c) { + } + /// Constructor to be used when reading the already parsed object + template <typename Q> Conditions(const Handle<Q>& e) + : Handle<Object>(e) { + } + /// Access the number of conditons available for this detector element + size_t count() const; + /// Access the full map of conditons + Entries& entries() const; + /// Clear all conditions. Auto-delete of all existing entries + void removeElements() const; + /** Set a single conditions value (eventually existing entries are overwritten) + * Note: Passing a valid handle also passes ownership!!! + * + * Failure return 0 in case an invalid handle is present + * Successful insertion returns 1 + * Successful overwriting an existing value returns 3 + */ + int set(Entry* data); + }; + + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_CONDITION_H */ diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index 215def9a7..06ecf1a8c 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -6,16 +6,17 @@ // Author : M.Frank // //==================================================================== - -#ifndef DD4HEP_LCDD_DETECTOR_H -#define DD4HEP_LCDD_DETECTOR_H +#ifndef DD4HEP_DETECTOR_H +#define DD4HEP_DETECTOR_H // Framework include files #include "DD4hep/Handle.h" +#include "DD4hep/Callback.h" #include "DD4hep/Objects.h" #include "DD4hep/Volumes.h" #include "DD4hep/Readout.h" #include "DD4hep/Alignment.h" +#include "DD4hep/Conditions.h" #include "DD4hep/Segmentations.h" // C/C++ include files @@ -32,36 +33,23 @@ namespace DD4hep { */ namespace Geometry { - // struct SensitiveDetector; - // struct Detector; - struct LCDD; + class LCDD; + class DetElementObject; + class SensitiveDetectorObject; /** @class SensitiveDetector Detector.h DD4hep/lcdd/Detector.h * * @author M.Frank * @version 1.0 */ - struct SensitiveDetector: public Ref_t { + class SensitiveDetector: public Handle<SensitiveDetectorObject> { public: - /// Definition of the extension type - typedef std::map<const std::type_info*, void*> Extensions; - - struct Object: public TNamed { - unsigned int magic; - int verbose; - int combineHits; - double ecut; - std::string hitsCollection; - Readout readout; - Region region; - LimitSet limits; - Extensions extensions; - - /// Default constructor - Object(); - /// Internal object destructor: release extension object(s) - virtual ~Object(); - }; + /// Extensions destructor type + typedef void (*destruct_t)(void*); + /// Internal object type + typedef SensitiveDetectorObject Object; + /// Definition of the base handle type + typedef Handle<SensitiveDetectorObject> RefObject; protected: /// Templated destructor function @@ -78,24 +66,29 @@ namespace DD4hep { public: /// Default constructor - SensitiveDetector() - : Ref_t() { + SensitiveDetector() + : RefObject() { } - /// Copy from handle - SensitiveDetector(const SensitiveDetector& sd) - : Ref_t(sd) { + /// Constructor to copy handled object + SensitiveDetector(Object* ptr) + : RefObject(ptr) { } /// Copy from named handle - SensitiveDetector(const Ref_t& sd) - : Ref_t(sd) { + SensitiveDetector(const RefObject& sd) + : RefObject(sd) { + } + + /// Copy from handle + SensitiveDetector(const SensitiveDetector& sd) + : RefObject(sd) { } /// Templated constructor for handle conversions template <typename Q> - SensitiveDetector(const Handle<Q>& e) - : Ref_t(e) { + SensitiveDetector(const Handle<Q>& e) + : RefObject(e) { } /// Constructor for a new sensitive detector element @@ -185,76 +178,34 @@ namespace DD4hep { * @author M.Frank * @version 1.0 */ - struct DetElement: public Ref_t { - typedef Ref_t Parent; + class DetElement: public Handle<DetElementObject> { + public: + /// Internal object type + typedef DetElementObject Object; + /// Definition of the base handle type + typedef Handle<DetElementObject> RefObject; + typedef DetElement Parent; + + /// Extensions copy constructor type + typedef void* (*copy_t)(const void*, DetElement); + /// Extensions destructor type + typedef void (*destruct_t)(void*); + typedef std::map<std::string, DetElement> Children; typedef std::map<const std::type_info*, void*> Extensions; enum CopyParameters { COPY_NONE = 0, COPY_PLACEMENT = 1 << 0, COPY_PARENT = 1 << 1, COPY_ALIGNMENT = 1 << 2, LAST }; - struct Object: public TNamed { - /// Magic number to ensure data integrity - unsigned int magic; - /// Unique integer identifier of the detector instance - int id; - /// Full path to this detector element. May be invalid - std::string path; - /// Flag to process hits - int combineHits; - - /// The subdetector placement corresponding to the detector element's volume - PlacedVolume placement; - /** The cached VolumeID of this subdetector element - * Please note: - * These values are set when populating the volume manager. - * There are restrictions: e.g. only sensitive subdetectors are present. - */ - VolumeID volumeID; - /// Reference to the parent element - Parent parent; - /// Reference element for stored transformations - Parent reference; - /// The array of children - Children children; - /// User extensions - Extensions extensions; - - /**@info: Additional information set externally to facilitate the processing of event data */ - /// Basic detector element alignment entry - Alignment alignment; - /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements - std::vector<Alignment> volume_alignments; - /// The detector elements condition entry - Conditions conditions; - - /**@info: Cached information of the detector element */ - /// Intermediate buffer to store the transformation to the world coordination system - TGeoMatrix* worldTrafo; - /// Intermediate buffer to store the transformation to the parent detector element - TGeoMatrix* parentTrafo; - /// Intermediate buffer for the transformation to an arbitrary DetElement - TGeoMatrix* referenceTrafo; - /// The path to the placement of the detector element (if placed) - std::string placementPath; - - /**@info: Public methods to ease the usage of the data. */ - /// Default constructor - Object(); - /// Internal object destructor: release extension object(s) - virtual ~Object(); - /// Deep object copy to replicate DetElement trees e.g. for reflection - virtual Object* clone(int new_id, int flag) const; - /// Conversion to reference object - operator Ref_t(); - /// Conversion to reference object - Ref_t asRef(); - /// Create cached matrix to transform to world coordinates - TGeoMatrix* worldTransformation(); - /// Create cached matrix to transform to parent coordinates - TGeoMatrix* parentTransformation(); - /// Create cached matrix to transform to reference coordinates - TGeoMatrix* referenceTransformation(); + + enum UpdateParam { + CONDITIONS_CHANGED = 1<<0, + PLACEMENT_CHANGED = 1<<1, + SOMETHING_CHANGED = 1<<2, + PLACEMENT_ELEMENT = 1<<20, + PLACEMENT_HIGHEST = 1<<21, + PLACEMENT_DETECTOR = 1<<22, + PLACEMENT_NONE }; /// Internal assert function to check conditions @@ -272,21 +223,31 @@ namespace DD4hep { } /// Add an extension object to the detector element - void* i_addExtension(void* ptr, const std::type_info& info, void* (*copy)(const void*, DetElement), - void (*destruct)(void*)); + void* i_addExtension(void* ptr, const std::type_info& info, copy_t ctor, destruct_t dtor) const; /// Access an existing extension object from the detector element void* i_extension(const std::type_info& info) const; + /// Internal call to extend the detector element with an arbitrary structure accessible by the type + void i_addUpdateCall(unsigned int callback_type, const Callback& callback) const; public: /// Default constructor - DetElement() - : Ref_t() { + DetElement() + : RefObject() { } + /// Constructor to copy handled object + DetElement(Object* ptr) + : RefObject(ptr) { + } + + /// Clone constructor + DetElement(Object* data, const std::string& name, const std::string& type); + +#if 0 /// Default constructor template <typename Q> DetElement(Q* data, const std::string& name, const std::string& type) - : Ref_t(data) { + : RefObject(data) { this->assign(data, name, type); } @@ -297,7 +258,7 @@ namespace DD4hep { /// Construction function for a new subdetector element template <typename Q> - static Q* createObject(const std::string& name, const std::string& type, int id) { + static Q* createObject(const std::string& name, const std::string& type, int id) { DetElement det; Q *p = new Q(); Object* o = p; @@ -310,27 +271,27 @@ namespace DD4hep { /// Construction function for a new subdetector element template <typename Q> - static DetElement create(const std::string& name, const std::string& type, int id, Q** ptr = 0) { + static DetElement create(const std::string& name, const std::string& type, int id, Q** ptr = 0) { Q* p = createObject<Q>(name, type, id); if (ptr) *ptr = p; - return DetElement(Ref_t(p)); + return DetElement(p); } - +#endif /// Templated constructor for handle conversions template <typename Q> DetElement(const Handle<Q>& e) - : Ref_t(e) { + : RefObject(e) { } /// Constructor to copy handle - DetElement(const DetElement& e) - : Ref_t(e) { + DetElement(const DetElement& e) + : RefObject(e) { } #ifdef __MAKECINT__ /// Constructor to copy handle - DetElement(const Ref_t& e) - : Ref_t(e) { + DetElement(const Ref_t& e) + : RefObject(e) { } #endif /// Constructor for a new subdetector element @@ -370,7 +331,8 @@ namespace DD4hep { DetElement clone(const std::string& new_name, int new_id) const; /// Extend the detector element with an arbitrary structure accessible by the type - template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) { + template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) const { + CallbackSequence::checkTypes(typeid(IFACE), typeid(CONCRETE), dynamic_cast<IFACE*>(c)); return (IFACE*) i_addExtension(dynamic_cast<IFACE*>(c), typeid(IFACE), _copy<CONCRETE>, _delete<IFACE>); } @@ -379,6 +341,17 @@ namespace DD4hep { return (T*) i_extension(typeid(T)); } + /// Extend the detector element with an arbitrary callback + template <typename Q, typename T> + void callAtUpdate(unsigned int type, Q* pointer, + void (T::*pmf)(unsigned int typ, DetElement& det, void* opt_par)) const + { + CallbackSequence::checkTypes(typeid(T), typeid(Q), dynamic_cast<T*>(pointer)); + i_addUpdateCall(type, Callback(pointer).make(pmf)); + } + /// Remove callback from object + void removeAtUpdate(unsigned int type, void* pointer) const; + /// Set the detector identifier int id() const; /// Setter: Combine hits attribute @@ -400,7 +373,7 @@ namespace DD4hep { /// Set all attributes in one go DetElement& setAttributes(const LCDD& lcdd, const Volume& volume, const std::string& region, const std::string& limits, - const std::string& vis); + const std::string& vis); /// Set Visualization attributes to the detector element DetElement& setVisAttributes(const LCDD& lcdd, const std::string& name, const Volume& volume); @@ -443,15 +416,26 @@ namespace DD4hep { /// Transformation from local coordinates of the placed volume to arbitrary parent system set as reference bool localToReference(const Position& local, Position& reference) const; + /// Create cached matrix to transform to world coordinates + const TGeoHMatrix& worldTransformation() const; + /// Create cached matrix to transform to parent coordinates + const TGeoHMatrix& parentTransformation() const; + /// Create cached matrix to transform to reference coordinates + const TGeoHMatrix& referenceTransformation() const; /// Transformation from world coordinates of the local placed volume coordinates bool worldToLocal(const Position& global, Position& local) const; /// Transformation from world coordinates of the local placed volume coordinates bool parentToLocal(const Position& parent, Position& local) const; /// Transformation from world coordinates of the local placed volume coordinates bool referenceToLocal(const Position& reference, Position& local) const; - }; } /* End namespace Geometry */ } /* End namespace DD4hep */ -#endif /* DD4HEP_LCDD_DETECTOR_H */ + +// It is not so clear if Clients do really rely on the interna +// of the DetElement and the SensitiveDetector object .... + +//#include "DD4hep/objects/DetectorInterna.h" + +#endif /* DD4HEP_DETECTOR_H */ diff --git a/DDCore/include/DD4hep/DetectorTools.h b/DDCore/include/DD4hep/DetectorTools.h index 436932556..93a8c0e65 100644 --- a/DDCore/include/DD4hep/DetectorTools.h +++ b/DDCore/include/DD4hep/DetectorTools.h @@ -12,6 +12,8 @@ // Framework include files #include "DD4hep/Detector.h" +class TGeoHMatrix; + /* * DD4hep namespace declaration */ @@ -30,47 +32,42 @@ namespace DD4hep { * @author M.Frank * @version 1.0 */ - class DetectorTools { - public: + namespace DetectorTools { typedef std::vector<DetElement> ElementPath; typedef std::vector<PlacedVolume> PlacementPath; + + /// Determine top level element (=world) for any element walking up the detector element tree + DetElement topElement(DetElement child); + /// Assemble the path of a particular detector element std::string elementPath(DetElement element); /// Assemble the path of the PlacedVolume selection - static std::string elementPath(const ElementPath& nodes); - /// Collect detector elements to the top detector element (world) - static void elementPath(DetElement elt, ElementPath& detectors); - /// Collect detector elements to any parent detector element - static void elementPath(DetElement parent, DetElement elt, ElementPath& detectors); - /// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] - static void elementPath(DetElement elt, PlacementPath& nodes); + std::string elementPath(const ElementPath& nodes); - /// Find DetElement as child of the top level volume by it's absolute path - static DetElement findElement(LCDD& lcdd, const std::string& path); + /// Collect detector elements to the top detector element (world) + void elementPath(DetElement elt, ElementPath& detectors); /// Find DetElement as child of a parent by it's relative or absolute path - static DetElement findElement(DetElement parent, const std::string& subpath); - /// Determine top level element (=world) for any element walking up the detector element tree - static DetElement topElement(DetElement child); - + DetElement findDaughterElement(DetElement parent, const std::string& subpath); + /// Find path between the child element and the parent element + bool isParentElement(DetElement parent, DetElement child); + /// Assemble the placement path from a given detector element to the world volume - static std::string placementPath(DetElement element); + std::string placementPath(DetElement element); /// Assemble the path of the PlacedVolume selection - static std::string placementPath(const PlacementPath& nodes); + std::string placementPath(const PlacementPath& nodes); + /// Collect detector elements placements to the top detector element (world) [no holes!] - static void placementPath(DetElement elt, PlacementPath& nodes); + void placementPath(DetElement elt, PlacementPath& nodes); /// Collect detector elements placements to the parent detector element [no holes!] - static void placementPath(DetElement parent, DetElement child, PlacementPath& nodes); - - - /// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes - static bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path); - /// Find path between the child element and the parent element - static bool findParent(DetElement parent, DetElement child, ElementPath& detectors); - - /// Create cached matrix to transform to positions to an upper level Placement - static TGeoMatrix* placementTrafo(const PlacementPath& nodes, bool inverse); + void placementPath(DetElement parent, DetElement child, PlacementPath& nodes); - }; + /// Find a given node in the hierarchy starting from the top node (absolute placement!) + PlacedVolume findNode(PlacedVolume top_place, const std::string& place); + /// Update cached matrix to transform to positions to an upper level Placement + void placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix*& mat); + /// Update cached matrix to transform to positions to an upper level Placement + void placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix& mat); + } } /* End namespace Geometry */ } /* End namespace DD4hep */ diff --git a/DDCore/include/DD4hep/Exceptions.h b/DDCore/include/DD4hep/Exceptions.h new file mode 100644 index 000000000..2ae200ce4 --- /dev/null +++ b/DDCore/include/DD4hep/Exceptions.h @@ -0,0 +1,48 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDCORE_EXCEPTIONS_H +#define DD4HEP_DDCORE_EXCEPTIONS_H + +// C/C++ include files +#include <string> +#include <typeinfo> +#include <stdexcept> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /** @class unrelated_type_error + * + * @author M.Frank + * @date 13.08.2013 + */ + struct unrelated_type_error : public std::runtime_error { + static std::string msg(const std::type_info& typ1, const std::type_info& typ2, const std::string& text); + unrelated_type_error(const std::type_info& typ1, const std::type_info& typ2, const std::string& text = "") + : std::runtime_error(msg(typ1, typ2, text)) { + } + }; + + /** @class unrelated_value_error + * + * @author M.Frank + * @date 13.08.2013 + */ + struct unrelated_value_error : public std::runtime_error { + static std::string msg(const std::type_info& typ, const std::string& text); + unrelated_value_error(const std::type_info& typ, const std::string& text = "") + : std::runtime_error(msg(typ, text)) { + } + }; + +} // End namespace DD4hep + +#endif /* DD4HEP_DDCORE_EXCEPTIONS_H */ diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index b289cc0dd..8f12ffc28 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -41,13 +41,6 @@ class TNamed; */ namespace DD4hep { - /// Access to the CXX abi name - std::string typeName(const std::type_info& type); - /// Throw exception when handles are check for validity - void invalidHandleError(const std::type_info& type); - /// Throw exception when handles are badly assigned - void invalidHandleAssignmentError(const std::type_info& from, const std::type_info& to); - /* * Geometry sub-namespace declaration */ diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h index 5971b421e..32c56fc56 100644 --- a/DDCore/include/DD4hep/LCDD.h +++ b/DDCore/include/DD4hep/LCDD.h @@ -52,8 +52,8 @@ namespace DD4hep { * @author M.Frank * @version 1.0 */ - struct LCDD { - + class LCDD { + public: typedef std::map<std::string, Handle<> > HandleMap; typedef std::map<std::string, std::string> PropertyValues; typedef std::map<std::string, PropertyValues> Properties; diff --git a/DDCore/include/DD4hep/ObjectExtensions.h b/DDCore/include/DD4hep/ObjectExtensions.h new file mode 100644 index 000000000..9fdf56c66 --- /dev/null +++ b/DDCore/include/DD4hep/ObjectExtensions.h @@ -0,0 +1,68 @@ +// $Id: Detector.h 1087 2014-04-09 12:25:51Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_OBJECTEXTENSIONS_H +#define DD4HEP_GEOMETRY_OBJECTEXTENSIONS_H + +// C/C++ include files +#include <typeinfo> +#include <map> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /** @class ObjectExtensions DetectorInterna.h DD4hep/objects/DetectorInterna.h + * + * @author M.Frank + * @version 1.0 + */ + class ObjectExtensions { + public: + /// Definition of the extension type + typedef std::map<const std::type_info*, void*> Extensions; + /// Extensions copy constructor type + typedef void* (*copy_t)(const void*, void* arg); + /// Extensions destructor type + typedef void (*destruct_t)(void*); + struct Entry { + copy_t copy; + destruct_t destruct; + int id; + }; + typedef std::map<const std::type_info*, Entry> ExtensionMap; + + /// The extensions object + Extensions extensions; + /// Pointer to the extension map + ExtensionMap* extensionMap; + + public: + /// Default constructor + ObjectExtensions(const std::type_info& parent_type); + /// Default destructor + virtual ~ObjectExtensions(); + /// Clear all extensions + void clear(); + /// Copy object extensions from another object. Hosting type must be identical! + void copyFrom(const Extensions& ext, void* arg); + /// Add an extension object to the detector element + void* addExtension(void* ptr, const std::type_info& info, copy_t ctor, destruct_t dtor); + /// Add an extension object to the detector element + void* addExtension(void* ptr, const std::type_info& info, destruct_t dtor); + /// Remove an existing extension object from the instance + void* removeExtension(const std::type_info& info, bool destroy); + /// Access an existing extension object from the detector element + void* extension(const std::type_info& info, bool alert) const; + /// Access an existing extension object from the detector element + void* extension(const std::type_info& info) const; + }; + +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_OBJECTEXTENSIONS_H */ diff --git a/DDCore/include/DD4hep/Parsers.h b/DDCore/include/DD4hep/Parsers.h new file mode 100644 index 000000000..c68f03380 --- /dev/null +++ b/DDCore/include/DD4hep/Parsers.h @@ -0,0 +1,695 @@ +// ============================================================================ +#ifndef DD4HEP_PARSERS_H +#define DD4HEP_PARSERS_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +// ============================================================================ +#define PARSERS_DECL_FOR_SINGLE(Type) \ + int parse(Type& result, const std::string& input); + +#define PARSERS_DECL_FOR_PAIR(FirstType, SecondType) \ + int parse(std::pair<FirstType, SecondType >& result,const std::string& input); + +#define PARSERS_DECL_FOR_LIST(InnerType) \ + int parse(std::vector<InnerType>& result,const std::string& input); \ + int parse(std::list<InnerType>& result,const std::string& input); \ + int parse(std::set<InnerType>& result,const std::string& input); +// ============================================================================ +/** @file + * The declaration of major parsing functions used e.g + * for (re)implementation of new extended properties see class Property + * These function also could be used in a different, much wider contex. + * all of them have the semantic: + * <c>int parse ( TYPE& result , const std::string& input )</c> + * where <c>input</c> is the input string to be parsed, + * and <c>result</c> is the the result of parsing + * + * @code + * + * const std::string input = ... ; + * std::vector<std::string> result ; + * + * // parse the input + * int sc = parse ( result , input ) ; + * if ( sc.isFailure() ) + * { + * // error here ... + * } + * std::cout << "vector size " << result.size() << std::endl ; + * + * @endcode + * + * @see DD4hep::Parsers::parse + * @see Property + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep { + namespace Parsers { + // ======================================================================== + /** parse the <c>bool</c> value + * @see DD4hep::Parsers::BoolGrammar + * @param result (output) boolean result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + PARSERS_DECL_FOR_SINGLE(bool) + // ======================================================================== + /** parse the <c>char</c> value + * + * @see DD4hep::Parsers::CharGrammar + * @param result (output) boolean result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + PARSERS_DECL_FOR_SINGLE(char) + /// @see DD4hep::Parsers::parser(char&,std::string&) + PARSERS_DECL_FOR_SINGLE(unsigned char) + /// @see DD4hep::Parsers::parser(char&,std::string&) + PARSERS_DECL_FOR_SINGLE(signed char) + // ======================================================================== + /** parse the <c>int</c> value + * + * @see DD4hep::Parsers::IntGrammar + * @param result (output) integer result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(int) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(short) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned short) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned int) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long long) + /// @see DD4hep::Parsers::parser( int&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(unsigned long long) + // ======================================================================== + /** parse the <c>double</c> value + * + * @see DD4hep::Parsers::RealGrammar + * @param result (output) double result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(double) + /// @see DD4hep::Parsers::parser( double&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(float) + /// @see DD4hep::Parsers::parser( double&, const std::string& ) + PARSERS_DECL_FOR_SINGLE(long double) + // ======================================================================== + /** parse the <c>std::string</c> value + * + * @see DD4hep::Parsers::StringGrammar + * @param result (output) string result + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_SINGLE(std::string) + // ======================================================================== + + PARSERS_DECL_FOR_LIST(bool) + PARSERS_DECL_FOR_LIST(char) + PARSERS_DECL_FOR_LIST(unsigned char) + PARSERS_DECL_FOR_LIST(signed char) + + PARSERS_DECL_FOR_LIST(int) + PARSERS_DECL_FOR_LIST(short) + PARSERS_DECL_FOR_LIST(unsigned short) + PARSERS_DECL_FOR_LIST(unsigned int) + PARSERS_DECL_FOR_LIST(long) + PARSERS_DECL_FOR_LIST(unsigned long) + PARSERS_DECL_FOR_LIST(long long) + PARSERS_DECL_FOR_LIST(unsigned long long) + + PARSERS_DECL_FOR_LIST(double) + PARSERS_DECL_FOR_LIST(float) + PARSERS_DECL_FOR_LIST(long double) + + PARSERS_DECL_FOR_LIST(std::string) + // ======================================================================== + // Advanced parses + // ======================================================================== + /** parse the <c>std::pair\<double,double\></c> value + * + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) pair of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_PAIR(double, double) + // ======================================================================== + /** parse the <c>std::pair\<int,int\></c> value + * + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) pair of integers + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + PARSERS_DECL_FOR_PAIR(int, int) + // ======================================================================== + /** parse the <c>std::vector\<std::pair\<double,double\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) vector with pairs of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector<std::pair<double, double> >& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::vector\<std::pair\<int,int\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::PairGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) vector with pairs of int + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector<std::pair<int, int> >& result, const std::string& input); + // ======================================================================== + // vector< vector< TYPE > > + // ======================================================================== + /** parse the <c>std::vector\<std::vector\<std::string\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::StringGrammar + * @param result (output) vector with vectors of strings + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector<std::vector<std::string> >& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::vector\<std::vector\<double\> \></c> value + * + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) vector with vectors of doubles + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::vector<std::vector<double> >& result, const std::string& input); + // ======================================================================== + // map< TYPE, TYPE > + // ======================================================================== + /** parse the <c>std::map\<int , int\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with integer key and double value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<int, int>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<int , double\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::IntGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with integer key and double value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<int, double>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , std::string\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @param result (output) map with string key and value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, std::string>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , int\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with string key and integer value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, int>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , double\></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with string key and integer value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, double>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<std::string\> \></c> + * value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @param result (output) map with string value and + * vector of strings as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, std::vector<std::string> >& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<int\> \></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::IntGrammar + * @param result (output) map with string value and + * vector of integers as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, std::vector<int> >& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<std::string , std::vector\<double\> \></c> value + * + * @see DD4hep::Parsers::MapGrammar + * @see DD4hep::Parsers::StringGrammar + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @param result (output) map with string value and + * vector of doubles as value + * @param input (input) the string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + int parse(std::map<std::string, std::vector<double> >& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2007-12-06 + */ + int parse(std::map<int, std::string>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<unsigned int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2007-12-06 + */ + int parse(std::map<unsigned int, std::string>& result, const std::string& input); + // ======================================================================== + /** parse the <c>std::map\<unsigned int,std::string\> \></c> objects + * + * @see DD4hep::Parsers::MapGrammar + */ + int parse(std::map<std::string, unsigned int>& result, const std::string& input); + + // ======================================================================== + /** parse the pair expression (map-component) " 'name' :value" + * + * @code + * + * const std::string input = "'PackageName':DD4hepKernel" ; + * std::string name ; + * std::string value ; + * int sc = DD4hep::Parsers::parse ( name , value , input ) ; + * if ( sc.isFailure() ) { ... } + * std::cout << "\tParsed name is " << name + * << "\tParsed value is " << value << std::endl + * @endcode + * + * @param name (output) the parsed name of the component, defined + * as 'name' or "name" before the column symbol ":", + * the leading and trailing blans are omitted + * @param value (output) the parsed value of the component, + * defined as everything after the column symbol ":" + * till the end of the string + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + int parse(std::string& name, std::string& value, const std::string& input); + + // ======================================================================== + /** helper function, needed for implementation of map of pairs + * It is very useful construction for monitoring to + * represent the value and error or the allowed range for + * some parameter + * @param params the map of pair + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @date 2009-05-19 + */ + int parse(std::map<std::string, std::pair<double, double> >& params, const std::string& input); + // ======================================================================== + /** parser function for C-arrays + * @param params C-array + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class T, unsigned int N> + int parse(T (&result)[N], const std::string& input) { + typedef std::vector<T> _Vct; + // create the temporary vector + _Vct tmp; + int sc = parse(tmp, input); + if (!sc) { + return sc; + } // RETURN + if (N != tmp.size()) { + return 0; + } // RETURN + // + std::copy(tmp.begin(), tmp.end(), result); + // + return 1; // RETURN + } + // ======================================================================== + /** parser function for C-strings + * @param params C-string + * @param input the string to be parsed + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-15 + */ + template <unsigned int N> + int parse(char (&result)[N], const std::string& input) { + // clear the string + std::fill_n(result, N, ' '); + // create the temporary string + std::string tmp; + int sc = parse(tmp, input); + if (!sc) { + return sc; + } // RETURN + if (N == tmp.size()) { + std::copy(tmp.begin(), tmp.end(), result); + } + else if (N + 2 == tmp.size() && ('\'' == tmp[0] || '\"' == tmp[0]) && (tmp[0] == tmp[tmp.size() - 1])) { + std::copy(tmp.begin() + 1, tmp.end() - 1, result); + } + else { + return 0; + } + // + return 1; // RETURN + } + + // ======================================================================== + /** parse 3D-point + * + * Valid representations of 3D-point: + * + * - a'la python tuple with 3 elements ("canonical") + * - a'la python list with 3 elements + * - tuple or list with named ordered fields + * + * @code + * + * " (1,2,3) " + * " [1,2,3] " + * " [ x : 1, 2, Z:3 ] " + * " [ pX : 1 , PY : 2, 3] " + * + * @endcode + * + * Valid keys for names fields: + * + * @code + * + * "x", "X" , "pX" , "Px" , "PX " + * "y", "Y" , "pY" , "Py" , "PY " + * "z", "Z" , "pZ" , "Pz" , "PZ " + * + * @endcode + * + * @attention Named fields must be ordered <code>(x,y,z)</code> + * + * @param result (output) the parsed point + * @param input (input) the input string + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse(ROOT::Math::XYZPoint& result, const std::string& input); + + // ======================================================================== + /** parse 3D-vector + * + * Valid representations of 3D-vector: + * + * - a'la python tuple with 3 elements ("canonical") + * - a'la python list with 3 elements + * - tuple or list with named ordered fields + * + * @code + * + * " (1,2,3) " + * " [1,2,3] " + * " [ x : 1, 2, Z:3 ] " + * " [ pX : 1 , PY : 2, 3] " + * + * @endcode + * + * Valid keys for names fields: + * + * @code + * + * "x", "X" , "pX" , "Px" , "PX " + * "y", "Y" , "pY" , "Py" , "PY " + * "z", "Z" , "pZ" , "Pz" , "PZ " + * + * @endcode + * + * @attention Named fields must be ordered <code>(x,y,z)</code> + * + * @param result (output) the parsed vector + * @param input (input) the input string + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse( ROOT::Math::XYZVector& result, const std::string& input); + + // ======================================================================== + /** parse PxPyPzEVector + * + * Valid representations of Lorenzt vector + * + * - a'la python tuple with 4 elements ("canonical") + * - a'la python list with 4 elements + * - python/list with inner representation of 3D-point/vector + * - tuple or list with named ordered fields + * + * @code + * + * " (1,2,3,4) " + * " (1,2,3;4) " + * + * " [1,2,3,4] " + * " [1,2,3;4] " + * + * " [ x:1 ,2,3; e= 4] " + * " [ pX : 1 , PY : 2, 3 , T= 4] " + * + * " [ ( pX : 1 , PY : 2, 3 ) , 4] " + * " [ ( pX : 1 , PY : 2, 3 ) ; 4] " + * + * " [ 4 , ( pX : 1 , PY : 2, 3 ) ] " + * " [ 4 ; ( pX : 1 , PY : 2, 3 ) ] " + * + * " [ [ pX : 1 , PY : 2, 3 ] , 4] " + * " [ [ pX : 1 , PY : 2, 3 ] ; 4] " + * + * " [ 4 , [ pX : 1 , PY : 2, 3 ] ] " + * " [ 4 ; [ pX : 1 , PY : 2, 3 ] ] " + * + * " ( ( pX : 1 , PY : 2, 3 ) , 4 )" + * " ( ( pX : 1 , PY : 2, 3 ) ; 4 )" + * + * " ( 4 , ( pX : 1 , PY : 2, 3 ) )" + * " ( 4 ; ( pX : 1 , PY : 2, 3 ) )" + * + * " ( [ pX : 1 , PY : 2, 3 ] , 4 )" + * " ( [ pX : 1 , PY : 2, 3 ] ; 4 )" + * + * " ( 4 , [ pX : 1 , PY : 2, 3 ] )" + * " ( 4 ; [ pX : 1 , PY : 2, 3 ] )" + * + * + * @endcode + * + * Note that "eenrgy" element can be separated with semicolumn. + * + * Valid keys for names fields: + * + * @code + * + * "x", "X" , "pX" , "Px" , "PX " + * "y", "Y" , "pY" , "Py" , "PY " + * "z", "Z" , "pZ" , "Pz" , "PZ " + * "t", "T" , "e" , "E" + * + * @endcode + * + * @attention Named fields must be ordered <code>(x,y,z)</code> + * + * @param result (output) the parsed lorentz vector + * @param input (input) the input string + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse(ROOT::Math::PxPyPzEVector& result, const std::string& input); + // ======================================================================== + /** parse the vector of points + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse( std::vector<ROOT::Math::XYZPoint>& result, const std::string& input); + int parse( std::list<ROOT::Math::XYZPoint>& result, const std::string& input); + int parse( std::set<ROOT::Math::XYZPoint>& result, const std::string& input); + // ======================================================================== + /** parse the vector of vectors + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse( std::vector<ROOT::Math::XYZVector>& result, const std::string& input); + int parse( std::list<ROOT::Math::XYZVector>& result, const std::string& input); + int parse( std::set<ROOT::Math::XYZVector>& result, const std::string& input); + // ======================================================================== + /** parse the vector of vectors + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse(std::vector<ROOT::Math::PxPyPzEVector>& result, const std::string& input); + int parse(std::list<ROOT::Math::PxPyPzEVector>& result, const std::string& input); + int parse(std::set<ROOT::Math::PxPyPzEVector>& result, const std::string& input); + + // ======================================================================== + }// end of namespace Parsers +// ========================================================================== +}// end of namespace DD4hep +// ============================================================================ +// The END +// ============================================================================ +#endif // DD4HEP_PARSERS_H +// ============================================================================ diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h index 130ecc99b..9fd951604 100644 --- a/DDCore/include/DD4hep/Primitives.h +++ b/DDCore/include/DD4hep/Primitives.h @@ -19,6 +19,83 @@ */ namespace DD4hep { + /// We need it so often: one-at-time 32 bit hash function + inline unsigned int hash32(const char* key) { + unsigned int hash = 0; + const char* k = key; + for (; *k; k++) { + hash += *k; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); hash += (hash << 15); + return hash; + } + /// ABI information about type names + std::string typeName(const std::type_info& type); + void typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text = ""); + /// Throw exception when handles are check for validity + void invalidHandleError(const std::type_info& type); + /// Throw exception when handles are badly assigned + void invalidHandleAssignmentError(const std::type_info& from, const std::type_info& to); + + /// Throw exception when handles are check for validity + template <typename T> void invalidHandleError() { + invalidHandleError(typeid(T)); + } + + /// Throw exception when handles are check for validity + void notImplemented(const std::string& msg); + + /** @class ComponentCast Primitives.h DD4hep/Primitives.h + * + * @author M.Frank + * @date 13.08.2013 + */ + class ComponentCast { + public: + typedef void (*destroy_t)(void*); + typedef void* (*cast_t)(const void*); +#ifdef __CINT__ + const std::type_info* type; +#else + const std::type_info& type; +#endif + const void* abi_class; + destroy_t destroy; + cast_t cast; + + private: + /// Initializing Constructor + ComponentCast(const std::type_info& t, destroy_t d, cast_t c); + /// Defautl destructor + virtual ~ComponentCast(); + + public: + template <typename TYPE> static void _destroy(void* p) { + TYPE* q = (TYPE*)p; + if (q) delete q; + } + template <typename TYPE> static void* _cast(const void* p) { + TYPE* q = (TYPE*)p; + q = dynamic_cast<TYPE*>(q); + return (void*)q; + } + template <typename TYPE> static ComponentCast& instance() { + static ComponentCast c(typeid(TYPE),_destroy<TYPE>,_cast<TYPE>); + return c; + } + + /// Apply cast using typeinfo instead of dynamic_cast + void* apply_dynCast(const ComponentCast& to, const void* ptr) const; + /// Apply cast using typeinfo instead of dynamic_cast + void* apply_upCast(const ComponentCast& to, const void* ptr) const; + /// Apply cast using typeinfo instead of dynamic_cast + void* apply_downCast(const ComponentCast& to, const void* ptr) const; + }; + + // Put here global basic type definitions derived from primitive types of the DD4hep namespace typedef DDSegmentation::CellID CellID; typedef DDSegmentation::VolumeID VolumeID; diff --git a/DDCore/include/DD4hep/Printout.h b/DDCore/include/DD4hep/Printout.h index 2f8f4251d..b2f34875b 100644 --- a/DDCore/include/DD4hep/Printout.h +++ b/DDCore/include/DD4hep/Printout.h @@ -130,6 +130,9 @@ namespace DD4hep { /// Set new print level. Returns the old print level PrintLevel setPrintLevel(PrintLevel new_level); + /// Access the current printer level + PrintLevel printLevel(); + /// Customize printer function void setPrinter(void* print_arg, output_function_t fcn); diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h index 6c09e9025..abefd8e0d 100644 --- a/DDCore/include/DD4hep/Readout.h +++ b/DDCore/include/DD4hep/Readout.h @@ -16,6 +16,9 @@ #include "DD4hep/IDDescriptor.h" #include "DD4hep/Segmentations.h" +// C/C++ include files +#include <map> + /* * DD4hep namespace declaration */ @@ -74,34 +77,6 @@ namespace DD4hep { Segmentation segmentation() const; }; - /** @class Conditions Readout.h DD4hep/lcdd/Readout.h - * - * @author M.Frank - * @version 1.0 - */ - struct Conditions: public Ref_t { - struct Object: public TNamed { - /// Standard constructor - Object(); - /// Default destructor - virtual ~Object(); - }; - /// Default constructor - Conditions() - : Ref_t() { - } - /// Constructor to be used when reading the already parsed object - template <typename Q> Conditions(const Handle<Q>& e) - : Ref_t(e) { - } - /// Initializing constructor - Conditions(const LCDD& doc, const std::string& name); - /// Additional data accessor - Object& _data() const { - return *data<Object>(); - } - }; - } /* End namespace Geometry */ } /* End namespace DD4hep */ #endif /* DD4hep_GEOMETRY_READOUT_H */ diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h index 6f2dc2a9d..fe7601db5 100644 --- a/DDCore/include/DD4hep/Shapes.h +++ b/DDCore/include/DD4hep/Shapes.h @@ -28,19 +28,6 @@ #include "TGeoTube.h" #include "TGeoTorus.h" #include "TGeoCompositeShape.h" -//class TGeoShape; -//class TGeoBBox; -//class TGeoPcon; -//class TGeoCone; -//class TGeoConeSeg; -//class TGeoSphere; -//class TGeoTrd2; -//class TGeoTorus; -//class TGeoTrap; -//class TGeoTube; -//class TGeoTubeSeg; -//class TGeoParaboloid; -//class TGeoCompositeShape; /* * DD4hep namespace declaration @@ -80,12 +67,12 @@ namespace DD4hep { : Handle<T>(p) { } - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object Solid_type(const Handle<T>& e) : Handle<T>(e) { } - /// Constructor to be used when reading the already parsed object: need to check pointers + /// Constructor to be used when passing an already created object: need to check pointers template <typename Q> Solid_type(const Handle<Q>& e) : Handle<T>(e) { } @@ -106,6 +93,10 @@ namespace DD4hep { typedef Solid_type<TGeoShape> Solid; /**@class Box Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoBBox.html + * * * @author M.Frank * @version 1.0 @@ -154,6 +145,11 @@ namespace DD4hep { * radii are changing; * - z coordinate, inner and outer radius for each z plane * + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoPcon.html + * + * * @author M.Frank * @version 1.0 */ @@ -179,6 +175,9 @@ namespace DD4hep { * A ConeSegment is, in the general case, a Phi segment of a cone, with * half-length dz, inner and outer radii specified at -dz and +dz. * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoConeSeg.html + * * @author M.Frank * @version 1.0 */ @@ -197,11 +196,6 @@ namespace DD4hep { double phi2 = 2.0 * M_PI); }; - /**@class Tube Shapes.h - * - * @author M.Frank - * @version 1.0 - */ struct MyConeSeg: public TGeoConeSeg { public: MyConeSeg() @@ -216,6 +210,18 @@ namespace DD4hep { return GetRmax1(); } }; + + /**@class Tube Shapes.h + * + * TGeoTube - cylindrical tube class. It takes 3 parameters : + * inner radius, outer radius and half-length dz. + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoConeSeg.html + * + * @author M.Frank + * @version 1.0 + */ struct Tube: public Solid_type< /*TGeoTubeSeg */MyConeSeg> { protected: void make(const std::string& name, double rmin, double rmax, double z, double startPhi, double deltaPhi); @@ -262,6 +268,10 @@ namespace DD4hep { }; /**@class Cone Shapes.h + * + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoCone.html * * @author M.Frank * @version 1.0 @@ -272,7 +282,7 @@ namespace DD4hep { public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object template <typename Q> Cone(const Handle<Q>& e) : Solid_type<TGeoCone>(e) { } @@ -292,6 +302,9 @@ namespace DD4hep { }; /**@class Trap Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoTrap.html * * @author M.Frank * @version 1.0 @@ -300,7 +313,11 @@ namespace DD4hep { private: void make(double pz, double py, double px, double pLTX); public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + Trap(const Trap& e) + : Solid_type<TGeoTrap>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> Trap(const Handle<Q>& e) : Solid_type<TGeoTrap>(e) { } @@ -322,6 +339,10 @@ namespace DD4hep { }; /**@class Trapezoid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoTrd2.html + * * * @author M.Frank * @version 1.0 @@ -330,12 +351,16 @@ namespace DD4hep { private: void make(double x1, double x2, double y1, double y2, double z); public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + Trapezoid(const Trapezoid& e) + : Solid_type<TGeoTrd2>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> Trapezoid(const Handle<Q>& e) : Solid_type<TGeoTrd2>(e) { } /// Constructor to create a new anonymous object with attribute initialization - Trapezoid(double x1, double x2, double y1, double y2, double z) { make(x1,x2,y1,y2,z); } + Trapezoid(double x1, double x2, double y1, double y2, double z); /// Constructor to create a new anonymous object with attribute initialization template <typename X1,typename X2,typename Y1,typename Y2,typename Z> Trapezoid(X1 x1, X2 x2, Y1 y1, Y2 y2, Z z) @@ -345,6 +370,9 @@ namespace DD4hep { }; /**@class Torus Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoTorus.html * * @author M.Frank * @version 1.0 @@ -353,7 +381,11 @@ namespace DD4hep { private: void make(double r, double rmin, double rmax, double phi, double delta_phi); public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + Torus(const Torus& e) + : Solid_type<TGeoTorus>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> Torus(const Handle<Q>& e) : Solid_type<TGeoTorus>(e) { } @@ -369,12 +401,20 @@ namespace DD4hep { }; /**@class Sphere Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoSphere.html + * * * @author M.Frank * @version 1.0 */ struct Sphere: public Solid_type<TGeoSphere> { - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + Sphere(const Sphere& e) + : Solid_type<TGeoSphere>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> Sphere(const Handle<Q>& e) : Solid_type<TGeoSphere>(e) { } @@ -386,12 +426,20 @@ namespace DD4hep { }; /**@class Paraboloid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoParaboloid.html + * * * @author M.Frank * @version 1.0 */ struct Paraboloid: public Solid_type<TGeoParaboloid> { - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + Paraboloid(const Paraboloid& e) + : Solid_type<TGeoParaboloid>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> Paraboloid(const Handle<Q>& e) : Solid_type<TGeoParaboloid>(e) { } @@ -401,7 +449,10 @@ namespace DD4hep { Paraboloid& setDimensions(double r_low, double r_high, double delta_z); }; - /**@class PolyhedraRegular Shapes.h + /**@class PolyhedraRegular Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoPgon.html * * @author M.Frank * @version 1.0 @@ -412,7 +463,11 @@ namespace DD4hep { void _create(const std::string& name, int nsides, double rmin, double rmax, double zpos, double zneg, double start, double delta); public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + PolyhedraRegular(const PolyhedraRegular& e) + : Solid_type<TGeoPgon>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> PolyhedraRegular(const Handle<Q>& e) : Solid_type<TGeoPgon>(e) { @@ -427,6 +482,9 @@ namespace DD4hep { }; /**@class EightPointSolid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoArb8.html * * @author M.Frank * @version 1.0 @@ -436,7 +494,11 @@ namespace DD4hep { /// Creator method void make(double dz, const double* vtx); public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + EightPointSolid(const EightPointSolid& e) + : Solid_type<TGeoArb8>(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> EightPointSolid(const Handle<Q>& e) : Solid_type<TGeoArb8>(e) { } @@ -445,19 +507,22 @@ namespace DD4hep { }; /**@class BooleanSolid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoCompositeShape.html * * @author M.Frank * @version 1.0 */ struct BooleanSolid: public Solid_type<TGeoCompositeShape> { protected: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object BooleanSolid() : Solid_type<TGeoCompositeShape>() { } public: - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object template <typename Q> BooleanSolid(const Handle<Q>& e) : Solid_type<TGeoCompositeShape>(e) { @@ -465,6 +530,10 @@ namespace DD4hep { }; /**@class SubtractionSolid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoCompositeShape.html + * @see http://root.cern.ch/root/html/TGeoSubtraction.html * * @author M.Frank * @version 1.0 @@ -474,7 +543,11 @@ namespace DD4hep { SubtractionSolid() : BooleanSolid() { } - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + SubtractionSolid(const SubtractionSolid& e) + : BooleanSolid(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> SubtractionSolid(const Handle<Q>& e) : BooleanSolid(e) { } @@ -491,6 +564,10 @@ namespace DD4hep { }; /**@class UnionSolid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoCompositeShape.html + * @see http://root.cern.ch/root/html/TGeoUnion.html * * @author M.Frank * @version 1.0 @@ -500,7 +577,11 @@ namespace DD4hep { UnionSolid() : BooleanSolid() { } - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + UnionSolid(const UnionSolid& e) + : BooleanSolid(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> UnionSolid(const Handle<Q>& e) : BooleanSolid(e) { } @@ -517,6 +598,10 @@ namespace DD4hep { }; /**@class IntersectionSolid Shapes.h + * + * For any further documentation please see the following ROOT documentation: + * @see http://root.cern.ch/root/html/TGeoCompositeShape.html + * @see http://root.cern.ch/root/html/TGeoIntersection.html * * @author M.Frank * @version 1.0 @@ -526,7 +611,11 @@ namespace DD4hep { IntersectionSolid() : BooleanSolid() { } - /// Constructor to be used when reading the already parsed object + /// Constructor to be used when passing an already created object + IntersectionSolid(const IntersectionSolid& e) + : BooleanSolid(e) { + } + /// Constructor to be used when passing an already created object template <typename Q> IntersectionSolid(const Handle<Q>& e) : BooleanSolid(e) { } diff --git a/DDCore/include/DD4hep/ToStream.h b/DDCore/include/DD4hep/ToStream.h new file mode 100644 index 000000000..4e59d803e --- /dev/null +++ b/DDCore/include/DD4hep/ToStream.h @@ -0,0 +1,302 @@ +// $Id: ToStream.h,v 1.8 2008/10/30 23:38:46 marcocle Exp $ +// ============================================================================ +// CVS tag $Name: $, version $Revision: 1.8 $ +// ============================================================================ +#ifndef DD4HEPPROPERTYPARSERS_PARSERVALUETOSTREAM_H +#define DD4HEPPROPERTYPARSERS_PARSERVALUETOSTREAM_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <iostream> +#include <iomanip> +#include <vector> +#include <map> +#include <set> +#include <list> +#include <string> +#include <sstream> +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +// ============================================================================ +/** @file DD4hepKernel/ToStream.h + * implemenattiono fvarioud functions for streaming. + * this functionality is essenital for usag eof varuodu types as property for + * the various DD4hep components + * @attention the implemenation of the specific specializations must be done + * before the inclusion of this file + * @todo ToStream.h : reimplement in terms of functors, to allow + * easier especializations + */ +// ============================================================================ +namespace DD4hep { + // ========================================================================== + namespace Utils { + // ======================================================================== + /** the generic implementation of the printout to the std::ostream + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class TYPE> + std::ostream& toStream(const TYPE& obj, std::ostream& s); + // ======================================================================== + /** the helper function to print the sequence + * @param first (INPUT) begin-iterator for the sequence + * @param last (INPUT) end-iterator for the sequence + * @param s (UPDATE) the stream itself + * @param open (INPUT) "open"-symbol + * @param close (INPUT) "close"-symbol + * @param delim (INPUT) "delimiter"-symbol + * @return the stream + * @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class ITERATOR> + inline std::ostream& toStream(ITERATOR first, // begin of the sequence + ITERATOR last, // end of the sequence + std::ostream& s, // the stream + const std::string& open, // opening + const std::string& close, // closing + const std::string& delim); // delimiter + // ======================================================================== + /** the printtout of the strings. + * the string is printed a'la Python using the quotes + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + inline std::ostream& toStream(const std::string& obj, std::ostream& s) { + if (std::string::npos == obj.find('\'')) { + s << "\'" << obj << "\'"; + } + else { + s << "\"" << obj << "\""; + } + return s; + } + /** the printout of boolean values "a'la Python" + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream(const bool obj, std::ostream& s) { + return s << (obj ? "True" : "False"); + } + /** the printout of float values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream(const float obj, std::ostream& s, const int prec = 6) { + const int p = s.precision(); + return s << std::setprecision(prec) << obj << std::setprecision(p); + } + /** the printout of double values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream(const double obj, std::ostream& s, const int prec = 8) { + const int p = s.precision(); + return s << std::setprecision(prec) << obj << std::setprecision(p); + } + /** the printout of long double values with the reasonable precision + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-09-09 + */ + inline std::ostream& toStream(const long double obj, std::ostream& s, const int prec = 10) { + const int p = s.precision(); + return s << std::setprecision(prec) << obj << std::setprecision(p); + } + // ======================================================================== + /** the partial template specialization of + * <c>std::pair<KTYPE,VTYPE></c> printout + * the pair is printed a'la Python tuple: " ( a , b )" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class KTYPE, class VTYPE> + inline std::ostream& toStream(const std::pair<KTYPE, VTYPE>& obj, std::ostream& s) { + s << "( "; + toStream(obj.first, s); + s << " , "; + toStream(obj.second, s); + return s << " )"; + } + // ======================================================================== + /** the partial template specialization of <c>std::vector<TYPE,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class TYPE, class ALLOCATOR> + inline std::ostream& toStream(const std::vector<TYPE, ALLOCATOR>& obj, std::ostream& s) { + return toStream(obj.begin(), obj.end(), s, "[ ", " ]", " , "); + } + // ======================================================================== + /** the partial template specialization of <c>std::list<TYPE,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2007-04-08 + */ + template <class TYPE, class ALLOCATOR> + inline std::ostream& toStream(const std::list<TYPE, ALLOCATOR>& obj, std::ostream& s) { + return toStream(obj.begin(), obj.end(), s, "[ ", " ]", " , "); + } + // ======================================================================== + /** the partial template specialization of <c>std::set<TYPE,CMP,ALLOCATOR></c> + * printout. The vector is printed a'la Python list: "[ a, b, c ]" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class TYPE, class CMP, class ALLOCATOR> + inline std::ostream& toStream(const std::set<TYPE, CMP, ALLOCATOR>& obj, std::ostream& s) { + return toStream(obj.begin(), obj.end(), s, "[ ", " ]", " , "); + } + // ======================================================================== + /** the partial template specialization of + * <c>std::map<KTYPE,VTYPE,CMP,ALLOCATOR></c> printout + * the map is printed a'la Python dict: " ( a : b , c: d , e : f )" + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class KTYPE, class VTYPE, class CMP, class ALLOCATOR> + inline std::ostream& toStream(const std::map<KTYPE, VTYPE, CMP, ALLOCATOR>& obj, std::ostream& s) { + s << "{ "; + for (typename std::map<KTYPE, VTYPE, CMP, ALLOCATOR>::const_iterator cur = obj.begin(); obj.end() != cur; ++cur) { + if (obj.begin() != cur) { + s << " , "; + } + toStream(cur->first, s); + s << " : "; + toStream(cur->second, s); + } + return s << " }"; + } + + // ======================================================================== + /** the specialization for C-arrays, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <class TYPE, unsigned int N> + std::ostream& toStream(TYPE (&obj)[N], std::ostream& s) { + return toStream(obj, obj + N, s, "( ", " )", " , "); + } + // ======================================================================== + /** the specialization for C-arrays, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <class TYPE, unsigned int N> + std::ostream& toStream(const TYPE (&obj)[N], std::ostream& s) { + return toStream(obj, obj + N, s, "( ", " )", " , "); + } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <unsigned int N> + std::ostream& toStream(char (&obj)[N], std::ostream& s) { + return toStream(std::string(obj, obj + N), s); + } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + template <unsigned int N> + std::ostream& toStream(const char (&obj)[N], std::ostream& s) { + return toStream(std::string(obj, obj + N), s); + } + // ======================================================================== + /** the specialization for C-string, a'la python tuple + * @author Vanya BELYAEV Ivan.Belyaev@nikhenf.nl + * @date 2009-10-05 + */ + inline std::ostream& toStream(const char* obj, std::ostream& s) { + return toStream(std::string(obj), s); + } + // ======================================================================== + /** the generic implementation of the printout to the std::ostream + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template <class TYPE> + inline std::ostream& toStream(const TYPE& obj, std::ostream& s) { + return s << obj; + } + // ======================================================================== + /** the helper function to print the sequence + * @param first (INPUT) begin-iterator for the sequence + * @param last (INPUT) end-iterator for the sequence + * @param s (UPDATE) the stream itself + * @param open (INPUT) "open"-symbol + * @param close (INPUT) "close"-symbol + * @param delim (INPUT) "delimiter"-symbol + * @return the stream + * @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl + * @date 2009-09-15 + */ + template <class ITERATOR> + inline std::ostream& toStream(ITERATOR first, // begin of the sequence + ITERATOR last, // end of the sequence + std::ostream& s, // the stream + const std::string& open, // opening + const std::string& close, // closing + const std::string& delim) // delimiter + { + s << open; + for (ITERATOR curr = first; curr != last; ++curr) { + if (first != curr) { + s << delim; + } + toStream(*curr, s); + } + s << close; + // + return s; + } + // ======================================================================== + /** the generic implementation of the type conversion to the string + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + * @see DD4hep::Utils::toStream + * @todo need to be compared with boost::lexical_cast + */ + template <class TYPE> + inline std::string toString(const TYPE& obj) { + std::ostringstream s; + std::ios::fmtflags orig_flags = s.flags(); + s.setf(std::ios::showpoint); // to display correctly floats + toStream(obj, s); + s.flags(orig_flags); + return s.str(); + } + // ============================================================================ + /// print XYZ point + std::ostream& toStream(const ROOT::Math::XYZPoint& obj, std::ostream& s); + // print XYZ-vector + std::ostream& toStream(const ROOT::Math::XYZVector& obj, std::ostream& s); + /// print Lorentz vector + std::ostream& toStream(const ROOT::Math::PxPyPzEVector& obj, std::ostream& s); + + // ======================================================================== + }// end of namespace DD4hep::Utils +// ========================================================================== +}// end of namespace DD4hep +// ============================================================================ +// The END +// ============================================================================ +#endif +// ============================================================================ + diff --git a/DDCore/include/DD4hep/VolumeManager.h b/DDCore/include/DD4hep/VolumeManager.h index 4efa16e52..18a9eae3a 100644 --- a/DDCore/include/DD4hep/VolumeManager.h +++ b/DDCore/include/DD4hep/VolumeManager.h @@ -62,55 +62,16 @@ namespace DD4hep { struct VolumeManager: public Ref_t { public: typedef DD4hep::VolumeID VolumeID; + typedef VolumeID VolIdentifier; // Creation flags enum PopulateFlags { - NONE = 0, TREE = 1 << 1, // Build 1 level DetElement hierarchy while populating - ONE = 1 << 2, // Populate all daughter volumes into one big lookup-container + NONE = 0, + TREE = 1 << 1, // Build 1 level DetElement hierarchy while populating + ONE = 1 << 2, // Populate all daughter volumes into one big lookup-container // This flag may be in parallel with 'TREE' LAST }; -#if 0 - /** @class VolumeManager::VolIdentifier VolumeManager.h DD4hep/lcdd/VolumeManager.h - * - * @author M.Frank - * @version 1.0 - */ - struct VolIdentifier { - public: - /// The volume identifier and it's mask - VolumeID identifier, mask; - private: - /// Equality operator is provate. Not to be used! - bool operator==(const VolIdentifier& c) const { - return identifier == c.identifier && mask == c.mask; - } - public: - /// Default constructor - VolIdentifier() : identifier(0), mask(~0x0ull) { - } - /// Initializing constructor - VolIdentifier(VolumeID id, VolumeID msk) : identifier(id), mask(msk) { - } - /// Copt constructor - VolIdentifier(const VolIdentifier& c) : identifier(c.identifier), mask(c.mask) { - } - /** Operator less for map storage. - * Note, that this takes advantag, the only volumes with the same descriptor length are - * stored in one map, because some bits are masked out. Otherwise all breaks! - */ - bool operator< (const VolIdentifier& c) const { - return identifier < (c.identifier&mask); - } - /// Assignment operator - VolIdentifier& operator=(const VolIdentifier& c) { - identifier=c.identifier; mask=c.mask; - return *this; - } - }; -#endif - typedef VolumeID VolIdentifier; - /** @class VolumeManager::Context VolumeManager.h DD4hep/lcdd/VolumeManager.h * * This structure describes the cached data for one placement @@ -145,13 +106,14 @@ namespace DD4hep { /// Default constructor Context(); /// Default destructor - ~Context(); + virtual ~Context(); }; /// Some useful Container abbreviations used by the VolumeManager typedef std::map<VolumeID, VolumeManager> Managers; typedef std::map<DetElement, VolumeManager> Detectors; typedef std::map<TGeoNode*, Context*> PhysVolumes; - typedef std::map<VolIdentifier, Context*> Volumes; + typedef std::map<VolumeID, Context*> Volumes; + typedef PlacedVolume::VolIDs VolIDs; /** @class VolumeManager::Object VolumeManager.h DD4hep/lcdd/VolumeManager.h * @@ -176,8 +138,6 @@ namespace DD4hep { Managers managers; /// The container of placements managed by this instance Volumes volumes; - /// Map of placed volumes and their corresponding context - PhysVolumes phys_volumes; /// The Detector element handle managed by this instance DetElement detector; /// The ID descriptor object @@ -198,9 +158,9 @@ namespace DD4hep { /// Default destructor virtual ~Object(); /// Search the locally cached volumes for a matching ID - Context* search(const VolIdentifier& id) const; - /// Search the locally cached volumes for a matching physical volume - Context* search(const PlacedVolume pv) const; + Context* search(const VolumeID& id) const; + /// Update callback when alignment has changed (called only for subdetectors....) + void update(unsigned int tags, DetElement& det, void* param); }; protected: diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index 65bfb23a4..620bec315 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -38,7 +38,6 @@ class TGeoExtension : public TObject { /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore virtual void Release() const = 0; }; - #endif /* @@ -86,8 +85,6 @@ namespace DD4hep { long refCount; /// ID container VolIDs volIDs; - /// Detector element with the placement - Ref_t detector; /// Default constructor Object(); /// Copy constructor @@ -138,10 +135,6 @@ namespace DD4hep { Volume motherVol() const; /// Access to the volume IDs const VolIDs& volIDs() const; - /// Set the detector element if appropriate (requires degenerate geometry subtree) - void setDetector(const DetElement& e) const; - /// Access the corresponding detector element of this placement (if set) - //const DetElement detector() const; /// String dump std::string toString() const; }; diff --git a/DDCore/include/DD4hep/objects/BasicGrammar_inl.h b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h new file mode 100644 index 000000000..014ce2bcd --- /dev/null +++ b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h @@ -0,0 +1,266 @@ +// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDG4_GRAMMAR_INL_H +#define DD4HEP_DDG4_GRAMMAR_INL_H + +// Framework include files +#include "DD4hep/BasicGrammar.h" + +#ifdef DD4HEP_USE_BOOST +#include "DD4hep/Parsers.h" +#include "DD4hep/ToStream.h" +#endif +#include "XML/Evaluator.h" +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +// C/C++ include files +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> + +namespace DD4hep { XmlTools::Evaluator& g4Evaluator(); } +namespace { static XmlTools::Evaluator& s__eval(DD4hep::g4Evaluator()); } + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /** @class PropertyGrammarCollection + * + * @author M.Frank + * @date 13.08.2013 + */ + template <typename TYPE> struct Grammar : public BasicGrammar { + /// Standarsd constructor + Grammar(); + /// Default destructor + virtual ~Grammar(); + /// PropertyGrammar overload: Access to the type information + virtual const std::type_info& type() const; + /// Access the object size (sizeof operator) + virtual size_t sizeOf() const; + /// PropertyGrammar overload: Serialize a property to a string + virtual std::string str(const void* ptr) const; + /// PropertyGrammar overload: Retrieve value from string + virtual bool fromString(void* ptr, const std::string& value) const; + /// Evaluate string value if possible before calling boost::spirit + virtual int evaluate(void* ptr, const std::string& value) const; + }; + + /// Standarsd constructor + template <typename TYPE> Grammar<TYPE>::Grammar() { + } + + /// Default destructor + template <typename TYPE> Grammar<TYPE>::~Grammar() { + } + + /// PropertyGrammar overload: Access to the type information + template <typename TYPE> const std::type_info& Grammar<TYPE>::type() const { + return typeid(TYPE); + } + + /// Access the object size (sizeof operator) + template <typename TYPE> size_t Grammar<TYPE>::sizeOf() const { + return sizeof(TYPE); + } + + /// Evaluate string value if possible before calling boost::spirit + template <typename TYPE> int Grammar<TYPE>::evaluate(void*, const std::string&) const { + return 0; + } + + /// PropertyGrammar overload: Retrieve value from string + template <typename TYPE> bool Grammar<TYPE>::fromString(void* ptr, const std::string& str) const { + int sc = 0; + TYPE temp; +#ifdef DD4HEP_USE_BOOST + sc = Parsers::parse(temp,str); +#endif + if ( !sc ) sc = evaluate(&temp,str); +#if 0 + std::cout << "Sc=" << sc << " Converting value: " << str + << " to type " << typeid(TYPE).name() + << std::endl; +#endif + if ( sc ) { + *(TYPE*)ptr = temp; + return true; + } +#ifndef DD4HEP_USE_BOOST + throw std::runtime_error("This version of DD4HEP is not compiled to use boost::spirit.\n" + "To enable elaborated property handling set DD4HEP_USE_BOOST=ON\n" + "and BOOST_INCLUDE_DIR=<boost include path>"); +#else + BasicGrammar::invalidConversion(str, typeid(TYPE)); + return false; +#endif + } + + /// Serialize a property to a string + template <typename TYPE> std::string Grammar<TYPE>::str(const void* ptr) const { +#ifdef DD4HEP_USE_BOOST + std::stringstream string_rep; + Utils::toStream(*(TYPE*)ptr,string_rep); + return string_rep.str(); +#else + if (ptr) { + } + throw std::runtime_error("This version of DD4HEP is not compiled to use boost::spirit.\n" + "To enable elaborated property handling set DD4HEP_USE_BOOST=ON\n" + "and BOOST_INCLUDE_DIR=<boost include path>"); +#endif + } + + static std::string pre_parse_obj(const std::string& in) { + std::string res = ""; + res.reserve(1024); + for(const char* c = in.c_str(); *c; ++c) { + switch(*c) { + case '\'': + return "Bad object representation"; + case ',': + res += "','"; + break; + case '(': + case '[': + res += "['"; + break; + case ')': + case ']': + res += "']"; + break; + default: + res += *c; + break; + } + } + //cout << "Pre-parsed:" << res << endl; + return res; + } + + /// Insertion function for std vectors + template <typename TYPE> static int fill_data(std::vector<TYPE>* p,const std::vector<std::string>& temp) { + const BasicGrammar& g = BasicGrammar::instance<TYPE>(); + TYPE val; + for(std::vector<std::string>::const_iterator i=temp.begin(); i != temp.end(); ++i) { + if ( !g.fromString(&val,*i) ) + return 0; + p->push_back(val); + } + return 1; + } + + /// Insertion function for std lists + template <typename TYPE> static int fill_data(std::list<TYPE>* p,const std::vector<std::string>& temp) { + const BasicGrammar& g = BasicGrammar::instance<TYPE>(); + TYPE val; + for(std::vector<std::string>::const_iterator i=temp.begin(); i != temp.end(); ++i) { + if ( !g.fromString(&val,*i) ) + return 0; + p->push_back(val); + } + return 1; + } + + /// Insertion function for std sets + template <typename TYPE> static int fill_data(std::set<TYPE>* p,const std::vector<std::string>& temp) { + const BasicGrammar& g = BasicGrammar::instance<TYPE>(); + TYPE val; + for(std::vector<std::string>::const_iterator i=temp.begin(); i != temp.end(); ++i) { + if ( !g.fromString(&val,*i) ) + return 0; + p->insert(val); + } + return 1; + } + + /// Container evaluator + template <typename TYPE> static int eval_container(TYPE* p, const std::string& str) { +#ifdef DD4HEP_USE_BOOST + std::vector<std::string> buff; + int sc = Parsers::parse(buff,str); + if ( sc ) { + return fill_data(p,buff); + } + else { + TYPE temp; + std::string temp_str = pre_parse_obj(str); + sc = Parsers::parse(temp,temp_str); + if ( sc ) { + *p = temp; + return 1; + } + buff.clear(); + sc = Parsers::parse(buff,temp_str); + if ( sc ) { + return fill_data(p,buff); + } + } +#else + if ( p && str.empty() ) return 0; +#endif + return 0; + } + + /// Item evaluator + template <typename T> static int eval_item(T* p, std::string s) { + size_t idx = s.find("(int)"); + if (idx != std::string::npos) + s.erase(idx, 5); + while (s[0] == ' ') + s.erase(0, 1); + double result = s__eval.evaluate(s.c_str()); + if (s__eval.status() != XmlTools::Evaluator::OK) { + return 0; + } + *p = (T)result; + return 1; + } + + /// Object evaluator + template<typename T> static int eval_obj(T* p, const std::string& str) { + return BasicGrammar::instance<T>().fromString(p,pre_parse_obj(str)); + } + + // Containers of objects are not handled! + +} // End namespace DD4hep + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) namespace DD4hep { \ + template<> const BasicGrammar& BasicGrammar::instance<x>() { static Grammar<x> s; return s;}} + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) namespace DD4hep { \ + template<> int Grammar<x >::evaluate(void* p, const std::string& v) const { return func ((x*)p,v); }} + +#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(std::vector<x>,eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(std::list<x>,eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(std::set<x>,eval_container) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_VL(x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(std::vector<x>,eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR(std::list<x>,eval_container) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(x) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(x,eval_item) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(unsigned x,eval_item) + +#endif /* DD4HEP_DDG4_GRAMMAR_INL_H */ diff --git a/DDCore/include/DD4hep/objects/ConditionsInterna.h b/DDCore/include/DD4hep/objects/ConditionsInterna.h new file mode 100644 index 000000000..e37d92741 --- /dev/null +++ b/DDCore/include/DD4hep/objects/ConditionsInterna.h @@ -0,0 +1,251 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_CONDITIONINTERNA_H +#define DD4HEP_GEOMETRY_CONDITIONINTERNA_H + +// Framework include files +#include "DD4hep/Detector.h" +#include "DD4hep/BasicGrammar.h" +#include "DD4hep/objects/NamedObject.h" +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + // Forward declarations + class DetElement; + class Condition; + + /* + * Conditions internal namespace declaration + * Internally defined datastructures are not presented to the + * user directly, but are used by dedicated views. + * + */ + namespace ConditionsInterna { + + class Object; + class Entry; + class IOV; + + /** @class IOV ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * Class describing the interval of validty + * + * + * @author M.Frank + * @version 1.0 + */ + class IOV { + friend class Condition; + public: + enum { + UNKNOWN_IOV = 1<<0 + } _IOVTypes; + /// IOV buffer type: Must be a bitmap! + int type; + unsigned char data[16]; + /// Initializing constructor + IOV(int t=UNKNOWN_IOV); + /// Standard Destructor + ~IOV(); + /// Move the data content: 'from' will be reset to NULL + void move(IOV& from); + /// Create IOV data from string representation + void fromString(const std::string& rep); + /// Create string representation of the IOV + std::string str(); + }; + + /** @class Block ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * Class describing an opaque conditions data block + * + * @author M.Frank + * @version 1.0 + */ + class BlockData : public Block { + friend class ::DD4hep::Geometry::Condition; + friend class Object; + + private: + enum { + PLAIN_DATA = 1<<0, + ALLOC_DATA = 1<<1, + BOUND_DATA = 1<<2 + } _DataTypes; + /// Data buffer: plain data are allocated directly on this buffer + unsigned int data[16]; + /// Destructor function -- only set if the object is valid + void (*destruct)(void*); + /// Constructor function -- only set if the object is valid + void (*copy)(void*,const void*); + /// Data buffer type: Must be a bitmap! + int type; + + public: + + /// Standard initializing constructor + BlockData(); + /// Standard Destructor + ~BlockData(); + /// Move the data content: 'from' will be reset to NULL + void move(BlockData& from); + /// Set data value + void bind(const BasicGrammar* grammar, + void (*ctor)(void*,const void*), + void (*dtor)(void*)); + /// Set data value + void assign(const void* ptr,const std::type_info& typ); + }; + + /** @class Entry ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * The intermediate conditions data + * + * @author M.Frank + * @version 1.0 + */ + class Entry : public NamedObject { + public: + /// Reference to the detector element + DetElement detector; + /// Conditions type (was the tag in the XML) + std::string type; + /// The actual conditions data + std::string value; + /// The validity string to be interpreted by the updating engine + std::string validity; + /// Default constructor + Entry() {} + /// Initializing constructor + Entry(const DetElement& det, const std::string& nam, const std::string& typ, const std::string& valid); + /// Copy constructor + Entry(const Entry& c); + /// Default destructor + virtual ~Entry(); + /// Assignment operator + Entry& operator=(const Entry& c); + }; + + /** @class Object ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * The data class behind a conditions handle. + * + * @author M.Frank + * @version 1.0 + */ + class Object : public NamedObject { + public: + /// Condition value (in string form) + std::string value; + /// Condition validity (in string form) + std::string validity; + /// Condition address + std::string address; + /// Comment string + std::string comment; + /// The detector element + DetElement detector; + /// Data block + BlockData data; + /// Interval of validity + IOV iov; + /// Standard constructor + Object(); + /// Standard Destructor + virtual ~Object(); + /// Move data content: 'from' will be reset to NULL + Object& move(Object& from); + }; + + /** @class Container ConditionsInterna.h DD4hep/ConditionsInterna.h + * + * The data class behind a conditions container handle. + * + * @author M.Frank + * @version 1.0 + */ + class Container : public NamedObject { + public: + /// Container definition + typedef std::map<std::string, Condition> Entries; + + Entries entries; + /// Standard constructor + Container(); + /// Default destructor + virtual ~Container(); + /// Clear all conditions. Auto-delete of all existing entries + void removeElements(); + }; + + } /* End namespace ConditionsInterna */ + + template <typename T> static void copyObject(void* t, const void* s) { + *((T*)t) = *((const T*)s); + } + template <typename T> static void destructObject(void* p) { + T* t = (T*)p; + t->~T(); + } + /// Generic getter. Specify the exact type, not a polymorph type + template <typename T> T& Block::get() { + if (!grammar || (grammar->type() != typeid(T))) { throw std::bad_cast(); } + return *(T*)pointer; + } + /// Generic getter (const version). Specify the exact type, not a polymorph type + template <typename T> const T& Block::get() const { + if (!grammar || (grammar->type() != typeid(T))) { throw std::bad_cast(); } + return *(T*)pointer; + } + /// Bind the data of the conditions object to a given format. + template <typename T> Condition& Condition::bind() { + Object* o = access(); + ConditionsInterna::BlockData& b = o->data; + b.bind(&BasicGrammar::instance<T>(),copyObject<T>,destructObject<T>); + new(b.pointer) T(); + if ( !o->value.empty() ) b.fromString(o->value); + return *this; + } + /// Generic getter. Specify the exact type, not a polymorph type + template <typename T> T& Condition::get() { + return access()->data.get<T>(); + } + /// Generic getter (const version). Specify the exact type, not a polymorph type + template <typename T> const T& Condition::get() const { + return access()->data.get<T>(); + } + } /* End namespace Geometry */ +} /* End namespace DD4hep */ + +#define DD4HEP_DEFINE_CONDITIONS_TYPE(x) \ + namespace DD4hep { namespace Geometry { \ + template Condition& Condition::bind<x>(); \ + template x& Condition::get<x>(); \ + template const x& Condition::get<x>() const; \ + }} + +#define DD4HEP_DEFINE_CONDITIONS_CONT(x) \ + DD4HEP_DEFINE_CONDITIONS_TYPE(x) \ + DD4HEP_DEFINE_CONDITIONS_TYPE(std::vector<x>) \ + DD4HEP_DEFINE_CONDITIONS_TYPE(std::list<x>) \ + DD4HEP_DEFINE_CONDITIONS_TYPE(std::set<x>) + +#define DD4HEP_DEFINE_CONDITIONS_U_CONT(x) \ + DD4HEP_DEFINE_CONDITIONS_CONT(x) \ + DD4HEP_DEFINE_CONDITIONS_CONT(unsigned x) + + +#endif /* DD4HEP_GEOMETRY_CONDITIONINTERNA_H */ diff --git a/DDCore/include/DD4hep/objects/DetectorInterna.h b/DDCore/include/DD4hep/objects/DetectorInterna.h new file mode 100644 index 000000000..e0628406d --- /dev/null +++ b/DDCore/include/DD4hep/objects/DetectorInterna.h @@ -0,0 +1,152 @@ +// $Id: Detector.h 1087 2014-04-09 12:25:51Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_DETECTORINTERNA_H +#define DD4HEP_GEOMETRY_DETECTORINTERNA_H + +// Framework include files +#include "DD4hep/Callback.h" +#include "DD4hep/Objects.h" +#include "DD4hep/Detector.h" +#include "DD4hep/Alignment.h" +#include "DD4hep/Conditions.h" +#include "DD4hep/Segmentations.h" +#include "DD4hep/ObjectExtensions.h" +#include "TGeoMatrix.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + class LCDD; + class DetElementObject; + class SensitiveDetectorObject; + + /** @class SensitiveDetectorObject DetectorInterna.h DD4hep/objects/DetectorInterna.h + * + * @author M.Frank + * @version 1.0 + */ + class SensitiveDetectorObject: public TNamed, public ObjectExtensions { + public: + unsigned int magic; + int verbose; + int combineHits; + double ecut; + Readout readout; + Region region; + LimitSet limits; + std::string hitsCollection; + + /// Default constructor + SensitiveDetectorObject(); + /// Internal object destructor: release extension object(s) + virtual ~SensitiveDetectorObject(); + }; + + /** @class DetElementObject DetectorInterna.h DD4hep/objects/DetectorInterna.h + * + * @author M.Frank + * @version 1.0 + */ + class DetElementObject: public TNamed, public ObjectExtensions { + public: + typedef DetElement::destruct_t destruct_t; + typedef DetElement::copy_t copy_t; + + typedef DetElement::Children Children; + typedef DetElement::Extensions Extensions; + typedef std::pair<Callback,unsigned long> UpdateCall; + typedef std::vector<UpdateCall> UpdateCallbacks; + + enum DetFlags { + HAVE_WORLD_TRAFO = 1<<0, + HAVE_PARENT_TRAFO = 1<<1, + HAVE_REFERENCE_TRAFO = 1<<2, + HAVE_OTHER = 1<<31 + }; + + /// Magic number to ensure data integrity + unsigned int magic; + /// Flag to remember internally calculated quatities + unsigned int flag; + /// Unique integer identifier of the detector instance + int id; + /// Flag to process hits + int combineHits; + /// Full path to this detector element. May be invalid + std::string path; + /// The path to the placement of the detector element (if placed) + std::string placementPath; + + /// The subdetector placement corresponding to the ideal detector element's volume + PlacedVolume idealPlace; + /// The subdetector placement corresponding to the actual detector element's volume + PlacedVolume placement; + /** The cached VolumeID of this subdetector element + * Please note: + * These values are set when populating the volume manager. + * There are restrictions: e.g. only sensitive subdetectors are present. + */ + VolumeID volumeID; + /// Reference to the parent element + DetElement parent; + /// Reference element for stored transformations + DetElement reference; + /// The array of children + Children children; + /// Placeholder for structure with update callbacks + UpdateCallbacks updateCalls; + + /**@info: Additional information set externally to facilitate the processing of event data */ + /// Basic detector element alignment entry + Alignment alignment; + /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements + std::vector<Alignment> volume_alignments; + /// The detector elements condition entry + Conditions conditions; + + /**@info: Cached information of the detector element */ + /// Intermediate buffer to store the transformation to the world coordination system + TGeoHMatrix worldTrafo; + /// Intermediate buffer to store the transformation to the parent detector element + TGeoHMatrix parentTrafo; + /// Intermediate buffer for the transformation to an arbitrary DetElement + TGeoHMatrix* referenceTrafo; + + /**@info: Public methods to ease the usage of the data. */ + /// Default constructor + DetElementObject(); + /// Internal object destructor: release extension object(s) + virtual ~DetElementObject(); + /// Deep object copy to replicate DetElement trees e.g. for reflection + virtual DetElementObject* clone(int new_id, int flag) const; + + /// Create cached matrix to transform to world coordinates + const TGeoHMatrix& worldTransformation(); + /// Create cached matrix to transform to parent coordinates + const TGeoHMatrix& parentTransformation(); + /// Create cached matrix to transform to reference coordinates + const TGeoHMatrix& referenceTransformation(); + /// Remove callback from object + void removeAtUpdate(unsigned int type, void* pointer); + /// Trigger update callbacks + void update(unsigned int tags, void* param); + /// Revalidate the caches + void revalidate(TGeoHMatrix* parent_world_trafo); + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_DETECTORINTERNA_H */ diff --git a/DDCore/include/DD4hep/objects/NamedObject.h b/DDCore/include/DD4hep/objects/NamedObject.h new file mode 100644 index 000000000..a6be3f36a --- /dev/null +++ b/DDCore/include/DD4hep/objects/NamedObject.h @@ -0,0 +1,71 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_INTERNAL_NAMEDOBJECT_H +#define DD4HEP_GEOMETRY_INTERNAL_NAMEDOBJECT_H + +// C/C++ include files +#include <string> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + /** @class Container NamedObject.h DD4hep/NamedObject.h + * + * The data class behind a conditions container handle. + * + * @author M.Frank + * @version 1.0 + */ + class NamedObject { + public: + /// The object name + std::string name; + /// The object type + std::string type; + + /// Standard constructor + NamedObject(); + /// Initializing constructor + NamedObject(const char* nam, const char* typ=""); + /// Initializing constructor + NamedObject(const std::string& nam); + /// Initializing constructor + NamedObject(const std::string& nam, const std::string& typ); + /// Copy constructor + NamedObject(const NamedObject& c); + /// Default destructor + virtual ~NamedObject(); + /// Assignment operator + NamedObject& operator=(const NamedObject& c); + /// Set name (used by Handle) + void SetName(const char* nam) { + name = nam; + } +#if 0 + /// Get name (used by Handle) + const char* GetName() const { + return name.c_str(); + } +#endif + /// Set Title (used by Handle) + void SetTitle(const char* tit) { + type = tit; + } + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_INTERNAL_NAMEDOBJECT_H */ diff --git a/DDCore/include/XML/XMLDimension.h b/DDCore/include/XML/XMLDimension.h index 2bd29d423..1c7f6c9b4 100644 --- a/DDCore/include/XML/XMLDimension.h +++ b/DDCore/include/XML/XMLDimension.h @@ -336,15 +336,17 @@ namespace DD4hep { /// Child access: beampipe Dimension beampipe(bool throw_if_not_present = true) const; - /// Access name attribute as STL string + /// Access "name" attribute as STL string std::string nameStr() const; - /// Access ref attribute as a string + /// Access "ref" attribute as a string std::string refStr() const; - /// Access type attribute as STL string + /// Access "type" attribute as STL string std::string typeStr() const; - /// Access module attribute as STL string + /// Access "value" attribute as STL string + std::string valueStr() const; + /// Access "module" attribute as STL string std::string moduleStr() const; - /// Access readout attribute as STL string + /// Access "readout" attribute as STL string std::string readoutStr() const; /// Access vis attribute as STL string. If not present empty return empty string std::string visStr() const; diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h index 2e1fc8a1d..03b770d56 100644 --- a/DDCore/include/XML/XMLElements.h +++ b/DDCore/include/XML/XMLElements.h @@ -83,44 +83,6 @@ namespace DD4hep { }; #endif - /** NodeList XMLElements.h XML/XMLElements.h - * - * Definition of a "list" of xml elements hanging of the parent. - * The list allows iterations, which can be restarted. - * Please not: Copies are not entirely free, since the - * string tag need to be replicated using strdup/free - * (or when using xerces the corresponding unicode routines). - * - * @author M.Frank - * @version 1.0 - */ - struct NodeList { - XmlChar* m_tag; - XmlElement* m_node; -#ifndef __TIXML__ - //XmlNodeList* m_ptr; - //mutable XmlSize_t m_index; - mutable XmlElement* m_ptr; -#else - mutable XmlElement* m_ptr; -#endif - - /// Copy constructor - NodeList(const NodeList& l); - /// Initializing constructor - NodeList(XmlElement* frst, const XmlChar* t); - /// Default destructor - ~NodeList(); - /// Reset the nodelist - e.g. restart iteration from beginning - XmlElement* reset(); - /// Advance to next element - XmlElement* next() const; - /// Go back to previous element - XmlElement* previous() const; - /// Assignment operator - NodeList& operator=(const NodeList& l); - }; - typedef const std::string& CSTR; /// Dump DOM tree of a document @@ -249,17 +211,16 @@ namespace DD4hep { struct Tag_t : public Strng_t { /// STL string buffer std::string m_str; - +#ifndef __TIXML__ /// Constructor from normal ASCII string Tag_t(const char* s) : Strng_t(s), m_str(s) { } -#ifndef __TIXML__ +#endif /// Constructor from unicode string Tag_t(const XmlChar* s) : Strng_t(s), m_str(_toString(s)) { } -#endif /// Constructor from internal XML string Tag_t(const Strng_t& s) : Strng_t(s), m_str(_toString(s)) { @@ -310,6 +271,38 @@ namespace DD4hep { return c == b.m_str; } + /** NodeList XMLElements.h XML/XMLElements.h + * + * Definition of a "list" of xml elements hanging of the parent. + * The list allows iterations, which can be restarted. + * Please not: Copies are not entirely free, since the + * string tag need to be replicated using strdup/free + * (or when using xerces the corresponding unicode routines). + * + * @author M.Frank + * @version 1.0 + */ + struct NodeList { + Tag_t m_tag; + XmlElement* m_node; + mutable XmlElement* m_ptr; + + /// Copy constructor + NodeList(const NodeList& l); + /// Initializing constructor + NodeList(XmlElement* frst, const XmlChar* t); + /// Default destructor + ~NodeList(); + /// Reset the nodelist - e.g. restart iteration from beginning + XmlElement* reset(); + /// Advance to next element + XmlElement* next() const; + /// Go back to previous element + XmlElement* previous() const; + /// Assignment operator + NodeList& operator=(const NodeList& l); + }; + /** @class Handle_t XMLElements.h XML/XMLElements.h * * Helper class to easily access the properties of single XmlElements. diff --git a/DDCore/src/BasicGrammar.cpp b/DDCore/src/BasicGrammar.cpp new file mode 100644 index 000000000..2e481dd7b --- /dev/null +++ b/DDCore/src/BasicGrammar.cpp @@ -0,0 +1,42 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Handle.h" +#include "DD4hep/Exceptions.h" +#include "DD4hep/BasicGrammar.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep; + +/// Default constructor +BasicGrammar::BasicGrammar() { +} + +/// Default destructor +BasicGrammar::~BasicGrammar() { +} + +/// Error callback on invalid conversion +void BasicGrammar::invalidConversion(const string& value, const type_info& to) { + string to_name = typeName(to); + throw unrelated_value_error(to, + "The Property data conversion of '" + value + "' to type " + to_name + " is not defined."); +} + +/// Error callback on invalid conversion +void BasicGrammar::invalidConversion(const type_info& from, const type_info& to) { + string to_name = typeName(to); + string from_name = typeName(from); + throw unrelated_type_error(from, to, + "The Property data conversion from type " + from_name + " to " + to_name + " is not implemented."); +} diff --git a/DDCore/src/BasicGrammarTypes.cpp b/DDCore/src/BasicGrammarTypes.cpp new file mode 100644 index 000000000..2837f85f4 --- /dev/null +++ b/DDCore/src/BasicGrammarTypes.cpp @@ -0,0 +1,58 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/objects/BasicGrammar_inl.h" + +DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(char) +DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(short) +DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(int) +DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(long) +DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(long long) + +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(bool,eval_item) +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(float,eval_item) +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(double,eval_item) + +DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(std::string) +DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(std::vector<std::string>) +DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(std::list<std::string>) +DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(std::set<std::string>) + +// ROOT::Math Object instances +typedef std::map<std::string, int> map_string_int; +DD4HEP_DEFINE_PARSER_GRAMMAR(map_string_int,eval_obj) + +namespace ROOT { + namespace Math { + static bool operator<(const XYZPoint& a, const XYZPoint& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + return false; + } + static bool operator<(const XYZVector& a, const XYZVector& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + return false; + } + static bool operator<(const PxPyPzEVector& a, const PxPyPzEVector& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + if ( a.T() < b.T() ) return true; + return false; + } + } +} + +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(ROOT::Math::XYZPoint,eval_obj) +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(ROOT::Math::XYZVector,eval_obj) +DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(ROOT::Math::PxPyPzEVector,eval_obj) diff --git a/DDCore/src/Callback.cpp b/DDCore/src/Callback.cpp new file mode 100644 index 000000000..3136e7569 --- /dev/null +++ b/DDCore/src/Callback.cpp @@ -0,0 +1,22 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Callback.h" +#include "DD4hep/Exceptions.h" + +using namespace DD4hep; + +/// Check the compatibility of two typed objects. The test is the result of a dynamic_cast +void CallbackSequence::checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test) { + if (!test) { + throw unrelated_type_error(typ1, typ2, "Cannot install a callback for these 2 types."); + } +} + diff --git a/DDCore/src/Conditions.cpp b/DDCore/src/Conditions.cpp new file mode 100644 index 000000000..102550f97 --- /dev/null +++ b/DDCore/src/Conditions.cpp @@ -0,0 +1,218 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/Handle.inl" +#include "DD4hep/Printout.h" +#include "DD4hep/Detector.h" +#include "DD4hep/objects/DetectorInterna.h" +#include "DD4hep/objects/ConditionsInterna.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +namespace { + void set_condition_values(Condition::Object* c, const Condition::Entry* e) { + c->type = e->type; + c->value = e->value; + c->comment = "----"; + c->address = "----"; + c->validity = e->validity; + c->detector = e->detector; + } + Condition make_condition(const Condition::Entry* e) { + Condition c(e->name); + set_condition_values(c.ptr(),e); + return c; + } +} + + +/// Standard initializing constructor +Block::Block() : grammar(0), pointer(0) { +} + +/// Standard Destructor +Block::~Block() { +} + +/// Create data block from string representation +void Block::fromString(const std::string& rep) { + if ( pointer && grammar ) { + grammar->fromString(pointer,rep); + return; + } + throw runtime_error("Conditions data block is unbound. Cannot parse string representation."); +} + +/// Create string representation of the data block +std::string Block::str() { + if ( pointer && grammar ) { + return grammar->str(pointer); + } + throw runtime_error("Conditions data block is unbound. Cannot create string representation."); +} + +/// Initializing constructor +Condition::Condition(const string& nam) : Handle<Object>() { + assign(new ConditionsInterna::Object(),nam,"condition"); +} + +/// Assignment operator +Condition& Condition::operator=(const Condition& c) { + if ( this != &c ) this->m_element = c.m_element; + return *this; +} + +/// Access the data type +int Condition::dataType() const { + return access()->data.type; +} + +/// Access the IOV block +Block& Condition::block() const { + return access()->data; +} + +/// Access the IOV type +int Condition::iovType() const { + return access()->iov.type; +} + +/// Access the IOV block +Condition::IOV& Condition::iov() const { + return access()->iov; +} + +/// Access the name of the condition +const string& Condition::name() const { + return access()->name; +} + +/// Access the type field of the condition +const string& Condition::type() const { + return access()->type; +} + +/// Access the validity field of the condition as a string +const string& Condition::validity() const { + return access()->validity; +} + +/// Access the value field of the condition as a string +const string& Condition::value() const { + return access()->value; +} + +/// Access the comment field of the condition +const string& Condition::comment() const { + return access()->comment; +} + +/// Access the address string [e.g. database identifier] +const string& Condition::address() const { + return access()->address; +} + +/// Access the hosting detector element +DetElement Condition::detector() const { + return access()->detector; +} + +/// Access to the type information +const type_info& Condition::typeInfo() const { + return descriptor().type(); +} + +/// Access to the grammar type +const DD4hep::BasicGrammar& Condition::descriptor() const { + const BasicGrammar* g = access()->data.grammar; + if ( !g ) invalidHandleError<Condition>(); + return *g; +} + +/// Replace the data block of the condition with a new value. Free old data +Condition& Condition::replace(Entry* new_condition) { + set_condition_values(access(),new_condition); + return rebind(); +} + +/// Re-evaluate the conditions data according to the previous bound type definition +Condition& Condition::rebind() { + Object* o = access(); + o->data.fromString(o->value); + o->iov.fromString(o->validity); + printout(INFO,"Condition","+++ condition:%s : %s rebinding value:%s", + detector().path().c_str(), name().c_str(), o->value.c_str()); + return *this; +} + +/// Clear all conditions. Auto-delete of all existing entries +void Conditions::removeElements() const { + if ( !isValid() ) { + invalidHandleError<Conditions>(); + } + data<Object>()->removeElements(); +} + +/// Access the number of conditons available for this detector element +size_t Conditions::count() const { + if ( !isValid() ) { + invalidHandleError<Conditions>(); + } + return data<Object>()->entries.size(); +} + +/// Access the full map of conditons +Conditions::Entries& Conditions::entries() const { + if ( !isValid() ) { + invalidHandleError<Conditions>(); + } + return data<Object>()->entries; +} + +/** Set a single conditions value (eventually existing entries are overwritten) + * Note: Passing a valid handle also passes ownership!!! + * + * Failure return 0 in case an invalid handle is present + * Successful insertion returns 1 + * Successful overwriting an existing value returns 3 + */ +int Conditions::set(Entry* cond) { + int status = 0; + if ( cond ) { + Condition c; + Object* o = 0; + status = 1; + if ( isValid() ) { + o = data<Object>(); + Entries::iterator i = o->entries.find(cond->name); + if ( i != o->entries.end() ) { + (*i).second.replace(cond); + c = (*i).second; + status = 2; + } + } + else { + DetElement det(cond->detector); + assign(o=new ConditionsInterna::Container(),cond->name,cond->detector.name()); + det._data().conditions = *this; // Ugly. Need to fix this.... + } + if ( status == 1 ) { + c = make_condition(cond); + o->entries.insert(make_pair(cond->name,c)); + } + printout(INFO,"Conditions","+++ %s condition:%s : %s value:%s", + (status==1) ? "Added NEW" : "Replaced existing", + c.detector().path().c_str(), c.name().c_str(), c->value.c_str()); + delete cond; + } + return status; +} diff --git a/DDCore/src/ConditionsInterna.cpp b/DDCore/src/ConditionsInterna.cpp new file mode 100644 index 000000000..56ce287f5 --- /dev/null +++ b/DDCore/src/ConditionsInterna.cpp @@ -0,0 +1,172 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/Handle.inl" +#include "DD4hep/Printout.h" +#include "DD4hep/Detector.h" +#include "DD4hep/InstanceCount.h" +#include "DD4hep/objects/ConditionsInterna.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; +using namespace DD4hep::Geometry::ConditionsInterna; + +DD4HEP_INSTANTIATE_HANDLE_NAMED(ConditionsInterna::Object); + +/// Initializing constructor +IOV::IOV(int t) : type(t) { +} + +/// Standard Destructor +IOV::~IOV() { +} + +/// Move the data content: 'from' will be reset to NULL +void IOV::move(IOV& from) { + ::memcpy(this,&from,sizeof(IOV)); + ::memset(&from,0,sizeof(IOV)); +} + +/// Create IOV data from string representation +void IOV::fromString(const std::string& rep) { + notImplemented("void IOV::fromString(const std::string& rep): "+rep); +} + +/// Create string representation of the IOV +std::string IOV::str() { + notImplemented("void IOV::fromString(const std::string& rep)"); + return ""; +} + +/// Standard initializing constructor +BlockData::BlockData() : Block(), destruct(0), type(0) { +} + +/// Standard Destructor +BlockData::~BlockData() { + if ( destruct ) { + (*destruct)(pointer); + if ( (type&ALLOC_DATA) == ALLOC_DATA ) ::operator delete(pointer); + } + pointer = 0; + grammar = 0; +} + +/// Move the data content: 'from' will be reset to NULL +void BlockData::move(BlockData& from) { + ::memcpy(this,&from,sizeof(BlockData)); + ::memset(&from,0,sizeof(BlockData)); + from.type = PLAIN_DATA; +} + +/// Set data value +void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), void (*dtor)(void*)) { + if ( !grammar ) { + size_t len = g->sizeOf(); + grammar = g; + destruct = dtor; + copy = ctor; + (len > sizeof(data)) + ? (pointer=::operator new(len),type=ALLOC_DATA) + : (pointer=data,type=PLAIN_DATA); + return; + } + else if ( grammar == g ) { + return; + } + typeinfoCheck(grammar->type(),g->type(),"Conditions data blocks may not be assigned."); +} + +/// Set data value +void BlockData::assign(const void* ptr, const type_info& typ) { + if ( !grammar ) { + throw runtime_error("Conditions data block is unbound. Cannot copy data."); + } + else if ( grammar->type() != typ ) { + throw runtime_error("bad binding"); + } + (*copy)(pointer,ptr); +} + +/// Standard constructor +Object::Object() : NamedObject(), detector(), data(), iov() { + InstanceCount::increment(this); +} + +/// Standard Destructor +Object::~Object() { + InstanceCount::decrement(this); +} + +/// Assignment operator +Object& Object::move(Object& c) { + if ( this != &c ) { + name = c.name; + type = c.type; + address = c.address; + comment = c.comment; + detector = c.detector; + data.move(c.data); + iov.move(c.iov); + } + return *this; +} + +/// Initializing constructor +Entry::Entry(const DetElement& det, const string& nam, + const string& typ, const string& valid) + : NamedObject(nam), detector(det), type(typ), value(), validity(valid) +{ + InstanceCount::increment(this); +} + +/// Copy constructor +Entry::Entry(const Entry& c) + : NamedObject(c), detector(c.detector), type(c.type), value(c.value), validity(c.validity) +{ + InstanceCount::increment(this); +} + +/// Default destructor +Entry::~Entry() { + InstanceCount::decrement(this); +} + +/// Assignment operator +Entry& Entry::operator=(const Entry& c) { + if ( this != &c ) { + this->NamedObject::operator=(c); + detector = c.detector; + type = c.type; + value = c.value; + validity = c.validity; + } + return *this; +} + +/// Standard constructor +Container::Container() : NamedObject() { + InstanceCount::increment(this); +} + +/// Default destructor +Container::~Container() { + removeElements(); + InstanceCount::decrement(this); +} + +/// Clear all conditions. Auto-delete of all existing entries +void Container::removeElements() { + for(Entries::iterator i=entries.begin(); i != entries.end(); ++i) + delete (*i).second.ptr(); + entries.clear(); +} + diff --git a/DDCore/src/ConditonsTypes.cpp b/DDCore/src/ConditonsTypes.cpp new file mode 100644 index 000000000..eb77f0435 --- /dev/null +++ b/DDCore/src/ConditonsTypes.cpp @@ -0,0 +1,44 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/objects/ConditionsInterna.h" + +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +// C/C++ include files +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> + +DD4HEP_DEFINE_CONDITIONS_U_CONT(char) +DD4HEP_DEFINE_CONDITIONS_U_CONT(short) +DD4HEP_DEFINE_CONDITIONS_U_CONT(int) +DD4HEP_DEFINE_CONDITIONS_U_CONT(long) +DD4HEP_DEFINE_CONDITIONS_U_CONT(long long) + +DD4HEP_DEFINE_CONDITIONS_CONT(bool) +DD4HEP_DEFINE_CONDITIONS_CONT(float) +DD4HEP_DEFINE_CONDITIONS_CONT(double) + +DD4HEP_DEFINE_CONDITIONS_TYPE(std::string) +DD4HEP_DEFINE_CONDITIONS_TYPE(std::vector<std::string>) +DD4HEP_DEFINE_CONDITIONS_TYPE(std::list<std::string>) +DD4HEP_DEFINE_CONDITIONS_TYPE(std::set<std::string>) + +// ROOT::Math Object instances +typedef std::map<std::string, int> map_string_int; +DD4HEP_DEFINE_CONDITIONS_TYPE(map_string_int) +DD4HEP_DEFINE_CONDITIONS_TYPE(ROOT::Math::XYZPoint) +DD4HEP_DEFINE_CONDITIONS_TYPE(ROOT::Math::XYZVector) +DD4HEP_DEFINE_CONDITIONS_TYPE(ROOT::Math::PxPyPzEVector) diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp index 800fd47c7..5aec89bb3 100644 --- a/DDCore/src/Detector.cpp +++ b/DDCore/src/Detector.cpp @@ -7,229 +7,67 @@ // //==================================================================== -#include "DD4hep/InstanceCount.h" -#include "DD4hep/IDDescriptor.h" +// Framework include files +#include "DD4hep/objects/DetectorInterna.h" #include "DD4hep/DetectorTools.h" #include "DD4hep/LCDD.h" -#include "TGeoVolume.h" -#include "TGeoMatrix.h" -#include "TGeoManager.h" -#include <iostream> using namespace std; using namespace DD4hep::Geometry; -typedef DetectorTools::PlacementPath PlacementPath; -typedef DetectorTools::ElementPath ElementPath; - -namespace { - struct ExtensionEntry { - void* (*copy)(const void*, DetElement); - void (*destruct)(void*); - int id; - }; - typedef map<const type_info*, ExtensionEntry> ExtensionMap; - static int s_extensionID = 0; - ExtensionMap& detelement_extensions() { - static ExtensionMap s_map; - return s_map; - } - ExtensionMap& sensitive_detector_extensions() { - static ExtensionMap s_map; - return s_map; - } -} - -/// Default constructor -DetElement::Object::Object() - : TNamed(), magic(magic_word()), id(0), combineHits(0), - placement(), volumeID(0), parent(), reference(), children(), extensions(), - alignment(), volume_alignments(), conditions(), - worldTrafo(0), parentTrafo(0), referenceTrafo(0) { - InstanceCount::increment(this); -} - -/// Internal object destructor: release extension object(s) -DetElement::Object::~Object() { - for_each(children.begin(), children.end(), destroyHandles(children)); - deletePtr (worldTrafo); - deletePtr (parentTrafo); - deletePtr (referenceTrafo); - alignment.clear(); - conditions.clear(); - placement.clear(); - parent.clear(); - ExtensionMap& m = detelement_extensions(); - for (Extensions::iterator i = extensions.begin(); i != extensions.end(); ++i) { - void* ptr = (*i).second; - if (ptr) { - ExtensionMap::iterator j = m.find((*i).first); - if (j != m.end()) { - ExtensionEntry& e = (*j).second; - if (e.destruct) - (*(e.destruct))(ptr); - } - } - } - extensions.clear(); - InstanceCount::decrement(this); -} - -/// Deep object copy to replicate DetElement trees e.g. for reflection -DetElement::Object* DetElement::Object::clone(int new_id, int flag) const { - Object* obj = new Object(); - const ExtensionMap& m = detelement_extensions(); - Ref_t det(obj); - obj->id = new_id; - obj->combineHits = combineHits; - obj->alignment = Alignment(); - obj->conditions = Conditions(); - obj->parent = DetElement(); - obj->placement = ((flag & COPY_PLACEMENT) == COPY_PLACEMENT) ? placement : PlacedVolume(); - - // This implicitly assumes that the children do not access the parent's extensions! - obj->extensions.clear(); - for (DetElement::Extensions::const_iterator i = extensions.begin(); i != extensions.end(); ++i) { - const type_info* info = (*i).first; - ExtensionMap::const_iterator j = m.find(info); - const ExtensionEntry& e = (*j).second; - obj->extensions[info] = (*(e.copy))((*i).second, det); - } - - obj->children.clear(); - for (DetElement::Children::const_iterator i = children.begin(); i != children.end(); ++i) { - const TNamed* pc = (*i).second.ptr(); - const DetElement::Object& d = (*i).second._data(); - DetElement child(d.clone(d.id, COPY_PLACEMENT), pc->GetName(), pc->GetTitle()); - pair<Children::iterator, bool> r = obj->children.insert(make_pair(child.name(), child)); - if (r.second) { - child._data().parent = det; - } - else { - throw runtime_error("DD4hep: DetElement::copy: Element " + string(child.name()) + " is already present [Double-Insert]"); - } - } - return obj; -} - -/// Conversion to reference object -Ref_t DetElement::Object::asRef() { - return Ref_t(this); -} - -/// Conversion to reference object -DetElement::Object::operator Ref_t() { - return this->asRef(); -} - -/// Create cached matrix to transform to world coordinates -TGeoMatrix* DetElement::Object::worldTransformation() { - if (!worldTrafo) { - PlacementPath nodes; - DetectorTools::placementPath(DetElement(asRef()), nodes); - worldTrafo = DetectorTools::placementTrafo(nodes,true); - } - return worldTrafo; -} - -/// Create cached matrix to transform to parent coordinates -TGeoMatrix* DetElement::Object::parentTransformation() { - if (!parentTrafo) { - PlacementPath nodes; - DetectorTools::placementPath(DetElement(parent), DetElement(asRef()), nodes); - parentTrafo = DetectorTools::placementTrafo(nodes,true); - } - return parentTrafo; -} -/// Create cached matrix to transform to reference coordinates -TGeoMatrix* DetElement::Object::referenceTransformation() { - if (!referenceTrafo) { - ElementPath elements; - DetElement ref(reference); - DetElement self(asRef()); - if ( ref.ptr() == self.ptr() ) { - referenceTrafo = new TGeoHMatrix(gGeoIdentity->Inverse()); - } - else if ( DetectorTools::findParent(ref,self,elements) ) { - PlacementPath nodes; - DetectorTools::placementPath(ref, self, nodes); - referenceTrafo = DetectorTools::placementTrafo(nodes,true); - } - else if ( DetectorTools::findParent(self,ref,elements) ) { - PlacementPath nodes; - DetectorTools::placementPath(self, ref, nodes); - referenceTrafo = DetectorTools::placementTrafo(nodes,true); - } - else { - throw runtime_error("DD4hep: referenceTransformation: No path from " + string(self.name()) + - " to reference element " + string(ref.name()) + " present!"); - } - } - return referenceTrafo; +/// Clone constructor +DetElement::DetElement(Object* data, const string& name, const string& type) + : RefObject(data) { + this->assign(data, name, type); } /// Constructor for a new subdetector element DetElement::DetElement(const string& name, const string& type, int id) { assign(new Object(), name, type); - object<Object>().id = id; + ptr()->id = id; } /// Constructor for a new subdetector element DetElement::DetElement(const string& name, int id) { assign(new Object(), name, ""); - object<Object>().id = id; + ptr()->id = id; } /// Constructor for a new subdetector element DetElement::DetElement(DetElement parent, const string& name, int id) { assign(new Object(), name, parent.type()); - object<Object>().id = id; + ptr()->id = id; parent.add(*this); } /// Add an extension object to the detector element -void* DetElement::i_addExtension(void* ptr, const type_info& info, void* (*copy)(const void*, DetElement), - void (*destruct)(void*)) { - Object& o = object<Object>(); - Extensions::iterator j = o.extensions.find(&info); - if (j == o.extensions.end()) { - ExtensionMap& m = detelement_extensions(); - ExtensionMap::iterator i = m.find(&info); - if (i == m.end()) { - ExtensionEntry entry; - entry.destruct = destruct; - entry.copy = copy; - entry.id = ++s_extensionID; - m.insert(make_pair(&info, entry)); - i = m.find(&info); - } - //cout << "Extension[" << name() << "]:" << ptr << " " << info.name() << endl; - return o.extensions[&info] = ptr; - } - throw runtime_error( - "DD4hep: addExtension: The object " + string(name()) - + " already has an extension of type:" + string(info.name()) + "."); +void* DetElement::i_addExtension(void* ptr, const type_info& info, copy_t ctor, destruct_t dtor) const { + return access()->addExtension(ptr, info, ObjectExtensions::copy_t(ctor), dtor); } /// Access an existing extension object from the detector element void* DetElement::i_extension(const type_info& info) const { - Object& o = object<Object>(); - Extensions::const_iterator j = o.extensions.find(&info); - if (j != o.extensions.end()) { - return (*j).second; - } - throw runtime_error( - "DD4hep: extension: The object " + string(name()) + " has no extension of type:" + string(info.name()) + "."); + return access()->extension(info); +} + +/// Internal call to extend the detector element with an arbitrary structure accessible by the type +void DetElement::i_addUpdateCall(unsigned int callback_type, const Callback& callback) const { + access()->updateCalls.push_back(make_pair(callback,callback_type)); +} + +/// Remove callback from object +void DetElement::removeAtUpdate(unsigned int type, void* pointer) const { + access()->removeAtUpdate(type,pointer); } /// Access to the full path to the placed object string DetElement::placementPath() const { - if (isValid()) { - Object& o = object<Object>(); - if (o.placementPath.empty()) { - o.placementPath = DetectorTools::placementPath(*this); + Object* o = ptr(); + if ( o ) { + if (o->placementPath.empty()) { + o->placementPath = DetectorTools::placementPath(*this); } - return o.placementPath; + return o->placementPath; } return ""; } @@ -241,35 +79,33 @@ string DetElement::type() const { /// Set the type of the sensitive detector DetElement& DetElement::setType(const string& typ) { - if (isValid()) { - m_element->SetTitle(typ.c_str()); - return *this; - } - throw runtime_error("DD4hep: DetElement::setType: Self is not defined [Invalid Handle]"); + Object* o = access(); + o->SetTitle(typ.c_str()); + return *this; } string DetElement::path() const { - if (m_element) { - Object& o = object<Object>(); - if (o.path.empty()) { - DetElement par = o.parent; - o.path = par.isValid() ? (par.path() + "/") + name() : string("/") + name(); + Object* o = ptr(); + if ( o ) { + if ( o->path.empty() ) { + DetElement par = o->parent; + o->path = par.isValid() ? (par.path() + "/") + name() : string("/") + name(); } - return o.path; + return o->path; } return ""; } int DetElement::id() const { - return object<Object>().id; + return access()->id; } bool DetElement::combineHits() const { - return object<Object>().combineHits != 0; + return access()->combineHits != 0; } DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens) { - object<Object>().combineHits = value; + access()->combineHits = value; if (sens.isValid()) sens.setCombineHits(value); return *this; @@ -277,22 +113,22 @@ DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens) { /// Access to the alignment information Alignment DetElement::alignment() const { - return object<Object>().alignment; + return access()->alignment; } /// Access to the conditions information Conditions DetElement::conditions() const { - return object<Object>().conditions; + return access()->conditions; } const DetElement::Children& DetElement::children() const { - return object<Object>().children; + return access()->children; } /// Access to individual children by name DetElement DetElement::child(const string& name) const { if (isValid()) { - const Children& c = object<Object>().children; + const Children& c = ptr()->children; Children::const_iterator i = c.find(name); return i == c.end() ? DetElement() : (*i).second; } @@ -301,10 +137,8 @@ DetElement DetElement::child(const string& name) const { /// Access to the detector elements's parent DetElement DetElement::parent() const { - if (isValid()) { - return object<Object>().parent; - } - return DetElement(); + Object* o = ptr(); + return (o) ? o->parent : 0; } void DetElement::check(bool condition, const string& msg) const { @@ -317,7 +151,7 @@ DetElement& DetElement::add(DetElement sdet) { if (isValid()) { pair<Children::iterator, bool> r = object<Object>().children.insert(make_pair(sdet.name(), sdet)); if (r.second) { - sdet.object<Object>().parent = *this; + sdet.access()->parent = *this; return *this; } throw runtime_error("DD4hep: DetElement::add: Element " + string(sdet.name()) + " is already present [Double-Insert]"); @@ -326,19 +160,13 @@ DetElement& DetElement::add(DetElement sdet) { } DetElement DetElement::clone(const string& new_name) const { - if (isValid()) { - Object& o = object<Object>(); - return DetElement(o.clone(o.id, COPY_NONE), new_name, o.GetTitle()); - } - throw runtime_error("DD4hep: DetElement::clone: Self is not defined - clone failed! [Invalid Handle]"); + Object* o = access(); + return DetElement(o->clone(o->id, COPY_NONE), new_name, o->GetTitle()); } DetElement DetElement::clone(const string& new_name, int new_id) const { - if (isValid()) { - Object& o = object<Object>(); - return DetElement(o.clone(new_id, COPY_NONE), new_name, o.GetTitle()); - } - throw runtime_error("DD4hep: DetElement::clone: Self is not defined - clone failed! [Invalid Handle]"); + Object* o = access(); + return DetElement(o->clone(new_id, COPY_NONE), new_name, o->GetTitle()); } /// Access to the physical volume of this detector element @@ -354,17 +182,15 @@ PlacedVolume DetElement::placement() const { /// Set the physical volumes of the detector element DetElement& DetElement::setPlacement(const PlacedVolume& placement) { - if (isValid()) { - if (placement.isValid()) { - Object& o = object<Object>(); - o.placement = placement; - //o.volume = placement.volume(); - //placement.setDetector(*this); - return *this; + if (placement.isValid()) { + Object* o = access(); + o->placement = placement; + if ( !o->idealPlace.isValid() ) { + o->idealPlace = placement; } - throw runtime_error("DD4hep: DetElement::setPlacement: Placement is not defined [Invalid Handle]"); + return *this; } - throw runtime_error("DD4hep: DetElement::setPlacement: Self is not defined [Invalid Handle]"); + throw runtime_error("DD4hep: DetElement::setPlacement: Placement is not defined [Invalid Handle]"); } /// The cached VolumeID of this subdetector element @@ -377,38 +203,26 @@ DD4hep::VolumeID DetElement::volumeID() const { /// Access to the logical volume of the placements (all daughters have the same!) Volume DetElement::volume() const { - if (isValid()) { - return object<Object>().placement.volume(); - } - throw runtime_error("DD4hep: DetElement::volume: Self is not defined [Invalid Handle]"); + return access()->placement.volume(); } DetElement& DetElement::setVisAttributes(const LCDD& lcdd, const string& name, const Volume& volume) { - if (isValid()) { - volume.setVisAttributes(lcdd, name); - return *this; - } - throw runtime_error("DD4hep: DetElement::setVisAttributes: Self is not defined [Invalid Handle]"); + volume.setVisAttributes(lcdd, name); + return *this; } DetElement& DetElement::setRegion(const LCDD& lcdd, const string& name, const Volume& volume) { - if (isValid()) { - if (!name.empty()) { - volume.setRegion(lcdd.region(name)); - } - return *this; + if (!name.empty()) { + volume.setRegion(lcdd.region(name)); } - throw runtime_error("DD4hep: DetElement::setRegion: Self is not defined [Invalid Handle]"); + return *this; } DetElement& DetElement::setLimitSet(const LCDD& lcdd, const string& name, const Volume& volume) { - if (isValid()) { - if (!name.empty()) { - volume.setLimitSet(lcdd.limitSet(name)); - } - return *this; + if (!name.empty()) { + volume.setLimitSet(lcdd.limitSet(name)); } - throw runtime_error("DD4hep: DetElement::setLimitSet: Self is not defined [Invalid Handle]"); + return *this; } DetElement& DetElement::setAttributes(const LCDD& lcdd, const Volume& volume, const string& region, const string& limits, @@ -427,11 +241,26 @@ DetElement& DetElement::setReference(DetElement reference) { return *this; } +/// Create cached matrix to transform to world coordinates +const TGeoHMatrix& DetElement::worldTransformation() const { + return access()->worldTransformation(); +} + +/// Create cached matrix to transform to parent coordinates +const TGeoHMatrix& DetElement::parentTransformation() const { + return access()->parentTransformation(); +} + +/// Create cached matrix to transform to reference coordinates +const TGeoHMatrix& DetElement::referenceTransformation() const { + return access()->referenceTransformation(); +} + /// Transformation from local coordinates of the placed volume to the world system bool DetElement::localToWorld(const Position& local, Position& global) const { Double_t master_point[3] = { 0, 0, 0 }, local_point[3] = { local.X(), local.Y(), local.Z() }; // If the path is unknown an exception will be thrown inside worldTransformation() ! - object<Object>().worldTransformation()->LocalToMaster(local_point, master_point); + worldTransformation().LocalToMaster(local_point, master_point); global.SetCoordinates(master_point); return true; } @@ -440,7 +269,7 @@ bool DetElement::localToWorld(const Position& local, Position& global) const { bool DetElement::localToParent(const Position& local, Position& global) const { // If the path is unknown an exception will be thrown inside parentTransformation() ! Double_t master_point[3] = { 0, 0, 0 }, local_point[3] = { local.X(), local.Y(), local.Z() }; - object<Object>().parentTransformation()->LocalToMaster(local_point, master_point); + parentTransformation().LocalToMaster(local_point, master_point); global.SetCoordinates(master_point); return true; } @@ -449,7 +278,7 @@ bool DetElement::localToParent(const Position& local, Position& global) const { bool DetElement::localToReference(const Position& local, Position& global) const { // If the path is unknown an exception will be thrown inside referenceTransformation() ! Double_t master_point[3] = { 0, 0, 0 }, local_point[3] = { local.X(), local.Y(), local.Z() }; - object<Object>().referenceTransformation()->LocalToMaster(local_point, master_point); + referenceTransformation().LocalToMaster(local_point, master_point); global.SetCoordinates(master_point); return true; } @@ -458,7 +287,7 @@ bool DetElement::localToReference(const Position& local, Position& global) const bool DetElement::worldToLocal(const Position& global, Position& local) const { // If the path is unknown an exception will be thrown inside worldTransformation() ! Double_t master_point[3] = { global.X(), global.Y(), global.Z() }, local_point[3] = { 0, 0, 0 }; - object<Object>().worldTransformation()->MasterToLocal(master_point, local_point); + worldTransformation().MasterToLocal(master_point, local_point); local.SetCoordinates(local_point); return true; } @@ -467,7 +296,7 @@ bool DetElement::worldToLocal(const Position& global, Position& local) const { bool DetElement::parentToLocal(const Position& global, Position& local) const { // If the path is unknown an exception will be thrown inside parentTransformation() ! Double_t master_point[3] = { global.X(), global.Y(), global.Z() }, local_point[3] = { 0, 0, 0 }; - object<Object>().parentTransformation()->MasterToLocal(master_point, local_point); + parentTransformation().MasterToLocal(master_point, local_point); local.SetCoordinates(local_point); return true; } @@ -476,38 +305,11 @@ bool DetElement::parentToLocal(const Position& global, Position& local) const { bool DetElement::referenceToLocal(const Position& global, Position& local) const { // If the path is unknown an exception will be thrown inside referenceTransformation() ! Double_t master_point[3] = { global.X(), global.Y(), global.Z() }, local_point[3] = { 0, 0, 0 }; - object<Object>().referenceTransformation()->MasterToLocal(master_point, local_point); + referenceTransformation().MasterToLocal(master_point, local_point); local.SetCoordinates(local_point); return true; } -/// Default constructor -SensitiveDetector::Object::Object() - : magic(magic_word()), verbose(0), combineHits(0), ecut(0.0), hitsCollection(), readout(), region(), limits(), extensions() { - InstanceCount::increment(this); -} - -/// Internal object destructor: release extension object(s) -SensitiveDetector::Object::~Object() { - ExtensionMap& m = sensitive_detector_extensions(); - readout.clear(); - region.clear(); - limits.clear(); - for (Extensions::iterator i = extensions.begin(); i != extensions.end(); ++i) { - void* ptr = (*i).second; - if (ptr) { - ExtensionMap::iterator j = m.find((*i).first); - if (j != m.end()) { - ExtensionEntry& e = (*j).second; - if (e.destruct) - (*(e.destruct))(ptr); - } - } - } - extensions.clear(); - InstanceCount::decrement(this); -} - /// Constructor SensitiveDetector::SensitiveDetector(const string& name, const string& type) { /* @@ -523,11 +325,8 @@ SensitiveDetector::SensitiveDetector(const string& name, const string& type) { /// Set the type of the sensitive detector SensitiveDetector& SensitiveDetector::setType(const string& typ) { - if (isValid()) { - m_element->SetTitle(typ.c_str()); - return *this; - } - throw runtime_error("DD4hep: SensitiveDetector::setType: Self is not defined [Invalid Handle]"); + access()->SetTitle(typ.c_str()); + return *this; } /// Access the type of the sensitive detector @@ -537,113 +336,89 @@ string SensitiveDetector::type() const { /// Assign the IDDescriptor reference SensitiveDetector& SensitiveDetector::setReadout(Readout ro) { - object<Object>().readout = ro; + access()->readout = ro; return *this; } /// Assign the IDDescriptor reference Readout SensitiveDetector::readout() const { - return object<Object>().readout; + return access()->readout; } /// Set energy cut off SensitiveDetector& SensitiveDetector::setEnergyCutoff(double value) { - object<Object>().ecut = value; + access()->ecut = value; return *this; } /// Access energy cut off double SensitiveDetector::energyCutoff() const { - return object<Object>().ecut; + return access()->ecut; } /// Assign the name of the hits collection SensitiveDetector& SensitiveDetector::setHitsCollection(const string& collection) { - object<Object>().hitsCollection = collection; + access()->hitsCollection = collection; return *this; } /// Access the hits collection name const string& SensitiveDetector::hitsCollection() const { - return object<Object>().hitsCollection; + return access()->hitsCollection; } /// Assign the name of the hits collection SensitiveDetector& SensitiveDetector::setVerbose(bool value) { int v = value ? 1 : 0; - object<Object>().verbose = v; + access()->verbose = v; return *this; } /// Access flag to combine hist bool SensitiveDetector::verbose() const { - return object<Object>().verbose == 1; + return access()->verbose == 1; } /// Assign the name of the hits collection SensitiveDetector& SensitiveDetector::setCombineHits(bool value) { int v = value ? 1 : 0; - object<Object>().combineHits = v; + access()->combineHits = v; return *this; } /// Access flag to combine hist bool SensitiveDetector::combineHits() const { - return object<Object>().combineHits == 1; + return access()->combineHits == 1; } /// Set the regional attributes to the sensitive detector SensitiveDetector& SensitiveDetector::setRegion(Region reg) { - object<Object>().region = reg; + access()->region = reg; return *this; } /// Access to the region setting of the sensitive detector (not mandatory) Region SensitiveDetector::region() const { - return object<Object>().region; + return access()->region; } /// Set the limits to the sensitive detector SensitiveDetector& SensitiveDetector::setLimitSet(LimitSet limits) { - object<Object>().limits = limits; + access()->limits = limits; return *this; } /// Access to the limit set of the sensitive detector (not mandatory). LimitSet SensitiveDetector::limits() const { - return object<Object>().limits; + return access()->limits; } /// Add an extension object to the detector element -void* SensitiveDetector::i_addExtension(void* ptr, const type_info& info, void (*destruct)(void*)) { - Object& o = object<Object>(); - Extensions::iterator j = o.extensions.find(&info); - if (j == o.extensions.end()) { - ExtensionMap& m = sensitive_detector_extensions(); - ExtensionMap::iterator i = m.find(&info); - if (i == m.end()) { - ExtensionEntry entry; - entry.destruct = destruct; - entry.copy = 0; - entry.id = ++s_extensionID; - m.insert(make_pair(&info, entry)); - i = m.find(&info); - } - //cout << "Add Extension[" << name() << "]:" << ptr << " " << typeid(*(TNamed*) ptr).name() << endl; - return o.extensions[&info] = ptr; - } - throw runtime_error( - "DD4hep: addExtension: The object " + string(name()) + " already has an extension of type:" + string(info.name()) + "."); +void* SensitiveDetector::i_addExtension(void* ptr, const type_info& info, destruct_t dtor) { + return access()->addExtension(ptr, info, dtor); } /// Access an existing extension object from the detector element void* SensitiveDetector::i_extension(const type_info& info) const { - Object& o = object<Object>(); - Extensions::const_iterator j = o.extensions.find(&info); - if (j != o.extensions.end()) { - return (*j).second; - } - throw runtime_error( - "DD4hep: extension: The object " + string(name()) + " has no extension of type:" + string(info.name()) + "."); + return access()->extension(info); } - diff --git a/DDCore/src/DetectorInterna.cpp b/DDCore/src/DetectorInterna.cpp new file mode 100644 index 000000000..9b67e6eb7 --- /dev/null +++ b/DDCore/src/DetectorInterna.cpp @@ -0,0 +1,233 @@ +// $Id: Detector.cpp 1087 2014-04-09 12:25:51Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/objects/ConditionsInterna.h" +#include "DD4hep/InstanceCount.h" +#include "DD4hep/DetectorTools.h" +#include "DD4hep/Handle.inl" +#include "DD4hep/Printout.h" +#include "TGeoVolume.h" +#include "TGeoMatrix.h" +#include "TGeoManager.h" +#include "DD4hep/objects/DetectorInterna.h" + +using namespace std; +using namespace DD4hep::Geometry; +typedef DetectorTools::PlacementPath PlacementPath; +typedef DetectorTools::ElementPath ElementPath; + +DD4HEP_INSTANTIATE_HANDLE(DetElementObject); +DD4HEP_INSTANTIATE_HANDLE(SensitiveDetectorObject); + +/// Default constructor +SensitiveDetectorObject::SensitiveDetectorObject() + : TNamed(), ObjectExtensions(typeid(SensitiveDetectorObject)), magic(magic_word()), verbose(0), combineHits(0), ecut(0.0), readout(), region(), limits(), hitsCollection() { + InstanceCount::increment(this); +} + +/// Internal object destructor: release extension object(s) +SensitiveDetectorObject::~SensitiveDetectorObject() { + readout.clear(); + region.clear(); + limits.clear(); + ObjectExtensions::clear(); + InstanceCount::decrement(this); +} + +/// Default constructor +DetElementObject::DetElementObject() + : TNamed(), ObjectExtensions(typeid(DetElementObject)), magic(magic_word()), flag(0), id(0), combineHits(0), path(), placementPath(), + idealPlace(), placement(), volumeID(0), parent(), reference(), children(), + alignment(), volume_alignments(), conditions(), + worldTrafo(), parentTrafo(), referenceTrafo(0) { + InstanceCount::increment(this); +} + +/// Internal object destructor: release extension object(s) +DetElementObject::~DetElementObject() { + for_each(children.begin(), children.end(), destroyHandles(children)); + deletePtr (referenceTrafo); + destroyHandle(conditions); + alignment.clear(); + placement.clear(); + idealPlace.clear(); + parent.clear(); + ObjectExtensions::clear(); + InstanceCount::decrement(this); +} + +/// Deep object copy to replicate DetElement trees e.g. for reflection +DetElementObject* DetElementObject::clone(int new_id, int flag) const { + DetElementObject* obj = new DetElementObject(); + obj->id = new_id; + obj->flag = 0; + obj->combineHits = combineHits; + obj->alignment = Alignment(); + obj->conditions = Conditions(); + obj->parent = DetElement(); + if ( (flag & DetElement::COPY_PLACEMENT) == DetElement::COPY_PLACEMENT ) { + obj->placement = placement; + obj->idealPlace = idealPlace; + obj->placementPath = placementPath; + obj->path = path; + } + // This implicitly assumes that the children do not access the parent's extensions! + obj->ObjectExtensions::clear(); + obj->ObjectExtensions::copyFrom(extensions, obj); + + obj->children.clear(); + for (DetElement::Children::const_iterator i = children.begin(); i != children.end(); ++i) { + const TNamed* pc = (*i).second.ptr(); + const DetElementObject& d = (*i).second._data(); + DetElement child(d.clone(d.id, DetElement::COPY_PLACEMENT), pc->GetName(), pc->GetTitle()); + pair<Children::iterator, bool> r = obj->children.insert(make_pair(child.name(), child)); + if (r.second) { + child._data().parent = obj; + } + else { + throw runtime_error("DD4hep: DetElement::copy: Element " + string(child.name()) + " is already present [Double-Insert]"); + } + } + return obj; +} + +/// Create cached matrix to transform to world coordinates +const TGeoHMatrix& DetElementObject::worldTransformation() { + if ( (flag&HAVE_WORLD_TRAFO) == 0 ) { + PlacementPath nodes; + flag |= HAVE_WORLD_TRAFO; + DetectorTools::placementPath(this, nodes); + DetectorTools::placementTrafo(nodes,true,worldTrafo); + } + return worldTrafo; +} + +/// Create cached matrix to transform to parent coordinates +const TGeoHMatrix& DetElementObject::parentTransformation() { + if ( (flag&HAVE_PARENT_TRAFO) == 0 ) { + PlacementPath nodes; + flag |= HAVE_PARENT_TRAFO; + DetectorTools::placementPath(DetElement(parent), this, nodes); + DetectorTools::placementTrafo(nodes,true,parentTrafo); + } + return parentTrafo; +} + +/// Create cached matrix to transform to reference coordinates +const TGeoHMatrix& DetElementObject::referenceTransformation() { + if (!referenceTrafo) { + DetElement ref(reference); + DetElement self(this); + if ( ref.ptr() == self.ptr() ) { + referenceTrafo = new TGeoHMatrix(gGeoIdentity->Inverse()); + } + else if ( DetectorTools::isParentElement(ref,self) ) { + PlacementPath nodes; + DetectorTools::placementPath(ref,self,nodes); + DetectorTools::placementTrafo(nodes,true,referenceTrafo); + } + else if ( DetectorTools::isParentElement(self,ref) ) { + PlacementPath nodes; + DetectorTools::placementPath(self,ref,nodes); + DetectorTools::placementTrafo(nodes,true,referenceTrafo); + } + else { + throw runtime_error("DD4hep: referenceTransformation: No path from " + string(self.name()) + + " to reference element " + string(ref.name()) + " present!"); + } + } + return *referenceTrafo; +} + +/// Revalidate the caches +void DetElementObject::revalidate(TGeoHMatrix* parent_world_trafo) { + PlacementPath par_path; + DetElement det(this); + DetElement par(det.parent()); + DetElement world = DetectorTools::topElement(det); + bool print = (DEBUG > printLevel()); + string place = det.placementPath(); + bool have_world_tr = (flag&HAVE_WORLD_TRAFO); + + DetectorTools::placementPath(par, this, par_path); + PlacedVolume node = DetectorTools::findNode(world.placement(),place); + if ( !node.isValid() ) { + throw runtime_error("DD4hep: DetElement: The placement " + place + " is not part of the hierarchy."); + } + //print = (idealPlace.ptr() != node.ptr()); + printout((idealPlace.ptr() != node.ptr()) ? INFO : DEBUG, + "DetElement","+++ Invalidate chache of %s -> %s Placement:%p --> %p %s", + det.path().c_str(), DetectorTools::placementPath(par_path).c_str(), + placement.ptr(), node.ptr(), (placement.ptr() == node.ptr()) ? "" : "[UPDATE]"); + + placement = node; + + if ( have_world_tr && print ) worldTrafo.Print(); + + if ( (flag&HAVE_PARENT_TRAFO) ) { + DetectorTools::placementTrafo(par_path,true,parentTrafo); + } + + /// Compute world transformations + if ( parent_world_trafo ) { + // If possible use the pre-computed values from the parent + worldTrafo = *parent_world_trafo; + worldTrafo.Multiply(&parentTransformation()); + flag |= HAVE_WORLD_TRAFO; + } + else if ( have_world_tr ) { + // Else re-compute the transformation to the world. + PlacementPath world_nodes; + DetectorTools::placementPath(this, world_nodes); + DetectorTools::placementTrafo(world_nodes,true,worldTrafo); + flag |= HAVE_WORLD_TRAFO; + } + + if ( (flag&HAVE_PARENT_TRAFO) && print ) worldTrafo.Print(); + deletePtr (referenceTrafo); + + /// Now iterate down the children.... + for(Children::const_iterator i = children.begin(); i!=children.end(); ++i) { + DetElement d((*i).second); + d->revalidate(&worldTrafo); + } +} + +/// Remove callback from object +void DetElementObject::removeAtUpdate(unsigned int type, void* pointer) { + for(UpdateCallbacks::iterator i=updateCalls.begin(); i != updateCalls.end(); ++i) { + if ( (type&((*i).second)) == type && (*i).first.par == pointer ) { + updateCalls.erase(i); + return; + } + } +} + +/// Trigger update callbacks +void DetElementObject::update(unsigned int tags, void* param) { + DetElement det(this); + const void* args[3] = { (void*)tags, this, param }; + if ( (tags&DetElement::PLACEMENT_CHANGED)==DetElement::PLACEMENT_CHANGED && + (tags&DetElement::PLACEMENT_HIGHEST)==DetElement::PLACEMENT_HIGHEST ) { + printout(INFO,"DetElement","+++ Need to update chaches and child caches of %s", + det.path().c_str()); + DetElement par = det.parent(); + TGeoHMatrix* parent_world_trafo = 0; + if ( par.isValid() && (par->flag&HAVE_PARENT_TRAFO) ) { + parent_world_trafo = &par->worldTrafo; + } + revalidate(parent_world_trafo); + } + for(UpdateCallbacks::const_iterator i=updateCalls.begin(); i != updateCalls.end(); ++i) { + if ( (tags&((*i).second)) == tags ) { + (*i).first.execute(args); + } + } +} diff --git a/DDCore/src/DetectorTools.cpp b/DDCore/src/DetectorTools.cpp index 03ef65845..00a08e87a 100644 --- a/DDCore/src/DetectorTools.cpp +++ b/DDCore/src/DetectorTools.cpp @@ -7,37 +7,70 @@ // //==================================================================== // Framework include files +#define DETECTORTOOLS_CPP #include "DD4hep/DetectorTools.h" #include "DD4hep/Printout.h" #include "DD4hep/LCDD.h" +#include "DD4hep/objects/DetectorInterna.h" + +// C/C++ include files #include <stdexcept> #include <memory> // ROOT include files #include "TGeoMatrix.h" + + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + /** @class Detectortools DetectorTools.h DD4hep/Detectortools.h + * + * @author M.Frank + * @version 1.0 + */ + namespace DetectorTools { + /// Assemble the path of the PlacedVolume selection + std::string elementPath(const PlacementPath& nodes); + /// Collect detector elements to any parent detector element + void elementPath(DetElement parent, DetElement elt, ElementPath& detectors); + /// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] + void elementPath(DetElement elt, PlacementPath& nodes); + /// Collect detector elements placements to the parent detector element [no holes!] + void elementPath(DetElement parent, DetElement element, PlacementPath& nodes); + /// Find DetElement as child of the top level volume by it's absolute path + DetElement findElement(LCDD& lcdd, const std::string& path); + /// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes + bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path); + + + // Internal helper + static void makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes); + } + } +} + using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; -/// Collect detector elements to any parent detector element -bool DetectorTools::findParent(DetElement parent, DetElement elt, vector<DetElement>& detectors) { - detectors.clear(); - if ( parent.isValid() && elt.isValid() ) { - if ( parent.ptr() == elt.ptr() ) { - detectors.push_back(elt); - return true; - } - ElementPath elements; - for(DetElement par = elt; par.isValid(); par = par.parent()) { - elements.push_back(par); - if ( par.ptr() == parent.ptr() ) { - detectors = elements; - return true; - } +/// Find path between the child element and the parent element +bool DetectorTools::isParentElement(DetElement parent, DetElement child) { + if ( parent.isValid() && child.isValid() ) { + if ( parent.ptr() == child.ptr() ) return true; + for(DetElement par=child; par.isValid(); par=par.parent()) { + if ( par.ptr() == parent.ptr() ) return true; } } - throw runtime_error("Search for parent detector element with invalid handles not allowed."); + throw runtime_error("Search for parent detector element with invalid handles not allowed."); } /// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes @@ -103,26 +136,60 @@ static bool findChildByName(PlacedVolume parent, PlacedVolume child, DetectorToo } /// Collect detector elements to the top detector element (world) -void DetectorTools::elementPath(DetElement elt, ElementPath& detectors) { - for(DetElement par = elt; par.isValid(); par = par.parent()) +void DetectorTools::elementPath(DetElement element, ElementPath& detectors) { + for(DetElement par = element; par.isValid(); par = par.parent()) detectors.push_back(par); } /// Collect detector elements to any parent detector element -void DetectorTools::elementPath(DetElement parent, DetElement elt, ElementPath& detectors) { - if ( findParent(parent,elt,detectors) ) - return; - throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+elt.name()); +void DetectorTools::elementPath(DetElement parent, DetElement child, ElementPath& detectors) { + detectors.clear(); + if ( parent.isValid() && child.isValid() ) { + if ( parent.ptr() == child.ptr() ) { + detectors.push_back(child); + return; + } + ElementPath elements; + for(DetElement par = child; par.isValid(); par = par.parent()) { + elements.push_back(par); + if ( par.ptr() == parent.ptr() ) { + detectors = elements; + return; + } + } + throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+child.name()); + } + throw runtime_error("Search for parent detector element with invalid handles not allowed."); } /// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] -void DetectorTools::elementPath(DetElement element, vector<PlacedVolume>& det_nodes) { +void DetectorTools::elementPath(DetElement parent, DetElement element, PlacementPath& det_nodes) { for(DetElement par = element; par.isValid(); par = par.parent()) { PlacedVolume pv = par.placement(); - if ( pv.isValid() ) { + if ( pv.isValid() ) { det_nodes.push_back(pv); } + if ( par.ptr() == parent.ptr() ) return; } + throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+element.name()); +} + +/// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] +void DetectorTools::elementPath(DetElement element, PlacementPath& det_nodes) { + for(DetElement par = element; par.isValid(); par = par.parent()) { + PlacedVolume pv = par.placement(); + if ( pv.isValid() ) { + det_nodes.push_back(pv); + } + } +} + +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::elementPath(const PlacementPath& nodes) { + string s = ""; + for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) + s += "/" + string((*i).name()); + return s; } /// Assemble the path of the PlacedVolume selection @@ -142,24 +209,24 @@ std::string DetectorTools::elementPath(DetElement element) { /// Find DetElement as child of the top level volume by it's absolute path DetElement DetectorTools::findElement(LCDD& lcdd, const std::string& path) { - return findElement(lcdd.world(),path); + return findDaughterElement(lcdd.world(),path); } /// Find DetElement as child of a parent by it's relative or absolute path -DetElement DetectorTools::findElement(DetElement parent, const std::string& subpath) { +DetElement DetectorTools::findDaughterElement(DetElement parent, const std::string& subpath) { if ( parent.isValid() ) { size_t idx = subpath.find('/',1); - if ( subpath[0] == '/' ) { + if ( subpath[0] == '/' ) { DetElement top = topElement(parent); if ( idx == string::npos ) return top; - return findElement(top,subpath.substr(idx+1)); + return findDaughterElement(top,subpath.substr(idx+1)); } if ( idx == string::npos ) return parent.child(subpath); string name = subpath.substr(0,idx); DetElement node = parent.child(name); - if ( node.isValid() ) { - return findElement(node,subpath.substr(idx+1)); + if ( node.isValid() ) { + return findDaughterElement(node,subpath.substr(idx+1)); } throw runtime_error("DD4hep: DetElement "+parent.path()+" has no child named:"+name+" [No such child]"); } @@ -176,32 +243,30 @@ DetElement DetectorTools::topElement(DetElement child) { throw runtime_error("DD4hep: DetElement cannot determine top parent (world) [invalid handle]"); } -/// Collect detector elements placements to the top detector element (world) [no holes!] -void DetectorTools::placementPath(DetElement element, PlacementPath& nodes) { - PlacementPath det_nodes, all_nodes; - DetectorTools::elementPath(element,det_nodes); - for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { - if (!findChildByName(det_nodes[i + 1], det_nodes[i], nodes)) { +static void DetectorTools::makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes) { + for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { + if (!findChildByName(det_nodes[i + 1], det_nodes[i], all_nodes)) { throw runtime_error("DD4hep: DetElement cannot determine placement path of " - + string(element.name()) + " [internal error]"); + + string(det_nodes[i].name()) + " [internal error]"); } } - if ( det_nodes.size()>0 ) { - nodes.push_back(det_nodes.back()); + if ( det_nodes.size() > 0 ) { + all_nodes.push_back(det_nodes.back()); } } +/// Collect detector elements placements to the top detector element (world) [no holes!] +void DetectorTools::placementPath(DetElement element, PlacementPath& all_nodes) { + PlacementPath det_nodes; + elementPath(element,det_nodes); + makePlacementPath(det_nodes, all_nodes); +} + /// Collect detector elements placements to the parent detector element [no holes!] -void DetectorTools::placementPath(DetElement parent, DetElement child, PlacementPath& nodes) { - ElementPath det_nodes; - PlacementPath all_nodes; - DetectorTools::elementPath(parent,child,det_nodes); - for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { - if (!findChild(det_nodes[i + 1], det_nodes[i], nodes)) { - throw runtime_error("Invalid placement path "+elementPath(det_nodes)+" [internal error]"); - } - } - if ( det_nodes.size()>0 ) nodes.push_back(det_nodes.back()); +void DetectorTools::placementPath(DetElement parent, DetElement element, PlacementPath& all_nodes) { + PlacementPath det_nodes; + elementPath(parent,element,det_nodes); + makePlacementPath(det_nodes, all_nodes); } /// Assemble the path of the PlacedVolume selection @@ -219,21 +284,71 @@ std::string DetectorTools::placementPath(const PlacementPath& nodes) { return s; } -/// Create cached matrix to transform to positions to an upper level Placement -TGeoMatrix* DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse) { - if (nodes.size() < 2) { - return new TGeoHMatrix(*gGeoIdentity); +/// Update cached matrix to transform to positions to an upper level Placement +void DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix*& mat) { + if ( !mat ) mat = new TGeoHMatrix(*gGeoIdentity); + placementTrafo(nodes,inverse,*mat); +} + +/// Update cached matrix to transform to positions to an upper level Placement +void DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix& mat) { + mat = *gGeoIdentity; + if (nodes.size() > 0) { + for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) { + const PlacedVolume& p = nodes[i]; + mat.MultiplyLeft(p->GetMatrix()); + } + if ( inverse ) mat = mat.Inverse(); } - auto_ptr<TGeoHMatrix> mat(new TGeoHMatrix(*gGeoIdentity)); - for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) { - const PlacedVolume& p = nodes[i]; - TGeoMatrix* m = p->GetMatrix(); - mat->MultiplyLeft(m); +} + +/// Find a given node in the hierarchy starting from the top node (absolute placement!) +PlacedVolume DetectorTools::findNode(PlacedVolume top_place, const std::string& place) { + TGeoNode* top = top_place.ptr(); + const char* path = place.c_str(); + // Check if a geometry path is valid without changing the state of the navigator. + Int_t length = strlen(path); + if (!length) return 0; + TString spath = path; + TGeoVolume *vol; + // Check first occurance of a '/' + Int_t ind1 = spath.Index("/"); + if (ind1<0) { + // No '/' so we check directly the path against the name of the top + if ( strcmp(path,top->GetName()) ) return 0; + return top; } - if ( inverse ) { - auto_ptr<TGeoHMatrix> inv(new TGeoHMatrix(mat->Inverse())); - mat = inv; + Int_t ind2 = ind1; + Bool_t end = kFALSE; + if (ind1>0) ind1 = -1; // no trailing '/' + else ind2 = spath.Index("/", ind1+1); + + if (ind2<0) ind2 = length; + TString name(spath(ind1+1, ind2-ind1-1)); + if ( name == top->GetName() ) { + if (ind2>=length-1) return top; + ind1 = ind2; + } + else { + return 0; + } + TGeoNode *node = top; + // Deeper than just top level + while (!end) { + ind2 = spath.Index("/", ind1+1); + if (ind2<0) { + ind2 = length; + end = kTRUE; + } + vol = node->GetVolume(); + name = spath(ind1+1, ind2-ind1-1); + node = vol->GetNode(name.Data()); + if (!node) + return 0; + else if (ind2>=length-1) + return node; + ind1 = ind2; } - return mat.release(); + return node; } diff --git a/DDCore/src/Evaluator/setSystemOfUnits.cpp b/DDCore/src/Evaluator/setSystemOfUnits.cpp index a8d15dd49..e785c411b 100644 --- a/DDCore/src/Evaluator/setSystemOfUnits.cpp +++ b/DDCore/src/Evaluator/setSystemOfUnits.cpp @@ -120,8 +120,9 @@ void Evaluator::setSystemOfUnits(double meter, // Pressure // --- honors Blaise Pascal (1623-1662) of France const double Pa = N / (m*m); - setVariable("pascal", Pa); - setVariable("Pa", Pa); + setVariable("pascal", Pa); + setVariable("Pa", Pa); + setVariable("hPa", 100.0*Pa); const double atm = 101325. * Pa; setVariable("atmosphere", atm); diff --git a/DDCore/src/Exceptions.cpp b/DDCore/src/Exceptions.cpp new file mode 100644 index 000000000..339bafab1 --- /dev/null +++ b/DDCore/src/Exceptions.cpp @@ -0,0 +1,25 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Exceptions.h" +#include "DD4hep/Primitives.h" + +using namespace std; +using namespace DD4hep; + +string unrelated_type_error::msg(const type_info& typ1, const type_info& typ2, const string& text) { + string m = "The types " + typeName(typ1) + " and " + typeName(typ2) + " are not related. " + text; + return m; +} + +string unrelated_value_error::msg(const type_info& typ, const string& text) { + string m = "The type " + typeName(typ) + " cannot be converted: " + text; + return m; +} diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index c46aa80ca..acd124e43 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -18,8 +18,6 @@ #include "cxxabi.h" #endif -class TObject; - namespace DD4hep { XmlTools::Evaluator& evaluator(); } @@ -159,141 +157,6 @@ namespace DD4hep { } } -static const std::string __typeinfoName(const std::type_info& tinfo) { - const char* class_name = tinfo.name(); - std::string result; -#ifdef WIN32 - size_t off = 0; - if ( ::strncmp(class_name, "class ", 6) == 0 ) { - // The returned name is prefixed with "class " - off = 6; - } - if ( ::strncmp(class_name, "struct ", 7) == 0 ) { - // The returned name is prefixed with "struct " - off = 7; - } - if ( off != std::string::npos ) { - std::string tmp = class_name + off; - size_t loc = 0; - while( (loc = tmp.find("class ")) != std::string::npos ) { - tmp.erase(loc, 6); - } - loc = 0; - while( (loc = tmp.find("struct ")) != std::string::npos ) { - tmp.erase(loc, 7); - } - result = tmp; - } - else { - result = class_name; - } - // Change any " *" to "*" - while ( (off=result.find(" *")) != std::string::npos ) { - result.replace(off, 2, "*"); - } - // Change any " &" to "&" - while ( (off=result.find(" &")) != std::string::npos ) { - result.replace(off, 2, "&"); - } -#elif defined(sun) - result = class_name; -#elif !defined(__ICC) - if (::strlen(class_name) == 1) { - // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf - // for details - switch (class_name[0]) { - case 'v': - result = "void"; - break; - case 'w': - result = "wchar_t"; - break; - case 'b': - result = "bool"; - break; - case 'c': - result = "char"; - break; - case 'h': - result = "unsigned char"; - break; - case 's': - result = "short"; - break; - case 't': - result = "unsigned short"; - break; - case 'i': - result = "int"; - break; - case 'j': - result = "unsigned int"; - break; - case 'l': - result = "long"; - break; - case 'm': - result = "unsigned long"; - break; - case 'x': - result = "long long"; - break; - case 'y': - result = "unsigned long long"; - break; - case 'n': - result = "__int128"; - break; - case 'o': - result = "unsigned __int128"; - break; - case 'f': - result = "float"; - break; - case 'd': - result = "double"; - break; - case 'e': - result = "long double"; - break; - case 'g': - result = "__float128"; - break; - case 'z': - result = "ellipsis"; - break; - } - } - else { - char buff[16 * 1024]; - size_t len = sizeof(buff); - int status = 0; - result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status); - } -#else - result = class_name; - throw std::runtime_error("CXXABI is missing for ICC!"); -#endif - return result; -} - -string DD4hep::typeName(const type_info& typ) { - return __typeinfoName(typ); -} - -void DD4hep::invalidHandleError(const type_info& type) { - throw runtime_error("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]"); -} - -void DD4hep::invalidHandleAssignmentError(const type_info& from, const type_info& to) { - string msg = "Wrong assingment from "; - msg += typeName(from); - msg += " to "; - msg += typeName(to); - msg += " not possible!!"; - throw runtime_error(msg); -} - #include "DDSegmentation/Segmentation.h" typedef DDSegmentation::Segmentation _Segmentation; //INSTANTIATE_UNNAMED(_Segmentation); @@ -344,6 +207,7 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoNodeOffset); #include "TGeoTube.h" #include "TGeoCone.h" #include "TGeoArb8.h" +#include "TGeoTrd1.h" #include "TGeoTrd2.h" #include "TGeoParaboloid.h" #include "TGeoSphere.h" @@ -351,6 +215,7 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoNodeOffset); #include "TGeoBoolNode.h" #include "TGeoVolume.h" #include "TGeoCompositeShape.h" +#include "TGeoShapeAssembly.h" DD4HEP_INSTANTIATE_HANDLE(TGeoVolume); DD4HEP_INSTANTIATE_HANDLE(TGeoBBox); DD4HEP_INSTANTIATE_HANDLE(TGeoCone); @@ -363,16 +228,23 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoPgon); DD4HEP_INSTANTIATE_HANDLE(TGeoTube); DD4HEP_INSTANTIATE_HANDLE(TGeoTubeSeg); DD4HEP_INSTANTIATE_HANDLE(TGeoTrap); +DD4HEP_INSTANTIATE_HANDLE(TGeoTrd1); DD4HEP_INSTANTIATE_HANDLE(TGeoTrd2); DD4HEP_INSTANTIATE_HANDLE(TGeoSphere); DD4HEP_INSTANTIATE_HANDLE(TGeoTorus); DD4HEP_INSTANTIATE_HANDLE(TGeoShape); +DD4HEP_INSTANTIATE_HANDLE(TGeoShapeAssembly); DD4HEP_INSTANTIATE_HANDLE(TGeoCompositeShape); // Volume Placements (needed by "Volumes.cpp") #include "TGeoPhysicalNode.h" DD4HEP_INSTANTIATE_HANDLE(TGeoPhysicalNode); +#include "TGeoBoolNode.h" +DD4HEP_INSTANTIATE_HANDLE_UNNAMED(TGeoUnion); +DD4HEP_INSTANTIATE_HANDLE_UNNAMED(TGeoIntersection); +DD4HEP_INSTANTIATE_HANDLE_UNNAMED(TGeoSubtraction); + // Replicated Volumes (needed by "Volumes.cpp") #include "TGeoPatternFinder.h" DD4HEP_INSTANTIATE_HANDLE_UNNAMED(TGeoPatternFinder); diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 242f845f7..ebc5d4371 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -11,6 +11,7 @@ #include "DD4hep/Printout.h" #include "DD4hep/GeoHandler.h" #include "DD4hep/InstanceCount.h" +#include "DD4hep/objects/DetectorInterna.h" #include "LCDDImp.h" // C/C++ include files @@ -55,14 +56,6 @@ namespace { m_t = BUILD_NONE; } }; - - typedef pair<int,void(*)(void*)> ExtensionEntry; - typedef map<const type_info*, ExtensionEntry> ExtensionMap; - static int s_extensionID = 0; - ExtensionMap& lcdd_extensions() { - static ExtensionMap s_map; - return s_map; - } static LCDD* s_lcdd = 0; } @@ -83,8 +76,6 @@ void lcdd_unexpected(){ } } - - LCDD& LCDD::getInstance() { if (!s_lcdd) s_lcdd = new LCDDImp(); @@ -100,12 +91,14 @@ void LCDD::destroyInstance() { /// Default constructor LCDDImp::LCDDImp() - : m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global"), m_buildType(BUILD_NONE) { + : m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global"), m_buildType(BUILD_NONE), + m_extensions(typeid(LCDDImp)) +{ std::set_unexpected( lcdd_unexpected ) ; std::set_terminate( lcdd_unexpected ) ; - InstanceCount::increment(this); + InstanceCount::increment(this); m_properties = new Properties(); if (0 == gGeoManager) { gGeoManager = new TGeoManager("world", "LCDD Geometry"); @@ -133,6 +126,7 @@ LCDDImp::LCDDImp() /// Standard destructor LCDDImp::~LCDDImp() { + m_extensions.clear(); destroyHandle(m_world); destroyHandle(m_field); destroyHandle(m_header); @@ -160,54 +154,17 @@ LCDDImp::~LCDDImp() { /// Add an extension object to the LCDD instance void* LCDDImp::addUserExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { - Extensions::iterator j = m_extensions.find(&info); - if (j == m_extensions.end()) { - ExtensionMap& m = lcdd_extensions(); - ExtensionMap::iterator i = m.find(&info); - if (i == m.end()) { - ExtensionEntry entry(++s_extensionID,destruct); - m.insert(make_pair(&info, entry)); - } - return m_extensions[&info] = ptr; - } - throw runtime_error("DD4hep: LCDD::addUserExtension: The object " - " already has an extension of type:" + string(info.name()) + "."); + return m_extensions.addExtension(ptr,info,destruct); } /// Remove an existing extension object from the LCDD instance void* LCDDImp::removeUserExtension(const std::type_info& info, bool destroy) { - Extensions::iterator j = m_extensions.find(&info); - if (j != m_extensions.end()) { - void *ptr = (*j).second; - if ( destroy ) { - ExtensionMap& m = lcdd_extensions(); - ExtensionMap::iterator i = m.find(&info); - if (i != m.end()) { - ExtensionEntry& e = (*i).second; - (*e.second)((*j).second); - printout(INFO,"LCDD","Destructed LCDD Extension: %p of type %s",ptr,info.name()); - ptr = 0; - } - } - else { - printout(INFO,"LCDD","Detached LCDD Extension: %p of type %s",ptr,info.name()); - } - m_extensions.erase(j); - return ptr; - } - throw runtime_error("DD4hep: LCDD::removeUserExtension: The object " - " of type " + string(info.name()) + " is not present."); + return m_extensions.removeExtension(info,destroy); } /// Access an existing extension object from the LCDD instance void* LCDDImp::userExtension(const std::type_info& info, bool alert) const { - Extensions::const_iterator j = m_extensions.find(&info); - if ( j != m_extensions.end() ) - return (*j).second; - else if ( !alert ) - return 0; - throw runtime_error("DD4hep: LCDD::userExtension: The object " - " has no extension of type:" + string(info.name()) + "."); + return m_extensions.extension(info,alert); } Volume LCDDImp::pickMotherVolume(const DetElement&) const { // throw if not existing @@ -404,10 +361,11 @@ void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) { cmd = "lcdd.fromXML('" + xmlfile + "')"; TPython::Exec(cmd.c_str()); #else - XML::Handle_t xml_root = XML::DocumentHandler().load(xmlfile).root(); - string tag = xml_root.tag(); try { LCDD* lcdd = this; + XML::DocumentHolder doc(XML::DocumentHandler().load(xmlfile)); + XML::Handle_t xml_root = doc.root(); + string tag = xml_root.tag(); string type = tag + "_XML_reader"; long result = PluginService::Create<long>(type, lcdd, &xml_root); if (0 == result) { diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h index 247a31213..515a006ca 100644 --- a/DDCore/src/LCDDImp.h +++ b/DDCore/src/LCDDImp.h @@ -12,6 +12,7 @@ // Framework include files #include "DD4hep/LCDD.h" +#include "DD4hep/ObjectExtensions.h" // Forward declarations class TGeoManager; @@ -32,7 +33,7 @@ namespace DD4hep { class LCDDImp: public LCDD { private: /// Disable copy constructor - LCDDImp(const LCDDImp&) { + LCDDImp(const LCDDImp&) : m_extensions(typeid(LCDDImp)) { } /// Disable assignment operator LCDDImp& operator=(const LCDDImp&) { @@ -100,8 +101,7 @@ namespace DD4hep { LCDDBuildType m_buildType; /// Definition of the extension type - typedef std::map<const std::type_info*, void*> Extensions; - Extensions m_extensions; + ObjectExtensions m_extensions; /// Default constructor LCDDImp(); diff --git a/DDCore/src/NamedObject.cpp b/DDCore/src/NamedObject.cpp new file mode 100644 index 000000000..9a2ee0966 --- /dev/null +++ b/DDCore/src/NamedObject.cpp @@ -0,0 +1,59 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/objects/NamedObject.h" +#include "DD4hep/Handle.inl" +#include "TObject.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +DD4HEP_INSTANTIATE_HANDLE_NAMED(NamedObject); + +/// Standard constructor +NamedObject::NamedObject() { +} + +/// Initializing constructor +NamedObject::NamedObject(const char* nam, const char* typ) + : name(nam ? nam : ""), type(typ ? typ : "") +{ +} + +/// Initializing constructor +NamedObject::NamedObject(const std::string& nam) + : name(nam), type() +{ +} + +/// Initializing constructor +NamedObject::NamedObject(const std::string& nam, const std::string& typ) + : name(nam), type(typ) +{ +} + +/// Copy constructor +NamedObject::NamedObject(const NamedObject& c) : name(c.name), type(c.type) { +} + +/// Default destructor +NamedObject::~NamedObject() { +} + +/// Assignment operator +NamedObject& NamedObject::operator=(const NamedObject& c) { + if ( this != &c ) { + name = c.name; + type = c.type; + } + return *this; +} + diff --git a/DDCore/src/ObjectExtensions.cpp b/DDCore/src/ObjectExtensions.cpp new file mode 100644 index 000000000..1625aa926 --- /dev/null +++ b/DDCore/src/ObjectExtensions.cpp @@ -0,0 +1,127 @@ +// $Id: Detector.cpp 1087 2014-04-09 12:25:51Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/ObjectExtensions.h" +#include "DD4hep/InstanceCount.h" +#include "DD4hep/Primitives.h" + +// C/C++ include files +#include <stdexcept> + +using namespace std; +using namespace DD4hep; + +namespace { + static int s_extensionID = 0; + ObjectExtensions::ExtensionMap* extensionContainer(const type_info& typ) { + static map<const type_info*, ObjectExtensions::ExtensionMap> s_map; + return &s_map[&typ]; + } +} + +/// Default constructor +ObjectExtensions::ObjectExtensions(const type_info& parent_type) { + extensionMap = extensionContainer(parent_type); + InstanceCount::increment(this); +} + +/// Default destructor +ObjectExtensions::~ObjectExtensions() { + clear(); + InstanceCount::decrement(this); +} + +/// Internal object destructor: release extension object(s) +void ObjectExtensions::clear() { + for (Extensions::iterator i = extensions.begin(); i != extensions.end(); ++i) { + void* ptr = (*i).second; + if (ptr) { + ExtensionMap::iterator j = extensionMap->find((*i).first); + if (j != extensionMap->end()) { + Entry& e = (*j).second; + if (e.destruct) + (*(e.destruct))(ptr); + } + } + } + extensions.clear(); +} + +/// Copy object extensions from another object +void ObjectExtensions::copyFrom(const Extensions& ext, void* arg) { + for (Extensions::const_iterator i = ext.begin(); i != ext.end(); ++i) { + const type_info* info = (*i).first; + ExtensionMap::const_iterator j = extensionMap->find(info); + const Entry& e = (*j).second; + extensions[info] = (*(e.copy))((*i).second, arg); + } +} + +/// Add an extension object to the detector element +void* ObjectExtensions::addExtension(void* ptr, const type_info& info, destruct_t dtor) { + return addExtension(ptr, info, 0, dtor); +} +/// Add an extension object to the detector element +void* ObjectExtensions::addExtension(void* ptr, const type_info& info, copy_t ctor, destruct_t dtor) { + Extensions::iterator j = extensions.find(&info); + if (j == extensions.end()) { + ExtensionMap::iterator i = extensionMap->find(&info); + if (i == extensionMap->end()) { + Entry entry; + entry.destruct = dtor; + entry.copy = ctor; + entry.id = ++s_extensionID; + extensionMap->insert(make_pair(&info, entry)); + i = extensionMap->find(&info); + } + return extensions[&info] = ptr; + } + throw runtime_error("DD4hep: addExtension: Object already has an extension of type:" + typeName(info) + "."); +} + +/// Remove an existing extension object from the instance +void* ObjectExtensions::removeExtension(const std::type_info& info, bool destroy) { + Extensions::iterator j = extensions.find(&info); + if (j != extensions.end()) { + void *ptr = (*j).second; + if ( destroy ) { + ExtensionMap::iterator i = extensionMap->find(&info); + if (i != extensionMap->end()) { + Entry& e = (*i).second; + (*e.destruct)((*j).second); + ptr = 0; + } + } + extensions.erase(j); + return ptr; + } + throw runtime_error("DD4hep: removeExtension: The object of type " + typeName(info) + " is not present."); +} + +/// Access an existing extension object from the detector element +void* ObjectExtensions::extension(const type_info& info) const { + Extensions::const_iterator j = extensions.find(&info); + if (j != extensions.end()) { + return (*j).second; + } + throw runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + "."); +} + +/// Access an existing extension object from the detector element +void* ObjectExtensions::extension(const type_info& info, bool alert) const { + Extensions::const_iterator j = extensions.find(&info); + if (j != extensions.end()) { + return (*j).second; + } + else if ( !alert ) + return 0; + throw runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + "."); +} + diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp index 63991804a..0147bef54 100644 --- a/DDCore/src/Objects.cpp +++ b/DDCore/src/Objects.cpp @@ -8,6 +8,7 @@ //==================================================================== #include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" #include "DD4hep/IDDescriptor.h" #include "DD4hep/InstanceCount.h" @@ -304,7 +305,7 @@ string VisAttr::toString() const { char text[256]; ::snprintf(text, sizeof(text), "%-20s RGB:%-8s [%d] %7.2f Style:%d %d ShowDaughters:%3s Visible:%3s", ptr()->GetName(), col->AsHexString(), obj->color, col->GetAlpha(), int(obj->drawingStyle), int(obj->lineStyle), - obj->showDaughters ? "YES" : "NO", obj->visible ? "YES" : "NO"); + yes_no(obj->showDaughters), yes_no(obj->visible)); return text; } diff --git a/DDCore/src/Primitives.cpp b/DDCore/src/Primitives.cpp new file mode 100644 index 000000000..3316b1ac4 --- /dev/null +++ b/DDCore/src/Primitives.cpp @@ -0,0 +1,277 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Primitives.h" +#include "DD4hep/Exceptions.h" +#include "DD4hep/Printout.h" + +// C/C++ include files +#include <stdexcept> +#include <cstring> +#include <map> + +#if defined(__linux) || defined(__APPLE__) +#include <cxxabi.h> +#ifndef __APPLE__ +typedef abi::__class_type_info class_t; +using abi::__dynamic_cast; +#endif +#endif + +using namespace std; +using namespace DD4hep; + +static const std::string __typeinfoName(const std::type_info& tinfo) { + const char* class_name = tinfo.name(); + std::string result; +#ifdef WIN32 + size_t off = 0; + if ( ::strncmp(class_name, "class ", 6) == 0 ) { + // The returned name is prefixed with "class " + off = 6; + } + if ( ::strncmp(class_name, "struct ", 7) == 0 ) { + // The returned name is prefixed with "struct " + off = 7; + } + if ( off != std::string::npos ) { + std::string tmp = class_name + off; + size_t loc = 0; + while( (loc = tmp.find("class ")) != std::string::npos ) { + tmp.erase(loc, 6); + } + loc = 0; + while( (loc = tmp.find("struct ")) != std::string::npos ) { + tmp.erase(loc, 7); + } + result = tmp; + } + else { + result = class_name; + } + // Change any " *" to "*" + while ( (off=result.find(" *")) != std::string::npos ) { + result.replace(off, 2, "*"); + } + // Change any " &" to "&" + while ( (off=result.find(" &")) != std::string::npos ) { + result.replace(off, 2, "&"); + } +#elif defined(sun) + result = class_name; +#elif !defined(__ICC) + if (::strlen(class_name) == 1) { + // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf + // for details + switch (class_name[0]) { + case 'v': + result = "void"; + break; + case 'w': + result = "wchar_t"; + break; + case 'b': + result = "bool"; + break; + case 'c': + result = "char"; + break; + case 'h': + result = "unsigned char"; + break; + case 's': + result = "short"; + break; + case 't': + result = "unsigned short"; + break; + case 'i': + result = "int"; + break; + case 'j': + result = "unsigned int"; + break; + case 'l': + result = "long"; + break; + case 'm': + result = "unsigned long"; + break; + case 'x': + result = "long long"; + break; + case 'y': + result = "unsigned long long"; + break; + case 'n': + result = "__int128"; + break; + case 'o': + result = "unsigned __int128"; + break; + case 'f': + result = "float"; + break; + case 'd': + result = "double"; + break; + case 'e': + result = "long double"; + break; + case 'g': + result = "__float128"; + break; + case 'z': + result = "ellipsis"; + break; + } + } + else { + char buff[16 * 1024]; + size_t len = sizeof(buff); + int status = 0; + result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status); + } +#else + result = class_name; + throw std::runtime_error("CXXABI is missing for ICC!"); +#endif + return result; +} + +string DD4hep::typeName(const type_info& typ) { + return __typeinfoName(typ); +} + +void DD4hep::invalidHandleError(const type_info& type) { + throw runtime_error("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]"); +} + +void DD4hep::invalidHandleAssignmentError(const type_info& from, const type_info& to) { + string msg = "Wrong assingment from "; + msg += typeName(from); + msg += " to "; + msg += typeName(to); + msg += " not possible!!"; + throw runtime_error(msg); +} + +/// Throw exception when handles are check for validity +void DD4hep::notImplemented(const std::string& msg) { + string m = "The requested feature " + msg + " is not implemented!"; + throw runtime_error(m); +} + +void DD4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text) { + if (typ1 != typ2) { + throw unrelated_type_error(typ1, typ2, text); + } +} + +/// Initializing Constructor +ComponentCast::ComponentCast(const std::type_info& t, destroy_t d, cast_t c) + : type(t), destroy(d), cast(c) { +#ifdef __APPLE__ + abi_class = 0; +#else + abi_class = dynamic_cast<const class_t*>(&type); + if (!abi_class) { + throw std::runtime_error("Class type " + typeName(type) + " is not an abi object type!"); + } +#endif +} + +/// Defautl destructor +ComponentCast::~ComponentCast() { +} + +#if 0 +// Dynamic cast runtime. +// src2dst has the following possible values +// >-1: src_type is a unique public non-virtual base of dst_type +// dst_ptr + src2dst == src_ptr +// -1: unspecified relationship +// -2: src_type is not a public base of dst_type +// -3: src_type is a multiple public non-virtual base of dst_type +extern "C" void* +__dynamic_cast(const void* __src_ptr,// Starting object. + const abi::__class_type_info* __src_type,// Static type of object. + const abi::__class_type_info* __dst_type,// Desired target type. + ptrdiff_t __src2dst);// How src and dst are related. +#endif + +#ifndef __APPLE__ +static inline void* cast_wrap(const void* p, + const abi::__class_type_info* src, + const abi::__class_type_info* dst, + ptrdiff_t src2dst) +{ + return abi::__dynamic_cast(p,src,dst,src2dst); +} +#endif + +/// Apply cast using typeinfo instead of dynamic_cast +void* ComponentCast::apply_dynCast(const ComponentCast& to, const void* ptr) const { + if (&to == this) { + return (void*) ptr; + } +#ifdef __APPLE__ + // First try down cast + void *r = (*to.cast)(ptr); + if (r) + return r; + { + // Now try the up-cast + r = (*cast)(ptr); +#else + const class_t* src_type = (const class_t*)to.abi_class; + if (src_type) { + // First try down cast + void *r = cast_wrap(ptr, src_type, (const class_t*) abi_class, -1); + if (r) + return r; + // Now try the up-cast + r = cast_wrap(ptr, (const class_t*) abi_class, src_type, -1); +#endif + if (r) + return r; + throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!"); + } + throw unrelated_type_error(type, to.type, "Target type is not an abi class type!"); +} + +/// Apply cast using typeinfo instead of dynamic_cast +void* ComponentCast::apply_upCast(const ComponentCast& to, const void* ptr) const { + if (&to == this) { + return (void*) ptr; + } + return apply_dynCast(to, ptr); +} + +/// Apply cast using typeinfo instead of dynamic_cast +void* ComponentCast::apply_downCast(const ComponentCast& to, const void* ptr) const { + if (&to == this) { + return (void*) ptr; + } +#ifdef __APPLE__ + void *r = (*to.cast)(ptr); + { +#else + const class_t* src_type = (const class_t*)to.abi_class; + if (src_type) { + void *r = cast_wrap(ptr, src_type, (const class_t*)abi_class, -1); +#endif + if (r) + return r; + throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!"); + } + throw unrelated_type_error(type, to.type, "Target type is not an abi class type!"); +} + diff --git a/DDCore/src/Printout.cpp b/DDCore/src/Printout.cpp index c558957a0..00ece2231 100644 --- a/DDCore/src/Printout.cpp +++ b/DDCore/src/Printout.cpp @@ -169,6 +169,11 @@ DD4hep::PrintLevel DD4hep::setPrintLevel(PrintLevel new_level) { return old; } +/// Access the current printer level +DD4hep::PrintLevel DD4hep::printLevel() { + return print_lvl; +} + /// Customize printer function void DD4hep::setPrinter(void* arg, output_function_t fcn) { print_arg = arg; @@ -242,9 +247,9 @@ namespace DD4hep { bool env = plc.isValid(); bool mat = plc.isValid(); ::snprintf(text, sizeof(text), "ID:%-3d Combine Hits:%3s Material:%s Envelope:%s VisAttr:%s", sd.id(), - yes_no(sd.combineHits()), mat ? plc.material()->GetName() : yes_no(mat), + yes_no(sd.combineHits()), mat ? plc.material().name() : yes_no(mat), env ? plc.motherVol()->GetName() : yes_no(env), yes_no(vis)); - os << prefix << "+= DetElement: " << val->GetName() << " " << val.type() << endl; + os << prefix << "+= DetElement: " << val.name() << " " << val.type() << endl; os << prefix << "| " << text << endl; if (vis) { @@ -253,8 +258,9 @@ namespace DD4hep { TColor* col = gROOT->GetColor(v->color); char text[256]; ::snprintf(text, sizeof(text), " RGB:%-8s [%d] %7.2f Style:%d %d ShowDaughters:%3s Visible:%3s", col->AsHexString(), - v->color, col->GetAlpha(), int(v->drawingStyle), int(v->lineStyle), v->showDaughters ? "YES" : "NO", - v->visible ? "YES" : "NO"); + v->color, col->GetAlpha(), int(v->drawingStyle), + int(v->lineStyle), yes_no(v->showDaughters), + yes_no(v->visible)); os << prefix << "| VisAttr: " << setw(32) << left << attr.name() << text << endl; } if (plc.isValid()) { diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp index 9aa45cff8..0027ca29c 100644 --- a/DDCore/src/Readout.cpp +++ b/DDCore/src/Readout.cpp @@ -78,18 +78,3 @@ void Readout::setSegmentation(const Segmentation& seg) const { Segmentation Readout::segmentation() const { return object<Object>().segmentation; } - -/// Standard constructor -Conditions::Object::Object() { - InstanceCount::increment(this); -} - -/// Default destructor -Conditions::Object::~Object() { - InstanceCount::decrement(this); -} - -/// Initializing constructor to create a new object -Conditions::Conditions(const LCDD& /* lcdd */, const string& nam) { - assign(new Object(), nam, "conditions"); -} diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index 1a78d6082..520526c42 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -18,6 +18,7 @@ #include "TGeoPcon.h" #include "TGeoPgon.h" #include "TGeoTube.h" +#include "TGeoTrd1.h" #include "TGeoTrd2.h" #include "TGeoArb8.h" #include "TGeoCone.h" @@ -162,6 +163,11 @@ Cone& Cone::setDimensions(double z, double rmin1, double rmax1, double rmin2, do return *this; } +/// Constructor to create a new anonymous object with attribute initialization +Trapezoid::Trapezoid(double x1, double x2, double y1, double y2, double z) { + make(x1,x2,y1,y2,z); +} + /// Constructor to be used when creating a new object with attribute initialization void Trapezoid::make(double x1, double x2, double y1, double y2, double z) { _assign(new TGeoTrd2(x1, x2, y1, y2, z ), "", "trd2", true); @@ -373,5 +379,6 @@ INSTANTIATE(TGeoTorus); INSTANTIATE(TGeoTube); INSTANTIATE(TGeoTubeSeg); INSTANTIATE(TGeoTrap); +INSTANTIATE(TGeoTrd1); INSTANTIATE(TGeoTrd2); INSTANTIATE(TGeoCompositeShape); diff --git a/DDCore/src/ToStream.cpp b/DDCore/src/ToStream.cpp new file mode 100644 index 000000000..d6c31b30a --- /dev/null +++ b/DDCore/src/ToStream.cpp @@ -0,0 +1,89 @@ +// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/ToStream.h" +#include "XML/Evaluator.h" + +// C/C++ include files +#include <stdexcept> + +namespace DD4hep { + XmlTools::Evaluator& g4Evaluator(); +} +namespace { + XmlTools::Evaluator& eval(DD4hep::g4Evaluator()); +} + +using namespace std; +//============================================================================== +namespace DD4hep { namespace Parsers { + template <typename T> T evaluate_string(const string& value) { + throw "Bad undefined call"; + } + + template <> double evaluate_string<double>(const string& value) { + double result = eval.evaluate(value.c_str()); + if (eval.status() != XmlTools::Evaluator::OK) { + cerr << value << ": "; + eval.print_error(); + throw runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value); + } + return result; + } + template <> float evaluate_string<float>(const string& value) { + double result = eval.evaluate(value.c_str()); + if (eval.status() != XmlTools::Evaluator::OK) { + cerr << value << ": "; + eval.print_error(); + throw runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value); + } + return (float) result; + } + } +} + +// ============================================================================ +// print XYZ-point +ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZPoint& obj, ostream& s) { + s << "( "; + toStream(obj.X () , s ); + s << " , "; + toStream(obj.Y () , s ); + s << " , "; + toStream(obj.Z () , s ); + s << " )"; + return s; +} +// ============================================================================ +// print XYZ-vector +ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZVector& obj, ostream& s) { + s << "( "; + toStream(obj.X () , s ); + s << " , "; + toStream(obj.Y () , s ); + s << " , "; + toStream(obj.Z () , s ); + s << " )"; + return s; +} +// ============================================================================ +// print LorentzVector +ostream& DD4hep::Utils::toStream(const ROOT::Math::PxPyPzEVector& obj, ostream& s){ + s << "( "; + toStream(obj.Px () , s , 12 ); + s << " , "; + toStream(obj.Py () , s , 12 ); + s << " , "; + toStream(obj.Pz () , s , 13 ); + s << " , "; + toStream(obj.E () , s , 14 ); + s << " )"; + return s; +} diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp index dbc399219..46d1ea810 100644 --- a/DDCore/src/VolumeManager.cpp +++ b/DDCore/src/VolumeManager.cpp @@ -10,6 +10,7 @@ #include "DD4hep/VolumeManager.h" #include "DD4hep/Printout.h" #include "DD4hep/LCDD.h" +#include "DD4hep/objects/DetectorInterna.h" // C/C++ includes #include <set> @@ -21,14 +22,11 @@ using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; -#define VOLUME_IDENTIFIER(id,mask) id -//#define VOLUME_IDENTIFIER(id,mask) id,mask - namespace { struct Populator { + typedef PlacedVolume::VolIDs VolIDs; typedef vector<const TGeoNode*> Chain; - /// Reference to the LCDD instance LCDD& m_lcdd; /// Reference to the volume manager to be populated @@ -49,7 +47,7 @@ namespace { if (pv.isValid()) { Chain chain; SensitiveDetector sd; - PlacedVolume::VolIDs ids; + VolIDs ids; m_entries.clear(); scanPhysicalVolume(de, de, pv, ids, sd, chain); continue; @@ -75,15 +73,15 @@ namespace { return DetElement(); } /// Scan a single physical volume and look for sensitive elements below - size_t scanPhysicalVolume(DetElement parent, DetElement e, PlacedVolume pv, PlacedVolume::VolIDs ids, SensitiveDetector& sd, + size_t scanPhysicalVolume(DetElement parent, DetElement e, PlacedVolume pv, VolIDs ids, SensitiveDetector& sd, Chain& chain) { const TGeoNode* node = pv.ptr(); size_t count = 0; if (node) { Volume vol = pv.volume(); chain.push_back(node); - PlacedVolume::VolIDs pv_ids = pv.volIDs(); - ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end()); + VolIDs pv_ids = pv.volIDs(); + ids.VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end()); bool got_readout = false; if (vol.isSensitive()) { sd = vol.sensitiveDetector(); @@ -95,7 +93,7 @@ namespace { } else { printout(WARNING, "VolumeManager", "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p", - parent.name(), pv.volume().name(), sd.ptr()); + parent.name(), pv.volume().name(), sd.ptr()); } } for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) { @@ -139,24 +137,19 @@ namespace { } return count; } - pair<VolumeID, VolumeID> encoding(const IDDescriptor iddesc, const PlacedVolume::VolIDs& ids) const { - //VolumeID volume_id = ~0x0ULL, mask = 0; + pair<VolumeID, VolumeID> encoding(const IDDescriptor iddesc, const VolIDs& ids) const { VolumeID volume_id = 0, mask = 0; - for (PlacedVolume::VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { + for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { const PlacedVolume::VolID& id = (*i); IDDescriptor::Field f = iddesc.field(id.first); VolumeID msk = f->mask(); int offset = f->offset(); - // This pads the unused bits with '1' instead of '0': - // volume_id &= ~msk; volume_id |= f->value(id.second << offset) << offset; mask |= msk; - //volume_id &= f.encode(id.second); - //mask |= f.mask; } return make_pair(volume_id, mask); } - void add_entry(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode* n, const PlacedVolume::VolIDs& ids, + void add_entry(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode* n, const VolIDs& ids, const Chain& nodes) { Readout ro = sd.readout(); IDDescriptor iddesc = ro.idSpec(); @@ -166,12 +159,11 @@ namespace { if (m_entries.find(code.first) == m_entries.end()) { // This is the block, we effectively have to save for each physical volume with a VolID VolumeManager::Context* context = new VolumeManager::Context; - DetElement::Object& o = parent._data(); context->identifier = code.first; context->mask = code.second; context->detector = parent; + context->placement = PlacedVolume(n); context->element = e; - context->placement = Ref_t(n); context->volID = ids; context->path = nodes; for (size_t i = nodes.size(); i > 1; --i) { // Omit the placement of the parent DetElement @@ -180,8 +172,7 @@ namespace { } context->toDetector = context->toWorld; context->toDetector.MultiplyLeft(nodes[0]->GetMatrix()); - context->toWorld.MultiplyLeft(o.worldTransformation()); - //if ( parent.id() == 8 ) print_node(sd,parent,e,n,ids,nodes); + context->toWorld.MultiplyLeft(&parent.worldTransformation()); if (!section.adoptPlacement(context)) { print_node(sd, parent, e, n, ids, nodes); } @@ -189,71 +180,8 @@ namespace { } } -#if 0 - void add_entry(DetElement parent, DetElement e,const TGeoNode* n, - const PlacedVolume::VolIDs& ids, const Chain& nodes) - { - Volume vol = PlacedVolume(n).volume(); - SensitiveDetector sd = vol.sensitiveDetector(); - add_entry(sd, parent,e,n,ids,nodes); - } - - void find_entry(DetElement parent, DetElement e,const TGeoNode* n, - const PlacedVolume::VolIDs& ids, const Chain& nodes) - { - Volume vol = PlacedVolume(n).volume(); - SensitiveDetector sd = vol.sensitiveDetector(); - Readout ro = sd.readout(); - IDDescriptor iddesc = ro.idSpec(); - pair<VolumeID,VolumeID> code = encoding(iddesc, ids); -#if 0 - VolumeID id = (VolumeID(rand())<<32) + VolumeID(rand()); - id &= ~code.second; - id |= code.second; - VolumeID volID = id&code.first; -#else - VolumeID volID = code.first; -#endif - - VolumeManager::Context* context = m_volManager.lookupContext(volID); - stringstream log; - if ( !context ) { - log << "CANNOT FIND volume:" - << " Ptr:" << (void*)n - << " [" << n->GetName() << "]" - << " ID:" << (void*)volID - << " Mask:" << (void*)code.second; - printout(ERROR,"VolumeManager",log.str().c_str()); - return; - } - else if ( context->placement.ptr() != n ) { - log << "FOUND WRONG volume:" - << " Ptr:" << (void*)context->placement.ptr() - << " instead of " << (void*)n - << " [" << context->placement.name() - << " instead of " << n->GetName() << "]" - << " ID:" << (void*)context->identifier - << " instead of " << (void*)volID; - printout(ERROR,"VolumeManager",log.str().c_str()); - return; - } - log << "Found volume:" - << " Ptr:" << (void*)context->placement.ptr() - << " [" << context->placement.name() << "]" - << " ID:" << (void*)context->identifier - << " Mask:" << (void*)context->mask; - printout(DEBUG,"VolumeManager",log.str().c_str()); - } - void print_node(DetElement parent, DetElement e, const TGeoNode* n, - const PlacedVolume::VolIDs& ids, const Chain& nodes) - { - Volume vol = PlacedVolume(n).volume(); - SensitiveDetector sd = vol.sensitiveDetector(); - print_node(sd, parent, e, n, ids, nodes); - } -#endif void print_node(SensitiveDetector sd, DetElement /* parent */, DetElement e, - const TGeoNode* n, const PlacedVolume::VolIDs& ids, const Chain& /* nodes */) + const TGeoNode* n, const VolIDs& ids, const Chain& /* nodes */) { static int s_count = 0; Readout ro = sd.readout(); @@ -268,13 +196,13 @@ namespace { stringstream log; log << s_count << ": " << e.name() << " de:" << e.ptr() << " ro:" << ro.ptr() << " pv:" << n->GetName() << " id:" << (void*) volume_id << " : "; - for (PlacedVolume::VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { + for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { const PlacedVolume::VolID& id = (*i); IDDescriptor::Field f = ro.idSpec().field(id.first); VolumeID value = f->value(volume_id); log << id.first << "=" << id.second << "," << value << " [" << f->offset() << "," << f->width() << "] "; } - log << " Sensitive:" << (sensitive ? "YES" : "NO"); + log << " Sensitive:" << yes_no(sensitive); printout(INFO, "VolumeManager", log.str().c_str()); #if 0 log.str(""); @@ -312,30 +240,32 @@ VolumeManager::Object::~Object() { subdetectors.clear(); } +/// Update callback when alignment has changed (called only for subdetectors....) +void VolumeManager::Object::update(unsigned int tags, DetElement& det, void* param) { + if ( DetElement::CONDITIONS_CHANGED == (tags&DetElement::CONDITIONS_CHANGED) ) + printout(INFO,"VolumeManager","+++ Conditions update %s param:%p",det.path().c_str(),param); + if ( DetElement::PLACEMENT_CHANGED == (tags&DetElement::PLACEMENT_CHANGED) ) + printout(INFO,"VolumeManager","+++ Alignment update %s param:%p",det.path().c_str(),param); + + for(Volumes::iterator i=volumes.begin(); i != volumes.end(); ++i) { + Context* c = (*i).second; + printout(INFO,"VolumeManager","+++ Alignment update %s",c->placement.name()); + + } +} + /// Search the locally cached volumes for a matching ID -VolumeManager::Context* VolumeManager::Object::search(const VolIdentifier& id) const { +VolumeManager::Context* VolumeManager::Object::search(const VolumeID& id) const { Context* context = 0; - VolIdentifier volume_id(id); + VolumeID volume_id(id); volume_id &= detMask; Volumes::const_iterator i = volumes.find(volume_id); if (i != volumes.end()) { context = (*i).second; } - //else if ( sysID == 8 ) { - // for(i=volumes.begin(); i!=volumes.end();++i) - // cout << (void*)(*i).first << " " << (*i).second->placement.name() << endl; - //} return context; } -/// Search the locally cached volumes for a matching physical volume -VolumeManager::Context* VolumeManager::Object::search(const PlacedVolume pv) const { - PhysVolumes::const_iterator i = phys_volumes.find(pv.ptr()); - if (i != phys_volumes.end()) - return (*i).second; - return 0; -} - /// Initializing constructor to create a new object VolumeManager::VolumeManager(LCDD& lcdd, const string& nam, DetElement elt, Readout ro, int flags) { Object* ptr = new Object(lcdd); @@ -366,7 +296,7 @@ VolumeManager VolumeManager::addSubdetector(DetElement detector, Readout ro) { throw runtime_error("DD4hep: VolumeManager::addSubdetector: Only subdetectors with a " "valid placement are allowed. [Invalid DetElement:" + det_name + "]"); } - PlacedVolume::VolIDs::Base::const_iterator vit = pv.volIDs().find("system"); + VolIDs::Base::const_iterator vit = pv.volIDs().find("system"); if (vit == pv.volIDs().end()) { throw runtime_error("DD4hep: VolumeManager::addSubdetector: Only subdetectors with " "valid placement VolIDs are allowed. [Invalid DetElement:" + det_name + "]"); @@ -388,6 +318,8 @@ VolumeManager VolumeManager::addSubdetector(DetElement detector, Readout ro) { mo.sysID = id.second; mo.detMask = mo.sysID; o.managers[mo.sysID] = m; + detector.callAtUpdate(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_DETECTOR, + &mo,&Object::update); } return (*i).second; } @@ -454,21 +386,20 @@ IDDescriptor VolumeManager::idSpec() const { bool VolumeManager::adoptPlacement(VolumeID /* sys_id */, Context* context) { stringstream err; Object& o = _data(); + VolumeID vid = context->identifier; PlacedVolume pv = context->placement; - VolIdentifier vid(VOLUME_IDENTIFIER(context->identifier,context->mask)); Volumes::iterator i = o.volumes.find(vid); #if 0 if ( (context->identifier&context->mask) != context->identifier ) { err << "Bad context mask:" << (void*)context->mask << " id:" << (void*)context->identifier << " pv:" << pv.name() << " Sensitive:" - << (pv.volume().isSensitive() ? "YES" : "NO") << endl; + << yes_no(pv.volume().isSensitive()) << endl; goto Fail; } #endif if (i == o.volumes.end()) { o.volumes[vid] = context; o.detMask |= context->mask; - //o.phys_volumes[pv.ptr()] = context; err << "Inserted new volume:" << setw(6) << left << o.volumes.size() << " Ptr:" << (void*) pv.ptr() << " [" << pv.name() << "]" << " ID:" << (void*) context->identifier << " Mask:" << (void*) context->mask; printout(DEBUG, "VolumeManager", err.str().c_str()); @@ -479,12 +410,12 @@ bool VolumeManager::adoptPlacement(VolumeID /* sys_id */, Context* context) { << " to detector " << o.detector.name() << " ptr:" << (void*) pv.ptr() << " Name:" << pv.name() - << " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO") << endl; + << " Sensitive:" << yes_no(pv.volume().isSensitive()) << endl; printout(ERROR, "VolumeManager", "%s", err.str().c_str()); err.str(""); err << " !!!!! ++++ VolIDS "; - const PlacedVolume::VolIDs::Base& ids = context->volID; - for (PlacedVolume::VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) + const VolIDs::Base& ids = context->volID; + for (VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) err << (*vit).first << "=" << (*vit).second << "; "; printout(ERROR, "VolumeManager", "%s", err.str().c_str()); err.str(""); @@ -495,15 +426,15 @@ bool VolumeManager::adoptPlacement(VolumeID /* sys_id */, Context* context) { << " to detector " << o.detector.name() << " ptr:" << (void*) pv.ptr() << " Name:" << pv.name() - << " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO") << endl; + << " Sensitive:" << yes_no(pv.volume().isSensitive()) << endl; printout(ERROR, "VolumeManager", "%s", err.str().c_str()); err.str(""); goto Fail; Fail: { err << " !!!!! ++++ VolIDS "; - const PlacedVolume::VolIDs::Base& ids = context->volID; - for (PlacedVolume::VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) + const VolIDs::Base& ids = context->volID; + for (VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) err << (*vit).first << "=" << (*vit).second << "; "; } printout(ERROR, "VolumeManager", "%s", err.str().c_str()); @@ -560,7 +491,7 @@ VolumeManager::Context* VolumeManager::lookupContext(VolumeID volume_id) const { if (!is_top && one_tree) { return VolumeManager(Ref_t(o.top)).lookupContext(volume_id); } - VolIdentifier id(VOLUME_IDENTIFIER(volume_id,~0x0ULL)); + VolumeID id = volume_id; /// First look in our own volume cache if the entry is found. c = o.search(id); if (c) diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index 8bad3afe6..020495a39 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -299,14 +299,14 @@ static TGeoVolume* _createTGeoVolumeAssembly(const string& name) { /// Default constructor PlacedVolume::Object::Object() - : TGeoExtension(), magic(0), refCount(0), volIDs(), detector() { + : TGeoExtension(), magic(0), refCount(0), volIDs() { magic = magic_word(); INCREMENT_COUNTER; } /// Copy constructor PlacedVolume::Object::Object(const Object& c) - : TGeoExtension(), magic(c.magic), refCount(0), volIDs(c.volIDs), detector(c.detector) { + : TGeoExtension(), magic(c.magic), refCount(0), volIDs(c.volIDs) { INCREMENT_COUNTER; } @@ -319,7 +319,6 @@ PlacedVolume::Object::~Object() { TGeoExtension* PlacedVolume::Object::Grab() { ++this->refCount; #ifdef ___print_vols - if ( detector.ptr() ) cout << "Placement grabbed with valid detector element....." << endl; else cout << "Placement grabbed....." << endl; #endif return this; @@ -394,24 +393,12 @@ const PlacedVolume::VolIDs& PlacedVolume::volIDs() const { return _data(*this)->volIDs; } -/// Set the detector element if appropriate (requires degenerate geometry subtree) -void PlacedVolume::setDetector(const DetElement& e) const { - PlacedVolume::Object* o = _userExtension(*this); - if ( o ) o->detector = e; -} -#if 0 -/// Access the corresponding detector element of this placement (if set) -DetElement PlacedVolume::detector() const { - DetElement e(_data(*this)->detector.ptr()); - return e; -} -#endif /// String dump string PlacedVolume::toString() const { stringstream s; Object* obj = _data(*this); s << m_element->GetName() << ": vol='" << m_element->GetVolume()->GetName() << "' mat:'" << m_element->GetMatrix()->GetName() - << "' volID[" << obj->volIDs.size() << "] "; + << "' volID[" << obj->volIDs.size() << "] "; for (VolIDs::const_iterator i = obj->volIDs.begin(); i != obj->volIDs.end(); ++i) s << (*i).first << "=" << (*i).second << " "; s << ends; @@ -589,6 +576,7 @@ const Volume& Volume::setVisAttributes(const VisAttr& attr) const { line_style == VisAttr::SOLID ? "Solid" : "Dashed", name() ); + m_element->SetLineWidth(10); m_element->SetLineColor(dark); if (draw_style == VisAttr::SOLID) { m_element->SetLineColor(bright); @@ -608,7 +596,6 @@ const Volume& Volume::setVisAttributes(const VisAttr& attr) const { else m_element->SetLineStyle(line_style); - m_element->SetLineWidth(10); /* m_element->SetVisibility(kTRUE); diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp index 25b31a4f5..760b484ed 100644 --- a/DDCore/src/XML/DocumentHandler.cpp +++ b/DDCore/src/XML/DocumentHandler.cpp @@ -1,3 +1,12 @@ +// $Id$ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "DD4hep/Printout.h" #include "XML/DocumentHandler.h" #include <iostream> #include <stdexcept> @@ -55,6 +64,10 @@ namespace DD4hep { /// Constructor DocumentErrorHandler() { } + /// Destructor + virtual ~DocumentErrorHandler() { + printout(DEBUG,"DocumentErrorHandler","+++ Destructing the XercesC DOM-XML document error handler...."); + } /// Reset errors (Noop) void resetErrors() { } @@ -68,24 +81,26 @@ namespace DD4hep { virtual bool handleError(const DOMError& domError); }; bool DocumentErrorHandler::handleError(const DOMError& domError) { + string err = "DOM UNKNOWN: "; switch (domError.getSeverity()) { case DOMError::DOM_SEVERITY_WARNING: - cout << "DOM WARNING: "; + err = "DOM WARNING: "; break; case DOMError::DOM_SEVERITY_ERROR: - cout << "DOM ERROR: "; + err = "DOM ERROR: "; break; case DOMError::DOM_SEVERITY_FATAL_ERROR: - cout << "DOM FATAL: "; + err = "DOM FATAL: "; break; default: - cout << "DOM UNKNOWN: "; return false; } - cout << _toString(domError.getType()) << ": " << _toString(domError.getMessage()) << endl; + printout(FATAL,"DocumentErrorHandler", "+++ %s %s: %s", err.c_str(), + _toString(domError.getType()).c_str(),_toString(domError.getMessage()).c_str()); DOMLocator* loc = domError.getLocation(); if (loc) { - cout << "Location: Line:" << loc->getLineNumber() << " Column:" << loc->getColumnNumber() << endl; + printout(FATAL,"DocumentErrorHandler","+++ Location: Line:%d Column: %d", + loc->getLineNumber(),loc->getColumnNumber()); } return false; } @@ -99,15 +114,14 @@ namespace DD4hep { || m.find("for attribute 'ID' is invalid Name or NMTOKEN value") != string::npos) return; string sys(_toString(e.getSystemId())); - cout << "Error at file \"" << sys << "\", line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endl - << "Message: " << m << endl; + printout(ERROR,"XercesC","+++ Error at file \"%s\", Line %d Column: %d Message:%s", + sys.c_str(), e.getLineNumber(), e.getColumnNumber(), m.c_str()); } void DocumentErrorHandler::fatalError(const SAXParseException& e) { string m(_toString(e.getMessage())); string sys(_toString(e.getSystemId())); - cout << "Fatal Error at file \"" << sys << "\", line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endl - << "Message: " << m << endl; - //throw runtime_error( "Standard pool exception : Fatal Error on the DOM Parser" ); + printout(FATAL,"XercesC","+++ FATAL Error at file \"%s\", Line %d Column: %d Message:%s", + sys.c_str(), e.getLineNumber(), e.getColumnNumber(), m.c_str()); } void dumpTree(xercesc::DOMDocument* doc) { @@ -147,25 +161,26 @@ Document DocumentHandler::load(Handle_t base, const XMLCh* fname) const { } Document DocumentHandler::load(const string& fname) const { - cout << "Loading document URI:" << fname << endl; + printout(INFO,"DocumentHandler","+++ Loading document URI: %s",fname.c_str()); XMLURL xerurl = (const XMLCh*) Strng_t(fname); string path = _toString(xerurl.getPath()); string proto = _toString(xerurl.getProtocolName()); auto_ptr < XercesDOMParser > parser(make_parser(m_errHdlr.get())); - cout << " protocol:" << proto << endl << " path:" << path << endl; + printout(INFO,"DocumentHandler","+++ protocol:%s path:%s",proto.c_str(), path.c_str()); try { parser->parse(path.c_str()); } - catch (exception& e) { - cout << "parse(path):" << e.what() << endl; + catch (const exception& e) { + printout(ERROR,"DocumentHandler","+++ Exception(XercesC): parse(path):%s",e.what()); try { parser->parse(fname.c_str()); } - catch (exception& ex) { - cout << "parse(URI):" << ex.what() << endl; + catch (const exception& ex) { + printout(FATAL,"DocumentHandler","+++ Exception(XercesC): parse(URI):%s",ex.what()); + throw; } } - cout << "Document succesfully parsed....." << endl; + printout(INFO,"DocumentHandler","+++ Document %s succesfully parsed with XercesC .....",path.c_str()); return (XmlDocument*) parser->adoptDocument(); } @@ -271,28 +286,26 @@ Document DocumentHandler::load(Handle_t base, const XmlChar* fname) const { } Document DocumentHandler::load(const string& fname) const { - cout << "Loading document URI:" << fname << endl; + printout(INFO,"DocumentHandler","+++ Loading document URI: %s",fname.c_str()); TiXmlDocument* doc = new TiXmlDocument(_clean_fname(fname).c_str()); bool result = false; try { result = doc->LoadFile(); if ( !result ) { if ( doc->Error() ) { - cout << "Unknown error whaile parsing XML document with TiXml:" << endl; - cout << "Document:" << doc->Value() << endl; - cout << "Location: Line:" << doc->ErrorRow() - << " Column:" << doc->ErrorCol() << endl; + printout(FATAL,"DocumentHandler","+++ Error (TinyXML) while parsing XML document:%s",doc->ErrorDesc()); + printout(FATAL,"DocumentHandler","+++ Document:%s Location Line:%d Column:%d", + doc->Value().c_str(), doc->ErrorRow(), doc->ErrorCol()); throw runtime_error(string("DD4hep: ")+doc->ErrorDesc()); } - else - throw runtime_error("DD4hep: Unknown error whaile parsing XML document with TiXml."); + throw runtime_error("DD4hep: Unknown error whaile parsing XML document with TinyXML."); } } catch(exception& e) { - cout << "parse(path):" << e.what() << endl; + printout(ERROR,"DocumentHandler","+++ Exception (TinyXML): parse(path):%s",e.what()); } if ( result ) { - cout << "Document " << fname << " succesfully parsed....." << endl; + printout(INFO,"DocumentHandler","+++ Document %s succesfully parsed with TinyXML .....",fname.c_str()); return (XmlDocument*)doc; } delete doc; @@ -307,16 +320,15 @@ Document DocumentHandler::parse(const char* doc_string, size_t /* length */) con return (XmlDocument*)doc; } if ( doc->Error() ) { - cout << "Unknown error whaile parsing XML document with TiXml:" << endl; - cout << "Document:" << doc->Value() << endl; - cout << "Location: Line:" << doc->ErrorRow() - << " Column:" << doc->ErrorCol() << endl; + printout(FATAL,"DocumentHandler","+++ Error (TinyXML) while parsing XML document:%s",doc->ErrorDesc()); + printout(FATAL,"DocumentHandler","+++ Document:%s Location Line:%d Column:%d", + doc->Value().c_str(), doc->ErrorRow(), doc->ErrorCol()); throw runtime_error(string("DD4hep: ")+doc->ErrorDesc()); } throw runtime_error("DD4hep: Unknown error whaile parsing XML document with TiXml."); } catch(exception& e) { - cout << "parse(xml-string):" << e.what() << endl; + printout(ERROR,"DocumentHandler","+++ Exception (TinyXML): parse(string):%s",e.what()); } delete doc; return 0; @@ -326,7 +338,7 @@ Document DocumentHandler::parse(const char* doc_string, size_t /* length */) con int DocumentHandler::output(Document doc, const string& fname) const { FILE* file = fname.empty() ? stdout : ::fopen(fname.c_str(),"w"); if ( !file ) { - cout << "Failed to open output file:" << fname << endl; + printout(ERROR,"DocumentHandler","+++ Failed to open output file: %s",fname.c_str()); return 0; } TiXmlDocument* d = (TiXmlDocument*)doc.ptr(); diff --git a/DDCore/src/XML/XMLDimension.cpp b/DDCore/src/XML/XMLDimension.cpp index 330b49f8f..e99ca2fa4 100644 --- a/DDCore/src/XML/XMLDimension.cpp +++ b/DDCore/src/XML/XMLDimension.cpp @@ -186,6 +186,11 @@ string Dimension::typeStr() const { return m_element.attr < string > (_U(type)); } +/// Access "value" attribute as STL string +std::string Dimension::valueStr() const { + return m_element.attr < string > (_U(value)); +} + string Dimension::regionStr() const { return m_element.hasAttr(_U(region)) ? m_element.attr < string > (_U(region)) : string(); } diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp index 80f792464..e47b8f473 100644 --- a/DDCore/src/XML/XMLElements.cpp +++ b/DDCore/src/XML/XMLElements.cpp @@ -7,6 +7,7 @@ // //==================================================================== // Framework include files +#include "DD4hep/Printout.h" #include "XML/Evaluator.h" #include "XML/XMLElements.h" #include "XML/XMLTags.h" @@ -63,13 +64,17 @@ union Xml { }; namespace { - XmlElement* node_first(XmlElement* e, const XmlChar* t) { + XmlElement* node_first(XmlElement* e, const Tag_t& t) { + if ( t=="*" ) return e ? (XmlElement*)_E(e)->FirstChildElement() : 0; return e ? (XmlElement*)_E(e)->FirstChildElement(t) : 0; } - size_t node_count(XmlElement* elt, const XmlChar* t) { + size_t node_count(XmlElement* elt, const Tag_t& t) { size_t cnt = 0; TiXmlElement* e = Xml(elt).e; - for(e=e->FirstChildElement(t);e; e=e->NextSiblingElement(t)) ++cnt; + if ( t=="*" ) + for(e=e->FirstChildElement();e; e=e->NextSiblingElement()) ++cnt; + else + for(e=e->FirstChildElement(t);e; e=e->NextSiblingElement(t)) ++cnt; return cnt; } } @@ -114,30 +119,30 @@ void DD4hep::XML::XmlString::release(char** p) { } namespace { - size_t node_count(XmlElement* e, const XmlChar* t) { + size_t node_count(XmlElement* e, const Tag_t& t) { size_t cnt = 0; if ( e ) { - string tag = _toString(t); + const string& tag = t; xercesc::DOMElement *ee = Xml(e).e; if ( ee ) { for(xercesc::DOMElement* elt=ee->getFirstElementChild(); elt; elt=elt->getNextElementSibling()) { if ( elt->getParentNode() == ee ) { string child_tag = _toString(elt->getTagName()); - if ( child_tag == tag ) ++cnt; + if ( tag == "*" || child_tag == tag ) ++cnt; } } } } return cnt; } - XmlElement* node_first(XmlElement* e, const XmlChar* t) { + XmlElement* node_first(XmlElement* e, const Tag_t& t) { if ( e ) { - //size_t cnt = 0; - string tag = _toString(t); + const string& tag = t; xercesc::DOMElement* ee = Xml(e).e; if ( ee ) { for(xercesc::DOMElement* elt=ee->getFirstElementChild(); elt; elt=elt->getNextElementSibling()) { if ( elt->getParentNode() == ee ) { + if ( tag == "*" ) return _XE(elt); string child_tag = _toString(elt->getTagName()); if ( child_tag == tag ) return _XE(elt); } @@ -429,48 +434,37 @@ Tag_t& Tag_t::operator=(const string& s) { /// Copy constructor NodeList::NodeList(const NodeList& copy) - : m_node(copy.m_node), m_ptr(0) -#ifndef DD4HEP_USE_TINYXML - // , m_index(0) -#endif + : m_tag(copy.m_tag), m_node(copy.m_node), m_ptr(0) { - m_tag = XmlString::replicate(copy.m_tag); reset(); } /// Initializing constructor NodeList::NodeList(XmlElement* node, const XmlChar* tag) - : m_node(node), m_ptr(0) -#ifndef DD4HEP_USE_TINYXML - // , m_index(0) -#endif + : m_tag(tag), m_node(node), m_ptr(0) { - m_tag = XmlString::replicate(tag); reset(); } /// Default destructor NodeList::~NodeList() { - if (m_tag) - XmlString::release (&m_tag); } /// Reset the nodelist XmlElement* NodeList::reset() { -#ifdef DD4HEP_USE_TINYXML return m_ptr=node_first(m_node,m_tag); -#else - return m_ptr=node_first(m_node,m_tag); -#endif } /// Advance to next element XmlElement* NodeList::next() const { #ifdef DD4HEP_USE_TINYXML + if ( m_tag.str()=="*" ) + return m_ptr =_XE(m_ptr ? _E(m_ptr)->NextSiblingElement() : 0); return m_ptr = _XE(m_ptr ? _E(m_ptr)->NextSiblingElement(m_tag) : 0); #else xercesc::DOMElement *elt = Xml(m_ptr).e; for(elt=elt->getNextElementSibling(); elt; elt=elt->getNextElementSibling()) { + if ( m_tag == "*" ) return m_ptr=Xml(elt).xe; string child_tag = _toString(elt->getTagName()); if ( child_tag == m_tag ) return m_ptr=Xml(elt).xe; } @@ -481,10 +475,13 @@ XmlElement* NodeList::next() const { /// Go back to previous element XmlElement* NodeList::previous() const { #ifdef DD4HEP_USE_TINYXML + if ( m_tag=="*" ) + return m_ptr = _XE(m_ptr ? _E(m_ptr)->PreviousSiblingElement() : 0); return m_ptr = _XE(m_ptr ? _E(m_ptr)->PreviousSiblingElement(m_tag) : 0); #else xercesc::DOMElement *elt = Xml(m_ptr).e; for(elt=elt->getPreviousElementSibling(); elt; elt=elt->getPreviousElementSibling()) { + if ( m_tag=="*" ) return m_ptr=Xml(elt).xe; string child_tag = _toString(elt->getTagName()); if ( child_tag == m_tag ) return m_ptr=Xml(elt).xe; } @@ -495,9 +492,7 @@ XmlElement* NodeList::previous() const { /// Assignment operator NodeList& NodeList::operator=(const NodeList& l) { if (this != &l) { - if (m_tag) - XmlString::release (&m_tag); - m_tag = XmlString::replicate(l.m_tag); + m_tag = l.m_tag; m_node = l.m_node; reset(); } @@ -923,12 +918,14 @@ Handle_t Document::root() const { /// Standard destructor - releases the document DocumentHolder::~DocumentHolder() { + if (m_doc) { + printout(DEBUG,"DocumentHolder","+++ Release DOM document...."); #ifdef DD4HEP_USE_TINYXML - if (m_doc) delete _D(m_doc); + delete _D(m_doc); #else - if (m_doc) _D(m_doc)->release(); #endif + } m_doc = 0; } diff --git a/DDCore/src/parsers/Grammars.h b/DDCore/src/parsers/Grammars.h new file mode 100644 index 000000000..37513082b --- /dev/null +++ b/DDCore/src/parsers/Grammars.h @@ -0,0 +1,530 @@ +// ============================================================================ +#ifndef DD4HEPKERNEL_GRAMMARS_H +#define DD4HEPKERNEL_GRAMMARS_H 1 +#ifdef __GNUC__ +#warning \ + The headers Grammars.h and Parsers.icpp are deprecated \ + and will be removed from the next release of Gaudi. You should migrate your \ + code the new pasers based on Boost.Spirit 2. +#endif +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <cctype> +// ============================================================================ +// Boost.Spirit +// ============================================================================ +#include <boost/version.hpp> +#if BOOST_VERSION >= 103800 +// FIXME: Move to the new boost::spirit::classic namespace +#if !defined(BOOST_SPIRIT_USE_OLD_NAMESPACE) +#define BOOST_SPIRIT_USE_OLD_NAMESPACE +#endif +#include <boost/spirit/include/classic.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#else +#include <boost/spirit.hpp> +#include <boost/spirit/phoenix.hpp> +#endif +#include <boost/bind.hpp> + +// ============================================================================ +/** @file + * Collection of grammars for property types + * + * @see Dd4hep::Parsers::parse + * @see Property + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep +{ + namespace Parsers + { + // ======================================================================== + using namespace boost::spirit ; + // ======================================================================== + using namespace phoenix ; + // ======================================================================== + /** @struct ClosureGrammar + * Grammar or grammar rule which derive from this struct will have + * attribute of type <c>T</c> and name <c>val</c> + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename T> + struct ClosureGrammar : public boost::spirit::closure < ClosureGrammar<T>,T > + { + typedef boost::spirit::closure<ClosureGrammar, T> closure; + typename closure::member1 val; + }; + // ======================================================================== + /** @struct AttributesClosureGrammar + * + * Grammar or grammar rule which derive from this struct will have + * two attributes: type <c>T1</c> and name <c>val</c>, type <c>T2</c> + * and name <c>attrs</c> + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename T1,typename T2> + struct AttributesClosureGrammar + : public boost::spirit::closure<AttributesClosureGrammar<T1,T2>,T1,T2> + { + typedef boost::spirit::closure<AttributesClosureGrammar, T1,T2> closure; + typename closure::member1 val; + typename closure::member2 attrs; + }; + // ======================================================================== + /** @class BoolGrammar + * + * The valid represenation of boolean values are: + * + * - true , True , TRUE or 1 + * - false , False , FALSE or 0 + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + class BoolGrammar : public grammar + < + BoolGrammar, + ClosureGrammar<bool>::context_t + > + { + public: + typedef bool ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( BoolGrammar const &self) + { + boolean_literal + = true_literal[self.val = true] | false_literal[self.val = false]; + true_literal + = str_p("true" ) | str_p("True" ) | str_p("TRUE" ) | str_p("1"); + false_literal + = str_p("false") | str_p("False") | str_p("FALSE") | str_p("0"); + } + rule<ScannerT> const& start() const + { return boolean_literal;} + rule<ScannerT> boolean_literal,true_literal,false_literal; + }; + }; + // ======================================================================== + /** @class CharGrammar + * + * The valid represenation of char values are: + * + * - 'a', 'b','\'' + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=char> + class CharGrammar : public grammar + < + CharGrammar<RT> , typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( CharGrammar<RT> const &self) + { + char_literal + = int_parser<RT>()[self.val=arg1] + | ('\'' + >> ( str_p("\\'")[self.val='\''] + | (anychar_p[self.val=arg1]-'\'') )>>'\''); + } + rule<ScannerT> const& start() const + { return char_literal; } + rule<ScannerT> char_literal; + }; + }; + // ======================================================================== + /** @class IntGrammar + * + * The valid representation of integers values are: + * + * - 1, 100, 123 + * + * @todo implement suffixes u U l L + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=int> + class IntGrammar : public grammar + < + IntGrammar<RT>, + typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( IntGrammar<RT> const &self) + { + int_literal = lexeme_d[int_parser<RT>()[self.val=arg1] + >> !(ch_p('u') | ch_p('U') | ch_p('l') | ch_p('L'))]; + } + rule<ScannerT> const& start() const { return int_literal; } + rule<ScannerT> int_literal; + }; + }; + // ======================================================================== + /** @class RealGrammar + * + * The valid represenation of real values are: + * + * - 1, 1.0 ,1.123, 1E+2, 0.5e-2 + * + * @todo implement suffixes f l F L + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template<typename RT=double> + class RealGrammar : public grammar + < + RealGrammar<RT>,typename ClosureGrammar<RT>::context_t + > + { + public: + typedef RT ResultT; + public: + template <typename ScannerT> + struct definition + { + definition( RealGrammar const &self) + { + real_literal + = lexeme_d[real_parser<RT, + real_parser_policies<RT> >()[self.val = arg1] + >> !(ch_p('f') | ch_p('F') | ch_p('l') | ch_p('L'))]; + } + rule<ScannerT> const& start() const + { return real_literal; } + rule<ScannerT> real_literal; + }; + }; + // ======================================================================== + /** @class StringGrammar + * + * The valid represenation of string values are: + * + * - "abc" , "\"abc\"" + * - 'abs' , '\'abc\'' + * + * @todo implement not ASCII chars in strings + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + + class StringGrammar : public grammar + < + StringGrammar, ClosureGrammar<std::string>::context_t + > + { + public: + typedef std::string ResultT; + /** remove CR/LF symbols form the parsed strings + * @attention it is a bit dangerous operation + * The operation allows to write "very long" input strings + * for opts-files (it is actual e.g. for DataOnDemandSvc configuration) + * by splitting the strings into few lines + * All new-line symbols (as well as '\n', '\t', CR/LF etc + * are substituted by ordinary blanks. + */ + void matchString() const + { + for ( std::string::iterator cur=this->val().begin(); + cur!=this->val().end();cur++) + { if(std::isspace(*cur) ) { *cur = ' '; } } + } + public: + template <typename ScannerT> + struct definition + { + definition( StringGrammar const &self ) + { + string_literal = (lexeme_d + [ + ('"' >> (*( str_p("\\\"") + | + (anychar_p-'"') )) + [self.val = construct_<std::string> + (arg1,arg2)] >> + '"') + | + ('\'' >> (*( str_p("\\'") + | + (anychar_p-'\'') )) + [self.val = construct_<std::string> + (arg1,arg2)]>> + '\'')])[boost::bind(&StringGrammar::matchString,&self)]; + } + rule<ScannerT> const& start() const { return string_literal; } + rule<ScannerT> string_literal; + }; + }; + // ======================================================================== + /** @class SkipperGrammar + * + * Skipping spaces and comments. Comments can be + * + * - // ... - one line + * - \/\* ... \*\/ - multiline + * + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + class SkipperGrammar : public grammar<SkipperGrammar> + { + public: + /** Constructor + * @param skipnewline Skip new line symbols or not + */ + SkipperGrammar ( const bool skipnewline = true ) + : m_skipnewline(skipnewline){} + public: + /// @return true - skip new line symbols, false - not skip + bool skipnewline() const{return m_skipnewline;} + public: + template <typename ScannerT> + struct definition + { + definition( SkipperGrammar const& self) + { + if ( self.skipnewline() ) + { + skip + = space_p + | comment_p("//") // C++ comment + | comment_p("/*", "*/") // C comment + ; + } + else + { + skip + = (space_p-eol_p) + | comment_p("//") // C++ comment + | comment_p("/*", "*/") // C comment + ; + } + } + rule<ScannerT> skip; + rule<ScannerT> const& start() const { return skip; } + }; + private: + bool m_skipnewline; + }; + // ======================================================================== + /** @class PairGrammar + * + * The valid represenation of pairs are: + * ("abc",123) or ("abc","def") + * Inner types of pair depends on KeyGrammarT and ValueGrammarT grammars + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename KeyGrammarT, typename ValueGrammarT> + class PairGrammar : public grammar + < + PairGrammar<KeyGrammarT,ValueGrammarT>, + typename ClosureGrammar< + std::pair<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT> >::context_t + > + { + public: + typedef typename KeyGrammarT::ResultT KeyT; + typedef typename ValueGrammarT::ResultT ValueT; + typedef std::pair<KeyT,ValueT> ResultT; + public: + /** Constructor + * @param delim Delimiter for pair values + */ + PairGrammar ( const std::string& delim = "," ) + : m_delim(delim) {} + public: + /// callback. Action when we match first value + void matchFirst ( const KeyT& first ) const { this->val().first = first; } + /// callback. Action when we match second value + void matchSecond ( const ValueT& second ) const { this->val().second = second; } + public: + template <typename ScannerT> + struct definition + { + definition( PairGrammar const &self) + { + para + = ( + str_p("(") + >> (grkey[boost::bind(&PairGrammar::matchFirst,&self,_1)]) + >> self.delim().c_str() + >> (grvalue[boost::bind(&PairGrammar::matchSecond,&self,_1)]) + >> str_p(")") + ) ; + } + rule<ScannerT> const& start() const { return para; } + rule<ScannerT> para; + KeyGrammarT grkey; + ValueGrammarT grvalue; + }; + public: + /// @return Delimiter for pair values + const std::string& delim() const { return m_delim ; } + /** Set delimiters for pair values + * @param delim Delimiter + */ + void setDelim ( const std::string& delim ) { m_delim = delim;} + private: + std::string m_delim; + }; + // ======================================================================== + /** @class VectorGrammar + * + * The valid represenation of vector are: + * - {"abc","defj","i"} or {1,2,3,4,5} + * - ["abc","defj","i"] or [1,2,3,4,5] + * Inner type depends on GrammarT grammar + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename GrammarT> + class VectorGrammar : public grammar + < + VectorGrammar<GrammarT> , + typename ClosureGrammar<std::vector<typename GrammarT::ResultT> >::context_t + > + { + public: + typedef typename GrammarT::ResultT ValueT; + typedef std::vector<ValueT> ResultT; + typedef VectorGrammar<GrammarT> SelfT; + public: + /// callback. Action when we match inner value + void matchItem(const ValueT& value) const { this->val().push_back(value); } + public: + template <typename ScannerT> + struct definition + { + definition(SelfT const &self) + { + inner = + !(gr[boost::bind(&VectorGrammar::matchItem,&self,_1)] + >> *(','>>gr[boost::bind(&VectorGrammar::matchItem,&self,_1)])); + vec = + '[' >> inner >> ']' | // a'la python list + '(' >> inner >> ')' | // a'la python tuple + '{' >> inner >> '}' ; // like obsolete list from opts-grammar + } + rule<ScannerT> const& start() const { return vec; } + rule<ScannerT> vec,inner; + GrammarT gr; + }; + }; + // ======================================================================== + /** @class MapGrammar + * + * The valid represenation of map are: + * - {"file1":"path1","something":"nothing"} + * - {"file1"="path1","something"="nothing"} + * - ["file1":10,"something":20] + * - ["file1"=30,"something"=40] + * Inner key type depends on KeyGrammarT grammar + * Inner value type depends on ValueGrammarT grammar + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-14 + */ + template <typename KeyGrammarT, typename ValueGrammarT> + class MapGrammar : public grammar + < + MapGrammar<KeyGrammarT,ValueGrammarT>, + typename AttributesClosureGrammar + < std::map<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT>, + std::pair<typename KeyGrammarT::ResultT, + typename ValueGrammarT::ResultT> >::context_t + > + { + public: + typedef typename KeyGrammarT::ResultT KeyT; + typedef typename ValueGrammarT::ResultT ValueT; + typedef std::map<KeyT,ValueT> ResultT; + public: + /// call backs. Action when we match pair in map + void matchItem () const + { + //this->val().insert(this->attrs()); + this->val()[this->attrs().first] = this->attrs().second ; + } + /// call backs. Action when we match key of pair + void matchFirst ( const KeyT& value ) const { this->attrs().first = value ; } + /// call backs. Action when we match value pf pair + void matchSecond( const ValueT& value ) const { this->attrs().second = value ; } + public: + template <typename ScannerT> + struct definition + { + definition( MapGrammar const &self) + { + vec + = ('{'>> inner_list >> '}') | ('['>>inner_list>>']'); + inner_list + = + !( inner[boost::bind(&MapGrammar::matchItem,&self)] + >> *( ch_p(',') >> + inner[boost::bind(&MapGrammar::matchItem,&self)] ) + ); + inner + = + grKey[boost ::bind(&MapGrammar::matchFirst,&self,_1)] + >> ( ch_p('=') | ch_p(':')) + >> grValue[boost::bind(&MapGrammar::matchSecond,&self,_1)] ; + } + KeyGrammarT grKey; + ValueGrammarT grValue; + rule<ScannerT> const& start() const { return vec; } + rule<ScannerT> vec,inner, inner_list ; + }; + }; + // ======================================================================== + } // end of namespace Dd4hep::Parsers +} // end of namespace Dd4hep +// ============================================================================ +// The END +// ============================================================================ +#endif // DD4HEPKERNEL_GRAMMARS_H +// ============================================================================ diff --git a/DDCore/src/parsers/GrammarsV2.h b/DDCore/src/parsers/GrammarsV2.h new file mode 100644 index 000000000..d9b3f3c48 --- /dev/null +++ b/DDCore/src/parsers/GrammarsV2.h @@ -0,0 +1,471 @@ +// ============================================================================ +#ifndef DD4HEPKERNEL_GRAMMARSV2_H +#define DD4HEPKERNEL_GRAMMARSV2_H 1 +#ifdef __GNUC__ +#pragma GCC system_header +#endif +// ============================================================================ +// Include files +// ============================================================================ +// STD: +//============================================================================== +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> +//============================================================================== +// Boost: +//============================================================================== +#include <boost/spirit/include/qi.hpp> +#include <boost/fusion/include/unused.hpp> +#include <boost/fusion/include/std_pair.hpp> + +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.hpp> + +#include <boost/spirit/repository/include/qi_confix.hpp> + +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +//============================================================================== +namespace DD4hep { namespace Parsers { + //============================================================================== + // Namespace aliases: + //============================================================================== + namespace sp = boost::spirit; + namespace ph = boost::phoenix; + namespace qi = sp::qi; + namespace enc = sp::ascii; + namespace rep = sp::repository; + + template <typename T> T evaluate_string(const std::string& value); + + //============================================================================== + // Grammars + //============================================================================== + typedef std::string::const_iterator DefaultIterator; + typedef enc::space_type DefaultSkipper; + //============================================================================== + template <typename Iterator, typename T, typename Skipper, class Enable=void> + struct Grammar_ { + /* READ THIS IF YOUR COMPILE BREAKS ON THE FOLLOWING LINE + * + * To users: You have to ask developers to implement parser for your type T + * To developer: You have to implement and register Grammar for type T + * + */ + BOOST_MPL_ASSERT_MSG(false, GRAMMAR_FOR_TYPE_DOES_NOT_EXISTS, (T)); + }; + +#define REGISTER_GRAMMAR(ResultType, GrammarName) \ + template <typename Iterator, typename Skipper> \ + struct Grammar_<Iterator, ResultType, Skipper> \ + { \ + typedef GrammarName<Iterator, Skipper> Grammar; \ + } + //============================================================================== + template< typename Iterator> struct SkipperGrammar : qi::grammar<Iterator> + { + SkipperGrammar() : SkipperGrammar::base_type(comments) { + comments = enc::space | rep::confix("/*", "*/")[*(qi::char_ - "*/")] + | + rep::confix("//", (sp::eol | sp::eoi))[*(qi::char_ - (sp::eol|sp::eoi))]; + } + qi::rule<Iterator> comments; + }; + //============================================================================== + template< typename Iterator, typename Skipper> + struct StringGrammar : qi::grammar<Iterator, std::string(), qi::locals<char>,Skipper> + { + //------------------------------------------------------------------------------ + typedef std::string ResultT; + //------------------------------------------------------------------------------ + StringGrammar() : StringGrammar::base_type( str ) { + begin_quote = enc::char_("\"'"); + quote = enc::char_(qi::_r1); + + str = qi::lexeme[begin_quote[qi::_a = qi::_1] + > *( (enc::char_('\\') >> quote(qi::_a))[qi::_val += qi::_a] + | (enc::char_[qi::_val += qi::_1] - quote(qi::_a))) > + quote(qi::_a)] + ; + } + //------------------------------------------------------------------------------ + qi::rule<Iterator, std::string(), qi::locals<char>, Skipper> str; + qi::rule<Iterator, char()> begin_quote; + qi::rule<Iterator, void(char)> quote; + //------------------------------------------------------------------------------ + }; + REGISTER_GRAMMAR(std::string, StringGrammar); + //============================================================================== + template< typename Iterator, typename Skipper> + struct CharGrammar : qi::grammar<Iterator, char(), Skipper> { + typedef char ResultT; + CharGrammar() : CharGrammar::base_type( ch ) { + ch = qi::int_parser<char>() + | + '\'' >> (qi::char_-'\'') >> '\''; + } + qi::rule<Iterator, char(), Skipper> ch; + }; + REGISTER_GRAMMAR(char, CharGrammar); + //============================================================================== + template< typename Iterator, typename Skipper> + struct BoolGrammar : qi::grammar<Iterator, bool(), Skipper> + { + typedef bool ResultT; + BoolGrammar() : BoolGrammar::base_type( boolean_literal ) { + boolean_literal = + (qi::lit("true") | "True" | "TRUE" | "1")[qi::_val=true] + | + (qi::lit("false") | "False" | "FALSE" | "0")[qi::_val=false]; + } + qi::rule<Iterator, bool(), Skipper> boolean_literal; + }; + REGISTER_GRAMMAR(bool, BoolGrammar); + //============================================================================== + template< typename Iterator, typename RT , typename Skipper> + struct IntGrammar : qi::grammar<Iterator, RT(), Skipper> { + typedef RT ResultT; + IntGrammar() : IntGrammar::base_type( integer ) { + integer = qi::int_parser<RT>()[qi::_val = qi::_1] + >> -qi::no_case[qi::char_('L')]; + } + qi::rule<Iterator, RT(), Skipper> integer; + }; + // ---------------------------------------------------------------------------- + // Register IntGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T, typename Skipper> + struct Grammar_<Iterator, T, Skipper, + typename boost::enable_if<boost::is_integral<T> >::type> + { + typedef IntGrammar<Iterator, T, Skipper> Grammar; + }; + //============================================================================== + template< typename Iterator, typename RT, typename Skipper> + struct RealGrammar : qi::grammar<Iterator, RT(), Skipper> { + typedef RT ResultT; + RealGrammar() : RealGrammar::base_type(real) { + real = qi::real_parser<RT>(); + } + qi::rule<Iterator, RT(), Skipper> real; + }; + // ---------------------------------------------------------------------------- + // Register RealGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T, typename Skipper > + struct Grammar_<Iterator, T, Skipper, + typename boost::enable_if<boost::is_floating_point<T> >::type > { + typedef RealGrammar<Iterator, T, Skipper> Grammar; + }; + //============================================================================== + template< typename Iterator, typename VectorT, typename Skipper> + struct VectorGrammar : qi::grammar<Iterator, VectorT(), qi::locals<char>,Skipper> + { + //------------------------------------------------------------------------------ + typedef VectorT ResultT; + //------------------------------------------------------------------------------ + VectorGrammar() : VectorGrammar::base_type(vec) { + begin = enc::char_('[')[qi::_val=']'] | enc::char_('{')[qi::_val='}'] + | enc::char_('(')[qi::_val=')']; + end = enc::char_(qi::_r1); + list = elementGrammar % ','; + vec = begin[qi::_a = qi::_1] >> -list[qi::_val=qi::_1] >> end(qi::_a); + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename VectorT::value_type, Skipper>::Grammar + elementGrammar; + qi::rule<Iterator, char()> begin; + qi::rule<Iterator, void(char)> end; + + qi::rule<Iterator, ResultT(), qi::locals<char>,Skipper> vec; + qi::rule<Iterator, ResultT(), Skipper> list; + // ---------------------------------------------------------------------------- + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::vector: + // ---------------------------------------------------------------------------- + template <typename Iterator,typename InnerT,typename AllocatorT,typename Skipper> + struct Grammar_<Iterator, std::vector<InnerT, AllocatorT>, Skipper > { + typedef + VectorGrammar<Iterator, std::vector<InnerT, AllocatorT>,Skipper> + Grammar; + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::list: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename InnerT, typename AllocatorT,typename Skipper> + struct Grammar_<Iterator, std::list<InnerT, AllocatorT>, Skipper > { + typedef + VectorGrammar<Iterator, std::list<InnerT, AllocatorT>,Skipper> + Grammar; + }; + // ---------------------------------------------------------------------------- + // Register VectorGrammar for std::set: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename InnerT, typename CompareT,typename AllocatorT, typename Skipper> + struct Grammar_<Iterator, std::set<InnerT, CompareT, AllocatorT>, Skipper > { + typedef + VectorGrammar<Iterator, std::set<InnerT, CompareT, AllocatorT>,Skipper> + Grammar; + }; + + //============================================================================== + template< typename Iterator, typename PairT, typename Skipper> + struct PairGrammar : + qi::grammar<Iterator,PairT(), qi::locals<char>, Skipper> { + //------------------------------------------------------------------------------ + typedef PairT ResultT; + typedef typename PairT::first_type first_type; + typedef typename PairT::second_type second_type; + //------------------------------------------------------------------------------ + PairGrammar() : PairGrammar::base_type(pair) { + init(","); + } + + PairGrammar(const std::string& delimeter) : PairGrammar::base_type(pair) { + init(delimeter); + } + //------------------------------------------------------------------------------ + struct first {}; + struct second {}; + void init(const std::string& delimeter) { + begin = enc::char_('(')[qi::_val=')'] + | + enc::char_('[')[qi::_val=']']; + end = qi::char_(qi::_r1); + pair = begin[qi::_a = qi::_1] >> pair_in[qi::_val = qi::_1] >> end(qi::_a); + pair_in = key >> qi::lit(delimeter) >> value; + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename PairT::first_type, Skipper>::Grammar key; + typename + Grammar_<Iterator, typename PairT::second_type, Skipper>::Grammar + value; + qi::rule<Iterator, char()> begin; + qi::rule<Iterator, void(char)> end; + qi::rule<Iterator, ResultT(), qi::locals<char>, Skipper> pair; + qi::rule<Iterator, ResultT(), Skipper> pair_in; + //ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; // END PairGrammar + // ---------------------------------------------------------------------------- + // Register PairGrammar: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename KeyT, typename ValueT, + typename Skipper> + struct Grammar_<Iterator, std::pair<KeyT, ValueT>, Skipper > + { + typedef PairGrammar<Iterator, std::pair<KeyT, ValueT>, Skipper> Grammar; + }; + // ============================================================================ + template< typename Iterator, typename MapT, typename Skipper> + struct MapGrammar : qi::grammar<Iterator,MapT(), Skipper> { + //------------------------------------------------------------------------------ + typedef MapT ResultT; + typedef typename MapT::key_type KeyT; + typedef typename MapT::mapped_type MappedT; + typedef std::pair<KeyT, MappedT> PairT; + + typedef std::vector<PairT> VectorPairT; + //------------------------------------------------------------------------------ + struct tag_key{}; + struct tag_mapped{}; + struct Operations { + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + //---------------------------------------------------------------------- + void operator()(ResultT& res, const VectorPairT& vec) const{ + for(typename VectorPairT::const_iterator cur = vec.begin(); + cur != vec.end(); cur++){ + res.insert(*cur); + } + } + void operator()(PairT& res, const KeyT& key, tag_key) const{ + res.first = key; + } + void operator()(PairT& res, const MappedT& value, tag_mapped) const{ + res.second = value; + } + //---------------------------------------------------------------------- + }; + //------------------------------------------------------------------------------ + MapGrammar() : MapGrammar::base_type(map) { + pair = key[op(qi::_val,qi::_1, tag_key())] > (qi::lit(':') | '=') > + value[op(qi::_val,qi::_1, tag_mapped())]; + list = -(pair % enc::char_(',')); + map = (('[' >> list >> ']') + | ('{' >> list >> '}'))[op(qi::_val,qi::_1)]; + } + // ---------------------------------------------------------------------------- + typename + Grammar_<Iterator, typename MapT::key_type, Skipper>::Grammar key; + typename + Grammar_<Iterator, typename MapT::mapped_type, Skipper>::Grammar value; + qi::rule<Iterator, PairT(), Skipper> pair; + qi::rule<Iterator, VectorPairT(), Skipper> list; + qi::rule<Iterator, ResultT(), Skipper> map; + ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; + // ---------------------------------------------------------------------------- + // Register MapGrammar for std::map: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename KeyT, typename ValueT, + typename KeyCompareT, typename AllocatorT, typename Skipper> + struct Grammar_<Iterator, std::map<KeyT, ValueT, KeyCompareT, AllocatorT>, + Skipper > { + typedef MapGrammar<Iterator, + std::map<KeyT, ValueT, KeyCompareT, AllocatorT>, Skipper> Grammar; + }; + + // ============================================================================ + template< typename Iterator, typename Skipper> + struct KeyValueGrammar : + qi::grammar<Iterator, std::pair<std::string, std::string>(), Skipper> { + //------------------------------------------------------------------------------ + typedef std::pair<std::string, std::string> ResultT; + //------------------------------------------------------------------------------ + struct first {}; + struct second {}; + + KeyValueGrammar() : KeyValueGrammar::base_type(pair) { + //------------------------------------------------------------------------------ + pair = gstring >> ":" >> +enc::char_; + } + // ---------------------------------------------------------------------------- + StringGrammar<Iterator, Skipper> gstring; + qi::rule<Iterator, ResultT(), Skipper> pair; + // ---------------------------------------------------------------------------- + }; // END KeyValueGrammar + // We don't register KeyalueGrammar because it's a special parser + + + // ============================================================================ + template< typename Iterator, typename PointT, typename Skipper> + struct Pnt3DGrammar : qi::grammar<Iterator, PointT(), Skipper> { + typedef PointT ResultT; + typedef std::string Scalar; + // ---------------------------------------------------------------------------- + struct Operations { + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + void operator()(ResultT& res, const Scalar& value,const char xyz) const{ + typename PointT::Scalar val = evaluate_string<typename PointT::Scalar>(value); + switch(xyz) { + case 'x': res.SetX(val); break; + case 'y': res.SetY(val); break; + case 'z': res.SetZ(val); break; + default: break; + } + } + }; // Operations + // ---------------------------------------------------------------------------- + Pnt3DGrammar() : Pnt3DGrammar::base_type(point) { + point = list | ('(' >> list >> ')') | ('[' >> list >> ']'); + list = -(enc::no_case[qi::lit("x") | qi::lit("px")] >> ':') + >> scalar[op(qi::_val,qi::_1,'x')] >> + ',' >> -(enc::no_case[qi::lit("y") | qi::lit("py")] >> ':') + >> scalar[op(qi::_val,qi::_1,'y')] >> + ',' >> -(enc::no_case[qi::lit("z") | qi::lit("pz")] >> ':') + >> scalar[op(qi::_val,qi::_1,'z')]; + } + // ---------------------------------------------------------------------------- + qi::rule<Iterator, ResultT(), Skipper> point, list; + typename Grammar_<Iterator, Scalar, Skipper>::Grammar scalar; + ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; // Pnt3DGrammar + // ---------------------------------------------------------------------------- + // Register Pnt3DGrammar for ROOT::Math::PositionVector3D: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T1, typename T2, typename Skipper> + struct Grammar_<Iterator, ROOT::Math::PositionVector3D<T1,T2>, Skipper>{ + typedef Pnt3DGrammar<Iterator, ROOT::Math::PositionVector3D<T1,T2>, Skipper> Grammar; + }; + // ---------------------------------------------------------------------------- + // Register Pnt3DGrammar for ROOT::Math::DisplacementVector3D: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T1, typename T2, typename Skipper> + struct Grammar_<Iterator, ROOT::Math::DisplacementVector3D<T1,T2>, Skipper>{ + typedef Pnt3DGrammar<Iterator,ROOT::Math::DisplacementVector3D<T1,T2>, Skipper> Grammar; + }; + // ============================================================================ + template< typename Iterator, typename PointT, typename Skipper> + struct Pnt4DGrammar : qi::grammar<Iterator, PointT(), Skipper> { + typedef PointT ResultT; + typedef std::string ScalarT; + //----------------------------------------------------------------------------- + struct Operations { + template <typename A, typename B = boost::fusion::unused_type, + typename C = boost::fusion::unused_type, + typename D = boost::fusion::unused_type> + struct result { typedef void type; }; + + void operator()(ResultT& res, const ScalarT& value,const char xyz) const{ + typename PointT::Scalar val = evaluate_string<typename PointT::Scalar>(value); + switch(xyz){ + case 'x': res.SetPx(val); break; + case 'y': res.SetPy(val); break; + case 'z': res.SetPz(val); break; + case 'e': res.SetE(val); break; + default: break; + } + } + void operator()(ResultT& res, const ResultT& xyz) const{ + res.SetPx(xyz.Px()); + res.SetPy(xyz.Py()); + res.SetPz(xyz.Pz()); + } + }; // Operations + // ---------------------------------------------------------------------------- + Pnt4DGrammar() : Pnt4DGrammar::base_type(point4d) { + point4d = list4d | ('(' >> list4d >> ')') | ('[' >> list4d >> ']'); + list4d = (point3d[op(qi::_val,qi::_1)] >> enc::char_(";,") + >> e[op(qi::_val, qi::_1, 'e')]) + | + (e[op(qi::_val,qi::_1, 'e')] >> enc::char_(";,") + >> point3d[op(qi::_val, qi::_1)]); + e = -(enc::no_case[enc::char_("te")] >> ':') + >> scalar[qi::_val = qi::_1]; + + point3d = list3d | ('(' >> list3d >> ')') | ('[' >> list3d >> ']'); + list3d = -(enc::no_case[qi::lit("x") | qi::lit("px")] >> ':') + >> scalar[op(qi::_val, qi::_1,'x')] >> + ',' >> -(enc::no_case[qi::lit("y") | qi::lit("py")] >> ':') + >> scalar[op(qi::_val, qi::_1,'y')] >> + ',' >> -(enc::no_case[qi::lit("z") | qi::lit("pz")] >> ':') + >> scalar[op(qi::_val, qi::_1,'z')]; + } + // ---------------------------------------------------------------------------- + qi::rule<Iterator, ResultT(), Skipper> point3d, point4d, list3d, + list4d; + qi::rule<Iterator, ScalarT(), Skipper> e; + typename Grammar_<Iterator, ScalarT, Skipper>::Grammar scalar; + ph::function<Operations> op; + // ---------------------------------------------------------------------------- + }; // Pnt4DGrammar + // ---------------------------------------------------------------------------- + // Register Pnt4DGrammar for ROOT::Math::LorentzVector: + // ---------------------------------------------------------------------------- + template <typename Iterator, typename T1, typename Skipper> + struct Grammar_<Iterator, ROOT::Math::LorentzVector<T1>, Skipper > { + typedef Pnt4DGrammar<Iterator, ROOT::Math::LorentzVector<T1>, Skipper> Grammar; + }; + // ============================================================================ + }} // DD4hep::Parsers +//============================================================================ +#endif diff --git a/DDCore/src/parsers/Parsers.icpp b/DDCore/src/parsers/Parsers.icpp new file mode 100644 index 000000000..170fd142d --- /dev/null +++ b/DDCore/src/parsers/Parsers.icpp @@ -0,0 +1,232 @@ +// $Id: Parsers.icpp,v 1.5 2008/10/28 14:02:18 marcocle Exp $ +// ============================================================================ +#ifndef DD4HEP_PARSERS_ICPP +#define DD4HEP_PARSERS_ICPP 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD&STL +// ============================================================================ +#include <vector> +#include <map> +#include <string> +// ============================================================================ +// Boost.Bind +// ============================================================================ +#include "boost/bind.hpp" +// ============================================================================ +// Boost.Spirit, Boost.Spirit.Phoenix +// ============================================================================ +#include <boost/version.hpp> +#if BOOST_VERSION >= 103800 +// FIXME: Move to the new boost::spirit::classic namespace +#if !defined(BOOST_SPIRIT_USE_OLD_NAMESPACE) +#define BOOST_SPIRIT_USE_OLD_NAMESPACE +#endif +#include <boost/spirit/include/classic.hpp> +#include <boost/spirit/include/phoenix1.hpp> +#else +#include <boost/spirit.hpp> +#include <boost/spirit/phoenix.hpp> +#endif +// ============================================================================ +// DD4hepKernel +// ============================================================================ +#include "DD4hep/Parsers.h" +#include "Grammars.h" +// ============================================================================ +/** @file + * + * Helper inline functions for implementation of real parsing function + * from the namespace DD4hep::Parsers + * + * For adding new type you should have only grammar class which recognize + * this type. Then by combining this grammar with such already implemented + * grammars like VectorGrammar, MapGrammar, PairGrammar you can very simply + * implement container types which will work with your type. + * + * If you want your type can be handled in property file - see ValueGrammar + * in JobOptionsSvc which lays in DD4hepCoreSvc. + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ +// ============================================================================ +namespace DD4hep { + namespace Parsers { + using namespace std; + using namespace boost::spirit ; + + /// the actual type of position iterator + typedef boost::spirit::position_iterator<string::const_iterator> IteratorT; + + /// create the position iterator from the input + inline IteratorT createIterator( const std::string& input) + { return IteratorT ( input.begin(), input.end() ) ; } + + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for integer-like quantities into one templated grammar + * @see DD4hep::Parsers::IntGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename IntegerT> + inline StatusCode parse_integer + (IntegerT& result,const string& input) + { + IntGrammar<IntegerT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1]).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of integer-like quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::IntGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename IntegerT> + inline StatusCode parse_integer_vector + ( std::vector<IntegerT>& result,const string& input) + { + VectorGrammar<IntGrammar<IntegerT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for "char-like" quantities into one templated grammar + * @see DD4hep::Parsers::CharGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename CharT> + inline StatusCode parse_char + ( CharT& result , const string& input ) + { + CharGrammar<CharT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1]).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of 'char-like' quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::CharGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename CharT> + inline StatusCode parse_char_vector + (std::vector<CharT>& result,const string& input) + { + VectorGrammar<CharGrammar<CharT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for "float-like" quantities into one templated grammar + * @see DD4hep::Parsers::RealGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + template<typename RealT> + inline StatusCode parse_real + ( RealT& result , const string& input) + { + RealGrammar<RealT> g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + // ======================================================================== + /** helper function to "merge" the implementation of all parsers + * for vector of 'char-like' quantities + * into the combination of templated grammars + * @see DD4hep::Parsers::VectorGrammar + * @see DD4hep::Parsers::RealGrammar + * @see DD4hep::Parsers::SkipperGrammar + * + * @param result (output) parsing result + * @param input (input) string to be parsed + * @return status code + * + * @author Alexander MAZUROV Alexander.Mazurov@gmail.com + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-12 + */ + // ======================================================================== + template<typename RealT> + StatusCode parse_real_vector + ( std::vector<RealT>& result,const string& input) + { + VectorGrammar< RealGrammar<RealT> > g; + return parse + ( createIterator(input), + IteratorT(), + g[var(result)=arg1], + SkipperGrammar()).full; + } + } // end of namespace Parsers +} // end of namespace DD4hep +// ============================================================================ +#endif +// ============================================================================ +// The END +// ============================================================================ + + diff --git a/DDCore/src/parsers/ParsersFactory.h b/DDCore/src/parsers/ParsersFactory.h new file mode 100644 index 000000000..b0b936b0b --- /dev/null +++ b/DDCore/src/parsers/ParsersFactory.h @@ -0,0 +1,53 @@ +// ============================================================================ +#ifndef DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H +#define DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <string> +#include <vector> +#include <map> +// ============================================================================ +// Boost: +// ============================================================================ +#include <boost/mpl/assert.hpp> +#include <boost/type_traits.hpp> +// ============================================================================ +// DD4hep +// ============================================================================ +#include "GrammarsV2.h" +// ============================================================================ +namespace DD4hep { + namespace Parsers { + // ======================================================================== + typedef std::string::const_iterator IteratorT; + //typedef boost::spirit::ascii::space_type Skipper; + typedef SkipperGrammar<IteratorT> Skipper; + // ======================================================================== + template<typename ResultT> inline int + parse_(ResultT& result, const std::string& input){ + Skipper skipper; + typename Grammar_<IteratorT, ResultT, Skipper>::Grammar g; + IteratorT iter = input.begin(), end = input.end(); + return qi::phrase_parse( iter, end, g, skipper , result) && (iter==end); + } + //========================================================================= + template<> inline int + parse_(std::string& result, const std::string& input){ + Skipper skipper; + Grammar_<IteratorT, std::string, Skipper>::Grammar g; + IteratorT iter = input.begin(), end = input.end(); + if (!(qi::phrase_parse( iter, end, g, skipper, result) && (iter==end))){ + result = input; + } + //@attention always + return true; + } + //========================================================================= + }/* Parsers */ +} /* DD4hep */ +//============================================================================= +#endif // DD4HEPPROPERTYPARSERS_PARSERSGENERATOR_H + diff --git a/DDCore/src/parsers/ParsersObjects.cpp b/DDCore/src/parsers/ParsersObjects.cpp new file mode 100644 index 000000000..850585c1c --- /dev/null +++ b/DDCore/src/parsers/ParsersObjects.cpp @@ -0,0 +1,130 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "ParsersFactory.h" +#include "DD4hep/ToStream.h" + +using namespace std; +namespace ROOT { + namespace Math { + static bool operator<(const XYZPoint& a, const XYZPoint& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + return false; + } + static bool operator<(const XYZVector& a, const XYZVector& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + return false; + } + static bool operator<(const PxPyPzEVector& a, const PxPyPzEVector& b) { + if ( a.X() < b.X() ) return true; + if ( a.Y() < b.Y() ) return true; + if ( a.Z() < b.Z() ) return true; + if ( a.T() < b.T() ) return true; + return false; + } + } +} +// ============================================================================ +namespace DD4hep { + namespace Parsers { + // ========================================================================== + template<typename T1, typename T2> inline int + parse_(ROOT::Math::PositionVector3D<T1,T2>& result, const string& input){ + Skipper skipper; + typename Grammar_<IteratorT,ROOT::Math::PositionVector3D<T1,T2>,Skipper>::Grammar g; + IteratorT iter = input.begin(), end = input.end(); + if (qi::phrase_parse( iter, end, g, skipper, result)){ + return 1; + } + return 0; + } + // ========================================================================== + int parse(ROOT::Math::XYZPoint& result,const string& input) { + return parse_(result, input); + } + // ========================================================================== + /* parse 3D-vector + * @param result (output) the parsed vector + * @param input (input) the input string + * @return status code + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + int parse(ROOT::Math::XYZVector& result,const string& input) { + ROOT::Math::XYZPoint point; + int sc = parse(point,input); + if ( 0 == sc ){ return sc; } // RETURN + result = point; + return 1; + } + int parse(ROOT::Math::PxPyPzEVector& result, const string& input) { + return parse_(result, input); + } + + // ========================================================================== + /* parse the vector of points + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + // ========================================================================== + int parse(vector<ROOT::Math::XYZPoint>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(list<ROOT::Math::XYZPoint>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(set<ROOT::Math::XYZPoint>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + // ========================================================================== + /* parse the vector of vectors + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + // ========================================================================== + int parse(vector<ROOT::Math::XYZVector>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(list<ROOT::Math::XYZVector>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(set<ROOT::Math::XYZVector>& result, const string& input) { + result.clear(); + return parse_(result, input); + } + // ========================================================================== + /* parse the vector of vectors + * @param resut (OUTPUT) the parser vector + * @param input (INPIUT) the string to be parsed + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-09-05 + */ + // ========================================================================== + int parse(vector<ROOT::Math::PxPyPzEVector>& result,const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(list<ROOT::Math::PxPyPzEVector>& result,const string& input) { + result.clear(); + return parse_(result, input); + } + int parse(set<ROOT::Math::PxPyPzEVector>& result,const string& input) { + result.clear(); + return parse_(result, input); + } + + } +} diff --git a/DDCore/src/parsers/ParsersStandardList1.cpp b/DDCore/src/parsers/ParsersStandardList1.cpp new file mode 100644 index 000000000..ad28873f7 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardList1.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(bool) +PARSERS_DEF_FOR_LIST(char) +PARSERS_DEF_FOR_LIST(unsigned char) +PARSERS_DEF_FOR_LIST(signed char) diff --git a/DDCore/src/parsers/ParsersStandardList2.cpp b/DDCore/src/parsers/ParsersStandardList2.cpp new file mode 100644 index 000000000..f32362c9b --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardList2.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(int) +PARSERS_DEF_FOR_LIST(short) +PARSERS_DEF_FOR_LIST(unsigned short) +PARSERS_DEF_FOR_LIST(unsigned int) diff --git a/DDCore/src/parsers/ParsersStandardList3.cpp b/DDCore/src/parsers/ParsersStandardList3.cpp new file mode 100644 index 000000000..f7e32e55d --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardList3.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(long) +PARSERS_DEF_FOR_LIST(unsigned long) +PARSERS_DEF_FOR_LIST(long long) +PARSERS_DEF_FOR_LIST(unsigned long long) diff --git a/DDCore/src/parsers/ParsersStandardList4.cpp b/DDCore/src/parsers/ParsersStandardList4.cpp new file mode 100644 index 000000000..04d9c5150 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardList4.cpp @@ -0,0 +1,5 @@ +#include "ParsersStandardListCommon.h" +PARSERS_DEF_FOR_LIST(double) +PARSERS_DEF_FOR_LIST(float) +PARSERS_DEF_FOR_LIST(long double) +PARSERS_DEF_FOR_LIST(std::string) diff --git a/DDCore/src/parsers/ParsersStandardListCommon.h b/DDCore/src/parsers/ParsersStandardListCommon.h new file mode 100644 index 000000000..e7533c828 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardListCommon.h @@ -0,0 +1,18 @@ +#ifndef PARSERS_STANDARD_LIST_COMMON_H +#define PARSERS_STANDARD_LIST_COMMON_H 1 +// ============================================================================ +// Include files +// ============================================================================ +#include "DD4hep/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#define PARSERS_DEF_FOR_LIST(InnerType)\ + int DD4hep::Parsers::parse(std::vector<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + int DD4hep::Parsers::parse(std::list<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + int DD4hep::Parsers::parse(std::set<InnerType>& result,const std::string& input)\ + { return DD4hep::Parsers::parse_(result, input); } \ + +// ============================================================================ +#endif /* PARSERS_STANDARD_LIST_COMMON_H */ diff --git a/DDCore/src/parsers/ParsersStandardMisc1.cpp b/DDCore/src/parsers/ParsersStandardMisc1.cpp new file mode 100644 index 000000000..8ae34a8c2 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMisc1.cpp @@ -0,0 +1,21 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::pair<double,double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::pair<int, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::pair<double, double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::pair<int, int> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::vector<std::vector<std::string> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDCore/src/parsers/ParsersStandardMisc2.cpp b/DDCore/src/parsers/ParsersStandardMisc2.cpp new file mode 100644 index 000000000..bb4ed696a --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMisc2.cpp @@ -0,0 +1,17 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::vector<std::vector<double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDCore/src/parsers/ParsersStandardMisc3.cpp b/DDCore/src/parsers/ParsersStandardMisc3.cpp new file mode 100644 index 000000000..9cc2a0348 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMisc3.cpp @@ -0,0 +1,17 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<std::string, int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, unsigned int>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, double>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<std::string> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDCore/src/parsers/ParsersStandardMisc4.cpp b/DDCore/src/parsers/ParsersStandardMisc4.cpp new file mode 100644 index 000000000..5867cd25e --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMisc4.cpp @@ -0,0 +1,13 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<int> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<std::string, std::vector<double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::map<int, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDCore/src/parsers/ParsersStandardMisc5.cpp b/DDCore/src/parsers/ParsersStandardMisc5.cpp new file mode 100644 index 000000000..5984100be --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMisc5.cpp @@ -0,0 +1,24 @@ +#include "ParsersStandardMiscCommon.h" + +int DD4hep::Parsers::parse(std::map<unsigned int, std::string>& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} + +int DD4hep::Parsers::parse(std::string& name, std::string& value , + const std::string& input ) { + Skipper skipper; + KeyValueGrammar<IteratorT, Skipper> g; + KeyValueGrammar<IteratorT, Skipper>::ResultT result; + std::string::const_iterator iter = input.begin(); + bool parse_result = qi::phrase_parse(iter, input.end(), g, skipper, + result) && (iter==input.end()); + if (parse_result) { + name = result.first; + value = result.second; + } + return parse_result; +} + +int DD4hep::Parsers::parse(std::map<std::string, std::pair<double, double> >& result, const std::string& input) { + return DD4hep::Parsers::parse_(result, input); +} diff --git a/DDCore/src/parsers/ParsersStandardMiscCommon.h b/DDCore/src/parsers/ParsersStandardMiscCommon.h new file mode 100644 index 000000000..8a2db6bdb --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardMiscCommon.h @@ -0,0 +1,9 @@ +#ifndef PARSERS_STANDARD_MISC_COMMON_H +#define PARSERS_STANDARD_MISC_COMMON_H 1 +// ============================================================================ +// Include files +// ============================================================================ +#include "DD4hep/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#endif /* PARSERS_STANDARD_MISC_COMMON_H */ diff --git a/DDCore/src/parsers/ParsersStandardSingle.cpp b/DDCore/src/parsers/ParsersStandardSingle.cpp new file mode 100644 index 000000000..a5428f120 --- /dev/null +++ b/DDCore/src/parsers/ParsersStandardSingle.cpp @@ -0,0 +1,26 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "DD4hep/Parsers.h" +#include "ParsersFactory.h" +// ============================================================================ +#define PARSERS_DEF_FOR_SINGLE(Type)\ + int DD4hep::Parsers::parse(Type& result, const std::string& input) \ + { return DD4hep::Parsers::parse_(result, input); } +// ============================================================================ +PARSERS_DEF_FOR_SINGLE(bool) +PARSERS_DEF_FOR_SINGLE(char) +PARSERS_DEF_FOR_SINGLE(unsigned char) +PARSERS_DEF_FOR_SINGLE(signed char) +PARSERS_DEF_FOR_SINGLE(int) +PARSERS_DEF_FOR_SINGLE(short) +PARSERS_DEF_FOR_SINGLE(unsigned short) +PARSERS_DEF_FOR_SINGLE(unsigned int) +PARSERS_DEF_FOR_SINGLE(long) +PARSERS_DEF_FOR_SINGLE(unsigned long) +PARSERS_DEF_FOR_SINGLE(long long) +PARSERS_DEF_FOR_SINGLE(unsigned long long) +PARSERS_DEF_FOR_SINGLE(double) +PARSERS_DEF_FOR_SINGLE(float) +PARSERS_DEF_FOR_SINGLE(long double) +PARSERS_DEF_FOR_SINGLE(std::string) diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 77e14112d..4c5245b8a 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -13,6 +13,8 @@ #include "DD4hep/FieldTypes.h" #include "DD4hep/Printout.h" #include "DD4hep/Plugins.h" +#include "DD4hep/objects/DetectorInterna.h" + #include "XML/DocumentHandler.h" #include "XML/Conversions.h" @@ -709,7 +711,8 @@ template <> void Converter<DetElement>::operator()(xml_h element) const { /// Read material entries from a seperate file in one of the include sections of the geometry template <> void Converter<GdmlFile>::operator()(xml_h element) const { - xml_h materials = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root(); + XML::DocumentHolder doc(XML::DocumentHandler().load(element, element.attr_value(_U(ref)))); + xml_h materials = doc.root(); xml_coll_t(materials, _U(element)).for_each(Converter < Atom > (this->lcdd)); xml_coll_t(materials, _U(material)).for_each(Converter < Material > (this->lcdd)); } @@ -721,14 +724,16 @@ template <> void Converter<XMLFile>::operator()(xml_h element) const { /// Read alignment entries from a seperate file in one of the include sections of the geometry template <> void Converter<AlignmentFile>::operator()(xml_h element) const { - xml_h alignments = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root(); + XML::DocumentHolder doc(XML::DocumentHandler().load(element, element.attr_value(_U(ref)))); + xml_h alignments = doc.root(); xml_coll_t(alignments, _U(alignment)).for_each(Converter < AlignmentEntry > (this->lcdd)); xml_coll_t(alignments, _U(include)).for_each(Converter < XMLFile > (this->lcdd)); } /// Read material entries from a seperate file in one of the include sections of the geometry template <> void Converter<DetElementInclude>::operator()(xml_h element) const { - xml_h node = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root(); + XML::DocumentHolder doc(XML::DocumentHandler().load(element, element.attr_value(_U(ref)))); + xml_h node = doc.root(); string tag = node.tag(); if ( tag == "lcdd" ) Converter < Compact > (this->lcdd)(node); diff --git a/DDCore/src/plugins/GeometryWalk.cpp b/DDCore/src/plugins/GeometryWalk.cpp index 904364f56..fc314ec24 100644 --- a/DDCore/src/plugins/GeometryWalk.cpp +++ b/DDCore/src/plugins/GeometryWalk.cpp @@ -74,24 +74,19 @@ GeometryWalk::GeometryWalk(LCDD& lcdd, DetElement sdet) : m_det(sdet) { } walk(m_det,VolIDs()); } -#include "TClass.h" -#include "TGeoManager.h" -void GeometryWalk::dumpPathes(DetElement e, PlacedVolume pv) const { + +/// Printout volume information +void GeometryWalk::print(DetElement e, PlacedVolume pv, const VolIDs& /* child_ids */) const { stringstream log; - PlacementPath det_nodes, all_nodes; + PlacementPath all_nodes; ElementPath det_elts; DetectorTools::elementPath(e,det_elts); - DetectorTools::elementPath(e,det_nodes); DetectorTools::placementPath(e,all_nodes); string elt_path = DetectorTools::elementPath(det_elts); string node_path = DetectorTools::placementPath(all_nodes); - string det_path = DetectorTools::placementPath(det_nodes); log << "Lookup " << left << setw(32) << pv.name() << " Detector[" << det_elts.size() << "]: " << elt_path; printout(INFO,m_det.name(),log.str()); log.str(""); - log << " " << left << setw(32) << pv.name() << " Elements[" << det_nodes.size() << "]: " << det_path; - printout(INFO,m_det.name(),log.str()); - log.str(""); log << " " << left << setw(32) << " " << " Places[" << all_nodes.size() << "]: " << node_path; printout(INFO,m_det.name(),log.str()); log.str(""); @@ -103,40 +98,6 @@ void GeometryWalk::dumpPathes(DetElement e, PlacedVolume pv) const { printout(INFO,m_det.name(),log.str()); } -/// Printout volume information -void GeometryWalk::print(DetElement e, PlacedVolume pv, const VolIDs& /* child_ids */) const { - stringstream log; - PlacementPath det_nodes, all_nodes; - DetectorTools::elementPath(e,det_nodes); - DetectorTools::placementPath(e,all_nodes); - string node_path = DetectorTools::placementPath(all_nodes); - string det_path = DetectorTools::placementPath(det_nodes); - dumpPathes(e, pv); - if ( det_path == "/world_volume_1" || - det_path == "/world_volume_1/MuonBarrel_envelope_13" || - det_path == "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7" || - det_path == "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7/MuonBarrel_layer8_7" -) - { - PlacedVolume pv = e.placement(); - TIter next(pv->GetVolume()->GetNodes()); - // Now check next layer children - for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { - cout << pv->GetName() << " --> " << daughter->GetName() << endl; - } - } - //cout << node_path << endl; - const char* path = "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7/MuonBarrel_inner_0/MuonBarrel_layer9_8"; - size_t path_len = strlen(path); - if ( strncmp(node_path.c_str(),path,path_len) == 0 ) { - gGeoManager->cd(node_path.c_str()); - //dumpPathes(e, pv); - //DetectorAlignment alignment(e); - //alignment.align(Position(0,0,1)); - //dumpPathes(e,pv); - } -} - /// Walk through tree of volume placements void GeometryWalk::walk(DetElement e, VolIDs ids) const { const _C& children = e.children(); diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp index 09a92a423..44e07f40f 100644 --- a/DDCore/src/plugins/LCDDConverter.cpp +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -12,6 +12,7 @@ #include "DD4hep/Volumes.h" #include "DD4hep/FieldTypes.h" #include "DD4hep/Segmentations.h" +#include "DD4hep/objects/DetectorInterna.h" #include "XML/DocumentHandler.h" #include "LCDDConverter.h" diff --git a/DDCore/src/plugins/LCDDConverter.h b/DDCore/src/plugins/LCDDConverter.h index 98e88f1cb..2c0e5c980 100644 --- a/DDCore/src/plugins/LCDDConverter.h +++ b/DDCore/src/plugins/LCDDConverter.h @@ -37,6 +37,9 @@ namespace DD4hep { */ namespace Geometry { + // Forward declarations + class SensitiveDetectorObject; + /** @class LCDDConverter LCDDConverter.h XML/LCDDConverter.h * * Geometry converter from DD4hep to Geant 4. diff --git a/DDCore/src/plugins/PluginInvoker.cpp b/DDCore/src/plugins/PluginInvoker.cpp new file mode 100644 index 000000000..1470d2875 --- /dev/null +++ b/DDCore/src/plugins/PluginInvoker.cpp @@ -0,0 +1,110 @@ +// $Id: Compact2Objects.cpp 1059 2014-04-04 20:24:53Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "XML/Conversions.h" +#include "XML/XMLElements.h" +#include "XML/DocumentHandler.h" +#include "DD4hep/DetFactoryHelper.h" + +// C/C++ include files +#include <stdexcept> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + namespace { + /// Some utility class to specialize the converters: + class include_file; + class plugins; + class plugin; + class arg; + } + + template <> void Converter<include_file>::operator()(xml_h element) const; + template <> void Converter<plugins>::operator()(xml_h e) const; + template <> void Converter<plugin>::operator()(xml_h e) const; + template <> void Converter<arg>::operator()(xml_h e) const; +} +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +/** Convert arg objects + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +template <> void Converter<arg>::operator()(xml_h e) const { + xml_comp_t c(e); + string val = c.valueStr(); + vector<string>* args = (vector<string>*)param; + args->push_back(val); +} + +/** Convert plugin objects + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +template <> void Converter<plugin>::operator()(xml_h e) const { + xml_comp_t c(e); + string nam = c.nameStr(); + vector<string> args; + vector<const char*> cargs; + //args.push_back("plugin:"+nam); + + xml_coll_t(e,"arg").for_each(Converter<arg>(lcdd,&args)); + for(vector<string>::const_iterator i=args.begin(); i!=args.end();++i) + cargs.push_back((*i).c_str()); + printout(INFO,"Converter<plugin>","+++ Now executing plugin:%s [%d args]",nam.c_str(),int(cargs.size())); + lcdd.apply(nam.c_str(),int(cargs.size()),(char**)&cargs[0]); +} + +/** Convert include_file objects + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +template <> void Converter<include_file>::operator()(xml_h element) const { + XML::DocumentHolder doc(XML::DocumentHandler().load(element, element.attr_value(_U(ref)))); + xml_h node = doc.root(); + string tag = node.tag(); + if ( tag == "plugin" ) + Converter<plugin>(lcdd,param)(node); + else if ( tag == "plugins" ) + Converter<plugins>(lcdd,param)(node); + else + throw runtime_error("Undefined tag name in XML structure:"+tag+" XML parsing abandoned."); +} + +/** Convert plugins objects + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +template <> void Converter<plugins>::operator()(xml_h e) const { + xml_coll_t(e,"include").for_each(Converter<include_file>(lcdd,param)); + xml_coll_t(e,"plugin").for_each(Converter<plugin>(lcdd,param)); +} + +static long handle_plugins(lcdd_t& lcdd, const xml_h& element) { + (DD4hep::Converter < plugins > (lcdd))(element); + return 1; +} +DECLARE_XML_DOC_READER(plugins,handle_plugins) + diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 3d8e9a2f2..34df0d87f 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -10,8 +10,8 @@ //==================================================================== // Framework include files -#include "DD4hep/Factories.h" #include "DD4hep/LCDD.h" +#include "DD4hep/Factories.h" #include "DD4hep/Printout.h" #include "../LCDDImp.h" @@ -67,14 +67,14 @@ static long load_compact(LCDD& lcdd, int argc, char** argv) { if ( argc > 0 ) { LCDDBuildType type = BUILD_DEFAULT; string input = argv[0]; - cout << "Processing compact input file : " << input; if ( argc > 1 ) { type = build_type(argv[1]); - cout << " with flag " << argv[1] << endl; + printout(INFO,"CompactLoader","+++ Processing compact file: %s with flag %s", + input.c_str(), argv[1]); lcdd.fromCompact(input,type); return 1; } - cout << endl; + printout(INFO,"CompactLoader","+++ Processing compact file: %s",input.c_str()); lcdd.fromCompact(input); return 1; } @@ -86,14 +86,14 @@ static long load_xml(LCDD& lcdd, int argc, char** argv) { if ( argc > 0 ) { LCDDBuildType type = BUILD_DEFAULT; string input = argv[0]; - cout << "Processing compact input file : " << input; if ( argc > 1 ) { type = build_type(argv[1]); - cout << " with flag " << argv[1] << endl; + printout(INFO,"XMLLoader","+++ Processing XML file: %s with flag %s", + input.c_str(), argv[1]); lcdd.fromXML(input,type); return 1; } - cout << endl; + printout(INFO,"XMLLoader","+++ Processing compact file: %s",input.c_str()); lcdd.fromXML(input); return 1; } @@ -106,7 +106,7 @@ static long load_volmgr(LCDD& lcdd, int, char**) { LCDDImp* imp = dynamic_cast<LCDDImp*>(&lcdd); if ( imp ) { imp->m_volManager = VolumeManager(lcdd, "World", imp->world(), Readout(), VolumeManager::TREE); - cout << "++ Volume manager populated and loaded." << endl; + printout(INFO,"VolumeManager","+++ Volume manager populated and loaded."); return 1; } } @@ -124,7 +124,7 @@ DECLARE_APPLY(DD4hepVolumeManager,load_volmgr) static long dump_geometry(LCDD& lcdd, int argc, char** argv) { if ( argc > 1 ) { string output = argv[1]; - cout << "Dump geometry to root file : " << output << endl; + printout(INFO,"Geometry2Root","+++ Dump geometry to root file:%s",output.c_str()); lcdd.manager().Export(output.c_str()+1); return 1; } @@ -132,33 +132,24 @@ static long dump_geometry(LCDD& lcdd, int argc, char** argv) { } DECLARE_APPLY(DD4hepGeometry2Root,dump_geometry) -static long dump_geometry(PlacedVolume pv,int level) { - char fmt[64]; - const TGeoNode* node = pv.ptr(); - ::sprintf(fmt,"%03d %%-%ds %%s",level+1,2*level+1); - printout(INFO,"+++",fmt,"",node->GetName()); - for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) { - TGeoNode* daughter = node->GetDaughter(idau); - PlacedVolume placement(daughter); - if ( placement.data() ) { - PlacedVolume pv_dau = Ref_t(daughter); - dump_geometry(pv_dau,level+1); - } - } - return 1; -} - -static long dump_geometry(DetElement de,int level, bool sensitive_only) { - const DetElement::Children& c = de.children(); - char fmt[64]; - if ( !sensitive_only || 0 != de.volumeID() ) { - ::sprintf(fmt,"%03d %%-%ds %%s #Dau:%%d VolID:%%p",level+1,2*level+1); - printout(INFO,"+++",fmt,"",de.placementPath().c_str(),int(c.size()),(void*)de.volumeID()); - } - for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) - dump_geometry((*i).second,level+1,sensitive_only); - return 1; +/** Basic entry point to print out the volume hierarchy + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +static long dump_volume_tree(LCDD& lcdd, int , char** ) { + struct Actor { static long dump(TGeoNode* node,int level) { + char fmt[64]; + ::sprintf(fmt,"%03d %%-%ds %%s",level+1,2*level+1); + printout(INFO,"+++",fmt,"",node->GetName()); + for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) + Actor::dump(node->GetDaughter(idau),level+1); + return 1; + }}; + return Actor::dump(lcdd.world().placement().ptr(),0); } +DECLARE_APPLY(DD4hepVolumeDump,dump_volume_tree) /** Basic entry point to print out the detector element hierarchy * @@ -167,11 +158,22 @@ static long dump_geometry(DetElement de,int level, bool sensitive_only) { * @date 01/04/2014 */ static long dump_detelement_tree(LCDD& lcdd, int argc, char** argv) { + struct Actor { static long dump(DetElement de,int level, bool sensitive_only) { + const DetElement::Children& c = de.children(); + char fmt[64]; + if ( !sensitive_only || 0 != de.volumeID() ) { + ::sprintf(fmt,"%03d %%-%ds %%s #Dau:%%d VolID:%%p",level+1,2*level+1); + printout(INFO,"+++",fmt,"",de.placementPath().c_str(),int(c.size()),(void*)de.volumeID()); + } + for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) + Actor::dump((*i).second,level+1,sensitive_only); + return 1; + }}; bool sensitive_only = false; for(int i=0; i<argc; ++i) { if ( ::strcmp(argv[i],"--sensitive")==0 ) { sensitive_only = true; } } - return dump_geometry(lcdd.world(),0,sensitive_only); + return Actor::dump(lcdd.world(),0,sensitive_only); } DECLARE_APPLY(DD4hepDetectorDump,dump_detelement_tree) @@ -181,7 +183,17 @@ DECLARE_APPLY(DD4hepDetectorDump,dump_detelement_tree) * @version 1.0 * @date 01/04/2014 */ -static long dump_volume_tree(LCDD& lcdd, int , char** ) { - return dump_geometry(lcdd.world().placement(),0); +static long detelement_cache(LCDD& lcdd, int , char** ) { + struct Actor { static long cache(DetElement de) { + const DetElement::Children& c = de.children(); + de.worldTransformation(); + de.parentTransformation(); + de.placementPath(); + de.path(); + for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) + Actor::cache((*i).second); + return 1; + }}; + return Actor::cache(lcdd.world()); } -DECLARE_APPLY(DD4hepVolumeDump,dump_volume_tree) +DECLARE_APPLY(DD4hepDetElementCache,detelement_cache) -- GitLab