diff --git a/DDCore/include/DD4hep/Alignment.h b/DDCore/include/DD4hep/Alignment.h index ccf71f992d3b18ae40e2517d5b46f838af1a679b..142ada4a1584a0a3792bd89cf9a7ce3534e5901d 100644 --- a/DDCore/include/DD4hep/Alignment.h +++ b/DDCore/include/DD4hep/Alignment.h @@ -39,6 +39,10 @@ namespace DD4hep { public: /// Default constructor Alignment(); + /// Default constructor + Alignment(TGeoPhysicalNode* p) + : Handle<TGeoPhysicalNode>(p) { + } /// Copy constructor Alignment(const Alignment& c); /// Constructor to be used when reading the already parsed object @@ -49,7 +53,7 @@ namespace DD4hep { Alignment(const std::string& path); /// Assignment operator Alignment& operator=(const Alignment& c); - /// Number of nodes in this branch + /// Number of nodes in this branch (=depth of the placement hierarchy from the top level volume) int numNodes() const; /// Access the placement of this node PlacedVolume placement() const; @@ -62,13 +66,23 @@ namespace DD4hep { * == direct mother of placement() */ PlacedVolume nodePlacement(int level=-1) const; + /// Access the currently applied alignment/placement matrix with respect to the world + Transform3D toGlobal(int level=-1) const; + /// Transform a point from local coordinates of a given level to global coordinates + Position toGlobal(const Position& localPoint, int level=-1) const; + /// Transform a point from global coordinates to local coordinates of a given level + Position globalToLocal(const Position& globalPoint, int level=-1) const; + + /// Access the currently applied alignment/placement matrix with respect to mother volume + Transform3D toMother(int level=-1) const; + + /// Access the currently applied alignment/placement matrix (mother to daughter) + Transform3D nominal() const; + /// Access the currently applied correction matrix (delta) (mother to daughter) + Transform3D delta() const; + /// Access the inverse of the currently applied correction matrix (delta) (mother to daughter) + Transform3D invDelta() const; - /// Align the PhysicalNode (translation only) - int align(const Position& pos, bool check = false, double overlap = 0.001); - /// Align the PhysicalNode (rotation only) - int align(const RotationZYX& rot, bool check = false, double overlap = 0.001); - /// Align the PhysicalNode (translation + rotation) - int align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001); }; } /* End namespace Geometry */ diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index c5e0d91568f489bed88916cf10a4dcaf4e34def5..d3fc671a9bd9973c5451cb310960319c5f050b41 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -199,7 +199,11 @@ namespace DD4hep { /// Full path to this detector element. May be invalid std::string path; int combineHits; + /// Basic detector element alignment entry Alignment alignment; + /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements + std::vector<Alignment> volume_alignments; + /// The detector elements condition entry Conditions conditions; PlacedVolume placement; Parent parent; diff --git a/DDCore/include/DD4hep/DetectorAlignment.h b/DDCore/include/DD4hep/DetectorAlignment.h deleted file mode 100644 index 2c2b3d6737e229bc5bafd73e7e7db9b4a66d7893..0000000000000000000000000000000000000000 --- a/DDCore/include/DD4hep/DetectorAlignment.h +++ /dev/null @@ -1,49 +0,0 @@ -// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ -//==================================================================== -// AIDA Detector description implementation for LCD -//-------------------------------------------------------------------- -// -// Author : M.Frank -// -//==================================================================== -#ifndef DD4HEP_GEOMETRY_DETECTORALIGNMENT_H -#define DD4HEP_GEOMETRY_DETECTORALIGNMENT_H - -// Framework include files -#include "DD4hep/Detector.h" - -/* - * DD4hep namespace declaration - */ -namespace DD4hep { - - /* - * Geometry namespace declaration - */ - namespace Geometry { - - class DetElement; - - /** @class Alignment Readoutn.h DD4hep/Alignment.h - * - * @author M.Frank - * @version 1.0 - */ - class DetectorAlignment : public DetElement { - protected: - public: - /// Initializing constructor - DetectorAlignment(DetElement e); - /// Collect all placements from the detector element up to the world volume - void collectNodes(std::vector<PlacedVolume>& nodes); - /// Align the PhysicalNode of the placement of the detector element (translation only) - int align(const Position& pos, bool check = false, double overlap = 0.001); - /// Align the PhysicalNode of the placement of the detector element (rotation only) - int align(const RotationZYX& rot, bool check = false, double overlap = 0.001); - /// Align the PhysicalNode of the placement of the detector element (translation + rotation) - int align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001); - }; - - } /* End namespace Geometry */ -} /* End namespace DD4hep */ -#endif /* DD4HEP_GEOMETRY_DETECTORALIGNMENT_H */ diff --git a/DDCore/include/DD4hep/DetectorTools.h b/DDCore/include/DD4hep/DetectorTools.h index d84cb7cf6a16782fc5271e962a2b67734b6ab50d..43693255676eba43e33d309ce1216b50210b5d59 100644 --- a/DDCore/include/DD4hep/DetectorTools.h +++ b/DDCore/include/DD4hep/DetectorTools.h @@ -22,6 +22,9 @@ namespace DD4hep { */ namespace Geometry { + // Forward declarations + class LCDD; + /** @class Detectortools DetectorTools.h DD4hep/Detectortools.h * * @author M.Frank @@ -31,6 +34,10 @@ namespace DD4hep { public: typedef std::vector<DetElement> ElementPath; typedef std::vector<PlacedVolume> PlacementPath; + /// Assemble the path of a particular detector element + std::string elementPath(DetElement element); + /// Assemble the path of the PlacedVolume selection + static std::string elementPath(const ElementPath& nodes); /// Collect detector elements to the top detector element (world) static void elementPath(DetElement elt, ElementPath& detectors); /// Collect detector elements to any parent detector element @@ -38,21 +45,30 @@ namespace DD4hep { /// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] static void elementPath(DetElement elt, PlacementPath& nodes); + /// Find DetElement as child of the top level volume by it's absolute path + static DetElement findElement(LCDD& lcdd, const std::string& path); + /// Find DetElement as child of a parent by it's relative or absolute path + static DetElement findElement(DetElement parent, const std::string& subpath); + /// Determine top level element (=world) for any element walking up the detector element tree + static DetElement topElement(DetElement child); + + /// Assemble the placement path from a given detector element to the world volume + static std::string placementPath(DetElement element); + /// Assemble the path of the PlacedVolume selection + static std::string placementPath(const PlacementPath& nodes); /// Collect detector elements placements to the top detector element (world) [no holes!] static void placementPath(DetElement elt, PlacementPath& nodes); /// Collect detector elements placements to the parent detector element [no holes!] static void placementPath(DetElement parent, DetElement child, PlacementPath& nodes); + + /// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes static bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path); - /// Create cached matrix to transform to positions to an upper level Placement - static TGeoMatrix* placementTrafo(const PlacementPath& nodes, bool inverse); - /// Find path between the child element and the parent element static bool findParent(DetElement parent, DetElement child, ElementPath& detectors); - /// Assemble the path of the PlacedVolume selection - static std::string elementPath(const ElementPath& nodes); - /// Assemble the path of the PlacedVolume selection - static std::string nodePath(const PlacementPath& nodes); + + /// Create cached matrix to transform to positions to an upper level Placement + static TGeoMatrix* placementTrafo(const PlacementPath& nodes, bool inverse); }; diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index 0b7ad394ceed0d56713f4953943de278d9e41282..275284c200876a600157da5cb510925abc044b13 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -182,12 +182,7 @@ namespace DD4hep { template <typename Q> Q& object() const { return *(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)); - } - } + void verifyObject() const; 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); diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h index 9b97b1486b443ae83537e5c5358523ed4489245f..5971b421e77d3c8b5de8dd6b15376df91941882b 100644 --- a/DDCore/include/DD4hep/LCDD.h +++ b/DDCore/include/DD4hep/LCDD.h @@ -206,12 +206,17 @@ namespace DD4hep { /// Extend the sensitive detector element with an arbitrary structure accessible by the type template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) { - return (IFACE*) addUserExtension(dynamic_cast<IFACE*>(c), typeid(IFACE)); + return (IFACE*) addUserExtension(dynamic_cast<IFACE*>(c), typeid(IFACE), _delete<IFACE>); + } + + /// Remove an existing extension object from the LCDD instance. If not destroyed, the instance is returned + template <class T> T* removeExtension(bool destroy=true) { + return (T*) removeUserExtension(typeid(T),destroy); } /// Access extension element by the type - template <class T> T* extension() const { - return (T*) userExtension(typeid(T)); + template <class T> T* extension(bool alert=true) const { + return (T*) userExtension(typeid(T),alert); } ///---Factory method------- @@ -220,10 +225,16 @@ namespace DD4hep { static void destroyInstance(); protected: + /// Templated destructor function + template <typename T> static void _delete(void* ptr) { + delete (T*) (ptr); + } /// Add an extension object to the detector element - virtual void* addUserExtension(void* ptr, const std::type_info& info) = 0; + virtual void* addUserExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) = 0; + /// Remove an existing extension object from the LCDD instance. If not destroyed, the instance is returned + virtual void* removeUserExtension(const std::type_info& info, bool destroy) = 0; /// Access an existing extension object from the detector element - virtual void* userExtension(const std::type_info& info) const = 0; + virtual void* userExtension(const std::type_info& info, bool alert=true) const = 0; }; diff --git a/DDCore/include/DD4hep/MatrixHelpers.h b/DDCore/include/DD4hep/MatrixHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..da55647405e1193d1136be77e543ef69d2725181 --- /dev/null +++ b/DDCore/include/DD4hep/MatrixHelpers.h @@ -0,0 +1,54 @@ +// $Id: Handle.cpp 575 2013-05-17 20:41:52Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4HEP_IMP_MATRIXHELPERS_H +#define DD4HEP_IMP_MATRIXHELPERS_H + +// Framework include files +#include "DD4hep/Objects.h" + +// Forward declarations +class TGeoTranslation; +class TGeoRotation; +class TGeoHMatrix; +class TGeoMatrix; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + typedef Position XYZAngles; + TGeoIdentity* identityTransform(); + TGeoTranslation* _translation(const Position& pos); + TGeoRotation* _rotationZYX(const RotationZYX& rot); + TGeoRotation* _rotation3D(const Rotation3D& rot); + TGeoHMatrix* _transform(const Transform3D& trans); + TGeoHMatrix* _transform(const Position& pos); + TGeoHMatrix* _transform(const RotationZYX& rot); + TGeoHMatrix* _transform(const Position& pos, const RotationZYX& rot); + + Transform3D _transform(const TGeoMatrix* matrix); + + void _decompose(const Transform3D& trafo, Position& pos, RotationZYX& rot); + void _decompose(const Transform3D& trafo, Position& pos, XYZAngles& rot); + void _decompose(const Transform3D& trafo, Translation3D& pos, RotationZYX& rot); + void _decompose(const Transform3D& trafo, Translation3D& pos, XYZAngles& rot); + + XYZAngles _XYZangles(const double* matrix); + XYZAngles _XYZangles(const TGeoMatrix* matrix); + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ + +#endif // DD4HEP_IMP_MATRIXHELPERS_H diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h index 518580a62ddf4f7247e293c057917164a2c59fc7..4837e79d196ab49afabe10365722db607c138ba2 100644 --- a/DDCore/include/DD4hep/Primitives.h +++ b/DDCore/include/DD4hep/Primitives.h @@ -39,6 +39,7 @@ namespace DD4hep { destroyObject(p); } }; + /// map Functor to delete objects from heap template <typename M> struct DestroyObjects { M& object; @@ -51,6 +52,9 @@ namespace DD4hep { void operator()(std::pair<typename M::key_type, typename M::mapped_type> p) const { DestroyObject<typename M::mapped_type>()(p.second); } + void operator()() const { + for_each(object.begin(),object.end(),(*this)); + } }; template <typename M> DestroyObjects<M> destroyObjects(M& m) { return DestroyObjects<M>(m); @@ -68,6 +72,9 @@ namespace DD4hep { void operator()(std::pair<typename M::key_type, typename M::mapped_type> p) const { DestroyObject<typename M::key_type>()(p.first); } + void operator()() const { + for_each(object.begin(),object.end(),(*this)); + } }; template <typename M> DestroyFirst<M> destroyFirst(M& m) { return DestroyFirst<M>(m); @@ -98,6 +105,9 @@ namespace DD4hep { void operator()(std::pair<typename M::key_type, typename M::mapped_type> p) const { ReleaseObject<typename M::mapped_type>()(p.second); } + void operator()() const { + for_each(object.begin(),object.end(),(*this)); + } }; template <typename M> ReleaseObjects<M> releaseObjects(M& m) { return ReleaseObjects<M>(m); diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h index 4b877a58a26f0f246e0d2d22653b8f911b911233..6f2dc2a9d5632cb7d6273b7ff8542640e272b07a 100644 --- a/DDCore/include/DD4hep/Shapes.h +++ b/DDCore/include/DD4hep/Shapes.h @@ -190,11 +190,11 @@ namespace DD4hep { /// Constructor to create a new ConeSegment object ConeSegment(double dz, double rmin1, double rmax1, double rmin2, double rmax2, double phi1 = 0.0, - double phi2 = 2.0 * M_PI*RAD_2_DEGREE); + double phi2 = 2.0 * M_PI); /// Set the cone segment dimensions ConeSegment& setDimensions(double dz, double rmin1, double rmax1, double rmin2, double rmax2, double phi1 = 0.0, - double phi2 = 2.0 * M_PI*RAD_2_DEGREE); + double phi2 = 2.0 * M_PI); }; /**@class Tube Shapes.h @@ -228,7 +228,7 @@ namespace DD4hep { /// Constructor to create a new anonymous tube object with attribute initialization Tube(double rmin, double rmax, double z) { - make("", rmin, rmax, z, 0, 2*M_PI*RAD_2_DEGREE); + make("", rmin, rmax, z, 0, 2*M_PI); } /// Constructor to create a new anonymous tube object with attribute initialization @@ -243,7 +243,7 @@ namespace DD4hep { /// Legacy: Constructor to create a new identifiable tube object with attribute initialization Tube(const std::string& name, double rmin, double rmax, double z) { - make(name, rmin, rmax, z, 0, 2*M_PI*RAD_2_DEGREE); + make(name, rmin, rmax, z, 0, 2*M_PI); } /// Legacy: Constructor to create a new identifiable tube object with attribute initialization @@ -258,7 +258,7 @@ namespace DD4hep { } /// Set the tube dimensions - Tube& setDimensions(double rmin, double rmax, double z, double startPhi=0.0, double deltaPhi=2*M_PI*RAD_2_DEGREE); + Tube& setDimensions(double rmin, double rmax, double z, double startPhi=0.0, double deltaPhi=2*M_PI); }; /**@class Cone Shapes.h @@ -359,10 +359,10 @@ namespace DD4hep { } /// Constructor to create a new anonymous object with attribute initialization template<typename R, typename RMIN, typename RMAX, typename PHI, typename DELTA_PHI> - Torus(R r, RMIN rmin, RMAX rmax, PHI phi = M_PI*RAD_2_DEGREE, DELTA_PHI delta_phi = 2. * M_PI*RAD_2_DEGREE) + Torus(R r, RMIN rmin, RMAX rmax, PHI phi=M_PI, DELTA_PHI delta_phi = 2.*M_PI) { make(_toDouble(r),_toDouble(rmin),_toDouble(rmax),_toDouble(phi),_toDouble(delta_phi)); } /// Constructor to create a new anonymous object with attribute initialization - Torus(double r, double rmin, double rmax, double phi = M_PI*RAD_2_DEGREE, double delta_phi = 2. * M_PI*RAD_2_DEGREE) + Torus(double r, double rmin, double rmax, double phi=M_PI, double delta_phi = 2.*M_PI) { make(r,rmin,rmax,phi,delta_phi); } /// Set the Torus dimensions Torus& setDimensions(double r, double rmin, double rmax, double phi, double delta_phi); @@ -379,8 +379,8 @@ namespace DD4hep { : Solid_type<TGeoSphere>(e) { } /// Constructor to create a new anonymous object with attribute initialization - Sphere(double rmin, double rmax, double theta = 0., double delta_theta = M_PI*RAD_2_DEGREE, double phi = 0.0, - double delta_phi = 2. * M_PI*RAD_2_DEGREE); + Sphere(double rmin, double rmax, double theta = 0., double delta_theta = M_PI, double phi = 0.0, + double delta_phi = 2. * M_PI); /// Set the Sphere dimensions Sphere& setDimensions(double rmin, double rmax, double theta, double delta_theta, double phi, double delta_phi); }; @@ -408,7 +408,7 @@ namespace DD4hep { */ struct PolyhedraRegular: public Solid_type<TGeoPgon> { protected: - /// Helper function to create holy hedron + /// Helper function to create the polyhedron void _create(const std::string& name, int nsides, double rmin, double rmax, double zpos, double zneg, double start, double delta); public: @@ -426,6 +426,24 @@ namespace DD4hep { PolyhedraRegular(int nsides, double phi_start, double rmin, double rmax, double zlen); }; + /**@class EightPointSolid Shapes.h + * + * @author M.Frank + * @version 1.0 + */ + struct EightPointSolid: public Solid_type<TGeoArb8> { + private: + /// Creator method + void make(double dz, const double* vtx); + public: + /// Constructor to be used when reading the already parsed object + template <typename Q> EightPointSolid(const Handle<Q>& e) + : Solid_type<TGeoArb8>(e) { + } + /// Constructor to create a new anonymous object with attribute initialization + EightPointSolid(double dz, const double* vertices) { make(dz,vertices); } + }; + /**@class BooleanSolid Shapes.h * * @author M.Frank diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index 11d043750fafefb9a676d3a3fe4227c13ab0fea2..65bfb23a4ed8a80b8ee7f024277d0d6e13ec58d4 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -222,9 +222,11 @@ namespace DD4hep { return *this; } + /// Check if placement is properly instrumented + Object* data() const; /// Place daughter volume. The position and rotation are the identity PlacedVolume placeVolume(const Volume& vol) const; - /// Place daughter volume according to generic Transform3D + /// Place daughter volume according to a generic Transform3D PlacedVolume placeVolume(const Volume& volume, const Transform3D& tr) const; /// Place un-rotated daughter volume at the given position. PlacedVolume placeVolume(const Volume& vol, const Position& pos) const; diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h index 62b6e29628132f12ea8950e948233862ffc6adc4..1ccb661b00c3756eca342a38961ee5e34aaf41ab 100644 --- a/DDCore/include/XML/UnicodeValues.h +++ b/DDCore/include/XML/UnicodeValues.h @@ -422,8 +422,9 @@ namespace DD4hep { UNICODE (x3); UNICODE (x4); UNICODE (xhalf); - UNICODE (xmin); UNICODE (xmax); + UNICODE (xmin); + UNICODE (xml); UNICODE (y); UNICODE (Y); diff --git a/DDCore/include/XML/XMLTags.h b/DDCore/include/XML/XMLTags.h index 3a2d5d0d447e9e85ef0831bb286b8b164128217c..b6e24665058d9496609814dbe455d4522849340e 100644 --- a/DDCore/include/XML/XMLTags.h +++ b/DDCore/include/XML/XMLTags.h @@ -9,7 +9,7 @@ #ifndef DD4hep_XML_TAGS_H #define DD4hep_XML_TAGS_H -#define DECLARE_UNICODE_TAG(x) namespace DD4hep { namespace XML { extern const Tag_t Unicode_##x (#x); }} +#define DECLARE_UNICODE_TAG(x) extern const Tag_t Unicode_##x (#x) #include "XML/XMLElements.h" #define UNICODE(x) extern const Tag_t Unicode_##x diff --git a/DDCore/src/Alignment.cpp b/DDCore/src/Alignment.cpp index 9002451402923eecdee8240c64c817f28915137f..70105d90f2342274544d7fdaa181e37989f8e674 100644 --- a/DDCore/src/Alignment.cpp +++ b/DDCore/src/Alignment.cpp @@ -10,23 +10,58 @@ // Framework include files #include "DD4hep/Alignment.h" #include "DD4hep/InstanceCount.h" -#include "MatrixHelpers.h" +#include "DD4hep/MatrixHelpers.h" +#include "DD4hep/Printout.h" // ROOT include files #include "TGeoMatrix.h" +#include "TGeoManager.h" + using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; + + namespace { - int _align(TGeoPhysicalNode* n, TGeoMatrix* transform, bool check, double overlap) { + int _align(const Alignment& a, TGeoHMatrix* transform, bool check, double overlap) { + TGeoPhysicalNode* n = a.ptr(); if ( n ) { + TGeoMatrix* mm = n->GetNode()->GetMatrix(); + transform->MultiplyLeft(mm); // orig * delta n->Align(transform, 0, check, overlap); + /* + printout(INFO,"Alignment","OLD matrix...."); + mm->Print(); + printout(INFO,"Alignment","Apply new relative matrix mother to daughter:"); + transform->Print(); + transform->MultiplyLeft(mm); // orig * delta + printout(INFO,"Alignment","With deltas...."); + transform->Print(); + n->Align(transform, 0, check, overlap); + printout(INFO,"Alignment","NEW matrix...."); + n->GetNode()->GetMatrix()->Print(); + */ + /* + */ + printout(INFO,"Alignment","NEW matrix...."); + n->GetNode()->GetMatrix()->Print(); + Position local, global = a.toGlobal(local); + cout << "Local:" << local << " Global: " << global + << " and back:" << a.globalToLocal(global) << endl; + return 1; } - throw runtime_error("DD4hep: Cannot align non existing physical node."); + throw runtime_error("DD4hep: Cannot align non existing physical node. [Invalid Handle]"); } + struct CheckHandle { + CheckHandle(const Alignment& a) { + if ( a.isValid() ) return; + throw runtime_error("DD4hep: Attempt to access invalid alignment object. [Invalid Handle]"); + } + ~CheckHandle() {} + }; } /// Default constructor @@ -39,7 +74,8 @@ Alignment::Alignment(const Alignment& c) : Handle<TGeoPhysicalNode>(c) { /// Initializing constructor to create a new object Alignment::Alignment(const string& path) { - //assign(new TGeoPhysicalNode(path.c_str()), path, "*"); + //cout << "Alignment: path=" << path << endl; + //m_element = gGeoManager->MakePhysicalNode(path.c_str()); m_element = new TGeoPhysicalNode(path.c_str()); } @@ -53,54 +89,89 @@ Alignment& Alignment::operator=(const Alignment& c) { /// Number of nodes in this branch int Alignment::numNodes() const { - if ( isValid() ) { - return ptr()->GetLevel(); - } - throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); + CheckHandle verify_handle(*this); + return ptr()->GetLevel(); } /// Access the placement of this node PlacedVolume Alignment::placement() const { - if ( isValid() ) { - return PlacedVolume(ptr()->GetNode(0)); - } - throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); + CheckHandle verify_handle(*this); + return PlacedVolume(ptr()->GetNode(0)); } /// Access the placement of a node in the chain of placements for this branch PlacedVolume Alignment::nodePlacement(int level) const { - if ( isValid() ) { - PlacedVolume pv = PlacedVolume(ptr()->GetNode(level)); - if ( pv.isValid() ) return pv; - throw runtime_error("DD4hep: The object chain of "+string(placement().name())+ - " is too short. [Invalid index]"); - } - throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); + CheckHandle verify_handle(*this); + PlacedVolume pv = PlacedVolume(ptr()->GetNode(level)); + if ( pv.isValid() ) return pv; + throw runtime_error("DD4hep: The object chain of "+string(placement().name())+ + " is too short. [Invalid index]"); } /// Access the placement of the mother of this node PlacedVolume Alignment::motherPlacement(int level_up) const { - if ( isValid() ) { - Int_t ind = ptr()->GetLevel()-level_up; - if ( ind >= 0 ) { - return PlacedVolume(ptr()->GetMother(level_up)); - } - throw runtime_error("DD4hep: This object "+string(placement().name())+" has not enough mothers. [Invalid index]"); + CheckHandle verify_handle(*this); + Int_t ind = ptr()->GetLevel()-level_up; + if ( ind >= 0 ) { + return PlacedVolume(ptr()->GetMother(level_up)); } - throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); + throw runtime_error("DD4hep: This object "+string(placement().name())+" has not enough mothers. [Invalid index]"); +} + +/// Access the currently applied alignment/placement matrix +Transform3D Alignment::toGlobal(int level) const { + CheckHandle verify_handle(*this); + return _transform(ptr()->GetMatrix(level)); +} + +/// Transform a point from local coordinates of a given level to global coordinates +Position Alignment::toGlobal(const Position& localPoint, int level) const { + CheckHandle verify_handle(*this); + Position result; + TGeoHMatrix* m = ptr()->GetMatrix(level); + m->LocalToMaster((Double_t*)&localPoint,(Double_t*)&result); + return result; +} + +/// Transform a point from local coordinates of a given level to global coordinates +Position Alignment::globalToLocal(const Position& globalPoint, int level) const { + CheckHandle verify_handle(*this); + Position result; + TGeoHMatrix* m = ptr()->GetMatrix(level); + m->MasterToLocal((Double_t*)&globalPoint,(Double_t*)&result); + return result; +} + +/// Access the currently applied alignment/placement matrix +Transform3D Alignment::toMother(int level) const { + CheckHandle verify_handle(*this); + return _transform(ptr()->GetNode(level)->GetMatrix()); } -/// Align the PhysicalNode (translation only) -int Alignment::align(const Position& pos, bool check, double overlap) { - return _align(ptr(),_translation(pos), check, overlap); +/// Access the currently applied alignment/placement matrix +Transform3D Alignment::nominal() const { + CheckHandle verify_handle(*this); + return _transform(ptr()->GetOriginalMatrix()); } -/// Align the PhysicalNode (rotation only) -int Alignment::align(const RotationZYX& rot, bool check, double overlap) { - return _align(ptr(),_rotationZYX(rot), check, overlap); +/// Access the currently applied correction matrix (delta) +Transform3D Alignment::delta() const { + // It may be useful at some point to cache some of these matrices.... + CheckHandle verify_handle(*this); + TGeoPhysicalNode* n = ptr(); + // T = T_0 * Delta -> Delta = T_0^-1 * T + TGeoHMatrix mat(n->GetOriginalMatrix()->Inverse()); + mat.Multiply(n->GetNode()->GetMatrix()); + return _transform(&mat); } -/// Align the PhysicalNode (translation + rotation) -int Alignment::align(const Position& pos, const RotationZYX& rot, bool check, double overlap) { - return _align(ptr(),_transform(pos,rot), check, overlap); +/// Access the inverse of the currently applied correction matrix (delta) (mother to daughter) +Transform3D Alignment::invDelta() const { + // It may be useful at some point to cache some of these matrices.... + CheckHandle verify_handle(*this); + TGeoPhysicalNode* n = ptr(); + // T = T_0 * Delta -> Delta^-1 = T^-1 * T_0 + TGeoHMatrix mat(n->GetNode()->GetMatrix()->Inverse()); + mat.Multiply(n->GetOriginalMatrix()); + return _transform(&mat); } diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp index 9f103ddd79056f7548ac6fed424abc6fecd8c9ca..f678d663f6a2f6ad5ded3aeb0348e06c01549f76 100644 --- a/DDCore/src/Detector.cpp +++ b/DDCore/src/Detector.cpp @@ -42,7 +42,7 @@ namespace { /// Default constructor DetElement::Object::Object() : TNamed(), magic(magic_word()), id(0), combineHits(0), // readout(), - alignment(), placement(), parent(), children(), worldTrafo(0), parentTrafo(0), referenceTrafo(0) { + alignment(), volume_alignments(), conditions(), placement(), parent(), children(), worldTrafo(0), parentTrafo(0), referenceTrafo(0) { InstanceCount::increment(this); } @@ -225,9 +225,7 @@ string DetElement::placementPath() const { if (isValid()) { Object& o = object<Object>(); if (o.placementPath.empty()) { - PlacementPath path; - DetectorTools::placementPath(*this, path); - o.placementPath = DetectorTools::nodePath(path); + o.placementPath = DetectorTools::placementPath(*this); } return o.placementPath; } diff --git a/DDCore/src/DetectorAlignment.cpp b/DDCore/src/DetectorAlignment.cpp deleted file mode 100644 index b7d58d2deea139ce58336d1a32262445b1b9d36d..0000000000000000000000000000000000000000 --- a/DDCore/src/DetectorAlignment.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// $Id: Readout.cpp 985 2014-01-30 13:50:10Z markus.frank@cern.ch $ -//==================================================================== -// AIDA Detector description implementation for LCD -//-------------------------------------------------------------------- -// -// Author : M.Frank -// -//==================================================================== -#include "DD4hep/DetectorAlignment.h" -#include "DD4hep/DetectorTools.h" -#include "DD4hep/InstanceCount.h" - -using namespace std; -using namespace DD4hep; -using namespace DD4hep::Geometry; - -typedef DetectorTools::ElementPath ElementPath; -typedef DetectorTools::PlacementPath PlacementPath; -typedef vector<pair<int,DetElement> > LevelElements; -namespace { - - Alignment& _alignment(DetectorAlignment& det) { - DetElement::Object& e = det._data(); - if ( !e.alignment.isValid() ) { - DetectorTools::PlacementPath nodes; - DetectorTools::placementPath(det,nodes); - string path = DetectorTools::nodePath(nodes); - //cout << "Align path:" << path << endl; - e.alignment = Alignment(path); - } - return e.alignment; - } - void _dumpParentElements(DetectorAlignment& det, LevelElements& elements) { - PlacementPath nodes; - ElementPath det_nodes; - DetectorTools::placementPath(det,nodes); - DetectorTools::elementPath(det,det_nodes); - /// cout << "Placement path:"; - int level = 0; - PlacementPath::const_reverse_iterator j=nodes.rbegin(); - ElementPath::const_reverse_iterator k=det_nodes.rbegin(); - for(; j!=nodes.rend(); ++j, ++level) { - //cout << "(" << level << ") " << (void*)((*j).ptr()) - // << " " << string((*j)->GetName()) << " "; - if ( ::strcmp((*j).ptr()->GetName(),(*k).placement().ptr()->GetName()) ) { - //cout << "[DE]"; - elements.push_back(make_pair(level,*k)); - ++k; - } - else { - //elements.push_back(make_pair(level,DetElement())); - } - //cout << " "; - } - //cout << endl; - } - void _patchParentElements(DetectorAlignment& det) { - DetElement::Object& obj = det._data(); - Alignment a = obj.alignment; - TGeoPhysicalNode* n = a.ptr(); - string path; - path.reserve(1024); - int level = -1; - - size_t path_len = ::strlen(a->GetName()); - for(int i = 0; i <= n->GetLevel(); ++i) { - path += "/"; - path += n->GetNode(i)->GetName(); - if ( path.length() == path_len && path == a->GetName() ) level = i; - } - //cout << "Physical node: " << path << endl; - PlacedVolume pv(n->GetNode(level)); - det.setPlacement(pv); -#if 0 - cout << "Updated placement of DetElement[" << level << "] " << det.name() - << " Placement: " << (void*)det.placement().ptr() - << " / " << n->GetNode(level) - << endl; - cout << "Placement path:"; - PlacementPath nodes; - DetectorTools::placementPath(det,nodes); - for(PlacementPath::const_reverse_iterator j=nodes.rbegin(); j!=nodes.rend(); ++j) - cout << (void*)((*j).ptr()) << " " << (*j)->GetName() << " "; - cout << endl; -#endif - cout << " Path:"; - for(int i = 0; i <= n->GetLevel(); ++i) - cout << (void*)(n->GetNode(i)) << " " << n->GetNode(i)->GetName() << " "; - cout << " / " << (void*)pv.ptr() << endl; - - TGeoNode* p = n->GetNode(n->GetLevel()-1); - TGeoNode* d = n->GetNode(n->GetLevel()); - if ( strcmp(d->GetName(),"MuonBarrel_layer9_slice1_0")==0 || - strcmp(d->GetName(),"MuonBarrel_layer9_slice9_8")==0) - { - TIter next(p->GetVolume()->GetNodes()); - // Now check next layer children - for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { - cout << p->GetName() << " / " << (void*)p << " ---> " << daughter->GetName() << " " << (void*)daughter << endl; - } - } - } -} - -/// Initializing constructor -DetectorAlignment::DetectorAlignment(DetElement e) - : DetElement(e) -{ -} - -/// Collect all placements from the detector element up to the world volume -void DetectorAlignment::collectNodes(vector<PlacedVolume>& nodes) { - DetectorTools::placementPath(*this,nodes); -} - -/// Align the PhysicalNode of the placement of the detector element (translation only) -int DetectorAlignment::align(const Position& pos, bool check, double overlap) { - int result = _alignment(*this).align(pos,check,overlap); - _patchParentElements(*this); - return result; -} - -/// Align the PhysicalNode of the placement of the detector element (rotation only) -int DetectorAlignment::align(const RotationZYX& rot, bool check, double overlap) { - int result = _alignment(*this).align(rot,check,overlap); - _patchParentElements(*this); - return result; -} - -/// Align the PhysicalNode of the placement of the detector element (translation + rotation) -int DetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool check, double overlap) { - int result = _alignment(*this).align(pos,rot,check,overlap); - _patchParentElements(*this); - return result; -} diff --git a/DDCore/src/DetectorTools.cpp b/DDCore/src/DetectorTools.cpp index d919d46b18759ec686dc36b773f840726f0c3829..03ef65845d559d0b6e295aff40687b782491463b 100644 --- a/DDCore/src/DetectorTools.cpp +++ b/DDCore/src/DetectorTools.cpp @@ -9,6 +9,7 @@ // Framework include files #include "DD4hep/DetectorTools.h" #include "DD4hep/Printout.h" +#include "DD4hep/LCDD.h" #include <stdexcept> #include <memory> @@ -19,22 +20,6 @@ using namespace std; using namespace DD4hep; using namespace DD4hep::Geometry; -/// Assemble the path of the PlacedVolume selection -std::string DetectorTools::nodePath(const PlacementPath& nodes) { - string s=""; - for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) - s += "/" + string((*i)->GetName()); - return s; -} - -/// Assemble the path of the PlacedVolume selection -std::string DetectorTools::elementPath(const ElementPath& nodes) { - string s = ""; - for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) - s += "/" + string((*i)->GetName()); - return s; -} - /// Collect detector elements to any parent detector element bool DetectorTools::findParent(DetElement parent, DetElement elt, vector<DetElement>& detectors) { detectors.clear(); @@ -118,13 +103,13 @@ static bool findChildByName(PlacedVolume parent, PlacedVolume child, DetectorToo } /// Collect detector elements to the top detector element (world) -void DetectorTools::elementPath(DetElement elt, vector<DetElement>& detectors) { +void DetectorTools::elementPath(DetElement elt, ElementPath& detectors) { for(DetElement par = elt; par.isValid(); par = par.parent()) detectors.push_back(par); } /// Collect detector elements to any parent detector element -void DetectorTools::elementPath(DetElement parent, DetElement elt, vector<DetElement>& detectors) { +void DetectorTools::elementPath(DetElement parent, DetElement elt, ElementPath& detectors) { if ( findParent(parent,elt,detectors) ) return; throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+elt.name()); @@ -140,8 +125,59 @@ void DetectorTools::elementPath(DetElement element, vector<PlacedVolume>& det_no } } +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::elementPath(const ElementPath& nodes) { + string s = ""; + for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) + s += "/" + string((*i)->GetName()); + return s; +} + +/// Assemble the path of a particular detector element +std::string DetectorTools::elementPath(DetElement element) { + ElementPath nodes; + elementPath(element,nodes); + return elementPath(nodes); +} + +/// Find DetElement as child of the top level volume by it's absolute path +DetElement DetectorTools::findElement(LCDD& lcdd, const std::string& path) { + return findElement(lcdd.world(),path); +} + +/// Find DetElement as child of a parent by it's relative or absolute path +DetElement DetectorTools::findElement(DetElement parent, const std::string& subpath) { + if ( parent.isValid() ) { + size_t idx = subpath.find('/',1); + if ( subpath[0] == '/' ) { + DetElement top = topElement(parent); + if ( idx == string::npos ) return top; + return findElement(top,subpath.substr(idx+1)); + } + if ( idx == string::npos ) + return parent.child(subpath); + string name = subpath.substr(0,idx); + DetElement node = parent.child(name); + if ( node.isValid() ) { + return findElement(node,subpath.substr(idx+1)); + } + throw runtime_error("DD4hep: DetElement "+parent.path()+" has no child named:"+name+" [No such child]"); + } + throw runtime_error("DD4hep: Cannot determine child with path "+subpath+" from invalid parent [invalid handle]"); +} + +/// Determine top level element (=world) for any element walking up the detector element tree +DetElement DetectorTools::topElement(DetElement child) { + if ( child.isValid() ) { + if ( child.parent().isValid() ) + return topElement(child.parent()); + return child; + } + throw runtime_error("DD4hep: DetElement cannot determine top parent (world) [invalid handle]"); +} + /// Collect detector elements placements to the top detector element (world) [no holes!] -void DetectorTools::placementPath(DetElement element, vector<PlacedVolume>& nodes) { +void DetectorTools::placementPath(DetElement element, PlacementPath& nodes) { PlacementPath det_nodes, all_nodes; DetectorTools::elementPath(element,det_nodes); for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { @@ -168,6 +204,21 @@ void DetectorTools::placementPath(DetElement parent, DetElement child, Placement if ( det_nodes.size()>0 ) nodes.push_back(det_nodes.back()); } +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::placementPath(DetElement element) { + PlacementPath path; + placementPath(element,path); + return placementPath(path); +} + +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::placementPath(const PlacementPath& nodes) { + string s=""; + for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) + s += "/" + string((*i)->GetName()); + return s; +} + /// Create cached matrix to transform to positions to an upper level Placement TGeoMatrix* DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse) { if (nodes.size() < 2) { @@ -185,3 +236,4 @@ TGeoMatrix* DetectorTools::placementTrafo(const PlacementPath& nodes, bool inver } return mat.release(); } + diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index fe851d12558a35cf567e7540ceb923b43ec94dc0..897c4c50bcadac0b8bc921c52c745253978ff300 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -177,10 +177,6 @@ namespace DD4hep { return this->m_element ? this->m_element->GetName() : ""; } - template <> const char* Handle<TObject>::name() const { - return ""; - } - template <> void Handle<TObject>::bad_assignment(const type_info& from, const type_info& to) { string msg = "Wrong assingment from "; msg += from.name(); @@ -334,13 +330,28 @@ namespace DD4hep { #include "TMap.h" #include "TColor.h" -#define INSTANTIATE(X) template struct DD4hep::Geometry::Handle<X> +#define INSTANTIATE(X) namespace DD4hep { namespace Geometry { \ + template <> void Handle<X>::verifyObject() const { \ + increment_object_validations(); \ + if (m_element && dynamic_cast<X*>((TObject*)m_element) == 0) { \ + bad_assignment(typeid(*m_element), typeid(X)); \ + } \ + }}} \ + template struct DD4hep::Geometry::Handle<X> + #define INSTANTIATE_UNNAMED(X) namespace DD4hep { namespace Geometry { \ template <> void Handle<X>::assign(X* n, const string&, const string&) { this->m_element = n;} \ template <> const char* Handle<X>::name() const { return ""; } \ + template <> void Handle<X>::verifyObject() const { \ + increment_object_validations(); \ + if (m_element && dynamic_cast<X*>((TObject*)m_element) == 0) { \ + bad_assignment(typeid(*m_element), typeid(X)); \ + } \ + } \ }} \ template struct DD4hep::Geometry::Handle<X> +INSTANTIATE_UNNAMED(TObject); INSTANTIATE(TNamed); #include "TGeoMedium.h" @@ -380,6 +391,7 @@ INSTANTIATE(TGeoNodeOffset); INSTANTIATE(TGeoVolume); INSTANTIATE(TGeoBBox); INSTANTIATE(TGeoCone); +INSTANTIATE(TGeoArb8); INSTANTIATE(TGeoConeSeg); INSTANTIATE(MyConeSeg); INSTANTIATE(TGeoParaboloid); diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 9b3bc261b35a22f9b9a7ae7d867a02eecc46e02e..242f845f72739ee3d9c0e5a06e677e19441f194a 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -8,6 +8,7 @@ //==================================================================== #include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" #include "DD4hep/GeoHandler.h" #include "DD4hep/InstanceCount.h" #include "LCDDImp.h" @@ -55,10 +56,8 @@ namespace { } }; - struct ExtensionEntry { - int id; - }; - typedef map<const type_info*, ExtensionEntry> ExtensionMap; + typedef pair<int,void(*)(void*)> ExtensionEntry; + typedef map<const type_info*, ExtensionEntry> ExtensionMap; static int s_extensionID = 0; ExtensionMap& lcdd_extensions() { static ExtensionMap s_map; @@ -109,7 +108,7 @@ LCDDImp::LCDDImp() InstanceCount::increment(this); m_properties = new Properties(); if (0 == gGeoManager) { - gGeoManager = new TGeoManager(); + gGeoManager = new TGeoManager("world", "LCDD Geometry"); } { m_manager = gGeoManager; @@ -159,32 +158,56 @@ LCDDImp::~LCDDImp() { InstanceCount::decrement(this); } -/// Add an extension object to the detector element -void* LCDDImp::addUserExtension(void* ptr, const std::type_info& info) { +/// Add an extension object to the LCDD instance +void* LCDDImp::addUserExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { Extensions::iterator j = m_extensions.find(&info); if (j == m_extensions.end()) { ExtensionMap& m = lcdd_extensions(); ExtensionMap::iterator i = m.find(&info); if (i == m.end()) { - ExtensionEntry entry; - entry.id = ++s_extensionID; + ExtensionEntry entry(++s_extensionID,destruct); m.insert(make_pair(&info, entry)); } - //cout << "Extension[" << name() << "]:" << ptr << " " << info.name() << endl; return m_extensions[&info] = ptr; } throw runtime_error("DD4hep: LCDD::addUserExtension: The object " - " already has an extension of type:" + string(info.name()) + "."); + " already has an extension of type:" + string(info.name()) + "."); } -/// Access an existing extension object from the detector element -void* LCDDImp::userExtension(const std::type_info& info) const { - Extensions::const_iterator j = m_extensions.find(&info); +/// Remove an existing extension object from the LCDD instance +void* LCDDImp::removeUserExtension(const std::type_info& info, bool destroy) { + Extensions::iterator j = m_extensions.find(&info); if (j != m_extensions.end()) { - return (*j).second; + void *ptr = (*j).second; + if ( destroy ) { + ExtensionMap& m = lcdd_extensions(); + ExtensionMap::iterator i = m.find(&info); + if (i != m.end()) { + ExtensionEntry& e = (*i).second; + (*e.second)((*j).second); + printout(INFO,"LCDD","Destructed LCDD Extension: %p of type %s",ptr,info.name()); + ptr = 0; + } + } + else { + printout(INFO,"LCDD","Detached LCDD Extension: %p of type %s",ptr,info.name()); + } + m_extensions.erase(j); + return ptr; } + throw runtime_error("DD4hep: LCDD::removeUserExtension: The object " + " of type " + string(info.name()) + " is not present."); +} + +/// Access an existing extension object from the LCDD instance +void* LCDDImp::userExtension(const std::type_info& info, bool alert) const { + Extensions::const_iterator j = m_extensions.find(&info); + if ( j != m_extensions.end() ) + return (*j).second; + else if ( !alert ) + return 0; throw runtime_error("DD4hep: LCDD::userExtension: The object " - " has no extension of type:" + string(info.name()) + "."); + " has no extension of type:" + string(info.name()) + "."); } Volume LCDDImp::pickMotherVolume(const DetElement&) const { // throw if not existing @@ -323,19 +346,6 @@ void LCDDImp::endDocument() { m_trackingVol.setVisAttributes(trackingVis); add(trackingVis); #endif - // Set the world volume to invisible. - VisAttr worldVis("WorldVis"); - worldVis.setAlpha(1.0); - worldVis.setVisible(false); - worldVis.setShowDaughters(true); - worldVis.setColor(1.0, 1.0, 1.0); - worldVis.setLineStyle(VisAttr::SOLID); - worldVis.setDrawingStyle(VisAttr::WIREFRAME); - m_worldVol.setVisAttributes(worldVis); -#ifndef DD4HEP_EMULATE_TGEOEXTENSIONS -#endif - add(worldVis); - /// Since we allow now for anonymous shapes, /// we will rename them to use the name of the volume they are assigned to mgr->CloseGeometry(); @@ -348,8 +358,8 @@ void LCDDImp::init() { if (!m_world.isValid()) { TGeoManager* mgr = m_manager; Box worldSolid("world_x", "world_y", "world_z"); - std::cout << " *********** created World volume with size : " << worldSolid->GetDX() << ", " << worldSolid->GetDY() << ", " - << worldSolid->GetDZ() << std::endl; + printout(INFO,"LCDD"," *********** created World volume with size : %7.0f %7.0f %7.0f", + worldSolid->GetDX(), worldSolid->GetDY(), worldSolid->GetDZ()); m_materialAir = material("Air"); m_materialVacuum = material("Vacuum"); @@ -357,6 +367,19 @@ void LCDDImp::init() { Volume world("world_volume", worldSolid, m_materialAir); m_world = TopDetElement("world"); m_worldVol = world; + // Set the world volume to invisible. + VisAttr worldVis("WorldVis"); + worldVis.setAlpha(1.0); + worldVis.setVisible(false); + worldVis.setShowDaughters(true); + worldVis.setColor(1.0, 1.0, 1.0); + worldVis.setLineStyle(VisAttr::SOLID); + worldVis.setDrawingStyle(VisAttr::WIREFRAME); + //m_worldVol.setVisAttributes(worldVis); + m_worldVol->SetVisibility(kFALSE); + m_worldVol->SetVisDaughters(kTRUE); + m_worldVol->SetVisContainers(kTRUE); + add(worldVis); #if 0 Tube trackingSolid(0.,"tracking_region_radius","2*tracking_region_zmax",2*M_PI); diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h index 1e43400df696d36ea06b46e046ca7b2740bd4b69..247a31213142c090748e68337b6d73f2724ed443 100644 --- a/DDCore/src/LCDDImp.h +++ b/DDCore/src/LCDDImp.h @@ -130,10 +130,12 @@ namespace DD4hep { virtual void init(); virtual void endDocument(); - /// Add an extension object to the detector element - virtual void* addUserExtension(void* ptr, const std::type_info& info); - /// Access an existing extension object from the detector element - virtual void* userExtension(const std::type_info& info) const; + /// Add an extension object to the LCDD instance + virtual void* addUserExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)); + /// Remove an existing extension object from the LCDD instance. If not destroyed, the instance is returned + virtual void* removeUserExtension(const std::type_info& info, bool destroy=true); + /// Access an existing extension object from the LCDD instance + virtual void* userExtension(const std::type_info& info, bool alert=true) 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; diff --git a/DDCore/src/MatrixHelpers.cpp b/DDCore/src/MatrixHelpers.cpp index 31f3e54d92d2f32481359d3898f2175dcd38dec6..e803c891f4d5d851181313e5d6a2ebf01c6728c9 100644 --- a/DDCore/src/MatrixHelpers.cpp +++ b/DDCore/src/MatrixHelpers.cpp @@ -8,7 +8,7 @@ //==================================================================== // Framework include files -#include "MatrixHelpers.h" +#include "DD4hep/MatrixHelpers.h" // ROOT includes #include "TGeoMatrix.h" @@ -30,15 +30,9 @@ TGeoRotation* DD4hep::Geometry::_rotation3D(const Rotation3D& rot3D) { return new TGeoRotation("", rot.Phi() * RAD_2_DEGREE, rot.Theta() * RAD_2_DEGREE, rot.Psi() * RAD_2_DEGREE); } -TGeoHMatrix* DD4hep::Geometry::_transform(const Transform3D& trans) { +TGeoHMatrix* DD4hep::Geometry::_transform(const Position& pos) { double t[3]; - RotationZYX rot; - Position pos; - trans.GetDecomposition(rot, pos); TGeoHMatrix *tr = new TGeoHMatrix(); - tr->RotateZ(rot.Phi() * RAD_2_DEGREE); - tr->RotateY(rot.Theta() * RAD_2_DEGREE); - tr->RotateX(rot.Psi() * RAD_2_DEGREE); pos.GetCoordinates(t); tr->SetDx(t[0]); tr->SetDy(t[1]); @@ -46,15 +40,77 @@ TGeoHMatrix* DD4hep::Geometry::_transform(const Transform3D& trans) { return tr; } -TGeoHMatrix* DD4hep::Geometry::_transform(const Position& pos, const RotationZYX& rot) { - double t[3]; +TGeoHMatrix* DD4hep::Geometry::_transform(const RotationZYX& rot) { TGeoHMatrix *tr = new TGeoHMatrix(); tr->RotateZ(rot.Phi() * RAD_2_DEGREE); tr->RotateY(rot.Theta() * RAD_2_DEGREE); tr->RotateX(rot.Psi() * RAD_2_DEGREE); + return tr; +} + +TGeoHMatrix* DD4hep::Geometry::_transform(const Transform3D& trans) { + Position pos; + RotationZYX rot; + trans.GetDecomposition(rot, pos); + return _transform(pos,rot); +} + +TGeoHMatrix* DD4hep::Geometry::_transform(const Position& pos, const RotationZYX& rot) { + double t[3]; + TGeoHMatrix *tr = _transform(rot); pos.GetCoordinates(t); tr->SetDx(t[0]); tr->SetDy(t[1]); tr->SetDz(t[2]); return tr; } + +DD4hep::Geometry::Transform3D DD4hep::Geometry::_transform(const TGeoMatrix* matrix) { + const Double_t* t = matrix->GetTranslation(); + if ( matrix->IsRotation() ) { + const Double_t* r = matrix->GetRotationMatrix(); + return Transform3D(r[0],r[1],r[2],t[0]*MM_2_CM, + r[3],r[4],r[5],t[1]*MM_2_CM, + r[6],r[7],r[8],t[2]*MM_2_CM); +#if 0 + return Transform3D(r[0],r[3],r[6],t[0]*MM_2_CM, + r[1],r[4],r[7],t[1]*MM_2_CM, + r[2],r[5],r[8],t[2]*MM_2_CM); +#endif + } + return Transform3D(0e0,0e0,0e0,t[0]*MM_2_CM, + 0e0,0e0,0e0,t[1]*MM_2_CM, + 0e0,0e0,0e0,t[2]*MM_2_CM); +} + +DD4hep::Geometry::XYZAngles DD4hep::Geometry::_XYZangles(const TGeoMatrix* m) { + return m->IsRotation() ? _XYZangles(m->GetRotationMatrix()) : XYZAngles(0,0,0); +} + +DD4hep::Geometry::XYZAngles DD4hep::Geometry::_XYZangles(const double* r) { + Double_t cosb = sqrt(r[0]*r[0] + r[1]*r[1]); + if (cosb > 0.00001) { + return XYZAngles(atan2(r[5], r[8]), atan2(-r[2], cosb), atan2(r[1], r[0])); + } + return XYZAngles(atan2(-r[7], r[4]),atan2(-r[2], cosb),0); +} + +void DD4hep::Geometry::_decompose(const Transform3D& trafo, Translation3D& pos, RotationZYX& rot) { + trafo.GetDecomposition(rot,pos); +} + +void DD4hep::Geometry::_decompose(const Transform3D& trafo, Translation3D& pos, XYZAngles& rot) { + EulerAngles r; + trafo.GetDecomposition(r,pos); + rot.SetXYZ(r.Psi(),r.Theta(),r.Phi()); +} + +void DD4hep::Geometry::_decompose(const Transform3D& trafo, Position& pos, RotationZYX& rot) { + trafo.GetDecomposition(rot,pos); +} + +void DD4hep::Geometry::_decompose(const Transform3D& trafo, Position& pos, XYZAngles& rot) { + EulerAngles r; + trafo.GetDecomposition(r,pos); + rot.SetXYZ(r.Psi(),r.Theta(),r.Phi()); +} diff --git a/DDCore/src/MatrixHelpers.h b/DDCore/src/MatrixHelpers.h deleted file mode 100644 index 26c54b6c1449e92164d879ebc873477453dd85db..0000000000000000000000000000000000000000 --- a/DDCore/src/MatrixHelpers.h +++ /dev/null @@ -1,41 +0,0 @@ -// $Id: Handle.cpp 575 2013-05-17 20:41:52Z markus.frank $ -//==================================================================== -// AIDA Detector description implementation for LCD -//-------------------------------------------------------------------- -// -// Author : M.Frank -// -//==================================================================== - -#ifndef DD4HEP_IMP_MATRIXHELPERS_H -#define DD4HEP_IMP_MATRIXHELPERS_H - -// Framework include files -#include "DD4hep/Objects.h" - -// Forward declarations -class TGeoTranslation; -class TGeoRotation; -class TGeoHMatrix; - -/* - * DD4hep namespace declaration - */ -namespace DD4hep { - - /* - * Geometry namespace declaration - */ - namespace Geometry { - - TGeoIdentity* identityTransform(); - TGeoTranslation* _translation(const Position& pos); - TGeoRotation* _rotationZYX(const RotationZYX& rot); - TGeoRotation* _rotation3D(const Rotation3D& rot); - TGeoHMatrix* _transform(const Transform3D& trans); - TGeoHMatrix* _transform(const Position& pos, const RotationZYX& rot); - - } /* End namespace Geometry */ -} /* End namespace DD4hep */ - -#endif // DD4HEP_IMP_MATRIXHELPERS_H diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index 1f658f1f586500fb4f64ff5844e69c97b9666e07..1a78d608240dace12a6fe55a2c74d0f0afb4a5fb 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -9,7 +9,7 @@ #define _USE_MATH_DEFINES #include "DD4hep/LCDD.h" -#include "MatrixHelpers.h" +#include "DD4hep/MatrixHelpers.h" // C/C++ include files #include <stdexcept> @@ -125,20 +125,20 @@ void Polycone::addZPlanes(const vector<double>& rmin, const vector<double>& rmax /// Constructor to be used when creating a new cone segment object ConeSegment::ConeSegment(double dz, double rmin1, double rmax1, double rmin2, double rmax2, double phi1, double phi2) { _assign( - new TGeoConeSeg(dz, rmin1, rmax1, rmin2, rmax2, phi1,phi2), "", "cone_segment", true); + new TGeoConeSeg(dz, rmin1, rmax1, rmin2, rmax2, phi1*RAD_2_DEGREE, phi2*RAD_2_DEGREE), "", "cone_segment", true); } /// Set the cone segment dimensions ConeSegment& ConeSegment::setDimensions(double dz, double rmin1, double rmax1, double rmin2, double rmax2, double phi1, double phi2) { - double params[] = { dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2 }; + double params[] = { dz, rmin1, rmax1, rmin2, rmax2, phi1*RAD_2_DEGREE, phi2*RAD_2_DEGREE }; _setDimensions(params); return *this; } /// Constructor to be used when creating a new object with attribute initialization void Tube::make(const string& name, double rmin, double rmax, double z, double startPhi, double deltaPhi) { - //_assign(new TGeoTubeSeg(rmin,rmax,z,startPhi,deltaPhi),name,"tube",true); + //_assign(new TGeoTubeSeg(rmin,rmax,z,startPhi*RAD_2_DEGREE,deltaPhi*RAD_2_DEGREE),name,"tube",true); _assign(new MyConeSeg(), name, "tube", true); setDimensions(rmin, rmax, z, startPhi, deltaPhi); } @@ -146,7 +146,7 @@ void Tube::make(const string& name, double rmin, double rmax, double z, double s /// Set the tube dimensions Tube& Tube::setDimensions(double rmin, double rmax, double z, double startPhi, double deltaPhi) { //double params[] = {rmin,rmax,z,startPhi,deltaPhi}; - double params[] = { z, rmin, rmax, rmin, rmax, startPhi,deltaPhi }; + double params[] = { z, rmin, rmax, rmin, rmax, startPhi*RAD_2_DEGREE,deltaPhi*RAD_2_DEGREE }; _setDimensions(params); return *this; } @@ -188,25 +188,25 @@ Paraboloid& Paraboloid::setDimensions(double r_low, double r_high, double delta_ /// Constructor to be used when creating a new object with attribute initialization Sphere::Sphere(double rmin, double rmax, double theta, double delta_theta, double phi, double delta_phi) { - _assign(new TGeoSphere(rmin, rmax, theta, delta_theta, phi, delta_phi), "", "sphere", true); + _assign(new TGeoSphere(rmin, rmax, theta, delta_theta*RAD_2_DEGREE, phi*RAD_2_DEGREE, delta_phi*RAD_2_DEGREE), "", "sphere", true); } /// Set the Sphere dimensions Sphere& Sphere::setDimensions(double rmin, double rmax, double theta, double delta_theta, double phi, double delta_phi) { - double params[] = { rmin, rmax, theta, delta_theta, phi, - delta_phi }; + double params[] = { rmin, rmax, theta, delta_theta*RAD_2_DEGREE, phi*RAD_2_DEGREE, + delta_phi*RAD_2_DEGREE }; _setDimensions(params); return *this; } /// Constructor to be used when creating a new object with attribute initialization void Torus::make(double r, double rmin, double rmax, double phi, double delta_phi) { - _assign(new TGeoTorus(r, rmin, rmax, phi, delta_phi), "", "torus", true); + _assign(new TGeoTorus(r, rmin, rmax, phi*RAD_2_DEGREE, delta_phi*RAD_2_DEGREE), "", "torus", true); } /// Set the Torus dimensions Torus& Torus::setDimensions(double r, double rmin, double rmax, double phi, double delta_phi) { - double params[] = { r, rmin, rmax, phi, delta_phi }; + double params[] = { r, rmin, rmax, phi*RAD_2_DEGREE, delta_phi*RAD_2_DEGREE }; _setDimensions(params); return *this; } @@ -264,6 +264,11 @@ PolyhedraRegular::PolyhedraRegular(int nsides, double rmin, double rmax, double _create("", nsides, rmin, rmax, zplanes[0], zplanes[1], 0, 2*M_PI*RAD_2_DEGREE); } +/// Creator method +void EightPointSolid::make(double dz, const double* vtx) { + _assign(new TGeoArb8(dz, (double*)vtx), "", "Arb8", true); +} + /// Constructor to be used when creating a new object. Position is identity, Rotation is the identity rotation SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2) { TGeoSubtraction* sub = new TGeoSubtraction(shape1, shape2, identityTransform(), identityTransform()); diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index 41d06b169e9001a87a4f713b3988cb863c17ae2f..8bad3afe6808532ab4da3cb1536995a91c04c16b 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -8,8 +8,9 @@ //==================================================================== #include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" #include "DD4hep/InstanceCount.h" -#include "MatrixHelpers.h" +#include "DD4hep/MatrixHelpers.h" // ROOT include files #include "TColor.h" @@ -483,6 +484,12 @@ Volume::Volume(const string& name, const Solid& s, const Material& m) { m_element = _createTGeoVolume(name,s.ptr(),m.ptr()); } +/// Check if placement is properly instrumented +Volume::Object* Volume::data() const { + Volume::Object* o = _userExtension(*this); + return o; +} + static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix* transform) { TGeoVolume* parent = par; TObjArray* a = parent->GetNodes(); @@ -556,35 +563,69 @@ Material Volume::material() const { return Ref_t(m_element->GetMedium()); } +#include "TROOT.h" + /// Set Visualization attributes to the volume const Volume& Volume::setVisAttributes(const VisAttr& attr) const { if (attr.isValid()) { VisAttr::Object* vis = attr.data<VisAttr::Object>(); - Color_t bright = TColor::GetColorBright(vis->color); - Color_t dark = TColor::GetColorDark(vis->color); + Color_t bright = vis->color;//kBlue;//TColor::GetColorBright(vis->color); + Color_t dark = vis->color;//kRed;//TColor::GetColorDark(vis->color); + TColor* c = (TColor*)vis->col;//gROOT->GetColor(dark); int draw_style = vis->drawingStyle; int line_style = vis->lineStyle; + + m_element->SetVisibility(vis->visible ? kTRUE : kFALSE); + m_element->SetVisContainers(kTRUE); + //m_element->SetAttBit(TGeoAtt::kVisContainers, kTRUE); + m_element->SetVisDaughters(vis->showDaughters ? kTRUE : kFALSE); + printout(DEBUG,"setVisAttributes", + "Set color %3d [%02X,%02X,%02X] DrawingStyle:%9s LineStyle:%6s for volume %s", + int(vis->color), + c ? int(255*c->GetRed()) : 0xFF, + c ? int(255*c->GetGreen()) : 0xFF, + c ? int(255*c->GetBlue()) : 0xFF, + draw_style == VisAttr::SOLID ? "Solid" : "Wireframe", + line_style == VisAttr::SOLID ? "Solid" : "Dashed", + name() + ); m_element->SetLineColor(dark); if (draw_style == VisAttr::SOLID) { + m_element->SetLineColor(bright); m_element->SetFillColor(bright); m_element->SetFillStyle(1001); // Root: solid } else { - //m_element->SetStyle(); + printout(DEBUG,"setVisAttributes","Set to wireframe vis:%s",name()); + m_element->SetLineColor(kBlack); m_element->SetFillColor(0); - m_element->SetFillStyle(0); // Root: hollow + m_element->SetFillStyle(0); // Root: hollow } + if (line_style == VisAttr::SOLID) // Root line style: 1=solid, 2=dash, 3=dot, 4=dash-dot. + m_element->SetLineStyle(1); + else if (line_style == VisAttr::DASHED) + m_element->SetLineStyle(2); + else + m_element->SetLineStyle(line_style); + + m_element->SetLineWidth(10); + + /* + m_element->SetVisibility(kTRUE); + m_element->SetAttBit(TGeoAtt::kVisContainers, kTRUE); + m_element->SetVisDaughters(kTRUE); + printout(INFO,"setVisAttributes","Set Line color for volume %s",name()); + m_element->SetLineColor(bright); + m_element->SetFillColor(bright); + m_element->SetFillStyle(1001); // Root: solid if (line_style == VisAttr::SOLID) m_element->SetFillStyle(1); else if (line_style == VisAttr::DASHED) m_element->SetFillStyle(2); else m_element->SetFillStyle(line_style); - m_element->SetLineWidth(10); - m_element->SetVisibility(vis->visible ? kTRUE : kFALSE); - m_element->SetAttBit(TGeoAtt::kVisContainers, kTRUE); - m_element->SetVisDaughters(vis->showDaughters ? kTRUE : kFALSE); + */ } Volume::Object* o = _userExtension(*this); if ( o ) o->vis = attr; diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp index a9e3e5fc63d556f014a741c78a59380b05360be6..843ba706e67237139594ebf3df6bc086932b1cd5 100644 --- a/DDCore/src/XML/DocumentHandler.cpp +++ b/DDCore/src/XML/DocumentHandler.cpp @@ -133,11 +133,17 @@ DocumentHandler::DocumentHandler() DocumentHandler::~DocumentHandler() { } -Document DocumentHandler::load(Handle_t base, const XMLCh* fname) const { +/// Build qualified URI from base element and additional path +string DocumentHandler::uri(Handle_t base, const XMLCh* fname) { xercesc::DOMElement* e = (xercesc::DOMElement*) base.ptr(); xercesc::XMLURL base_url(e->getBaseURI()); xercesc::XMLURL ref_url(base_url, fname); - return load(_toString(ref_url.getURLText())); + return _toString(ref_url.getURLText()); +} + +Document DocumentHandler::load(Handle_t base, const XMLCh* fname) const { + string path = uri(base,fname); + return load(path); } Document DocumentHandler::load(const string& fname) const { diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 732b2c924624322b1686fd6b01470765c83ff556..77e14112d2a0deb4881cc81afad60e26021a28ce 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -36,6 +36,7 @@ namespace DD4hep { struct Includes; struct GdmlFile; struct Property; + struct XMLFile; struct AlignmentFile; struct DetElementInclude {}; } @@ -52,6 +53,7 @@ namespace DD4hep { template <> void Converter<SensitiveDetector>::operator()(xml_h element) const; template <> void Converter<DetElement>::operator()(xml_h element) const; template <> void Converter<GdmlFile>::operator()(xml_h element) const; + template <> void Converter<XMLFile>::operator()(xml_h element) const; template <> void Converter<AlignmentFile>::operator()(xml_h element) const; template <> void Converter<Header>::operator()(xml_h element) const; template <> void Converter<DetElementInclude>::operator()(xml_h element) const; @@ -712,10 +714,16 @@ template <> void Converter<GdmlFile>::operator()(xml_h element) const { xml_coll_t(materials, _U(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<XMLFile>::operator()(xml_h element) const { + this->lcdd.fromXML(element.attr<string>(_U(ref))); +} + /// Read alignment entries from a seperate file in one of the include sections of the geometry template <> void Converter<AlignmentFile>::operator()(xml_h element) const { xml_h alignments = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root(); xml_coll_t(alignments, _U(alignment)).for_each(Converter < AlignmentEntry > (this->lcdd)); + xml_coll_t(alignments, _U(include)).for_each(Converter < XMLFile > (this->lcdd)); } /// Read material entries from a seperate file in one of the include sections of the geometry @@ -759,6 +767,7 @@ template <> void Converter<Compact>::operator()(xml_h element) const { printout(DEBUG, "Compact", "++ Converting detector structures..."); xml_coll_t(compact, _U(detectors)).for_each(_U(detector), Converter < DetElement > (lcdd)); xml_coll_t(compact, _U(includes)).for_each(_U(alignment), Converter < AlignmentFile > (lcdd)); + xml_coll_t(compact, _U(includes)).for_each(_U(xml), Converter < XMLFile > (lcdd)); xml_coll_t(compact, _U(alignments)).for_each(_U(alignment), Converter < AlignmentEntry > (lcdd)); xml_coll_t(compact, _U(fields)).for_each(_U(field), Converter < CartesianField > (lcdd)); xml_coll_t(compact, _U(sensitive_detectors)).for_each(_U(sd), Converter < SensitiveDetector > (lcdd)); diff --git a/DDCore/src/plugins/GeometryWalk.cpp b/DDCore/src/plugins/GeometryWalk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..904364f56544770042397b51d855f455eba68fd6 --- /dev/null +++ b/DDCore/src/plugins/GeometryWalk.cpp @@ -0,0 +1,177 @@ +// $Id: TubeSegment_geo.cpp 633 2013-06-21 13:50:50Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Factories.h" +#include "DD4hep/IDDescriptor.h" +#include "DD4hep/VolumeManager.h" +#include "DD4hep/DetectorTools.h" +//#include "DD4hep/DetectorAlignment.h" + +// C/C++ include files +#include <stdexcept> +#include <algorithm> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +typedef DetectorTools::ElementPath ElementPath; +typedef DetectorTools::PlacementPath PlacementPath; + +namespace { + /** @class GeometryWalk + * + * Test the volume manager by scanning the sensitive + * volumes of one or several subdetectors. + * + * @author M.Frank + * @version 1.0 + */ + struct GeometryWalk { + typedef vector<PlacedVolume::VolID> VolIDs; + /// Helper to scan volume ids + struct FND { + const string& test; + FND(const string& c) : test(c) {} + bool operator()(const VolIDs::value_type& c) const { return c.first == test; } + }; + VolumeManager m_mgr; + DetElement m_det; + + /// Initializing constructor + GeometryWalk(LCDD& lcdd, DetElement sdet); + /// Default destructor + virtual ~GeometryWalk() {} + /// Walk through tree of detector elements + void walk(DetElement de, VolIDs ids) const; + /// Printout volume information + void print(DetElement e, PlacedVolume pv, const VolIDs& child_ids) const; + /// Action routine to execute the test + static long run(LCDD& lcdd,int argc,char** argv); + void dumpPathes(DetElement e, PlacedVolume pv) const; + }; +} + +typedef DetElement::Children _C; + +/// Initializing constructor +GeometryWalk::GeometryWalk(LCDD& lcdd, DetElement sdet) : m_det(sdet) { + m_mgr = lcdd.volumeManager(); + if ( !m_det.isValid() ) { + stringstream err; + err << "The subdetector " << m_det.name() << " is not known to the geometry."; + printout(INFO,"GeometryWalk",err.str().c_str()); + throw runtime_error(err.str()); + } + walk(m_det,VolIDs()); +} +#include "TClass.h" +#include "TGeoManager.h" +void GeometryWalk::dumpPathes(DetElement e, PlacedVolume pv) const { + stringstream log; + PlacementPath det_nodes, all_nodes; + ElementPath det_elts; + DetectorTools::elementPath(e,det_elts); + DetectorTools::elementPath(e,det_nodes); + DetectorTools::placementPath(e,all_nodes); + string elt_path = DetectorTools::elementPath(det_elts); + string node_path = DetectorTools::placementPath(all_nodes); + string det_path = DetectorTools::placementPath(det_nodes); + log << "Lookup " << left << setw(32) << pv.name() << " Detector[" << det_elts.size() << "]: " << elt_path; + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " << left << setw(32) << pv.name() << " Elements[" << det_nodes.size() << "]: " << det_path; + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " << left << setw(32) << " " << " Places[" << all_nodes.size() << "]: " << node_path; + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " << left << setw(32) << " " << " Matrices[" << all_nodes.size() << "]: "; + for(PlacementPath::const_iterator i=all_nodes.begin(); i!=all_nodes.end(); ++i) { + log << (void*)((*i)->GetMatrix()) << " "; + if ( i+1 == all_nodes.end() ) log << "( -> " << (*i)->GetName() << ")"; + } + printout(INFO,m_det.name(),log.str()); +} + +/// Printout volume information +void GeometryWalk::print(DetElement e, PlacedVolume pv, const VolIDs& /* child_ids */) const { + stringstream log; + PlacementPath det_nodes, all_nodes; + DetectorTools::elementPath(e,det_nodes); + DetectorTools::placementPath(e,all_nodes); + string node_path = DetectorTools::placementPath(all_nodes); + string det_path = DetectorTools::placementPath(det_nodes); + dumpPathes(e, pv); + if ( det_path == "/world_volume_1" || + det_path == "/world_volume_1/MuonBarrel_envelope_13" || + det_path == "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7" || + det_path == "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7/MuonBarrel_layer8_7" +) + { + PlacedVolume pv = e.placement(); + TIter next(pv->GetVolume()->GetNodes()); + // Now check next layer children + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + cout << pv->GetName() << " --> " << daughter->GetName() << endl; + } + } + //cout << node_path << endl; + const char* path = "/world_volume_1/MuonBarrel_envelope_13/MuonBarrel_stave_7/MuonBarrel_inner_0/MuonBarrel_layer9_8"; + size_t path_len = strlen(path); + if ( strncmp(node_path.c_str(),path,path_len) == 0 ) { + gGeoManager->cd(node_path.c_str()); + //dumpPathes(e, pv); + //DetectorAlignment alignment(e); + //alignment.align(Position(0,0,1)); + //dumpPathes(e,pv); + } +} + +/// Walk through tree of volume placements +void GeometryWalk::walk(DetElement e, VolIDs ids) const { + const _C& children = e.children(); + PlacedVolume pv = e.placement(); + VolIDs child_ids(ids); + print(e,pv,ids); + child_ids.insert(child_ids.end(),pv.volIDs().begin(),pv.volIDs().end()); + for (_C::const_iterator i=children.begin(); i!=children.end(); ++i) { + walk((*i).second,child_ids); + } +} + +/// Action routine to execute the test +long GeometryWalk::run(LCDD& lcdd,int argc,char** argv) { + cout << "++ Processing plugin....GeometryWalker.." << endl; + for(int i=1; i<argc;++i) { + string name = argv[i]+1; + if ( name == "all" || name == "All" || name == "ALL" ) { + const _C& children = lcdd.world().children(); + for (_C::const_iterator i=children.begin(); i!=children.end(); ++i) { + DetElement sdet = (*i).second; + cout << "++ Processing subdetector: " << sdet.name() << endl; + GeometryWalk test(lcdd,sdet); + } + return 1; + } + cout << "++ Processing subdetector: " << name << endl; + GeometryWalk test(lcdd,lcdd.detector(name)); + } + return 1; +} + +namespace DD4hep { + namespace Geometry { + using ::GeometryWalk; + } +} +DECLARE_APPLY(GeometryWalker,GeometryWalk::run) diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp index f1054fa3e1a2a1c94322a55f1a2933922231b7db..09a92a4234fb04904b5245d11a43efc1ad9aa939 100644 --- a/DDCore/src/plugins/LCDDConverter.cpp +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -50,7 +50,7 @@ using namespace DD4hep; using namespace std; namespace { typedef Position XYZRotation; -#if 0 + XYZRotation getXYZangles(const Double_t* r) { Double_t cosb = sqrt(r[0]*r[0] + r[1]*r[1]); if (cosb > 0.00001) { @@ -58,7 +58,8 @@ namespace { } return XYZRotation(atan2(-r[7], r[4]),atan2(-r[2], cosb),0); } -#endif + +#if 0 XYZRotation getXYZangles(const Double_t* rotationMatrix) { Double_t a, b, c; Double_t rad = 1.0; // RAD by default! 180.0 / TMath::ACos(-1.0); @@ -74,8 +75,21 @@ namespace { b = TMath::ATan2(-r[2], cosb) * rad; c = 0; } + XYZRotation rr(a, b, c); + cout << " X:" << a << " " << rr.X() << " Y:" << b << " " << rr.Y() << " Z:" << c << " " << rr.Z() + << " lx:" << r[0] << " ly:" << r[4] << " lz:" << r[8] << endl; return XYZRotation(a, b, c); } +#endif + + bool is_volume(const TGeoVolume* volume) { + Volume v = Ref_t(volume); + return v.data() != 0; + } + bool is_placement(const TGeoNode* node) { + PlacedVolume v = Ref_t(node); + return v.data() != 0; + } } void LCDDConverter::GeometryInfo::check(const string& name, const TNamed* n, map<string, const TNamed*>& m) const { @@ -623,7 +637,7 @@ xml_h LCDDConverter::handleVolume(const string& name, const TGeoVolume* volume) handlePlacement(node->GetName(), node); } } - if (geo.doc_header && dynamic_cast<const Volume::Object*>(volume)) { + if (geo.doc_header && is_volume(volume)) { Region reg = _v.region(); LimitSet lim = _v.limitSet(); VisAttr vis = _v.visAttributes(); @@ -656,7 +670,7 @@ xml_h LCDDConverter::handleVolumeVis(const string& /* name */, const TGeoVolume* if (!vol) { const TGeoVolume* v = volume; Volume _v = Ref_t(v); - if (dynamic_cast<const Volume::Object*>(volume)) { + if (is_volume(volume)) { VisAttr vis = _v.visAttributes(); if (vis.isValid()) { geo.doc_structure.append(vol = xml_elt_t(geo.doc, _U(volume))); @@ -673,7 +687,7 @@ xml_h LCDDConverter::handleVolumeVis(const string& /* name */, const TGeoVolume* /// Dump logical volume in GDML format to output stream void LCDDConverter::collectVolume(const string& /* name */, const TGeoVolume* volume) const { Volume v = Ref_t(volume); - if (dynamic_cast<const Volume::Object*>(volume)) { + if ( is_volume(volume) ) { GeometryInfo& geo = data(); Region reg = v.region(); LimitSet lim = v.limitSet(); @@ -695,7 +709,7 @@ void LCDDConverter::checkVolumes(const string& name, const TGeoVolume* volume) c if (i != m_checkNames.end()) { Volume v = Ref_t(volume); cout << "checkVolumes: Volume " << name << " "; - if (dynamic_cast<const Volume::Object*>(volume)) { + if (is_volume(volume)) { SensitiveDetector s = v.sensitiveDetector(); VisAttr vis = v.visAttributes(); if (s.isValid()) { @@ -731,12 +745,14 @@ xml_h LCDDConverter::handlePlacement(const string& name, const TGeoNode* node) c ::snprintf(text, sizeof(text), "_%p_pos", (void*)node); xml_ref_t pos = handlePosition(name + text, m); ::snprintf(text, sizeof(text), "_%p_rot", (void*)node); - xml_ref_t rot = handleRotation(name + text, m); place.setRef(_U(positionref), pos.name()); - place.setRef(_U(rotationref), rot.name()); + if ( m->IsRotation() ) { + xml_ref_t rot = handleRotation(name + text, m); + place.setRef(_U(rotationref), rot.name()); + } } if (geo.doc_root.tag() != "gdml") { - if (dynamic_cast<const PlacedVolume::Object*>(node)) { + if (is_placement(node)) { PlacedVolume p = Ref_t(node); const PlacedVolume::VolIDs& ids = p.volIDs(); for (PlacedVolume::VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 904804e0d3c468ca41ae20d4459998a03daf3301..7f67fa50b5d3f47bd5b167a1d0817a83529bccab 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -12,6 +12,7 @@ // Framework include files #include "DD4hep/Factories.h" #include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" #include "../LCDDImp.h" // ROOT includes @@ -19,6 +20,7 @@ #include "TGeoVolume.h" using namespace std; +using namespace DD4hep; using namespace DD4hep::Geometry; static LCDDBuildType build_type(const char* value) { @@ -110,7 +112,7 @@ static long load_volmgr(LCDD& lcdd, int, char**) { } catch (const exception& e) { throw runtime_error(string(e.what()) + "\n" - "DD4hep: while programming VolumeManager. Are your volIDs correct?"); + "DD4hep: while programming VolumeManager. Are your volIDs correct?"); } catch (...) { throw runtime_error("UNKNOWN exception while programming VolumeManager. Are your volIDs correct?"); @@ -119,3 +121,61 @@ static long load_volmgr(LCDD& lcdd, int, char**) { } DECLARE_APPLY(DD4hepVolumeManager,load_volmgr) +static long dump_geometry(LCDD& lcdd, int argc, char** argv) { + if ( argc > 1 ) { + string output = argv[1]; + cout << "Dump geometry to root file : " << output << endl; + lcdd.manager().Export(output.c_str()+1); + return 1; + } + return 0; +} +DECLARE_APPLY(DD4hepGeometry2Root,dump_geometry) + +static long dump_geometry(PlacedVolume pv,int level) { + char fmt[64]; + const TGeoNode* node = pv.ptr(); + ::sprintf(fmt,"%03d %%-%ds %%s",level+1,2*level+1); + printout(INFO,"+++",fmt,"",node->GetName()); + for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) { + TGeoNode* daughter = node->GetDaughter(idau); + PlacedVolume placement(daughter); + if ( placement.data() ) { + PlacedVolume pv_dau = Ref_t(daughter); + dump_geometry(pv_dau,level+1); + } + } + return 1; +} +static long dump_geometry(DetElement de,int level) { + const DetElement::Children& c = de.children(); + char fmt[64]; + for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) { + ::sprintf(fmt,"%03d %%-%ds %%s",level+1,2*level+1); + printout(INFO,"+++",fmt,"",(*i).second.placementPath().c_str()); + dump_geometry((*i).second,level+1); + } + return 1; +} + +/** Basic entry point to print otu the detector element hierarchy + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +static long dump_detelement_tree(LCDD& lcdd, int, char**) { + return dump_geometry(lcdd.world(),0); +} +DECLARE_APPLY(DD4hepDetectorDump,dump_detelement_tree) + +/** Basic entry point to print otu the volume hierarchy + * + * @author M.Frank + * @version 1.0 + * @date 01/04/2014 + */ +static long dump_volume_tree(LCDD& lcdd, int, char**) { + return dump_geometry(lcdd.world().placement(),0); +} +DECLARE_APPLY(DD4hepVolumeDump,dump_volume_tree)