From 14c1c03269cb96390dd2152d2ffb473369877312 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Fri, 4 Apr 2014 20:24:53 +0000
Subject: [PATCH] Changes to support alignment stuff and several bug fixes to
 existing classes

---
 DDCore/include/DD4hep/Alignment.h         |  28 +++-
 DDCore/include/DD4hep/Detector.h          |   4 +
 DDCore/include/DD4hep/DetectorAlignment.h |  49 ------
 DDCore/include/DD4hep/DetectorTools.h     |  30 +++-
 DDCore/include/DD4hep/Handle.h            |   7 +-
 DDCore/include/DD4hep/LCDD.h              |  21 ++-
 DDCore/include/DD4hep/MatrixHelpers.h     |  54 +++++++
 DDCore/include/DD4hep/Primitives.h        |  10 ++
 DDCore/include/DD4hep/Shapes.h            |  38 +++--
 DDCore/include/DD4hep/Volumes.h           |   4 +-
 DDCore/include/XML/UnicodeValues.h        |   3 +-
 DDCore/include/XML/XMLTags.h              |   2 +-
 DDCore/src/Alignment.cpp                  | 141 ++++++++++++-----
 DDCore/src/Detector.cpp                   |   6 +-
 DDCore/src/DetectorAlignment.cpp          | 135 -----------------
 DDCore/src/DetectorTools.cpp              |  90 ++++++++---
 DDCore/src/Handle.cpp                     |  22 ++-
 DDCore/src/LCDDImp.cpp                    |  85 +++++++----
 DDCore/src/LCDDImp.h                      |  10 +-
 DDCore/src/MatrixHelpers.cpp              |  76 ++++++++--
 DDCore/src/MatrixHelpers.h                |  41 -----
 DDCore/src/Shapes.cpp                     |  25 +--
 DDCore/src/Volumes.cpp                    |  59 ++++++--
 DDCore/src/XML/DocumentHandler.cpp        |  10 +-
 DDCore/src/plugins/Compact2Objects.cpp    |   9 ++
 DDCore/src/plugins/GeometryWalk.cpp       | 177 ++++++++++++++++++++++
 DDCore/src/plugins/LCDDConverter.cpp      |  34 +++--
 DDCore/src/plugins/StandardPlugins.cpp    |  62 +++++++-
 28 files changed, 830 insertions(+), 402 deletions(-)
 delete mode 100644 DDCore/include/DD4hep/DetectorAlignment.h
 create mode 100644 DDCore/include/DD4hep/MatrixHelpers.h
 delete mode 100644 DDCore/src/DetectorAlignment.cpp
 delete mode 100644 DDCore/src/MatrixHelpers.h
 create mode 100644 DDCore/src/plugins/GeometryWalk.cpp

diff --git a/DDCore/include/DD4hep/Alignment.h b/DDCore/include/DD4hep/Alignment.h
index ccf71f992..142ada4a1 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 c5e0d9156..d3fc671a9 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 2c2b3d673..000000000
--- 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 d84cb7cf6..436932556 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 0b7ad394c..275284c20 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 9b97b1486..5971b421e 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 000000000..da5564740
--- /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 518580a62..4837e79d1 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 4b877a58a..6f2dc2a9d 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 11d043750..65bfb23a4 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 62b6e2962..1ccb661b0 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 3a2d5d0d4..b6e246650 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 900245140..70105d90f 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 9f103ddd7..f678d663f 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 b7d58d2de..000000000
--- 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 d919d46b1..03ef65845 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 fe851d125..897c4c50b 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 9b3bc261b..242f845f7 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 1e43400df..247a31213 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 31f3e54d9..e803c891f 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 26c54b6c1..000000000
--- 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 1f658f1f5..1a78d6082 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 41d06b169..8bad3afe6 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 a9e3e5fc6..843ba706e 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 732b2c924..77e14112d 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 000000000..904364f56
--- /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 f1054fa3e..09a92a423 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 904804e0d..7f67fa50b 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)
-- 
GitLab