From 74f0dc8b97a2bc9440d9fa86433837029b669699 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Wed, 21 Sep 2016 19:13:04 +0200
Subject: [PATCH] Add global alignment example

---
 DDAlign/include/DDAlign/AlignmentOperators.h  |   2 +-
 DDAlign/include/DDAlign/AlignmentStack.h      |  56 +++----
 DDAlign/include/DDAlign/AlignmentTags.h       |   1 +
 DDAlign/include/DDAlign/DetectorAlignment.h   |  77 ----------
 DDAlign/src/AlignmentOperators.cpp            |  85 ++++++-----
 DDAlign/src/AlignmentStack.cpp                |  95 ++----------
 DDAlign/src/AlignmentWriter.cpp               |   4 +-
 ...gnment.cpp => GlobalDetectorAlignment.cpp} |  98 +++++++-----
 DDAlign/src/plugins/AlignmentParser.cpp       | 142 ++++++++++--------
 DDCore/include/DD4hep/AlignmentData.h         |  27 +++-
 DDCore/include/DD4hep/GlobalAlignment.h       |   2 +-
 DDCore/include/XML/XMLElements.h              |   2 +
 DDCore/src/AlignmentData.cpp                  |   2 +-
 DDCore/src/XML/XMLElements.cpp                |  10 ++
 DDCore/src/plugins/StandardPlugins.cpp        |   4 +-
 UtilityApps/src/run_plugin.h                  |  18 ++-
 examples/AlignDet/CMakeLists.txt              |  32 +++-
 .../AlignDet/compact/AlephTPC_alignment.xml   |   5 +-
 examples/AlignDet/compact/AlephTPC_reset.xml  |   4 +-
 19 files changed, 298 insertions(+), 368 deletions(-)
 delete mode 100644 DDAlign/include/DDAlign/DetectorAlignment.h
 rename DDAlign/src/{DetectorAlignment.cpp => GlobalDetectorAlignment.cpp} (69%)

diff --git a/DDAlign/include/DDAlign/AlignmentOperators.h b/DDAlign/include/DDAlign/AlignmentOperators.h
index 596e108ab..9d6276c8a 100644
--- a/DDAlign/include/DDAlign/AlignmentOperators.h
+++ b/DDAlign/include/DDAlign/AlignmentOperators.h
@@ -43,7 +43,7 @@ namespace DD4hep {
       /// Initializing functor constructor
       AlignmentOperator(AlignmentCache& c, Nodes& n) : cache(c), nodes(n) {}
       /// Insert alignment entry
-      void insert(Alignment alignment)  const;
+      void insert(GlobalAlignment alignment)  const;
     };
 
     /// Select alignment operations according to certain criteria
diff --git a/DDAlign/include/DDAlign/AlignmentStack.h b/DDAlign/include/DDAlign/AlignmentStack.h
index 87be8a206..052d77960 100644
--- a/DDAlign/include/DDAlign/AlignmentStack.h
+++ b/DDAlign/include/DDAlign/AlignmentStack.h
@@ -15,7 +15,7 @@
 #define DD4HEP_ALIGNMENT_ALIGNMENTSTACK_H
 
 // Framework include files
-#include "DD4hep/Detector.h"
+#include "DD4hep/Alignments.h"
 #include "DD4hep/Objects.h"
 #include "DD4hep/Memory.h"
 
@@ -35,12 +35,12 @@ namespace DD4hep {
     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,
+        OVERLAP_DEFINED     = 1<<20,
+        MATRIX_DEFINED      = 1<<21,
+        CHECKOVL_DEFINED    = 1<<22,
+        CHECKOVL_VALUE      = 1<<23,
+        RESET_VALUE         = 1<<24,
+        RESET_CHILDREN      = 1<<25,
         ____LLLAST          = 1<<31
       } Flags;
 
