diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h
index d6e60d6185bcb14b085ebfcc69fc2b73c88c601b..fc44ab3c65be20329b79eae9aca97d8e86772f4d 100644
--- a/DDCore/include/DD4hep/Detector.h
+++ b/DDCore/include/DD4hep/Detector.h
@@ -113,13 +113,29 @@ namespace DD4hep {
 	PlacedVolume      placement;
         Placements        placements;
 	Parent            parent;
+	Parent            reference;
         Children          children;
+	TGeoMatrix*       worldTrafo;
+	TGeoMatrix*       parentTrafo;
+	TGeoMatrix*       referenceTrafo;
 	/// Default constructor
         Object();
 	/// Construct new empty object
 	virtual Value<TNamed,Object>* construct(int new_id, int flag) const;
 	/// Deep object copy to replicate DetElement trees e.g. for reflection
 	virtual void deepCopy(const Object& source, int new_id, int flag);
+	/// Conversion to reference object
+	operator Ref_t();
+	/// Conversion to reference object
+	Ref_t asRef();
+	/// Top detector element
+	Ref_t top();
+	/// Create cached matrix to transform to world coordinates
+	TGeoMatrix* worldTransformation();
+	/// Create cached matrix to transform to parent coordinates
+	TGeoMatrix* parentTransformation();
+	/// Create cached matrix to transform to reference coordinates
+	TGeoMatrix* referenceTransformation();
       };
 
       /// Additional data accessor
@@ -180,9 +196,9 @@ namespace DD4hep {
       DetElement&     setPlacement(const PlacedVolume& volume);
 
       /// Access the physical volumes of the detector element
-      Placements      placements() const;
+      //Placements      placements() const;
       /// Set the physical volumes of the detector element
-      DetElement&     addPlacement(const PlacedVolume& volume);
+      //DetElement&     addPlacement(const PlacedVolume& volume);
 
       /// Access to the logical volume of the placements (all daughters have the same!)
       Volume          volume() const;
@@ -191,6 +207,24 @@ namespace DD4hep {
       const Children& children() const;
       /// Access to individual children by name
       DetElement      child(const std::string& name) const;
+
+      /// Set detector element for reference transformations. Will delete existing reference trafo.
+      DetElement&     setReference(DetElement reference);
+
+      /// Transformation from local coordinates of the placed volume to the world system
+      bool localToWorld(const Position& local, Position& global)  const;
+      /// Transformation from local coordinates of the placed volume to the parent system
+      bool localToParent(const Position& local, Position& parent)  const;
+      /// Transformation from local coordinates of the placed volume to arbitrary parent system set as reference
+      bool localToReference(const Position& local, Position& reference)  const;
+
+      /// Transformation from world coordinates of the local placed volume coordinates
+      bool worldToLocal(const Position& global, Position& local)  const;
+      /// Transformation from world coordinates of the local placed volume coordinates
+      bool parentToLocal(const Position& parent, Position& local)  const;
+      /// Transformation from world coordinates of the local placed volume coordinates
+      bool referenceToLocal(const Position& reference, Position& local)  const;
+
     };
     
   }       /* End namespace Geometry      */
diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h
index 60422028be753038690a835bbd448eeadeff7dbb..c7328b7efac38b4ef7b0deecbf36435a83ff19f3 100644
--- a/DDCore/include/DD4hep/Objects.h
+++ b/DDCore/include/DD4hep/Objects.h
@@ -94,44 +94,68 @@ namespace DD4hep {
       std::string toString()  const;
     };
 
+    // We want the 3 coordinates ass-to-ass, so that they can be interpreted as "double*"
+#ifdef _WIN32
+#pragma pack(push,DD4Hep_Objects_Position,1)
+#define DD4HEP_BYTE_ALIGN(x) x
+#else
+#define DD4HEP_BYTE_ALIGN(x) x __attribute__((__packed__))
+#endif
     /** @class Position Objects.h
      *  
      *  @author  M.Frank
      *  @version 1.0
      */
