diff --git a/DDCore/include/DD4hep/Factories.h b/DDCore/include/DD4hep/Factories.h index e2fac36a798c7b239c3ec50dc41ef501e4d123af..161f7b0090f5f8e16c36a90a5456dc817fdeb779 100644 --- a/DDCore/include/DD4hep/Factories.h +++ b/DDCore/include/DD4hep/Factories.h @@ -62,6 +62,18 @@ namespace DD4hep { static Ref_t create(LCDD& lcdd, const XML::Handle_t& e); }; + /** @class XMLDocumentReaderFactory Factories.h DDCore/Factories.h + * Read an arbitrary XML document and analyze it's content + * + * @author M.Frank + * @version 1.0 + * @date 2012/07/31 + */ + template <typename T> class XMLDocumentReaderFactory { + public: + static long create(LCDD& lcdd, const XML::Handle_t& e); + }; + /** @class DetElementFactory Factories.h DDCore/Factories.h * Standard factory to create Detector elements from the compact * XML representation. @@ -104,6 +116,19 @@ namespace { }; + template < typename P > class Factory<P, long(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*)> { + public: + typedef DD4hep::Geometry::LCDD LCDD; + typedef DD4hep::XML::Handle_t xml_h; + static void Func(void *retaddr, void*, const std::vector<void*>& arg, void*) { + LCDD* lcdd = (LCDD* )arg[0]; + xml_h* elt = (xml_h*)arg[1]; + long ret = DD4hep::Geometry::XMLDocumentReaderFactory<P>::create(*lcdd,*elt); + new(retaddr) (long)(ret); + } + }; + + template < typename P > class Factory<P, TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*,DD4hep::Geometry::SensitiveDetector*)> { public: typedef DD4hep::Geometry::LCDD LCDD; @@ -117,6 +142,8 @@ namespace { *(void**)retaddr = handle.ptr(); } }; + + } #define DECLARE_DETELEMENT_FACTORY(x) \ @@ -142,6 +169,12 @@ namespace { template <> Ref_t XMLElementFactory<xml_element_##name>::create(LCDD& l,const XML::Handle_t& e) {return func(l,e);} }}\ PLUGINSVC_FACTORY_WITH_ID(xml_element_##name,std::string(#name),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*)) +#define DECLARE_XML_DOC_READER(name,func) \ + namespace DD4hep { namespace Geometry { namespace { struct xml_document_##name {}; } \ + using DD4hep::Geometry::xml_document_##name; \ + template <> long XMLDocumentReaderFactory<xml_document_##name>::create(LCDD& l,const XML::Handle_t& e) {return func(l,e);} }}\ + PLUGINSVC_FACTORY_WITH_ID(xml_document_##name,std::string(#name "_XML_reader"),long(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*)) + #define DECLARE_DETELEMENT(name,func) \ namespace DD4hep { namespace Geometry { namespace { struct det_element_##name {}; } \ using DD4hep::Geometry::det_element_##name; \ diff --git a/DDCore/include/DD4hep/FieldTypes.h b/DDCore/include/DD4hep/FieldTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..54f1f118e903b9a26060c2060b4af0e90516ee98 --- /dev/null +++ b/DDCore/include/DD4hep/FieldTypes.h @@ -0,0 +1,90 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4HEP_GEOMETRY_FIELDTYPES_H +#define DD4HEP_GEOMETRY_FIELDTYPES_H + +// Framework include files +#include "DD4hep/Fields.h" +#include <vector> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geoemtry namespace declaration + */ + namespace Geometry { + + /** @class ConstantField FieldTypes.h + * + * Generic constant uniform field + * + * @author M.Frank + * @version 1.0 + */ + class ConstantField : public CartesianField::Object { + public: + /// Field direction + Direction direction; + public: + /// Initializing constructor + ConstantField() : direction() { } + /// Call to access the field components at a given location + virtual void fieldComponents(const double* /* pos */, double* field); + }; + + /** @class SolenoidField FieldTypes.h DD4hep/FieldTypes.h + * + * Generic solonoid magnetic field + * + * @author M.Frank + * @version 1.0 + */ + class SolenoidField : public CartesianField::Object { + public: + double innerField; + double outerField; + double minZ; + double maxZ; + double innerRadius; + double outerRadius; + + public: + /// Initializing constructor + SolenoidField(); + /// Call to access the field components at a given location + virtual void fieldComponents(const double* pos, double* field); + }; + + /** @class DipoleField FieldTypes.h DD4hep/FieldTypes.h + * + * Generic solonoid magnetic field + * + * @author M.Frank + * @version 1.0 + */ + class DipoleField : public CartesianField::Object { + public: + double zmax; + double zmin; + double rmax; + std::vector<double> coefficents; + public: + /// Initializing constructor + DipoleField(); + /// Call to access the field components at a given location + virtual void fieldComponents(const double* pos, double* field); + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_FIELDTYPES_H */ diff --git a/DDCore/include/DD4hep/Fields.h b/DDCore/include/DD4hep/Fields.h new file mode 100644 index 0000000000000000000000000000000000000000..e859078829b00064616b70e207c36897ea2c0c5c --- /dev/null +++ b/DDCore/include/DD4hep/Fields.h @@ -0,0 +1,203 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4HEP_GEOMETRY_FIELDS_H +#define DD4HEP_GEOMETRY_FIELDS_H + +// Framework include files +#include "DD4hep/Objects.h" + +// C/C++ include files +#include <vector> +#include <map> + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geoemtry namespace declaration + */ + namespace Geometry { + + /** @class CartesianField Fields.h + * + * Generic structure describing any field type (electric or magnetic) + * with field components in Cartesian coordinates. + * + * The actual behaviour is solely implemented in the underlying object + * class. + * + * @author M.Frank + * @version 1.0 + */ + struct CartesianField : public Ref_t { + enum FieldType { UNKNOWN=0, ELECTRIC=0x1, MAGNETIC=0x2 }; + typedef std::map<std::string,std::string> PropertyValues; + typedef std::map<std::string,PropertyValues> Properties; + + /// Internal data class shared by all handles of a given type + struct Object { + /// Field type + int type; + /// Field extensions + Properties properties; + /// Default constructor + Object() : type(UNKNOWN) {} + /// Call to access the field components at a given location + virtual void fieldComponents(const double* pos, double* field) = 0; + }; + + /// Default constructor + CartesianField() : Ref_t() {} + + /// Constructor to be used when reading the already parsed DOM tree + CartesianField(const CartesianField& e) : Ref_t(e) {} + + /// Constructor to be used when reading the already parsed DOM tree + template <typename Q> CartesianField(const Handle<Q>& e) : Ref_t(e) {} + + /// Access the field type + int fieldType() const { return data<Object>()->type; } + + /// Access the field type (string) + const char* type() const; + + /// Does the field change the energy of charged particles? + bool changesEnergy() const; + + /// Returns the 3 field components (x, y, z). + void value(const Position& pos, Direction& field) const { value(pos,&field.x); } + + /// Returns the 3 field components (x, y, z). + void value(const Position& pos, double* val) const { value(&pos.x,val); } + + /// Returns the 3 field components (x, y, z). + void value(const double* pos, double* val) const; + + /// Access to properties container + Properties& properties() const; + }; + + typedef CartesianField ElectricField; + typedef CartesianField MagneticField; + + + /** @class OverlayedField Fields.h + * + * Generic structure describing any field type (electric or magnetic) + * with field components in Cartesian coordinates. + * + * The actual behaviour is solely implemented in the underlying object + * class. + * + * @author M.Frank + * @version 1.0 + */ + struct OverlayedField : public Ref_t { + enum FieldType { ELECTRIC=0x1, MAGNETIC=0x2 }; + typedef std::map<std::string,std::string> PropertyValues; + typedef std::map<std::string,PropertyValues> Properties; + + struct Object { + int type; + CartesianField electric; + CartesianField magnetic; + std::vector<CartesianField> electric_components; + std::vector<CartesianField> magnetic_components; + /// Field extensions + Properties properties; + Object() : type(0), electric(), magnetic() {} + }; + + /// Default constructor + OverlayedField() : Ref_t() {} + + /// Constructor to be used when reading the already parsed DOM tree + template <typename Q> + OverlayedField(const Handle<Q>& e) : Ref_t(e) {} + + /// Object constructor + OverlayedField(const std::string& name); + + /// Access the field type + int type() const { return data<Object>()->type; } + + /// Does the field change the energy of charged particles? + bool changesEnergy() const; + + /// Add a new field component + void add(CartesianField field); + + /// Returns the 3 electric field components (x, y, z) if many components are present + void combinedElectric(const Position& pos, double* field) const { + combinedElectric(&pos.x,field); + } + + /// Returns the 3 electric field components (x, y, z) if many components are present + void combinedElectric(const double* pos, double* field) const; + + /// Returns the 3 magnetic field components (x, y, z) if many components are present + void combinedMagnetic(const Position& pos, double* field) const { + combinedMagnetic(&pos.x,field); + } + + /// Returns the 3 magnetic field components (x, y, z) if many components are present + void combinedMagnetic(const double* pos, double* field) const; + + /// Returns the 3 electric field components (x, y, z). + void electricField(const Position& pos, Direction& field) const { + electricField(&pos.x, &field.x); + } + + /// Returns the 3 electric field components (x, y, z). + void electricField(const Position& pos, double* field) const { + electricField(&pos.x, field); + } + + /// Returns the 3 electric field components (x, y, z). + void electricField(const double* pos, double* field) const { + CartesianField f = data<Object>()->electric; + f.isValid() ? f.value(pos,field) : combinedElectric(pos,field); + } + + /// Returns the 3 magnetic field components (x, y, z). + void magneticField(const Position& pos, Direction& field) const { + magneticField(&pos.x, &field.x); + } + + /// Returns the 3 magnetic field components (x, y, z). + void magneticField(const Position& pos, double* field) const { + magneticField(&pos.x, field); + } + + /// Returns the 3 magnetic field components (x, y, z). + void magneticField(const double* pos, double* field) const { + CartesianField f = data<Object>()->magnetic; + f.isValid() ? f.value(pos,field) : combinedMagnetic(pos,field); + } + + /// Returns the 3 electric (val[0]-val[2]) and magnetic field components (val[3]-val[5]). + void electromagneticField(const Position& pos, double* val) const { + electromagneticField(&pos.x,val); + } + + /// Returns the 3 electric (val[0]-val[2]) and magnetic field components (val[3]-val[5]). + void electromagneticField(const double* pos, double* val) const; + + /// Access to properties container + Properties& properties() const; + }; + + typedef OverlayedField ElectroMagneticField; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_FIELDS_H */ diff --git a/DDCore/include/DD4hep/GeoHandler.h b/DDCore/include/DD4hep/GeoHandler.h index 11e037d1e229fa4e8ba88a542d1066cb024069b4..63486c6b5f7e130716ccfc0f766f47359ac4f53e 100644 --- a/DDCore/include/DD4hep/GeoHandler.h +++ b/DDCore/include/DD4hep/GeoHandler.h @@ -48,6 +48,7 @@ namespace DD4hep { typedef std::map<const TNamed*,ConstVolumeSet> LimitVolumes; typedef std::map<int, std::set<const TGeoNode*> > Data; typedef std::set<TNamed*> VisRefs; + typedef std::set<TNamed*> Fields; typedef LCDD::HandleMap DefinitionSet; typedef Geometry::LCDD LCDD; @@ -61,6 +62,7 @@ namespace DD4hep { VolumeSet volumes; TransformSet trafos; VisRefs vis; + Fields fields; MaterialSet materials; // SensitiveVolumes sensitives; // RegionVolumes regions; diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index 0441804bd1a1cffa2e40b463e20a43034f8579c6..b5efb49dcdb46167219b8a05690581774e5dc0e1 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -56,19 +56,43 @@ namespace DD4hep { bool _toBool (const std::string& value); int _toInt (const std::string& value); + long _toLong (const std::string& value); float _toFloat (const std::string& value); double _toDouble(const std::string& value); inline bool _toBool(bool value) { return value; } inline int _toInt(int value) { return value; } + inline long _toLong(long value) { return value; } inline float _toFloat(float value) { return value; } inline double _toDouble(double value) { return value; } + template<class T> T _multiply(const std::string& left, T right); + template<class T> T _multiply(T left, const std::string& right); template<class T> T _multiply(const std::string& left, const std::string& right); - template <> int _multiply<int>(const std::string& left, const std::string& right); - template <> long _multiply<long>(const std::string& left, const std::string& right); - template <> float _multiply<float>(const std::string& left, const std::string& right); - template <> double _multiply<double>(const std::string& left, const std::string& right); + + template <> int _multiply<int>(const std::string& left, const std::string& right); + template <> inline int _multiply<int>(int left, const std::string& right) + { return left * _toInt(right); } + template <> inline int _multiply<int>(const std::string& left, int right) + { return _toInt(left) * right; } + + template <> long _multiply<long>(const std::string& left, const std::string& right); + template <> inline long _multiply<long>(long left, const std::string& right) + { return left * _toLong(right); } + template <> inline long _multiply<long>(const std::string& left, long right) + { return _toLong(left) * right; } + + template <> float _multiply<float>(const std::string& left, const std::string& right); + template <> inline float _multiply<float>(float left, const std::string& right) + { return left * _toFloat(right); } + template <> inline float _multiply<float>(const std::string& left, float right) + { return _toFloat(left) * right; } + + template <> double _multiply<double>(const std::string& left, const std::string& right); + template <> inline double _multiply<double>(const std::string& left, double right) + { return _toDouble(left) * right; } + template <> inline double _multiply<double>(double left, const std::string& right) + { return left * _toDouble(right); } void _toDictionary(const std::string& name, const std::string& value); @@ -99,33 +123,30 @@ namespace DD4hep { typedef T Implementation; typedef Handle<Implementation> handle_t; T* m_element; - Handle() : m_element(0) { } - Handle(T* e) : m_element(e) { } - Handle(const Handle<T>& e) : m_element(e.m_element) { } + Handle() : m_element(0) { } + Handle(T* e) : m_element(e) { } + Handle(const Handle<T>& e) : m_element(e.m_element) { } template<typename Q> Handle(Q* e) - : m_element((T*)e) { verifyObject(); } + : m_element((T*)e) { verifyObject(); } template<typename Q> Handle(const Handle<Q>& e) - : m_element((T*)e.m_element) { verifyObject(); } + : m_element((T*)e.m_element) { verifyObject(); } - T* ptr() const { return m_element; } - template <typename Q> Q* _ptr() const { return (Q*)m_element; } - bool isValid() const { return 0 != m_element; } - bool operator!() const { return 0 == m_element; } - T* operator->() const { return m_element; } - operator T& () const { return *m_element; } - T& operator*() const { return *m_element; } - - template <typename Q> Q* data() const { - return (Value<T,Q>*)m_element; - } + bool isValid() const { return 0 != m_element; } + bool operator!() const { return 0 == m_element; } + T* operator->() const { return m_element; } + operator T& () const { return *m_element; } + T& operator*() const { return *m_element; } + T* ptr() const { return m_element; } + template <typename Q> Q* _ptr() const { return (Q*)m_element; } + template <typename Q> Q* data() const { return (Value<T,Q>*)m_element; } void verifyObject() const { increment_object_validations(); if ( m_element && dynamic_cast<T*>(m_element) == 0 ) { bad_assignment(typeid(*m_element),typeid(T)); } } - static void bad_assignment(const std::type_info& from, const std::type_info& to); const char* name() const; + static void bad_assignment(const std::type_info& from, const std::type_info& to); void assign(Implementation* n, const std::string& nam, const std::string& title); }; typedef Handle<> Elt_t; diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h index 751a4a88dc6bf9c458fd8255857ea2d2d9f1f7dd..74c7a4175994d7ac0d326ac905b7ce8613e86912 100644 --- a/DDCore/include/DD4hep/LCDD.h +++ b/DDCore/include/DD4hep/LCDD.h @@ -7,11 +7,12 @@ // //==================================================================== -#ifndef DD4hep_LCDD_LCDD_H -#define DD4hep_LCDD_LCDD_H +#ifndef DD4HEP_LCDD_LCDD_H +#define DD4HEP_LCDD_LCDD_H // Framework includes #include "DD4hep/Handle.h" +#include "DD4hep/Fields.h" #include "DD4hep/Objects.h" #include "DD4hep/Shapes.h" #include "DD4hep/Volumes.h" @@ -39,14 +40,19 @@ namespace DD4hep { */ struct LCDD { typedef std::map<std::string,Handle<> > HandleMap; + typedef std::map<std::string,std::string> PropertyValues; + typedef std::map<std::string,PropertyValues> Properties; + /// Destructor virtual ~LCDD() {} - virtual void create() = 0; + /// Initialize geometry virtual void init() = 0; + /// Finalize the geometry virtual void endDocument() = 0; - virtual void addStdMaterials() = 0; + /// Access to properties map + virtual Properties& properties() const = 0; /// Return handle to material describing air virtual Material air() const = 0; /// Return handle to material describing vacuum @@ -61,6 +67,9 @@ namespace DD4hep { /// Return handle to the world volume containing the volume with the tracking devices virtual Volume trackingVolume() const = 0; + /// Return handle to the combined electromagentic field description. + virtual OverlayedField field() const = 0; + /// Accessor to the map of header entries virtual const HandleMap& header() const = 0; /// Accessor to the map of constants @@ -79,6 +88,8 @@ namespace DD4hep { virtual const HandleMap& limitsets() const = 0; /// Accessor to the map of aligment entries virtual const HandleMap& alignments() const = 0; + /// Accessor to the map of field entries, which together form the global field + virtual const HandleMap& fields() const = 0; virtual Volume pickMotherVolume(const DetElement& sd) const = 0; @@ -101,6 +112,8 @@ namespace DD4hep { /// Retrieve a sensitive detector by it's name from the detector description virtual SensitiveDetector sensitiveDetector(const std::string& name) const = 0; /// Retrieve a subdetector element by it's name from the detector description + virtual CartesianField field(const std::string& name) const = 0; + /// Retrieve a field component by it's name from the detector description virtual DetElement detector(const std::string& name) const = 0; /// Add a new constant to the detector description @@ -121,6 +134,8 @@ namespace DD4hep { virtual LCDD& add(DetElement detector) = 0; /// Add alignment entry to the detector description virtual LCDD& add(AlignmentEntry entry) = 0; + /// Add a field component to the detector description + virtual LCDD& add(CartesianField entry) = 0; /// Add a new constant by named reference to the detector description virtual LCDD& addConstant(const Ref_t& element) = 0; @@ -142,18 +157,19 @@ namespace DD4hep { virtual LCDD& addDetector(const Ref_t& detector) = 0; /// Add alignment entry by named reference to the detector description virtual LCDD& addAlignment(const Ref_t& alignment) = 0; + /// Add a field component by named reference to the detector description + virtual LCDD& addField(const Ref_t& field) = 0; /// Read compact geometry description or alignment file virtual void fromCompact(const std::string& fname) = 0; - /// Apply & lock realigments - virtual void applyAlignment() = 0; - - /// Dump geometry description + /// Read any geometry description or alignment file + virtual void fromXML(const std::string& fname) = 0; + /// virtual void dump() const = 0; - + ///---Factory method------- static LCDD& getInstance(void); }; } /* End namespace Geometry */ } /* End namespace DD4hep */ -#endif /* DD4hep_LCDD_LCDD_H */ +#endif /* DD4HEP_LCDD_LCDD_H */ diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h index d8ef32c59aa9c86b0fc1387d30889418660a7085..6cc21e510ae86331dddb3d0fc349b64b8a5599f9 100644 --- a/DDCore/include/DD4hep/Objects.h +++ b/DDCore/include/DD4hep/Objects.h @@ -7,8 +7,8 @@ // //==================================================================== -#ifndef DD4hep_GEOMETRY_OBJECTS_H -#define DD4hep_GEOMETRY_OBJECTS_H +#ifndef DD4HEP_GEOMETRY_OBJECTS_H +#define DD4HEP_GEOMETRY_OBJECTS_H // Framework include files #include "DD4hep/Handle.h" @@ -30,14 +30,13 @@ class TGeoPhysicalNode; #ifndef M_PI #define M_PI 3.14159265358979323846 #endif + + /* * DD4hep namespace declaration */ namespace DD4hep { - // Forward declarations - class IDDescriptor; - /* * Geoemtry namespace declaration */ @@ -45,6 +44,8 @@ namespace DD4hep { // Forward declarations struct LCDD; + class IDDescriptor; + /** @class Author Objects.h * @@ -90,9 +91,9 @@ namespace DD4hep { template <typename Q> Constant(const Handle<Q>& e) : Ref_t(e) {} /// Constructor to be used when creating a new DOM tree - Constant(LCDD& doc, const std::string& name); + Constant(const std::string& name); /// Constructor to be used when creating a new DOM tree - Constant(LCDD& doc, const std::string& name, const std::string& val); + Constant(const std::string& name, const std::string& val); /// String representation of this object std::string toString() const; }; @@ -268,7 +269,7 @@ namespace DD4hep { template <typename Q> Atom(const Handle<Q>& e) : Handle<TGeoElement>(e) {} /// Constructor to be used when reading the already parsed DOM tree - Atom(LCDD& doc, const std::string& name, const std::string& formula, int Z, int N, double density); + Atom(const std::string& name, const std::string& formula, int Z, int N, double density); }; /** @class Material Objects.h @@ -283,7 +284,7 @@ namespace DD4hep { template <typename Q> Material(const Handle<Q>& e) : Handle<TGeoMaterial>(e) {} /// Constructor to be used when reading the already parsed DOM tree - Material(LCDD& doc, const std::string& name); + Material(const std::string& name); /// String representation of this object std::string toString() const; }; @@ -319,7 +320,7 @@ namespace DD4hep { /// Copy constructor for handle VisAttr(const VisAttr& e) : Ref_t(e) {} /// Constructor to be used when creating a new registered visualization object - VisAttr(LCDD& doc, const std::string& name); + VisAttr(const std::string& name); /// Additional data accessor Object& _data() const { return *data<Object>(); } @@ -373,7 +374,7 @@ namespace DD4hep { template <typename Q> AlignmentEntry(const Handle<Q>& h) : Base(h) {} /// Constructor to be used when creating a new aligment entry - AlignmentEntry(LCDD& doc, const std::string& path); + AlignmentEntry(const std::string& path); /// Align the PhysicalNode (translation only) int align(const Position& pos, bool check=false, double overlap=0.001); /// Align the PhysicalNode (rotation only) @@ -484,5 +485,5 @@ namespace DD4hep { }; } /* End namespace Geometry */ -} /* End namespace DD4hep */ -#endif /* DD4hep_GEOMETRY_OBJECTS_H */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_OBJECTS_H */ diff --git a/DDCore/src/compact/Conversions.h b/DDCore/include/XML/Conversions.h similarity index 64% rename from DDCore/src/compact/Conversions.h rename to DDCore/include/XML/Conversions.h index df18a0a54153ae98f7c26d8cec9bd226b204d253..2597dd1ddec3e7b765d1a28c5136cf243cd88c00 100644 --- a/DDCore/src/compact/Conversions.h +++ b/DDCore/include/XML/Conversions.h @@ -28,10 +28,10 @@ namespace DD4hep { /* * XML namespace declaration */ - namespace Geometry { + //namespace Geometry { // Function prototypes used for object conversions - template <typename T> Ref_t toRefObject(LCDD& lcdd, const XML::Handle_t& xml); + //template <typename T> Ref_t toRefObject(LCDD& lcdd, const XML::Handle_t& xml); /** @class Converter Conversions.h DD4hep/compact/Conversions.h * @@ -39,9 +39,12 @@ namespace DD4hep { * @version 1.0 */ template <typename T> struct Converter { - typedef T to_type; - LCDD& lcdd; - Converter(LCDD& l) : lcdd(l) {} + typedef T to_type; + typedef void* user_param; + Geometry::LCDD& lcdd; + user_param param; + Converter(Geometry::LCDD& l) : lcdd(l), param(0) {} + Converter(Geometry::LCDD& l, user_param p) : lcdd(l), param(p) {} void operator()(const XML::Handle_t& xml) const; }; @@ -52,13 +55,13 @@ namespace DD4hep { */ template <typename T> struct PrintMap { typedef T item_type; - typedef const LCDD::HandleMap cont_type; + typedef const Geometry::LCDD::HandleMap cont_type; - const LCDD& lcdd; - std::ostream& os; - std::string text; - cont_type& cont; - PrintMap(const LCDD& l, std::ostream& stream, cont_type& c, const std::string& t="") + const Geometry::LCDD& lcdd; + std::ostream& os; + std::string text; + cont_type& cont; + PrintMap(const Geometry::LCDD& l, std::ostream& stream, cont_type& c, const std::string& t="") : lcdd(l), os(stream), text(t), cont(c) {} void operator()() const; }; @@ -69,15 +72,15 @@ namespace DD4hep { * @version 1.0 */ template <typename T> struct Printer { - const LCDD& lcdd; - std::ostream& os; - std::string prefix; - Printer(const LCDD& l, std::ostream& stream, const std::string& p="") + const Geometry::LCDD& lcdd; + std::ostream& os; + std::string prefix; + Printer(const Geometry::LCDD& l, std::ostream& stream, const std::string& p="") : lcdd(l), os(stream), prefix(p) {} void operator()(const T& value) const; }; inline const char* yes_no(bool value) { return value ? "YES" : "NO "; } - } /* End namespace Geometry */ + //} /* End namespace Geometry */ } /* End namespace DD4hep */ #endif /* DD4hep_COMPACT_CONVERSION_H */ diff --git a/DDCore/include/XML/XMLDetector.h b/DDCore/include/XML/XMLDetector.h index 1cfc04d3f2cbab8569ec92548b6cbb4ffebb3a4f..c0823f2c681b40a57ab3527bc7bc986c8adc3cac 100644 --- a/DDCore/include/XML/XMLDetector.h +++ b/DDCore/include/XML/XMLDetector.h @@ -53,10 +53,13 @@ namespace DD4hep { double zhalf() const; double deltaphi() const; - double outer_z() const; + double outer_radius() const; double outer_r() const; - double inner_z() const; + double outer_z() const; + double inner_radius() const; double inner_r() const; + double inner_z() const; + double z_length() const; double length() const; double width() const; @@ -70,6 +73,7 @@ namespace DD4hep { double crossing_angle() const; double zmin() const; + double zmax() const; double radius() const; double offset() const; @@ -132,6 +136,8 @@ namespace DD4hep { std::string visStr() const; std::string regionStr() const; std::string limitsStr() const; + double inner_field() const; + double outer_field() const; Dimension dimensions() const; bool isTracker() const; bool isCalorimeter() const; diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h index 8c376b6883521b1e0b18f35b20bd1ee914c863f9..559b8fd5c8198a9d44f56e82419ac1dab087916f 100644 --- a/DDCore/include/XML/XMLElements.h +++ b/DDCore/include/XML/XMLElements.h @@ -6,11 +6,12 @@ // Author : M.Frank // //==================================================================== -#ifndef DD4hep_HandleS_H -#define DD4hep_HandleS_H +#ifndef DD4HEP_XMLELEMENTS_H +#define DD4HEP_XMLELEMENTS_H #include <cmath> #include <string> +#include <vector> #include <stdexcept> #include "xercesc/util/XMLString.hpp" #include "xercesc/dom/DOMElement.hpp" @@ -32,8 +33,12 @@ namespace DD4hep { template<class T> void deletePtr(T*& p) { if(p) delete p; p=0; } namespace XML { - typedef xercesc::DOMAttr* Attribute; - typedef const std::string& CSTR; + typedef xercesc::DOMNodeList* NodeList; + typedef xercesc::DOMAttr* Attribute; + typedef const std::string& CSTR; + + /// Dump DOM tree of a document + void dumpTree(xercesc::DOMDocument* doc); std::string _toString(const Attribute attr); std::string _toString(const XMLCh *toTranscode); @@ -43,99 +48,211 @@ namespace DD4hep { std::string _toString(float d, const char* fmt="%f"); std::string _toString(double d, const char* fmt="%f"); void _toDictionary(const XMLCh* name, const XMLCh* value); - bool _toBool(const XMLCh* value); - int _toInt(const XMLCh* value); - long _toLong(const XMLCh* value); - float _toFloat(const XMLCh* value); - double _toDouble(const XMLCh* value); - void dumpTree(xercesc::DOMDocument* doc); - + /// Conversion function from raw unicode string to bool + bool _toBool(const XMLCh* value); + /// Conversion function from raw unicode string to int + int _toInt(const XMLCh* value); + /// Conversion function from raw unicode string to long + long _toLong(const XMLCh* value); + /// Conversion function from raw unicode string to float + float _toFloat(const XMLCh* value); + /// Conversion function from raw unicode string to double + double _toDouble(const XMLCh* value); + + /** @class Strng_t XMLElements.h XML/XMLElements.h + * + * Helper class to encapsulate a unicode string + * + * @author M.Frank + * @version 1.0 + */ struct Strng_t { XMLCh* m_xml; Strng_t(const XMLCh* c) { m_xml=xercesc::XMLString::replicate(c); } Strng_t(const char* c) { m_xml=xercesc::XMLString::transcode(c); } - Strng_t(CSTR c) { m_xml=xercesc::XMLString::transcode(c.c_str()); } + Strng_t(const std::string& c) { m_xml=xercesc::XMLString::transcode(c.c_str()); } ~Strng_t() { if (m_xml) xercesc::XMLString::release(&m_xml); } - operator const XMLCh*() const { return m_xml; } - const XMLCh* ptr() const { return m_xml; } + operator const XMLCh*() const { return m_xml; } + const XMLCh* ptr() const { return m_xml; } Strng_t& operator=(const char* s); Strng_t& operator=(const Strng_t& s); Strng_t& operator=(const std::string& s); }; + /// Unicode string concatenation of a normal ASCII string from right side Strng_t operator+(const Strng_t& a, const char* b); + /// Unicode string concatenation of a normal ASCII string from left side Strng_t operator+(const char* a, const Strng_t& b); + /// Unicode string concatenation of a encapsulated and raw unicode string from right side Strng_t operator+(const Strng_t& a, const XMLCh* b); + /// Unicode string concatenation of a encapsulated and raw unicode string from left side Strng_t operator+(const XMLCh* a, const Strng_t& b); + /// Unicode string concatenation of a raw unicode and an STL string from the right Strng_t operator+(const XMLCh* a, const std::string& b); + /// Unicode string concatenation of a raw unicode and an STL string from the left Strng_t operator+(const std::string& a, const XMLCh* b); + /** @class Tag_t XMLElements.h XML/XMLElements.h + * + * Helper class to easily convert between + * -- unicode + * -- std::string + * -- const char*. + * Internally a copy representation as an std::string is kept. + * + * @author M.Frank + * @version 1.0 + */ struct Tag_t : public Strng_t { + /// STL string buffer std::string m_str; - Tag_t(CSTR s) : Strng_t(s), m_str(s) { } - Tag_t(const char* s) : Strng_t(s), m_str(s) { } + + /// Constructor from normal ASCII string + Tag_t(const char* s) : Strng_t(s), m_str(s) { } + /// Constructor from unicode string + Tag_t(const XMLCh* s) : Strng_t(s), m_str(_toString(s)) { } + /// Constructor from internal XML string Tag_t(const Strng_t& s) : Strng_t(s), m_str(_toString(s)) { } - Tag_t(const XMLCh* s) : Strng_t(s), m_str(_toString(s)) { } - ~Tag_t() { } + /// Constructor from STL string + Tag_t(const std::string& s) : Strng_t(s), m_str(s) { } + /// Destructor + ~Tag_t() { } + + /// Assignment of a normal ASCII string Tag_t& operator=(const char* s); + /// Assignment of a tag object Tag_t& operator=(const Tag_t& s); + /// Assignment of a internal XML string Tag_t& operator=(const Strng_t& s); + /// Assignment of a STL string Tag_t& operator=(const std::string& s); - operator CSTR () const { return m_str; } - CSTR str() const { return m_str; } + + /// Automatic conversion to STL string + operator const std::string& () const { return m_str; } + /// Access writable STL string + const std::string& str() const { return m_str; } + /// Access data buffer of STL string const char* c_str() const { return m_str.c_str(); } }; + + /// Tag/string concatenation with a normal ASCII string from right side Tag_t operator+(const Tag_t& a, const char* b); + /// Tag/string concatenation with a normal ASCII string from left side Tag_t operator+(const char* a, const Tag_t& b); + /// Tag/string concatenation with a unicode string from right side Tag_t operator+(const Tag_t& a, const XMLCh* b); + /// Tag/string concatenation with a internal XML string from right side Tag_t operator+(const Tag_t& a, const Strng_t& b); + /// Tag/string concatenation with a STL string from right side Tag_t operator+(const Tag_t& a, const std::string& b); - - inline bool operator==(CSTR c, const Tag_t& b) { return c == b.m_str; } - + /// Equality operator between tag object and STL string + inline bool operator==(const std::string& c, const Tag_t& b) { return c == b.m_str; } + + /** @class Handle_t XMLElements.h XML/XMLElements.h + * + * Helper class to easily access the properties of single DOMElements. + * + * Note: The assignmant operator as well as the copy constructor + * do not have to be implemented, they are aut-generated by the compiler! + * + * @author M.Frank + * @version 1.0 + */ struct Handle_t { - mutable xercesc::DOMElement* m_node; - Handle_t(xercesc::DOMElement* e=0) : m_node(e) {} - xercesc::DOMElement* operator->() const { return m_node; } - operator xercesc::DOMElement* () const { return m_node; } - xercesc::DOMElement* ptr() const { return m_node; } + // Abbreviation for internal use + typedef xercesc::DOMElement* Elt_t; + + /// The pointer to the DOMElement + mutable Elt_t m_node; + + /// Initializing constructor + Handle_t(Elt_t e=0) : m_node(e) {} + /// Direct access to the DOMElement using the operator-> + Elt_t operator->() const { return m_node; } + /// Direct access to the DOMElement by dereferencing + operator Elt_t() const { return m_node; } + /// Direct access to the DOMElement by function + Elt_t ptr() const { return m_node; } + /// Clone the DOMelement - with the option of a deep copy Handle_t clone(xercesc::DOMDocument* new_doc, bool deep) const; + + /// Unicode text access to the element's tag + const XMLCh* rawTag() const { return m_node->getTagName(); } + /// Unicode text access to the element's text + const XMLCh* rawText() const { return m_node->getTextContent(); } + /// Unicode text access to the element's value + const XMLCh* rawValue() const { return m_node->getNodeValue(); } + /// Text access to the element's tag + std::string tag() const { return _toString(rawTag()); } + /// Text access to the element's text + std::string text() const { return _toString(rawText()); } + /// Text access to the element's value + std::string value() const { return _toString(rawValue()); } + + /*** DOM Attribute handling + */ + /// Access attribute name (throws exception if not present) + const XMLCh* attr_name(const Attribute attr) const; + /// Access attribute value by the attribute (throws exception if not present) + const XMLCh* attr_value(const Attribute attr) const; + /// Access attribute value by the attribute's unicode name (throws exception if not present) + const XMLCh* attr_value(const XMLCh* attr) const; + /// Access attribute value by the attribute's unicode name (no exception thrown if not present) + const XMLCh* attr_value_nothrow(const XMLCh* attr) const; + + /// Access attribute pointer by the attribute's unicode name (throws exception if not present) + Attribute attr_ptr(const XMLCh* attr) const; + /// Access attribute pointer by the attribute's unicode name (no exception thrown if not present) + Attribute attr_nothrow(const XMLCh* tag) const { return m_node->getAttributeNode(tag); } + + /// Retrieve a collection of all attributes of this DOM element + std::vector<Attribute> attributes() const; + /// Check for the existence of a named attribute bool hasAttr(const XMLCh* t) const { return 0 != m_node->getAttributeNode(t); } - bool hasAttr(const char* t) const { return 0 != m_node->getAttributeNode(Strng_t(t));} - template <class T> T attr(const Attribute a) const; - template <class T> T attr(const XMLCh* t) const; - template <class T> T attr(const char* t) const { return this->attr<T>(Strng_t(t)); } + /// Check for the existence of a named attribute + bool hasAttr(const char* t) const { return hasAttr(Strng_t(t)); } + /// Access typed attribute value by the DOMAttr + template <class T> T attr(const Attribute a) const { return this->attr<T>(this->attr_name(a)); } + /// Access typed attribute value by it's name + template <class T> T attr(const char* name) const { return this->attr<T>(Strng_t(name)); } + /// Access typed attribute value by it's unicode name + template <class T> T attr(const XMLCh* name) const; + void setAttrs(Handle_t e) const; + + /// Generic attribute setter with unicode value Attribute setAttr(const XMLCh* t, const XMLCh* v) const; + /// Generic attribute setter with DOMAttr value Attribute setAttr(const XMLCh* t, const Attribute v) const; + /// Generic attribute setter with integer value Attribute setAttr(const XMLCh* t, int val) const; + /// Generic attribute setter with boolen value Attribute setAttr(const XMLCh* t, bool val) const; + /// Generic attribute setter with floating point value Attribute setAttr(const XMLCh* t, float val) const; + /// Generic attribute setter with double precision floating point value Attribute setAttr(const XMLCh* t, double val) const; + /// Generic attribute setter with text value Attribute setAttr(const XMLCh* t, const char* v) const; - const XMLCh* rawTag() const { return m_node->getTagName(); } - const XMLCh* rawText() const { return m_node->getTextContent(); } - const XMLCh* rawValue() const { return m_node->getNodeValue(); } - std::string tag() const { return _toString(rawTag()); } - std::string text() const { return _toString(rawText()); } - std::string value() const { return _toString(rawValue()); } - + /*** DOM Element child handling + */ + /// Check the existence of a child with a given tag name bool hasChild(const XMLCh* tag) const; - Handle_t firstChild(const XMLCh* tag) const; + /// Access a single child by it's tag name (unicode) Handle_t child(const XMLCh* tag, bool throw_exception=true) const; - xercesc::DOMNodeList* children(const XMLCh* tag) const{ return m_node->getElementsByTagName (tag); } + /// Access a group of children identified by the same tag name + NodeList children(const XMLCh* tag) const{ return m_node->getElementsByTagName (tag); } + /// Access the number of children of this DOM element with a given tag name size_t numChildren(const XMLCh* tag, bool throw_exception) const; - Handle_t remove(xercesc::DOMElement* node) const; + /// Remove a single child node identified by it's handle from the tree of the element + Handle_t remove(Handle_t e) const; + /// Remove children with a given tag name from the DOM node void removeChildren(const XMLCh* tag) const; - void append(xercesc::DOMElement* e) const { m_node->appendChild(e); } - const XMLCh* attr_value(const XMLCh* attr) const; - const XMLCh* attr_value(const Attribute attr) const; - const XMLCh* attr_value_nothrow(const XMLCh* attr) const; + /// Append a DOM element to the current node + void append(Handle_t e) const { m_node->appendChild(e.ptr()); } - Attribute attr_ptr(const XMLCh* attr) const; - Attribute attr_nothrow(const XMLCh* tag) const { return m_node->getAttributeNode(tag); } }; #define INLINE inline @@ -160,7 +277,7 @@ namespace DD4hep { template<> INLINE std::string Handle_t::attr<std::string>(const XMLCh* tag) const { return _toString(attr_nothrow(tag)); } - +#if 0 template<> INLINE bool Handle_t::attr<bool>(const Attribute tag) const { return _toBool(attr_value(tag)); } @@ -175,23 +292,54 @@ namespace DD4hep { template<> INLINE std::string Handle_t::attr<std::string>(const Attribute tag) const { return _toString(attr_value(tag)); } +#endif - struct Collection_t : public Handle_t { - mutable XMLSize_t m_index; - xercesc::DOMElement* m_element; - xercesc::DOMNodeList* m_children; - Collection_t(xercesc::DOMElement* node, const XMLCh* tag); - Collection_t(xercesc::DOMElement* node, const char* tag); - Collection_t(xercesc::DOMElement* node, xercesc::DOMNodeList* children); + /** @class Collection_t XMLElements.h XML/XMLElements.h + * + * Helper class to easily access collections of DOMNodes (or DOMElements) + * + * @author M.Frank + * @version 1.0 + */ + struct Collection_t : public Handle_t { + /// Iteration type. See NodeType enumeration for details + xercesc::DOMNode::NodeType m_type; + /// Current iteration index + mutable XMLSize_t m_index; + /// Reference to the list of child nodes + NodeList m_children; + + /// Constructor to initialize loop over children with a given node type + Collection_t(Elt_t node, xercesc::DOMNode::NodeType typ); + /// Constructor over DOMElements with a given tag name + Collection_t(Elt_t node, const XMLCh* tag); + /// Constructor over DOMElements with a given tag name + Collection_t(Elt_t node, const char* tag); + /// Constructor over DOMElements in a node list + Collection_t(NodeList children); + /// Constructor over arbitrary DOMNodes in a node list + Collection_t(NodeList children, xercesc::DOMNode::NodeType typ); + /// Reset the collection object to restart the iteration Collection_t& reset(); + /// Access the collection size size_t size() const; + /// Operator to advance the collection (pre increment) void operator++() const; - xercesc::DOMElement* current() const { return m_node; } + /// Operator to advance the collection (post increment) + void operator++(int) const; + /// Operator to advance the collection (pre decrement) + void operator--() const; + /// Operator to advance the collection (post decrement) + void operator--(int) const; + /// Access to current element + Elt_t current() const { return m_node; } + /// Loop processor using function object template <class T> void for_each(T oper) const { for(const Collection_t& c=*this; c; ++c) oper(*this); } + /// Loop processor using function object template <class T> void for_each(const XMLCh* tag, T oper) const { for(const Collection_t& c=*this; c; ++c) Collection_t(c.m_node, tag).for_each(oper); @@ -199,55 +347,93 @@ namespace DD4hep { }; + /** @class Document XMLElements.h XML/XMLElements.h + * + * User class encapsulating a DOM document + * + * @author M.Frank + * @version 1.0 + */ struct Document { - xercesc::DOMDocument *m_doc; - Document(xercesc::DOMDocument* d) : m_doc(d) {} - operator xercesc::DOMDocument*() const { return m_doc; } - xercesc::DOMDocument* operator->() const { return m_doc; } - xercesc::DOMElement* createElt(const XMLCh* tag) const; + typedef xercesc::DOMDocument* DOC; + DOC m_doc; + + /// Constructor + Document(DOC d) : m_doc(d) {} + /// Auto-conversion to DOM document + operator DOC() const { return m_doc; } + /// Accessot to DOM document behaviour using arrow operator + DOC operator->() const { return m_doc; } + /// Access the ROOT eleemnt of the DOM document + Handle_t root() const; + + /// Create DOM element + Handle_t createElt(const XMLCh* tag) const; + /// Create DOM attribute (name/value pair) Attribute createAttr(const XMLCh* name, const XMLCh* value) const; - Handle_t clone(Handle_t source,bool deep) const; - Handle_t root() const; + /// Clone a DOM element / sub-tree depending on deep_copy flag + Handle_t clone(Handle_t source, bool deep_copy) const; }; struct DocumentHolder : public Document { - DocumentHolder(xercesc::DOMDocument* d) : Document(d) {} + DocumentHolder(DOC d) : Document(d) {} virtual ~DocumentHolder(); }; + /** @class Document XMLElements.h XML/XMLElements.h + * + * User class encapsulating a DOM element + * using the Handle helper + * + * @author M.Frank + * @version 1.0 + */ struct Element { + typedef Handle_t::Elt_t Elt_t; Handle_t m_element; + + /// Constructor from DOMElement handle Element(const Handle_t& e) : m_element(e) { } + /// Constructor from DOM document entity Element(const Document& document, const XMLCh* type); - operator bool() const { return 0 != m_element.ptr(); } - bool operator!() const { return 0 == m_element.ptr(); } - operator Handle_t () const { return m_element; } - operator xercesc::DOMElement*() const { return m_element; } - xercesc::DOMElement* ptr() const { return m_element; } + /// Access the hosting document handle of this DOM element Document document() const; - const XMLCh* tagName() const - { return m_element.rawTag(); } - void append(Handle_t handle) const - { m_element.append(handle); } - Handle_t clone(const Document& new_doc, bool deep) const - { return new_doc.clone(m_element,deep); } - size_t numChildren(const XMLCh* tag, bool throw_exception=true) const - { return m_element.numChildren(tag,throw_exception); } - bool hasAttr(const XMLCh* name) const - { return m_element.hasAttr(name); } - template <class T> T attr(const XMLCh* tag) const - { return m_element.attr<T>(tag); } - void setAttrs(Handle_t e) const - { return m_element.setAttrs(e); } - template <class T> Attribute setAttr(const XMLCh* name,const T& value) const - { return m_element.setAttr(name,value); } + + /// operator bool: check handle validity + operator bool() const { return 0 != m_element.ptr(); } + /// operator NOT: check handle validity + bool operator!() const { return 0 == m_element.ptr(); } + /// Automatic conversion to DOM element handle + operator Handle_t () const { return m_element; } + /// Automatic conversion to DOMElement pointer + operator Elt_t() const { return m_element; } + /// Access to DOMElement pointer + Elt_t ptr() const { return m_element; } + + /// Access the tag name of this DOM element + const XMLCh* tagName() const { return m_element.rawTag(); } + /// Append a new element to the existing tree + void append(Handle_t handle) const { m_element.append(handle); } + /// Clone the DOMelement - with the option of a deep copy + Handle_t clone(const Document& new_doc, bool deep) const { return new_doc.clone(m_element,deep); } + /// Access the number of children of this DOM element with a given tag name + size_t numChildren(const XMLCh* tag, bool exc=true) const { return m_element.numChildren(tag,exc); } + /// Check for the existence of a named attribute + bool hasAttr(const XMLCh* name) const { return m_element.hasAttr(name); } + + template <class T> T attr(const XMLCh* tag) const { return m_element.attr<T>(tag); } + void setAttrs(Handle_t e) const { return m_element.setAttrs(e); } + template <class T> + Attribute setAttr(const XMLCh* nam,const T& val) const{ return m_element.setAttr(nam,val); } + /// Retrieve a collection of all attributes of this DOM element + std::vector<Attribute> attributes() const { return m_element.attributes(); } Attribute getAttr(const XMLCh* name) const; + Handle_t clone(Handle_t h, bool deep) const; Handle_t addChild(const XMLCh* tag) const; Handle_t setChild(const XMLCh* tag) const; Handle_t child(const Strng_t& tag, bool throw_exception=true) const; - Handle_t remove(Handle_t node) const - { return m_element.remove(node); } + Handle_t remove(Handle_t node) const { return m_element.remove(node); } Attribute setRef(const XMLCh* tag, const XMLCh* refname) const; const XMLCh* getRef(const XMLCh* tag) const; }; @@ -272,4 +458,4 @@ namespace DD4hep { } } /* End namespace DD4hep */ -#endif /* DD4hep_HandleS_H */ +#endif /* DD4HEP_XMLELEMENTS_H */ diff --git a/DDCore/include/XML/XMLTags.h b/DDCore/include/XML/XMLTags.h index 893b587be7e28bdfab7371ea28019a29d6f0fd0e..8cb7beabb6ba507740af0b620a202de8dcadad01 100644 --- a/DDCore/include/XML/XMLTags.h +++ b/DDCore/include/XML/XMLTags.h @@ -25,6 +25,8 @@ namespace DD4hep { namespace XML { extern const Tag_t Tag_radian; extern const Tag_t Tag_mm; extern const Tag_t Tag_cm; + extern const Tag_t Attr_global; + extern const Tag_t Attr_local; extern const Tag_t Attr_overlap; @@ -45,6 +47,9 @@ namespace DD4hep { namespace XML { extern const Tag_t Attr_density; extern const Tag_t Tag_composite; extern const Tag_t Tag_fraction; + extern const Tag_t Tag_strength; + extern const Tag_t Tag_properties; + extern const Tag_t Tag_attributes; extern const Tag_t Tag_define; extern const Tag_t Tag_detector; @@ -67,9 +72,14 @@ namespace DD4hep { namespace XML { extern const Tag_t Attr_dimensions; extern const Tag_t Attr_ecut; extern const Tag_t Attr_false; + extern const Tag_t Attr_strength; + extern const Tag_t Attr_field; + extern const Tag_t Attr_inner_field; + extern const Tag_t Attr_outer_field; extern const Tag_t Attr_field_name; extern const Tag_t Attr_hits_collection; extern const Tag_t Attr_incoming_r; + extern const Tag_t Attr_inner_radius; extern const Tag_t Attr_inner_r; extern const Tag_t Attr_inner_z; extern const Tag_t Attr_layer; @@ -79,7 +89,10 @@ namespace DD4hep { namespace XML { extern const Tag_t Attr_name; extern const Tag_t Attr_nphi; extern const Tag_t Attr_ntheta; + extern const Tag_t Attr_funit; + extern const Tag_t Tag_dipole_coeff; + extern const Tag_t Attr_outer_radius; extern const Tag_t Attr_outer_r; extern const Tag_t Attr_outer_z; extern const Tag_t Attr_outgoing_r; @@ -108,6 +121,7 @@ namespace DD4hep { namespace XML { extern const Tag_t Tag_color; extern const Tag_t Tag_detectors; extern const Tag_t Tag_display; + extern const Tag_t Tag_field; extern const Tag_t Tag_fields; extern const Tag_t Tag_gdml; extern const Tag_t Tag_header; @@ -296,6 +310,7 @@ namespace DD4hep { namespace XML { // Solid: // No tags extern const Tag_t Attr_zmin; + extern const Tag_t Attr_zmax; // -- ZPlane extern const Tag_t Tag_zplane; diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp index 30bafd1b459a82402c9e008df9d8778464c92f2f..40aa12a901d389c531f95bd361afb8a374e6e15b 100644 --- a/DDCore/src/Detector.cpp +++ b/DDCore/src/Detector.cpp @@ -23,7 +23,7 @@ namespace { void (*destruct)(void*); int id; }; - typedef map<const std::type_info*, ExtensionEntry> ExtensionMap; + typedef map<const type_info*, ExtensionEntry> ExtensionMap; static int s_extensionID = 0; ExtensionMap& detelement_extensions() { static ExtensionMap s_map; @@ -163,7 +163,7 @@ Value<TNamed,DetElement::Object>* DetElement::Object::clone(int new_id, int flag // 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 std::type_info* info = (*i).first; + 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); @@ -266,7 +266,7 @@ DetElement::DetElement(DetElement parent, const string& name, int id) { } /// Add an extension object to the detector element -void* DetElement::i_addExtension(void* ptr, const std::type_info& info, void* (*copy)(const void*,DetElement), void (*destruct)(void*)) { +void* DetElement::i_addExtension(void* ptr, const type_info& info, void* (*copy)(const void*,DetElement), void (*destruct)(void*)) { Object& o = _data(); Extensions::iterator j = o.extensions.find(&info); if ( j == o.extensions.end() ) { @@ -289,7 +289,7 @@ void* DetElement::i_addExtension(void* ptr, const std::type_info& info, void* (* } /// Access an existing extension object from the detector element -void* DetElement::i_extension(const std::type_info& info) const { +void* DetElement::i_extension(const type_info& info) const { Object& o = _data(); Extensions::const_iterator j = o.extensions.find(&info); if ( j != o.extensions.end() ) { @@ -300,7 +300,7 @@ void* DetElement::i_extension(const std::type_info& info) const { } /// Access to the full path to the placed object -std::string DetElement::placementPath() const { +string DetElement::placementPath() const { if ( isValid() ) { Object& o = _data(); if ( o.placementPath.empty() ) { @@ -325,7 +325,7 @@ string DetElement::type() const { } /// Set the type of the sensitive detector -DetElement& DetElement::setType(const std::string& typ) { +DetElement& DetElement::setType(const string& typ) { if ( isValid() ) { m_element->SetTitle(typ.c_str()); return *this; @@ -373,7 +373,7 @@ const DetElement::Children& DetElement::children() const { } /// Access to individual children by name -DetElement DetElement::child(const std::string& name) const { +DetElement DetElement::child(const string& name) const { if ( isValid() ) { const Children& c = _data().children; Children::const_iterator i = c.find(name); @@ -484,9 +484,9 @@ DetElement& DetElement::setLimitSet(const LCDD& lcdd, const string& name, const } DetElement& DetElement::setAttributes(const LCDD& lcdd, const Volume& volume, - const std::string& region, - const std::string& limits, - const std::string& vis) + const string& region, + const string& limits, + const string& vis) { return setRegion(lcdd,region,volume).setLimitSet(lcdd,limits,volume).setVisAttributes(lcdd,vis,volume); } @@ -563,7 +563,7 @@ SensitiveDetector::Object::~Object() { } /// Constructor -SensitiveDetector::SensitiveDetector(const std::string& name, const std::string& type) { +SensitiveDetector::SensitiveDetector(const string& name, const string& type) { /* <calorimeter ecut="0" eunit="MeV" hits_collection="EcalEndcapHits" name="EcalEndcap" verbose="0"> <global_grid_xy grid_size_x="3.5" grid_size_y="3.5"/> @@ -576,7 +576,7 @@ SensitiveDetector::SensitiveDetector(const std::string& name, const std::string& } /// Set the type of the sensitive detector -SensitiveDetector& SensitiveDetector::setType(const std::string& typ) { +SensitiveDetector& SensitiveDetector::setType(const string& typ) { if ( isValid() ) { m_element->SetTitle(typ.c_str()); return *this; @@ -669,7 +669,7 @@ LimitSet SensitiveDetector::limits() const { } /// Add an extension object to the detector element -void* SensitiveDetector::i_addExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { +void* SensitiveDetector::i_addExtension(void* ptr, const type_info& info, void (*destruct)(void*)) { Object& o = _data(); Extensions::iterator j = o.extensions.find(&info); if ( j == o.extensions.end() ) { @@ -692,7 +692,7 @@ void* SensitiveDetector::i_addExtension(void* ptr, const std::type_info& info, v } /// Access an existing extension object from the detector element -void* SensitiveDetector::i_extension(const std::type_info& info) const { +void* SensitiveDetector::i_extension(const type_info& info) const { Object& o = _data(); Extensions::const_iterator j = o.extensions.find(&info); if ( j != o.extensions.end() ) { diff --git a/DDCore/src/FieldTypes.cpp b/DDCore/src/FieldTypes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58513d1d1e155738afb6061a6a1ca9efa9611c30 --- /dev/null +++ b/DDCore/src/FieldTypes.cpp @@ -0,0 +1,66 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DD4hep/FieldTypes.h" +#include <cmath> + +using namespace std; +using namespace DD4hep::Geometry; + +#ifndef INFINITY +#define INFINITY (numeric_limits<double>::max()) +#endif + +/// Call to access the field components at a given location +void ConstantField::fieldComponents(const double* /* pos */, double* field) { + field[0] += direction.x; + field[1] += direction.y; + field[2] += direction.z; +} + +/// Initializing constructor +SolenoidField::SolenoidField() + : innerField(0), outerField(0), + minZ(-INFINITY), maxZ(INFINITY), + innerRadius(0), outerRadius(INFINITY) +{ + type = CartesianField::MAGNETIC; +} + +/// Call to access the field components at a given location +void SolenoidField::fieldComponents(const double* pos, double* field) { + double radius = sqrt( pos[0] * pos[0] + pos[1] * pos[1] ); + if ( radius < innerRadius ) + field[2] += innerField; + else if ( radius < outerRadius ) + field[2] += outerField; +} + +/// Initializing constructor +DipoleField::DipoleField() + : zmax(INFINITY), zmin(-INFINITY), rmax(INFINITY) +{ +} + +/// Call to access the field components at a given location +void DipoleField::fieldComponents(const double* pos, double* field) { + double bx = 0, z = pos[2], r = sqrt(pos[0] * pos[0] + pos[1] * pos[1]); + + // Check if z coordinate is within dipole z bounds. + if (z > zmin && z < zmax && r < rmax) { + // Apply all coefficients to this z coordinate. + for (size_t i=0; i<coefficents.size(); ++i) + bx += coefficents[i] * pow(fabs(z),i); + + // Flip sign for negative z. + if (z < 0) bx = -bx; + // Add Bx to the input field. + field[0] += bx; + } +} diff --git a/DDCore/src/Fields.cpp b/DDCore/src/Fields.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55f88d095ffecc42b606f899ace1319c8b9efccc --- /dev/null +++ b/DDCore/src/Fields.cpp @@ -0,0 +1,105 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DD4hep/Fields.h" + +using namespace std; +using namespace DD4hep::Geometry; + +namespace { + void calculate_combined_field(vector<CartesianField>& v, const double* pos, double* field) { + for(vector<CartesianField>::iterator i=v.begin(); i!=v.end(); ++i) + (*i).value(pos,field); + } +} + +/// Access the field type (string) +const char* CartesianField::type() const { + return m_element->GetTitle(); +} + +/// Does the field change the energy of charged particles? +bool CartesianField::changesEnergy() const { + return ELECTRIC==(fieldType()&ELECTRIC); +} + +/// Access to properties container +CartesianField::Properties& CartesianField::properties() const { + return data<Object>()->properties; +} + +/// Returns the 3 field components (x, y, z). +void CartesianField::value(const double* pos, double* val) const { + data<Object>()->fieldComponents(pos,val); +} + +/// Object constructor +OverlayedField::OverlayedField(const string& name) : Ref_t() { + Value<TNamed,Object>* ptr = new Value<TNamed,Object>(); + assign(ptr,name,"overlay_field"); +} + +/// Access to properties container +OverlayedField::Properties& OverlayedField::properties() const { + return data<Object>()->properties; +} + +/// Does the field change the energy of charged particles? +bool OverlayedField::changesEnergy() const { + int field = data<Object>()->type; + return CartesianField::ELECTRIC==(field&CartesianField::ELECTRIC); +} + +/// Add a new field component +void OverlayedField::add(CartesianField field) { + if ( field.isValid() ) { + Object* o = data<Object>(); + if ( o ) { + int typ = field.fieldType(); + bool isEle = field.ELECTRIC==(typ&field.ELECTRIC); + bool isMag = field.MAGNETIC==(typ&field.MAGNETIC); + if ( isEle ) { + vector<CartesianField>& v = o->electric_components; + v.push_back(field); + o->type |= field.ELECTRIC; + o->electric = v.size()==1 ? field : CartesianField(); + } + if ( isMag ) { + vector<CartesianField>& v = o->magnetic_components; + v.push_back(field); + o->type |= field.MAGNETIC; + o->magnetic = v.size()==1 ? field : CartesianField(); + } + if ( isMag ||isEle ) return; + throw runtime_error("OverlayedField::add: Attempt to add an unknown field type."); + } + throw runtime_error("OverlayedField::add: Attempt to add to an invalid object."); + } + throw runtime_error("OverlayedField::add: Attempt to add an invalid field."); +} + +/// Returns the 3 electric field components (x, y, z). +void OverlayedField::combinedElectric(const double* pos, double* field) const { + field[0] = field[1] = field[2] = 0.; + calculate_combined_field(data<Object>()->electric_components,pos,field); +} + +/// Returns the 3 magnetic field components (x, y, z). +void OverlayedField::combinedMagnetic(const double* pos, double* field) const { + field[0] = field[1] = field[2] = 0.; + calculate_combined_field(data<Object>()->magnetic_components,pos,field); +} + +/// Returns the 3 electric (val[0]-val[2]) and magnetic field components (val[3]-val[5]). +void OverlayedField::electromagneticField(const double* pos, double* field) const { + Object* o = data<Object>(); + field[0] = field[1] = field[2] = 0.; + calculate_combined_field(o->electric_components,pos,field); + calculate_combined_field(o->magnetic_components,pos,field+3); +} diff --git a/DDCore/src/GeometryTreeDump.cpp b/DDCore/src/GeometryTreeDump.cpp index 226bcde2d24d813bc17fb31a60018b06240fffb7..eaa62817e3afabcbc9ff9db38d4c9b339ec34236 100644 --- a/DDCore/src/GeometryTreeDump.cpp +++ b/DDCore/src/GeometryTreeDump.cpp @@ -39,7 +39,7 @@ namespace { string indent = ""; /// Reference to output stream - std::ostream& m_output = cout; + ostream& m_output = cout; void getAngles(const Double_t* m, Double_t &phi, Double_t &theta, Double_t &psi) { diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index a898f94aee702a830eac31395810f25c7944e909..f884a5defd633b70742edaa85bb143f3ac0808ac 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -39,6 +39,20 @@ int DD4hep::Geometry::_toInt(const string& value) { return (int)result; } +long DD4hep::Geometry::_toLong(const string& value) { + string s(value); + size_t idx = s.find("(int)"); + if ( idx != string::npos ) + s.erase(idx,5); + while(s[0]==' ')s.erase(0,1); + double result = eval.evaluate(s.c_str()); + if (eval.status() != XmlTools::Evaluator::OK) { + cerr << value << ": "; + eval.print_error(); + } + return (long)result; +} + bool DD4hep::Geometry::_toBool(const string& value) { return value == "true"; } @@ -61,19 +75,19 @@ double DD4hep::Geometry::_toDouble(const string& value) { return result; } -template <> int _multiply<int>(const std::string& left, const std::string& right) { +template <> int _multiply<int>(const string& left, const string& right) { return (int)_toDouble(left+"*"+right); } -template <> long _multiply<long>(const std::string& left, const std::string& right) { +template <> long _multiply<long>(const string& left, const string& right) { return (long)_toDouble(left+"*"+right); } -template <> float _multiply<float>(const std::string& left, const std::string& right) { +template <> float _multiply<float>(const string& left, const string& right) { return _toFloat(left+"*"+right); } -template <> double _multiply<double>(const std::string& left, const std::string& right) { +template <> double _multiply<double>(const string& left, const string& right) { return _toDouble(left+"*"+right); } @@ -129,7 +143,7 @@ namespace DD4hep { namespace Geometry { msg += " to "; msg += to.name(); msg += " not possible!!"; - throw std::runtime_error(msg); + throw runtime_error(msg); } template <typename T> void Handle<T>::assign(T* n, const string& nam, const string& tit) { this->m_element = n; @@ -149,7 +163,7 @@ namespace DD4hep { namespace Geometry { msg += " to "; msg += to.name(); msg += " not possible!!"; - throw std::runtime_error(msg); + throw runtime_error(msg); } }} diff --git a/DDCore/src/IDDescriptor.cpp b/DDCore/src/IDDescriptor.cpp index 0efbb3792fb0a85300e98dc01d293b3a2f18368a..035c643d31f885306e43d57a565b3ce8dfdc0671 100644 --- a/DDCore/src/IDDescriptor.cpp +++ b/DDCore/src/IDDescriptor.cpp @@ -55,7 +55,7 @@ namespace { } /// Initializing constructor -IDDescriptor::IDDescriptor(const std::string& description) +IDDescriptor::IDDescriptor(const string& description) { Value<TNamed,Object>* obj = new Value<TNamed,Object>(); assign(obj,description,"iddescriptor"); diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index fa24ab0a3990dc4ead65750cc1301f947f50dadd..e63b03766646b6f96d6b217af09ff97bb76b4fd4 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -21,21 +21,20 @@ #include "TGeoVolume.h" #include "TGeoShape.h" #include "TClass.h" +#include "Reflex/PluginService.h" #if DD4HEP_USE_PYROOT #include "TPython.h" #elif DD4HEP_USE_XERCESC - #include "compact/Conversions.h" #include "XML/DocumentHandler.h" #endif -namespace DD4hep { namespace Geometry { struct Compact; }} using namespace DD4hep::Geometry; using namespace DD4hep; using namespace std; namespace { struct TopDetElement : public DetElement { - TopDetElement(const std::string& nam, Volume vol) : DetElement(nam,/* "structure", */0) { _data().volume = vol; } + TopDetElement(const string& nam, Volume vol) : DetElement(nam,/* "structure", */0) { _data().volume = vol; } }; } @@ -44,7 +43,19 @@ LCDD& LCDD::getInstance() { return *s_lcdd; } -LCDDImp::LCDDImp() : m_world(), m_trackers(), m_worldVol(), m_trackingVol() { +/// Default constructor +LCDDImp::LCDDImp() : m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global") +{ + m_properties = new Properties(); + if ( 0 == gGeoManager ) { + gGeoManager = new TGeoManager(); + } +} + +/// Standard destructor +LCDDImp::~LCDDImp() { + if ( m_properties ) delete m_properties; + m_properties = 0; } Volume LCDDImp::pickMotherVolume(const DetElement&) const { // throw if not existing @@ -57,17 +68,14 @@ LCDD& LCDDImp::addDetector(const Ref_t& x) { return *this; } -void LCDDImp::convertMaterials(const string& fname) { - //convertMaterials(XML::DocumentHandler().load(fname).root()); -} - -void LCDDImp::addStdMaterials() { - convertMaterials("file:../cmt/elements.xml"); - convertMaterials("file:../cmt/materials.xml"); +/// Add a field component by named reference to the detector description +LCDD& LCDDImp::addField(const Ref_t& x) { + m_field.add(x); + m_fields.append(x); + return *this; } - -Handle<TObject> LCDDImp::getRefChild(const HandleMap& e, const std::string& name, bool do_throw) const { +Handle<TObject> LCDDImp::getRefChild(const HandleMap& e, const string& name, bool do_throw) const { HandleMap::const_iterator i = e.find(name); if ( i != e.end() ) { return (*i).second; @@ -135,13 +143,13 @@ void LCDDImp::endDocument() { m_trackingVol.setRegion(trackingRegion); // Set the world volume to invisible. - VisAttr worldVis(lcdd,"WorldVis"); + VisAttr worldVis("WorldVis"); worldVis.setVisible(false); m_worldVol.setVisAttributes(worldVis); add(worldVis); // Set the tracking volume to invisible. - VisAttr trackingVis(lcdd,"TrackingVis"); + VisAttr trackingVis("TrackingVis"); trackingVis.setVisible(false); m_trackingVol.setVisAttributes(trackingVis); add(trackingVis); @@ -155,12 +163,6 @@ void LCDDImp::endDocument() { } } -void LCDDImp::create() { - if ( 0 == gGeoManager ) { - gGeoManager = new TGeoManager(); - } -} - void LCDDImp::init() { if ( !m_world.isValid() ) { Box worldSolid("world_box","world_x","world_y","world_z"); @@ -182,45 +184,46 @@ void LCDDImp::init() { } } -void LCDDImp::fromCompact(const std::string& xmlfile) { - create(); +void LCDDImp::fromXML(const string& xmlfile) { #if DD4HEP_USE_PYROOT string cmd; TPython::Exec("import lcdd"); - cmd = "lcdd.fromCompact('" + xmlfile + "')"; + cmd = "lcdd.fromXML('" + xmlfile + "')"; TPython::Exec(cmd.c_str()); #elif DD4HEP_USE_XERCESC - XML::Handle_t compact = XML::DocumentHandler().load(xmlfile).root(); + const XML::Handle_t xml_root = XML::DocumentHandler().load(xmlfile).root(); + string tag = xml_root.tag(); try { - Converter<Compact>(*this)(compact); + LCDD* lcdd = this; + string type = tag + "_XML_reader"; + long result = ROOT::Reflex::PluginService::Create<long>(type,lcdd,&xml_root); + if ( 0 == result ) { + throw runtime_error("Failed to locate plugin to interprete files of type" + " \""+tag+"\" - no factory:"+type); + } + result = *(long*)result; + if ( result != 1 ) { + throw runtime_error("Failed to parse the XML file "+xmlfile+" with the plugin "+type); + } } catch(const exception& e) { cout << "Exception:" << e.what() << endl; + throw runtime_error("Exception:"+string(e.what())+" while parsing "+xmlfile); } catch(xercesc::DOMException& e) { cout << "XML-DOM Exception:" << XML::_toString(e.msg) << endl; + throw runtime_error("XML-DOM Exception:"+XML::_toString(e.msg)+" while parsing "+xmlfile); } catch(...) { cout << "UNKNOWN Exception" << endl; + throw runtime_error("UNKNOWN excetion while parsing "+xmlfile); } #endif } -void LCDDImp::applyAlignment() { -} - -#include "SimpleGDMLWriter.h" -//#include "Geant4Converter.h" -#include "GeometryTreeDump.h" - void LCDDImp::dump() const { TGeoManager* mgr = gGeoManager; mgr->SetVisLevel(4); mgr->SetVisOption(1); m_worldVol->Draw("ogl"); - - // SimpleGDMLWriter handler(cout); - // Geant4Converter handler; - //GeometryTreeDump handler; - //handler.create(m_world); } diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h index 8bcc7dd79de41ee2523e099a886f623296ae8d58..a3e5a514d58b607d74c547b9302ccf6f6d38f3f2 100644 --- a/DDCore/src/LCDDImp.h +++ b/DDCore/src/LCDDImp.h @@ -37,17 +37,6 @@ namespace DD4hep { struct ObjectHandleMap : public HandleMap { ObjectHandleMap() {} -#if 0 - void append_noCheck(const Ref_t& e) { - if ( e.isValid() ) { - std::string n = e.name(); - if ( this->find(n) != this->end() ) { - throw InvalidObjectError("Object "+n+" is already present in map!"); - } - this->insert(std::make_pair(n,e.ptr())); - } - } -#endif void append(const Ref_t& e, bool throw_on_doubles=true) { if ( e.isValid() ) { std::string n = e.name(); @@ -58,6 +47,7 @@ namespace DD4hep { } throw InvalidObjectError("Attempt to add an invalid object."); } + template <typename T> void append(const Ref_t& e, bool throw_on_doubles=true) { T* obj = dynamic_cast<T*>(e.ptr()); if ( obj ) { @@ -67,7 +57,7 @@ namespace DD4hep { throw InvalidObjectError("Attempt to add an object, which is of the wrong type."); } }; - + ObjectHandleMap m_readouts; ObjectHandleMap m_header; ObjectHandleMap m_idDict; @@ -91,28 +81,37 @@ namespace DD4hep { Material m_materialAir; Material m_materialVacuum; - + + OverlayedField m_field; Ref_t m_setup; + Properties* m_properties; - void convertMaterials(const std::string& uri); + /// Default constructor LCDDImp(); + /// Standard destructor + virtual ~LCDDImp(); + /// Read compact geometry description or alignment file - virtual void fromCompact(const std::string& fname); + virtual void fromCompact(const std::string& fname) { fromXML(fname); } + /// Read any XML file + virtual void fromXML(const std::string& fname); + + virtual void dump() const; + /// Apply & lock realigments - virtual void applyAlignment(); + //virtual void applyAlignment(); - virtual void create(); + //virtual void create(); virtual void init(); - virtual void addStdMaterials(); virtual void endDocument(); - void dump() const; - virtual Handle<TObject> getRefChild(const HandleMap& e, const std::string& name, bool throw_if_not=true) const; virtual Volume pickMotherVolume(const DetElement& sd) const; + /// Access to properties + Properties& properties() const { return *m_properties; } /// Return handle to material describing air virtual Material air() const { return m_materialVacuum; } /// Return handle to material describing vacuum @@ -125,37 +124,43 @@ namespace DD4hep { virtual Volume worldVolume() const { return m_worldVol; } /// Return handle to the world volume containing the volume with the tracking devices virtual Volume trackingVolume() const { return m_trackingVol; } + /// Return handle to the combined electromagentic field description. + virtual OverlayedField field() const { return m_field; } + /// Retrieve a constant by it's name from the detector description virtual Constant constant(const std::string& name) const { return getRefChild(m_define,name); } /// Retrieve a limitset by it's name from the detector description - virtual LimitSet limitSet(const std::string& name) const + virtual LimitSet limitSet(const std::string& name) const { return getRefChild(m_limits,name); } /// Retrieve a visualization attribute by it's name from the detector description - virtual VisAttr visAttributes(const std::string& name) const + virtual VisAttr visAttributes(const std::string& name) const { return getRefChild(m_display,name,false); } /// Retrieve a matrial by it's name from the detector description - virtual Material material(const std::string& name) const + virtual Material material(const std::string& name) const { return getRefChild(m_materials,name); } /// Retrieve a region object by it's name from the detector description - virtual Region region(const std::string& name) const + virtual Region region(const std::string& name) const { return getRefChild(m_regions,name); } /// Retrieve a id descriptor by it's name from the detector description - virtual IDDescriptor idSpecification(const std::string& name) const + virtual IDDescriptor idSpecification(const std::string& name) const { return getRefChild(m_idDict,name); } /// Retrieve a readout object by it's name from the detector description - virtual Readout readout(const std::string& name) const + virtual Readout readout(const std::string& name) const { return getRefChild(m_readouts,name); } /// Retrieve an alignment entry by it's name from the detector description - virtual AlignmentEntry alignment(const std::string& path) const + virtual AlignmentEntry alignment(const std::string& path) const { return getRefChild(alignments(),path); } /// Retrieve a subdetector element by it's name from the detector description - virtual DetElement detector(const std::string& name) const + virtual DetElement detector(const std::string& name) const { return getRefChild(m_detectors,name); } /// Retrieve a sensitive detector by it's name from the detector description virtual SensitiveDetector sensitiveDetector(const std::string& name) const { return getRefChild(m_sensitive,name,false); } + /// Retrieve a subdetector element by it's name from the detector description + virtual CartesianField field(const std::string& name) const + { return getRefChild(m_fields,name,false); } /// Accessor to the map of header entries virtual const HandleMap& header() const { return m_header; } @@ -175,7 +180,9 @@ namespace DD4hep { virtual const HandleMap& detectors() const { return m_detectors; } /// Accessor to the map of aligment entries virtual const HandleMap& alignments() const { return m_alignments; } - + /// Accessor to the map of field entries, which together form the global field + virtual const HandleMap& fields() const { return m_fields; } + #define __R return *this /// Add a new constant to the detector description virtual LCDD& add(Constant x) { return addConstant(x); } @@ -195,6 +202,8 @@ namespace DD4hep { virtual LCDD& add(Readout x) { return addReadout(x); } /// Add a new subdetector to the detector description virtual LCDD& add(DetElement x) { return addDetector(x); } + /// Add a field component to the detector description + virtual LCDD& add(CartesianField x) { return addField(x); } /// Add a new constant by named reference to the detector description virtual LCDD& addConstant(const Ref_t& x) { m_define.append(x,false); __R;} @@ -216,6 +225,8 @@ namespace DD4hep { virtual LCDD& addDetector(const Ref_t& x); /// Add a new alignment entry by named reference to the detector description virtual LCDD& addAlignment(const Ref_t& x) { m_alignments.append(x); __R;} + /// Add a field component by named reference to the detector description + virtual LCDD& addField(const Ref_t& x); #undef __R }; diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp index e1f839927eb15f0e55099f80742ea47accfe1d47..06da9a57b693c7d1d3d4d57dc8865beeadfeab88 100644 --- a/DDCore/src/Objects.cpp +++ b/DDCore/src/Objects.cpp @@ -24,7 +24,6 @@ using namespace std; using namespace DD4hep::Geometry; -using DD4hep::IDDescriptor; #if 0 Header& Header::fromCompact(Document doc, Handle_t element, const string& fname) { @@ -57,16 +56,14 @@ Header::Header(LCDD& /* lcdd */) { } /// Constructor to be used when creating a new DOM tree -Constant::Constant(LCDD& lcdd, const string& nam, const string& val) +Constant::Constant(const string& nam, const string& val) { m_element = new TNamed(nam.c_str(),val.c_str()); - lcdd.add(*this); } /// Constructor to be used when creating a new DOM tree -Constant::Constant(LCDD& lcdd, const string& name) { +Constant::Constant(const string& name) { m_element = new TNamed(name.c_str(),""); - lcdd.add(*this); } /// String representation of this object @@ -78,7 +75,7 @@ string Constant::toString() const { } /// Constructor to be used when creating a new DOM tree -Atom::Atom(LCDD& /* lcdd */, const string& name, const string& formula, int Z, int N, double density) { +Atom::Atom(const string& name, const string& formula, int Z, int N, double density) { TGeoElementTable* t = TGeoElement::GetElementTable(); TGeoElement* e = t->FindElement(name.c_str()); if ( !e ) { @@ -89,7 +86,7 @@ Atom::Atom(LCDD& /* lcdd */, const string& name, const string& formula, int Z, i } /// Constructor to be used when creating a new DOM tree -Material::Material(LCDD& /* lcdd */, const string& name) { +Material::Material(const string& name) { TGeoMaterial* mat = gGeoManager->GetMaterial(name.c_str()); m_element = mat; } @@ -104,7 +101,7 @@ string Material::toString() const { } /// Constructor to be used when creating a new DOM tree -VisAttr::VisAttr(LCDD& /* lcdd */, const string& name) { +VisAttr::VisAttr(const string& name) { Value<TNamed,Object>* obj = new Value<TNamed,Object>(); assign(obj, name, "vis"); obj->color = 2; @@ -204,7 +201,7 @@ string VisAttr::toString() const { } /// Constructor to be used when creating a new aligment entry -AlignmentEntry::AlignmentEntry(LCDD& /* lcdd */, const string& path) { +AlignmentEntry::AlignmentEntry(const string& path) { TGeoPhysicalNode* obj = new TGeoPhysicalNode(path.c_str()); assign(obj,path,"*"); } @@ -242,7 +239,7 @@ int AlignmentEntry::align(const Position& pos, const Rotation& rot, bool check, m_element->Align(new_matrix,0,check,overlap); return 1; } - throw std::runtime_error("Callot align non existing physical node."); + throw runtime_error("Callot align non existing physical node."); } @@ -270,7 +267,7 @@ bool Limit::operator< (const Limit& c) const { } /// Conversion to a string representation -std::string Limit::toString() const { +string Limit::toString() const { string res = name + " = " + content; if ( !unit.empty() ) res += unit + " "; res + " (" + particles + ")"; diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp index d72706489fd3d45c47c146a71288f6ff231b9648..b5503eca986164b040ce4bc67bebc4e110ecd1c0 100644 --- a/DDCore/src/Segementations.cpp +++ b/DDCore/src/Segementations.cpp @@ -41,7 +41,7 @@ const string Segmentation::type() const { } /// Add an extension object to the detector element -void* Segmentation::i_setExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { +void* Segmentation::i_setExtension(void* ptr, const type_info& info, void (*destruct)(void*)) { Object& o = _data(); o.type = EXTENDED; o.data.extension.ptr = ptr; @@ -51,7 +51,7 @@ void* Segmentation::i_setExtension(void* ptr, const std::type_info& info, void ( } /// Access an existing extension object from the detector element -void* Segmentation::i_extension(const std::type_info& info) const { +void* Segmentation::i_extension(const type_info& info) const { if ( isValid() ) { Object::Data::Extension& o = _data().data.extension; if ( o.ptr ) { @@ -143,13 +143,13 @@ GridXY::GridXY() : Segmentation("grid_xy") {} /// Constructor to be used when creating a new object. Data are taken from the input handle -GridXY::GridXY(const std::string& tag) +GridXY::GridXY(const string& tag) : Segmentation(tag) { } /// Constructor to be used when creating a new object. -GridXY::GridXY(const std::string& tag, double size_x, double size_y) +GridXY::GridXY(const string& tag, double size_x, double size_y) : Segmentation(tag) { _data().data.cartesian_grid.grid_size_x = size_x; diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index e87aa741b3daa0646064b192a6da477817490fea..984fa05fa0c510565697bab41eb9ace6b7c2417b 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -211,7 +211,7 @@ namespace DD4hep { namespace Geometry { }} /// Add identifier -PlacedVolume& PlacedVolume::addPhysVolID(const std::string& name, int value) { +PlacedVolume& PlacedVolume::addPhysVolID(const string& name, int value) { Object* obj = data<Object>(); obj->volIDs[name] = value; return *this; @@ -424,7 +424,7 @@ LimitSet Volume::limitSet() const { return data<Object>()->limits; } /// Constructor to be used when creating a new geometry tree. -Assembly::Assembly(const std::string& name) { +Assembly::Assembly(const string& name) { m_element = new Value<TGeoVolumeAssembly,Volume::Object>(name.c_str()); } diff --git a/DDCore/src/XML/XMLDetector.cpp b/DDCore/src/XML/XMLDetector.cpp index 90cf63613732d3cf174e0c69aab759977aea9bf0..f65fa6f80569dd4c8da386920b31addbf63c2490 100644 --- a/DDCore/src/XML/XMLDetector.cpp +++ b/DDCore/src/XML/XMLDetector.cpp @@ -55,6 +55,10 @@ double Dimension::zmin() const { return m_element.attr<double>(Attr_zmin); } +double Dimension::zmax() const { + return m_element.attr<double>(Attr_zmax); +} + double Dimension::rmax() const { return m_element.attr<double>(Attr_rmax); } @@ -71,6 +75,10 @@ double Dimension::outer_r() const { return m_element.attr<double>(Attr_outer_r); } +double Dimension::outer_radius() const { + return m_element.attr<double>(Attr_outer_radius); +} + double Dimension::inner_z() const { return m_element.attr<double>(Attr_inner_z); } @@ -79,6 +87,10 @@ double Dimension::inner_r() const { return m_element.attr<double>(Attr_inner_r); } +double Dimension::inner_radius() const { + return m_element.attr<double>(Attr_inner_radius); +} + bool Dimension::reflect() const { return m_element.attr<bool>(Attr_reflect); } @@ -250,6 +262,14 @@ double Dimension::zstart() const { return m_element.attr<double>(Attr_zstart); } +double DetElement::inner_field() const { + return m_element.attr<double>(Attr_inner_field); +} + +double DetElement::outer_field() const { + return m_element.attr<double>(Attr_outer_field); +} + int DetElement::Component::id() const { return m_element.attr<int>(Attr_id); } diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp index 568694b47188a8aa5aed2b244edad9eec835959b..3a9f3a91dbb2f2c75ef90aa95c76fc8e03d6cbc0 100644 --- a/DDCore/src/XML/XMLElements.cpp +++ b/DDCore/src/XML/XMLElements.cpp @@ -233,12 +233,26 @@ Tag_t& Tag_t::operator=(const string& s) { return *this; } +/// Clone the DOMelement - with the option of a deep copy Handle_t Handle_t::clone(DOMDocument* new_doc, bool deep) const { return (DOMElement*)new_doc->importNode(m_node, deep); } +/// Retrieve a collection of all attributes of this DOM element +vector<Attribute> Handle_t::attributes() const { + vector<Attribute> attrs; + if ( m_node ) { + xercesc::DOMNamedNodeMap* l = m_node->getAttributes(); + for(XMLSize_t i=0, n=l->getLength(); i<n; ++i) { + DOMNode* n = l->item(i); + attrs.push_back(Attribute(n)); + } + } + return attrs; +} + size_t Handle_t::numChildren(const XMLCh* t, bool throw_exception) const { - DOMNodeList* e = (DOMNodeList*)(m_node ? m_node->getElementsByTagName(t) : 0); + NodeList e = (NodeList)(m_node ? m_node->getElementsByTagName(t) : 0); if ( e || !throw_exception ) return e->getLength(); string msg = "Handle_t::numChildren: "; if ( m_node ) @@ -248,19 +262,9 @@ size_t Handle_t::numChildren(const XMLCh* t, bool throw_exception) const { throw runtime_error(msg); } -Handle_t Handle_t::firstChild(const XMLCh* t) const { - DOMNodeList* e = (DOMNodeList*)(m_node ? m_node->getElementsByTagName(t) : 0); - if ( e && e->getLength()>0 ) return (DOMElement*)e->item(0); - string msg = "Handle_t::firstChild: "; - if ( m_node ) - msg += "Element ["+tag()+"] has no children of type '"+_toString(t)+"'"; - else - msg += "Element [INVALID] has no children of type '"+_toString(t)+"'"; - throw runtime_error(msg); -} - Handle_t Handle_t::child(const XMLCh* t, bool throw_exception) const { - DOMElement* e = (DOMElement*)(m_node ? m_node->getElementsByTagName(t)->item(0) : 0); + NodeList l = (NodeList)(m_node ? m_node->getElementsByTagName(t) : 0); + DOMElement* e = (DOMElement*)(l ? l->item(0) : 0); if ( e || !throw_exception ) return e; string msg = "Handle_t::child: "; if ( m_node ) @@ -270,29 +274,28 @@ Handle_t Handle_t::child(const XMLCh* t, bool throw_exception) const { throw runtime_error(msg); } -Handle_t Handle_t::remove(xercesc::DOMElement* node) const { - DOMElement* e = (DOMElement*)(m_node && node ? m_node->removeChild(node) : 0); +Handle_t Handle_t::remove(Handle_t node) const { + DOMElement* e = (DOMElement*)(m_node && node.ptr() ? m_node->removeChild(node.ptr()) : 0); if ( e ) return e; string msg = "Handle_t::remove: "; - Handle_t n(node); - if ( m_node && n.ptr() ) - msg += "Element ["+tag()+"] has no child of type '"+n.tag()+"'"; - else if ( n ) - msg += "Element [INVALID]. Cannot remove child of type: '"+n.tag()+"'"; - else if ( n ) + if ( m_node && node.ptr() ) + msg += "Element ["+tag()+"] has no child of type '"+node.tag()+"'"; + else if ( node ) + msg += "Element [INVALID]. Cannot remove child of type: '"+node.tag()+"'"; + else if ( node ) msg += "Element [INVALID]. Cannot remove [INVALID] child. Big Shit!!!!"; throw runtime_error(msg); } void Handle_t::removeChildren(const XMLCh* tag) const { - DOMNodeList* l=m_node->getElementsByTagName(tag); + NodeList l=m_node->getElementsByTagName(tag); for(XMLSize_t i=0, n=l->getLength(); i<n; ++i) m_node->removeChild(l->item(i)); } bool Handle_t::hasChild(const XMLCh* tag) const { - DOMNodeList* n = m_node->getElementsByTagName(tag); + NodeList n = m_node->getElementsByTagName(tag); return n ? n->getLength()>0 : false; } @@ -319,6 +322,10 @@ Attribute Handle_t::attr_ptr(const XMLCh* t) const { throw runtime_error(msg); } +const XMLCh* Handle_t::attr_name(const Attribute attr) const { + return attr->getName(); +} + const XMLCh* Handle_t::attr_value(const XMLCh* attr) const { return attr_ptr(attr)->getValue(); } @@ -375,7 +382,7 @@ Attribute Handle_t::setAttr(const XMLCh* name, const XMLCh* value) const { return attr; } -DOMElement* Document::createElt(const XMLCh* tag) const { +Handle_t Document::createElt(const XMLCh* tag) const { return m_doc->createElement(tag); } @@ -429,14 +436,14 @@ Handle_t Element::addChild(const XMLCh* tag) const { } Handle_t Element::child(const Strng_t& tag, bool throw_exception) const { - DOMNodeList* l=m_element->getElementsByTagName(tag); + NodeList l=m_element->getElementsByTagName(tag); if ( l && l->getLength() > 0 ) return Handle_t((DOMElement*)l->item(0)); if ( throw_exception ) throw runtime_error("Cannot find the required child node!"); return Handle_t(0); } Handle_t Element::setChild(const XMLCh* tag) const { - DOMNodeList* l=m_element->getElementsByTagName(tag); + NodeList l=m_element->getElementsByTagName(tag); if ( l && l->getLength() > 0 ) return Handle_t((DOMElement*)l->item(0)); return addChild(tag); } @@ -472,46 +479,85 @@ void RefElement::setName(const XMLCh* new_name) { setAttr(Attr_name,new_name); } -Collection_t::Collection_t(DOMElement* n, const XMLCh* tag) : m_index(-1), m_element(n) { - m_children = n->getElementsByTagName(tag); - m_node = (DOMElement*)(m_children->getLength() == 0 ? 0 : n); +Collection_t::Collection_t(Elt_t element, DOMNode::NodeType typ) + : m_type(typ), m_index(-1) +{ + m_children = element->getChildNodes(); + m_node = (DOMElement*)m_children->item(0); ++(*this); } -Collection_t::Collection_t(DOMElement* n, const char* tag) : m_index(-1), m_element(n) { - m_children = n->getElementsByTagName(Tag_t(tag)); - m_node = (DOMElement*)(m_children->getLength() == 0 ? 0 : n);//m_children->item(m_index)); +Collection_t::Collection_t(Elt_t element, const XMLCh* tag) + : m_type(DOMNode::ELEMENT_NODE), m_index(-1) +{ + m_children = element->getElementsByTagName(tag); + m_node = (DOMElement*)m_children->item(0); ++(*this); } -Collection_t::Collection_t(DOMElement* n, DOMNodeList* c) : m_index(-1), m_element(n), m_children(c) { - m_node = (DOMElement*)(m_children->getLength() == 0 ? 0 : n); +Collection_t::Collection_t(Elt_t element, const char* tag) + : m_type(DOMNode::ELEMENT_NODE), m_index(-1) +{ + m_children = element->getElementsByTagName(Strng_t(tag)); + m_node = (DOMElement*)m_children->item(0); + ++(*this); +} + +Collection_t::Collection_t(NodeList node_list) + : m_type(DOMNode::ELEMENT_NODE), m_index(-1), m_children(node_list) +{ + m_node = (DOMElement*)m_children->item(0); + ++(*this); +} + +Collection_t::Collection_t(NodeList node_list, DOMNode::NodeType typ) + : m_type(typ), m_index(-1), m_children(node_list) +{ + m_node = (DOMElement*)m_children->item(0); ++(*this); } Collection_t& Collection_t::reset() { m_index = -1; - m_node = (DOMElement*)(m_children->getLength() == 0 ? 0 : m_element); + m_node = (DOMElement*)(m_children->getLength() == 0 ? 0 : m_children->item(0)); ++(*this); return *this; } size_t Collection_t::size() const { - return m_children ? m_children->getLength() : 0; + return m_children->getLength(); } void Collection_t::operator++() const { + Elt_t e = Elt_t(m_node ? m_node->getParentNode() : 0); while(m_node) { - //int t1 = m_node->getNodeType(); - //int t2 = DOMNode::ELEMENT_NODE; m_node = (DOMElement*)m_children->item(++m_index); - if ( m_node && m_node->getNodeType() == DOMNode::ELEMENT_NODE ) { - if ( m_node->getParentNode() == m_element ) + if ( m_node && m_node->getNodeType() == m_type ) { + if ( m_node->getParentNode() == e ) return; } } } +void Collection_t::operator--() const { + Elt_t e = Elt_t(m_node ? m_node->getParentNode() : 0); + while(m_node) { + m_node = (DOMElement*)m_children->item(--m_index); + if ( m_node && m_node->getNodeType() == m_type ) { + if ( m_node->getParentNode() == e ) + return; + } + } +} + +void Collection_t::operator++(int) const { + ++(*this); +} + +void Collection_t::operator--(int) const { + --(*this); +} + Handle_t Document::clone(Handle_t source, bool deep) const { return (DOMElement*)(m_doc->importNode(source,deep)); } diff --git a/DDCore/src/XML/XMLTags.cpp b/DDCore/src/XML/XMLTags.cpp index eca4dd8088af56f52095d42811181c3788165e9c..fccbd6c1adbee5167cf9dd20215e438673444641 100644 --- a/DDCore/src/XML/XMLTags.cpp +++ b/DDCore/src/XML/XMLTags.cpp @@ -58,6 +58,10 @@ namespace DD4hep { namespace XML { TAG(fraction); TAG(composite); TAG(sd); + TAG(dipole_coeff); + ATTR(funit); + ATTR(global); + ATTR(local); TAG(box); TAG(define); @@ -93,12 +97,15 @@ namespace DD4hep { namespace XML { TAG(tube); TAG(vis); TAG(visref); + TAG(strength); TAG(volume); TAG(volumeref); TAG(zplane); TAG(alignments); TAG(alignment); + TAG(properties); + TAG(attributes); ATTR(overlap); ATTR(check); @@ -116,6 +123,10 @@ namespace DD4hep { namespace XML { ATTR(dimensions); ATTR(ecut); ATTR(false); + ATTR(strength); + ATTR(field); + ATTR(inner_field); + ATTR(outer_field); ATTR(field_name); ATTR(g); ATTR(gridSizeX); @@ -125,6 +136,7 @@ namespace DD4hep { namespace XML { ATTR(hits_collection); TAG(identity_rot); TAG(identity_pos); + ATTR(inner_radius); ATTR(inner_r); ATTR(inner_z); ATTR(layer); @@ -134,6 +146,7 @@ namespace DD4hep { namespace XML { ATTR(name); ATTR(nphi); ATTR(ntheta); + ATTR(outer_radius); ATTR(outer_r); ATTR(outer_z); ATTR(position); @@ -146,6 +159,7 @@ namespace DD4hep { namespace XML { ATTR(region); ATTR(repeat); ATTR(zmin); + ATTR(zmax); ATTR(rmin); ATTR(rmax); ATTR(rotation); @@ -174,6 +188,7 @@ namespace DD4hep { namespace XML { TAG(color); TAG(detectors); TAG(display); + TAG(field); TAG(fields); TAG(gdml); TAG(grid_xyz); diff --git a/DDCore/src/compact/Compact2Objects.cpp b/DDCore/src/compact/Compact2Objects.cpp index 0acf7f742002aecd3d4df88bcaacd31065c93bf7..78eb80f3edf609c36842f9c862e6342b2ee19a29 100644 --- a/DDCore/src/compact/Compact2Objects.cpp +++ b/DDCore/src/compact/Compact2Objects.cpp @@ -6,15 +6,14 @@ // Author : M.Frank // //==================================================================== - #include "DD4hep/DetFactoryHelper.h" #include "DD4hep/IDDescriptor.h" +#include "DD4hep/FieldTypes.h" #include "XML/DocumentHandler.h" +#include "XML/Conversions.h" #include "xercesc/util/XMLURL.hpp" -#include "Conversions.h" #include "TGeoManager.h" -//#include "TGeoElement.h" #include "TGeoMaterial.h" #include "Reflex/PluginService.h" @@ -26,6 +25,32 @@ using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; + +namespace DD4hep { + namespace Geometry { + struct Compact; + struct Includes; + struct GdmlFile; + struct Property; + struct AlignmentFile; + } + template <> void Converter<Constant>::operator()(const xml_h& e) const; + template <> void Converter<Material>::operator()(const xml_h& e) const; + template <> void Converter<Atom>::operator()(const xml_h& e) const; + template <> void Converter<VisAttr>::operator()(const xml_h& e) const; + template <> void Converter<AlignmentEntry>::operator()(const xml_h& e) const; + template <> void Converter<Region>::operator()(const xml_h& e) const; + template <> void Converter<Readout>::operator()(const xml_h& e) const; + template <> void Converter<LimitSet>::operator()(const xml_h& e) const; + template <> void Converter<Property>::operator()(const xml_h& e) const; + template <> void Converter<CartesianField>::operator()(const xml_h& e) const; + template <> void Converter<SensitiveDetector>::operator()(const xml_h& element) const; + template <> void Converter<DetElement>::operator()(const xml_h& element) const; + template <> void Converter<GdmlFile>::operator()(const xml_h& element) const; + template <> void Converter<AlignmentFile>::operator()(const xml_h& element) const; + template <> void Converter<Compact>::operator()(const xml_h& element) const; +} + namespace { static UInt_t unique_mat_id = 0xAFFEFEED; } @@ -85,450 +110,546 @@ static Ref_t create_ProjectiveZPlane(lcdd_t& /* lcdd */, const xml_h& e) { } DECLARE_XMLELEMENT(ProjectiveZPlane,create_ProjectiveZPlane); -namespace DD4hep { namespace Geometry { - struct Compact; - struct Includes; - struct GdmlFile; - struct AlignmentFile; +static Ref_t create_ConstantField(lcdd_t& /* lcdd */, const xml_h& e) { + CartesianField obj; + xml_comp_t field(e), strength(e.child(_X(strength))); + string t = e.attr<string>(_A(field)); + Value<TNamed,ConstantField>* ptr = new Value<TNamed,ConstantField>(); + ptr->type = ::toupper(t[0])=='E' ? CartesianField::ELECTRIC : CartesianField::MAGNETIC; + ptr->direction.set(strength.x(),strength.y(),strength.z()); + obj.assign(ptr,field.nameStr(),field.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(ConstantField,create_ConstantField); - template <typename T> Handle<> toObject(LCDD& lcdd, const xml_h& xml); - - template <> Ref_t toRefObject<Constant>(lcdd_t& lcdd, const xml_h& e) { - xml_ref_t constant(e); - TNamed* obj = new TNamed(constant.attr<string>(_A(name)).c_str(), - constant.attr<string>(_A(value)).c_str()); - Ref_t cons(obj); - _toDictionary(obj->GetName(),obj->GetTitle()); - lcdd.addConstant(cons); - return cons; +static Ref_t create_SolenoidField(lcdd_t& /* lcdd */, const xml_h& e) { + xml_comp_t c(e); + CartesianField obj; + Value<TNamed,SolenoidField>* ptr = new Value<TNamed,SolenoidField>(); + if ( c.hasAttr(_A(inner_radius)) ) ptr->innerRadius = c.attr<double>(_A(inner_radius)); + if ( c.hasAttr(_A(outer_radius)) ) ptr->outerRadius = c.attr<double>(_A(outer_radius)); + if ( c.hasAttr(_A(inner_field)) ) ptr->innerField = c.attr<double>(_A(inner_field)); + if ( c.hasAttr(_A(outer_field)) ) ptr->outerField = c.attr<double>(_A(outer_field)); + if ( c.hasAttr(_A(zmax)) ) ptr->maxZ = c.attr<double>(_A(zmax)); + if ( c.hasAttr(_A(zmin)) ) ptr->minZ = c.attr<double>(_A(zmin)); + else ptr->minZ = - ptr->maxZ; + obj.assign(ptr,c.nameStr(),c.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(SolenoidMagnet,create_SolenoidField); + +static Ref_t create_DipoleField(lcdd_t& /* lcdd */, const xml_h& e) { + xml_comp_t c(e); + CartesianField obj; + Value<TNamed,DipoleField>* ptr = new Value<TNamed,DipoleField>(); + double val, lunit = c.attr<double>(_A(lunit)), funit = c.attr<double>(_A(funit)); + + if ( c.hasAttr(_A(zmin)) ) ptr->zmin = _multiply<double>(c.attr<string>(_A(zmin)),lunit); + if ( c.hasAttr(_A(zmax)) ) ptr->zmax = _multiply<double>(c.attr<string>(_A(zmax)),lunit); + if ( c.hasAttr(_A(rmax)) ) ptr->rmax = _multiply<double>(c.attr<string>(_A(rmax)),lunit); + for( xml_coll_t coll(c,_X(dipole_coeff)); coll; ++coll) { + val = funit/pow(lunit,ptr->coefficents.size()); + val = _multiply<double>(coll.value(),val); + ptr->coefficents.push_back(val); } - - template <> Ref_t toRefObject<Atom>(lcdd_t& /* lcdd */, const xml_h& e) { - /* <element Z="29" formula="Cu" name="Cu" > - <atom type="A" unit="g/mol" value="63.5456" /> - </element> - */ - xml_ref_t elem(e); - xml_tag_t eltname = elem.name(); - TGeoManager* mgr = gGeoManager; - TGeoElementTable* tab = mgr->GetElementTable(); - TGeoElement* element = tab->FindElement(eltname.c_str()); - if ( !element ) { - xml_ref_t atom(elem.child(_X(atom))); - tab->AddElement(elem.attr<string>(_A(name)).c_str(), - elem.attr<string>(_A(formula)).c_str(), - elem.attr<int>(_A(Z)), - atom.attr<int>(_A(value)) - ); - element = tab->FindElement(eltname.c_str()); - } - return Ref_t(element); + obj.assign(ptr,c.nameStr(),c.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(DipoleMagnet,create_DipoleField); + +static long create_Compact(lcdd_t& lcdd, const xml_h& element) { + Converter<Compact> converter(lcdd); + converter(element); + return 1; +} +DECLARE_XML_DOC_READER(lccdd,create_Compact); + +/** Convert compact constant objects (defines) + * + * + */ +template <> void Converter<Constant>::operator()(const xml_h& e) const { + xml_ref_t constant(e); + TNamed* obj = new TNamed(constant.attr<string>(_A(name)).c_str(), + constant.attr<string>(_A(value)).c_str()); + Ref_t cons(obj); + _toDictionary(obj->GetName(),obj->GetTitle()); + lcdd.addConstant(cons); +} + +/** Convert compact material/element description objects + * + * Materials: + * <material name="Air"> + * <D type="density" unit="g/cm3" value="0.0012"/> + * <fraction n="0.754" ref="N"/> + * <fraction n="0.234" ref="O"/> + * <fraction n="0.012" ref="Ar"/> + * </material> + * + * Elements: + * <element Z="29" formula="Cu" name="Cu" > + * <atom type="A" unit="g/mol" value="63.5456" /> + * </element> + * + */ +template <> void Converter<Material>::operator()(const xml_h& e) const { + xml_ref_t m(e); + TGeoManager* mgr = gGeoManager; + xml_tag_t mname = m.name(); + const char* matname = mname.c_str(); + xml_h density = m.child(XML::Tag_D); + TGeoElementTable* table = mgr->GetElementTable(); + TGeoMaterial* mat = mgr->GetMaterial(matname); + TGeoMixture* mix = dynamic_cast<TGeoMixture*>(mat); + xml_coll_t fractions(m,_X(fraction)); + xml_coll_t composites(m,_X(composite)); + set<string> elts; + if ( 0 == mat ) { + xml_h radlen = m.child(XML::Tag_RL,false); + xml_h intlen = m.child(XML::Tag_NIL,false); + double radlen_val = radlen.ptr() ? radlen.attr<double>(_A(value)) : 0.0; + double intlen_val = intlen.ptr() ? intlen.attr<double>(_A(value)) : 0.0; + mat = mix = new TGeoMixture(matname,composites.size(),density.attr<double>(_A(value))); + mat->SetRadLen(radlen_val,intlen_val); + //cout << "Compact2Objects[INFO]: Creating material:" << matname << " composites:" << composites.size()+fractions.size() << endl; } - - template <> Ref_t toRefObject<Material>(lcdd_t& /* lcdd */, const xml_h& e) { - /* <material name="Air"> - <D type="density" unit="g/cm3" value="0.0012"/> - <fraction n="0.754" ref="N"/> - <fraction n="0.234" ref="O"/> - <fraction n="0.012" ref="Ar"/> - </material> - <element Z="29" formula="Cu" name="Cu" > - <atom type="A" unit="g/mol" value="63.5456" /> - </element> - */ - xml_ref_t m(e); - TGeoManager* mgr = gGeoManager; - xml_tag_t mname = m.name(); - const char* matname = mname.c_str(); - xml_h density = m.child(XML::Tag_D); - TGeoElementTable* table = mgr->GetElementTable(); - TGeoMaterial* mat = mgr->GetMaterial(matname); - TGeoMixture* mix = dynamic_cast<TGeoMixture*>(mat); - xml_coll_t fractions(m,_X(fraction)); - xml_coll_t composites(m,_X(composite)); - set<string> elts; - if ( 0 == mat ) { - xml_h radlen = m.child(XML::Tag_RL,false); - xml_h intlen = m.child(XML::Tag_NIL,false); - double radlen_val = radlen.ptr() ? radlen.attr<double>(_A(value)) : 0.0; - double intlen_val = intlen.ptr() ? intlen.attr<double>(_A(value)) : 0.0; - mat = mix = new TGeoMixture(matname,composites.size(),density.attr<double>(_A(value))); - mat->SetRadLen(radlen_val,intlen_val); - //cout << "Compact2Objects[INFO]: Creating material:" << matname << " composites:" << composites.size()+fractions.size() << endl; - } - if ( mix ) { - for(Int_t i=0, n=mix->GetNelements(); i<n; ++i) - elts.insert(mix->GetElement(i)->GetName()); - } - for(; composites; ++composites) { - std::string nam = composites.attr<string>(_X(ref)); - TGeoElement* element; - if ( elts.find(nam) == elts.end() ) { - double fraction = composites.attr<double>(_X(n)); - if ( 0 != (element=table->FindElement(nam.c_str())) ) - mix->AddElement(element,fraction); - else if ( 0 != (mat=mgr->GetMaterial(nam.c_str())) ) - mix->AddElement(mat,fraction); - else { - string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; - cout << msg << endl; - throw runtime_error(msg); - } + if ( mix ) { + for(Int_t i=0, n=mix->GetNelements(); i<n; ++i) + elts.insert(mix->GetElement(i)->GetName()); + } + for(; composites; ++composites) { + std::string nam = composites.attr<string>(_X(ref)); + TGeoElement* element; + if ( elts.find(nam) == elts.end() ) { + double fraction = composites.attr<double>(_X(n)); + if ( 0 != (element=table->FindElement(nam.c_str())) ) + mix->AddElement(element,fraction); + else if ( 0 != (mat=mgr->GetMaterial(nam.c_str())) ) + mix->AddElement(mat,fraction); + else { + string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; + cout << msg << endl; + throw runtime_error(msg); } } - for(; fractions; ++fractions) { - std::string nam = fractions.attr<string>(_X(ref)); - TGeoElement* element; - if ( elts.find(nam) == elts.end() ) { - double fraction = fractions.attr<double>(_X(n)); - if ( 0 != (element=table->FindElement(nam.c_str())) ) - mix->AddElement(element,fraction); - else if ( 0 != (mat=mgr->GetMaterial(nam.c_str())) ) - mix->AddElement(mat,fraction); - else { - string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; - cout << msg << endl; - throw runtime_error(msg); - } + } + for(; fractions; ++fractions) { + std::string nam = fractions.attr<string>(_X(ref)); + TGeoElement* element; + if ( elts.find(nam) == elts.end() ) { + double fraction = fractions.attr<double>(_X(n)); + if ( 0 != (element=table->FindElement(nam.c_str())) ) + mix->AddElement(element,fraction); + else if ( 0 != (mat=mgr->GetMaterial(nam.c_str())) ) + mix->AddElement(mat,fraction); + else { + string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; + cout << msg << endl; + throw runtime_error(msg); } } - TGeoMedium* medium = mgr->GetMedium(matname); - if ( 0 == medium ) { - --unique_mat_id; - medium = new TGeoMedium(matname,unique_mat_id,mat); - medium->SetTitle("material"); - medium->SetUniqueID(unique_mat_id); - } - return Ref_t(medium); - } - - template <> Ref_t toRefObject<IDDescriptor>(lcdd_t& /* lcdd */, const xml_h& e) { - /* <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> */ - IDDescriptor id(e.text()); - return Ref_t(id); } - - template <> Ref_t toRefObject<LimitSet>(lcdd_t& lcdd, const xml_h& e) { - /* <limitset name="...."> - * <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> - * ... </limitset> - */ - LimitSet ls(e.attr<string>(_A(name))); - for (xml_coll_t c(e,XML::Tag_limit); c; ++c) { - Limit limit; - limit.particles = c.attr<string>(_A(particles)); - limit.name = c.attr<string>(_A(name)); - limit.content = c.attr<string>(_A(value)); - limit.unit = c.attr<string>(_A(unit)); - limit.value = _multiply<double>(limit.content,limit.unit); - ls.addLimit(limit); - } - return ls; + TGeoMedium* medium = mgr->GetMedium(matname); + if ( 0 == medium ) { + --unique_mat_id; + medium = new TGeoMedium(matname,unique_mat_id,mat); + medium->SetTitle("material"); + medium->SetUniqueID(unique_mat_id); } - - /// Convert compact visualization attribute to LCDD visualization attribute - template <> Ref_t toRefObject<VisAttr>(lcdd_t& lcdd, const xml_h& e) { - /* <vis name="SiVertexBarrelModuleVis" alpha="1.0" r="1.0" g="0.75" b="0.76" drawingStyle="wireframe" showDaughters="false" visible="true"/> - */ - VisAttr attr(lcdd,e.attr<string>(_A(name))); - float r = e.hasAttr(_A(r)) ? e.attr<float>(_A(r)) : 1.0f; - float g = e.hasAttr(_A(g)) ? e.attr<float>(_A(g)) : 1.0f; - float b = e.hasAttr(_A(b)) ? e.attr<float>(_A(b)) : 1.0f; - attr.setColor(r,g,b); - if ( e.hasAttr(_A(alpha)) ) attr.setAlpha(e.attr<float>(_A(alpha))); - if ( e.hasAttr(_A(visible)) ) attr.setVisible(e.attr<bool>(_A(visible))); - if ( e.hasAttr(_A(lineStyle)) ) { - string ls = e.attr<string>(_A(lineStyle)); - if ( ls == "unbroken" ) attr.setLineStyle(VisAttr::SOLID); - if ( ls == "broken" ) attr.setLineStyle(VisAttr::DASHED); - } - else { - attr.setLineStyle(VisAttr::SOLID); - } - if ( e.hasAttr(_A(drawingStyle)) ) { - string ds = e.attr<string>(_A(drawingStyle)); - if ( ds == "wireframe" ) attr.setDrawingStyle(VisAttr::WIREFRAME); - } - else { - attr.setDrawingStyle(VisAttr::WIREFRAME); - } - if ( e.hasAttr(_A(showDaughters)) ) attr.setShowDaughters(e.attr<bool>(_A(showDaughters))); - return attr; + + lcdd.addMaterial(Ref_t(medium)); +} + +/** Convert compact atom objects + * + * <element Z="29" formula="Cu" name="Cu" > + */ +template <> void Converter<Atom>::operator()(const xml_h& e) const { + xml_ref_t elem(e); + xml_tag_t eltname = elem.name(); + TGeoManager* mgr = gGeoManager; + TGeoElementTable* tab = mgr->GetElementTable(); + TGeoElement* element = tab->FindElement(eltname.c_str()); + if ( !element ) { + xml_ref_t atom(elem.child(_X(atom))); + tab->AddElement(elem.attr<string>(_A(name)).c_str(), + elem.attr<string>(_A(formula)).c_str(), + elem.attr<int>(_A(Z)), + atom.attr<int>(_A(value)) + ); + element = tab->FindElement(eltname.c_str()); } +} - template <> Ref_t toRefObject<Readout>(lcdd_t& lcdd, const xml_h& e) { - /* <readout name="HcalBarrelHits"> - <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" /> - <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> - </readout> - */ - const xml_h id = e.child(_X(id)); - const xml_h seg = e.child(_X(segmentation),false); - string name = e.attr<string>(_A(name)); - Readout ro(name); - - if ( seg ) { // Segmentation is not mandatory! - string type = seg.attr<string>(_A(type)); - Ref_t segment(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&seg)); - if ( !segment.isValid() ) throw runtime_error("FAILED to create segmentation:"+type); - ro.setSegmentation(segment); - } - if ( id ) { - Ref_t idSpec = toRefObject<IDDescriptor>(lcdd,id); - idSpec->SetName(ro.name()); - ro.setIDDescriptor(idSpec); - lcdd.addIDSpecification(idSpec); - } - return ro; +/** Convert compact visualization attribute to LCDD visualization attribute + * + * <vis name="SiVertexBarrelModuleVis" + * alpha="1.0" r="1.0" g="0.75" b="0.76" + * drawingStyle="wireframe" + * showDaughters="false" + * visible="true"/> + */ +template <> void Converter<VisAttr>::operator()(const xml_h& e) const { + VisAttr attr(e.attr<string>(_A(name))); + float r = e.hasAttr(_A(r)) ? e.attr<float>(_A(r)) : 1.0f; + float g = e.hasAttr(_A(g)) ? e.attr<float>(_A(g)) : 1.0f; + float b = e.hasAttr(_A(b)) ? e.attr<float>(_A(b)) : 1.0f; + attr.setColor(r,g,b); + if ( e.hasAttr(_A(alpha)) ) attr.setAlpha(e.attr<float>(_A(alpha))); + if ( e.hasAttr(_A(visible)) ) attr.setVisible(e.attr<bool>(_A(visible))); + if ( e.hasAttr(_A(lineStyle)) ) { + string ls = e.attr<string>(_A(lineStyle)); + if ( ls == "unbroken" ) attr.setLineStyle(VisAttr::SOLID); + if ( ls == "broken" ) attr.setLineStyle(VisAttr::DASHED); + } + else { + attr.setLineStyle(VisAttr::SOLID); + } + if ( e.hasAttr(_A(drawingStyle)) ) { + string ds = e.attr<string>(_A(drawingStyle)); + if ( ds == "wireframe" ) attr.setDrawingStyle(VisAttr::WIREFRAME); + } + else { + attr.setDrawingStyle(VisAttr::WIREFRAME); } + if ( e.hasAttr(_A(showDaughters)) ) attr.setShowDaughters(e.attr<bool>(_A(showDaughters))); + lcdd.addVisAttribute(attr); +} - template <> Ref_t toRefObject<AlignmentEntry>(lcdd_t& lcdd, const xml_h& e) { - /* <alignment name="<path/to/object>" shortcut="short_cut_name"> - <position x="x-value" y="y-value" z="z-value"/> - <rotation theta="theta-value" phi="phi-value" psi="psi-value"/> - </alignment> - */ - xml_comp_t child(e); - string path = e.attr<string>(_A(name)); - bool check = e.hasAttr(_A(check)); - bool overlap = e.hasAttr(_A(overlap)); - AlignmentEntry alignment(lcdd,path); - Position pos; - Rotation rot; - if ( (child=e.child(_X(position),false)) ) { // Position is not mandatory! - pos.x = child.x(); - pos.y = child.y(); - pos.z = child.z(); - } - if ( (child=e.child(_X(rotation),false)) ) { // Rotation is not mandatory - rot.theta = child.x(); // child.theta(); - rot.phi = child.y(); // child.phi(); - rot.psi = child.z(); // child.psi(); - } - if ( overlap ) { - double ovl = e.attr<double>(_A(overlap)); - alignment.align(pos,rot,check,ovl); - } - else { - alignment.align(pos,rot,check); - } - return alignment; +/** Specialized converter for compact AlignmentEntry objects. + * + * <alignment name="<path/to/object>" shortcut="short_cut_name"> + * <position x="x-value" y="y-value" z="z-value"/> + * <rotation theta="theta-value" phi="phi-value" psi="psi-value"/> + * </alignment> + */ +template <> void Converter<AlignmentEntry>::operator()(const xml_h& e) const { + xml_comp_t child(e); + string path = e.attr<string>(_A(name)); + bool check = e.hasAttr(_A(check)); + bool overlap = e.hasAttr(_A(overlap)); + AlignmentEntry alignment(path); + Position pos; + Rotation rot; + if ( (child=e.child(_X(position),false)) ) { // Position is not mandatory! + pos.x = child.x(); + pos.y = child.y(); + pos.z = child.z(); } - - namespace { - template <typename T> static Ref_t toRefObject(LCDD& lcdd, const xml_h& xml, SensitiveDetector& sens) - { return toRefObject<T>(lcdd,xml,sens); } + if ( (child=e.child(_X(rotation),false)) ) { // Rotation is not mandatory + rot.theta = child.x(); // child.theta(); + rot.phi = child.y(); // child.phi(); + rot.psi = child.z(); // child.psi(); } - - template <> Ref_t toRefObject<Region>(lcdd_t& /* lcdd */, const xml_h& e) { - Region region(e.attr<string>(_A(name))); - vector<string>& limits = region.limits(); - string ene = e.attr<string>(_A(eunit)), len = e.attr<string>(_A(lunit)); - - region.setEnergyUnit(ene); - region.setLengthUnit(len); - region.setCut(_multiply<double>(e.attr<string>(_A(cut)),len)); - region.setThreshold(_multiply<double>(e.attr<string>(_A(threshold)),ene)); - region.setStoreSecondaries(e.attr<bool>(_A(store_secondaries))); - for(xml_coll_t user_limits(e,_X(limitsetref)); user_limits; ++user_limits) - limits.push_back(user_limits.attr<string>(_A(name))); - return region; + if ( overlap ) { + double ovl = e.attr<double>(_A(overlap)); + alignment.align(pos,rot,check,ovl); } - - template <> void Converter<Constant>::operator()(const xml_h& element) const { - lcdd.addConstant(toRefObject<to_type>(lcdd,element)); + else { + alignment.align(pos,rot,check); } - template <> void Converter<Material>::operator()(const xml_h& element) const { - lcdd.addMaterial(toRefObject<to_type>(lcdd,element)); + lcdd.addAlignment(alignment); +} + +/** Specialized converter for compact region objects. + * + */ +template <> void Converter<Region>::operator()(const xml_h& e) const { + Region region(e.attr<string>(_A(name))); + vector<string>& limits = region.limits(); + string ene = e.attr<string>(_A(eunit)), len = e.attr<string>(_A(lunit)); + + region.setEnergyUnit(ene); + region.setLengthUnit(len); + region.setCut(_multiply<double>(e.attr<string>(_A(cut)),len)); + region.setThreshold(_multiply<double>(e.attr<string>(_A(threshold)),ene)); + region.setStoreSecondaries(e.attr<bool>(_A(store_secondaries))); + for(xml_coll_t user_limits(e,_X(limitsetref)); user_limits; ++user_limits) + limits.push_back(user_limits.attr<string>(_A(name))); + lcdd.addRegion(region); +} + +/** Specialized converter for compact readout objects. + * + * <readout name="HcalBarrelHits"> + * <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" /> + * <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> + * </readout> + */ +template <> void Converter<Readout>::operator()(const xml_h& e) const { + const xml_h id = e.child(_X(id)); + const xml_h seg = e.child(_X(segmentation),false); + string name = e.attr<string>(_A(name)); + Readout ro(name); + + if ( seg ) { // Segmentation is not mandatory! + string type = seg.attr<string>(_A(type)); + Ref_t segment(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&seg)); + if ( !segment.isValid() ) throw runtime_error("FAILED to create segmentation:"+type); + ro.setSegmentation(segment); } - template <> void Converter<Atom>::operator()(const xml_h& element) const { - toRefObject<to_type>(lcdd,element); + if ( id ) { + // <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> + Ref_t idSpec = IDDescriptor(id.text()); + idSpec->SetName(ro.name()); + ro.setIDDescriptor(idSpec); + lcdd.addIDSpecification(idSpec); } - template <> void Converter<VisAttr>::operator()(const xml_h& element) const { - lcdd.addVisAttribute(toRefObject<to_type>(lcdd,element)); + lcdd.addReadout(ro); +} + +/** Specialized converter for compact LimitSet objects. + * + * <limitset name="...."> + * <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + * ... </limitset> + */ +template <> void Converter<LimitSet>::operator()(const xml_h& e) const { + LimitSet ls(e.attr<string>(_A(name))); + for (xml_coll_t c(e,XML::Tag_limit); c; ++c) { + Limit limit; + limit.particles = c.attr<string>(_A(particles)); + limit.name = c.attr<string>(_A(name)); + limit.content = c.attr<string>(_A(value)); + limit.unit = c.attr<string>(_A(unit)); + limit.value = _multiply<double>(limit.content,limit.unit); + ls.addLimit(limit); } - template <> void Converter<AlignmentEntry>::operator()(const xml_h& element) const { - lcdd.addAlignment(toRefObject<to_type>(lcdd,element)); + lcdd.addLimitSet(ls); +} + +/** Specialized converter for generic LCDD properties + * + * <properties> + * <attributes name="key" type="" .... /> + * ... </properties> + */ +template <> void Converter<Property>::operator()(const xml_h& e) const { + string name = e.attr<string>(_A(name)); + LCDD::Properties& prp = lcdd.properties(); + if ( name.empty() ) { + throw runtime_error("Failed to convert properties. No name given!"); } - template <> void Converter<Region>::operator()(const xml_h& element) const { - lcdd.addRegion(toRefObject<to_type>(lcdd,element)); + vector<xml_attr_t> a = e.attributes(); + if ( prp.find(name) == prp.end() ) { + prp.insert(make_pair(name,LCDD::PropertyValues())); } - template <> void Converter<Readout>::operator()(const xml_h& element) const { - lcdd.addReadout(toRefObject<to_type>(lcdd,element)); + for( vector<xml_attr_t>::iterator i=a.begin(); i != a.end(); ++i) { + pair<string,string> val(xml_tag_t(e.attr_name(*i)),e.attr<string>(*i)); + prp[name].insert(val); } - template <> void Converter<LimitSet>::operator()(const xml_h& element) const { - lcdd.addLimitSet(toRefObject<to_type>(lcdd,element)); +} + +/** Specialized converter for electric and magnetic fields + * + * Uses internally a plugin to allow flexible field descriptions. + * + * <field type="ConstantField" name="Myfield" field="electric"> + * <strength x="0" y="0" z="5"/> + * </field> + */ +template <> void Converter<CartesianField>::operator()(const xml_h& e) const { + string msg = "updated"; + string name = e.attr<string>(_A(name)); + string type = e.attr<string>(_A(type)); + CartesianField field = lcdd.field(name); + if ( !field.isValid() ) { + // The field is not present: We create it and add it to LCDD + field = Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&e)); + if ( !field.isValid() ) { + throw runtime_error("Failed to create field object of type "+type); + } + lcdd.addField(field); + msg = "created"; } - void setChildTitles(const pair<string,DetElement>& e) { - DetElement parent = e.second.parent(); - const DetElement::Children& children = e.second.children(); - if ( strlen(e.second->GetTitle()) == 0 ) { - e.second->SetTitle(parent.isValid() ? parent.type().c_str() : e.first.c_str()); + type = field.type(); + // Now update the field structure with the generic part ie. set it's properties + CartesianField::Properties& prp = field.properties(); + for( xml_coll_t c(e,_X(properties)); c; ++c) { + string props_name = c.attr<string>(_A(name)); + vector<xml_attr_t> a = c.attributes(); + if ( prp.find(props_name) == prp.end() ) { + prp.insert(make_pair(props_name,CartesianField::PropertyValues())); + } + for( vector<xml_attr_t>::iterator i=a.begin(); i != a.end(); ++i) { + pair<string,string> val(xml_tag_t(c.attr_name(*i)),c.attr<string>(*i)); + prp[props_name].insert(val); } - else { - //cout << "Title present: " << e.second->GetTitle() << endl; + if ( c.hasAttr(_A(global)) && c.attr<bool>(_A(global)) ) { + lcdd.field().properties() = prp; } - for_each(children.begin(),children.end(),setChildTitles); } + cout << "Converted field: Successfully " << msg << " field " << name << " [" << type << "]" << endl; +} +/** Update sensitive detectors from group tags. + * + * Handle xml sections of the type: + * <sd name="MuonBarrel" + * type="Geant4Calorimeter" + * ecut="100.0*MeV" + * verbose="true" + * hit_aggregation="position" + * limits="limit-set-reference" + * region="region-name-reference"> + * </sd> + * + */ +template <> void Converter<SensitiveDetector>::operator()(const xml_h& element) const { + string name = element.attr<string>(_A(name)); + try { + DetElement det = lcdd.detector(name); + SensitiveDetector sd = lcdd.sensitiveDetector(name); - /** Update sensitive detectors from group tags. - * - * Handle xml sections of the type: - * <sd name="MuonBarrel" - * type="Geant4Calorimeter" - * ecut="100.0*MeV" - * verbose="true" - * hit_aggregation="position" - * limits="limit-set-reference" - * region="region-name-reference"> - * </sd> - * - */ - template <> void Converter<SensitiveDetector>::operator()(const xml_h& element) const { - string name = element.attr<string>(_A(name)); - try { - DetElement det = lcdd.detector(name); - SensitiveDetector sd = lcdd.sensitiveDetector(name); - - xml_attr_t type = element.attr_nothrow(_A(type)); - if ( type ) { - sd.setType(element.attr<string>(type)); - } - xml_attr_t verbose = element.attr_nothrow(_A(verbose)); - if ( verbose ) { - sd.setVerbose(element.attr<bool>(verbose)); - } - xml_attr_t combine = element.attr_nothrow(_A(combine_hits)); - if ( combine ) { - sd.setCombineHits(element.attr<bool>(combine)); - } - xml_attr_t limits = element.attr_nothrow(_A(limits)); - if ( limits ) { - string l = element.attr<string>(limits); - LimitSet ls = lcdd.limitSet(l); - if ( !ls.isValid() ) { - throw runtime_error("Converter<SensitiveDetector>: Request for non-existing limitset:"+l); - } - sd.setLimitSet(ls); - } - xml_attr_t region = element.attr_nothrow(_A(region)); - if ( region ) { - string r = element.attr<string>(region); - Region reg = lcdd.region(r); - if ( !reg.isValid() ) { - throw runtime_error("Converter<SensitiveDetector>: Request for non-existing region:"+r); - } - sd.setRegion(reg); - } - xml_attr_t hits = element.attr_nothrow(_A(hits_collection)); - if ( hits ) { - sd.setHitsCollection(element.attr<string>(hits)); - } - xml_attr_t ecut = element.attr_nothrow(_A(ecut)); - xml_attr_t eunit = element.attr_nothrow(_A(eunit)); - if ( ecut && eunit ) { - double value = _multiply<double>(_toString(ecut),_toString(eunit)); - sd.setEnergyCutoff(value); - } - else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used! - sd.setEnergyCutoff(element.attr<double>(ecut)); + xml_attr_t type = element.attr_nothrow(_A(type)); + if ( type ) { + sd.setType(element.attr<string>(type)); + } + xml_attr_t verbose = element.attr_nothrow(_A(verbose)); + if ( verbose ) { + sd.setVerbose(element.attr<bool>(verbose)); + } + xml_attr_t combine = element.attr_nothrow(_A(combine_hits)); + if ( combine ) { + sd.setCombineHits(element.attr<bool>(combine)); + } + xml_attr_t limits = element.attr_nothrow(_A(limits)); + if ( limits ) { + string l = element.attr<string>(limits); + LimitSet ls = lcdd.limitSet(l); + if ( !ls.isValid() ) { + throw runtime_error("Converter<SensitiveDetector>: Request for non-existing limitset:"+l); } - if ( sd.verbose() ) { - cout << "SensitiveDetector-update:" << setw(18) << left << sd.name() - << setw(24) << left << " ["+sd.type()+"] " - << "Hits:" << setw(24) << left << sd.hitsCollection() - << "Cutoff:" << sd.energyCutoff() - << endl; + sd.setLimitSet(ls); + } + xml_attr_t region = element.attr_nothrow(_A(region)); + if ( region ) { + string r = element.attr<string>(region); + Region reg = lcdd.region(r); + if ( !reg.isValid() ) { + throw runtime_error("Converter<SensitiveDetector>: Request for non-existing region:"+r); } + sd.setRegion(reg); } - catch(const exception& e) { - cout << "FAILED to convert sensitive detector:" << name << ": " << e.what() << endl; + xml_attr_t hits = element.attr_nothrow(_A(hits_collection)); + if ( hits ) { + sd.setHitsCollection(element.attr<string>(hits)); } - catch(...) { - cout << "FAILED to convert sensitive detector:" << name << ": UNKNONW Exception" << endl; + xml_attr_t ecut = element.attr_nothrow(_A(ecut)); + xml_attr_t eunit = element.attr_nothrow(_A(eunit)); + if ( ecut && eunit ) { + double value = _multiply<double>(_toString(ecut),_toString(eunit)); + sd.setEnergyCutoff(value); } + else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used! + sd.setEnergyCutoff(element.attr<double>(ecut)); + } + if ( sd.verbose() ) { + cout << "SensitiveDetector-update:" << setw(18) << left << sd.name() + << setw(24) << left << " ["+sd.type()+"] " + << "Hits:" << setw(24) << left << sd.hitsCollection() + << "Cutoff:" << sd.energyCutoff() + << endl; + } + } + catch(const exception& e) { + cout << "FAILED to convert sensitive detector:" << name << ": " << e.what() << endl; } + catch(...) { + cout << "FAILED to convert sensitive detector:" << name << ": UNKNONW Exception" << endl; + } +} - template <> void Converter<DetElement>::operator()(const xml_h& element) const { - static const char* req_dets = ::getenv("REQUIRED_DETECTORS"); - static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES"); - static const char* ign_dets = ::getenv("IGNORED_DETECTORS"); - static const char* ign_typs = ::getenv("IGNORED_DETECTOR_TYPES"); - string type = element.attr<string>(_A(type)); - string name = element.attr<string>(_A(name)); - string name_match = ":"+name+":"; - string type_match = ":"+type+":"; - if ( req_dets && !strstr(req_dets,name_match.c_str()) ) return; - if ( req_typs && !strstr(req_typs,type_match.c_str()) ) return; - if ( ign_dets && strstr(ign_dets,name_match.c_str()) ) return; - if ( ign_typs && strstr(ign_typs,type_match.c_str()) ) return; - try { - xml_attr_t attr_ro = element.attr_nothrow(_A(readout)); - SensitiveDetector sd; +void setChildTitles(const pair<string,DetElement>& e) { + DetElement parent = e.second.parent(); + const DetElement::Children& children = e.second.children(); + if ( ::strlen(e.second->GetTitle()) == 0 ) { + e.second->SetTitle(parent.isValid() ? parent.type().c_str() : e.first.c_str()); + } + for_each(children.begin(),children.end(),setChildTitles); +} +template <> void Converter<DetElement>::operator()(const xml_h& element) const { + static const char* req_dets = ::getenv("REQUIRED_DETECTORS"); + static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES"); + static const char* ign_dets = ::getenv("IGNORED_DETECTORS"); + static const char* ign_typs = ::getenv("IGNORED_DETECTOR_TYPES"); + string type = element.attr<string>(_A(type)); + string name = element.attr<string>(_A(name)); + string name_match = ":"+name+":"; + string type_match = ":"+type+":"; + if ( req_dets && !strstr(req_dets,name_match.c_str()) ) return; + if ( req_typs && !strstr(req_typs,type_match.c_str()) ) return; + if ( ign_dets && strstr(ign_dets,name_match.c_str()) ) return; + if ( ign_typs && strstr(ign_typs,type_match.c_str()) ) return; + try { + xml_attr_t attr_ro = element.attr_nothrow(_A(readout)); + SensitiveDetector sd; + if ( attr_ro ) { + Readout ro = lcdd.readout(element.attr<string>(attr_ro)); + sd = SensitiveDetector(name,"sensitive"); + sd.setHitsCollection(ro.name()); + sd.setReadout(ro); + lcdd.addSensitiveDetector(sd); + } + DetElement det(Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&element,&sd))); + if ( det.isValid() ) { + setChildTitles(make_pair(name,det)); if ( attr_ro ) { - Readout ro = lcdd.readout(element.attr<string>(attr_ro)); - sd = SensitiveDetector(name,"sensitive"); - sd.setHitsCollection(ro.name()); - sd.setReadout(ro); - lcdd.addSensitiveDetector(sd); - } - DetElement det(Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&element,&sd))); - if ( det.isValid() ) { - setChildTitles(make_pair(name,det)); - if ( attr_ro ) { - det.setReadout(sd.readout()); - } + det.setReadout(sd.readout()); } - cout << (det.isValid() ? "Converted" : "FAILED ") - << " subdetector:" << name << " of type " << type; - if ( sd.isValid() ) cout << " [" << sd.type() << "]"; - cout << endl; - lcdd.addDetector(det); - } - catch(const exception& e) { - cout << "FAILED to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl; - } - catch(...) { - cout << "FAILED to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl; } + cout << (det.isValid() ? "Converted" : "FAILED ") + << " subdetector:" << name << " of type " << type; + if ( sd.isValid() ) cout << " [" << sd.type() << "]"; + cout << endl; + lcdd.addDetector(det); } - - /// Read material entries from a seperate file in one of the include sections of the geometry - template <> void Converter<GdmlFile>::operator()(const xml_h& element) const { - xercesc::XMLURL base(element.ptr()->getBaseURI()); - xercesc::XMLURL ref(base, element.attr_value(_A(ref))); - xml_h materials = XML::DocumentHandler().load(_toString(ref.getURLText())).root(); - xml_coll_t(materials,_X(element) ).for_each(Converter<Atom>(this->lcdd)); - xml_coll_t(materials,_X(material)).for_each(Converter<Material>(this->lcdd)); + catch(const exception& e) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl; } - - /// Read alignment entries from a seperate file in one of the include sections of the geometry - template <> void Converter<AlignmentFile>::operator()(const xml_h& element) const { - xercesc::XMLURL base(element.ptr()->getBaseURI()); - xercesc::XMLURL ref(base, element.attr_value(_A(ref))); - xml_h alignments = XML::DocumentHandler().load(_toString(ref.getURLText())).root(); - xml_coll_t(alignments,_X(alignment)).for_each(Converter<AlignmentEntry>(this->lcdd)); + catch(...) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl; } +} - template <> void Converter<Compact>::operator()(const xml_h& element) const { - xml_elt_t compact(element); - xml_coll_t(compact,_X(includes) ).for_each(_X(gdmlFile), Converter<GdmlFile>(lcdd)); - //Header(lcdd.header()).fromCompact(doc,compact.child(Tag_info),Strng_t("In memory")); - xml_coll_t(compact,_X(define) ).for_each(_X(constant), Converter<Constant>(lcdd)); - xml_coll_t(compact,_X(materials) ).for_each(_X(element), Converter<Atom>(lcdd)); - xml_coll_t(compact,_X(materials) ).for_each(_X(material), Converter<Material>(lcdd)); - lcdd.init(); - xml_coll_t(compact,_X(limits) ).for_each(_X(limitset), Converter<LimitSet>(lcdd)); - xml_coll_t(compact,_X(display) ).for_each(_X(vis), Converter<VisAttr>(lcdd)); - xml_coll_t(compact,_X(readouts) ).for_each(_X(readout), Converter<Readout>(lcdd)); - xml_coll_t(compact,_X(detectors) ).for_each(_X(detector), Converter<DetElement>(lcdd)); - xml_coll_t(compact,_X(includes) ).for_each(_X(alignment),Converter<AlignmentFile>(lcdd)); - xml_coll_t(compact,_X(alignments) ).for_each(_X(alignment),Converter<AlignmentEntry>(lcdd)); - xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(sd),Converter<SensitiveDetector>(lcdd)); - lcdd.endDocument(); - } -}} +/// Read material entries from a seperate file in one of the include sections of the geometry +template <> void Converter<GdmlFile>::operator()(const xml_h& element) const { + xercesc::XMLURL base(element.ptr()->getBaseURI()); + xercesc::XMLURL ref(base, element.attr_value(_A(ref))); + xml_h materials = XML::DocumentHandler().load(_toString(ref.getURLText())).root(); + xml_coll_t(materials,_X(element) ).for_each(Converter<Atom>(this->lcdd)); + xml_coll_t(materials,_X(material)).for_each(Converter<Material>(this->lcdd)); +} + +/// Read alignment entries from a seperate file in one of the include sections of the geometry +template <> void Converter<AlignmentFile>::operator()(const xml_h& element) const { + xercesc::XMLURL base(element.ptr()->getBaseURI()); + xercesc::XMLURL ref(base, element.attr_value(_A(ref))); + xml_h alignments = XML::DocumentHandler().load(_toString(ref.getURLText())).root(); + xml_coll_t(alignments,_X(alignment)).for_each(Converter<AlignmentEntry>(this->lcdd)); +} + +template <> void Converter<Compact>::operator()(const xml_h& element) const { + xml_elt_t compact(element); + xml_coll_t(compact,_X(includes) ).for_each(_X(gdmlFile), Converter<GdmlFile>(lcdd)); + //Header(lcdd.header()).fromCompact(doc,compact.child(Tag_info),Strng_t("In memory")); + xml_coll_t(compact,_X(define) ).for_each(_X(constant), Converter<Constant>(lcdd)); + xml_coll_t(compact,_X(materials) ).for_each(_X(element), Converter<Atom>(lcdd)); + xml_coll_t(compact,_X(materials) ).for_each(_X(material), Converter<Material>(lcdd)); + xml_coll_t(compact,_X(properties) ).for_each(_X(attributes),Converter<Property>(lcdd)); + lcdd.init(); + xml_coll_t(compact,_X(limits) ).for_each(_X(limitset), Converter<LimitSet>(lcdd)); + xml_coll_t(compact,_X(display) ).for_each(_X(vis), Converter<VisAttr>(lcdd)); + xml_coll_t(compact,_X(readouts) ).for_each(_X(readout), Converter<Readout>(lcdd)); + xml_coll_t(compact,_X(detectors) ).for_each(_X(detector), Converter<DetElement>(lcdd)); + xml_coll_t(compact,_X(includes) ).for_each(_X(alignment),Converter<AlignmentFile>(lcdd)); + xml_coll_t(compact,_X(alignments) ).for_each(_X(alignment),Converter<AlignmentEntry>(lcdd)); + xml_coll_t(compact,_X(fields) ).for_each(_X(field), Converter<CartesianField>(lcdd)); + xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(sd),Converter<SensitiveDetector>(lcdd)); + lcdd.endDocument(); +} + #ifdef _WIN32 template Converter<Atom>; diff --git a/DDCore/src/compact/LCDD2Output.cpp b/DDCore/src/compact/LCDD2Output.cpp index ec5c0bb62ec5b089c20148da5f888e0d4828d1e9..a2d56a80c201eb7238794a541a8e1ac92f7348f7 100644 --- a/DDCore/src/compact/LCDD2Output.cpp +++ b/DDCore/src/compact/LCDD2Output.cpp @@ -7,7 +7,7 @@ // //==================================================================== -#include "Conversions.h" +#include "XML/Conversions.h" #include "DD4hep/LCDD.h" #include "DD4hep/Objects.h" #include "DD4hep/IDDescriptor.h" @@ -21,8 +21,9 @@ #include <iomanip> using namespace std; +using namespace DD4hep::Geometry; -namespace DD4hep { namespace Geometry { +namespace DD4hep { template <> void Printer<Constant>::operator()(const Constant& val) const { os << "++ Constant:" << val.toString() << endl; @@ -194,4 +195,4 @@ namespace DD4hep { namespace Geometry { void dumpTopVolume() { dumpVolume(gGeoManager->GetTopVolume(),0); } -}} +}