@@ -52,28 +52,16 @@ namespace DD4hep {
        */
       struct StackEntry {
         /// Reference to the detector element
-        DetElement    detector;
-        /// 3-D Transformation matrix for the volume
-        Transform3D   transform;
+        DetElement        detector;
+        /// Delta transformation to be applied
+        Delta             delta;
         /// Path to the misaligned volume
-        std::string   path;
+        std::string       path;
         /// Parameter for overlap checking
-        double        overlap;
-        /// Flag containing various encodings
-        int           flag;
+        double            overlap;
 
         /// 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);
+        StackEntry(DetElement p, const std::string& placement, const Delta& t, double ov);
         /// Copy constructor
         StackEntry(const StackEntry& e);
         /// Default destructor
@@ -82,25 +70,19 @@ namespace DD4hep {
         /// Assignment operator
         StackEntry& operator=(const StackEntry& e);
 
-        /// Check a given flag
-        bool checkFlag(int mask) const {  return (flag&mask) == mask; }
         /// Check if the overlap flag checking is enabled
-        bool overlapDefined() const    {  return checkFlag(OVERLAP_DEFINED); }
+        bool overlapDefined() const    {  return delta.checkFlag(OVERLAP_DEFINED);  }
         /// Check if the overlap flag checking is enabled
-        bool checkOverlap() const      {  return checkFlag(CHECKOVL_DEFINED); }
+        bool checkOverlap() const      {  return delta.checkFlag(CHECKOVL_DEFINED); }
         /// Check if the overalp value is present
-        bool overlapValue() const      {  return checkFlag(CHECKOVL_VALUE); }
+        bool overlapValue() const      {  return delta.checkFlag(CHECKOVL_VALUE);   }
         /// Check if this alignment entry has a non unitary transformation matrix
-        bool hasMatrix() const         {  return checkFlag(MATRIX_DEFINED); }
+        bool hasMatrix() const         {  return delta.checkFlag(MATRIX_DEFINED);   }
         /// Check flag if the node location should be reset
-        bool needsReset() const        {  return checkFlag(RESET_VALUE); }
+        bool needsReset() const        {  return delta.checkFlag(RESET_VALUE);      }
         /// Check flag if the node location and all children should be reset
-        bool resetChildren() const     {  return checkFlag(RESET_CHILDREN); }
+        bool resetChildren() const     {  return delta.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
diff --git a/DDAlign/include/DDAlign/AlignmentTags.h b/DDAlign/include/DDAlign/AlignmentTags.h
index 44d295b8e..7287c19e9 100644
--- a/DDAlign/include/DDAlign/AlignmentTags.h
+++ b/DDAlign/include/DDAlign/AlignmentTags.h
@@ -42,6 +42,7 @@ namespace DD4hep {
     UNICODE(open_transaction);
     UNICODE(close_transaction);
     UNICODE(check_overlaps);
+    UNICODE(debug);
   }
 }
 
diff --git a/DDAlign/include/DDAlign/DetectorAlignment.h b/DDAlign/include/DDAlign/DetectorAlignment.h
deleted file mode 100644
index dad90f60a..000000000
--- a/DDAlign/include/DDAlign/DetectorAlignment.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// $Id: $
-//==========================================================================
-//  AIDA Detector description implementation for LCD
-//--------------------------------------------------------------------------
-// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
-// All rights reserved.
-//
-// For the licensing terms see $DD4hepINSTALL/LICENSE.
-// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
-//
-// Author     : M.Frank
-//
-//==========================================================================
-#ifndef DD4HEP_GEOMETRY_DETECTORALIGNMENT_H
-#define DD4HEP_GEOMETRY_DETECTORALIGNMENT_H
-
-// Framework include files
-#include "DD4hep/Detector.h"
-#include "DD4hep/GlobalAlignment.h"
-
-// Forward declarations
-class TGeoHMatrix;
-
-/// Namespace for the AIDA detector description toolkit
-namespace DD4hep {
-
-  /// Namespace for the geometry part of the AIDA detector description toolkit
-  namespace Alignments {
-
-    /// DetectorAlignment. DetElement Handle supporting alignment operations.
-    /**
-     *  \author   M.Frank
-     *  \version  1.0
-     *  \ingroup  DD4HEP_ALIGN
-     */
-    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
-      GlobalAlignment alignment() const;
-      /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
-      std::vector<GlobalAlignment>& volumeAlignments();
-      /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
-      const std::vector<GlobalAlignment>& volumeAlignments() const;
-
-      /** @DetElement alignment: Calls to align the detector element itself  */
-      /// Align the PhysicalNode of the placement of the detector element (translation only)
-      GlobalAlignment align(const Position& pos, bool check = false, double overlap = 0.001);
-      /// Align the PhysicalNode of the placement of the detector element (rotation only)
-      GlobalAlignment align(const RotationZYX& rot, bool check = false, double overlap = 0.001);
-      /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
-      GlobalAlignment align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001);
-      /// Align the physical node according to a generic Transform3D
-      GlobalAlignment align(const Transform3D& tr, bool check = false, double overlap = 0.001);
-      /// Align the physical node according to a generic TGeo matrix
-      GlobalAlignment 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)
-      GlobalAlignment 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)
-      GlobalAlignment 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)
-      GlobalAlignment 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
-      GlobalAlignment 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
-      GlobalAlignment align(const std::string& volume_path, TGeoHMatrix* matrix, bool check = false, double overlap = 0.001);
-    };
-
-  } /* End namespace Alignments                     */
-} /* End namespace DD4hep                           */
-#endif    /* DD4HEP_GEOMETRY_DETECTORALIGNMENT_H    */
diff --git a/DDAlign/src/AlignmentOperators.cpp b/DDAlign/src/AlignmentOperators.cpp
index a331152eb..f4fefaa3c 100644
--- a/DDAlign/src/AlignmentOperators.cpp
+++ b/DDAlign/src/AlignmentOperators.cpp
@@ -17,7 +17,7 @@
 #include "DD4hep/Printout.h"
 #include "DD4hep/objects/DetectorInterna.h"
 #include "DDAlign/AlignmentOperators.h"
-#include "DDAlign/DetectorAlignment.h"
+#include "DDAlign/GlobalDetectorAlignment.h"
 
 // C/C++ include files
 #include <stdexcept>
@@ -26,7 +26,7 @@ using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Alignments;
 