-    struct Position  {
+    DD4HEP_BYTE_ALIGN(struct) Position  {
+      /// 3-dimensional cartesian coordinates
       double x, y, z;
       /// Default constructor
       Position() : x(0), y(0), z(0) {}
       /// Initializing constructor
-      Position(double xval, double yval, double zval) : x(xval), y(yval), z(zval) {}
+      Position(double xval, double yval, double zval) : x(xval), y(yval), z(zval) {     }
       /// Is it a identity rotation ?
-      bool isNull() const { return x==0 && y==0 && z==0; }
+      bool isNull() const                             { return x==0 && y==0 && z==0;    }
+      /// Access to array like coordinates
+      const double* coordinates() const               { return &x;                      }
+      /// Initializer for all member variables
+      Position& set(double xv, double yv, double zv)  { x=xv; y=yv; z=zv; return *this; }
     };
-
-    /** @class IdentityPos Objects.h
+#ifdef _WIN32
+#pragma pack(pop,DD4Hep_Objects_Position)
+#pragma pack(push,DD4Hep_Objects_Rotation,1)
+#endif
+    /** @class Rotation Objects.h
      *  
      *  @author  M.Frank
      *  @version 1.0
      */
-    struct IdentityPos {
+    DD4HEP_BYTE_ALIGN(struct) Rotation  {
+      double theta, phi, psi;
       /// Default constructor
-      IdentityPos() {}
+      Rotation() : theta(0), phi(0), psi(0) {}
+      /// Initializing constructor
+      Rotation(double thetaval, double phival, double psival) : theta(thetaval), phi(phival), psi(psival) {}
+      /// Is it a identity rotation ?
+      bool isNull() const                              { return theta==0 && phi==0 && psi==0;   }
+      /// Access to array like coordinates
+      const double* angles() const                     { return &theta;                         }
+      /// Initializer for all member variables
+      Rotation& set(double th, double ph, double ps)   { theta=th; phi=ph; psi=ps;return *this; }
     };
 
-    /** @class Rotation Objects.h
+#ifdef _WIN32
+#pragma pack(pop,DD4Hep_Objects_Rotation,1)
+#endif
+#undef DD4HEP_BYTE_ALIGN
+
+    /** @class IdentityPos Objects.h
      *  
      *  @author  M.Frank
      *  @version 1.0
      */
-    struct Rotation  {
-      double theta, phi, psi;
+    struct IdentityPos {
       /// Default constructor
-      Rotation() : theta(0), phi(0), psi(0) {}
-      /// Initializing constructor
-      Rotation(double thetaval, double phival, double psival) : theta(thetaval), phi(phival), psi(psival) {}
-      /// Is it a identity rotation ?
-      bool isNull() const { return theta==0 && phi==0 && psi==0; }
+      IdentityPos() {}
     };
 
     /** @class IdentityRot Objects.h
diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h
index ef8729cef4bb13c375d1463478ca269b402dbb16..07dba2baa7e9c27503b87062f11be5c33a55ae96 100644
--- a/DDCore/include/DD4hep/Volumes.h
+++ b/DDCore/include/DD4hep/Volumes.h
@@ -51,10 +51,14 @@ namespace DD4hep {
     struct PlacedVolume : Handle<TGeoNodeMatrix> {
       typedef std::map<std::string,int> VolIDs;
       struct Object  {
+	/// Magic word
         unsigned long magic;
+	/// ID container
         VolIDs        volIDs;
-        Ref_t         detector;
-        Object() : volIDs(), detector() {}
+	/// Default constructor
+        Object() : volIDs() {}
+	/// Copy constructor
+	Object(const Object& c) : magic(c.magic), volIDs(c.volIDs) {}
       };
       /// Constructor to be used when reading the already parsed DOM tree
       PlacedVolume(const TGeoNode* e) : Handle<TGeoNodeMatrix>(e) {}
@@ -74,10 +78,6 @@ namespace DD4hep {
       Volume motherVol() const;
       /// Access to the volume IDs
       const VolIDs& volIDs() const;
-      /// Set the detector handle
-      void setDetElement(Ref_t detector)  const;
-      /// Access to the corresponding detector element (maybe invalid)
-      Ref_t detElement() const;
       /// String dump
       std::string toString() const;
     };
@@ -144,7 +144,7 @@ namespace DD4hep {
       void setLimitSet(const LimitSet& obj)  const;
       /// Access to the limit set
       LimitSet limitSet() const;
-      
+
       /// Set Visualization attributes to the volume
       void setVisAttributes(const VisAttr& obj) const;
       /// Set Visualization attributes to the volume
diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp
index 7509189d1abad4f0c7564681f1510dfed1dfdeda..bc2c7913025770464d545f2a4d4f0de76d61b7de 100644
--- a/DDCore/src/Detector.cpp
+++ b/DDCore/src/Detector.cpp
@@ -10,14 +10,113 @@
 #include "DD4hep/IDDescriptor.h"
 #include "DD4hep/LCDD.h"
 #include "TGeoVolume.h"
+#include "TGeoMatrix.h"
+#include "TGeoManager.h"
 
 using namespace std;
 using namespace DD4hep::Geometry;
 
+static bool traverse_find(TGeoNode* parent, TGeoNode* child, vector<TGeoMatrix*>& trafos) {
+  TIter next(parent->GetVolume()->GetNodes());
+  for (TGeoNode *daughter=(TGeoNode*)next(); daughter; daughter=(TGeoNode*)next() ) {
+    if ( daughter == child )   {
+      trafos.push_back(daughter->GetMatrix());
+      return true;
+    }
+  }
+  next.Reset();
+  for (TGeoNode *daughter=(TGeoNode*)next(); daughter; daughter=(TGeoNode*)next() ) {
+    if ( traverse_find(daughter, child, trafos) ) {
+      trafos.push_back(daughter->GetMatrix());
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool traverse_up(const DetElement& parent, const DetElement& child, vector<TGeoMatrix*>& trafos) {
+  if ( child.ptr() != parent.ptr() ) {
+    for( DetElement par=parent, cld=child; par.isValid(); cld=par, par=par._data().parent ) {
+      PlacedVolume cld_place = cld._data().placement;
+      PlacedVolume par_place = par._data().placement;
+      if ( !traverse_find(par_place.ptr(),cld_place.ptr(),trafos) ) {
+	return false;
+      }
+    }
+  }
+  return true;
+}
+#include <iostream>
+static string find_child(TGeoNode* top, TGeoNode* child, vector<TGeoNode*>& path) {
+  TIter next(top->GetVolume()->GetNodes());
+  for (TGeoNode *daughter=(TGeoNode*)next(); daughter; daughter=(TGeoNode*)next() ) {
+    if ( daughter == child )   {
+      cout << "Found child:" << child->GetName() << endl;
+      path.push_back(daughter);
+      return child->GetName();
+    }
+  }
+  next.Reset();
+  for (TGeoNode *daughter=(TGeoNode*)next(); daughter; daughter=(TGeoNode*)next() ) {
+    string res = find_child(daughter, child, path);
+    if ( !res.empty() ) {
+      path.push_back(daughter);
+      return top->GetName() + ("/"+res);
+    }
+  }
+  //cout << "FAILED child:" << (unsigned long)child << endl;
+  return "";
+}
+
+/// Create cached matrix to transform to positions to an upper level DetElement
+static TGeoHMatrix* create_trafo(const Ref_t& parent, const Ref_t& child)   {
+  if ( parent.isValid() && child.isValid() )   {
+    TGeoHMatrix* mat = 0;    // Now collect all transformations
+    vector<TGeoMatrix*> trafos;
+    if ( !traverse_up(parent,child,trafos) )   {
+      trafos.clear();
+      if ( !traverse_up(child,parent,trafos) )   {  // Some error, non-existing path!
+	throw runtime_error("DetElement "+string(parent.name())+" is not connected to child "+string(child.name())+" [Geo-Error]");
+      }
+      else {
+	/// The two detector elements were only found by reversing the hierarchy.
+	/// Hence the transformations must be applied in reverse order.
+	for(vector<TGeoMatrix*>::const_reverse_iterator i=trafos.rbegin(); i!=trafos.rend(); ++i) {
+	  if ( !mat ) mat = new TGeoHMatrix(*(*i));
+	  else mat->MultiplyLeft(*i);
+	}
+      }
+    }
+    else {
+      /// Combine the transformations to a single transformation.
+      for(vector<TGeoMatrix*>::const_iterator i=trafos.begin(); i!=trafos.end(); ++i) {
+	if ( !mat ) mat = new TGeoHMatrix(*(*i));
+	else mat->MultiplyLeft(*i);
+      }
+    }
+#if 0
+    // Test: find arbitrary child by traversing TGeoNode tree
+    vector<TGeoNode*> path;
+    TGeoNode* top  = gGeoManager->GetTopNode();
+    TGeoNode* node = DetElement(child).placement().ptr();
+    string res = find_child(top,node,path);
+    cout << "Path:" << res << endl;
+#endif
+    return mat;
+  }
+  if ( parent.isValid() )
+    throw runtime_error("DetElement cannot connect "+string(parent.name())+" to not-existing child!");
+  else if ( child.isValid() )
+    throw runtime_error("DetElement cannot connect "+string(child.name())+" to not-existing parent!");
+  else
+    throw runtime_error("DetElement cannot connect nonexisting parent to not-existing child!");
+}
+
 /// Default constructor
 DetElement::Object::Object()  
   : magic(magic_word()), id(0), combine_hits(0), readout(), 
-    alignment(), placement(), placements(), parent(), children()
+    alignment(), placement(), placements(), parent(), children(),
+    worldTrafo(0), parentTrafo(0), referenceTrafo(0)
 {
 }
 
@@ -55,6 +154,59 @@ void DetElement::Object::deepCopy(const Object& source, int new_id, int flag)  {
   }
 }
 
+/// Top detector element
+Ref_t DetElement::Object::top()   {
+  // This is an ugly staement. Need to rethink it a bit.....(MSF)
+  if ( !this->parent.isValid() )  return this->asRef();
+  return DetElement(this->parent)._data().top();
+}
+
+/// Conversion to reference object
+Ref_t DetElement::Object::asRef() {
+  return Ref_t(dynamic_cast<Value<TNamed,DetElement::Object>*>(this));
+}
+
+/// Conversion to reference object
+DetElement::Object::operator Ref_t() {
+  return this->asRef();
+}
+
+/// Create cached matrix to transform to world coordinates
+TGeoMatrix* DetElement::Object::worldTransformation() {
+  if ( !worldTrafo ) {
+    DetElement top_det(this->top());
+    vector<TGeoMatrix*> trafos;
+    TGeoHMatrix* mat = create_trafo(top_det,asRef());
+    // Now we got the point in the top-most detector element. We now have
+    // to translate this to the "world volume", which has no transformation matrix anymore
+    TGeoNode* top_node = gGeoManager->GetTopNode();
+    PlacedVolume place = top_det.placement();
+    if ( !traverse_find(top_node, place.ptr(), trafos) ) {
+      // Some error, non-existing path!
+      throw runtime_error("DetElement "+string(parent.name())+" is not connected to top geo node [Geo-Error]");
+    }    
+    for(vector<TGeoMatrix*>::const_iterator i=trafos.begin(); i!=trafos.end(); ++i)
+      mat->MultiplyLeft(*i);
+    worldTrafo = mat;
+  }    
+  return worldTrafo;
+}
+
+/// Create cached matrix to transform to parent coordinates
+TGeoMatrix* DetElement::Object::parentTransformation() {
+  if ( !parentTrafo )   {
+    parentTrafo = create_trafo(this->parent,asRef());
+  }
+  return parentTrafo;
+}
+
+/// Create cached matrix to transform to reference coordinates
+TGeoMatrix* DetElement::Object::referenceTransformation() {
+  if ( !referenceTrafo )   {
+    referenceTrafo = create_trafo(this->reference,asRef());
+  }
+  return referenceTrafo;
+}
 
 /// Constructor for a new subdetector element
 DetElement::DetElement(const LCDD& /* lcdd */, const string& name, const string& type, int id)
@@ -79,9 +231,7 @@ string DetElement::path() const   {
     Object& o = _data();
     if ( o.path.empty() )   {
       DetElement par = o.parent;
-      if ( par.isValid() )
-	return (par.path()+"/")+name();
-      return string("/") + name();
+      o.path = par.isValid() ? (par.path()+"/")+name() : string("/") + name();
     }
     return o.path;
   }
@@ -134,10 +284,6 @@ DetElement& DetElement::add(const DetElement& sdet)  {
   throw runtime_error("DetElement::add: Self is not defined [Invalid Handle]");
 }
 
-DetElement::Placements DetElement::placements() const    {
-  return _data().placements;
-}
-
 DetElement DetElement::clone(const string& new_name)  const  {
   if ( isValid() ) {
     return DetElement(_data().construct(_data().id,COPY_NONE), new_name, ptr()->GetTitle());
@@ -167,16 +313,20 @@ PlacedVolume DetElement::placement() const {
 DetElement& DetElement::setPlacement(const PlacedVolume& placement) {
   if ( isValid() ) {
     if ( placement.isValid() )  {
-      Object& o = _data();
+      Object& o   = _data();
       o.placement = placement;
-      o.volume = placement.volume();
-      placement.setDetElement(*this);
+      o.volume    = placement.volume();
+      //placement.setDetElement(*this);
       return *this;
     }
     throw runtime_error("DetElement::addPlacement: Placement is not defined [Invalid Handle]");
   }
   throw runtime_error("DetElement::addPlacement: Self is not defined [Invalid Handle]");
 }
+#if 0
+DetElement::Placements DetElement::placements() const    {
+  return _data().placements;
+}
 
 // OBSOLETE: to be replaced by setPlacement
 DetElement& DetElement::addPlacement(const PlacedVolume& placement)  {
@@ -190,7 +340,7 @@ DetElement& DetElement::addPlacement(const PlacedVolume& placement)  {
   }
   throw runtime_error("DetElement::addPlacement: Self is not defined [Invalid Handle]");
 }
-
+#endif
 /// Access to the logical volume of the placements (all daughters have the same!)
 Volume DetElement::volume() const {
   if ( isValid() )  {
@@ -263,6 +413,62 @@ bool DetElement::isCalorimeter() const   {
   return false;
 }
 
+/// Set detector element for reference transformations. Will delete existing reference trafo.
+DetElement& DetElement::setReference(DetElement reference) {
+  Object& o = _data();
+  if ( o.referenceTrafo )  {
+    delete o.referenceTrafo;
+    o.referenceTrafo = 0;
+  }
+  _data().reference = reference;
+  return *this;
+}
+
+/// Transformation from local coordinates of the placed volume to the world system
+bool DetElement::localToWorld(const Position& local, Position& global)  const {
+  Double_t master_point[3]={0,0,0}, local_point[3] = {local.x,local.y,local.z};
+  // If the path is unknown an exception will be thrown inside worldTransformation() !
+  _data().worldTransformation()->LocalToMaster(local_point,master_point);
+  global.set(master_point[0],master_point[1],master_point[2]);
+  return true;
+}
+
+/// Transformation from local coordinates of the placed volume to the parent system
+bool DetElement::localToParent(const Position& local, Position& global)  const {
+  // If the path is unknown an exception will be thrown inside parentTransformation() !
+  _data().parentTransformation()->LocalToMaster(&local.x,&global.x);
+  return true;
+}
+
+/// Transformation from local coordinates of the placed volume to arbitrary parent system set as reference
+bool DetElement::localToReference(const Position& local, Position& global)  const {
+  // If the path is unknown an exception will be thrown inside referenceTransformation() !
+  _data().referenceTransformation()->LocalToMaster(&local.x,&global.x);
+  return true;
+}
+
+/// Transformation from world coordinates of the local placed volume coordinates
+bool DetElement::worldToLocal(const Position& global, Position& local)  const {
+  // If the path is unknown an exception will be thrown inside worldTransformation() !
+  _data().worldTransformation()->MasterToLocal(&global.x,&local.x);
+  return true;
+}
+
+/// Transformation from parent coordinates of the local placed volume coordinates
+bool DetElement::parentToLocal(const Position& global, Position& local)  const {
+  // If the path is unknown an exception will be thrown inside parentTransformation() !
+  _data().parentTransformation()->MasterToLocal(&global.x,&local.x);
+  return true;
+}
+
+/// Transformation from arbitrary parent system coordinates of the local placed volume coordinates
+bool DetElement::referenceToLocal(const Position& global, Position& local)  const {
+  // If the path is unknown an exception will be thrown inside referenceTransformation() !
+  _data().referenceTransformation()->MasterToLocal(&global.x,&local.x);
+  return true;
+}
+
+/// Constructor
 SensitiveDetector::SensitiveDetector(const LCDD& /* lcdd */, const std::string& type, const std::string& name) 
 {
   /*
diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp
index 4c0d88d350e7a4a1e1552d1896f9d4e811b043bf..a61ac1d1fe7d7f9155efeebf3042e6e9de5d2b1f 100644
--- a/DDCore/src/LCDDImp.cpp
+++ b/DDCore/src/LCDDImp.cpp
@@ -41,12 +41,12 @@ Volume LCDDImp::pickMotherVolume(const DetElement&) const  {     // throw if not
 }
 
 LCDD& LCDDImp::addVolume(const Ref_t& x)    {
-  m_structure.append<TGeoVolume>(x);
+  m_structure.append<TGeoVolume>(x,false);
   return *this;
 }
 
 LCDD& LCDDImp::addSolid(const Ref_t& x)    {
-  m_structure.append<TGeoShape>(x);
+  m_structure.append<TGeoShape>(x,false);
   return *this;
 }
 
@@ -165,6 +165,135 @@ static void dumpChildren(const DetElement& e, int level) {
     dumpChildren(DetElement((*i).second),level+1);
 }
 
+#if 0
+#include "TGeoNode.h"
+
+static void dumpGeometry(vector<TGeoNode*>& globals, vector<TGeoNode*>& locals, TGeoNode* current) {
+  typedef Value<TGeoNodeMatrix,PlacedVolume::Object> _P;
+  TGeoMatrix* matrix = current->GetMatrix();
+  TGeoVolume* volume = current->GetVolume();
+  TObjArray*  nodes  = volume->GetNodes();
+  int   num_children = nodes ? nodes->GetEntriesFast() : 0;
+  _P*   val = dynamic_cast<_P*>(current);
+  static vector<DetElement> det_cache;
+  vector<TGeoNode*>   loc_cache;
+  vector<TGeoNode*>*  ptrloc_cache = &locals;
+  const char* tag = val ? "Yes" : "No ";
+  bool valid_det = false;
+  bool prt = false;
+  for(size_t i=0; i<globals.size(); ++i) {
+    if(strncmp(globals[i]->GetName(),"Muon",4)==0) { prt = true; break;}
+  }
+
+  if ( val ) {
+    DetElement d = val->detector;
+    if ( d.isValid() )   {
+      valid_det = true;
+      det_cache.push_back(d);
+      ptrloc_cache = &loc_cache;
+    }
+  }
+  if ( prt ) {
+    cout << "[" << int(globals.size()) << " , " << tag << "] \t" << (void*)current << "\t" 
+	 << char(valid_det ? '*' : ' ')
+	 << current->GetName();
+    if ( num_children > 0 )
+      cout << " #Children:" << num_children << ".";
+    else
+      cout << " No Children.";
+    cout << "\t Vol:" << volume->GetName();
+    if ( valid_det ) {
+      DetElement d = val->detector;
+      cout << " DetElement:" << d->GetName();
+      //cout << " Vol:" << d.volume().name();
+      cout << " DetTrafos:" << locals.size();
+    }
+    else  {
+      cout << " Trafos:" << locals.size();
+      for(size_t i=0; i<locals.size(); ++i)
+	cout << " " << (void*)locals[i];
+    }
+    cout << endl;
+  }
+  if ( num_children > 0 )   {
+    globals.push_back(current);
+    for(int i=0; i<num_children; ++i)   {
+      TGeoNode* node = (TGeoNode*)nodes->At(i);
+      ptrloc_cache->push_back(node);
+      dumpGeometry(globals,*ptrloc_cache,node);
+      ptrloc_cache->pop_back();
+    }
+    globals.pop_back();
+  }
+  if ( valid_det ) det_cache.pop_back();
+}
+
+vector<TGeoMatrix*>          Transformations;
+vector<TGeoSolid*>           Volumes;
+map<int, vector<TGeoNode*> > Placements;
+
+
+static void dumpGeo(TGeoNode* current) {
+
+  typedef Value<TGeoNodeMatrix,PlacedVolume::Object> _P;
+  TGeoMatrix* matrix = current->GetMatrix();
+  TGeoVolume* volume = current->GetVolume();
+  TObjArray*  nodes  = volume->GetNodes();
+  int   num_children = nodes ? nodes->GetEntriesFast() : 0;
+  _P*   val = dynamic_cast<_P*>(current);
+  static vector<DetElement> det_cache;
+  vector<TGeoNode*>   loc_cache;
+  vector<TGeoNode*>*  ptrloc_cache = &locals;
+  const char* tag = val ? "Yes" : "No ";
+  bool valid_det = false;
+  bool prt = false;
+  for(size_t i=0; i<globals.size(); ++i) {
+    if(strncmp(globals[i]->GetName(),"Muon",4)==0) { prt = true; break;}
+  }
+
+  if ( val ) {
+    DetElement d = val->detector;
+    if ( d.isValid() )   {
+      valid_det = true;
+      det_cache.push_back(d);
+      ptrloc_cache = &loc_cache;
+    }
+  }
+  if ( prt ) {
+    cout << "[" << int(globals.size()) << " , " << tag << "] \t" << (void*)current << "\t" 
+	 << char(valid_det ? '*' : ' ')
+	 << current->GetName();
+    if ( num_children > 0 )
+      cout << " #Children:" << num_children << ".";
+    else
+      cout << " No Children.";
+    cout << "\t Vol:" << volume->GetName();
+    if ( valid_det ) {
+      DetElement d = val->detector;
+      cout << " DetElement:" << d->GetName();
+      //cout << " Vol:" << d.volume().name();
+      cout << " DetTrafos:" << locals.size();
+    }
+    else  {
+      cout << " Trafos:" << locals.size();
+      for(size_t i=0; i<locals.size(); ++i)
+	cout << " " << (void*)locals[i];
+    }
+    cout << endl;
+  }
+  if ( num_children > 0 )   {
+    globals.push_back(current);
+    for(int i=0; i<num_children; ++i)   {
+      TGeoNode* node = (TGeoNode*)nodes->At(i);
+      ptrloc_cache->push_back(node);
+      dumpGeometry(globals,*ptrloc_cache,node);
+      ptrloc_cache->pop_back();
+    }
+    globals.pop_back();
+  }
+  if ( valid_det ) det_cache.pop_back();
+}
+#endif
 void LCDDImp::dump() const  {
   TGeoManager* mgr = gGeoManager;
   mgr->CloseGeometry();
@@ -178,5 +307,12 @@ void LCDDImp::dump() const  {
     dumpChildren(e,0);
     //cout << "Detector: " << (*i).first << " : " << e.name() << endl;
   }
+#if 0
+  TGeoNode* top = mgr->GetTopNode();
+  vector<TGeoNode*> globals;
+  vector<TGeoNode*> locals;
+  //dumpGeometry(globals,locals,top);
+  //dumpGeo(top);
+#endif
 }
 
diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h
index d75392df330f0a2ec11d6dcc43f76d5bb6a18c2f..1c87cdb58afc19afb5e5da5f91b087dfad94067d 100644
--- a/DDCore/src/LCDDImp.h
+++ b/DDCore/src/LCDDImp.h
@@ -46,19 +46,21 @@ namespace DD4hep {
             this->insert(std::make_pair(n,e.ptr()));
           }
         }
-        void append(const Ref_t& e) { 
+        void append(const Ref_t& e, bool throw_on_doubles=true) { 
           if ( e.isValid() )  {
             std::string n = e.name();
-            this->insert(std::make_pair(n,e.ptr()));
-            return;
+	    std::pair<iterator,bool> r = this->insert(std::make_pair(n,e.ptr()));
+	    if ( !throw_on_doubles || r.second )
+	      return;
+	    throw InvalidObjectError("Attempt to add an already existing object:"+std::string(e.name())+".");
           }
-          throw InvalidObjectError("Attempt to add an invalid object object");
+          throw InvalidObjectError("Attempt to add an invalid object.");
         }
-        template <typename T> void append(const Ref_t& e) {
+        template <typename T> void append(const Ref_t& e, bool throw_on_doubles=true) {
           T* obj = dynamic_cast<T*>(e.ptr());
           if ( obj )  {
-            this->append(e);
-            return;
+            this->append(e,throw_on_doubles);
+	    return;
           }
           throw InvalidObjectError("Attempt to add an object, which is of the wrong type.");
         }
@@ -168,7 +170,7 @@ namespace DD4hep {
       virtual LCDD& addVolume(const Ref_t& x);      //  { m_structure.append(x);  __R;}
       
       // These not:
-      virtual LCDD& addConstant(const Ref_t& x)         { m_define.append(x);     __R;}
+      virtual LCDD& addConstant(const Ref_t& x)         { m_define.append(x,false);     __R;}
       virtual LCDD& addMaterial(const Ref_t& x)         { m_materials.append(x);  __R;}
       virtual LCDD& addLimitSet(const Ref_t& x)         { m_limits.append(x);     __R;}
       virtual LCDD& addRegion(const Ref_t& x)           { m_regions.append(x);    __R;}
diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp
index 46617752343843361dabb0adc4ac0edc56edf9aa..ad18e0d0619f22f535593e1bf04e5eefe9a697a6 100644
--- a/DDCore/src/Volumes.cpp
+++ b/DDCore/src/Volumes.cpp
@@ -37,6 +37,29 @@ namespace DD4hep  { namespace Geometry  {
     Value(const TGeoVolume* v, const TGeoMatrix* m) : TGeoNodeMatrix(v,m), PlacedVolume::Object() {
       magic = magic_word();
     }
+    Value(const Value& c) : TGeoNodeMatrix(c.GetVolume(),c.GetMatrix()), PlacedVolume::Object(c) {
+    }
+    virtual TGeoNode *MakeCopyNode() const {
+      TGeoNodeMatrix *node = new Value<TGeoNodeMatrix,PlacedVolume::Object>(*this);
+      node->SetName(GetName());
+      // set the mother
+      node->SetMotherVolume(fMother);
+      // set the copy number
+      node->SetNumber(fNumber);
+      // copy overlaps
+      if (fNovlp>0) {
+	if (fOverlaps) {
+	  Int_t *ovlps = new Int_t[fNovlp];
+	  memcpy(ovlps, fOverlaps, fNovlp*sizeof(Int_t));
+	  node->SetOverlaps(ovlps, fNovlp);
+	} else {
+	  node->SetOverlaps(fOverlaps, fNovlp);
+	}
+      }
+      // copy VC
+      if (IsVirtual()) node->SetVirtual();
+      return node;
+    }
   };
   
   template <class T> struct _VolWrap : public T  {
@@ -44,20 +67,20 @@ namespace DD4hep  { namespace Geometry  {
     virtual ~_VolWrap() {}
     virtual void AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t* = "") {
       TGeoMatrix *matrix = mat;
-      if (matrix==0) matrix = gGeoIdentity;
-      else           matrix->RegisterYourself();
-      if (!vol) {
+      if ( matrix == 0 ) matrix = gGeoIdentity;
+      else               matrix->RegisterYourself();
+      if (!vol)   {
         this->T::Error("AddNode", "Volume is NULL");
         return;
       }
-      if (!vol->IsValid()) {
+      if (!vol->IsValid())   {
         this->T::Error("AddNode", "Won't add node with invalid shape");
         printf("### invalid volume was : %s\n", vol->GetName());
         return;
-      }   
-      if (!this->T::fNodes) this->T::fNodes = new TObjArray();   
+      }
+      if ( !this->T::fNodes ) this->T::fNodes = new TObjArray();   
       
-      if (this->T::fFinder) {
+      if ( this->T::fFinder )    {
         // volume already divided.
         this->T::Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, this->T::GetName());
         return;
@@ -99,7 +122,7 @@ namespace DD4hep  { namespace Geometry  {
       ((TObject*)vol)->SetBit(kVolumeClone);
       return vol;       
     }
-    TGeoVolume* CloneVolume() const    {
+    virtual TGeoVolume* CloneVolume() const    {
       TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), fShape, fMedium);
       Int_t i;
       // copy volume attributes
@@ -177,20 +200,58 @@ namespace DD4hep  { namespace Geometry  {
       return vol;
     }
   };
+
 }}
 
+/// Add identifier
+PlacedVolume& PlacedVolume::addPhysVolID(const std::string& name, int value)   {
+  Object* obj = data<Object>();
+  obj->volIDs[name] = value;
+  return *this;
+}
+
+/// Volume material
+Material PlacedVolume::material() const 
+{  return Material::handle_t(m_element ? m_element->GetMedium()->GetMaterial() : 0);  }
+
+/// Logical volume of this placement
+Volume   PlacedVolume::volume() const 
+{  return Volume::handle_t(m_element ? m_element->GetVolume() : 0);                   }
+
+/// Parent volume (envelope)
+Volume PlacedVolume::motherVol() const 
+{  return Volume::handle_t(m_element ? m_element->GetMotherVolume() : 0);             }
+
+/// Access to the volume IDs
+const PlacedVolume::VolIDs& PlacedVolume::volIDs() const 
+{  return data<Object>()->volIDs;                                                     }
+
+/// String dump
+string PlacedVolume::toString() const {
+  stringstream s;
+  Object* obj = data<Object>();
+  s << m_element->GetName() << ":  vol='" << m_element->GetVolume()->GetName()
+    << "' mat:'" << m_element->GetMatrix()->GetName() << "' volID[" << obj->volIDs.size() << "] ";
+  for(VolIDs::const_iterator i=obj->volIDs.begin(); i!=obj->volIDs.end();++i)
+    s << (*i).first << "=" << (*i).second << "  ";
+  s << ends;
+  return s.str();
+}
 
+/// Constructor to be used when creating a new geometry tree.
 Volume::Volume(LCDD& lcdd, const string& name)    {
   m_element = new Value<TGeoVolume,Volume::Object>(name.c_str());
   lcdd.addVolume(*this);
 }
 
+/// Constructor to be used when creating a new geometry tree. Also sets materuial and solid attributes
 Volume::Volume(LCDD& lcdd, const string& name, const Solid& s, const Material& m) {
   m_element = new Value<TGeoVolume,Volume::Object>(name.c_str(),s);
   setMaterial(m);
   lcdd.addVolume(*this);
 }
 
+/// Set the volume's material
 void Volume::setMaterial(const Material& m)  const  {
   if ( m.isValid() )   {
     TGeoMedium* medium = m._ptr<TGeoMedium>();
@@ -203,10 +264,6 @@ void Volume::setMaterial(const Material& m)  const  {
   throw runtime_error("Volume: Attempt to assign invalid material.");
 }
 
-void Volume::setSolid(const Solid& solid)  const  {
-  m_element->SetShape(solid);
-}
-
 static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix* transform) {
   TGeoVolume* parent = par;
   TObjArray* a = parent->GetNodes();
@@ -216,6 +273,7 @@ static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix*
   return PlacedVolume(n);
 }
 
+/// Place translated and rotated daughter volume
 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos, const Rotation& rot)  const  {
   if ( volume.isValid() )   {
     string nam = string(volume.name())+"_placement";
@@ -227,6 +285,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos, cons
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
 
+/// Place un-rotated daughter volume at the given position.
 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos)  const  {
   if ( volume.isValid() )   {
     string nam = string(volume.name())+"_placement";
@@ -236,6 +295,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos)  con
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
 
+/// Place rotated daughter volume. The position is automatically the identity position
 PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot)  const  {
   if ( volume.isValid() )   {
     string nam = string(volume.name())+"_placement";
@@ -245,6 +305,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot)  con
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
 
+/// Place daughter volume. The position and rotation are the identity
 PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityPos& /* pos */)  const  {
   if ( volume.isValid() )   {
     string nam = string(volume.name())+"_placement";
@@ -253,6 +314,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityPos& /* pos
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
 
+/// Place daughter volume. The position and rotation are the identity
 PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityRot& /* rot */)  const  {
   if ( volume.isValid() )   {
     string nam = string(volume.name())+"_placement";
@@ -261,14 +323,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityRot& /* rot
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
 
-void Volume::setRegion(const Region& obj)  const   {
-  data<Object>()->region = obj;
-}
-
-void Volume::setLimitSet(const LimitSet& obj)  const   {
-  data<Object>()->limits = obj;
-}
-
+/// Set Visualization attributes to the volume
 void Volume::setVisAttributes(const VisAttr& attr) const   {
   if ( attr.isValid() )  {
     VisAttr::Object* vis = attr.data<VisAttr::Object>();
@@ -284,6 +339,7 @@ void Volume::setVisAttributes(const VisAttr& attr) const   {
   data<Object>()->vis = attr;
 }
 
+/// Set Visualization attributes to the volume
 void Volume::setVisAttributes(const LCDD& lcdd, const string& name)  const {
   if ( !name.empty() )   {
     VisAttr attr = lcdd.visAttributes(name);
@@ -316,86 +372,49 @@ void Volume::setAttributes(const LCDD& lcdd,
   setVisAttributes(lcdd,vis);
 }
 
-/// Assign the sensitive detector structure
-void Volume::setSensitiveDetector(const SensitiveDetector& obj) const  {
-  data<Object>()->sens_det = obj;
-}
+/// Set the volume's solid shape
+void Volume::setSolid(const Solid& solid)  const  
+{  m_element->SetShape(solid);                              }
 
-/// Access to Solid (Shape)
-Solid Volume::solid() const   {
-  return Solid((*this)->GetShape());
-}
+/// Set the regional attributes to the volume
+void Volume::setRegion(const Region& obj)  const   
+{  data<Object>()->region = obj;                            }
 
-/// Constructor to be used when creating a new geometry tree.
-Assembly::Assembly(LCDD& lcdd, const std::string& name) {
-  m_element = new Value<TGeoVolumeAssembly,Volume::Object>(name.c_str());
-  lcdd.addVolume(*this);
-}
+/// Set the limits to the volume
+void Volume::setLimitSet(const LimitSet& obj)  const   
+{  data<Object>()->limits = obj;                            }
 
-Material Volume::material() const   {
-  return Handle<TGeoMaterial>(m_element->GetMaterial());
-}
+/// Assign the sensitive detector structure
+void Volume::setSensitiveDetector(const SensitiveDetector& obj) const  
+{  data<Object>()->sens_det = obj;                          }
 
-VisAttr Volume::visAttributes() const   {
-  return data<Object>()->vis;
-}
+/// Access to Solid (Shape)
+Solid Volume::solid() const   
+{  return Solid((*this)->GetShape());                       }
 
-Ref_t Volume::sensitiveDetector() const    {
-  return data<Object>()->sens_det;
-}
+/// Access to the Volume material
+Material Volume::material() const   
+{  return Handle<TGeoMaterial>(m_element->GetMaterial());   }
 
-Region Volume::region() const   {
-  return data<Object>()->region;
-}
+/// Access the visualisation attributes
+VisAttr Volume::visAttributes() const
+{  return data<Object>()->vis;                              }
 
-LimitSet Volume::limitSet() const   {
-  return data<Object>()->limits;
-}
+/// Access to the handle to the sensitive detector
+Ref_t Volume::sensitiveDetector() const
+{  return data<Object>()->sens_det;                         }
 
-PlacedVolume& PlacedVolume::addPhysVolID(const std::string& name, int value) {
-  Object* obj = data<Object>();
-  obj->volIDs[name] = value;
-  return *this;
-}
-
-/// Volume material
-Material PlacedVolume::material() const {
-  return Material::handle_t(m_element ? m_element->GetMedium()->GetMaterial() : 0);
-}
+/// Access to the handle to the region structure
+Region Volume::region() const   
+{  return data<Object>()->region;                           }
 
-/// Logical volume of this placement
-Volume   PlacedVolume::volume() const {
-  return Volume::handle_t(m_element ? m_element->GetVolume() : 0);
-}
+/// Access to the limit set
+LimitSet Volume::limitSet() const   
+{  return data<Object>()->limits;                           }
 
-/// Parent volume (envelope)
-Volume PlacedVolume::motherVol() const {
-  return Volume::handle_t(m_element ? m_element->GetMotherVolume() : 0);
-}
-
-/// Access to the volume IDs
-const PlacedVolume::VolIDs& PlacedVolume::volIDs() const {
-  return data<Object>()->volIDs;
-}
-
-/// Set the detector handle
-void PlacedVolume::setDetElement(Ref_t detector)   const {
-  data<Object>()->detector = detector;
-}
-
-/// Access to the corresponding detector element (maybe invalid)
-Ref_t PlacedVolume::detElement() const {
-  return data<Object>()->detector;
+/// Constructor to be used when creating a new geometry tree.
+Assembly::Assembly(LCDD& lcdd, const std::string& name) {
+  m_element = new Value<TGeoVolumeAssembly,Volume::Object>(name.c_str());
+  lcdd.addVolume(*this);
 }
 
-/// String dump
-string PlacedVolume::toString() const {
-  stringstream s;
-  Object* obj = data<Object>();
-  s << m_element->GetName() << ":  vol='" << m_element->GetVolume()->GetName()
-  << "' mat:'" << m_element->GetMatrix()->GetName() << "' volID[" << obj->volIDs.size() << "] ";
-  for(VolIDs::const_iterator i=obj->volIDs.begin(); i!=obj->volIDs.end();++i)
-    s << (*i).first << "=" << (*i).second << "  ";
-  s << ends;
-  return s.str();
-}
diff --git a/DDCore/src/compact/LCDD2Output.cpp b/DDCore/src/compact/LCDD2Output.cpp
index af0ae3230b2dfe5bf1e433dc569d23c0bea22597..ec5c0bb62ec5b089c20148da5f888e0d4828d1e9 100644
--- a/DDCore/src/compact/LCDD2Output.cpp
+++ b/DDCore/src/compact/LCDD2Output.cpp
@@ -69,7 +69,7 @@ namespace DD4hep { namespace Geometry {
     if ( obj )  {
       char text[256];
       const DetElement& sd = val;
-      PlacedVolume plc = sd.placements()[0];
+      PlacedVolume plc = sd.placement();
       bool rdo = sd.readout().isValid();
       bool vis = plc.isValid();
       bool env = plc.isValid();