From 350e27b99ca6b1a2c7cd70e93005a830f4747027 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Fri, 25 Apr 2014 08:15:20 +0000
Subject: [PATCH] Please see doc/release.notes for changes

---
 DDAlign/CMakeLists.txt                        |  6 +-
 DDAlign/include/DDAlign/AlignmentStack.h      | 37 ++++++--
 .../include/DDAlign/AlignmentTransaction.h    | 55 ++++++++++++
 DDAlign/src/AlignmentCache.cpp                | 84 +++++++++++--------
 DDAlign/src/AlignmentOperators.cpp            | 12 +--
 DDAlign/src/AlignmentParser.cpp               | 68 +++++----------
 DDAlign/src/AlignmentStack.cpp                | 72 ++++++++++++----
 DDAlign/src/AlignmentTransaction.cpp          | 36 ++++++++
 DDAlign/src/AlignmentWriter.cpp               |  2 +-
 DDAlign/src/DetectorAlignment.cpp             |  5 +-
 10 files changed, 256 insertions(+), 121 deletions(-)
 create mode 100644 DDAlign/include/DDAlign/AlignmentTransaction.h
 create mode 100644 DDAlign/src/AlignmentTransaction.cpp

diff --git a/DDAlign/CMakeLists.txt b/DDAlign/CMakeLists.txt
index 2313286bb..1d5b10ae6 100644
--- a/DDAlign/CMakeLists.txt
+++ b/DDAlign/CMakeLists.txt
@@ -9,14 +9,16 @@ include( DD4hep )
 
 find_package( ROOT REQUIRED )
 #---Includedirs ------------------------------------------------------------------