-void AlignmentOperator::insert(Alignment alignment)  const   {
+void AlignmentOperator::insert(GlobalAlignment alignment)  const   {
   if ( !cache.insert(alignment) )     {
     // Error
   }
@@ -74,7 +74,6 @@ template <> void AlignmentActor<DDAlign_standard_operations::node_delete>::opera
 
 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++) {
@@ -103,55 +102,55 @@ template <> void AlignmentActor<DDAlign_standard_operations::node_reset>::operat
 }
 
 template <> void AlignmentActor<DDAlign_standard_operations::node_align>::operator()(Nodes::value_type& n) const  {
-  Entry& e = *n.second.second;
-  bool       check = e.checkOverlap();
+  Entry&     e       = *n.second.second;
   bool       overlap = e.overlapDefined();
-  bool       has_matrix  = e.hasMatrix();
-  DetElement det = e.detector;
-  bool       valid     = det->global_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;
-  }
+  DetElement det     = e.detector;
 
-  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.overlapValue(), e.overlap)
-      : ad.align(e.path, e.transform, e.overlapValue(), e.overlap);
-  }
-  else if ( check )    {
-    alignment = is_not_volume
-      ? ad.align(e.transform, e.overlapValue())
-      : ad.align(e.path, e.transform, e.overlapValue());
+  if ( !det->global_alignment.isValid() && !e.hasMatrix() )  {
+    printout(WARNING,"AlignmentActor","++++ SKIP Alignment %s DE:%s Valid:%s Matrix:%s",
+             e.path.c_str(),det.placementPath().c_str(),
+             yes_no(det->global_alignment.isValid()), yes_no(e.hasMatrix()));
+    return;
   }
-  else     {
-    alignment = is_not_volume ? ad.align(e.transform) : ad.align(e.path, e.transform);
+  if ( GlobalDetectorAlignment::debug() )  {
+    printout(INFO,"AlignmentActor","++++ %s DE:%s Matrix:%s",
+             e.path.c_str(),det.placementPath().c_str(),yes_no(e.hasMatrix()));
   }
-  if ( alignment.isValid() )  {
-    insert(alignment);
+  // Need to care about optional arguments 'check_overlaps' and 'overlap'
+  GlobalDetectorAlignment ad(det);
+  GlobalAlignment   align;
+  Transform3D       trafo;
+  bool              no_vol  = e.path == det.placementPath();
+  double            ovl_val = e.overlapValue();
+  const Delta&      delta   = e.delta;
+
+  if ( delta.checkFlag(Delta::HAVE_ROTATION|Delta::HAVE_PIVOT|Delta::HAVE_TRANSLATION) )
+    trafo = Transform3D(Translation3D(delta.translation)*delta.pivot*delta.rotation*(delta.pivot.Inverse()));
+  else if ( delta.checkFlag(Delta::HAVE_ROTATION|Delta::HAVE_TRANSLATION) )
+    trafo = Transform3D(delta.rotation,delta.translation);
+  else if ( delta.checkFlag(Delta::HAVE_ROTATION|Delta::HAVE_PIVOT) )
+    trafo = Transform3D(delta.pivot*delta.rotation*(delta.pivot.Inverse()));
+  else if ( delta.checkFlag(Delta::HAVE_ROTATION) )
+    trafo = Transform3D(delta.rotation);
+  else if ( delta.checkFlag(Delta::HAVE_TRANSLATION) )
+    trafo = Transform3D(delta.translation);
+
+  if ( e.checkOverlap() && overlap )
+    align = no_vol ? ad.align(trafo,ovl_val,e.overlap) : ad.align(e.path,trafo,ovl_val,e.overlap);
+  else if ( e.checkOverlap() )
+    align = no_vol ? ad.align(trafo,ovl_val) : ad.align(e.path,trafo,ovl_val);
+  else
+    align = no_vol ? ad.align(trafo) : ad.align(e.path,trafo);
+
+  if ( align.isValid() )  {
+    insert(align);
     return;
   }
-  throw runtime_error("Failed to apply alignment for "+e.path);
+  except("AlignmentActor","Failed to apply alignment for "+e.path);
 }
 
 #if 0
-void alignment_reset_dbg(const string& path, const Alignment& a)   {
+void alignment_reset_dbg(const string& path, const GlobalAlignment& a)   {
   TGeoPhysicalNode* n = a.ptr();
   cout << " +++++++++++++++++++++++++++++++ " << path << endl;
   cout << "      +++++ Misaligned physical node: " << endl;
diff --git a/DDAlign/src/AlignmentStack.cpp b/DDAlign/src/AlignmentStack.cpp
index 74f3176de..ba51135fc 100644
--- a/DDAlign/src/AlignmentStack.cpp
+++ b/DDAlign/src/AlignmentStack.cpp
@@ -33,74 +33,16 @@ static dd4hep_ptr<AlignmentStack>& _stack(AlignmentStack* obj)  {
   return s;
 }
 
-/// Fully initializing constructor
-AlignmentStack::StackEntry::StackEntry(const DetElement& p, const string& placement, const Transform3D& t, double ov, int f)
-  : detector(p), transform(t), path(placement), overlap(ov), flag(f)
-{
-  InstanceCount::increment(this);
-}
-
-/// Constructor with partial initialization
-AlignmentStack::StackEntry::StackEntry(DetElement element, bool rst, bool rst_children)
-  : detector(element), transform(), overlap(0.001), flag(0)
-{
-  InstanceCount::increment(this);
-  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)
-{
-  InstanceCount::increment(this);
-  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)
-{
-  InstanceCount::increment(this);
-  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)
+AlignmentStack::StackEntry::StackEntry(DetElement element, const std::string& p, const Delta& del, double ov)
+  : detector(element), delta(del), path(p), overlap(ov)
 {
   InstanceCount::increment(this);
-  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)
-{
-  InstanceCount::increment(this);
-  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)
+  : detector(e.detector), delta(e.delta), path(e.path), overlap(e.overlap)
 {
   InstanceCount::increment(this);
 }
@@ -114,53 +56,38 @@ AlignmentStack::StackEntry::~StackEntry() {
 AlignmentStack::StackEntry& AlignmentStack::StackEntry::operator=(const StackEntry& e)   {
   if ( this != &e )  {
     detector = e.detector;
-    transform = e.transform;
-    overlap = e.overlap;
-    path = e.path;
-    flag = e.flag;
+    delta    = e.delta;
+    overlap  = e.overlap;
+    path     = e.path;
   }
   return *this;
 }
 
-/// 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);
+  new_value ? (delta.flags |= RESET_VALUE) : (delta.flags &= ~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);
+  new_value ? (delta.flags |= RESET_CHILDREN) : (delta.flags &= ~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);
+  new_value ? (delta.flags |= CHECKOVL_DEFINED) : (delta.flags &= ~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;
+  delta.flags |= CHECKOVL_DEFINED;
+  delta.flags |= CHECKOVL_VALUE;
   overlap = precision;
   return *this;
 }
diff --git a/DDAlign/src/AlignmentWriter.cpp b/DDAlign/src/AlignmentWriter.cpp
index d6d9cb032..e568a7f85 100644
--- a/DDAlign/src/AlignmentWriter.cpp
+++ b/DDAlign/src/AlignmentWriter.cpp
@@ -22,7 +22,7 @@
 #include "XML/DocumentHandler.h"
 #include "DDAlign/AlignmentTags.h"
 #include "DDAlign/AlignmentCache.h"
-#include "DDAlign/DetectorAlignment.h"
+#include "DDAlign/GlobalDetectorAlignment.h"
 
 #include "TGeoMatrix.h"
 
@@ -52,7 +52,7 @@ XML::Element AlignmentWriter::createElement(XML::Document doc, DetElement elemen
   XML::Element e(0), placement(0), elt = XML::Element(doc,_ALU(detelement));
   string path = element.placementPath();
   GlobalAlignment a = element->global_alignment;
-  DetectorAlignment det(element);
+  GlobalDetectorAlignment det(element);
   const vector<GlobalAlignment>& va = det.volumeAlignments();
 
   elt.setAttr(_ALU(path),element.path());
diff --git a/DDAlign/src/DetectorAlignment.cpp b/DDAlign/src/GlobalDetectorAlignment.cpp
similarity index 69%
rename from DDAlign/src/DetectorAlignment.cpp
rename to DDAlign/src/GlobalDetectorAlignment.cpp
index 7f0e60515..3e88e366e 100644
--- a/DDAlign/src/DetectorAlignment.cpp
+++ b/DDAlign/src/GlobalDetectorAlignment.cpp
@@ -13,7 +13,7 @@
 //==========================================================================
 
 // Framework include files
-#include "DDAlign/DetectorAlignment.h"
+#include "DDAlign/GlobalDetectorAlignment.h"
 #include "DD4hep/DetectorTools.h"
 #include "DD4hep/InstanceCount.h"
 #include "DD4hep/MatrixHelpers.h"
@@ -36,13 +36,16 @@ namespace DD4hep {
       GlobalAlignment global;
       std::vector<GlobalAlignment> volume_alignments;
     public:
-      GlobalAlignmentData() : NamedObject("","global-alignment") {}
-      virtual ~GlobalAlignmentData() {}
+      GlobalAlignmentData(const std::string& path) : NamedObject(path,"global-alignment") {
+        global = GlobalAlignment(path);
+      }
+      virtual ~GlobalAlignmentData() {
+        destroyHandle (global);
+      }
     };
   } /* End namespace Aligments               */
 } /* End namespace DD4hep                    */
 
-
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Alignments;
@@ -50,20 +53,30 @@ using namespace DD4hep::Alignments;
 namespace DetectorTools = DD4hep::Geometry::DetectorTools;
 typedef vector<pair<int,DetElement> > LevelElements;
 
+DD4HEP_INSTANTIATE_HANDLE_NAMED(GlobalAlignmentData);
+
+
 namespace {
 
+  static bool s_GlobalDetectorAlignment_debug = false;
+  
   GlobalAlignment _align(const GlobalAlignment& 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();
-      /*
+      bool dbg = GlobalDetectorAlignment::debug();
+      if ( dbg )  {
+        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);
+      if ( dbg )   {
+        printout(INFO,"Alignment","NEW matrix of %s",n->GetName());
+        n->GetNode()->GetMatrix()->Print();
+      }
       /*
         printout(INFO,"Alignment","Apply new relative matrix  mother to daughter:");
         transform->Print();
@@ -71,8 +84,6 @@ namespace {
         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
@@ -83,25 +94,20 @@ namespace {
     throw runtime_error("DD4hep: Cannot align non existing physical node. [Invalid Handle]");
   }
 
-  GlobalAlignment _alignment(const DetectorAlignment& det)  {
-    Ref_t gbl = det._data().global_alignment;
-    if ( gbl.isValid() )  {
-      Handle<GlobalAlignmentData> h(gbl);
-      return h->global;
-    }
-    throw runtime_error("DD4hep: Cannot access global alignment data. [Invalid Handle]");
-#if 0
+  GlobalAlignment _alignment(const GlobalDetectorAlignment& det)  {
     DetElement::Object& e = det._data();
-    if ( !e.alignment.isValid() )  {
+    if ( !e.global_alignment.isValid() )  {
       string path = DetectorTools::placementPath(det);
-      //cout << "Align path:" << path << endl;
-      e.alignment = GlobalAlignment(path);
+      e.global_alignment = Ref_t(new GlobalAlignmentData(path));
     }
-    return e.alignment;
-#endif    
+    Handle<GlobalAlignmentData> h(e.global_alignment);
+    if ( h.isValid() && h->global.isValid() )  {
+      return h->global;
+    }
+    throw runtime_error("DD4hep: Cannot access global alignment data. [Invalid Handle]");
   }
 
-  void _dumpParentElements(DetectorAlignment& det, LevelElements& elements)   {
+  void _dumpParentElements(GlobalDetectorAlignment& det, LevelElements& elements)   {
     int level = 0;
     DetectorTools::PlacementPath nodes;
     DetectorTools::ElementPath   det_nodes;
@@ -127,84 +133,94 @@ namespace {
   }
 }
 
-DD4HEP_INSTANTIATE_HANDLE_NAMED(GlobalAlignmentData);
-
 /// Initializing constructor
-DetectorAlignment::DetectorAlignment(DetElement e)
+GlobalDetectorAlignment::GlobalDetectorAlignment(DetElement e)
   : DetElement(e)
 {
 }
 
+/// Access debugging flag
+bool GlobalDetectorAlignment::debug()   {
+  return s_GlobalDetectorAlignment_debug;
+}
+
+/// Set debugging flag
+bool GlobalDetectorAlignment::debug(bool value)   {
+  bool tmp = s_GlobalDetectorAlignment_debug;
+  s_GlobalDetectorAlignment_debug = value;
+  return tmp;
+}
+
 /// Collect all placements from the detector element up to the world volume
-void DetectorAlignment::collectNodes(vector<PlacedVolume>& nodes)   {
+void GlobalDetectorAlignment::collectNodes(vector<PlacedVolume>& nodes)   {
   DetectorTools::placementPath(*this,nodes);
 }
 
 /// Access to the alignment block
-GlobalAlignment DetectorAlignment::alignment() const   {
+GlobalAlignment GlobalDetectorAlignment::alignment() const   {
   return _alignment(*this);
 }
 
 /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
-vector<GlobalAlignment>& DetectorAlignment::volumeAlignments()  {
+vector<GlobalAlignment>& GlobalDetectorAlignment::volumeAlignments()  {
   Handle<GlobalAlignmentData> h(_data().global_alignment);
   return h->volume_alignments;
 }
 
 /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
-const vector<GlobalAlignment>& DetectorAlignment::volumeAlignments() const   {
+const vector<GlobalAlignment>& GlobalDetectorAlignment::volumeAlignments() const   {
   Handle<GlobalAlignmentData> h(_data().global_alignment);
   return h->volume_alignments;
 }
 
 /// Align the PhysicalNode of the placement of the detector element (translation only)
-GlobalAlignment DetectorAlignment::align(const Position& pos, bool chk, double overlap) {
+GlobalAlignment GlobalDetectorAlignment::align(const Position& pos, bool chk, double overlap) {
   return align(Geometry::_transform(pos),chk,overlap);
 }
 
 /// Align the PhysicalNode of the placement of the detector element (rotation only)
-GlobalAlignment DetectorAlignment::align(const RotationZYX& rot, bool chk, double overlap) {
+GlobalAlignment GlobalDetectorAlignment::align(const RotationZYX& rot, bool chk, double overlap) {
   return align(Geometry::_transform(rot),chk,overlap);
 }
 
 /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
-GlobalAlignment DetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
+GlobalAlignment GlobalDetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
   return align(Geometry::_transform(pos,rot),chk,overlap);
 }
 
 /// Align the physical node according to a generic Transform3D
-GlobalAlignment DetectorAlignment::align(const Transform3D& transform, bool chk, double overlap)  {
+GlobalAlignment GlobalDetectorAlignment::align(const Transform3D& transform, bool chk, double overlap)  {
   return align(Geometry::_transform(transform),chk,overlap);
 }
 
 /// Align the physical node according to a generic TGeo matrix
-GlobalAlignment DetectorAlignment::align(TGeoHMatrix* matrix, bool chk, double overlap)  {
+GlobalAlignment GlobalDetectorAlignment::align(TGeoHMatrix* matrix, bool chk, double overlap)  {
   return _align(_alignment(*this),matrix,chk,overlap);
 }
 
 /// Align the PhysicalNode of the placement of the detector element (translation only)
-GlobalAlignment DetectorAlignment::align(const string& elt_path, const Position& pos, bool chk, double overlap) {
+GlobalAlignment GlobalDetectorAlignment::align(const string& elt_path, const Position& pos, bool chk, double overlap) {
   return align(elt_path,Geometry::_transform(pos),chk,overlap);
 }
 
 /// Align the PhysicalNode of the placement of the detector element (rotation only)
-GlobalAlignment DetectorAlignment::align(const string& elt_path, const RotationZYX& rot, bool chk, double overlap) {
+GlobalAlignment GlobalDetectorAlignment::align(const string& elt_path, const RotationZYX& rot, bool chk, double overlap) {
   return align(elt_path,Geometry::_transform(rot),chk,overlap);
 }
 
 /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
 GlobalAlignment 
-DetectorAlignment::align(const string& elt_path, const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
+GlobalDetectorAlignment::align(const string& elt_path, const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
   return align(elt_path,Geometry::_transform(pos,rot),chk,overlap);
 }
 
 /// Align the physical node according to a generic Transform3D
-GlobalAlignment DetectorAlignment::align(const string& elt_path, const Transform3D& transform, bool chk, double overlap)  {
+GlobalAlignment GlobalDetectorAlignment::align(const string& elt_path, const Transform3D& transform, bool chk, double overlap)  {
   return align(elt_path,Geometry::_transform(transform),chk,overlap);
 }
 
 /// Align the physical node according to a generic TGeo matrix
-GlobalAlignment DetectorAlignment::align(const string& elt_path, TGeoHMatrix* matrix, bool chk, double overlap)  {
+GlobalAlignment GlobalDetectorAlignment::align(const string& elt_path, TGeoHMatrix* matrix, bool chk, double overlap)  {
   if ( elt_path.empty() )
     return _align(_alignment(*this),matrix,chk,overlap);
   else if ( elt_path == placementPath() )
diff --git a/DDAlign/src/plugins/AlignmentParser.cpp b/DDAlign/src/plugins/AlignmentParser.cpp
index e0df8b57c..2bef0931d 100644
--- a/DDAlign/src/plugins/AlignmentParser.cpp
+++ b/DDAlign/src/plugins/AlignmentParser.cpp
@@ -14,6 +14,8 @@
 
 // Framework include files
 #include "DD4hep/LCDD.h"
+#include "DD4hep/Path.h"
+#include "DD4hep/Mutex.h"
 #include "DD4hep/Printout.h"
 #include "XML/Conversions.h"
 #include "XML/XMLElements.h"
@@ -25,6 +27,7 @@
 #include "DDAlign/AlignmentStack.h"
 #include "DDAlign/AlignmentCache.h"
 #include "DDAlign/AlignmentTransaction.h"
+#include "DDAlign/GlobalDetectorAlignment.h"
 
 // C/C++ include files
 #include <stdexcept>
@@ -41,14 +44,16 @@ namespace DD4hep  {
     class rotation;
     class position;
     class pivot;
-    class transform3d;
+    class delta;
+    class debug;
   }
 
   /// Forward declarations for all specialized converters
+  template <> void Converter<debug>::operator()(xml_h seq)  const;
   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<delta>::operator()(xml_h seq)  const;
 
   template <> void Converter<volume>::operator()(xml_h seq)  const;
   template <> void Converter<alignment>::operator()(xml_h seq)  const;
@@ -62,6 +67,11 @@ using namespace DD4hep::Alignments;
 using DD4hep::Geometry::Position;
 using DD4hep::Geometry::Translation3D;
 
+template <> void Converter<debug>::operator()(xml_h e) const {
+  bool value = e.attr<bool>(_U(value));
+  GlobalDetectorAlignment::debug(value);
+}
+
 /** Convert rotation objects
  *
  *    <rotation x="0.5" y="0"  z="0"/>
@@ -74,7 +84,7 @@ 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>",
+  printout(INFO,"Alignment<rot>",
            "  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());
 }
@@ -91,7 +101,7 @@ 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",
+  printout(INFO,"Alignment<pos>","  Position:   x=%9.3f y=%9.3f   z=%9.3f",
            v->X(), v->Y(), v->Z());
 }
 
@@ -108,10 +118,10 @@ template <> void Converter<pivot>::operator()(xml_h e) const {
   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);
+  printout(INFO,"Alignment<piv>","     Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
 }
 
-/** Convert transform3d objects
+/** Convert delta objects
  *
  *     A generic alignment transformation is defined by
  *     - a translation in 3D space identified in XML as a
@@ -134,35 +144,30 @@ template <> void Converter<pivot>::operator()(xml_h e) const {
  *  @version 1.0
  *  @date    01/04/2014
  */
-template <> void Converter<transform3d>::operator()(xml_h e) const {
-  typedef pair<bool,Transform3D> Data;
+template <> void Converter<delta>::operator()(xml_h e) const {
   Position pos;
   RotationZYX rot;
   Translation3D piv;
-  xml_h child_rot, child_pos, child_piv;
-  Data* tr = (Data*)param;
+  xml_h  child_rot, child_pos, child_piv;
+  Delta* delta = (Delta*)param;
 
   if ( (child_pos=e.child(_U(position),false)) )
-    Converter<position>(lcdd,&pos)(child_pos);
+    Converter<position>(lcdd,&delta->translation)(child_pos);
   if ( (child_rot=e.child(_U(rotation),false)) )   {
-    Converter<rotation>(lcdd,&rot)(child_rot);
+    Converter<rotation>(lcdd,&delta->rotation)(child_rot);
     if ( (child_piv=e.child(_U(pivot),false)) )
-      Converter<pivot>(lcdd,&piv)(child_piv);
+      Converter<pivot>(lcdd,&delta->pivot)(child_piv);
   }
-  tr->first = true;
   if ( child_rot && child_pos && child_piv )
-    tr->second = Transform3D(Translation3D(pos)*piv*rot*(piv.Inverse()));
+    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT|Delta::HAVE_TRANSLATION;
   else if ( child_rot && child_pos )
-    tr->second = Transform3D(rot,pos);
+    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_TRANSLATION;
   else if ( child_rot && child_piv )
-    tr->second = Transform3D(piv*rot*(piv.Inverse()));
+    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT;
   else if ( child_rot )
-    tr->second = Transform3D(rot);
+    delta->flags |= Delta::HAVE_ROTATION;
   else if ( child_pos )
-    tr->second = Transform3D(pos);
-  else   {
-    tr->first  = false;
-  }
+    delta->flags |= Delta::HAVE_TRANSLATION;
 }
 
 typedef AlignmentStack::StackEntry StackEntry;
@@ -183,31 +188,30 @@ typedef AlignmentStack::StackEntry StackEntry;
  *  @date    01/04/2014
  */
 template <> void Converter<volume>::operator()(xml_h e) const {
-  pair<bool,Transform3D> trafo;
+  Delta val;
   pair<DetElement,string>* elt = (pair<DetElement,string>*)param;
-  string subpath   = e.attr<string>(_ALU(path));
-  bool   reset     = e.hasAttr(_ALU(reset)) ? e.attr<bool>(_ALU(reset)) : true;
-  bool   reset_dau = e.hasAttr(_ALU(reset_children)) ? e.attr<bool>(_ALU(reset_children)) : true;
-  bool   check     = e.hasAttr(_ALU(check_overlaps));
-  bool   check_val = check ? e.attr<bool>(_ALU(check_overlaps)) : false;
-  bool   overlap   = e.hasAttr(_ALU(overlap));
-  double ovl       = overlap ? e.attr<double>(_ALU(overlap)) : 0.001;
-  string eltPlacement  = elt->first.placementPath();
-  string placementPath = subpath[0]=='/' ? subpath : eltPlacement + "/" + subpath;
+  string subpath    = e.attr<string>(_ALU(path));
+  bool   reset      = e.hasAttr(_ALU(reset)) ? e.attr<bool>(_ALU(reset)) : true;
+  bool   reset_dau  = e.hasAttr(_ALU(reset_children)) ? e.attr<bool>(_ALU(reset_children)) : true;
+  bool   check      = e.hasAttr(_ALU(check_overlaps));
+  bool   check_val  = check ? e.attr<bool>(_ALU(check_overlaps)) : false;
+  bool   overlap    = e.hasAttr(_ALU(overlap));
+  double ovl        = overlap ? e.attr<double>(_ALU(overlap)) : 0.001;
+  string elt_place  = elt->first.placementPath();
+  string placement  = subpath[0]=='/' ? subpath : elt_place + "/" + 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));
+  printout(INFO,"Alignment<vol>","    path:%s placement:%s reset:%s children:%s",
+           subpath.c_str(), placement.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;
+  Converter<delta>(lcdd,&val)(e);
+  if ( val.flags ) val.flags |= AlignmentStack::MATRIX_DEFINED;
+  if ( overlap   ) val.flags |= AlignmentStack::OVERLAP_DEFINED;
+  if ( reset     ) val.flags |= AlignmentStack::RESET_VALUE;
+  if ( reset_dau ) val.flags |= AlignmentStack::RESET_CHILDREN;
+  if ( check     ) val.flags |= AlignmentStack::CHECKOVL_DEFINED;
+  if ( check_val ) val.flags |= AlignmentStack::CHECKOVL_VALUE;
 
-  dd4hep_ptr<StackEntry> entry(new StackEntry(elt->first,placementPath,trafo.second,ovl,flags));
+  dd4hep_ptr<StackEntry> entry(new StackEntry(elt->first,placement,val,ovl));
   AlignmentStack::insert(entry);
   pair<DetElement,string> vol_param(elt->first,subpath);
   xml_coll_t(e,_U(volume)).for_each(Converter<volume>(lcdd,&vol_param));
@@ -239,33 +243,33 @@ template <> void Converter<detelement>::operator()(xml_h e) const {
   bool   overlap   = e.hasAttr(_ALU(overlap));
   double ovl       = overlap ? e.attr<double>(_ALU(overlap)) : 0.001;
   DetElement elt   = Geometry::DetectorTools::findDaughterElement(det,path);
-  string placementPath = elt.isValid() ? elt.placementPath() : string("-----");
+  string placement = elt.isValid() ? elt.placementPath() : string("-----");
 
   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 ( trafo.first )  {
-    flags |= AlignmentStack::MATRIX_DEFINED;
+  Delta val;
+  Converter<delta>(lcdd,&val)(e);
+  if ( val.flags )  {
+    val.flags |= AlignmentStack::MATRIX_DEFINED;
     reset = reset_dau = true;
   }
-  if ( overlap     ) flags |= AlignmentStack::OVERLAP_DEFINED;
-  if ( check       ) flags |= AlignmentStack::CHECKOVL_DEFINED;
-  if ( reset       ) flags |= AlignmentStack::RESET_VALUE;
-  if ( reset_dau   ) flags |= AlignmentStack::RESET_CHILDREN;
-  if ( check_val   ) flags |= AlignmentStack::CHECKOVL_VALUE;
+  if ( overlap     ) val.flags |= AlignmentStack::OVERLAP_DEFINED;
+  if ( check       ) val.flags |= AlignmentStack::CHECKOVL_DEFINED;
+  if ( reset       ) val.flags |= AlignmentStack::RESET_VALUE;
+  if ( reset_dau   ) val.flags |= AlignmentStack::RESET_CHILDREN;
+  if ( check_val   ) val.flags |= AlignmentStack::CHECKOVL_VALUE;
 
-  printout(INFO,"Alignment<detelement>","path:%s [%s] placement:%s matrix:%s reset:%s children:%s",
+  printout(INFO,"Alignment<det>","path:%s [%s] placement:%s matrix:%s reset:%s children:%s",
            path.c_str(),
            elt.isValid() ? elt.path().c_str() : "-----",
-           placementPath.c_str(),
-           yes_no(trafo.first), yes_no(reset), yes_no(reset_dau));
+           placement.c_str(),
+           yes_no(val.checkFlag(AlignmentStack::MATRIX_DEFINED)),
+           yes_no(reset), yes_no(reset_dau));
 
-  dd4hep_ptr<StackEntry> entry(new StackEntry(elt,placementPath,trafo.second,ovl,flags));
+  dd4hep_ptr<StackEntry> entry(new StackEntry(elt,placement,val,ovl));
   AlignmentStack::insert(entry);
 
   pair<DetElement,string> vol_param(elt,"");
@@ -316,6 +320,7 @@ template <> void Converter<alignment>::operator()(xml_h e)  const  {
 
   /// Now we process all allowed elements within the alignment tag:
   /// <detelement/>, <detelements/>, <subdetectors/> and <include/>
+  xml_coll_t(e,_ALU(debug)).for_each(Converter<debug>(lcdd,&top));
   xml_coll_t(e,_ALU(detelement)).for_each(Converter<detelement>(lcdd,&top));
   xml_coll_t(e,_ALU(detelements)).for_each(_ALU(detelement),Converter<detelement>(lcdd,&top));
   xml_coll_t(e,_ALU(subdetectors)).for_each(_ALU(detelement),Converter<detelement>(lcdd,&top));
@@ -328,13 +333,22 @@ template <> void Converter<alignment>::operator()(xml_h e)  const  {
  *  @version 1.0
  *  @date    01/04/2014
  */
-static long setup_Alignment(lcdd_t& lcdd, const xml_h& e) {
-  AlignmentCache::install(lcdd);
-  AlignmentTransaction tr(lcdd, e);
-  (DD4hep::Converter<DD4hep::alignment>(lcdd))(e);
+static long setup_Alignment(lcdd_t& lcdd, const xml_h& e) {{
+    static dd4hep_mutex_t s_mutex;
+    dd4hep_lock_t lock(s_mutex);
+    AlignmentCache::install(lcdd);
+    AlignmentTransaction tr(lcdd, e);
+    (DD4hep::Converter<DD4hep::alignment>(lcdd))(e);
+  }
+  if ( GlobalDetectorAlignment::debug() )  {
+    xml_elt_t elt(e);
+    Path uri = elt.document().uri();
+    printout(INFO,"GlobalAlignment","+++ Successfully parsed XML: %s",
+             uri.filename().c_str());
+  }
   return 1;
 }
-DECLARE_XML_DOC_READER(alignment,setup_Alignment)
+DECLARE_XML_DOC_READER(global_alignment,setup_Alignment)
 
 /** Basic entry point to install the alignment cache in a LCDD instance
  *
@@ -346,4 +360,4 @@ static long install_Alignment(lcdd_t& lcdd, int, char**) {
   AlignmentCache::install(lcdd);
   return 1;
 }
-DECLARE_APPLY(DD4hepAlignmentInstall,install_Alignment)
+DECLARE_APPLY(DD4hep_GlobalAlignmentInstall,install_Alignment)
diff --git a/DDCore/include/DD4hep/AlignmentData.h b/DDCore/include/DD4hep/AlignmentData.h
index 35af9d8ac..a8e762fce 100644
--- a/DDCore/include/DD4hep/AlignmentData.h
+++ b/DDCore/include/DD4hep/AlignmentData.h
@@ -50,8 +50,8 @@ namespace DD4hep {
     class Delta   {
     public:
       typedef Translation3D Pivot;
-      Pivot         pivot;
       Position      translation;
+      Pivot         pivot;
       RotationZYX   rotation;
       unsigned int  flags;
 
@@ -64,6 +64,21 @@ namespace DD4hep {
 
       /// Default constructor
       Delta() : flags(0) {}
+      /// Initializing constructor
+      Delta(const Position& tr)
+        : translation(tr), flags(HAVE_TRANSLATION) {}
+      /// Initializing constructor
+      Delta(const RotationZYX& rot)
+        : translation(), rotation(rot), flags(HAVE_ROTATION) {}
+      /// Initializing constructor
+      Delta(const Position& tr, const RotationZYX& rot)
+        : translation(tr), rotation(rot), flags(HAVE_ROTATION|HAVE_TRANSLATION) {}
+      /// Initializing constructor
+      Delta(const Translation3D& piv, const RotationZYX& rot)
+        : pivot(piv), rotation(rot), flags(HAVE_ROTATION|HAVE_PIVOT) {}
+      /// Initializing constructor
+      Delta(const Position& tr, const Translation3D& piv, const RotationZYX& rot)
+        : translation(tr), pivot(piv), rotation(rot), flags(HAVE_ROTATION|HAVE_PIVOT|HAVE_TRANSLATION) {}
       /// Copy constructor
       Delta(const Delta& c);
       /// Default destructor
@@ -72,12 +87,16 @@ namespace DD4hep {
       Delta& operator=(const Delta& c);
       /// Reset information to identity
       void clear();
+      /// Check a given flag
+      bool checkFlag(unsigned int mask) const {  return (flags&mask) == mask;        }
+      /// Check a given flag
+      void setFlag(unsigned int mask)         {  flags |= mask;                      }
       /// Access flags: Check if the delta operation contains a translation
-      bool hasTranslation() const  {  return (flags&HAVE_TRANSLATION) != 0; }
+      bool hasTranslation() const             {  return checkFlag(HAVE_TRANSLATION); }
       /// Access flags: Check if the delta operation contains a rotation
-      bool hasRotation() const     {  return (flags&HAVE_ROTATION) != 0;    }
+      bool hasRotation() const                {  return checkFlag(HAVE_ROTATION);    }
       /// Access flags: Check if the delta operation contains a pivot
-      bool hasPivot() const        {  return (flags&HAVE_PIVOT) != 0;       }
+      bool hasPivot() const                   {  return checkFlag(HAVE_PIVOT);       }
     };
 
     /// Derived condition data-object definition
diff --git a/DDCore/include/DD4hep/GlobalAlignment.h b/DDCore/include/DD4hep/GlobalAlignment.h
index 75cc59b90..95f065ca8 100644
--- a/DDCore/include/DD4hep/GlobalAlignment.h
+++ b/DDCore/include/DD4hep/GlobalAlignment.h
@@ -36,7 +36,7 @@ namespace DD4hep {
      *  \ingroup DD4HEP_GEOMETRY
      *  \ingroup DD4HEP_ALIGN
      */
-    class GlobalAlignment: public Handle<TGeoPhysicalNode> {
+    class GlobalAlignment : public Handle<TGeoPhysicalNode> {
 
       typedef Geometry::RotationZYX RotationZYX;
       typedef Geometry::Transform3D Transform3D;
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index 979fbd825..5bd36037c 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -637,6 +637,8 @@ namespace DD4hep {
       Handle_t createElt(const XmlChar* tag) const;
       /// Clone a DOM element / sub-tree
       Handle_t clone(Handle_t source) const;
+      /// Acces the document URI
+      std::string uri() const;
     };
 
     /// Class supporting the basic functionality of an XML document including ownership
diff --git a/DDCore/src/AlignmentData.cpp b/DDCore/src/AlignmentData.cpp
index dc7c1b28d..6319fece5 100644
--- a/DDCore/src/AlignmentData.cpp
+++ b/DDCore/src/AlignmentData.cpp
@@ -27,7 +27,7 @@ using namespace DD4hep::Alignments;
 
 /// Copy constructor
 Delta::Delta(const Delta& c)
-  : pivot(c.pivot), translation(c.translation), rotation(c.rotation), flags(c.flags)
+  : translation(c.translation), pivot(c.pivot), rotation(c.rotation), flags(c.flags)
 {
 }
 
diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp
index efccaf202..d2ed4bd35 100644
--- a/DDCore/src/XML/XMLElements.cpp
+++ b/DDCore/src/XML/XMLElements.cpp
@@ -63,6 +63,7 @@ namespace {
 #define appendChild         LinkEndChild
 #define getOwnerDocument    GetDocument
 #define getDocumentElement  RootElement
+#define getDocumentURI      Value
 
 /// Union to ease castless object access in TinyXML
 union Xml {
@@ -1034,6 +1035,15 @@ Handle_t Document::root() const {
   throw runtime_error("Document::root: Invalid handle!");
 }
 
+/// Acces the document URI
+std::string Document::uri() const   {
+  if (m_doc)   {
+    Tag_t val(_D(m_doc)->getDocumentURI());
+    return val;
+  }
+  throw runtime_error("Document::uri: Invalid handle!");
+}
+
 /// Assign new document. Old document is dropped.
 DocumentHolder& DocumentHolder::assign(DOC d)   {
   if (m_doc)   {
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index ab71e35c5..ea1b822b7 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -35,7 +35,9 @@ using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
 static LCDDBuildType build_type(const char* value)   {
-  if ( strcmp(value,"BUILD_DEFAULT")==0 )
+  if ( !value )
+    return BUILD_DEFAULT;
+  else if ( strcmp(value,"BUILD_DEFAULT")==0 )
     return BUILD_DEFAULT;
   else if ( strcmp(value,"BUILD_SIMU")==0 )
     return BUILD_SIMU;
diff --git a/UtilityApps/src/run_plugin.h b/UtilityApps/src/run_plugin.h
index c7582adab..f276af34e 100644
--- a/UtilityApps/src/run_plugin.h
+++ b/UtilityApps/src/run_plugin.h
@@ -91,8 +91,7 @@ namespace {
       "                                    The lower the level, the more printout...      \n"
       "        -plugin <name> <args>       Execute plugin <name> after loading geometry.  \n"
       "                                    All arguments following until the next '-'     \n"
-      "                                    are considered as arguments to the plugin.     \n"
-      " ";
+      "                                    are considered as arguments to the plugin.     \n";
     return cout;
   }
 
@@ -138,6 +137,8 @@ namespace {
       }
       else if ( strncmp(argv[i],"-load_only",5)==0 )
         dry_run = true;
+      else if ( strncmp(argv[i],"-dry-run",5)==0 )
+        dry_run = true;
       else if ( strncmp(argv[i],"-print",4)==0 )
         DD4hep::setPrintLevel(DD4hep::PrintLevel(print = decodePrintLevel(argv[++i])));
       else if ( strncmp(argv[i],"-destroy",5)==0 )
@@ -174,20 +175,23 @@ namespace {
       long result;
       for(size_t i=0; i<plugins.size(); ++i)   {
         std::vector<const char*>& plug=plugins[i];
-        result = run_plugin(lcdd,plug[0],plug.size()-1,(char**)(plug.size()>1 ? &plug[1] : 0));
+        // Remove plugin name and trailing 0x0 from args.
+        size_t num_args = plug.size()>2 ? plug.size()-2 : 0;
+
+        result = run_plugin(lcdd,plug[0],plug.size()-1,(char**)(num_args>0 ? &plug[1] : 0));
         if ( result == EINVAL )   {
           cout << "FAILED to execute DD4hep plugin: '" << plug[0] 
-               << "' with args (" << (plug.size()-1) << ") :[ ";
+               << "' with args (" << num_args << ") :[ ";
           for(size_t j=1; j<plug.size(); ++j)   {
-            cout << plug[j] << " ";
+            if ( plug[j] ) cout << plug[j] << " ";
           }
           cout << "]" << endl;
           usage_default(name);
         }
         cout << "Executed DD4hep plugin: '" << plug[0]
-             << "' with args (" << (plug.size()-1) << ") :[ ";
+             << "' with args (" << num_args << ") :[ ";
         for(size_t j=1; j<plug.size(); ++j)   {
-          cout << plug[j] << " ";
+          if ( plug[j] ) cout << plug[j] << " ";
         }
         cout << "]" << endl;
       }
diff --git a/examples/AlignDet/CMakeLists.txt b/examples/AlignDet/CMakeLists.txt
index b83229baa..d07c95a26 100644
--- a/examples/AlignDet/CMakeLists.txt
+++ b/examples/AlignDet/CMakeLists.txt
@@ -12,7 +12,7 @@
 cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
 include ( ${DD4hep_DIR}/cmake/DD4hep.cmake )
 
-#-----------------------------------------------------------------------------------
+#--------------------------------------------------------------------------
 dd4hep_configure_output()
 dd4hep_package ( AlignDet MAJOR 0 MINOR 0 PATCH 1
   USES           [ROOT   REQUIRED COMPONENTS Geom GenVector MathCore] 
@@ -24,3 +24,33 @@ dd4hep_package ( AlignDet MAJOR 0 MINOR 0 PATCH 1
 dd4hep_add_plugin( AlignDet SOURCES src/*.cpp  )
 dd4hep_install_dir( compact DESTINATION examples/AlignDet )
 dd4hep_configure_scripts( AlignDet DEFAULT_SETUP WITH_TESTS)
+
+#
+#---Testing: Load ALEPH TPC geometry --------------------------------------
+dd4hep_add_test_reg( test_DetAlign_AlephTPC_load
+  COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_AlignDet.sh"
+  EXEC_ARGS  geoPluginRun
+             -input file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC.xml
+             -destroy -no-interpreter -plugin DD4hep_GlobalAlignmentInstall
+  REGEX_PASS "189 nodes/ 23 volume UID's in LCDD Geometry" )
+#
+#---Testing: Load and misalign ALEPH TPC geometry -------------------------
+dd4hep_add_test_reg( test_DetAlign_Global_AlephTPC_align
+  COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_AlignDet.sh"
+  EXEC_ARGS  geoPluginRun
+             -input file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC.xml
+             -destroy -no-interpreter
+             -plugin DD4hep_GlobalAlignmentInstall
+             -plugin DD4hepXMLLoader file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC_alignment.xml BUILD_DEFAULT
+  REGEX_PASS "Successfully parsed XML: AlephTPC_alignment.xml")
+#
+#---Testing: Load and misalign ALEPH TPC geometry -------------------------
+dd4hep_add_test_reg( test_DetAlign_Global_AlephTPC_reset
+  COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_AlignDet.sh"
+  EXEC_ARGS  geoPluginRun
+             -input file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC.xml
+             -destroy -no-interpreter
+             -plugin DD4hep_GlobalAlignmentInstall
+             -plugin DD4hepXMLLoader file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC_alignment.xml
+             -plugin DD4hepXMLLoader file:${CMAKE_CURRENT_SOURCE_DIR}/compact/AlephTPC_reset.xml
+  REGEX_PASS "Successfully parsed XML: AlephTPC_reset.xml" )
diff --git a/examples/AlignDet/compact/AlephTPC_alignment.xml b/examples/AlignDet/compact/AlephTPC_alignment.xml
index c7181f69d..d8bff42d4 100644
--- a/examples/AlignDet/compact/AlephTPC_alignment.xml
+++ b/examples/AlignDet/compact/AlephTPC_alignment.xml
@@ -1,5 +1,6 @@
-<alignment>
+<global_alignment>
 
+  <debug value="true"/>
   <open_transaction/>
   <subdetectors>
     <!--
@@ -76,4 +77,4 @@ Any supplied pivot point in this case is ignored.
   </subdetectors>
 
   <close_transaction/>
-</alignment>
+</global_alignment>
diff --git a/examples/AlignDet/compact/AlephTPC_reset.xml b/examples/AlignDet/compact/AlephTPC_reset.xml
index ed5d594c0..98ea4111b 100644
--- a/examples/AlignDet/compact/AlephTPC_reset.xml
+++ b/examples/AlignDet/compact/AlephTPC_reset.xml
@@ -1,4 +1,4 @@
-<alignment print="true">
+<global_alignment print="true">
   <open_transaction/>
   <subdetectors>
     <!--
@@ -23,4 +23,4 @@
     </detelement>
   </subdetectors>
   <close_transaction/>
-</alignment>
+</global_alignment>
-- 
GitLab