diff --git a/DDCore/CMakeLists.txt b/DDCore/CMakeLists.txt index 10d8be783a6e4d1ffe05752c47fda5877a5c24df..c43a1dc689cb8a6f4314d06756e21d0d62c19551 100644 --- a/DDCore/CMakeLists.txt +++ b/DDCore/CMakeLists.txt @@ -21,7 +21,8 @@ dd4hep_add_dictionary( G__DD4hep SOURCES include/ROOT/Warnings.h include/DD4hep/*.h include/DD4hep/detail/*.h - include/XML/*.h + include/XML/*.h + src/DetectorImp.h EXCLUDE include/DD4hep/DetFactoryHelper.h include/DD4hep/Factories.h include/DD4hep/Plugins.h diff --git a/DDCore/include/DD4hep/BasicGrammar.h b/DDCore/include/DD4hep/BasicGrammar.h index 81af61d2cb19e2e0635f0e0bc29c60e796ddbd60..561a4c0cbd7070c5b761db80082e9544941870be 100644 --- a/DDCore/include/DD4hep/BasicGrammar.h +++ b/DDCore/include/DD4hep/BasicGrammar.h @@ -17,6 +17,9 @@ #include <string> #include <typeinfo> +// Forward declarations +class TClass; + /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -35,27 +38,56 @@ namespace dd4hep { * \ingroup DD4HEP */ class BasicGrammar { - protected: - /// Instance pointer - BasicGrammar* self = 0; - public: + typedef unsigned long long int key_type; + /// Instance type name + const std::string name; + /// Instance hash code + const key_type hash_value = 0; + /// Cached TClass reference for speed improvements + mutable TClass* root_class = 0; + /// Cached TDataType information for fundamental types + mutable int root_data_type = -1; + /// Initialization flag + mutable bool inited = false; + + protected: /// Default constructor - BasicGrammar(); + BasicGrammar(const std::string& typ); /// Default destructor virtual ~BasicGrammar(); + /// Second step initialization after the virtual table is fixed + void initialize() const; + int initialized_data_type() const; + TClass* initialized_clazz() const; + + public: /// Instance factory template <typename TYPE> static const BasicGrammar& instance(); + /// Lookup existing grammar using the grammar's hash code/hash64(type-name) (used for reading objects) + static const BasicGrammar& get(unsigned long long int hash_code); /// 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 the hash value for this grammar type + key_type hash() const { return hash_value; } + /// Access to the type information name + const std::string& type_name() const { return name; } + /// Access ROOT data type for fundamentals + int data_type() const { + if ( inited ) return root_data_type; + return initialized_data_type(); + } + /// Access the ROOT class for complex objects + TClass* clazz() const { + if ( inited ) return root_class; + return initialized_clazz(); + } /// Access to the type information virtual const std::type_info& type() const = 0; - /// Access to the type information name - virtual const std::string& type_name() const = 0; /// Access the object size (sizeof operator) virtual size_t sizeOf() const = 0; /// Serialize an opaque value to a string @@ -66,6 +98,8 @@ namespace dd4hep { virtual void destruct(void* pointer) const = 0; /// Opaque object copy construction. Memory must be allocated externally virtual void copy(void* to, const void* from) const = 0; + /// Bind opaque address to object + virtual void bind(void* pointer) const = 0; }; } // End namespace dd4hep diff --git a/DDCore/include/DD4hep/DD4hepRootPersistency.h b/DDCore/include/DD4hep/DD4hepRootPersistency.h index f838b7ef33211bfb2b76b6ee4c03ec5f20a25fc6..58c0b6cba96184b6e1c376757325ffcc591ef5b0 100644 --- a/DDCore/include/DD4hep/DD4hepRootPersistency.h +++ b/DDCore/include/DD4hep/DD4hepRootPersistency.h @@ -20,108 +20,62 @@ class DD4hepRootPersistency : public TNamed { public: typedef std::map<std::string, dd4hep::Handle<dd4hep::NamedObject> > HandleMap; - typedef std::map<std::string, std::string> PropertyValues; - typedef std::map<std::string, PropertyValues> Properties; + /// The main data block + dd4hep::DetectorData* m_data = 0; /// Helper since plain segmentations cannot be saved std::map<dd4hep::Readout,std::pair<dd4hep::IDDescriptor,dd4hep::DDSegmentation::Segmentation*> > m_segments; + /// Helper to save alignment conditions from the DetElement nominals + std::map<dd4hep::DetElement,dd4hep::AlignmentCondition> nominals; - std::map<dd4hep::DetElement,dd4hep::AlignmentCondition> nominals; //! - - /// The main data block - dd4hep::DetectorData* m_data = 0; - /// Default constructor DD4hepRootPersistency() : TNamed() {} /// Default destructor virtual ~DD4hepRootPersistency() {} - + /// Save an existing detector description in memory to a ROOT file static int save(dd4hep::Detector& description, const char* fname, const char* instance = "Geometry"); + /// Load an detector description from a ROOT file to memory static int load(dd4hep::Detector& description, const char* fname, const char* instance = "Geometry"); /// Access the geometry manager of this instance - TGeoManager& manager() const { - return *m_data->m_manager; - } - /// Access to properties - Properties& properties() const { - return *(Properties*)&m_data->m_properties; - } + TGeoManager& manager() const { return *m_data->m_manager; } /// Return handle to material describing air - dd4hep::Material air() const { - return m_data->m_materialAir; - } + dd4hep::Material air() const { return m_data->m_materialAir; } /// Return handle to material describing vacuum - dd4hep::Material vacuum() const { - return m_data->m_materialVacuum; - } + dd4hep::Material vacuum() const { return m_data->m_materialVacuum; } /// Return handle to "invisible" visualization attributes - dd4hep::VisAttr invisible() const { - return m_data->m_invisibleVis; - } + dd4hep::VisAttr invisible() const { return m_data->m_invisibleVis; } /// Return reference to the top-most (world) detector element - dd4hep::DetElement world() const { - return m_data->m_world; - } + dd4hep::DetElement world() const { return m_data->m_world; } /// Return reference to detector element with all tracker devices. - dd4hep::DetElement trackers() const { - return m_data->m_trackers; - } + dd4hep::DetElement trackers() const { return m_data->m_trackers; } /// Return handle to the world volume containing everything - dd4hep::Volume worldVolume() const { - return m_data->m_worldVol; - } + dd4hep::Volume worldVolume() const { return m_data->m_worldVol; } /// Return handle to the world volume containing the volume with the tracking devices - dd4hep::Volume trackingVolume() const { - return m_data->m_trackingVol; - } + dd4hep::Volume trackingVolume() const { return m_data->m_trackingVol; } /// Return handle to the VolumeManager - dd4hep::VolumeManager volumeManager() const { - return m_data->m_volManager; - } + dd4hep::VolumeManager volumeManager() const { return m_data->m_volManager; } /// Return handle to the combined electromagentic field description. - dd4hep::OverlayedField field() const { - return m_data->m_field; - } + dd4hep::OverlayedField field() const { return m_data->m_field; } /// Accessor to the header entry - dd4hep::Header header() const { - return m_data->m_header; - } + dd4hep::Header header() const { return m_data->m_header; } /// Accessor to the map of constants - const HandleMap& constants() const { - return m_data->m_define; - } + const HandleMap& constants() const { return m_data->m_define; } /// Accessor to the map of visualisation attributes - const HandleMap& visAttributes() const { - return m_data->m_display; - } + const HandleMap& visAttributes() const { return m_data->m_display; } /// Accessor to the map of limit settings - const HandleMap& limitsets() const { - return m_data->m_limits; - } + const HandleMap& limitsets() const { return m_data->m_limits; } /// Accessor to the map of region settings - const HandleMap& regions() const { - return m_data->m_regions; - } + const HandleMap& regions() const { return m_data->m_regions; } /// Accessor to the map of readout structures - const HandleMap& readouts() const { - return m_data->m_readouts; - } + const HandleMap& readouts() const { return m_data->m_readouts; } /// Accessor to the map of sub-detectors - const HandleMap& detectors() const { - return m_data->m_detectors; - } + const HandleMap& detectors() const { return m_data->m_detectors; } /// Retrieve a sensitive detector by it's name from the detector description - const HandleMap& sensitiveDetectors() const { - return m_data->m_sensitive; - } + const HandleMap& sensitiveDetectors() const { return m_data->m_sensitive; } /// Accessor to the map of field entries, which together form the global field - const HandleMap& fields() const { - return m_data->m_fields; - } + const HandleMap& fields() const { return m_data->m_fields; } /// Accessor to the map of ID specifications - const HandleMap& idSpecifications() const { - return m_data->m_idDict; - } + const HandleMap& idSpecifications() const { return m_data->m_idDict; } /// ROOT implementation macro ClassDef(DD4hepRootPersistency,1); @@ -161,8 +115,12 @@ public: size_t checkLimitSets() const; /// Call to check the volume manager hierarchy size_t checkVolManager() const; + /// Call to check the nominal alignments in the DetElement hierarchy + size_t checkNominals() const; /// Call to check a top level Detector element (subdetector) size_t checkDetectors() const; + /// Call to check segmentations starting from the top level Detector element + size_t checkSegmentations() const; /// Check all of the above size_t checkAll() const; }; diff --git a/DDCore/include/DD4hep/DetectorData.h b/DDCore/include/DD4hep/DetectorData.h index 5b547e50a6ac3852113ff0ad0dbe322b68f82c22..e8a6bfada25b27f24563859f8ac5819a8a35e259 100644 --- a/DDCore/include/DD4hep/DetectorData.h +++ b/DDCore/include/DD4hep/DetectorData.h @@ -150,6 +150,47 @@ namespace dd4hep { void clearData(); /// Adopt all data from source structure. void adoptData(DetectorData& source, bool CLR=true); + + /// Access the geometry manager of this instance + TGeoManager& manager() const { return *m_manager; } + /// Return handle to material describing air + dd4hep::Material air() const { return m_materialAir; } + /// Return handle to material describing vacuum + dd4hep::Material vacuum() const { return m_materialVacuum; } + /// Return handle to "invisible" visualization attributes + dd4hep::VisAttr invisible() const { return m_invisibleVis; } + /// Return reference to the top-most (world) detector element + dd4hep::DetElement world() const { return m_world; } + /// Return reference to detector element with all tracker devices. + dd4hep::DetElement trackers() const { return m_trackers; } + /// Return handle to the world volume containing everything + dd4hep::Volume worldVolume() const { return m_worldVol; } + /// Return handle to the world volume containing the volume with the tracking devices + dd4hep::Volume trackingVolume() const { return m_trackingVol; } + /// Return handle to the VolumeManager + dd4hep::VolumeManager volumeManager() const { return m_volManager; } + /// Return handle to the combined electromagentic field description. + dd4hep::OverlayedField field() const { return m_field; } + /// Accessor to the header entry + dd4hep::Header header() const { return m_header; } + /// Accessor to the map of constants + const Detector::HandleMap& constants() const { return m_define; } + /// Accessor to the map of visualisation attributes + const Detector::HandleMap& visAttributes() const { return m_display; } + /// Accessor to the map of limit settings + const Detector::HandleMap& limitsets() const { return m_limits; } + /// Accessor to the map of region settings + const Detector::HandleMap& regions() const { return m_regions; } + /// Accessor to the map of readout structures + const Detector::HandleMap& readouts() const { return m_readouts; } + /// Accessor to the map of sub-detectors + const Detector::HandleMap& detectors() const { return m_detectors; } + /// Retrieve a sensitive detector by it's name from the detector description + const Detector::HandleMap& sensitiveDetectors() const { return m_sensitive; } + /// Accessor to the map of field entries, which together form the global field + const Detector::HandleMap& fields() const { return m_fields; } + /// Accessor to the map of ID specifications + const Detector::HandleMap& idSpecifications() const { return m_idDict; } }; } /* End namespace dd4hep */ diff --git a/DDCore/include/DD4hep/DetectorLoad.h b/DDCore/include/DD4hep/DetectorLoad.h index daf83357a45df2f114ff5e57bde20bad01edf1c1..4c1f35ba4ca7ffd7cc6ae53919915c90be51a192 100644 --- a/DDCore/include/DD4hep/DetectorLoad.h +++ b/DDCore/include/DD4hep/DetectorLoad.h @@ -10,8 +10,8 @@ // Author : M.Frank // //========================================================================== -#ifndef DD4HEP_DDCORE_DetectorLOAD_H -#define DD4HEP_DDCORE_DetectorLOAD_H +#ifndef DD4HEP_DDCORE_DETECTORLOAD_H +#define DD4HEP_DDCORE_DETECTORLOAD_H // Framework includes #include "DD4hep/Detector.h" @@ -59,5 +59,5 @@ namespace dd4hep { virtual void processXMLElement(const xml::Handle_t& root, DetectorBuildType type); }; -} /* End namespace dd4hep */ -#endif /* DD4HEP_DDCORE_DetectorLOAD_H */ +} /* End namespace dd4hep */ +#endif /* DD4HEP_DDCORE_DETECTORLOAD_H */ diff --git a/DDCore/include/DD4hep/Dictionary.h b/DDCore/include/DD4hep/Dictionary.h index e9277981c048157287cb1848f2341ca6e7f0b38e..e53df5bc29d9be920a46e69b3bcc7d503b078e95 100644 --- a/DDCore/include/DD4hep/Dictionary.h +++ b/DDCore/include/DD4hep/Dictionary.h @@ -116,6 +116,7 @@ template class dd4hep::Handle<TNamed>; #pragma link C++ class dd4hep::OpaqueDataBlock+; #pragma link C++ class dd4hep::Detector+; +#pragma link C++ class dd4hep::DetectorLoad+; #pragma link C++ class dd4hep::DetectorData+; #pragma link C++ class dd4hep::DetectorData::ObjectHandleMap+; #pragma link C++ class dd4hep::Detector::PropertyValues+; diff --git a/DDCore/include/DD4hep/OpaqueData.h b/DDCore/include/DD4hep/OpaqueData.h index 4d816184bda07741aa850a9240c0b1597956762b..6e5b444d53ddadccfbf9f4c1a23216b7bed98137 100644 --- a/DDCore/include/DD4hep/OpaqueData.h +++ b/DDCore/include/DD4hep/OpaqueData.h @@ -75,6 +75,8 @@ namespace dd4hep { /// Class describing an opaque conditions data block /** + * This class is used to handle the actual data IO. + * Hence, we have write access to the data in abstract form. * * \author M.Frank * \version 1.0 @@ -107,10 +109,12 @@ namespace dd4hep { OpaqueDataBlock& operator=(const OpaqueDataBlock& clone); /// Move the data content: 'from' will be reset to NULL bool move(OpaqueDataBlock& from); + /// Write access to the data buffer. Is only valid after call to bind<T>() + void* ptr() const { return pointer; } /// Bind data value - bool bind(const BasicGrammar* grammar); + void* bind(const BasicGrammar* grammar); /// Bind data value in place - bool bind(void* ptr, size_t len, const BasicGrammar* grammar); + void* bind(void* ptr, size_t len, const BasicGrammar* grammar); /// Bind data value template <typename T> T& bind(); /// Bind data value diff --git a/DDCore/include/DD4hep/detail/AlignmentsInterna.h b/DDCore/include/DD4hep/detail/AlignmentsInterna.h index 5eee59e931b6e3f1de9e071c11c27d732bce5269..4611cf9dcf160b6982ca9aef9cb0de98b2c7ebdd 100644 --- a/DDCore/include/DD4hep/detail/AlignmentsInterna.h +++ b/DDCore/include/DD4hep/detail/AlignmentsInterna.h @@ -56,7 +56,7 @@ namespace dd4hep { class AlignmentObject : public detail::ConditionObject { public: /// Cached pointer to the bound conditions data, since these may be accessed very frequently - AlignmentData* alignment_data = 0; + AlignmentData* alignment_data = 0; //! This valiable is internally bound and not ROOT persistent! public: /// Default constructor. Alignment data wuill be bound to the heap. diff --git a/DDCore/include/DD4hep/detail/BasicGrammar_inl.h b/DDCore/include/DD4hep/detail/BasicGrammar_inl.h index 16c54aaab11ae3ee7b3719eeafbc7e90fd90b9cc..2de0631dc556cda94b15a81a1de3f8892410e293 100644 --- a/DDCore/include/DD4hep/detail/BasicGrammar_inl.h +++ b/DDCore/include/DD4hep/detail/BasicGrammar_inl.h @@ -53,8 +53,7 @@ namespace { static XmlTools::Evaluator& s__eval(dd4hep::g4Evaluator()); } namespace dd4hep { /// Standarsd constructor - template <typename TYPE> Grammar<TYPE>::Grammar() { - m_typeName = typeName(typeid(TYPE)); + template <typename TYPE> Grammar<TYPE>::Grammar() : BasicGrammar(typeName(typeid(TYPE))) { } /// Default destructor @@ -66,16 +65,16 @@ namespace dd4hep { return typeid(TYPE); } - /// PropertyGrammar overload: Access to the type information - template <typename TYPE> const std::string& Grammar<TYPE>::type_name() const { - return m_typeName; - } - /// Access the object size (sizeof operator) template <typename TYPE> size_t Grammar<TYPE>::sizeOf() const { return sizeof(TYPE); } + /// Bind opaque address to object + template <typename TYPE> void Grammar<TYPE>::bind(void* pointer) const { + new(pointer) TYPE(); + } + /// Evaluate string value if possible before calling boost::spirit template <typename TYPE> int Grammar<TYPE>::evaluate(void*, const std::string&) const { return 0; @@ -276,6 +275,7 @@ namespace dd4hep { // Containers of objects are not handled! } // End namespace dd4hep +#define DD4HEP_PARSER_GRAMMAR_CNAME(serial,name) namespace_dd4hep__grammar_##serial##_##name #define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ namespace dd4hep { \ @@ -285,61 +285,71 @@ namespace dd4hep { namespace dd4hep { \ template<> int Grammar<x >::evaluate(void* ptr, const std::string& val) const { return func ((x*)ptr,val); }} -#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_INSTANCE(serial,x) namespace DD4HEP_PARSER_GRAMMAR_CNAME(serial,0) { \ + static const ::dd4hep::BasicGrammar& DD4HEP_PARSER_GRAMMAR_CNAME(serial,100) = ::dd4hep::BasicGrammar::instance<x>(); } -#define DD4HEP_DEFINE_PARSER_GRAMMAR_DUMMY(x,func) \ - PARSERS_DECL_FOR_SINGLE(x) \ +#define DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,ctxt,x,func) \ DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) \ - namespace dd4hep { namespace Parsers { \ - int parse(x&, const std::string&) { return 1; } \ - }} + DD4HEP_DEFINE_PARSER_GRAMMAR_INSTANCE(DD4HEP_PARSER_GRAMMAR_CNAME(serial,ctxt),x) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_DUMMY_SERIAL(serial,x,func) \ + PARSERS_DECL_FOR_SINGLE(x) \ + namespace dd4hep { namespace Parsers { \ + int parse(x&, const std::string&) { return 1; } }} \ + DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_INSTANCE(serial,x) #if defined(DD4HEP_HAVE_ALL_PARSERS) -#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) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(std::deque<x>, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::int_map_t, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::ulong_map_t, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::string_map_t, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::int_pair_t, eval_pair) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::ulong_pair_t, eval_pair) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::string_pair_t, eval_pair) - -#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) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(serial,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,1,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,2,std::vector<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,3,std::list<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,4,std::set<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,5,std::deque<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,6,dd4hep::detail::Primitive<x>::int_map_t, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,7,dd4hep::detail::Primitive<x>::ulong_map_t, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,8,dd4hep::detail::Primitive<x>::string_map_t, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,9,dd4hep::detail::Primitive<x>::int_pair_t, eval_pair) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,10,dd4hep::detail::Primitive<x>::ulong_pair_t, eval_pair) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,11,dd4hep::detail::Primitive<x>::string_pair_t, eval_pair) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_VL_SERIAL(serial,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,12,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,13,std::vector<x>,eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,14,std::list<x>,eval_container) + +#define DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT_SERIAL(serial,x) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(serial,x,eval_item) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(serial,unsigned x,eval_item) #else -#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) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::int_map_t, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::string_map_t, eval_container) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::int_pair_t, eval_pair) \ - DD4HEP_DEFINE_PARSER_GRAMMAR(dd4hep::detail::Primitive<x>::string_pair_t, eval_pair) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(serial,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,1,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,2,std::vector<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,3,std::list<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,4,std::set<x>, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,5,dd4hep::detail::Primitive<x>::int_map_t, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,6,dd4hep::detail::Primitive<x>::string_map_t, eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,7,dd4hep::detail::Primitive<x>::int_pair_t, eval_pair) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,8,dd4hep::detail::Primitive<x>::string_pair_t, eval_pair) -#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_CONT_VL_SERIAL(serial,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,9,x,eval_func) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,10,std::vector<x>,eval_container) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(serial,11,std::list<x>,eval_container) -#define DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(x) \ - DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(x,eval_item) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT_SERIAL(serial,x) \ + DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(serial,x,eval_item) #endif +#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func) DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(__LINE__,__LINE__,x,func) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(x,eval_func) DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_SERIAL(__LINE__,x,eval_func) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT(x) DD4HEP_DEFINE_PARSER_GRAMMAR_U_CONT_SERIAL(__LINE__,x) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_VL(x,eval_func) DD4HEP_DEFINE_PARSER_GRAMMAR_CONT_VL_SERIAL(__LINE__x,eval_func) +#define DD4HEP_DEFINE_PARSER_GRAMMAR_DUMMY(x,func) DD4HEP_DEFINE_PARSER_GRAMMAR_DUMMY_SERIAL(__LINE__,x,func) + #endif /* DD4HEP_DDCORE_BASICGRAMMAR_INL_H */ diff --git a/DDCore/include/DD4hep/detail/ConditionsInterna.h b/DDCore/include/DD4hep/detail/ConditionsInterna.h index 072b38363d3649948575c9edbdada1307788e73a..b60184ef1988cd1907cfb421259b3e502a066948 100644 --- a/DDCore/include/DD4hep/detail/ConditionsInterna.h +++ b/DDCore/include/DD4hep/detail/ConditionsInterna.h @@ -68,7 +68,7 @@ namespace dd4hep { /// Data block OpaqueDataBlock data; /// Interval of validity - const IOV* iov = 0; + const IOV* iov = 0; //! No ROOT persistency /// Hash value of the name Condition::key_type hash = 0; /// Flags diff --git a/DDCore/include/DD4hep/detail/Grammar.h b/DDCore/include/DD4hep/detail/Grammar.h index b9579af79ec837bd07e7ee0aa4758c5050d67514..51803796b20cb9204962ffdef0d88925d9fe60d1 100644 --- a/DDCore/include/DD4hep/detail/Grammar.h +++ b/DDCore/include/DD4hep/detail/Grammar.h @@ -35,19 +35,16 @@ namespace dd4hep { */ template <typename TYPE> class Grammar : public BasicGrammar { friend class BasicGrammar; - /// Cached type information name - std::string m_typeName; - public: /// Default destructor virtual ~Grammar(); /// Standarsd constructor Grammar(); + public: + /** Base class overrides */ /// PropertyGrammar overload: Access to the type information virtual const std::type_info& type() const override; - /// Access to the type information name - virtual const std::string& type_name() const override; /// Access the object size (sizeof operator) virtual size_t sizeOf() const override; /// PropertyGrammar overload: Serialize a property to a string @@ -58,6 +55,8 @@ namespace dd4hep { virtual void destruct(void* pointer) const override; /// Opaque object copy construction. Memory must be allocated externally virtual void copy(void* to, const void* from) const override; + /// Bind opaque address to object + virtual void bind(void* pointer) const override; /** Class member function */ /// Evaluate string value if possible before calling boost::spirit diff --git a/DDCore/src/BasicGrammar.cpp b/DDCore/src/BasicGrammar.cpp index 18c4419ace2d4259d4287b0a494dc3b08636baec..d55ffac8bc3a40bc08246425d2ecba8a3ea8d6dc 100644 --- a/DDCore/src/BasicGrammar.cpp +++ b/DDCore/src/BasicGrammar.cpp @@ -12,21 +12,83 @@ //========================================================================== // Framework include files +#include "DD4hep/Printout.h" #include "DD4hep/Primitives.h" #include "DD4hep/Exceptions.h" #include "DD4hep/BasicGrammar.h" +// ROOT include files +#include "TDataType.h" +#include "TROOT.h" + // C/C++ include files #include <stdexcept> +#include <mutex> +#include <map> + +namespace { + + std::mutex s_mutex; + + // This static object needs to be in function to trick out static constructors populating this registry.... + static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*>& registry() { + static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*> s_registry; + return s_registry; + } +} /// Default constructor -dd4hep::BasicGrammar::BasicGrammar() { - self = this; +dd4hep::BasicGrammar::BasicGrammar(const std::string& typ) + : name(typ), hash_value(dd4hep::detail::hash64(typ)) +{ + if ( !registry().insert(std::make_pair(hash_value,this)).second ) { + // Error: Already existing grammar. + dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]",name.c_str(), hash_value); + } } /// Default destructor dd4hep::BasicGrammar::~BasicGrammar() { - self = 0; +} + +/// Second step initialization after the virtual table is fixed +void dd4hep::BasicGrammar::initialize() const { + std::lock_guard<std::mutex> lock(s_mutex); + if ( !inited ) { + TClass* cl = gROOT->GetClass(type()); + if ( cl ) { + root_class = cl; + inited = true; + return; + } + root_data_type = TDataType::GetType(type()); + if ( root_data_type == kOther_t ) { + except("BasicGrammar", + "+++ ERROR +++ Cannot initialize gammar object: %s. " + "No TClass and no data type information present!",name.c_str()); + } + inited = true; + } +} + +/// Access ROOT data type for fundamentals +int dd4hep::BasicGrammar::initialized_data_type() const { + this->initialize(); + return root_data_type; +} + +/// Access the ROOT class for complex objects +TClass* dd4hep::BasicGrammar::initialized_clazz() const { + this->initialize(); + return root_class; +} + +/// Lookup existing grammar using hash code (reading objects) +const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(key_type hash_code) { + auto i = registry().find(hash_code); + if ( i != registry().end() ) return *((*i).second); + dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX",hash_code); + throw "Error"; // Not reachable anyhow. Simply to please the compiler! } /// Error callback on invalid conversion @@ -45,3 +107,4 @@ void dd4hep::BasicGrammar::invalidConversion(const std::type_info& from, const s "Data conversion from '" + from_name + "' to '" + to_name + "' is not implemented."); } + diff --git a/DDCore/src/DD4hepRootPersistency.cpp b/DDCore/src/DD4hepRootPersistency.cpp index 8869f71bf623ae27e32aef8d2ed733ab1a50b2df..e58fe3b5487683c84193e18d5198066036891618 100644 --- a/DDCore/src/DD4hepRootPersistency.cpp +++ b/DDCore/src/DD4hepRootPersistency.cpp @@ -18,31 +18,19 @@ #include "DD4hep/detail/SegmentationsInterna.h" // ROOT include files -#include "TClassStreamer.h" -#include "TDataMember.h" -#include "TClass.h" #include "TFile.h" -#include "TROOT.h" +#include "TTimeStamp.h" ClassImp(DD4hepRootPersistency) using namespace dd4hep; using namespace std; -namespace { - void stream_opaque_datablock(TBuffer& b, void* obj) { - if ( b.IsReading() ) { - printout(INFO,"OpaqueData","Streaming IN opaque data object..."); - } - else { - printout(INFO,"OpaqueData","Streaming OUT opaque data object..."); - } - } -} int DD4hepRootPersistency::save(Detector& description, const char* fname, const char* instance) { TFile* f = TFile::Open(fname,"RECREATE"); if ( f && !f->IsZombie()) { + TTimeStamp start; DD4hepRootPersistency* persist = new DD4hepRootPersistency(); persist->m_data = new dd4hep::DetectorData(); persist->m_data->adoptData(dynamic_cast<DetectorData&>(description),false); @@ -60,35 +48,14 @@ int DD4hepRootPersistency::save(Detector& description, const char* fname, const } } printout(ALWAYS,"DD4hepRootPersistency","+++ Saving %ld nominals....",persist->nominals.size()); -#if 0 - TClass* opaqueCl = gROOT->GetClass("dd4hep::OpaqueDataBlock"); - if ( 0 == opaqueCl ) { - printout(ERROR,"DD4hepRootPersistency","+++ Missing TClass for 'dd4hep::OpaqueDataBlock'."); - return 0; - } - if ( 0 == opaqueCl->GetStreamer() ) { - opaqueCl->AdoptStreamer(new TClassStreamer(stream_opaque_datablock)); - printout(ALWAYS,"DD4hepRootPersistency","+++ Set Streamer to %s",opaqueCl->GetName()); - } -#endif - TDataMember* m = 0; - TClass* volCl = TGeoVolume::Class(); - printout(ALWAYS,"DD4hepRootPersistency","+++ Patching %s.fUserExtension to persistent",volCl->GetName()); - m = volCl->GetDataMember("fUserExtension"); - m->SetTitle(m->GetTitle()+2); - m->SetBit(BIT(2)); - TClass* nodCl = TGeoNode::Class(); - printout(ALWAYS,"DD4hepRootPersistency","+++ Patching %s.fUserExtension to persistent",nodCl->GetName()); - m = nodCl->GetDataMember("fUserExtension"); - m->SetTitle(m->GetTitle()+2); - m->SetBit(BIT(2)); - + /// Now we write the object int nBytes = persist->Write(instance); f->Close(); + TTimeStamp stop; printout(ALWAYS,"DD4hepRootPersistency", - "+++ Wrote %d Bytes of geometry data '%s' to '%s'.", - nBytes, instance, fname); + "+++ Wrote %d Bytes of geometry data '%s' to '%s' [%8.3f seconds].", + nBytes, instance, fname, stop.AsDouble()-start.AsDouble()); if ( nBytes > 0 ) { printout(ALWAYS,"DD4hepRootPersistency", "+++ Successfully saved geometry data to file."); @@ -102,42 +69,19 @@ int DD4hepRootPersistency::save(Detector& description, const char* fname, const } int DD4hepRootPersistency::load(Detector& description, const char* fname, const char* instance) { -#if 0 - TClass* opaqueCl = gROOT->GetClass("dd4hep::OpaqueDataBlock"); - if ( 0 == opaqueCl ) { - printout(ERROR,"DD4hepRootPersistency","+++ Missing TClass for 'dd4hep::OpaqueDataBlock'."); - return 0; - } - if ( 0 == opaqueCl->GetStreamer() ) { - opaqueCl->AdoptStreamer(new TClassStreamer(stream_opaque_datablock)); - printout(ALWAYS,"DD4hepRootPersistency","+++ Set Streamer to %s",opaqueCl->GetName()); - } -#endif - TDataMember* m = 0; - TClass* volCl = TGeoVolume::Class(); - printout(ALWAYS,"DD4hepRootPersistency","+++ Patching %s.fUserExtension to persistent",volCl->GetName()); - m = volCl->GetDataMember("fUserExtension"); - m->SetTitle(m->GetTitle()+2); - m->SetBit(BIT(2)); - TClass* nodCl = TGeoNode::Class(); - printout(ALWAYS,"DD4hepRootPersistency","+++ Patching %s.fUserExtension to persistent",nodCl->GetName()); - m = nodCl->GetDataMember("fUserExtension"); - m->SetTitle(m->GetTitle()+2); - m->SetBit(BIT(2)); - - TFile* f = TFile::Open(fname); if ( f && !f->IsZombie()) { - DD4hepRootPersistency* persist = (DD4hepRootPersistency*)f->Get(instance); - if ( persist ) { - DetectorData& data = dynamic_cast<DetectorData&>(description); - DetectorData* target = persist->m_data; - for( const auto& s : target->m_idDict ) { + TTimeStamp start; + unique_ptr<DD4hepRootPersistency> persist((DD4hepRootPersistency*)f->Get(instance)); + if ( persist.get() ) { + DetectorData* source = persist->m_data; + const auto& iddesc = persist->idSpecifications(); + for( const auto& s : iddesc ) { IDDescriptor id = s.second; id.rebuild(id->description); } printout(ALWAYS,"DD4hepRootPersistency", - "+++ Fixed %ld IDDescriptor objects.",target->m_idDict.size()); + "+++ Fixed %ld IDDescriptor objects.",iddesc.size()); for( const auto& s : persist->m_segments ) { Readout ro = s.first; IDDescriptor id = s.second.first; @@ -148,7 +92,6 @@ int DD4hepRootPersistency::load(Detector& description, const char* fname, const printout(ALWAYS,"DD4hepRootPersistency", "+++ Fixed %ld segmentation objects.",persist->m_segments.size()); persist->m_segments.clear(); - const auto& sdets = persist->volumeManager()->subdetectors; size_t num[3] = {0,0,0}; for( const auto& vm : sdets ) { @@ -170,15 +113,14 @@ int DD4hepRootPersistency::load(Detector& description, const char* fname, const } printout(ALWAYS,"DD4hepRootPersistency", "+++ Fixed VolumeManager TOTALS %-24s %6ld volumes %4ld sdets %4ld mgrs.","",num[0],num[1],num[2]); - - printout(ALWAYS,"DD4hepRootPersistency","+++ loaded %ld nominals....",persist->nominals.size()); - - data.adoptData(*target); - //target->clearData(); - delete persist; + DetectorData* tar_data = dynamic_cast<DetectorData*>(&description); + DetectorData* src_data = dynamic_cast<DetectorData*>(source); + tar_data->adoptData(*src_data,false); + TTimeStamp stop; printout(ALWAYS,"DD4hepRootPersistency", - "+++ Successfully loaded detector description from file:%s",fname); + "+++ Successfully loaded detector description from file:%s [%8.3f seconds]", + fname, stop.AsDouble()-start.AsDouble()); return 1; } printout(ERROR,"DD4hepRootPersistency", @@ -192,6 +134,10 @@ int DD4hepRootPersistency::load(Detector& description, const char* fname, const return 0; } + +#include "DD4hep/detail/DetectorInterna.h" +#include "DD4hep/detail/ConditionsInterna.h" +#include "DD4hep/detail/AlignmentsInterna.h" namespace { class PersistencyChecks { @@ -380,6 +326,55 @@ namespace { fld.name()); return 1; } + size_t checkAlignment(DetElement det) { + AlignmentCondition::Object* align = det->nominal.ptr(); + if ( 0 == align ) { + printout(ERROR,"chkNominals", + "+++ ERROR +++ Detector element with invalid nominal:%s", + det.path().c_str()); + ++errors; + } + else if ( 0 == align->alignment_data ) { + printout(ERROR,"chkNominals", + "+++ ERROR +++ Detector element with invalid nominal data:%s", + det.path().c_str()); + ++errors; + } + else if ( Condition(align).data().ptr() != align->alignment_data ) { + printout(ERROR,"chkNominals", + "+++ ERROR +++ Detector element with inconsisten nominal data:%s [%p != %p]", + det.path().c_str(),Condition(align).data().ptr(),align->alignment_data); + ++errors; + } + else { + return 1; + } + return 0; + } + + /// Check nominal alignments of the volume manager + size_t checkNominals(VolumeManager mgr) { + int count = 0; + const auto& sdets = mgr->subdetectors; + for( const auto& vm : sdets ) { + VolumeManager::Object* obj = vm.second.ptr(); + for( const auto& iv : obj->volumes ) { + VolumeManagerContext* ctx = iv.second; + count += checkAlignment(ctx->element); + } + } + return count; + } + size_t checkDetectorNominals(DetElement d) { + int count = 0; + Volume v = d.placement().volume(); + if ( v.isSensitive() ) { + count += checkAlignment(d); + } + for( const auto& c : d.children() ) + count += checkDetectorNominals(c.second); + return count; + } }; } @@ -389,8 +384,8 @@ size_t DD4hepRootCheck::checkConstants() const { PersistencyChecks checks; for( const auto& obj : object->constants() ) count += checks.checkConstant(obj); - printout(ALWAYS,"chkProperty","+++ Checked %ld Constant objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkProperty","+++ %s Checked %ld Constant objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -400,8 +395,8 @@ size_t DD4hepRootCheck::checkProperties() const { PersistencyChecks checks; for( const auto& obj : object->properties() ) count += checks.checkProperty(obj); - printout(ALWAYS,"chkProperty","+++ Checked %ld Property objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkProperty","+++ %s Checked %ld Property objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -418,9 +413,16 @@ size_t DD4hepRootCheck::checkReadouts() const { PersistencyChecks checks; for( const auto& obj : object->readouts() ) count += checks.checkReadout(obj.second); - printout(ALWAYS,"chkReadouts","+++ Checked %ld Readout objects. Num.Errors: %ld", - count, checks.errors); - return checks.errors; + + if ( object->sensitiveDetectors().size() != object->readouts().size() ) { + printout(ERROR,"chkNominals", + "+++ Number of sensitive detectors does NOT match number of readouts: %ld != %ld", + object->sensitiveDetectors().size(),object->readouts().size()); + ++checks.errors; + } + printout(ALWAYS,"chkNominals","+++ %s Checked %ld readout objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); + return count; } /// Call to theck the DD4hep fields @@ -429,8 +431,8 @@ size_t DD4hepRootCheck::checkFields() const { PersistencyChecks checks; for( const auto& obj : object->fields() ) count += checks.checkField(obj.second); - printout(ALWAYS,"chkFields","+++ Checked %ld Field objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkFields","+++ %s Checked %ld Field objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -440,8 +442,8 @@ size_t DD4hepRootCheck::checkRegions() const { PersistencyChecks checks; for( const auto& obj : object->regions() ) count += checks.checkRegion(obj.second); - printout(ALWAYS,"chkRegions","+++ Checked %ld Region objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkRegions","+++ %s Checked %ld Region objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -451,8 +453,8 @@ size_t DD4hepRootCheck::checkIdSpecs() const { PersistencyChecks checks; for( const auto& obj : object->idSpecifications() ) count += checks.checkIDDescriptor(obj.second); - printout(ALWAYS,"chkReadouts","+++ Checked %ld Readout objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkReadouts","+++ %s Checked %ld Readout objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -462,8 +464,8 @@ size_t DD4hepRootCheck::checkDetectors() const { PersistencyChecks checks; for( const auto& obj : object->detectors() ) count += checks.checkDetector(obj.second); - printout(ALWAYS,"chkDetectors","+++ Checked %ld DetElement objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkDetectors","+++ %s Checked %ld DetElement objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -473,8 +475,8 @@ size_t DD4hepRootCheck::checkSensitives() const { PersistencyChecks checks; for( const auto& obj : object->sensitiveDetectors() ) count += checks.checkSensitive(obj.second); - printout(ALWAYS,"chkSensitives","+++ Checked %ld SensitiveDetector objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkSensitives","+++ %s Checked %ld SensitiveDetector objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } @@ -484,16 +486,43 @@ size_t DD4hepRootCheck::checkLimitSets() const { size_t count = 0; for( const auto& obj : object->limitsets() ) count += checks.checkLimitset(obj.second); - printout(ALWAYS,"chkSensitives","+++ Checked %ld SensitiveDetector objects. Num.Errors: %ld", - count, checks.errors); + printout(ALWAYS,"chkSensitives","+++ %s Checked %ld SensitiveDetector objects. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return checks.errors; } /// Call to check the volume manager hierarchy size_t DD4hepRootCheck::checkVolManager() const { - const void* args[] = {"SiTrackerBarrel",0}; - size_t count = object->apply("DD4hepVolumeMgrTest",1,(char**)args); - printout(ALWAYS,"chkVolumeMgr","+++ Checked %ld Volume objects.",count); + PersistencyChecks checks; + size_t count = checks.checkNominals(object->volumeManager()); + printout(ALWAYS,"chkNominals","+++ %s Checked %ld VolumeManager contexts. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); + return count; +} + +/// Call to check the nominal alignments in the detector hierarchy (for sensitive detectors) +size_t DD4hepRootCheck::checkNominals() const { + size_t count = 0; + PersistencyChecks checks; + const auto& dets = object->sensitiveDetectors(); + for( const auto& d : dets ) + count += checks.checkDetectorNominals(object->detector(d.first)); + printout(ALWAYS,"chkNominals","+++ %s Checked %ld DetElements. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); + return count; +} + +/// Call to check the segmentations starting from the top level detector +size_t DD4hepRootCheck::checkSegmentations() const { + size_t count = 0; + PersistencyChecks checks; + const auto& dets = object->sensitiveDetectors(); + for( const auto& d : dets ) { + Segmentation seg = SensitiveDetector(d.second).readout().segmentation(); + if ( seg.isValid() ) count += checks.checkSegmentation(seg); + } + printout(ALWAYS,"chkNominals","+++ %s Checked %ld readout segmentations. Num.Errors: %ld", + checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); return count; } diff --git a/DDCore/src/DetectorData.cpp b/DDCore/src/DetectorData.cpp index 6f2559c9f620196a03888143dc943adf9feb6fa9..83ba19d7651656623ae158333dd94fb013d76e34 100644 --- a/DDCore/src/DetectorData.cpp +++ b/DDCore/src/DetectorData.cpp @@ -12,6 +12,7 @@ //========================================================================== // Framework include files +#include "DD4hep/BasicGrammar.h" #include "DD4hep/DetectorData.h" #include "DD4hep/InstanceCount.h" #include "DD4hep/detail/ObjectsInterna.h" @@ -19,12 +20,135 @@ // ROOT include files #include "TGeoManager.h" +#include "TClassStreamer.h" +#include "TDataMember.h" +#include "TDataType.h" +#include "TClass.h" +#include "TROOT.h" + namespace dd4hep { namespace detail { class DetectorImp; }} using namespace dd4hep::detail; using namespace dd4hep; +namespace { + + union FundamentalData { + Char_t c; + Short_t s; + Int_t i; + Long_t l; + Float_t f; + Double_t d; + UChar_t uc; + UShort_t us; + UInt_t ui; + ULong_t ul; + Long64_t ll; + ULong64_t ull; + Bool_t b; + void read(TBuffer& buff,int dtyp) { + switch(dtyp) { + case 1: buff >> c; break; + case 2: buff >> s; break; + case 3: buff >> i; break; + case 4: buff >> l; break; + case 5: buff >> f; break; + case 6: buff >> i; break; + //case 7: buff >> d; break; // char* + case 8: buff >> d; break; + case 9: buff >> d; break; + case 11: buff >> uc; break; + case 12: buff >> us; break; + case 13: buff >> ui; break; + case 14: buff >> ul; break; + case 15: buff >> ui; break; + case 16: buff >> ll; break; + case 17: buff >> ull; break; + case 18: buff >> b; break; + case 19: buff >> f; break; + default: + printout(ERROR,"OpaqueData","Unknown fundamental data type: [%X]",dtyp); + break; + } + } + void write(TBuffer& buff,int dtyp) const { + switch(dtyp) { + case 1: buff << c; break; + case 2: buff << s; break; + case 3: buff << i; break; + case 4: buff << l; break; + case 5: buff << f; break; + case 6: buff << i; break; + //case 7: buff << d; break; // char* + case 8: buff << d; break; + case 9: buff << d; break; + case 11: buff << uc; break; + case 12: buff << us; break; + case 13: buff << ui; break; + case 14: buff << ul; break; + case 15: buff << ui; break; + case 16: buff << ll; break; + case 17: buff << ull; break; + case 18: buff << b; break; + case 19: buff << f; break; + default: + printout(ERROR,"OpaqueData","Unknown fundamental data type: [%X]",dtyp); + break; + } + } + }; + + void stream_opaque_datablock(TBuffer& b, void* obj) { + UInt_t R__s = 0; // Start of object. + UInt_t R__c = 0; // Count of bytes. + TClass* cl = BasicGrammar::instance<OpaqueDataBlock>().clazz();//gROOT->GetClass("dd4hep::OpaqueDataBlock"); + + OpaqueDataBlock* block = (OpaqueDataBlock*)obj; + if ( b.IsReading() ) { + b.ReadVersion(&R__s, &R__c, cl); + BasicGrammar::key_type key = 0; + b >> key; + const BasicGrammar& gr = BasicGrammar::get(key); + //printout(INFO,"OpaqueData"," Data type:%s [%016llX]",gr.name.c_str(),key); + void* ptr = block->ptr(); + if ( !ptr ) { // Some blocks are already bound. Skip those. + ptr = block->bind(&gr); + gr.bind(ptr); + } + /// Now perform the I/O action + if ( gr.type() == typeid(std::string) ) + b.ReadStdString(*(std::string*)ptr); + else if ( gr.clazz() ) + b.ReadClassBuffer(gr.clazz(),ptr); + else + ((FundamentalData*)ptr)->read(b,gr.data_type()); + b.CheckByteCount(R__s, R__c, cl); + } + else if ( 0 == block->grammar ) { + printout(ERROR,"OpaqueData","+++ ERROR +++ Opaque data block has no grammar attached. Cannot be saved!"); + } + else { + const BasicGrammar& gr = *block->grammar; + std::string typ = gr.type_name(); + R__c = b.WriteVersion(cl,kTRUE); + b << gr.hash(); + //printout(INFO,"OpaqueData"," Data type:%s Grammar:%s",typ.c_str(),block->grammar->name.c_str()); + + /// Now perform the I/O action + if ( gr.type() == typeid(std::string) ) + b.WriteStdString(*(std::string*)block->ptr()); + else if ( gr.clazz() ) + b.WriteClassBuffer(gr.clazz(),block->ptr()); + else + ((const FundamentalData*)block->ptr())->write(b,gr.data_type()); + b.SetByteCount(R__c, kTRUE); + } + } +} + + /// Default constructor DetectorData::DetectorData() : m_manager(0), m_world(), m_trackers(), m_worldVol(), @@ -32,6 +156,29 @@ DetectorData::DetectorData() m_buildType(BUILD_DEFAULT), m_extensions(typeid(DetectorData)), m_volManager(), m_inhibitConstants(false) { + static bool first = true; + if ( first ) { + first = false; + TClass* cl = gROOT->GetClass("dd4hep::OpaqueDataBlock"); + if ( 0 == cl ) { + except("PersistencyIO","+++ Missing TClass for 'dd4hep::OpaqueDataBlock'."); + } + if ( 0 == cl->GetStreamer() ) { + cl->AdoptStreamer(new TClassStreamer(stream_opaque_datablock)); + printout(INFO,"PersistencyIO","+++ Set Streamer to %s",cl->GetName()); + } + TDataMember* m = 0; + cl = TGeoVolume::Class(); + printout(INFO,"PersistencyIO","+++ Patching %s.fUserExtension to persistent",cl->GetName()); + m = cl->GetDataMember("fUserExtension"); + m->SetTitle(m->GetTitle()+2); + m->SetBit(BIT(2)); + cl = TGeoNode::Class(); + printout(INFO,"PersistencyIO","+++ Patching %s.fUserExtension to persistent",cl->GetName()); + m = cl->GetDataMember("fUserExtension"); + m->SetTitle(m->GetTitle()+2); + m->SetBit(BIT(2)); + } InstanceCount::increment(this); } diff --git a/DDCore/src/DetectorImp.cpp b/DDCore/src/DetectorImp.cpp index 47253ea4d60db7bcaebfef101d804f034d579e36..1c5487fabdcf967eb8ba0ae600971f3448a4de8b 100644 --- a/DDCore/src/DetectorImp.cpp +++ b/DDCore/src/DetectorImp.cpp @@ -34,6 +34,7 @@ #include "TGeoVolume.h" #include "TGeoShape.h" #include "TClass.h" + #include "XML/DocumentHandler.h" #if DD4HEP_USE_PYROOT @@ -102,12 +103,12 @@ void Detector::destroyInstance() { } /// Default constructor -DetectorImp::DetectorImp() : DetectorData(), DetectorLoad(this), m_buildType(BUILD_NONE) +DetectorImp::DetectorImp() + : DetectorData(), DetectorLoad(this), m_buildType(BUILD_NONE) { - set_unexpected( description_unexpected ) ; set_terminate( description_unexpected ) ; - + InstanceCount::increment(this); if (0 == gGeoManager) { gGeoManager = new TGeoManager("world", "Detector Geometry"); diff --git a/DDCore/src/DetectorImp.h b/DDCore/src/DetectorImp.h index 50d4f7122c4ca33adad50d5a14a77706e2608f11..9536feb4e37723873e566264966afff59716d2b6 100644 --- a/DDCore/src/DetectorImp.h +++ b/DDCore/src/DetectorImp.h @@ -352,4 +352,8 @@ namespace dd4hep { }; } /* End namespace dd4hep */ + +#if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) +#pragma link C++ class dd4hep::DetectorImp+; +#endif #endif /* dd4hep_DetectorGEOIMP_H */ diff --git a/DDCore/src/OpaqueData.cpp b/DDCore/src/OpaqueData.cpp index ad93d449b148bb89b5e34e5186f9c27c68883ac5..9f5543cb9f1dbf3d7ffa74a86a4add034fd7959c 100644 --- a/DDCore/src/OpaqueData.cpp +++ b/DDCore/src/OpaqueData.cpp @@ -119,15 +119,15 @@ OpaqueDataBlock& OpaqueDataBlock::operator=(const OpaqueDataBlock& c) { return *this; } -/// Set data value -bool OpaqueDataBlock::bind(const BasicGrammar* g) { +/// Bind data value +void* OpaqueDataBlock::bind(const BasicGrammar* g) { if ( !grammar ) { size_t len = g->sizeOf(); grammar = g; (len > sizeof(data)) ? (pointer=::operator new(len),type=ALLOC_DATA) : (pointer=data,type=PLAIN_DATA); - return true; + return pointer; } else if ( grammar == g ) { // We cannot ingore secondary requests for data bindings. @@ -135,11 +135,11 @@ bool OpaqueDataBlock::bind(const BasicGrammar* g) { except("OpaqueData","You may not bind opaque multiple times!"); } typeinfoCheck(grammar->type(),g->type(),"Opaque data blocks may not be assigned."); - return false; + return 0; } /// Set data value -bool OpaqueDataBlock::bind(void* ptr, size_t size, const BasicGrammar* g) { +void* OpaqueDataBlock::bind(void* ptr, size_t size, const BasicGrammar* g) { if ( !grammar ) { size_t len = g->sizeOf(); grammar = g; @@ -149,7 +149,7 @@ bool OpaqueDataBlock::bind(void* ptr, size_t size, const BasicGrammar* g) { pointer=data, type=PLAIN_DATA; else pointer=::operator new(len),type=ALLOC_DATA; - return true; + return pointer; } else if ( grammar == g ) { // We cannot ingore secondary requests for data bindings. @@ -157,7 +157,7 @@ bool OpaqueDataBlock::bind(void* ptr, size_t size, const BasicGrammar* g) { except("OpaqueData","You may not bind opaque multiple times!"); } typeinfoCheck(grammar->type(),g->type(),"Opaque data blocks may not be assigned."); - return false; + return 0; } /// Set data value @@ -170,3 +170,18 @@ void OpaqueDataBlock::assign(const void* ptr, const type_info& typ) { } grammar->copy(pointer,ptr); } + +/// print Conditions object +std::ostream& operator << (std::ostream& s, const OpaqueDataBlock& data) { + s << data.str(); + return s; +} +#include "DDParsers/Parsers.h" +#include "DDParsers/ToStream.h" +DD4HEP_DEFINE_PARSER_DUMMY(OpaqueDataBlock) + +#include "DD4hep/detail/BasicGrammar_inl.h" +#include "DD4hep/detail/ConditionsInterna.h" +DD4HEP_DEFINE_PARSER_GRAMMAR(OpaqueDataBlock,eval_none<OpaqueDataBlock>) +DD4HEP_DEFINE_CONDITIONS_TYPE(OpaqueDataBlock) + diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 4501bb1fe30ee40902165627f98e8dbd23f4b30a..b982d9cf387fd113fc55b74cb3c2e028d30a7c69 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -536,6 +536,20 @@ static long load_geometryFromroot(Detector& description, int argc, char** argv) } DECLARE_APPLY(DD4hepRootLoader,load_geometryFromroot) +/// Basic entry point to check sensitive detector strictures +/** + * Factory: DD4hepCheckDetectors + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2014 + */ +static long check_detectors(Detector& description, int /* argc */, char** /* argv */) { + DD4hepRootCheck check(&description); + return check.checkDetectors(); +} +DECLARE_APPLY(DD4hepCheckDetectors,check_detectors) + /// Basic entry point to check sensitive detector strictures /** * Factory: DD4hepCheckSensitives @@ -552,17 +566,17 @@ DECLARE_APPLY(DD4hepCheckSensitives,check_sensitives) /// Basic entry point to check sensitive detector strictures /** - * Factory: DD4hepCheckDetectors + * Factory: DD4hepCheckSegmentations * * \author M.Frank * \version 1.0 * \date 01/04/2014 */ -static long check_detectors(Detector& description, int /* argc */, char** /* argv */) { +static long check_segmentations(Detector& description, int /* argc */, char** /* argv */) { DD4hepRootCheck check(&description); - return check.checkDetectors(); + return check.checkSegmentations(); } -DECLARE_APPLY(DD4hepCheckDetectors,check_detectors) +DECLARE_APPLY(DD4hepCheckSegmentations,check_segmentations) /// Basic entry point to check sensitive detector strictures /** @@ -592,6 +606,34 @@ static long check_idspecs(Detector& description, int /* argc */, char** /* argv } DECLARE_APPLY(DD4hepCheckIdspecs,check_idspecs) +/// Basic entry point to check IDDescriptors of the detector object +/** + * Factory: DD4hepCheckVolumeManager + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2014 + */ +static long check_volumemanager(Detector& description, int /* argc */, char** /* argv */) { + DD4hepRootCheck check(&description); + return check.checkVolManager(); +} +DECLARE_APPLY(DD4hepCheckVolumeManager,check_volumemanager) + +/// Basic entry point to check IDDescriptors of the detector object +/** + * Factory: DD4hepCheckNominals + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2014 + */ +static long check_nominals(Detector& description, int /* argc */, char** /* argv */) { + DD4hepRootCheck check(&description); + return check.checkNominals(); +} +DECLARE_APPLY(DD4hepCheckNominals,check_nominals) + /// Basic entry point to print out the volume hierarchy /** * Factory: DD4hepVolumeDump diff --git a/examples/CLICSiD/CMakeLists.txt b/examples/CLICSiD/CMakeLists.txt index 4521b9b64240117086283159002289ad38944c96..ba6d2fbb5706c5cf30f9e5ab0c038a599261a406 100644 --- a/examples/CLICSiD/CMakeLists.txt +++ b/examples/CLICSiD/CMakeLists.txt @@ -58,37 +58,6 @@ dd4hep_add_test_reg( CLICSiD_check_overlaps_LONGTEST --tolerance=0.1 REGEX_PASS " Execution finished..." ) # -# Test saving geometry to ROOT file -dd4hep_add_test_reg( CLICSiD_ROOT_Save_LONGTEST - COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" - EXEC_ARGS geoPluginRun - -volmgr -destroy -input file:${CMAKE_CURRENT_SOURCE_DIR}/compact/compact.xml - -plugin DD4hepGeometry2ROOT -output CLICSiD_geometry.root - REGEX_PASS "\\+\\+\\+ Successfully saved geometry data to file.") -# -# Test restoring geometry from ROOT file: Volume Manager -dd4hep_add_test_reg( CLICSiD_ROOT_Restore_LONGTEST - COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" - EXEC_ARGS geoPluginRun -print WARNING - -plugin DD4hepRootLoader CLICSiD_geometry.root - REGEX_PASS "\\+\\+\\+ Successfully loaded detector description from file") -# -# Test restoring geometry from ROOT file: Volume Manager -dd4hep_add_test_reg( CLICSiD_ROOT_Restore_VolMgr_LONGTEST - COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" - EXEC_ARGS geoPluginRun -print WARNING - -plugin DD4hepRootLoader CLICSiD_geometry.root - -plugin DD4hepVolumeMgrTest SiTrackerBarrel - REGEX_PASS "\\+\\+\\+ PASSED: Checked 81306 objects. Num.Errors:0") -# -# Test restoring geometry from ROOT file: Volume Manager -dd4hep_add_test_reg( CLICSiD_ROOT_Restore_Sensitives_LONGTEST - COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" - EXEC_ARGS geoPluginRun -print WARNING - -plugin DD4hepRootLoader CLICSiD_geometry.root - -plugin DD4hepCheckSensitives - REGEX_PASS "\\+\\+\\+ Checked 14 SensitiveDetector objects. Num.Errors: 0") -# #---Geant4 Testsing----------------------------------------------------------------- # if (DD4HEP_USE_GEANT4) diff --git a/examples/Persistency/CMakeLists.txt b/examples/Persistency/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..51d7751ad9b43a1dffe9bcd3df55341f20c32394 --- /dev/null +++ b/examples/Persistency/CMakeLists.txt @@ -0,0 +1,121 @@ +#========================================================================== +# AIDA Detector description implementation +#-------------------------------------------------------------------------- +# Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +# All rights reserved. +# +# For the licensing terms see $DD4hepINSTALL/LICENSE. +# For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +# +#========================================================================== +cmake_minimum_required(VERSION 3.3 FATAL_ERROR) +include ( ${DD4hep_DIR}/cmake/DD4hep.cmake ) + +#-------------------------------------------------------------------------- +dd4hep_configure_output () +dd4hep_package ( Persistency MAJOR 0 MINOR 0 PATCH 1 + USES [ROOT REQUIRED COMPONENTS Geom GenVector] + [DD4hep REQUIRED COMPONENTS DDCore] + OPTIONAL XERCESC +) +#----------------------------------------------------------------------------------- +dd4hep_add_plugin(PersistencyExample SOURCES src/*.cpp) +dd4hep_configure_scripts (Persistency DEFAULT_SETUP WITH_TESTS ) +#-------------------------------------------------------------------------- +# +# Test saving conditions to ROOT file +dd4hep_add_test_reg( Persist_Conditions_Save + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun + -plugin DD4hep_PersistencyExample_write_cond -output Conditions.root + REGEX_PASS "\\+\\+\\+ Wrote 1360 bytes to file Conditions.root" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Volume Manager +dd4hep_add_test_reg( Persist_Conditions_Restore + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun + -plugin DD4hep_PersistencyExample_read_cond -input Conditions.root + REGEX_PASS "\\+\\+\\+ Read successfully 14 conditions. Result=1637" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test saving geometry to ROOT file +dd4hep_add_test_reg( Persist_CLICSiD_Save_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun + -volmgr -destroy -input file:${CMAKE_CURRENT_SOURCE_DIR}/../CLICSiD/compact/compact.xml + -plugin DD4hepGeometry2ROOT -output CLICSiD_geometry.root + REGEX_PASS "\\+\\+\\+ Successfully saved geometry data to file." + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Volume Manager +dd4hep_add_test_reg( Persist_CLICSiD_Restore_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + REGEX_PASS "\\+\\+\\+ Successfully loaded detector description from file" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Volume Manager loading+nominals +dd4hep_add_test_reg( Persist_CLICSiD_Restore_VolMgr1_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepCheckVolumeManager + REGEX_PASS "\\+\\+\\+ PASSED Checked 29270 VolumeManager contexts. Num.Errors: 0" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Test Volume Manager results +dd4hep_add_test_reg( Persist_CLICSiD_Restore_VolMgr2_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepVolumeMgrTest SiTrackerBarrel + REGEX_PASS "\\+\\+\\+ PASSED: Checked 81306 objects. Num.Errors:0" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: DetElement nominal alignments +# Note: BeamCal has a problem. Need to be taken into account +dd4hep_add_test_reg( Persist_CLICSiD_Restore_Nominal_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepCheckNominals + REGEX_PASS "\\+\\+\\+ FAILED Checked 15946 DetElements. Num.Errors: 50" + ) +# +# Test restoring geometry from ROOT file: Sensitive detectors +dd4hep_add_test_reg( Persist_CLICSiD_Restore_Sensitives_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepCheckSensitives + REGEX_PASS "\\+\\+\\+ PASSED Checked 14 SensitiveDetector objects. Num.Errors: 0" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Readout segmentations +dd4hep_add_test_reg( Persist_CLICSiD_Restore_Segmentations_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepCheckSegmentations + REGEX_PASS "\\+\\+\\+ PASSED Checked 9 readout segmentations. Num.Errors: 0" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) +# +# Test restoring geometry from ROOT file: Readout structures +dd4hep_add_test_reg( Persist_CLICSiD_Restore_Readouts_LONGTEST + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -print WARNING + -plugin DD4hepRootLoader CLICSiD_geometry.root + -plugin DD4hepCheckReadouts + REGEX_PASS "\\+\\+\\+ PASSED Checked 14 readout objects. Num.Errors: 0" + REGEX_FAIL " ERROR ;EXCEPTION;Exception;FAILED" + ) diff --git a/examples/Persistency/src/PersistencySetup.cpp b/examples/Persistency/src/PersistencySetup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aea2ad59be32ad9381b4f0bb7ae02742b92d2647 --- /dev/null +++ b/examples/Persistency/src/PersistencySetup.cpp @@ -0,0 +1,93 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "PersistencySetup.h" + +// ROOT include files +#include "TFile.h" + +using namespace std; +using namespace dd4hep; +using namespace PersistencyExamples; + +/// Print conditions object +int dd4hep::PersistencyExamples::printCondition(Condition cond) { + const BasicGrammar* gr = cond.data().grammar; + int result = 0; + + if ( gr->type() == typeid(int) ) + result += int(cond.get<int>()); + else if ( gr->type() == typeid(long) ) + result += int(cond.get<long>()); + else if ( gr->type() == typeid(float) ) + result += int(cond.get<float>()); + else if ( gr->type() == typeid(double) ) + result += int(cond.get<double>()); + else if ( gr->type() == typeid(string) ) + result += cond.get<string>().length(); + else if ( gr->type() == typeid(Delta) ) + result += sizeof(cond.get<Delta>()); + else if ( gr->type() == typeid(AlignmentData) ) { + if ( dynamic_cast<detail::AlignmentObject*>(cond.ptr()) ) { + AlignmentCondition ac = cond; + bool ok = (void*)cond.data().ptr() == (void*)&ac->values(); + printout(ok ? INFO : ERROR, + "Data","+++ %s +++ \t\tAlignmentCondition: %s [%p] -- %p %s", + ok ? "SUCCESS" : "ERROR", cond.name(),cond.data().ptr(),&ac->values(), + ok ? "[Good-payload-mapping]" : "[Bad-payload-mapping]"); + } + result += sizeof(cond.get<AlignmentData>()); + } + else if ( gr->type() == typeid(vector<int>) ) + result += int(cond.get<vector<int> >().size()); + else if ( gr->type() == typeid(vector<long>) ) + result += int(cond.get<vector<long> >().size()); + else if ( gr->type() == typeid(vector<float>) ) + result += int(cond.get<vector<float> >().size()); + else if ( gr->type() == typeid(vector<double>) ) + result += int(cond.get<vector<double> >().size()); + else if ( gr->type() == typeid(vector<string>) ) + result += int(cond.get<vector<string> >().size()); + + else if ( gr->type() == typeid(map<string,int>) ) { + const map<string,int>& m = cond.get<map<string,int> >(); + result += int(m.size()); + for(const auto& i : m ) { + result += i.second; + printout(INFO,"Data","\t\tMap: %s [%s] -> %d",cond.name(), i.first.c_str(),i.second); + } + } + printout(INFO,"Data","Condition: [%016llX] %-24s -> %s",cond.key(), cond.name(), cond.data().str().c_str()); + return result; +} + +/// Default constructor +PersistencyIO::PersistencyIO() { +} + +/// Default destructor +PersistencyIO::~PersistencyIO() { +} + +/// Generic object write method +int PersistencyIO::write(const std::string& fname, const std::string& title, const std::type_info& typ, const void* object) { + TFile* f = TFile::Open(fname.c_str(),"RECREATE"); + if ( f && !f->IsZombie()) { + /// Now we write the object + int nBytes = f->WriteObjectAny(object,TBuffer::GetClass(typ),title.c_str()); + f->Close(); + return nBytes; + } + return 0; +} diff --git a/examples/Persistency/src/PersistencySetup.h b/examples/Persistency/src/PersistencySetup.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8f68f253e2cff7e5183a21ecb4a7c412c44781 --- /dev/null +++ b/examples/Persistency/src/PersistencySetup.h @@ -0,0 +1,62 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_PERSISTENCYEXAMPLE_PERSISTENCYSETUP_H +#define DD4HEP_PERSISTENCYEXAMPLE_PERSISTENCYSETUP_H + +#include "DD4hep/Detector.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Primitives.h" +#include "DD4hep/Conditions.h" +#include "DD4hep/Alignments.h" +#include "DD4hep/BasicGrammar.h" +#include "DD4hep/AlignmentData.h" +#include "DD4hep/detail/AlignmentsInterna.h" +#include "DD4hep/detail/ConditionsInterna.h" + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for persistency examples + namespace PersistencyExamples { + + template<typename T> Condition make_condition(const std::string& name, T val) { + Condition cond("Test#"+name, name); + T& value = cond.bind<T>(); + value = val; + cond->hash = ConditionKey(detail::hash32("TestCondition"),name).hash; + return cond; + } + + /// Print conditions object + int printCondition(Condition cond); + + class PersistencyIO { + public: + /// Default constructor + PersistencyIO(); + /// Default destructor + virtual ~PersistencyIO(); + /// Generic object write method + int write(const std::string& fname, const std::string& title, const std::type_info& typ, const void* object); + /// Object write method + template <typename T> int write(const std::string& fname, const std::string& title, const T& object) + { + return write(fname, title, typeid(T), &object); + } + + }; + + } /* End namespace persistencyexamples */ +} /* End namespace dd4hep */ + +#endif // DD4HEP_PERSISTENCYEXAMPLE_PERSISTENCYSETUP_H diff --git a/examples/Persistency/src/TestReadConditions.cpp b/examples/Persistency/src/TestReadConditions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..785832f7aa1b4c4423902ad12326ddd55b0654bd --- /dev/null +++ b/examples/Persistency/src/TestReadConditions.cpp @@ -0,0 +1,84 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +/* + Plugin invocation: + ================== + This plugin behaves like a main program. + Invoke the plugin with something like this: + + geoPluginRun -plugin DD4hep_PersistencyExample_read_cond \ + -output <file-name> + + Test the writing of a bunch of standard conditions objects + to a native ROOT file. + +*/ +// Framework include files +#include "PersistencySetup.h" +#include "DD4hep/Factories.h" +#include "TFile.h" + +using namespace std; +using namespace dd4hep; +using namespace PersistencyExamples; + +/// Plugin function: Condition program example +/** + * Factory: DD4hep_PersistencyExample_read_cond + * + * \author M.Frank + * \version 1.0 + * \date 01/12/2016 + */ +static int persistency_example (Detector& /* description */, int argc, char** argv) { + string input; + bool arg_error = false; + for(int i=0; i<argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-input",argv[i],4) ) + input = argv[++i]; + else + arg_error = true; + } + if ( arg_error || input.empty() ) { + /// Help printout describing the basic command line interface + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " name: factory name DD4hep_PersistencyExample_read_cond \n" + " -input <string> Geometry input file \n" + " -iovs <number> Number of parallel IOV slots for processing. \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + + PersistencyIO io; + TFile*f = TFile::Open(input.c_str()); + f->ls(); + std::vector<dd4hep::Condition>* p = (std::vector<dd4hep::Condition>*)f->Get("Conditions"); + if ( p ) { + int result = 0; + for( const auto& cond : *p ) { + //printout(INFO,"Example","+++ Reading condition object: %s",cond.name()); + result += printCondition(cond); + } + printout(ALWAYS,"Example","+++ Read successfully %ld conditions. Result=%d",p->size(),result); + } + else { + printout(ERROR,"Example","+++ ERROR +++ Failed to read object 'Conditions' from %s",f->GetName()); + } + // All done. + return 1; +} + +// first argument is the type from the xml file +DECLARE_APPLY(DD4hep_PersistencyExample_read_cond,persistency_example) diff --git a/examples/Persistency/src/TestWriteConditions.cpp b/examples/Persistency/src/TestWriteConditions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbf5580e92f47830ea1d97fc3f2d96006122579b --- /dev/null +++ b/examples/Persistency/src/TestWriteConditions.cpp @@ -0,0 +1,117 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +/* + Plugin invocation: + ================== + This plugin behaves like a main program. + Invoke the plugin with something like this: + + geoPluginRun -plugin DD4hep_PersistencyExample_write_cond \ + -output <file-name> + + Test the writing of a bunch of standard conditions objects + to a native ROOT file. + +*/ +// Framework include files +#include "PersistencySetup.h" +#include "DD4hep/Factories.h" + +using namespace std; +using namespace dd4hep; +using namespace PersistencyExamples; + +/// Plugin function: Condition program example +/** + * Factory: DD4hep_PersistencyExample_write_cond + * + * \author M.Frank + * \version 1.0 + * \date 01/12/2016 + */ +static int persistency_example (Detector& /* description */, int argc, char** argv) { + string output; + bool arg_error = false; + for(int i=0; i<argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-output",argv[i],4) ) + output = argv[++i]; + else + arg_error = true; + } + if ( arg_error || output.empty() ) { + /// Help printout describing the basic command line interface + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " name: factory name DD4hep_PersistencyExample_write_cond \n" + " -output <string> Geometry output file \n" + " -iovs <number> Number of parallel IOV slots for processing. \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + + std::vector<Condition> conditions; + + //Condition char_data = make_condition<char> ("char_data", 'A'); + //Condition shrt_data = make_condition<short> ("short_data",11); + Condition int_data = make_condition<int> ("int_data", 12); + Condition long_data = make_condition<long> ("long_data", 13); + Condition dble_data = make_condition<double> ("dble_data", 14.222); + Condition flt_data = make_condition<float> ("flt_data", 15.88); + Condition str_data = make_condition<string> ("str_data", string("Hello")); + Condition delta_data = make_condition<Delta> ("delta_data",Delta(Position(333.0,0,0))); + Condition align_data = make_condition<AlignmentData> ("align_data",AlignmentData()); + Condition alignment = AlignmentCondition("Test#alignment"); + + Condition flt_vector = make_condition<vector<float> > ("float_vector",{0.,1.,2.,3.,4.,5.,6.,7.,8.,9.}); + Condition dbl_vector = make_condition<vector<double> > ("double_vector",{0.,1.,2.,3.,4.,5.,6.,7.,8.,9.}); + //Condition char_vector = make_condition<vector<char> > ("char_vector",{'a','b','c','d','e','f','g','h','i','j'}); + //Condition shrt_vector = make_condition<vector<short> >("short_vector",{0,10,20,30,40,50,60,70,80,90}); + Condition int_vector = make_condition<vector<int> > ("int_vector",{0,10,20,30,40,50,60,70,80,90}); + Condition long_vector = make_condition<vector<long> > ("long_vector",{0,10,20,30,40,50,60,70,80,90}); + Condition str_vector = make_condition<vector<string> > ("str_vector",{"Hello","World","!","Here","I","am","!"}); + Condition string_map = make_condition<map<string,int> >("string_map",{{"A",10},{"B",20},{"C",30}}); + + //conditions.push_back(char_data); + //conditions.push_back(shrt_data); + conditions.push_back(int_data); + conditions.push_back(long_data); + conditions.push_back(dble_data); + conditions.push_back(flt_data); + conditions.push_back(str_data); + + conditions.push_back(flt_vector); + conditions.push_back(dbl_vector); + //conditions.push_back(char_vector); + conditions.push_back(int_vector); + conditions.push_back(long_vector); + conditions.push_back(str_vector); + + conditions.push_back(string_map); + + /// Alignment stuff + conditions.push_back(delta_data); + conditions.push_back(align_data); + conditions.push_back(alignment); + + PersistencyIO io; + printout(INFO,"Example","+++ Writing generic conditions vector to %s",output.c_str()); + int nbytes = io.write(output,"Conditions",conditions); + printout(INFO,"Example","+++ Wrote %d bytes to file %s",nbytes,output.c_str()); + + // All done. + return 1; +} + +// first argument is the type from the xml file +DECLARE_APPLY(DD4hep_PersistencyExample_write_cond,persistency_example)