-include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include
+include_directories(${CMAKE_SOURCE_DIR}/DDCore/include
+	            ${CMAKE_SOURCE_DIR}/DDSegmentation/include	
+                    ${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})
+target_link_libraries(DD4hepAlign DD4hepCore ${ROOT_LIBRARIES})
 SET( CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-long-long")
 if(DD4HEP_USE_XERCESC)
   add_definitions(-DDD4HEP_USE_XERCESC)
diff --git a/DDAlign/include/DDAlign/AlignmentStack.h b/DDAlign/include/DDAlign/AlignmentStack.h
index 87bb31011..e90486983 100644
--- a/DDAlign/include/DDAlign/AlignmentStack.h
+++ b/DDAlign/include/DDAlign/AlignmentStack.h
@@ -34,6 +34,9 @@ namespace DD4hep {
      */
     class AlignmentStack  {
     public:
+
+      friend class std::auto_ptr<AlignmentStack>;
+
       enum {
 	OVERLAP_DEFINED     = 1<<0,
 	MATRIX_DEFINED      = 1<<1,
@@ -45,10 +48,15 @@ namespace DD4hep {
       } Flags;
 
       struct StackEntry {
+	/// Reference to the detector element
 	DetElement    detector;
+	/// 3-D Transformation matrix for the volume
 	Transform3D   transform;
+	/// Path to the misaligned volume
 	std::string   path;
+	/// Parameter for overlap checking
 	double        overlap;
+	/// Flag containing various encodings
 	int           flag;
 
 	/// Fully initializing constructor
@@ -66,13 +74,24 @@ namespace DD4hep {
 	/// Copy constructor
 	StackEntry(const StackEntry& e);
 	/// Default destructor
-	~StackEntry() {}
+	virtual ~StackEntry();
+
+	/// Assignment operator
+	StackEntry& operator=(const StackEntry& e);
+
+	/// Check a given flag
 	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); }
+	/// Check if the overlap flag checking is enabled
+	bool overlapDefined() const    {  return checkFlag(OVERLAP_DEFINED); }
+	/// Check if the overlap flag checking is enabled
+	bool checkOverlap() const      {  return checkFlag(CHECKOVL_DEFINED); }
+	/// Check if the overalp value is present
+	bool overlapValue() const      {  return checkFlag(CHECKOVL_VALUE); }
+	/// Check if this alignment entry has a non unitary transformation matrix
 	bool hasMatrix() const         {  return checkFlag(MATRIX_DEFINED); }
+	/// Check flag if the node location should be reset
 	bool needsReset() const        {  return checkFlag(RESET_VALUE); }
+	/// Check flag if the node location and all children should be reset
 	bool resetChildren() const     {  return checkFlag(RESET_CHILDREN); }
 
 	/// Attach transformation object
@@ -96,11 +115,11 @@ namespace DD4hep {
 
       /// Default constructor
       AlignmentStack();
+      /// Default destructor. Careful with this one: 
+      virtual ~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.
@@ -108,15 +127,15 @@ namespace DD4hep {
       /// 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);
+      static bool insert(const std::string& full_path, std::auto_ptr<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);
+      static bool insert(std::auto_ptr<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);
+      bool add(std::auto_ptr<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!
diff --git a/DDAlign/include/DDAlign/AlignmentTransaction.h b/DDAlign/include/DDAlign/AlignmentTransaction.h
new file mode 100644
index 000000000..2be31da31
--- /dev/null
+++ b/DDAlign/include/DDAlign/AlignmentTransaction.h
@@ -0,0 +1,55 @@
+// $Id: Geant4Setup.cpp 578 2013-05-17 22:33:09Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_ALIGNMENT_ALIGNMENTTRANSACTION_H
+#define DD4HEP_ALIGNMENT_ALIGNMENTTRANSACTION_H
+
+// Framework include files
+#include "DD4hep/Primitives.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  namespace XML { class Handle_t; }
+
+  /*
+   *   Alignment namespace declaration
+   */
+  namespace Geometry {
+
+    // Forward declarations
+    class LCDD;
+    class AlignmentCache;
+
+    /** @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& lcdd;
+      /// Reference to the alignment cache
+      AlignmentCache* m_cache;
+      
+      /// Default constructor
+      AlignmentTransaction(LCDD& l, const XML::Handle_t& e);
+      /// Default destructor
+      ~AlignmentTransaction();
+    };
+
+  } /* End namespace Geometry        */
+} /* End namespace DD4hep            */
+#endif    /* DD4HEP_ALIGNMENT_ALIGNMENTTRANSACTION_H       */
diff --git a/DDAlign/src/AlignmentCache.cpp b/DDAlign/src/AlignmentCache.cpp
index 49b39b5cd..7c6933f27 100644
--- a/DDAlign/src/AlignmentCache.cpp
+++ b/DDAlign/src/AlignmentCache.cpp
@@ -12,37 +12,18 @@
 #include "DD4hep/DetectorTools.h"
 #include "DDAlign/AlignmentCache.h"
 #include "DDAlign/AlignmentOperators.h"
+#include "DD4hep/objects/DetectorInterna.h"
+#include "DD4hep/objects/ConditionsInterna.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());
@@ -56,7 +37,7 @@ DetElement _detector(DetElement child)   {
 }
 
 /// Default constructor
-AlignmentCache::AlignmentCache(LCDD& lcdd, const std::string& sdPath, bool top)
+AlignmentCache::AlignmentCache(LCDD& lcdd, const string& sdPath, bool top)
   : m_lcdd(lcdd), m_sdPath(sdPath), m_sdPathLen(sdPath.length()), m_refCount(1), m_top(top)
 {
 }
@@ -101,7 +82,7 @@ bool AlignmentCache::insert(Alignment alignment)  {
 }
 
 /// Retrieve the cache section corresponding to the path of an entry.
-AlignmentCache* AlignmentCache::section(const std::string& path_name) const   {
+AlignmentCache* AlignmentCache::section(const string& path_name) const   {
   size_t idx, idq;
   if ( path_name[0] != '/' )   {
     return section(m_lcdd.world().placementPath()+'/'+path_name);
@@ -118,8 +99,8 @@ AlignmentCache* AlignmentCache::section(const std::string& path_name) const   {
   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   {
+/// Retrieve an alignment entry by its placement path
+Alignment AlignmentCache::get(const 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);
@@ -184,11 +165,7 @@ void AlignmentCache::closeTransaction()   {
     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>",
@@ -211,7 +188,7 @@ void AlignmentCache::uninstall(LCDD& lcdd)   {
 }
 
 /// Retrieve branch cache by name. If not present it will be created
-AlignmentCache* AlignmentCache::subdetectorAlignments(const std::string& name)    {
+AlignmentCache* AlignmentCache::subdetectorAlignments(const string& name)    {
   SubdetectorAlignments::const_iterator i = m_detectors.find(name);
   if ( i == m_detectors.end() )   {
     AlignmentCache* ptr = new AlignmentCache(m_lcdd,name,false);
@@ -223,25 +200,60 @@ AlignmentCache* AlignmentCache::subdetectorAlignments(const std::string& name)
 
 /// 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;
+  typedef map<string,DetElement> DetElementUpdates;
+  typedef map<DetElement,vector<Entry*> > sd_entries_t;
+  TGeoManager& mgr = m_lcdd.manager();
+  DetElementUpdates detelt_updates;
+  sd_entries_t all, highest;
+
   while(stack.size() > 0)    {
     Entry* e = stack.pop().release();
     DetElement det = _detector(e->detector);
-    all[det.ptr()].push_back(e);
+    all[det].push_back(e);
+    if ( e->hasMatrix() || e->needsReset() || e->resetChildren() )  {
+      detelt_updates.insert(make_pair(e->detector.path(),e->detector));
+    }
   }
   for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i)  {
-    DetElement det(Ref_t((*i).first));
+    DetElement det((*i).first);
     AlignmentCache* sd_cache = subdetectorAlignments(det.placement().name());
     sd_cache->apply( (*i).second );
     (*i).second.clear();
   }
-}
 
+  printout(INFO,"AlignmentCache","Alignments were applied. Refreshing physical nodes....");
+  mgr.GetCurrentNavigator()->ResetAll();
+  mgr.GetCurrentNavigator()->BuildCache();
+  mgr.RefreshPhysicalNodes();
+
+  // Provide update callback for every detector element with a changed placement
+  for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i)  {
+    DetElement elt((*i).second);
+    printout(DEBUG,"AlignmentCache","+++ Trigger placement update for %s [2]",elt.path().c_str());
+    elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_ELEMENT,elt.ptr());
+  }
+  // Provide update callback for the highest detector element
+  string last_path = "?????";
+  for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i)  {
+    const string& path = (*i).first;
+    if ( path.find(last_path) == string::npos )  {
+      DetElement elt((*i).second);
+      printout(DEBUG,"AlignmentCache","+++ Trigger placement update for %s [1]",elt.path().c_str());
+      elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_HIGHEST,elt.ptr());
+      last_path = (*i).first;
+    }
+  }
+  // Provide update callback at the detector level
+  for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i)  {
+    DetElement elt((*i).first);
+    printout(DEBUG,"AlignmentCache","+++ Trigger placement update for %s [0]",elt.path().c_str());
+    elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_DETECTOR,elt.ptr());
+  }
+}
 
 /// 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 map<string,pair<TGeoPhysicalNode*,Entry*> > Nodes;
   typedef vector<Entry*> Changes;
   Nodes nodes;
 
diff --git a/DDAlign/src/AlignmentOperators.cpp b/DDAlign/src/AlignmentOperators.cpp
index fe73c627d..4c6a818e4 100644
--- a/DDAlign/src/AlignmentOperators.cpp
+++ b/DDAlign/src/AlignmentOperators.cpp
@@ -97,8 +97,8 @@ 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.checkOverflow();
-  bool overlap = e.checkOverlap();
+  bool check = e.checkOverlap();
+  bool overlap = e.overlapDefined();
   bool has_matrix  = e.hasMatrix();
   DetElement det = e.detector;
   bool valid = det.alignment().isValid();
@@ -125,13 +125,13 @@ template <> void AlignmentActor<DDAlign_standard_operations::node_align>::operat
   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);
+      ? 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.overflowValue())
-      : ad.align(e.path, e.transform, e.overflowValue());
+      ? ad.align(e.transform, e.overlapValue())
+      : ad.align(e.path, e.transform, e.overlapValue());
   }
   else     {
     alignment = is_not_volume ? ad.align(e.transform) : ad.align(e.path, e.transform);
diff --git a/DDAlign/src/AlignmentParser.cpp b/DDAlign/src/AlignmentParser.cpp
index 9de3872c4..c17ab8f59 100644
--- a/DDAlign/src/AlignmentParser.cpp
+++ b/DDAlign/src/AlignmentParser.cpp
@@ -19,6 +19,7 @@
 #include "DDAlign/AlignmentTags.h"
 #include "DDAlign/AlignmentStack.h"
 #include "DDAlign/AlignmentCache.h"
+#include "DDAlign/AlignmentTransaction.h"
 
 // C/C++ include files
 #include <stdexcept>
@@ -27,41 +28,6 @@ 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;
@@ -234,7 +200,7 @@ template <> void Converter<volume>::operator()(xml_h e) const {
   if ( check       ) flags |= AlignmentStack::CHECKOVL_DEFINED;
   if ( check_val   ) flags |= AlignmentStack::CHECKOVL_VALUE;
 
-  StackEntry* entry = new StackEntry(elt->first,placementPath,trafo.second,ovl,flags);
+  auto_ptr<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));
@@ -261,19 +227,13 @@ template <> void Converter<detelement>::operator()(xml_h e) const {
   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   reset     = e.hasAttr(_U(reset)) ? e.attr<bool>(_U(reset)) : false;
+  bool   reset_dau = e.hasAttr(_U(reset_children)) ? e.attr<bool>(_U(reset_children)) : false;
   bool   overlap   = e.hasAttr(_U(overlap));
   double ovl       = overlap ? e.attr<double>(_U(overlap)) : 0.001;
-  DetElement elt   = Geometry::DetectorTools::findElement(det,path);
+  DetElement elt   = Geometry::DetectorTools::findDaughterElement(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);
@@ -282,14 +242,23 @@ template <> void Converter<detelement>::operator()(xml_h e) const {
   pair<bool,Transform3D> trafo;
   Converter<transform3d>(lcdd,&trafo)(e);
   int flags = 0;
+  if ( trafo.first )  {
+    flags |= AlignmentStack::MATRIX_DEFINED;
+    reset = reset_dau = true;
+  }
   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);
+  printout(INFO,"Alignment<detelement>","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));
+
+  auto_ptr<StackEntry> entry(new StackEntry(elt,placementPath,trafo.second,ovl,flags));
   AlignmentStack::insert(entry);
 
   pair<DetElement,string> vol_param(elt,"");
@@ -310,7 +279,8 @@ template <> void Converter<detelement>::operator()(xml_h e) const {
  *  @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();
+  XML::DocumentHolder doc(XML::DocumentHandler().load(element, element.attr_value(_U(ref))));
+  xml_h node = doc.root();
   string tag = node.tag();
   if ( tag == "alignment" )  
     Converter<alignment>(lcdd,param)(node);
@@ -335,7 +305,6 @@ template <> void Converter<include_file>::operator()(xml_h element) const {
  *  @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:
@@ -354,6 +323,7 @@ template <> void Converter<alignment>::operator()(xml_h e)  const  {
  */
 static long setup_Alignment(lcdd_t& lcdd, const xml_h& e) {
   AlignmentCache::install(lcdd);
+  AlignmentTransaction tr(lcdd, e);
   (DD4hep::Converter<DD4hep::alignment>(lcdd))(e);
   return 1;
 }
diff --git a/DDAlign/src/AlignmentStack.cpp b/DDAlign/src/AlignmentStack.cpp
index db5f3656c..8f60b62fe 100644
--- a/DDAlign/src/AlignmentStack.cpp
+++ b/DDAlign/src/AlignmentStack.cpp
@@ -10,25 +10,35 @@
 #include "DD4hep/LCDD.h"
 #include "DD4hep/Objects.h"
 #include "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
 #include "DDAlign/AlignmentStack.h"
 
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
-static AlignmentStack* s_alignStack = 0;
-
+static auto_ptr<AlignmentStack>& _stack()  {
+  static auto_ptr<AlignmentStack> s;
+  return s;
+}
+static auto_ptr<AlignmentStack>& _stack(AlignmentStack* obj)  {
+  auto_ptr<AlignmentStack>& s = _stack();
+  s = auto_ptr<AlignmentStack>(obj);
+  return s;
+}
 
 /// Fully initializing constructor
-AlignmentStack::StackEntry::StackEntry(const DetElement& p, const std::string& placement, const Transform3D& t, double ov, int f)
+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();
@@ -38,6 +48,7 @@ AlignmentStack::StackEntry::StackEntry(DetElement element, bool rst, bool rst_ch
 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;
@@ -48,6 +59,7 @@ AlignmentStack::StackEntry::StackEntry(DetElement element, const Transform3D& tr
 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;
@@ -58,6 +70,7 @@ AlignmentStack::StackEntry::StackEntry(DetElement element, const Position& trans
 AlignmentStack::StackEntry::StackEntry(DetElement element, const RotationZYX& rot, bool rst, bool rst_children)
 : detector(element), transform(rot), overlap(0.001), flag(0)
 {
+  InstanceCount::increment(this);
   flag |= MATRIX_DEFINED;
   if ( rst ) flag |= RESET_VALUE;
   if ( rst_children ) flag |= RESET_CHILDREN;
@@ -68,6 +81,7 @@ AlignmentStack::StackEntry::StackEntry(DetElement element, const RotationZYX& ro
 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;
@@ -78,6 +92,24 @@ AlignmentStack::StackEntry::StackEntry(DetElement element, const Position& trans
 AlignmentStack::StackEntry::StackEntry(const StackEntry& e)
 : detector(e.detector), transform(e.transform), path(e.path), overlap(e.overlap), flag(e.flag)
 {
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+AlignmentStack::StackEntry::~StackEntry() {
+  InstanceCount::decrement(this);
+}
+
+/// Assignment operator
+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;
+  }
+  return *this;
 }
 
 /// Attach transformation object
@@ -126,45 +158,46 @@ AlignmentStack::StackEntry& AlignmentStack::StackEntry::setOverlapPrecision(doub
 /// Default constructor
 AlignmentStack::AlignmentStack()
 {
+  InstanceCount::increment(this);
 }
 
 /// Default destructor
 AlignmentStack::~AlignmentStack()   {
   destroyObjects(m_stack)();
+  InstanceCount::decrement(this);
 }
 
 /// Static client accessor
 AlignmentStack& AlignmentStack::get()  {
-  if ( s_alignStack ) return *s_alignStack;
+  if ( _stack().get() ) return *_stack();
   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 )   {
+  if ( _stack().get() )   {
     throw runtime_error("AlignmentStack> Stack already allocated. Multiple copies are not allowed!");
   }
-  s_alignStack = new AlignmentStack();
+  _stack(new AlignmentStack());
 }
 
 /// Check existence of alignment stack
 bool AlignmentStack::exists()   {
-  return s_alignStack != 0;
+  return _stack().get() != 0;
 }
 
 /// Clear data content and remove the slignment stack
 void AlignmentStack::release()    {
-  if ( s_alignStack )  {
-    delete s_alignStack;
-    s_alignStack = 0;
+  if ( _stack().get() )  {
+    _stack(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() )  {
+bool AlignmentStack::insert(const string& full_path, auto_ptr<StackEntry>& entry)  {
+  if ( entry.get() && !full_path.empty() )  {
     entry->path = full_path;
     return get().add(entry);
   }
@@ -172,16 +205,23 @@ bool AlignmentStack::insert(const std::string& full_path, StackEntry* entry)  {
 }
 
 /// Add a new entry to the cache. The key is the placement path
-bool AlignmentStack::insert(StackEntry* entry)  {
+bool AlignmentStack::insert(auto_ptr<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() )  {
+bool AlignmentStack::add(auto_ptr<StackEntry>& entry)  {
+  if ( entry.get() && !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));
+
+      // Need to make some checks BEFORE insertion
+      if ( !entry->detector.isValid() )   {
+	throw runtime_error("AlignmentStack> Invalid alignment entry [No such detector]");
+      }
+      printout(INFO,"AlignmentStack","Add node:%s",entry->path.c_str());
+      m_stack.insert(make_pair(entry->path,entry.get()));
+      entry.release();
       return true;
     }
     throw runtime_error("AlignmentStack> The entry with path "+entry->path+
diff --git a/DDAlign/src/AlignmentTransaction.cpp b/DDAlign/src/AlignmentTransaction.cpp
new file mode 100644
index 000000000..8796af6d0
--- /dev/null
+++ b/DDAlign/src/AlignmentTransaction.cpp
@@ -0,0 +1,36 @@
+// $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 "DDAlign/AlignmentTags.h"
+#include "DDAlign/AlignmentCache.h"
+#include "DDAlign/AlignmentTransaction.h"
+
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+/// Default constructor
+AlignmentTransaction::AlignmentTransaction(LCDD& l, const XML::Handle_t& 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::~AlignmentTransaction()   {
+  /// Last check if a transaction is to be closed
+  if ( flag ) {
+    lcdd.extension<Geometry::AlignmentCache>()->closeTransaction();
+  }
+  m_cache->release();
+}
diff --git a/DDAlign/src/AlignmentWriter.cpp b/DDAlign/src/AlignmentWriter.cpp
index a87c54894..e11cf63db 100644
--- a/DDAlign/src/AlignmentWriter.cpp
+++ b/DDAlign/src/AlignmentWriter.cpp
@@ -165,7 +165,7 @@ static long create_alignment_file(LCDD& lcdd, int argc, char** argv)   {
   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);
+  top = DetectorTools::findDaughterElement(lcdd.world(),path);
   if ( top.isValid() )   {
     AlignmentWriter wr(lcdd);
     return wr.write(wr.dump(top,enable_transactions), output);
diff --git a/DDAlign/src/DetectorAlignment.cpp b/DDAlign/src/DetectorAlignment.cpp
index 000a73072..bd1d1d071 100644
--- a/DDAlign/src/DetectorAlignment.cpp
+++ b/DDAlign/src/DetectorAlignment.cpp
@@ -11,6 +11,7 @@
 #include "DD4hep/InstanceCount.h"
 #include "DD4hep/MatrixHelpers.h"
 #include "DD4hep/Printout.h"
+#include "DD4hep/objects/DetectorInterna.h"
 
 // ROOT include files
 #include "TGeoMatrix.h"
@@ -109,12 +110,12 @@ Alignment DetectorAlignment::alignment() const   {
 }
 
 /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
-std::vector<Alignment>& DetectorAlignment::volumeAlignments()  {
+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   {
+const vector<Alignment>& DetectorAlignment::volumeAlignments() const   {
   return _data().volume_alignments;
 }
 
-- 
GitLab