diff --git a/DDAlign/CMakeLists.txt b/DDAlign/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2313286bb1711b45d0b3e259f9510adc74e4715f
--- /dev/null
+++ b/DDAlign/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
+#---------------------------
+set( PackageName DDAlign )
+
+#---add additional packages here--------------------------------------------------
+find_package( DD4hep ) 
+set(CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH}  ${DD4hep_ROOT}/cmake ) 
+include( DD4hep )
+
+find_package( ROOT REQUIRED )
+#---Includedirs ------------------------------------------------------------------
+include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${DD4hep_INCLUDE_DIRS}
+    ${ROOT_INCLUDE_DIR} )
+
+#---DD4hepAlign library --------------------------------------------------------------
+file(GLOB sources src/*.cpp)
+add_library(DD4hepAlign SHARED ${sources})
+target_link_libraries(DD4hepAlign ${DD4hep_LIBRARIES} DD4hepCore ${ROOT_LIBRARIES} ${ROOT_COMPONENT_LIBRARIES})
+SET( CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-long-long")
+if(DD4HEP_USE_XERCESC)
+  add_definitions(-DDD4HEP_USE_XERCESC)
+else()
+  add_definitions(-DDD4HEP_USE_TINYXML)
+endif()
+SET_TARGET_PROPERTIES( DD4hepAlign PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION})
+#---DD4hepAlign rootmap --------------------------------------------------------------
+dd4hep_generate_rootmap(DD4hepAlign)
+
+install(DIRECTORY include/DDAlign
+  DESTINATION include
+  PATTERN ".svn" EXCLUDE )
+
+install(TARGETS DD4hepAlign
+  RUNTIME DESTINATION bin
+  LIBRARY DESTINATION lib
+  )
+# to do: add corresponding uninstall...
+#-------------------------------------------------------
diff --git a/DDAlign/include/DDAlign/AlignmentCache.h b/DDAlign/include/DDAlign/AlignmentCache.h
new file mode 100644
index 0000000000000000000000000000000000000000..55842e7c11034a0e84dda664710d67b58b590f9d
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentCache.h
@@ -0,0 +1,107 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_ALIGNMENT_ALIGNMENTCACHE_H
+#define DD4HEP_ALIGNMENT_ALIGNMENTCACHE_H
+
+// Framework include files
+#include "DD4hep/Alignment.h"
+#include "DDAlign/AlignmentStack.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Alignment namespace declaration
+   */
+  namespace Geometry {
+
+    /// Forward declarations
+    class AlignmentOperator;
+    class AlignmentCache;
+    class AlignmentStack;
+    class LCDD;
+
+    /** @class AlignmentCache AlignmentCache.h AlignmentCache.h
+     *
+     *  Class caching all known alignment operations for one LCDD instance.
+     *  Internally the instances are fragmented to subdetectors defined
+     *  by the next-to-top level detector elements.
+     *
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class AlignmentCache  {
+      friend class LCDD;
+      friend class AlignmentOperator;
+
+    public:
+      typedef AlignmentStack::StackEntry Entry;
+      typedef std::map<unsigned int, TGeoPhysicalNode*> Cache;
+      typedef std::map<std::string,AlignmentCache*> SubdetectorAlignments;
+
+    protected:
+      LCDD&       m_lcdd;
+      /// Cache of subdetectors
+      SubdetectorAlignments m_detectors;
+      /// The subdetector specific map of alignments caches
+      Cache       m_cache;
+      /// Branchg name: If it is not the main tree instance, the name of the subdetector
+      std::string m_sdPath;
+      /// The length of the branch name to optimize lookups....
+      size_t      m_sdPathLen;
+      /// Reference count
+      int         m_refCount;
+      /// Flag to indicate the top instance
+      bool        m_top;
+
+    protected:
+      /// Default constructor
+      AlignmentCache(LCDD& lcdd, const std::string& sdPath, bool top);
+      /// Default destructor
+      virtual ~AlignmentCache();
+      /// Retrieve branch cache by name. If not present it will be created
+      AlignmentCache* subdetectorAlignments(const std::string& name);
+
+      /// Population entry: Apply a complete stack of ordered alignments to the geometry structure
+      void apply(AlignmentStack& stack);
+      /// Apply a vector of SD entries of ordered alignments to the geometry structure
+      void apply(const std::vector<Entry*> &changes);
+      /// Add a new entry to the cache. The key is the placement path
+      bool insert(Alignment alignment);
+
+    public:
+      /// Create and install a new instance tree
+      static void install(LCDD& lcdd);
+      /// Unregister and delete a tree instance
+      static void uninstall(LCDD& lcdd);
+      
+      /// Add reference count
+      int addRef();
+      /// Release object. If reference count goes to NULL, automatic deletion is triggered.
+      int release();
+      /// Access the section name
+      const std::string& name() const   {   return m_sdPath;  }
+      /// Open a new transaction stack (Note: only one stack allowed!)
+      void openTransaction();
+      /// Close existing transaction stack and apply all alignments
+      void closeTransaction();
+      /// Retrieve the cache section corresponding to the path of an entry.
+      AlignmentCache* section(const std::string& path_name) const;
+      /// Retrieve an alignment entry by its lacement path
+      Alignment get(const std::string& path) const;
+      /// Return all entries matching a given path. Careful: Expensive operaton!
+      std::vector<Alignment> matches(const std::string& path_match, bool exclude_exact=false) const;
+    };
+
+  } /* End namespace Geometry        */
+} /* End namespace DD4hep            */
+#endif    /* DD4HEP_ALIGNMENT_ALIGNMENTCACHE_H       */
diff --git a/DDAlign/include/DDAlign/AlignmentOperators.h b/DDAlign/include/DDAlign/AlignmentOperators.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d5b59b27b320c5336452dd5603fd34d32373350
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentOperators.h
@@ -0,0 +1,89 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_ALIGNMENT_ALIGNMENTOPERATORS_H
+#define DD4HEP_ALIGNMENT_ALIGNMENTOPERATORS_H
+
+// Framework include files
+#include "DD4hep/Alignment.h"
+#include "DDAlign/AlignmentCache.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Alignment namespace declaration
+   */
+  namespace Geometry {
+
+    /// Forward declarations
+    class LCDD;
+
+
+    /** @class AlignmentOperator AlignmentOperators.h DDAlign/AlignmentOperators.h
+     *
+     *
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    struct AlignmentOperator  {
+      typedef AlignmentStack::StackEntry Entry;
+      typedef AlignmentCache::Cache      Cache;
+      typedef std::vector<Entry*>        Entries;
+      typedef std::map<std::string,std::pair<TGeoPhysicalNode*,Entry*> > Nodes;
+      AlignmentCache& cache;
+      Nodes& nodes;
+    public: 
+      AlignmentOperator(AlignmentCache& c, Nodes& n) : cache(c), nodes(n) {}
+      void insert(Alignment alignment)  const;
+    };
+
+    /** @class AlignmentSelector AlignmentOperators.h DDAlign/AlignmentOperators.h
+     *
+     *
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    struct AlignmentSelector : public AlignmentOperator {
+    public: 
+      const Entries& entries;
+      AlignmentSelector(AlignmentCache& c, Nodes& n, const Entries& e) : AlignmentOperator(c,n), entries(e) {}
+      ~AlignmentSelector() { }
+      const AlignmentSelector& reset()   const { nodes.clear(); return *this; }
+      void operator()(const AlignmentCache::Cache::value_type& e) const;
+      void operator()(Entry* e) const;
+    };
+
+    template <typename T> struct AlignmentActor : public AlignmentOperator {
+    public: 
+      AlignmentActor(AlignmentCache& c, Nodes& n) : AlignmentOperator(c,n) { init(); }
+      void init() {}
+      void operator()(Nodes::value_type& e) const;
+    };
+
+    namespace DDAlign_standard_operations  {
+      struct node_print;
+      struct node_reset;
+      struct node_align;
+      struct node_delete;
+    }
+
+    // Specializations
+    template <> void AlignmentActor<DDAlign_standard_operations::node_print>::init();
+    template <> void AlignmentActor<DDAlign_standard_operations::node_print>::operator() (Nodes::value_type& n)  const;
+    template <> void AlignmentActor<DDAlign_standard_operations::node_delete>::operator()(Nodes::value_type& n)  const;
+    template <> void AlignmentActor<DDAlign_standard_operations::node_reset>::operator() (Nodes::value_type& n)  const;
+    template <> void AlignmentActor<DDAlign_standard_operations::node_align>::operator() (Nodes::value_type& n)  const;
+
+  } /* End namespace Geometry        */
+} /* End namespace DD4hep            */
+#endif    /* DD4HEP_ALIGNMENT_ALIGNMENTOPERATORS_H       */
diff --git a/DDAlign/include/DDAlign/AlignmentStack.h b/DDAlign/include/DDAlign/AlignmentStack.h
new file mode 100644
index 0000000000000000000000000000000000000000..87bb3101118b52253da09e54e99a57254325423b
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentStack.h
@@ -0,0 +1,128 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_ALIGNMENT_ALIGNMENTSTACK_H
+#define DD4HEP_ALIGNMENT_ALIGNMENTSTACK_H
+
+// Framework include files
+#include "DD4hep/Detector.h"
+#include "DD4hep/Objects.h"
+
+// C/C++ include files
+#include <memory>
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Alignment namespace declaration
+   */
+  namespace Geometry {
+
+    /** @class AlignmentStack AlignmentStack.h AlignmentStack.h
+     *
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class AlignmentStack  {
+    public:
+      enum {
+	OVERLAP_DEFINED     = 1<<0,
+	MATRIX_DEFINED      = 1<<1,
+	CHECKOVL_DEFINED    = 1<<2,
+	CHECKOVL_VALUE      = 1<<3,
+	RESET_VALUE         = 1<<4,
+	RESET_CHILDREN      = 1<<5,
+	____LLLAST          = 1<<31
+      } Flags;
+
+      struct StackEntry {
+	DetElement    detector;
+	Transform3D   transform;
+	std::string   path;
+	double        overlap;
+	int           flag;
+
+	/// Fully initializing constructor
+        StackEntry(const DetElement& p, const std::string& placement, const Transform3D& t, double ov, int flg);
+	/// Constructor with partial initialization
+	StackEntry(DetElement element, bool rst=true, bool rst_children=true);
+	/// Constructor with partial initialization
+	StackEntry(DetElement element, const Transform3D& trafo, bool rst=true, bool rst_children=true);
+	/// Constructor with partial initialization
+	StackEntry(DetElement element, const Position& translation, bool rst=true, bool rst_children=true);
+	/// Constructor with partial initialization
+	StackEntry(DetElement element, const RotationZYX& rot, bool rst=true, bool rst_children=true);
+	/// Constructor with partial initialization
+	StackEntry(DetElement element, const Position& translation, const RotationZYX& rot, bool rst=true, bool rst_children=true);
+	/// Copy constructor
+	StackEntry(const StackEntry& e);
+	/// Default destructor
+	~StackEntry() {}
+	bool checkFlag(int mask) const {  return (flag&mask) == mask; }
+	bool checkOverflow() const     {  return checkFlag(CHECKOVL_DEFINED); }
+	bool overflowValue() const     {  return checkFlag(CHECKOVL_VALUE); }
+	bool checkOverlap() const      {  return checkFlag(OVERLAP_DEFINED); }
+	bool hasMatrix() const         {  return checkFlag(MATRIX_DEFINED); }
+	bool needsReset() const        {  return checkFlag(RESET_VALUE); }
+	bool resetChildren() const     {  return checkFlag(RESET_CHILDREN); }
+
+	/// Attach transformation object
+	StackEntry& setTransformation(const Transform3D& trafo);
+	/// Instruct entry to ignore the transformation
+	StackEntry& clearTransformation();
+	/// Set flag to reset the entry to it's ideal geometrical position
+	StackEntry& setReset(bool new_value=true);
+	/// Set flag to reset the entry's children to their ideal geometrical position
+	StackEntry& setResetChildren(bool new_value=true);
+	/// Set flag to check overlaps
+	StackEntry& setOverlapCheck(bool new_value=true);
+	/// Set the precision for the overlap check (otherwise the default is 0.001 cm)
+	StackEntry& setOverlapPrecision(double precision=0.001);
+      };
+      typedef std::map<std::string, StackEntry*> Stack;
+
+    protected:
+      /// The subdetector specific map of alignments caches
+      Stack m_stack;
+
+      /// Default constructor
+      AlignmentStack();
+
+    public:
+
+      /// Default destructor. Careful with this one: 
+      virtual ~AlignmentStack();
+      /// Static client accessor
+      static AlignmentStack& get(); 
+      /// Create an alignment stack instance. The creation of a second instance will be refused.
+      static void create();
+      /// Check existence of alignment stack
+      static bool exists();
+      /// Add a new entry to the cache. The key is the placement path
+      static bool insert(const std::string& full_path, StackEntry* new_entry);
+      /// Add a new entry to the cache. The key is the placement path. The placement path must be set in the entry
+      static bool insert(StackEntry* new_entry);
+      /// Clear data content and remove the slignment stack
+      void release();
+      /// Access size of the alignment stack
+      size_t size() const  {  return m_stack.size(); }
+      /// Add a new entry to the cache. The key is the placement path
+      bool add(StackEntry* new_entry);
+      /// Retrieve an alignment entry of the current stack
+      std::auto_ptr<StackEntry> pop();
+      /// Get all path entries to be aligned. Note: transient!
+      std::vector<const StackEntry*> entries() const;
+    };
+
+  } /* End namespace Geometry        */
+} /* End namespace DD4hep            */
+#endif    /* DD4HEP_ALIGNMENT_ALIGNMENTSTACK_H       */
diff --git a/DDAlign/include/DDAlign/AlignmentTags.h b/DDAlign/include/DDAlign/AlignmentTags.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f20da4620f026125c316342ab466310f90f3ec0
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentTags.h
@@ -0,0 +1,42 @@
+// $Id: XMLTags.h 889 2013-11-14 15:55:39Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_ALIGNMENT_ALIGNMENT_TAGS_H
+#define DD4HEP_ALIGNMENT_ALIGNMENT_TAGS_H
+
+// Framework include files
+#include "XML/XMLElements.h"
+#ifndef UNICODE 
+#define UNICODE(x)  extern const Tag_t Unicode_##x
+#endif
+
+// Unicode tags known to the alignment section
+namespace DD4hep {
+  namespace XML {
+    UNICODE(DetectorAlignment);
+    UNICODE(subdetectors);
+    UNICODE(subdetector);
+    UNICODE(detelements);
+    UNICODE(detelement);
+    UNICODE(subpath);
+    UNICODE(path);
+    UNICODE(pivot);
+    UNICODE(reset);
+    UNICODE(placement);
+    UNICODE(reset_children);
+    UNICODE(open_transaction);
+    UNICODE(close_transaction);
+    UNICODE(check_overlaps);
+  }
+}
+
+#undef UNICODE // Do not miss this one!
+
+#include "XML/XMLTags.h"
+
+#endif /* DD4HEP_ALIGNMENT_ALIGNMENT_TAGS_H  */
diff --git a/DDAlign/include/DDAlign/AlignmentWriter.h b/DDAlign/include/DDAlign/AlignmentWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..45b61fac18c6f0107d838766f96ff51b1ddf6f5c
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentWriter.h
@@ -0,0 +1,65 @@
+// $Id: LCDDConverter.h 889 2013-11-14 15:55:39Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDALIGN_ALIGNMENTWRITER_H
+#define DD4HEP_DDALIGN_ALIGNMENTWRITER_H
+
+// Framework include files
+#include "XML/XMLElements.h"
+#include "DD4hep/Detector.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Geomentry namespace declaration
+   */
+  namespace Geometry {
+
+    // Forward declarations
+    class LCDD;
+    class AlignmentCache;
+
+    /** @class AlignmentWriter AlignmentWriter.cpp AlignmentWriter.cpp
+     *
+     * Geometry converter from DD4hep to Geant 4.
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class AlignmentWriter  {
+    protected:
+      /// Reference to detector description
+      LCDD& m_lcdd;
+      /// Reference to the alignment cache
+      AlignmentCache* m_cache;
+
+      /// Add single alignment node to the XML document
+      void addNode(XML::Element elt, Alignment a)  const;
+
+    public:
+      /// Initializing Constructor
+      AlignmentWriter(LCDD& lcdd);
+      /// Standard destructor
+      virtual ~AlignmentWriter();
+
+      /// Dump one full DetElement subtree into a newly created document
+      XML::Document dump(DetElement element, bool enable_transactions=false) const;
+      /// Scan one DetElement structure and return an XML element containing the alignment in this subtree.
+      XML::Element scan(XML::Document doc, DetElement element)  const;
+      /// Create the element corresponding to one single detector element without children
+      XML::Element createElement(XML::Document doc, DetElement element)  const;
+      /// Write the XML document structure to a file.
+      long write(XML::Document doc, const std::string& output)  const;
+    };
+  }    // End namespace XML
+}      // End namespace DD4hep
+#endif // DD4HEP_DDALIGN_ALIGNMENTWRITER_H
+ 
diff --git a/DDAlign/include/DDAlign/DetectorAlignment.h b/DDAlign/include/DDAlign/DetectorAlignment.h
new file mode 100644
index 0000000000000000000000000000000000000000..055d1bbbad94db5776f6d4b514b433d2d358a493
--- /dev/null
+++ b/DDAlign/include/DDAlign/DetectorAlignment.h
@@ -0,0 +1,76 @@
+// $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"
+
+// Forward declarations
+class TGeoHMatrix;
+
+/*
+ *   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);
+      /// Access to the alignment block
+      Alignment alignment() const;
+      /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
+      std::vector<Alignment>& volumeAlignments();
+      /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
+      const std::vector<Alignment>& volumeAlignments() const;
+
+      /** @DetElement alignment: Calls to align the detector element itself  */
+      /// Align the PhysicalNode of the placement of the detector element (translation only)
+      Alignment align(const Position& pos, bool check = false, double overlap = 0.001);
+      /// Align the PhysicalNode of the placement of the detector element (rotation only)
+      Alignment align(const RotationZYX& rot, bool check = false, double overlap = 0.001);
+      /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
+      Alignment align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001);
+      /// Align the physical node according to a generic Transform3D
+      Alignment align(const Transform3D& tr, bool check = false, double overlap = 0.001);
+      /// Align the physical node according to a generic TGeo matrix
+      Alignment align(TGeoHMatrix* matrix, bool check = false, double overlap = 0.001);
+
+      /** @Volume alignment: Calls to align the volumes within on detector element  */
+      /// Align the PhysicalNode of the placement of the detector element (translation only)
+      Alignment align(const std::string& volume_path, const Position& pos, bool check = false, double overlap = 0.001);
+      /// Align the PhysicalNode of the placement of the detector element (rotation only)
+      Alignment align(const std::string& volume_path, const RotationZYX& rot, bool check = false, double overlap = 0.001);
+      /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
+      Alignment align(const std::string& volume_path, const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001);
+      /// Align the physical node according to a generic Transform3D
+      Alignment align(const std::string& volume_path, const Transform3D& tr, bool check = false, double overlap = 0.001);
+      /// Align the physical node according to a generic TGeo matrix
+      Alignment align(const std::string& volume_path, TGeoHMatrix* matrix, bool check = false, double overlap = 0.001);
+    };
+
+  } /* End namespace Geometry                       */
+} /* End namespace DD4hep                           */
+#endif    /* DD4HEP_GEOMETRY_DETECTORALIGNMENT_H    */
diff --git a/DDAlign/src/AlignmentCache.cpp b/DDAlign/src/AlignmentCache.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..49b39b5cdc9bcd10d98c1ad481e6cae20e7df19c
--- /dev/null
+++ b/DDAlign/src/AlignmentCache.cpp
@@ -0,0 +1,256 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/DetectorTools.h"
+#include "DDAlign/AlignmentCache.h"
+#include "DDAlign/AlignmentOperators.h"
+
+// ROOT include files
+#include "TGeoManager.h"
+
+// C/C++ include files
+#include <stdexcept>
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+using namespace DD4hep::Geometry::DDAlign_standard_operations;
+
+typedef AlignmentStack::StackEntry Entry;
+
+namespace {
+  /// one-at-time hash function
+  inline unsigned int hash32(const char* key) {
+    unsigned int hash = 0;
+    const char* k = key;
+    for (; *k; k++) {
+      hash += *k; 
+      hash += (hash << 10); 
+      hash ^= (hash >> 6);
+    }
+    hash += (hash << 3); 
+    hash ^= (hash >> 11); hash += (hash << 15);
+    return hash;
+  }
+
+}
+
+DetElement _detector(DetElement child)   {
+  if ( child.isValid() )   {
+    DetElement p(child.parent());
+    if ( p.isValid() && !p.parent().isValid() )
+      return child;
+    else if ( !p.isValid() )  // World detector element...
+      return child;
+    return _detector(p);
+  }
+  throw runtime_error("DD4hep: DetElement cannot determine detector parent [Invalid handle]");
+}
+
+/// Default constructor
+AlignmentCache::AlignmentCache(LCDD& lcdd, const std::string& sdPath, bool top)
+  : m_lcdd(lcdd), m_sdPath(sdPath), m_sdPathLen(sdPath.length()), m_refCount(1), m_top(top)
+{
+}
+
+/// Default destructor
+AlignmentCache::~AlignmentCache()   {
+  int nentries = (int)m_cache.size();
+  int nsect = (int)m_detectors.size();
+  releaseObjects(m_detectors)();
+  m_cache.clear();
+  printout(INFO,"AlignmentCache",
+	   "Destroy cache for subdetector %s [%d section(s), %d entrie(s)]",
+	   m_sdPath.c_str(),nsect,nentries);
+}
+
+/// Add reference count
+int AlignmentCache::addRef()   {
+  return ++m_refCount;
+}
+
+/// Release object. If reference count goes to NULL, automatic deletion is triggered.
+int AlignmentCache::release()   {
+  int value = --m_refCount;
+  if ( value == 0 )  {
+    delete this;
+  }
+  return value;
+}
+
+/// Add a new entry to the cache. The key is the placement path
+bool AlignmentCache::insert(Alignment alignment)  {
+  TGeoPhysicalNode* pn = alignment.ptr();
+  unsigned int index = hash32(pn->GetName()+m_sdPathLen);
+  Cache::const_iterator i = m_cache.find(index);
+  printout(ALWAYS,"AlignmentCache","Section: %s adding entry: %s",
+	   name().c_str(),alignment->GetName());
+  if ( i == m_cache.end() )   {
+    m_cache[index] = pn;
+    return true;
+  }
+  return false;
+}
+
+/// Retrieve the cache section corresponding to the path of an entry.
+AlignmentCache* AlignmentCache::section(const std::string& path_name) const   {
+  size_t idx, idq;
+  if ( path_name[0] != '/' )   {
+    return section(m_lcdd.world().placementPath()+'/'+path_name);
+  }
+  else if ( (idx=path_name.find('/',1)) == string::npos )  {
+    return (m_sdPath == path_name.c_str()+1) ? (AlignmentCache*)this : 0;
+  }
+  else if ( m_detectors.empty() )  {
+    return 0;
+  }
+  if ( (idq=path_name.find('/',idx+1)) != string::npos ) --idq;
+  string path = path_name.substr(idx+1,idq-idx);
+  SubdetectorAlignments::const_iterator j = m_detectors.find(path);
+  return (j==m_detectors.end()) ? 0 : (*j).second;
+}
+
+/// Retrieve an alignment entry by its lacement path
+Alignment AlignmentCache::get(const std::string& path_name) const   {
+  size_t idx, idq;
+  unsigned int index = hash32(path_name.c_str()+m_sdPathLen);
+  Cache::const_iterator i = m_cache.find(index);
+  if ( i != m_cache.end() )  {
+    return Alignment((*i).second);
+  }
+  else if ( m_detectors.empty() )  {
+    return Alignment(0);
+  }
+  else if ( path_name[0] != '/' )   {
+    return get(m_lcdd.world().placementPath()+'/'+path_name);
+  }
+  else if ( (idx=path_name.find('/',1)) == string::npos )  {
+    // Escape: World volume and not found in cache --> not present
+    return Alignment(0);
+  }
+  if ( (idq=path_name.find('/',idx+1)) != string::npos ) --idq;
+  string path = path_name.substr(idx+1,idq-idx);
+  SubdetectorAlignments::const_iterator j = m_detectors.find(path);
+  if ( j != m_detectors.end() ) return (*j).second->get(path_name);
+  return Alignment(0);
+}
+
+/// Return all entries matching a given path. 
+vector<Alignment> AlignmentCache::matches(const string& match, bool exclude_exact) const   {
+  vector<Alignment> result;
+  AlignmentCache* c = section(match);
+  if ( c )  {
+    size_t len = match.length();
+    result.reserve(c->m_cache.size());
+    for(Cache::const_iterator i=c->m_cache.begin(); i!=c->m_cache.end();++i)  {
+      const Cache::value_type& v = *i;
+      const char* n = v.second->GetName();
+      if ( 0 == ::strncmp(n,match.c_str(),len) )   {
+	if ( exclude_exact && len == ::strlen(n) ) continue;
+	result.push_back(Alignment(v.second));
+      }
+    }
+  }
+  return result;
+}
+
+/// Open a new transaction stack (Note: only one stack allowed!)
+void AlignmentCache::openTransaction()   {
+  /// Check if transaction already present. If not, open, else issue an error
+  if ( !AlignmentStack::exists() )  {
+    AlignmentStack::create();
+    return;
+  }
+  string msg = "Request to open a second alignment transaction stack -- not allowed!";
+  string err = format("Alignment<alignment>",msg);
+  printout(FATAL,"AlignmentCache",msg);
+  throw runtime_error(err);
+}
+
+/// Close existing transaction stack and apply all alignments
+void AlignmentCache::closeTransaction()   {
+  /// Check if transaction is open. If yes, close it and apply alignment stack.
+  /// If no transaction is active, ignore the staement, but issue a warning.
+  if ( AlignmentStack::exists() )  {
+    TGeoManager& mgr = m_lcdd.manager();
+    mgr.UnlockGeometry();
+    apply(AlignmentStack::get());
+    AlignmentStack::get().release();
+    printout(INFO,"AlignmentCache","Alignments were applied. Refreshing physical nodes....");
+    mgr.LockGeometry();
+    mgr.GetCurrentNavigator()->ResetAll();
+    mgr.GetCurrentNavigator()->BuildCache();
+    mgr.RefreshPhysicalNodes();
+    return;
+  }
+  printout(WARNING,"Alignment<alignment>",
+	   "Request to close a non-existing alignmant transaction.");
+}
+
+/// Create and install a new instance tree
+void AlignmentCache::install(LCDD& lcdd)   {
+  AlignmentCache* cache = lcdd.extension<AlignmentCache>(false);
+  if ( !cache )  {
+    lcdd.addExtension<AlignmentCache>(new AlignmentCache(lcdd,"world",true));
+  }
+}
+
+/// Unregister and delete a tree instance
+void AlignmentCache::uninstall(LCDD& lcdd)   {
+  if ( lcdd.extension<AlignmentCache>(false) )  {
+    lcdd.removeExtension<AlignmentCache>(true);
+  }
+}
+
+/// Retrieve branch cache by name. If not present it will be created
+AlignmentCache* AlignmentCache::subdetectorAlignments(const std::string& name)    {
+  SubdetectorAlignments::const_iterator i = m_detectors.find(name);
+  if ( i == m_detectors.end() )   {
+    AlignmentCache* ptr = new AlignmentCache(m_lcdd,name,false);
+    m_detectors.insert(make_pair(name,ptr));
+    return ptr;
+  }
+  return (*i).second;
+}
+
+/// Apply a complete stack of ordered alignments to the geometry structure
+void AlignmentCache::apply(AlignmentStack& stack)    {
+  typedef map<TNamed*,vector<Entry*> > sd_entries_t;
+  sd_entries_t all;
+  while(stack.size() > 0)    {
+    Entry* e = stack.pop().release();
+    DetElement det = _detector(e->detector);
+    all[det.ptr()].push_back(e);
+  }
+  for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i)  {
+    DetElement det(Ref_t((*i).first));
+    AlignmentCache* sd_cache = subdetectorAlignments(det.placement().name());
+    sd_cache->apply( (*i).second );
+    (*i).second.clear();
+  }
+}
+
+
+/// Apply a vector of SD entries of ordered alignments to the geometry structure
+void AlignmentCache::apply(const vector<Entry*>& changes)   {
+  typedef std::map<std::string,std::pair<TGeoPhysicalNode*,Entry*> > Nodes;
+  typedef vector<Entry*> Changes;
+  Nodes nodes;
+
+  AlignmentSelector selector(*this,nodes,changes);
+  for_each(m_cache.begin(),m_cache.end(),selector.reset());
+  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_print>(*this,nodes));
+  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_reset>(*this,nodes));
+
+  for_each(changes.begin(),changes.end(),selector.reset());
+  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_align>(*this,nodes));
+  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_delete>(*this,nodes));
+}
diff --git a/DDAlign/src/AlignmentOperators.cpp b/DDAlign/src/AlignmentOperators.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe73c627de507c62058bfe8af5808d8a28c4f2d9
--- /dev/null
+++ b/DDAlign/src/AlignmentOperators.cpp
@@ -0,0 +1,196 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DDAlign/AlignmentOperators.h"
+#include "DDAlign/DetectorAlignment.h"
+
+// C/C++ include files
+#include <stdexcept>
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+void AlignmentOperator::insert(Alignment alignment)  const   {
+  if ( !cache.insert(alignment) )     {
+    // Error
+  }
+}
+
+void AlignmentSelector::operator()(Entries::value_type e)  const {
+  TGeoPhysicalNode* pn = 0;
+  nodes.insert(make_pair(e->path,make_pair(pn,e)));
+}
+
+void AlignmentSelector::operator()(const Cache::value_type& e)  const {
+  TGeoPhysicalNode* pn = e.second;
+  for(Entries::const_iterator j=entries.begin(); j != entries.end(); ++j)   {
+    Entries::value_type e = (*j);
+    if ( e->needsReset() || e->hasMatrix() )  {
+      const char* p = pn->GetName();
+      bool reset_children = e->resetChildren();
+      if ( reset_children && ::strstr(p,e->path.c_str()) == p )   {
+	nodes.insert(make_pair(p,make_pair(pn,e)));
+	break;
+      }
+      else if ( e->path == p )  {
+	nodes.insert(make_pair(p,make_pair(pn,e)));
+	break;
+      }
+    }
+  } 
+}
+
+template <> void AlignmentActor<DDAlign_standard_operations::node_print>::init() {
+  printout(ALWAYS,"AlignmentCache","++++++++++++++++++++++++ Summary ++++++++++++++++++++++++");
+}
+
+template <> void AlignmentActor<DDAlign_standard_operations::node_print>::operator()(Nodes::value_type& n)  const {
+  TGeoPhysicalNode* p = n.second.first;
+  Entry* e = n.second.second;
+  printout(ALWAYS,"AlignmentCache","Need to reset entry:%s - %s [needsReset:%s, hasMatrix:%s]",
+	   p->GetName(),e->path.c_str(),yes_no(e->needsReset()),yes_no(e->hasMatrix()));
+}
+
+template <> void AlignmentActor<DDAlign_standard_operations::node_delete>::operator()(Nodes::value_type& n)  const {
+  delete n.second.second;
+  n.second.second = 0;
+}
+
+template <> void AlignmentActor<DDAlign_standard_operations::node_reset>::operator()(Nodes::value_type& n) const  {
+  TGeoPhysicalNode* p = n.second.first;
+  //Entry*            e = n.second.second;
+  string np;
+  if ( p->IsAligned() )   {
+    for (Int_t i=0, nLvl=p->GetLevel(); i<=nLvl; i++) {
+      TGeoNode* node = p->GetNode(i);
+      TGeoMatrix* mm = node->GetMatrix();  // Node's relative matrix
+      np += string("/")+node->GetName();
+      if ( !mm->IsIdentity() && i > 0 )  {    // Ignore the 'world', is identity anyhow
+	Alignment a = cache.get(np);
+	if ( a.isValid() )  {
+	  printout(ALWAYS,"AlignmentActor<reset>","Correct path:%s leaf:%s",p->GetName(),np.c_str());
+	  TGeoHMatrix* glob = p->GetMatrix(i-1);
+	  if ( a.isValid() && i!=nLvl )   {
+	    *mm = *(a->GetOriginalMatrix());
+	  }
+	  else if ( i==nLvl ) {
+	    TGeoHMatrix* hm = dynamic_cast<TGeoHMatrix*>(mm);
+	    TGeoMatrix*  org = p->GetOriginalMatrix();
+	    hm->SetTranslation(org->GetTranslation());
+	    hm->SetRotation(org->GetRotationMatrix());
+	  }
+	  *glob *= *mm;
+	}
+      }
+    }
+  }
+}
+
+template <> void AlignmentActor<DDAlign_standard_operations::node_align>::operator()(Nodes::value_type& n) const  {
+  Entry& e = *n.second.second;
+  bool check = e.checkOverflow();
+  bool overlap = e.checkOverlap();
+  bool has_matrix  = e.hasMatrix();
+  DetElement det = e.detector;
+  bool valid = det.alignment().isValid();
+  string det_placement = det.placementPath();
+
+  if ( !valid && !has_matrix )  {
+    cout << "++++ SKIP ALIGNMENT: ++++ " << e.path 
+	 << " DE:" << det_placement 
+	 << " Valid:" << yes_no(valid) 
+	 << " Matrix:" << yes_no(has_matrix) << endl;
+    /*    */
+    return;
+  }
+
+  cout << "++++ " << e.path 
+       << " DE:" << det_placement 
+       << " Valid:" << yes_no(valid) 
+       << " Matrix:" << yes_no(has_matrix)
+       << endl;
+  /*  */
+  // Need to care about optional arguments 'check_overlaps' and 'overlap'
+  DetectorAlignment ad(det);
+  Alignment alignment;
+  bool is_not_volume = e.path == det_placement;
+  if ( check && overlap )     {
+    alignment = is_not_volume 
+      ? ad.align(e.transform, e.overflowValue(), e.overlap)
+      : ad.align(e.path, e.transform, e.overflowValue(), e.overlap);
+  }
+  else if ( check )    {
+    alignment = is_not_volume 
+      ? ad.align(e.transform, e.overflowValue())
+      : ad.align(e.path, e.transform, e.overflowValue());
+  }
+  else     {
+    alignment = is_not_volume ? ad.align(e.transform) : ad.align(e.path, e.transform);
+   }
+  if ( alignment.isValid() )  {
+    insert(alignment);
+    return;
+  }
+  throw runtime_error("Failed to apply alignment for "+e.path);
+}
+
+#if 0
+    void alignment_reset_dbg(const string& path, const Alignment& a)   {      
+      TGeoPhysicalNode* n = a.ptr();
+      cout << " +++++++++++++++++++++++++++++++ " << path << endl;
+      cout << "      +++++ Misaligned physical node: " << endl;
+      n->Print();
+      string np;
+      if ( n->IsAligned() ) {
+	for (Int_t i=0; i<=n->GetLevel(); i++) {
+	  TGeoMatrix* mm = n->GetNode(i)->GetMatrix();
+	  np += "/";
+	  np += n->GetNode(i)->GetName();
+	  if ( mm->IsIdentity() ) continue;
+	  if ( i == 0 ) continue;
+
+	  TGeoHMatrix* glob = n->GetMatrix(i-1);
+	  NodeMap::const_iterator j=original_matrices.find(np);
+	  if ( j != original_matrices.end() && i!=n->GetLevel() )   {
+	    cout << "      +++++ Patch Level: " << i << np << endl;
+	    *mm = *((*j).second);
+	  }
+	  else  {
+	    if ( i==n->GetLevel() ) {
+	      cout << "      +++++ Level: " << i << np << " --- Original matrix: " << endl;
+	      n->GetOriginalMatrix()->Print();
+	      cout << "      +++++ Level: " << i << np << " --- Local matrix: " << endl;
+	      mm->Print();
+	      TGeoHMatrix* hm = dynamic_cast<TGeoHMatrix*>(mm);
+	      hm->SetTranslation(n->GetOriginalMatrix()->GetTranslation());
+	      hm->SetRotation(n->GetOriginalMatrix()->GetRotationMatrix());
+	      cout << "      +++++ Level: " << i << np << " --- New local matrix" << endl;
+	      mm->Print();
+	    }
+	    else	      {
+	      cout << "      +++++ Level: " << i << np << " --- Keep matrix " << endl;
+	      mm->Print();
+	    }
+	  }
+	  cout << "      +++++ Level: " << i << np << " --- Global matrix: " << endl;
+	  glob->Print();
+	  *glob *= *mm;
+	  cout << "      +++++ Level: " << i << np << " --- New global matrix: " << endl;
+	  glob->Print();
+	}
+      }
+      cout << "\n\n\n      +++++ physical node (full): " << np <<  endl;
+      n->Print();
+      cout << "      +++++ physical node (global): " << np <<  endl;
+      n->GetMatrix()->Print();
+    }
+#endif
diff --git a/DDAlign/src/AlignmentParser.cpp b/DDAlign/src/AlignmentParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9de3872c48c7872dba5dfada4c5481afc6dd4723
--- /dev/null
+++ b/DDAlign/src/AlignmentParser.cpp
@@ -0,0 +1,372 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "XML/Conversions.h"
+#include "XML/XMLElements.h"
+#include "XML/DocumentHandler.h"
+#include "DD4hep/DetectorTools.h"
+#include "DD4hep/DetFactoryHelper.h"
+
+#include "DDAlign/AlignmentTags.h"
+#include "DDAlign/AlignmentStack.h"
+#include "DDAlign/AlignmentCache.h"
+
+// C/C++ include files
+#include <stdexcept>
+
+namespace DD4hep  {
+
+  namespace   {
+
+    /** @class AlignmentTransaction
+     *
+     *  Manage alignment transaction to the cache for a given LCDD instance
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     *  @date    01/04/2014
+     */
+    struct AlignmentTransaction {
+      /// Internal flag to remember transaction contexts
+      bool flag;
+      /// Reference to the current LCDD instance
+      lcdd_t& lcdd;
+      /// Reference to the alignment cache
+      Geometry::AlignmentCache* m_cache;
+      
+      /// Default constructor
+      AlignmentTransaction(lcdd_t& l, xml_h e) : lcdd(l) {
+	flag = e.hasChild(_U(close_transaction));
+	/// First check if a transaction is to be opened
+	m_cache = lcdd.extension<Geometry::AlignmentCache>();
+	m_cache->addRef();
+	if ( e.hasChild(_U(open_transaction)) )  {
+	  m_cache->openTransaction();
+	}
+      }
+      /// Default destructor
+      ~AlignmentTransaction()   {
+	/// Last check if a transaction is to be closed
+	if ( flag ) {
+	  lcdd.extension<Geometry::AlignmentCache>()->closeTransaction();
+	}
+	m_cache->release();
+      }
+    };
+    /// Some utility class to specialize the convetrers:
+    class alignment;
+    class detelement;
+    class include_file;
+    class volume;
+    class rotation;
+    class position;
+    class pivot;
+    class transform3d;
+  }
+
+  /// Forward declarations for all specialized converters
+  template <> void Converter<pivot>::operator()(xml_h seq)  const;
+  template <> void Converter<position>::operator()(xml_h seq)  const;
+  template <> void Converter<rotation>::operator()(xml_h seq)  const;
+  template <> void Converter<transform3d>::operator()(xml_h seq)  const;
+
+  template <> void Converter<volume>::operator()(xml_h seq)  const;
+  template <> void Converter<alignment>::operator()(xml_h seq)  const;
+  template <> void Converter<detelement>::operator()(xml_h seq)  const;
+  template <> void Converter<include_file>::operator()(xml_h seq)  const;
+}  
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+/** Convert rotation objects
+ *
+ *    <rotation x="0.5" y="0"  z="0"/>     
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<rotation>::operator()(xml_h e) const {
+  xml_comp_t r(e);
+  RotationZYX* v = (RotationZYX*)param;
+  v->SetComponents(r.z(), r.y(), r.x());
+  printout(INFO,"Alignment<rotation>",
+	   "  Rotation:   x=%9.3f y=%9.3f   z=%9.3f  phi=%7.4f psi=%7.4f theta=%7.4f",
+	   r.x(), r.y(), r.z(), v->Phi(), v->Psi(), v->Theta());
+}
+
+/** Convert position objects
+ *
+ *    <position x="0.5" y="0"  z="0"/>     
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<position>::operator()(xml_h e) const {
+  xml_comp_t p(e);
+  Position* v = (Position*)param;
+  v->SetXYZ(p.x(), p.y(), p.z());
+  printout(INFO,"Alignment<position>","  Position:   x=%9.3f y=%9.3f   z=%9.3f",
+	   v->X(), v->Y(), v->Z());
+}
+
+/** Convert pivot objects
+ *
+ *    <pivot x="0.5" y="0"  z="0"/>     
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<pivot>::operator()(xml_h e) const {
+  xml_comp_t p(e);
+  double x,y,z;
+  Translation3D* v = (Translation3D*)param;
+  v->SetXYZ(x=p.x(), y=p.y(), z=p.z());
+  printout(INFO,"Alignment<pivot>","     Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
+}
+
+/** Convert transform3d objects
+ *
+ *     A generic alignment transformation is defined by
+ *     - a translation in 3D space identified in XML as a
+ *	   <position/> element
+ *	 - a rotation in 3D space around a pivot point specified in XML by
+ *	   2 elements: the <rotation/> and the <pivot/> element.
+ *	 The specification of any of the elements is optional:
+ *     - The absence of a translation implies the origine (0,0,0)
+ *     - The absence of a pivot point implies the origine (0,0,0)
+ *	 - The absence of a rotation implies the identity rotation.
+ *	   Any supplied pivot point in this case is ignored.
+ *
+ *	<xx>
+ *	  <position x="0" y="0"  z="0.0001*mm"/>
+ *	  <rotation x="0" y="0"  z="0"/>     
+ *	  <pivot    x="0" y="0"    z="100"/>     
+ *	</xx>
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<transform3d>::operator()(xml_h e) const {
+  typedef pair<bool,Transform3D> Data;
+  Position pos;
+  RotationZYX rot;
+  Translation3D piv;
+  xml_h child_rot, child_pos, child_piv;
+  Data* tr = (Data*)param;
+    
+  if ( (child_pos=e.child(_U(position),false)) )
+    Converter<position>(lcdd,&pos)(child_pos);
+  if ( (child_rot=e.child(_U(rotation),false)) )   {
+    Converter<rotation>(lcdd,&rot)(child_rot);
+    if ( (child_piv=e.child(_U(pivot),false)) )
+      Converter<pivot>(lcdd,&piv)(child_piv);
+  }
+  tr->first = true;
+  if ( child_rot && child_pos && child_piv )
+    tr->second = Transform3D(Translation3D(pos)*piv*rot*(piv.Inverse()));
+  else if ( child_rot && child_pos )
+    tr->second = Transform3D(rot,pos);
+  else if ( child_rot && child_piv )
+    tr->second = Transform3D(piv*rot*(piv.Inverse()));
+  else if ( child_rot )
+    tr->second = Transform3D(rot);
+  else if ( child_pos )
+    tr->second = Transform3D(pos);
+  else   {
+    tr->first  = false;
+  }
+}
+
+typedef AlignmentStack::StackEntry StackEntry;
+
+/** Convert volume objects
+ *
+ *	<volume subpath="layer4_0">
+ *	  <position x="0"   y="0"  z="0"/>
+ *	  <rotation x="0.5" y="0.1"  z="0.2"/>     
+ *	  <pivot    x="0" y="0"    z="100"/>
+ *      <volume>
+ *         ...
+ *      <volume>
+ *	</volume>
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<volume>::operator()(xml_h e) const {
+  pair<bool,Transform3D> trafo;
+  pair<DetElement,string>* elt = (pair<DetElement,string>*)param;
+  string subpath   = e.attr<string>(_U(path));
+  bool   reset     = e.hasAttr(_U(reset)) ? e.attr<bool>(_U(reset)) : true;
+  bool   reset_dau = e.hasAttr(_U(reset_children)) ? e.attr<bool>(_U(reset_children)) : true;
+  bool   check     = e.hasAttr(_U(check_overlaps));
+  bool   check_val = check ? e.attr<bool>(_U(check_overlaps)) : false;
+  bool   overlap   = e.hasAttr(_U(overlap));
+  double ovl       = overlap ? e.attr<double>(_U(overlap)) : 0.001;
+  string eltPlacement  = elt->first.placementPath();
+  string placementPath = subpath[0]=='/' ? subpath : eltPlacement + "/" + subpath;
+
+  printout(INFO,"Alignment<volume>","    path:%s placement:%s reset:%s children:%s",
+	   subpath.c_str(), placementPath.c_str(), yes_no(reset), yes_no(reset_dau));
+
+  Converter<transform3d>(lcdd,&trafo)(e);
+  int flags = 0;
+  if ( overlap     ) flags |= AlignmentStack::OVERLAP_DEFINED;
+  if ( trafo.first ) flags |= AlignmentStack::MATRIX_DEFINED;
+  if ( reset       ) flags |= AlignmentStack::RESET_VALUE;
+  if ( reset_dau   ) flags |= AlignmentStack::RESET_CHILDREN;
+  if ( check       ) flags |= AlignmentStack::CHECKOVL_DEFINED;
+  if ( check_val   ) flags |= AlignmentStack::CHECKOVL_VALUE;
+
+  StackEntry* entry = new StackEntry(elt->first,placementPath,trafo.second,ovl,flags);
+  AlignmentStack::insert(entry);
+  pair<DetElement,string> vol_param(elt->first,subpath);
+  xml_coll_t(e,_U(volume)).for_each(Converter<volume>(lcdd,&vol_param));
+}
+
+/** Convert detelement objects
+ *
+ *    Function entry expects as a parameter a valid DetElement handle
+ *    pointing to the subdetector, which detector elements should be 
+ *    realigned.
+ *
+ *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
+ *      <position x="0"   y="0"  z="0"/>
+ *      <rotation x="0.5" y="0"  z="0"/>     
+ *	  <pivot    x="0" y="0"    z="100"/>     
+ *    </detelement>
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<detelement>::operator()(xml_h e) const {
+  DetElement det   = param ? *(DetElement*)param : DetElement();
+  string path      = e.attr<string>(_U(path));
+  bool   check     = e.hasAttr(_U(check_overlaps));
+  bool   check_val = check ? e.attr<bool>(_U(check_overlaps)) : false;
+  bool   reset     = e.hasAttr(_U(reset)) ? e.attr<bool>(_U(reset)) : true;
+  bool   reset_dau = e.hasAttr(_U(reset_children)) ? e.attr<bool>(_U(reset_children)) : true;
+  bool   overlap   = e.hasAttr(_U(overlap));
+  double ovl       = overlap ? e.attr<double>(_U(overlap)) : 0.001;
+  DetElement elt   = Geometry::DetectorTools::findElement(det,path);
+  string placementPath = elt.isValid() ? elt.placementPath() : string("-----");
+
+  printout(INFO,"Alignment<detelement>","path:%s [%s] placement:%s reset:%s children:%s",
+	   path.c_str(), 
+	   elt.isValid() ? elt.path().c_str() : "-----",
+	   placementPath.c_str(),
+	   yes_no(reset), yes_no(reset_dau));
+
+  if ( !elt.isValid() )   {
+    string err = "DD4hep: DetElement "+det.path()+" has no child:"+path+" [No such child]";
+    throw runtime_error(err);
+  }
+
+  pair<bool,Transform3D> trafo;
+  Converter<transform3d>(lcdd,&trafo)(e);
+  int flags = 0;
+  if ( overlap     ) flags |= AlignmentStack::OVERLAP_DEFINED;
+  if ( check       ) flags |= AlignmentStack::CHECKOVL_DEFINED;
+  if ( trafo.first ) flags |= AlignmentStack::MATRIX_DEFINED;
+  if ( reset       ) flags |= AlignmentStack::RESET_VALUE;
+  if ( reset_dau   ) flags |= AlignmentStack::RESET_CHILDREN;
+  if ( check_val   ) flags |= AlignmentStack::CHECKOVL_VALUE;
+
+  StackEntry* entry = new StackEntry(elt,placementPath,trafo.second,ovl,flags);
+  AlignmentStack::insert(entry);
+
+  pair<DetElement,string> vol_param(elt,"");
+  xml_coll_t(e,_U(volume)).for_each(Converter<volume>(lcdd,&vol_param));
+  xml_coll_t(e,_U(detelement)).for_each(Converter<detelement>(lcdd,&elt));
+  xml_coll_t(e,_U(include)).for_each(Converter<include_file>(lcdd,&elt));
+}
+
+/** Convert detelement_include objects
+ *
+ *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
+ *      <position x="0"   y="0"  z="0"/>
+ *      <rotation x="0.5" y="0"  z="0"/>     
+ *    </detelement>
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<include_file>::operator()(xml_h element) const {
+  xml_h node = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root();
+  string tag = node.tag();
+  if ( tag == "alignment" )  
+    Converter<alignment>(lcdd,param)(node);
+  else if ( tag == "detelement" )
+    Converter<detelement>(lcdd,param)(node);
+  else if ( tag == "subdetectors" || tag == "detelements" )
+    xml_coll_t(node,_U(detelements)).for_each(Converter<detelement>(lcdd,param));
+  else
+    throw runtime_error("Undefined tag name in XML structure:"+tag+" XML parsing abandoned.");
+}
+
+/** Convert alignment objects
+ *
+ *    <alignment>
+ *      <detelement path="TPC">
+ *        ...
+ *      </detelement>
+ *    </alignment>
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+template <> void Converter<alignment>::operator()(xml_h e)  const  {
+  AlignmentTransaction tr(lcdd, e);
+  DetElement top = param ? *(DetElement*)param : lcdd.world();
+
+  /// Now we process all allowed elements within the alignment tag:
+  /// <detelement/>, <detelements/>, <subdetectors/> and <include/>
+  xml_coll_t(e,_U(detelement)).for_each(Converter<detelement>(lcdd,&top));
+  xml_coll_t(e,_U(detelements)).for_each(_U(detelement),Converter<detelement>(lcdd,&top));
+  xml_coll_t(e,_U(subdetectors)).for_each(_U(detelement),Converter<detelement>(lcdd,&top));
+  xml_coll_t(e,_U(include)).for_each(Converter<include_file>(lcdd,&top));
+}
+
+/** Basic entry point to read alignment files
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+static long setup_Alignment(lcdd_t& lcdd, const xml_h& e) {
+  AlignmentCache::install(lcdd);
+  (DD4hep::Converter<DD4hep::alignment>(lcdd))(e);
+  return 1;
+}
+DECLARE_XML_DOC_READER(alignment,setup_Alignment)
+
+/** Basic entry point to install the alignment cache in a LCDD instance
+ *
+ *  @author  M.Frank
+ *  @version 1.0
+ *  @date    01/04/2014
+ */
+static long install_Alignment(lcdd_t& lcdd, int, char**) {
+  AlignmentCache::install(lcdd);
+  return 1;
+}
+DECLARE_APPLY(DD4hepAlignmentInstall,install_Alignment)
diff --git a/DDAlign/src/AlignmentParser.cpp.save b/DDAlign/src/AlignmentParser.cpp.save
new file mode 100644
index 0000000000000000000000000000000000000000..df7d53a8442443bcbabf59d11ebe5faffdb87eec
--- /dev/null
+++ b/DDAlign/src/AlignmentParser.cpp.save
@@ -0,0 +1,486 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "XML/Conversions.h"
+#include "XML/XMLElements.h"
+#include "XML/DocumentHandler.h"
+#include "DD4hep/MatrixHelpers.h"
+#include "DD4hep/DetectorTools.h"
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DetectorAlignment.h"
+
+#include "DDAlign/AlignmentTags.h"
+#include "TGeoManager.h"
+#include "Math/Rotation3D.h"
+#include "Math/Translation3D.h"
+
+using namespace std;
+using namespace DD4hep;
+typedef DD4hep::Geometry::DetectorAlignment DetectorAlignment;
+typedef DD4hep::Geometry::DetectorTools   DetectorTools;
+typedef DD4hep::Geometry::RotationZYX     RotationZYX;
+typedef DD4hep::Geometry::Rotation3D      Rotation3D;
+typedef DD4hep::Geometry::Position        Position;
+typedef DD4hep::Geometry::Transform3D     Transform3D;
+typedef ROOT::Math::Translation3D         Translation3D;
+typedef DD4hep::Geometry::DetElement      DetElement;
+typedef DD4hep::Geometry::Alignment       Alignment;
+
+typedef DD4hep::Geometry::LCDD lcdd_t;
+
+namespace DD4hep  {
+
+
+  /** @class AlignmentCache AlignmentCache.h AlignmentCache.h
+   *
+   */
+  class AlignmentCache  {
+  protected:
+    typedef std::map<unsigned int, TGeoPhysicalNode*> Cache;
+    /// The subdetector specific map of alignments caches
+    Cache m_cache;
+    std::string m_sdPath;
+    size_t      m_sdPathLen;
+  public:
+    /// Default constructor
+    AlignmentCache(const std::string& sdPath);
+    /// Default destructor
+    virtual ~AlignmentCache();
+    /// Add a new entry to the cache. The key is the placement path
+    bool insert(Alignment alignment);
+    /// Retrieve an alignment entry by its lacement path
+    Alignment get(const std::string& path) const;
+  };
+
+  /// one-at-time hash function
+  static unsigned int hash32(const char* key) {
+    unsigned int hash = 0;
+    const char* k = key;
+    for (; *k; k++) {
+      hash += *k; 
+      hash += (hash << 10); 
+      hash ^= (hash >> 6);
+    }
+    hash += (hash << 3); 
+    hash ^= (hash >> 11); hash += (hash << 15);
+    return hash;
+  }
+
+  /// Default constructor
+  AlignmentCache::AlignmentCache(const std::string& sdPath)
+    : m_sdPath(sdPath), m_sdPathLen(sdPath.length())
+  {
+  }
+
+  /// Default destructor
+  AlignmentCache::~AlignmentCache()   {
+    m_cache.clear();
+  }
+
+  /// Add a new entry to the cache. The key is the placement path
+  bool AlignmentCache::insert(Alignment alignment)  {
+    TGeoPhysicalNode* pn = alignment.ptr();
+    unsigned int index = hash32(pn->GetName()+m_sdPathLen);
+    Cache::const_iterator i = m_cache.find(index);
+    if ( i == m_cache.end() )   {
+      m_cache[index] = pn;
+      return true;
+    }
+    return false;
+  }
+
+  /// Retrieve an alignment entry by its lacement path
+  Alignment AlignmentCache::get(const std::string& path) const   {
+    unsigned int index = hash32(path.c_str()+m_sdPathLen);
+    Cache::const_iterator i = m_cache.find(index);
+    return Alignment(i == m_cache.end() ? 0 : (*i).second);
+  }
+
+  AlignmentCache* subdetectorAlignments(const std::string& name)   {
+    typedef map<string,AlignmentCache*> SubdetectorAlignments;
+    SubdetectorAlignments c;
+    SubdetectorAlignments::const_iterator i = c.find(name);
+    if ( i == c.end() )   {
+      AlignmentCache* ptr = new AlignmentCache(name);
+      c.insert(make_pair(name,ptr));
+      return ptr;
+    }
+    return (*i).second;
+  }
+
+  namespace   {
+    class alignment;
+    class subdetector;
+    class detelement;
+    class include_file;
+    class volume;
+    class rotation;
+    class position;
+    class pivot;
+    class transform3d;
+  }
+  template <> void Converter<alignment>::operator()(xml_h seq)  const;
+  
+  namespace {
+    using namespace Geometry;
+#if 0
+    void alignment_reset_dbg(const string& path, const Alignment& a)   {      
+      TGeoPhysicalNode* n = a.ptr();
+      cout << " +++++++++++++++++++++++++++++++ " << path << endl;
+      cout << "      +++++ Misaligned physical node: " << endl;
+      n->Print();
+      string np;
+      if ( n->IsAligned() ) {
+	for (Int_t i=0; i<=n->GetLevel(); i++) {
+	  TGeoMatrix* mm = n->GetNode(i)->GetMatrix();
+	  np += "/";
+	  np += n->GetNode(i)->GetName();
+	  if ( mm->IsIdentity() ) continue;
+	  if ( i == 0 ) continue;
+
+	  TGeoHMatrix* glob = n->GetMatrix(i-1);
+	  NodeMap::const_iterator j=original_matrices.find(np);
+	  if ( j != original_matrices.end() && i!=n->GetLevel() )   {
+	    cout << "      +++++ Patch Level: " << i << np << endl;
+	    *mm = *((*j).second);
+	  }
+	  else  {
+	    if ( i==n->GetLevel() ) {
+	      cout << "      +++++ Level: " << i << np << " --- Original matrix: " << endl;
+	      n->GetOriginalMatrix()->Print();
+	      cout << "      +++++ Level: " << i << np << " --- Local matrix: " << endl;
+	      mm->Print();
+	      TGeoHMatrix* hm = dynamic_cast<TGeoHMatrix*>(mm);
+	      hm->SetTranslation(n->GetOriginalMatrix()->GetTranslation());
+	      hm->SetRotation(n->GetOriginalMatrix()->GetRotationMatrix());
+	      cout << "      +++++ Level: " << i << np << " --- New local matrix" << endl;
+	      mm->Print();
+	    }
+	    else	      {
+	      cout << "      +++++ Level: " << i << np << " --- Keep matrix " << endl;
+	      mm->Print();
+	    }
+	  }
+	  cout << "      +++++ Level: " << i << np << " --- Global matrix: " << endl;
+	  glob->Print();
+	  *glob *= *mm;
+	  cout << "      +++++ Level: " << i << np << " --- New global matrix: " << endl;
+	  glob->Print();
+	}
+      }
+      cout << "\n\n\n      +++++ physical node (full): " << np <<  endl;
+      n->Print();
+      cout << "      +++++ physical node (global): " << np <<  endl;
+      n->GetMatrix()->Print();
+    }
+#endif
+
+    void alignment_reset(AlignmentCache* cache, const string& path, const Alignment& a)   {      
+      TGeoPhysicalNode* pn = a.ptr();
+      string np;
+      if ( pn->IsAligned() )   {
+	for (Int_t i=0, nLvl=pn->GetLevel(); i<=nLvl; i++) {
+	  TGeoNode* node = pn->GetNode(i);
+	  TGeoMatrix* mm = node->GetMatrix();  // Node's relative matrix
+	  np += string("/")+node->GetName();
+	  if ( !mm->IsIdentity() && i > 0 )  {    // Ignore the 'world', is identity anyhow
+	    TGeoHMatrix* glob = pn->GetMatrix(i-1);
+	    Alignment a = cache->get(np);
+	    if ( a.isValid() && i!=nLvl )   {
+	      *mm = *(a->GetOriginalMatrix());
+	    }
+	    else if ( i==nLvl ) {
+	      TGeoHMatrix* hm = dynamic_cast<TGeoHMatrix*>(mm);
+	      TGeoMatrix*  org = pn->GetOriginalMatrix();
+	      hm->SetTranslation(org->GetTranslation());
+	      hm->SetRotation(org->GetRotationMatrix());
+	    }
+	    *glob *= *mm;
+	  }
+	}
+      }
+    }
+  }
+
+
+
+  /** Convert rotation objects
+   *
+   *    <rotation x="0.5" y="0"  z="0"/>     
+   */
+  template <> void Converter<rotation>::operator()(xml_h e) const {
+    xml_comp_t r(e);
+    RotationZYX* v = (RotationZYX*)param;
+    v->SetComponents(r.z(), r.y(), r.x());
+    printout(INFO,"Alignment<rotation>",
+	     "  Rotation:   x=%9.3f y=%9.3f   z=%9.3f  phi=%7.4f psi=%7.4f theta=%7.4f",
+	     r.x(), r.y(), r.z(), v->Phi(), v->Psi(), v->Theta());
+  }
+
+  /** Convert position objects
+   *
+   *    <position x="0.5" y="0"  z="0"/>     
+   */
+  template <> void Converter<position>::operator()(xml_h e) const {
+    xml_comp_t p(e);
+    Position* v = (Position*)param;
+    v->SetXYZ(p.x(), p.y(), p.z());
+    printout(INFO,"Alignment<position>","  Position:   x=%9.3f y=%9.3f   z=%9.3f",
+	     v->X(), v->Y(), v->Z());
+  }
+
+  /** Convert pivot objects
+   *
+   *    <pivot x="0.5" y="0"  z="0"/>     
+   */
+  template <> void Converter<pivot>::operator()(xml_h e) const {
+    xml_comp_t p(e);
+    double x,y,z;
+    Translation3D* v = (Translation3D*)param;
+    v->SetXYZ(x=p.x(), y=p.y(), z=p.z());
+    printout(INFO,"Alignment<pivot>","     Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
+  }
+
+  /** Convert transform3d objects
+   *
+   *     A generic alignment transformation is defined by
+   *     - a translation in 3D space identified in XML as a
+   *	   <position/> element
+   *	 - a rotation in 3D space around a pivot point specified in XML by
+   *	   2 elements: the <rotation/> and the <pivot/> element.
+   *	 The specification of any of the elements is optional:
+   *     - The absence of a translation implies the origine (0,0,0)
+   *     - The absence of a pivot point implies the origine (0,0,0)
+   *	 - The absence of a rotation implies the identity rotation.
+   *	   Any supplied pivot point in this case is ignored.
+   *
+   *	<xx>
+   *	  <position x="0" y="0"  z="0.0001*mm"/>
+   *	  <rotation x="0" y="0"  z="0"/>     
+   *	  <pivot    x="0" y="0"    z="100"/>     
+   *	</xx>
+   *
+   */
+  template <> void Converter<transform3d>::operator()(xml_h e) const {
+    typedef pair<bool,Transform3D> Data;
+    Position pos;
+    RotationZYX rot;
+    Translation3D piv;
+    xml_h child_rot, child_pos, child_piv;
+    Data* tr = (Data*)param;
+    
+    if ( (child_pos=e.child(_U(position),false)) )
+      Converter<position>(lcdd,&pos)(child_pos);
+    if ( (child_rot=e.child(_U(rotation),false)) )   {
+      Converter<rotation>(lcdd,&rot)(child_rot);
+      if ( (child_piv=e.child(_U(pivot),false)) )
+	Converter<pivot>(lcdd,&piv)(child_piv);
+    }
+    tr->first = true;
+    if ( child_rot && child_pos && child_piv )
+      tr->second = Transform3D(Translation3D(pos)*piv*rot*(piv.Inverse()));
+    else if ( child_rot && child_pos )
+      tr->second = Transform3D(rot,pos);
+    else if ( child_rot && child_piv )
+      tr->second = Transform3D(piv*rot*(piv.Inverse()));
+    else if ( child_rot )
+      tr->second = Transform3D(rot);
+    else if ( child_pos )
+      tr->second = Transform3D(pos);
+    else   {
+      tr->first  = false;
+    }
+  }
+
+  /** Convert volume objects
+   *
+   *	<volume subpath="layer4_0">
+   *	  <position x="0"   y="0"  z="0"/>
+   *	  <rotation x="0.5" y="0.1"  z="0.2"/>     
+   *	  <pivot    x="0" y="0"    z="100"/>
+   *      <volume>
+   *         ...
+   *      </volume>
+   *	</volume>
+   */
+  template <> void Converter<volume>::operator()(xml_h e) const {
+    pair<bool,Transform3D> trafo;
+    pair<DetElement,string>* elt = (pair<DetElement,string>*)param;
+    string subpath = e.attr<string>(_U(path));
+    bool   reset   = e.hasAttr(_U(reset)) ? e.attr<bool>(_U(reset)) : false;
+
+    printout(INFO,"Alignment<volume>","    path:%s / %s reset:%s",
+	     elt->first.path().c_str(),subpath.c_str(), reset ? "YES" : "NO");
+    Converter<transform3d>(lcdd,&trafo)(e);
+
+    pair<DetElement,string> vol_param(elt->first,subpath);
+    xml_coll_t(e,_U(volume)).for_each(Converter<volume>(lcdd,&vol_param));
+  }
+
+  /** Convert detelement objects
+   *
+   *    Function entry expects as a parameter a valid DetElement handle
+   *    pointing to the subdetector, which detector elements should be 
+   *    realigned.
+   *
+   *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
+   *      <position x="0"   y="0"  z="0"/>
+   *      <rotation x="0.5" y="0"  z="0"/>     
+   *	  <pivot    x="0" y="0"    z="100"/>     
+   *    </detelement>
+   */
+  template <> void Converter<detelement>::operator()(xml_h e) const {
+    xml_comp_t node(e);
+    string path = node.attr<string>(_U(path));
+    bool   check = node.hasAttr(_U(check_overlaps));
+    bool   overlap = node.hasAttr(_U(overlap));
+    bool   reset   = node.hasAttr(_U(reset)) ? node.attr<bool>(_U(reset)) : false;
+    DetElement det(param ? (TNamed*)param : 0);
+    DetElement elt  = DetectorTools::findElement(det,path);
+
+    if ( !elt.isValid() )   {
+      string err = "DD4hep: DetElement "+det.path()+" has no child:"+path+" [No such child]";
+      throw runtime_error(err);
+    }
+
+    string placementPath = elt.isValid() ? elt.placementPath() : string("-----");
+    printout(INFO,"Alignment<detelement>","path:%s [%s] placement:%s reset:%s",
+	     path.c_str(), 
+	     elt.isValid() ? elt.path().c_str() : "-----",
+	     placementPath.c_str(),
+	     reset ? "YES" : "NO");
+
+    if ( reset && elt.alignment().isValid() )   {
+      alignment_reset(det, placementPath, elt.alignment());
+    }
+
+    int sc = 0;
+    pair<bool,Transform3D> trafo;
+    Converter<transform3d>(lcdd,&trafo)(e);
+    if ( trafo.first )  {
+      DetectorAlignment alignment(elt);
+      // Need to care about optional arguments 'check_overlaps' and 'overlap'
+      if ( check && overlap )  {
+	bool   check_overlaps = node.attr<bool>(_U(check_overlaps));
+	double overlap = node.attr<double>(_U(overlap));
+	sc = alignment.align(trafo.second, check_overlaps, overlap);
+      }
+      else if ( check ) {
+	bool check_overlaps = node.attr<bool>(_U(check_overlaps));
+	sc = alignment.align(trafo.second, check_overlaps);
+      }
+      else  {
+	sc = alignment.align(trafo.second);
+      }
+      if ( !subDetectorAlignment(elt)->insert(alignment) )  {
+	// Error
+      }
+    }
+    pair<DetElement,string> vol_param(elt,"");
+    xml_coll_t(node,_U(volume)).for_each(Converter<volume>(lcdd,&vol_param));
+  }
+
+  /** Convert subdetector objects
+   *
+   *   <subdetector name="TPC">
+   *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
+   *      ...
+   *    </detelement>
+   *    ...
+   *    <include ref="file-name"/>
+   *    ...
+   *   </subdetector>
+   */
+  template <> void Converter<subdetector>::operator()(xml_h e) const {
+    xml_comp_t sd(e);
+    string path  = sd.nameStr();
+    bool   reset = sd.hasAttr(_U(reset)) ? sd.attr<bool>(_U(reset)) : false;
+    printout(INFO,"Alignment<subdetector>","name:%s reset:%s",
+	     path.c_str(), reset ? "YES" : "NO");
+    DetElement elt = DetectorTools::findElement(lcdd.world(),path);
+    if ( !elt.isValid() )   {
+      throw runtime_error("DD4hep: The subdetector "+path+" is not present [Invalid Handle]");
+    }
+    string placementPath = elt.placementPath();
+    if ( reset && elt.alignment().isValid() )   {
+      alignment_reset(elt, placementPath, elt.alignment());
+    }
+    xml_coll_t(sd,_U(detelement)).for_each(Converter<detelement>(lcdd,&elt));
+    xml_coll_t(sd,_U(include)).for_each(Converter<include_file>(lcdd,&elt));
+  }
+
+  /** Convert detelement_inlclude objects
+   *
+   *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
+   *      <position x="0"   y="0"  z="0"/>
+   *      <rotation x="0.5" y="0"  z="0"/>     
+   *    </detelement>
+   */
+  template <> void Converter<include_file>::operator()(xml_h element) const {
+    xml_h node = XML::DocumentHandler().load(element, element.attr_value(_U(ref))).root();
+    string tag = node.tag();
+    if ( tag == "alignment" )  {
+      Converter<alignment>(lcdd,param)(node);
+    }
+    else if ( tag == "subdetector" )  {
+      Converter<subdetector>(lcdd,param)(node);
+    }
+    else if ( tag == "detelement" )    {
+      Converter<detelement>(lcdd,0)(node);
+    }
+    else if ( tag == "subdetectors" )    {
+      xml_coll_t(node,_U(subdetector)).for_each(Converter<subdetector>(lcdd,param));
+    }
+    else if ( tag == "detelements" )    {
+      xml_coll_t(node,_U(detelement)).for_each(Converter<detelement>(lcdd,0));
+    }
+  }
+
+  template <> void Converter<alignment>::operator()(xml_h seq)  const  {
+    xml_elt_t compact(seq);
+    xml_coll_t(compact,_U(subdetectors)).for_each(_U(subdetector),Converter<subdetector>(lcdd,param));
+    xml_coll_t(compact,_U(include)).for_each(Converter<include_file>(lcdd,param));
+  }
+}
+
+static long setup_Alignment(lcdd_t& lcdd, const xml_h& e) {
+  TGeoManager* mgr = gGeoManager;
+  if ( 1 || e.hasAttr("print") )   {
+    TObjArray* pn = mgr->GetListOfPhysicalNodes();
+    TIter next(pn);
+    int count = 0;
+    typedef TGeoPhysicalNode PN;
+    for (PN *p=(PN*)next(); p; p=(PN*)next(), ++count) {
+      //p->Print();
+    }
+    printout(INFO,"Alignment","Found %d physical nodes registered to the geometyry manager",count);
+  }
+#if 0
+  if ( original_matrices.size() > 0 )  {
+    const NodeMap& nm = original_matrices;
+    for(NodeMap::const_iterator i=nm.begin(); i!=nm.end();++i)  {
+      cout << "Nodemap: " << (*i).first << endl;
+      //(*i).second->Print();
+    }
+    //mgr->UnlockGeometry();
+    //mgr->ClearPhysicalNodes(kTRUE);
+    //mgr->RefreshPhysicalNodes();
+    //return 1;
+  }
+#endif
+  (Converter<alignment>(lcdd))(e);
+  printout(INFO,"Alignment","Refreshing physical nodes....");
+  mgr->GetCurrentNavigator()->ResetAll();
+  mgr->GetCurrentNavigator()->BuildCache();
+  mgr->RefreshPhysicalNodes();
+  return 1;
+}
+DECLARE_XML_DOC_READER(alignment,setup_Alignment)
diff --git a/DDAlign/src/AlignmentStack.cpp b/DDAlign/src/AlignmentStack.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db5f3656c6454ccc21a067da969dcb5947a75366
--- /dev/null
+++ b/DDAlign/src/AlignmentStack.cpp
@@ -0,0 +1,213 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Objects.h"
+#include "DD4hep/Printout.h"
+#include "DDAlign/AlignmentStack.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+static AlignmentStack* s_alignStack = 0;
+
+
+/// Fully initializing constructor
+AlignmentStack::StackEntry::StackEntry(const DetElement& p, const std::string& placement, const Transform3D& t, double ov, int f)
+  : detector(p), transform(t), path(placement), overlap(ov), flag(f)
+{
+}
+
+/// Constructor with partial initialization
+AlignmentStack::StackEntry::StackEntry(DetElement element, bool rst, bool rst_children)
+  : detector(element), transform(), overlap(0.001), flag(0)
+{
+  if ( rst ) flag |= RESET_VALUE;
+  if ( rst_children ) flag |= RESET_CHILDREN;
+  if ( detector.isValid() ) path = detector.placementPath();
+}
+
+/// Constructor with partial initialization
+AlignmentStack::StackEntry::StackEntry(DetElement element, const Transform3D& trafo, bool rst, bool rst_children)
+  : detector(element), transform(trafo), overlap(0.001), flag(0)
+{
+  flag |= MATRIX_DEFINED;
+  if ( rst ) flag |= RESET_VALUE;
+  if ( rst_children ) flag |= RESET_CHILDREN;
+  if ( detector.isValid() ) path = detector.placementPath();
+}
+
+/// Constructor with partial initialization
+AlignmentStack::StackEntry::StackEntry(DetElement element, const Position& translation, bool rst, bool rst_children)
+: detector(element), transform(translation), overlap(0.001), flag(0)
+{
+  flag |= MATRIX_DEFINED;
+  if ( rst ) flag |= RESET_VALUE;
+  if ( rst_children ) flag |= RESET_CHILDREN;
+  if ( detector.isValid() ) path = detector.placementPath();
+}
+
+/// Constructor with partial initialization
+AlignmentStack::StackEntry::StackEntry(DetElement element, const RotationZYX& rot, bool rst, bool rst_children)
+: detector(element), transform(rot), overlap(0.001), flag(0)
+{
+  flag |= MATRIX_DEFINED;
+  if ( rst ) flag |= RESET_VALUE;
+  if ( rst_children ) flag |= RESET_CHILDREN;
+  if ( detector.isValid() ) path = detector.placementPath();
+}
+
+/// Constructor with partial initialization
+AlignmentStack::StackEntry::StackEntry(DetElement element, const Position& translation, const RotationZYX& rot, bool rst, bool rst_children) 
+  : detector(element), transform(rot,translation), overlap(0.001), flag(0)
+{
+  flag |= MATRIX_DEFINED;
+  if ( rst ) flag |= RESET_VALUE;
+  if ( rst_children ) flag |= RESET_CHILDREN;
+  if ( detector.isValid() ) path = detector.placementPath();
+}
+
+/// Copy constructor
+AlignmentStack::StackEntry::StackEntry(const StackEntry& e)
+: detector(e.detector), transform(e.transform), path(e.path), overlap(e.overlap), flag(e.flag)
+{
+}
+
+/// Attach transformation object
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::setTransformation(const Transform3D& trafo)   {
+  flag |= MATRIX_DEFINED;
+  transform = trafo;
+  return *this;
+}
+
+/// Instruct entry to ignore the transformation
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::clearTransformation()   {
+  flag &= ~MATRIX_DEFINED;
+  transform = Transform3D();
+  return *this;
+}
+
+/// Set flag to reset the entry to it's ideal geometrical position
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::setReset(bool new_value)   {
+  new_value ? (flag |= RESET_VALUE) : (flag &= ~RESET_VALUE);
+  return *this;
+}
+
+
+/// Set flag to reset the entry's children to their ideal geometrical position
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::setResetChildren(bool new_value)   {
+  new_value ? (flag |= RESET_CHILDREN) : (flag &= ~RESET_CHILDREN);
+  return *this;
+}
+
+
+/// Set flag to check overlaps
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::setOverlapCheck(bool new_value)   {
+  new_value ? (flag |= CHECKOVL_DEFINED) : (flag &= ~CHECKOVL_DEFINED);
+  return *this;
+}
+
+
+/// Set the precision for the overlap check (otherwise the default is 0.001 cm)
+AlignmentStack::StackEntry& AlignmentStack::StackEntry::setOverlapPrecision(double precision)   {
+  flag |= CHECKOVL_DEFINED;
+  flag |= CHECKOVL_VALUE;
+  overlap = precision;
+  return *this;
+}
+
+/// Default constructor
+AlignmentStack::AlignmentStack()
+{
+}
+
+/// Default destructor
+AlignmentStack::~AlignmentStack()   {
+  destroyObjects(m_stack)();
+}
+
+/// Static client accessor
+AlignmentStack& AlignmentStack::get()  {
+  if ( s_alignStack ) return *s_alignStack;
+  throw runtime_error("AlignmentStack> Stack not allocated -- may not be retrieved!");
+}
+
+/// Create an alignment stack instance. The creation of a second instance will be refused.
+void AlignmentStack::create()   {
+  if ( s_alignStack )   {
+    throw runtime_error("AlignmentStack> Stack already allocated. Multiple copies are not allowed!");
+  }
+  s_alignStack = new AlignmentStack();
+}
+
+/// Check existence of alignment stack
+bool AlignmentStack::exists()   {
+  return s_alignStack != 0;
+}
+
+/// Clear data content and remove the slignment stack
+void AlignmentStack::release()    {
+  if ( s_alignStack )  {
+    delete s_alignStack;
+    s_alignStack = 0;
+    return;
+  }
+  throw runtime_error("AlignmentStack> Attempt to delete non existing stack.");
+}
+
+/// Add a new entry to the cache. The key is the placement path
+bool AlignmentStack::insert(const std::string& full_path, StackEntry* entry)  {
+  if ( entry && !full_path.empty() )  {
+    entry->path = full_path;
+    return get().add(entry);
+  }
+  throw runtime_error("AlignmentStack> Attempt to apply an invalid alignment entry.");
+}
+
+/// Add a new entry to the cache. The key is the placement path
+bool AlignmentStack::insert(StackEntry* entry)  {
+  return get().add(entry);
+}
+
+/// Add a new entry to the cache. The key is the placement path
+bool AlignmentStack::add(StackEntry* entry)  {
+  if ( entry && !entry->path.empty() )  {
+    Stack::const_iterator i = m_stack.find(entry->path);
+    if ( i == m_stack.end() )   {
+      m_stack.insert(make_pair(entry->path,entry));
+      return true;
+    }
+    throw runtime_error("AlignmentStack> The entry with path "+entry->path+
+			" cannot be re-aligned twice in one transaction.");
+  }
+  throw runtime_error("AlignmentStack> Attempt to apply an invalid alignment entry.");
+}
+
+/// Retrieve an alignment entry of the current stack
+auto_ptr<AlignmentStack::StackEntry> AlignmentStack::pop()   {
+  Stack::iterator i = m_stack.begin();
+  if ( i != m_stack.end() )   {
+    StackEntry* e = (*i).second;
+    m_stack.erase(i);
+    return auto_ptr<StackEntry>(e);
+  }
+  throw runtime_error("AlignmentStack> Alignment stack is empty. "
+		      "Cannot pop entries - check size first!");
+}
+
+/// Get all pathes to be aligned
+vector<const AlignmentStack::StackEntry*> AlignmentStack::entries() const    {
+  vector<const StackEntry*> result;
+  result.reserve(m_stack.size());
+  for(Stack::const_iterator i=m_stack.begin(); i != m_stack.end(); ++i)
+    result.push_back((*i).second);
+  return result;
+}
+
diff --git a/DDAlign/src/AlignmentTags.cpp b/DDAlign/src/AlignmentTags.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6278743ab71ea9256f88f61326101a2788b17630
--- /dev/null
+++ b/DDAlign/src/AlignmentTags.cpp
@@ -0,0 +1,15 @@
+// $Id: XMLTags.h 889 2013-11-14 15:55:39Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "XML/XMLTags.h"
+
+// Define unicode tags
+#define UNICODE(x)  DECLARE_UNICODE_TAG(x)
+#include "DDAlign/AlignmentTags.h"
diff --git a/DDAlign/src/AlignmentWriter.cpp b/DDAlign/src/AlignmentWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a87c54894afc6cade3631f1eb763e3527df3f1b1
--- /dev/null
+++ b/DDAlign/src/AlignmentWriter.cpp
@@ -0,0 +1,176 @@
+// $Id: LCDDConverter.h 889 2013-11-14 15:55:39Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework includes
+#include "DDAlign/AlignmentWriter.h"
+
+#include "DD4hep/Printout.h"
+#include "DD4hep/MatrixHelpers.h"
+#include "DD4hep/DetectorTools.h"
+#include "DD4hep/DetFactoryHelper.h"
+#include "XML/DocumentHandler.h"
+#include "DDAlign/AlignmentTags.h"
+#include "DDAlign/AlignmentCache.h"
+#include "DDAlign/DetectorAlignment.h"
+
+#include "TGeoMatrix.h"
+
+// C/C++ include files
+#include <stdexcept>
+
+using namespace DD4hep::Geometry;
+using namespace DD4hep;
+using namespace std;
+
+/// Initializing Constructor
+AlignmentWriter::AlignmentWriter(LCDD& lcdd)
+  : m_lcdd(lcdd)
+{
+  m_cache = lcdd.extension<Geometry::AlignmentCache>();
+}
+
+/// Standard destructor
+AlignmentWriter::~AlignmentWriter()  {
+  if ( m_cache ) m_cache->release();
+}
+
+/// Create the element corresponding to one single detector element without children
+XML::Element AlignmentWriter::createElement(XML::Document doc, DetElement element)  const  {
+  XML::Element e(0), placement(0), elt = XML::Element(doc,_U(detelement));
+  string path = element.placementPath();
+  Alignment a = element.alignment();
+  DetectorAlignment det(element);
+  const vector<Alignment>& va = det.volumeAlignments();
+
+  elt.setAttr(_U(path),element.path());
+  if ( a.isValid() )  {
+    addNode(elt,a);
+  }
+  for(vector<Alignment>::const_iterator i=va.begin(); i!=va.end();++i)  {
+    e = XML::Element(doc,_U(volume));
+    e.setAttr(_U(path),(*i)->GetName());
+    addNode(e,*i);
+    elt.append(e);
+  }
+  return elt;
+}
+
+/// Add single alignment node to the XML document
+void AlignmentWriter::addNode(XML::Element elt, Alignment a)  const   {
+  TGeoNode* n = a->GetNode();
+  TGeoHMatrix mat(a->GetOriginalMatrix()->Inverse());
+  mat.Multiply(n->GetMatrix());
+  const Double_t* t = mat.GetTranslation();
+  XML::Element placement = XML::Element(elt.document(),_U(comment));
+  placement.setAttr(_U(placement),a->GetName());
+  elt.append(placement);
+
+  printout(INFO,"AlignmentWriter","Write Delta constants for %s",a->GetName());
+  //mat.Print();
+  if ( fabs(t[0]) > numeric_limits<double>::epsilon() ||
+       fabs(t[1]) > numeric_limits<double>::epsilon() ||
+       fabs(t[2]) > numeric_limits<double>::epsilon() )	{
+    XML::Element e = XML::Element(elt.document(),_U(position));
+    e.setAttr(_U(x),t[0]);
+    e.setAttr(_U(y),t[1]);
+    e.setAttr(_U(z),t[2]);
+    elt.append(e);
+  }
+  if ( mat.IsRotation() )  {
+    XYZAngles rot = _XYZangles(&mat);
+    if ( fabs(rot.X()) > numeric_limits<double>::epsilon() ||
+	 fabs(rot.Y()) > numeric_limits<double>::epsilon() ||
+	 fabs(rot.Z()) > numeric_limits<double>::epsilon() )	{
+	
+      XML::Element e = XML::Element(elt.document(),_U(rotation));
+      // Don't know why the angles have the wrong sign....
+      rot *= -1;
+      e.setAttr(_U(x),rot.X());
+      e.setAttr(_U(y),rot.Y());
+      e.setAttr(_U(z),rot.Z());
+      elt.append(e);
+    }
+  }
+}
+
+/// Scan a DetElement subtree and add on the fly the XML entries
+XML::Element AlignmentWriter::scan(XML::Document doc, DetElement element)  const  {
+  XML::Element elt(0);
+  if ( element.isValid() )   {
+    const DetElement::Children& c = element.children();
+    Alignment alignment = element.alignment();
+    if ( alignment.isValid() ) elt = createElement(doc,element);
+    for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i)   {
+      XML::Element daughter = scan(doc, (*i).second);
+      if ( daughter )   {
+	(elt ? (elt) : (elt=createElement(doc,element))).append(daughter);
+      }
+    }
+  }
+  return elt;
+}
+
+/// Dump the tree content into a XML document structure
+XML::Document AlignmentWriter::dump(DetElement top, bool enable_transactions)  const {
+  const char comment[] = "\n"
+    "      +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
+    "      ++++   DD4hep generated alignment file using the         ++++\n"
+    "      ++++   DD4hep Detector description XML generator.        ++++\n"
+    "      ++++                                                     ++++\n"
+    "      ++++   Parser:"
+    XML_IMPLEMENTATION_TYPE
+    "                ++++\n"
+    "      ++++                                                     ++++\n"
+    "      ++++                              M.Frank CERN/LHCb      ++++\n"
+    "      +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n  ";
+  XML::DocumentHandler docH;
+  XML::Document doc = docH.create("alignment", comment);
+  XML::Element elt(0), elements(0), root = doc.root();
+  root.append(elements = XML::Element(doc, _U(detelements)));
+  if ( enable_transactions ) root.append(XML::Element(doc,_U(open_transaction)));
+  if ( (elt=scan(doc,top)) ) elements.append(elt);
+  if ( enable_transactions ) root.append(XML::Element(doc,_U(close_transaction)));
+  return doc;
+}
+
+/// Write the XML document structure to a file.
+long AlignmentWriter::write(XML::Document doc, const string& output)   const {
+  XML::DocumentHandler docH;
+  return docH.output(doc, output);
+}
+
+static long create_alignment_file(LCDD& lcdd, int argc, char** argv)   {
+  DetElement top;
+  string output, path = "/world";
+  bool enable_transactions = false;
+  for(int i=1; i<argc;++i) {
+    if ( argv[i][0]=='-' || argv[i][0]=='/' ) {
+      const char* p = ::strchr(argv[i],'=');
+      if ( p && strncmp(argv[i]+1,"-output",7)==0 )
+        output = p+1;
+      else if ( p && strncmp(argv[i]+1,"-path",5)==0 )
+        path = p+1;
+      else if ( strncmp(argv[i]+1,"-transactions",5)==0 )
+        enable_transactions = true;
+      else
+	throw runtime_error("AlignmentWriter: Invalid argument:"+string(argv[i]));
+    }
+  }
+  printout(ALWAYS,"AlignmentWriter",
+	   "++++ Writing DD4hep alignment constants of the \"%s\" DetElement tree to file \"%s\"",
+	   path.c_str(), output.c_str());
+  top = DetectorTools::findElement(lcdd.world(),path);
+  if ( top.isValid() )   {
+    AlignmentWriter wr(lcdd);
+    return wr.write(wr.dump(top,enable_transactions), output);
+  }
+  throw runtime_error("AlignmentWriter: Invalid top level element name:"+path);  
+}
+
+DECLARE_APPLY(DDAlignmentWriter, create_alignment_file)
diff --git a/DDAlign/src/DetectorAlignment.cpp b/DDAlign/src/DetectorAlignment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..000a73072f0fe6f6c104ef47a09d7cf692d35e5a
--- /dev/null
+++ b/DDAlign/src/DetectorAlignment.cpp
@@ -0,0 +1,180 @@
+// $Id: Readout.cpp 985 2014-01-30 13:50:10Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#include "DDAlign/DetectorAlignment.h"
+#include "DD4hep/DetectorTools.h"
+#include "DD4hep/InstanceCount.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;
+
+typedef DetectorTools::ElementPath   ElementPath;
+typedef DetectorTools::PlacementPath PlacementPath;
+typedef vector<pair<int,DetElement> > LevelElements;
+namespace {
+
+  Alignment _align(const Alignment& a, TGeoHMatrix* transform, bool check, double overlap) {
+    TGeoPhysicalNode* n = a.ptr();
+    if ( n )  {
+      TGeoMatrix* mm = n->GetNode()->GetMatrix();
+      printout(INFO,"Alignment","DELTA matrix of %s",n->GetName());
+      transform->Print();
+      /*
+      printout(INFO,"Alignment","OLD matrix of %s",n->GetName());
+      mm->Print();
+      */
+      transform->MultiplyLeft(mm); // orig * delta
+      n->Align(transform, 0, check, overlap);
+      /*
+	printout(INFO,"Alignment","Apply new relative matrix  mother to daughter:");
+	transform->Print();
+	transform->MultiplyLeft(mm); // orig * delta
+	printout(INFO,"Alignment","With deltas %s ....",n->GetName());
+	transform->Print();
+	n->Align(transform, 0, check, overlap);
+	printout(INFO,"Alignment","NEW matrix of %s",n->GetName());
+	n->GetNode()->GetMatrix()->Print();
+
+	Position local, global = a.toGlobal(local);
+	cout << "Local:" << local << " Global: " << global 
+	     << " and back:" << a.globalToLocal(global) << endl;
+      */
+      return Alignment(n);
+    }
+    throw runtime_error("DD4hep: Cannot align non existing physical node. [Invalid Handle]");
+  }
+
+  Alignment& _alignment(const DetectorAlignment& det)  {
+    DetElement::Object& e = det._data();
+    if ( !e.alignment.isValid() )  {
+      string path = DetectorTools::placementPath(det);
+      //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;
+  }
+}
+
+/// 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);
+}
+
+/// Access to the alignment block
+Alignment DetectorAlignment::alignment() const   {
+  return _alignment(*this);
+}
+
+/// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
+std::vector<Alignment>& DetectorAlignment::volumeAlignments()  {
+  return _data().volume_alignments;
+}
+
+/// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
+const std::vector<Alignment>& DetectorAlignment::volumeAlignments() const   {
+  return _data().volume_alignments;
+}
+
+/// Align the PhysicalNode of the placement of the detector element (translation only)
+Alignment DetectorAlignment::align(const Position& pos, bool check, double overlap) {
+  return align(_transform(pos),check,overlap);
+}
+
+/// Align the PhysicalNode of the placement of the detector element (rotation only)
+Alignment DetectorAlignment::align(const RotationZYX& rot, bool check, double overlap) {
+  return align(_transform(rot),check,overlap);
+}
+
+/// Align the PhysicalNode of the placement of the detector element (translation + rotation)
+Alignment DetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool check, double overlap) {
+  return align(_transform(pos,rot),check,overlap);
+}
+
+/// Align the physical node according to a generic Transform3D
+Alignment DetectorAlignment::align(const Transform3D& transform, bool check, double overlap)  {
+  return align(_transform(transform),check,overlap);
+}
+
+/// Align the physical node according to a generic TGeo matrix
+Alignment DetectorAlignment::align(TGeoHMatrix* matrix, bool check, double overlap)  {
+  return _align(_alignment(*this),matrix,check,overlap);
+}
+
+/// Align the PhysicalNode of the placement of the detector element (translation only)
+Alignment DetectorAlignment::align(const string& path, const Position& pos, bool check, double overlap) {
+  return align(path,_transform(pos),check,overlap);
+}
+
+/// Align the PhysicalNode of the placement of the detector element (rotation only)
+Alignment DetectorAlignment::align(const string& path, const RotationZYX& rot, bool check, double overlap) {
+  return align(path,_transform(rot),check,overlap);
+}
+
+/// Align the PhysicalNode of the placement of the detector element (translation + rotation)
+Alignment DetectorAlignment::align(const string& path, const Position& pos, const RotationZYX& rot, bool check, double overlap) {
+  return align(path,_transform(pos,rot),check,overlap);
+}
+
+/// Align the physical node according to a generic Transform3D
+Alignment DetectorAlignment::align(const string& path, const Transform3D& transform, bool check, double overlap)  {
+  return align(path,_transform(transform),check,overlap);
+}
+
+/// Align the physical node according to a generic TGeo matrix
+Alignment DetectorAlignment::align(const string& path, TGeoHMatrix* matrix, bool check, double overlap)  {
+  if ( path.empty() )
+    return _align(_alignment(*this),matrix,check,overlap);
+  else if ( path == placementPath() )
+    return _align(_alignment(*this),matrix,check,overlap);
+  else if ( path[0] == '/' )   {
+    Alignment a(path);
+    volumeAlignments().push_back(a);
+    return _align(a,matrix,check,overlap);
+  }
+  Alignment a(placementPath()+'/'+path);
+  volumeAlignments().push_back(a);
+  return _align(a,matrix,check,overlap);
+}