From 28406391a25efe8e81cf4cf5bb62375dcbf79189 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Thu, 9 Aug 2012 14:29:50 +0000
Subject: [PATCH] Support for user defined Segmentation objects

---
 DDCore/include/DD4hep/DetFactoryHelper.h |   1 +
 DDCore/include/DD4hep/Detector.h         |  69 ++++--
 DDCore/include/DD4hep/Factories.h        |  26 +--
 DDCore/include/DD4hep/GeoHandler.h       |  27 +--
 DDCore/include/DD4hep/Handle.h           |   6 +
 DDCore/include/DD4hep/Objects.h          | 109 +++++++--
 DDCore/include/DD4hep/Readout.h          |   2 +-
 DDCore/include/DD4hep/Segmentations.h    |  76 +++++--
 DDCore/include/DD4hep/Volumes.h          |   1 +
 DDCore/include/XML/XMLElements.h         |  55 +++--
 DDCore/src/Detector.cpp                  | 113 ++++++----
 DDCore/src/GeoHandler.cpp                |   7 +
 DDCore/src/Handle.cpp                    |  16 ++
 DDCore/src/LCDDImp.cpp                   | 102 +++++----
 DDCore/src/Objects.cpp                   |  74 +++++--
 DDCore/src/Readout.cpp                   |   2 +-
 DDCore/src/Segementations.cpp            |  42 ++++
 DDCore/src/Volumes.cpp                   |  21 +-
 DDCore/src/XML/DocumentHandler.cpp       |   6 +-
 DDCore/src/XML/XMLDetector.cpp           |   4 +-
 DDCore/src/XML/XMLElements.cpp           |   4 +
 DDCore/src/compact/Compact2Objects.cpp   | 269 +++++++++++++----------
 22 files changed, 676 insertions(+), 356 deletions(-)

diff --git a/DDCore/include/DD4hep/DetFactoryHelper.h b/DDCore/include/DD4hep/DetFactoryHelper.h
index c8b0c1469..b38dd17c4 100644
--- a/DDCore/include/DD4hep/DetFactoryHelper.h
+++ b/DDCore/include/DD4hep/DetFactoryHelper.h
@@ -18,6 +18,7 @@
 #define _A(a) DD4hep::XML::Attr_##a
 
 // Shortcuts to elements of the XML namespace
+typedef DD4hep::XML::Attribute     xml_attr_t;
 typedef DD4hep::XML::Collection_t  xml_coll_t;
 typedef DD4hep::XML::Handle_t      xml_h;
 typedef DD4hep::XML::RefElement    xml_ref_t;
diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h
index 38bdb3688..dffeca72a 100644
--- a/DDCore/include/DD4hep/Detector.h
+++ b/DDCore/include/DD4hep/Detector.h
@@ -48,13 +48,12 @@ namespace DD4hep {
       struct Object  {
         unsigned int magic;
         int          verbose;
-        int          combine_hits;
+        int          combineHits;
         double       ecut;
-        std::string  eunit;
-        std::string  hits_collection;
+        std::string  hitsCollection;
 	Readout      readout;
 	Extensions   extensions;
-        Object() : magic(magic_word()), verbose(0), readout(), extensions() {}
+        Object() : magic(magic_word()), verbose(0), combineHits(0), ecut(0.0), hitsCollection(), readout(), extensions() {}
       };
       protected:
 
@@ -72,12 +71,15 @@ namespace DD4hep {
       /// Default constructor
       SensitiveDetector() : Ref_t() {}
 
+      /// Copy from handle
+      SensitiveDetector(const SensitiveDetector& sd) : Ref_t(sd) {}
+      
       /// Templated constructor for handle conversions
       template <typename Q>
       SensitiveDetector(const Handle<Q>& e) : Ref_t(e) {}
 
       /// Constructor for a new sensitive detector element
-      SensitiveDetector(const std::string& type, const std::string& name);
+      SensitiveDetector(const std::string& name, const std::string& type);
       
       /// Additional data accessor
       Object& _data()   const {  return *data<Object>();  }
@@ -85,18 +87,39 @@ namespace DD4hep {
       /// Access the type of the sensitive detector
       std::string type() const;
 
+      ///  Set detector type (structure, tracker, calorimeter, etc.). 
+      SensitiveDetector& setType(const std::string& typ);
+
+      /// Set flag to handle hits collection
+      SensitiveDetector& setVerbose(bool value);
+
+      /// Access flag to combine hist
+      bool verbose() const;
+
       /// Set flag to handle hits collection
       SensitiveDetector& setCombineHits(bool value);
 
+      /// Access flag to combine hist
+      bool combineHits() const;
+
       /// Assign the name of the hits collection
       SensitiveDetector& setHitsCollection(const std::string& spec);
 
+      /// Access the hits collection name
+      const std::string& hitsCollection() const;
+
       /// Assign the IDDescriptor reference
       SensitiveDetector& setReadout(Readout readout);
 
       /// Access readout structure of the sensitive detector
       Readout readout() const;
 
+      /// Set energy cut off
+      SensitiveDetector& setEnergyCutoff(double value);
+
+      /// Access energy cut off
+      double energyCutoff()  const;
+
       /// Extend the sensitive detector element with an arbitrary structure accessible by the type
       template<typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c)    
       {  return (IFACE*)i_addExtension(dynamic_cast<IFACE*>(c),typeid(IFACE),_delete<IFACE>);  }      
@@ -108,13 +131,9 @@ namespace DD4hep {
     
     /** @class SubDetector Detector.h DD4hep/lcdd/Detector.h
      *
-     *  Please note: 
-     *  Though nowhere enforced, it is obvious that only placements
-     *  of the **SAME** logical volume should be added.
-     *
-     *  We explicitly rely here on the common sense of the user
-     *  of this class. People without a brain can always screw 
-     *  things completely - nothing one can do about!
+     *  The basic object type to access all information of a given
+     *  Subdetector including it's hierarchical structure with
+     *  other dependending DetElement daughters.
      *
      *  @author  M.Frank
      *  @version 1.0
@@ -122,7 +141,6 @@ namespace DD4hep {
     struct DetElement : public Ref_t   {
       typedef Ref_t                                  Parent;
       typedef std::map<std::string,DetElement>       Children;
-      typedef std::vector<PlacedVolume>              Placements;
       typedef std::map<const std::type_info*,void*>  Extensions;
 
       enum {
@@ -135,14 +153,14 @@ namespace DD4hep {
       struct Object  {
         unsigned int      magic;
         int               id;
+	/// Full path to this detector element. May be invalid
 	std::string       path;
-        int               combine_hits;
+        int               combineHits;
         Volume            volume;
         Readout           readout;
         Alignment         alignment;
         Conditions        conditions;
 	PlacedVolume      placement;
-        Placements        placements;
 	Parent            parent;
 	Parent            reference;
         Children          children;
@@ -229,15 +247,24 @@ namespace DD4hep {
       template <class T> T* extension()  const
       {  return (T*)i_extension(typeid(T));      }
 
-      DetElement&     setCombineHits(bool value, SensitiveDetector& sens);
+      /// Set the detector identifier
       int             id() const;
+      /// Setter: Combine hits attribite
+      DetElement&     setCombineHits(bool value, SensitiveDetector& sens);
+      /// Getter: Combine hits attribite
+      bool            combineHits() const;
+
+      /// Access detector type (structure, tracker, calorimeter, etc.). 
+      /** Required for determination of G4 sensitive detector.
+       */
       std::string     type() const;
+      ///  Set detector type (structure, tracker, calorimeter, etc.). 
+      DetElement& setType(const std::string& typ);
+
+      /// Path of the detector element (not necessarily identical to placement path!)
       std::string     path() const;
       /// Access to the full path to the placed object
       std::string     placementPath() const;
-      bool            isTracker() const;
-      bool            isCalorimeter() const;
-      bool            combineHits() const;
       
       /// Set all attributes in one go
       DetElement& setAttributes(const LCDD& lcdd, const Volume& volume,
@@ -257,10 +284,8 @@ namespace DD4hep {
       /// Assign readout definition
       DetElement&     setReadout(const Readout& readout);
 
-      /// Access to the logical volume of the placements (all daughters have the same!)
+      /// Access to the logical volume of the daughter placement
       Volume          volume() const;
-      /// Set the logical volume of the placements (all daughters have the same!)
-      //void            setVolume(Volume vol);
 
       /// Access to the physical volume of this detector element
       PlacedVolume    placement() const;
diff --git a/DDCore/include/DD4hep/Factories.h b/DDCore/include/DD4hep/Factories.h
index 4a4761538..e2fac36a7 100644
--- a/DDCore/include/DD4hep/Factories.h
+++ b/DDCore/include/DD4hep/Factories.h
@@ -6,8 +6,8 @@
 //  Author     : M.Frank
 //
 //====================================================================
-#ifndef DD4hep_FACTORIES_H
-#define DD4hep_FACTORIES_H
+#ifndef DD4HEP_FACTORIES_H
+#define DD4HEP_FACTORIES_H
 
 #ifndef __CINT__
 #include "Reflex/PluginService.h"
@@ -132,20 +132,20 @@ namespace {
   PLUGINSVC_FACTORY_WITH_ID(x,std::string(#x),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*,DD4hep::Geometry::SensitiveDetector*))
 
 #define DECLARE_TRANSLATION(name,func) \
-  namespace DD4hep { namespace Geometry { namespace { struct name {}; }                  \
-  template <> Ref_t TranslationFactory<name>::create(LCDD& lcdd) {return func(lcdd);} }} \
+  namespace DD4hep { namespace Geometry { namespace { struct name {}; }            \
+  template <> Ref_t TranslationFactory<name>::create(LCDD& l) {return func(l);} }} \
   DECLARE_NAMED_TRANSLATION_FACTORY(DD4hep::Geometry,name)
 
 #define DECLARE_XMLELEMENT(name,func) \
-  namespace DD4hep { namespace Geometry { namespace { struct name {}; }                 \
-  template <> Ref_t XMLElementFactory<name>::create(LCDD& lcdd, const XML::Handle_t& e) \
-    {   return func(lcdd,e);} }}						        \
-  DECLARE_NAMED_XMLELEMENT_FACTORY(DD4hep::Geometry,name)
+  namespace DD4hep { namespace Geometry { namespace { struct xml_element_##name {}; }                \
+  using DD4hep::Geometry::xml_element_##name;					                     \
+  template <> Ref_t XMLElementFactory<xml_element_##name>::create(LCDD& l,const XML::Handle_t& e) {return func(l,e);} }}\
+  PLUGINSVC_FACTORY_WITH_ID(xml_element_##name,std::string(#name),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*))
 
 #define DECLARE_DETELEMENT(name,func) \
-  namespace DD4hep { namespace Geometry { namespace { struct name {}; }                                       \
-  template <> Ref_t DetElementFactory<name>::create(LCDD& lcdd, const XML::Handle_t& e, SensitiveDetector& s) \
-    {   return func(lcdd,e,s);} }}						                              \
-  DECLARE_NAMED_DETELEMENT_FACTORY(DD4hep::Geometry,name)
+  namespace DD4hep { namespace Geometry { namespace { struct det_element_##name {}; }                                       \
+  using DD4hep::Geometry::det_element_##name;                                                                               \
+  template <> Ref_t DetElementFactory<det_element_##name>::create(LCDD& l,const XML::Handle_t& e,SensitiveDetector& s){return func(l,e,s);}}}\
+  PLUGINSVC_FACTORY_WITH_ID(det_element_##name,std::string(#name),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*,DD4hep::Geometry::SensitiveDetector*))
 
-#endif // DD4hep_FACTORIES_H
+#endif // DD4HEP_FACTORIES_H
diff --git a/DDCore/include/DD4hep/GeoHandler.h b/DDCore/include/DD4hep/GeoHandler.h
index 02fe51519..a53c3f993 100644
--- a/DDCore/include/DD4hep/GeoHandler.h
+++ b/DDCore/include/DD4hep/GeoHandler.h
@@ -42,16 +42,28 @@ namespace DD4hep {
       typedef std::vector<std::pair<std::string, TGeoMatrix*> >  TransformSet;
       typedef std::set<TGeoShape*>                               SolidSet;
       typedef std::set<TGeoMedium*>                              MaterialSet;
+      typedef std::map<TNamed*,std::set<const TGeoVolume*> >     SensitiveVolumes;
+      typedef std::map<TNamed*,std::set<const TGeoVolume*> >     RegionVolumes;
+      typedef std::map<TNamed*,std::set<const TGeoVolume*> >     LimitVolumes;
       typedef std::map<int, std::set<const TGeoNode*> >          Data;
       typedef std::set<TNamed*>                                  VisRefs;
       typedef LCDD::HandleMap                                    DefinitionSet;
 
+      typedef Geometry::LCDD              LCDD;
+      typedef Geometry::Volume            Volume;
+      typedef Geometry::PlacedVolume      PlacedVolume;
+      typedef Geometry::DetElement        DetElement;
+      typedef Geometry::SensitiveDetector SensitiveDetector;
+
       struct GeometryInfo   {
 	SolidSet           solids;
 	VolumeSet          volumes;
 	TransformSet       trafos;
 	VisRefs            vis;
 	MaterialSet        materials;
+	// SensitiveVolumes   sensitives;
+	// RegionVolumes      regions;
+	// LimitVolumes       limits;
 	std::set<TGeoMedium*>   media;
 	std::set<TGeoElement*>  elements;
       };
@@ -74,21 +86,6 @@ namespace DD4hep {
       GeoHandler& collect(DetElement top, GeometryInfo& info);
       /// Access to collected node list
       Data* release();
-#if  0
-      template <typename C, typename F> static void _handle(const O* ptr, const C& c, F pmf)  {
-	for(typename C::const_iterator i=c.begin(); i != c.end(); ++i)   {
-	  (ptr->*pmf)((*i).first, (*i).second);
-	}
-      }
-#endif
-      template <typename O, typename C, typename F> static void handle(const O* o, const C& c, F pmf)    {
-	for(typename C::const_iterator i=c.begin(); i != c.end(); ++i)
-	  (o->*pmf)((*i)->GetName(),*i);
-      }
-      template <typename O, typename C, typename F> static void handle(O* o, const C& c, F pmf)     {
-	for(typename C::const_iterator i=c.begin(); i != c.end(); ++i)
-	  (o->*pmf)((*i)->GetName(),*i);
-      }
     };
 
     struct GeoScan {
diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h
index 58157c6c9..0441804bd 100644
--- a/DDCore/include/DD4hep/Handle.h
+++ b/DDCore/include/DD4hep/Handle.h
@@ -63,6 +63,12 @@ namespace DD4hep {
     inline int     _toInt(int value)         {  return value; }
     inline float   _toFloat(float value)     {  return value; }
     inline double  _toDouble(double value)   {  return value; }
+
+    template<class T> T _multiply(const std::string& left, const std::string& right);
+    template <> int    _multiply<int>(const std::string& left, const std::string& right);
+    template <> long   _multiply<long>(const std::string& left, const std::string& right);
+    template <> float  _multiply<float>(const std::string& left, const std::string& right);
+    template <> double _multiply<double>(const std::string& left, const std::string& right);
     
     void _toDictionary(const std::string& name, const std::string& value);
     
diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h
index e879bde4e..51b380ddb 100644
--- a/DDCore/include/DD4hep/Objects.h
+++ b/DDCore/include/DD4hep/Objects.h
@@ -22,6 +22,8 @@ class TGeoPhysicalNode;
 #include "TGeoPhysicalNode.h"
 
 // C/C++ include files
+#include <set>
+
 #define _USE_MATH_DEFINES
 #include <cmath>
 #ifndef M_PI
@@ -112,18 +114,55 @@ namespace DD4hep {
       /// 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;       }
+      /// Ceck 2 positions for equality
+      bool operator==(const Position& c)  const       { return x==c.x && y==c.y && z==c.z; }
+      /// Ceck 2 positions for in-equality
+      bool operator!=(const Position& c)  const       { return x!=c.x || y!=c.y || x!=c.z; }
+      /// Negation of the direction
+      Position operator - () const                    { return Position(-x,-y,-z);         }
+      /// Scalar multiplication
+      Position& operator *=(double a)                 { x *= a;y *= a;z *= a;return *this; }
+      /// Addition operator
+      Position& operator +=(const Position& p)        { x+=p.x;y+=p.y;z+=p.z;return *this; }
+      /// Subtraction operator
+      Position& operator -= (const Position& p)       { x-=p.x;y-=p.y;z-=p.z;return *this; }
+
+      /// Position length
+      double length() const                           { return sqrt(x*x + y*y + z*z);      }
       /// Access to array like coordinates
-      const double* coordinates() const               { return &x;                      }
+      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; }
+      Position& set(double xv, double yv, double zv)  { x=xv; y=yv; z=zv; return *this;    }
     };
 #ifdef _WIN32
 #pragma pack(pop,DD4Hep_Objects_Position)
 #pragma pack(push,DD4Hep_Objects_Rotation,1)
 #endif
+    /// Addition of 2 positions
+    inline Position operator + (const Position& l, const Position& r)
+    {  return Position(l.x+r.x,l.y+r.y,l.z+r.z);                                           }
+    /// Subtraction of to positions
+    inline Position operator - (const Position& l, const Position& r)
+    {  return Position(l.x-r.x,l.y-r.y,l.z-r.z);                                           }
+    /// Dot product of 3-vectors.
+    inline double operator * (const Position& l, const Position& r)
+    {  return sqrt(l.x*r.x + l.y*r.y + l.z*r.z);                                           }
+    /// Positions scaling from left
+    inline Position operator * (double l, const Position& r) 
+    {  return Position(r.x*l,r.y*l,r.z*l);                                                 }
+    /// Positions scaling from right
+    inline Position operator * (const Position& l, double r)
+    {  return Position(l.x*r,l.y*r,l.z*r);                                                 }
+    /// Positions scaling from right
+    inline Position operator / (const Position& l, double r)
+    {  return Position(l.x/r,l.y/r,l.z/r);                                                 }
+
+    typedef Position Direction;
+    typedef Position Momentum;
+
     /** @class Rotation Objects.h
      *  
      *  @author  M.Frank
@@ -136,11 +175,15 @@ namespace DD4hep {
       /// 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;   }
+      bool isNull() const                              { return theta==0 && phi==0 && psi==0;              }
+      /// Ceck 2 rotations for equality
+      bool operator==(const Rotation& c)  const        { return theta==c.theta && phi==c.phi && psi==c.psi;}
+      /// Ceck 2 rotations for in-equality 
+      bool operator!=(const Rotation& c)  const        { return theta!=c.theta || phi!=c.phi || psi!=c.psi;}
       /// Access to array like coordinates
-      const double* angles() const                     { return &theta;                         }
+      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; }
+      Rotation& set(double th, double ph, double ps)   { theta=th; phi=ph; psi=ps;return *this;            }
     };
 
 #ifdef _WIN32
@@ -324,20 +367,29 @@ namespace DD4hep {
 
 
     /** @class Limit Objects.h
-     *  
+     *  Small object describing a limit structure 
+     * 
      *  @author  M.Frank
      *  @version 1.0
      */
-    struct Limit : public Ref_t  {
-      typedef std::pair<std::string,double> Object;
-
-      /// Constructor to be used when creating a new limit object
-      Limit(LCDD& doc, const std::string& name);
-      /// Additional data accessor
-      Object& _data()   const {  return *data<Object>();  }
-      void setParticles(const std::string& particleNames);
-      void setValue(double value);
-      void setUnit(const std::string& unit);
+    struct Limit {
+      std::string particles;
+      std::string name;
+      std::string unit;
+      std::string content;
+      double      value;
+      /// Default constructor
+      Limit() : particles(), name(), unit(), content(), value(0.0) {}
+      /// Copy constructor
+      Limit(const Limit& c) : particles(c.particles), name(c.name), unit(c.unit), content(c.content), value(c.value)  {}
+      /// Assignment operator
+      Limit& operator=(const Limit& c);
+      /// Equality operator
+      bool operator==(const Limit& c) const;
+      /// operator less
+      bool operator< (const Limit& c) const;
+      /// Conversion to a string representation
+      std::string toString()  const;
     };
 
     /** @class LimitSet Objects.h
@@ -346,15 +398,18 @@ namespace DD4hep {
      *  @version 1.0
      */
     struct LimitSet : public Ref_t  {
-      typedef TMap Object;
+      typedef std::set<Limit> Object;  
       /// Constructor to be used when reading the already parsed DOM tree
       LimitSet() : Ref_t() {}
       /// Constructor to be used when reading the already parsed DOM tree
       template <typename Q> 
       LimitSet(const Handle<Q>& e) : Ref_t(e) {}
       /// Constructor to be used when creating a new DOM tree
-      LimitSet(LCDD& doc, const std::string& name);
-      void addLimit(const Ref_t& limit);
+      LimitSet(const std::string& name);
+      /// Add new limit. Returns true if the new limit was added, false if it already existed.
+      bool addLimit(const Limit& limit);
+      /// Accessor to limits container
+      const Object& limits() const;
     };
 
     /** @class Region Objects.h
@@ -369,6 +424,7 @@ namespace DD4hep {
         double        cut;
         bool          store_secondaries;
         std::string   lunit, eunit;
+	std::vector<std::string> user_limits;
       };
       /// Default constructor
       Region() : Ref_t() {}
@@ -376,7 +432,7 @@ namespace DD4hep {
       template <typename Q> 
       Region(const Handle<Q>& e) : Ref_t(e) {}
       /// Constructor to be used when creating a new DOM tree
-      Region(LCDD& doc, const std::string& name);
+      Region(const std::string& name);
 
       /// Additional data accessor
       Object& _data()   const {  return *data<Object>();  }
@@ -385,6 +441,15 @@ namespace DD4hep {
       Region& setCut(double value);
       Region& setLengthUnit(const std::string& unit);
       Region& setEnergyUnit(const std::string& unit);
+      /// Access references to user limits
+      std::vector<std::string>& limits() const;
+
+      /// Access cut value
+      double  cut() const;
+      /// Access production threshold
+      double threshold() const;
+      /// Access secondaries flag
+      bool storeSecondaries() const;
     };
 
     /** @class IDSpec Objects.h
diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h
index 4bce185d1..d4a9e9b5f 100644
--- a/DDCore/include/DD4hep/Readout.h
+++ b/DDCore/include/DD4hep/Readout.h
@@ -49,7 +49,7 @@ namespace DD4hep {
       /// Constructor to be used when reading the already parsed object
       template <typename Q> Readout(const Handle<Q>& e) : Ref_t(e) {}
       /// Initializing constructor
-      Readout(const LCDD& doc, const std::string& name);
+      Readout(const std::string& name);
       /// Assign IDDescription to readout structure
       void setIDDescriptor(const Ref_t& spec)   const;
       /// Access IDDescription structure
diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h
index 80d07864a..86292f90e 100644
--- a/DDCore/include/DD4hep/Segmentations.h
+++ b/DDCore/include/DD4hep/Segmentations.h
@@ -7,12 +7,15 @@
 //
 //====================================================================
 
-#ifndef DD4hep_GEOMETRY_SEGMENTATIONS_H
-#define DD4hep_GEOMETRY_SEGMENTATIONS_H
+#ifndef DD4HEP_GEOMETRY_SEGMENTATIONS_H
+#define DD4HEP_GEOMETRY_SEGMENTATIONS_H
 
 // Framework include files
 #include "DD4hep/Handle.h"
 
+// C/C++ include files
+#include <cmath>
+
 /*
  *   DD4hep namespace declaration
  */
@@ -29,38 +32,64 @@ namespace DD4hep {
      * @version 1.0
      */
     struct Segmentation : public Ref_t   {
+      public:
+      enum { REGULAR=0, EXTENDED=1 };
+
       struct Object  {
+	/// Magic word to check object integrity
 	unsigned long magic;
+	/// Segmentation type (REGULAR or EXTENDED)
+	unsigned char type;
+	/// Flag to use segmentation for hit positioning
         unsigned char useForHitPosition;
-        union {
-          double values[10];
-          struct {
+	/// Spares to start 16 byte Byte aligned
+	unsigned char _spare[6];
+
+        union Data {
+	  /// Maximal size and data buffer for specialized user segentations
+          double values[32];
+	  /// Extension buffer for specialized user segentations, where above values are insufficient
+	  struct Extension {
+	    const std::type_info* info;
+	    void (*destructor)(void*);
+	    void* ptr;
+	  } extension;
+	  /// No the regular structures for default segmentations
+          struct Cartesian {
             int nx;
             int ny;
             int nz;
           } cartesian;
-          struct {
+          struct CartesianGrid {
             double grid_size_x;
             double grid_size_y;
             double grid_size_z;
           } cartesian_grid;
-          struct {
+          struct CylindricalBinning  {
             int nphi;
             int ntheta;
             int nz;
           } cylindrical_binning;
-          struct {
+          struct CylindricalGrid   {
             double grid_size_phi;
             double grid_size_theta;
             double grid_size_z;
-          } cylindrical_grid;        
+          } cylindrical_grid;
+	    
         } data;
-        Object() : useForHitPosition(0) {
-          data.cartesian_grid.grid_size_x = 0;
-          data.cartesian_grid.grid_size_y = 0;
-          data.cartesian_grid.grid_size_z = 0;
-        }
+	Object();
+	~Object();
       };
+
+      protected:
+      /// Templated destructor function
+      template <typename T> static void  _delete(void* ptr) { delete (T*)(ptr); }
+      /// Add an extension object to the detector element
+      void* i_setExtension(void* ptr, const std::type_info& info, void (*destruct)(void*));
+      /// Access an existing extension object from the detector element
+      void* i_extension(const std::type_info& info)  const;
+
+      public:
       /// Default constructor
       Segmentation() : Handle<Implementation>() {}
       /// Constructor to be used when reading the already parsed object
@@ -69,11 +98,23 @@ namespace DD4hep {
       /// Constructor to create a new segmentation object (to be called by super class only)
       Segmentation(const std::string& type);
       /// Accessor to ata structure
-      Object& _data() const {  return *data<Object>(); }
+      Object& _data() const                            {  return *data<Object>();               }
       /// Access flag for hit positioning
       bool useForHitPosition() const;
       /// Segmentation type
       const std::string type() const;
+      /// Extend the segmentation object with an arbitrary structure accessible by the type
+      template<typename IFACE, typename CONCRETE> IFACE* setExtension(CONCRETE* c)    
+      {  return (IFACE*)i_addExtension(dynamic_cast<IFACE*>(c),typeid(IFACE),_delete<IFACE>);   }
+      /// Access extension element by the type
+      template <class T> T* extension()  const         {  return (T*)i_extension(typeid(T));    }
+      /// Access extension element by the type
+      template <class T> T* extensionUnchecked() const {  return (T*)_data().data.extension.ptr;}
+
+      /// Compute the coordinate in one dimension given a eauidistant bin value.
+      static double binCenter(int bin, double width)   {  return (double(bin) + .5) * width;    }
+      /// Compute the equidistant bin given a coordinate in one dimension.
+      static int bin(double value, double width)       {  return int(floor(value/width));       }
     };
 
     /** @class ProjectiveCylinder Segmentations.h DD4hep/lcdd/Segmentations.h
@@ -200,6 +241,7 @@ namespace DD4hep {
       GlobalGridXY() : GridXY("global_grid_xy") {}
     };
 
-  }       /* End namespace Geometry               */
+
+  }       /* End namespace Geometry              */
 }         /* End namespace DD4hep                */
-#endif    /* DD4hep_GEOMETRY_SEGMENTATIONS_H     */
+#endif    /* DD4HEP_GEOMETRY_SEGMENTATIONS_H     */
diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h
index 222c819db..42eda251f 100644
--- a/DDCore/include/DD4hep/Volumes.h
+++ b/DDCore/include/DD4hep/Volumes.h
@@ -104,6 +104,7 @@ namespace DD4hep {
         Ref_t         sens_det;
 	int           referenced;
         Object() : region(), limits(), vis(), sens_det(), referenced(0)  {}
+        void copy(const Object& c) { region=c.region; limits=c.limits; vis=c.vis; sens_det=c.sens_det; referenced=c.referenced; }
       };
       /// Default constructor
       Volume() : Base(0) {}
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index 875e2eddf..8c376b688 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -103,6 +103,7 @@ namespace DD4hep {
       Handle_t clone(xercesc::DOMDocument* new_doc, bool deep) const;
       bool hasAttr(const XMLCh* t) const                    { return 0 != m_node->getAttributeNode(t);    }
       bool hasAttr(const char* t) const                     { return 0 != m_node->getAttributeNode(Strng_t(t));}
+      template <class T> T attr(const Attribute a)  const;
       template <class T> T attr(const XMLCh* t)  const;
       template <class T> T attr(const char* t)  const       { return this->attr<T>(Strng_t(t));            }
       void setAttrs(Handle_t e) const;
@@ -130,40 +131,50 @@ namespace DD4hep {
       void removeChildren(const XMLCh* tag)  const;
       void append(xercesc::DOMElement* e) const { m_node->appendChild(e); }
       const XMLCh* attr_value(const XMLCh* attr)  const;
+      const XMLCh* attr_value(const Attribute attr)  const;
+      const XMLCh* attr_value_nothrow(const XMLCh* attr)  const;
+
       Attribute attr_ptr(const XMLCh* attr)  const;
       Attribute attr_nothrow(const XMLCh* tag)  const { return m_node->getAttributeNode(tag);  }
-      const XMLCh* attr_value_nothrow(const XMLCh* attr)  const;
     };
 
 #define INLINE inline
-    template <> INLINE Attribute Handle_t::attr<Attribute>(const XMLCh* tag) const {
-      return attr_ptr(tag);
-    }
+    template <> INLINE Attribute Handle_t::attr<Attribute>(const XMLCh* tag) const 
+      {      return attr_ptr(tag);                       }
 
     typedef const XMLCh* cpXMLCh;
-    template<> INLINE cpXMLCh Handle_t::attr<cpXMLCh>(const XMLCh* tag)  const  {
-      return attr_value(tag);
-    }
+    template<> INLINE cpXMLCh Handle_t::attr<cpXMLCh>(const XMLCh* tag)  const  
+      {      return attr_value(tag);                     }
+
+    template<> INLINE bool Handle_t::attr<bool>(const XMLCh* tag)  const  
+      {      return _toBool(attr_value_nothrow(tag));    }
+
+    template<> INLINE int Handle_t::attr<int>(const XMLCh* tag)  const  
+      {      return _toInt(attr_value(tag));             }
+
+    template<> INLINE float Handle_t::attr<float>(const XMLCh* tag)  const
+      {      return _toFloat(attr_value(tag));           }
+
+    template<> INLINE double Handle_t::attr<double>(const XMLCh* tag)  const  
+      {      return _toDouble(attr_value(tag));          }
+
+    template<> INLINE std::string Handle_t::attr<std::string>(const XMLCh* tag)  const  
+      {      return _toString(attr_nothrow(tag));        }
 
-    template<> INLINE bool Handle_t::attr<bool>(const XMLCh* tag)  const  {
-      return _toBool(attr_value_nothrow(tag));
-    }
+    template<> INLINE bool Handle_t::attr<bool>(const Attribute tag)  const  
+      {      return _toBool(attr_value(tag));            }
 
-    template<> INLINE int Handle_t::attr<int>(const XMLCh* tag)  const  {
-      return _toInt(attr_value(tag));
-    }
+    template<> INLINE int Handle_t::attr<int>(const Attribute tag)  const  
+      {      return _toInt(attr_value(tag));             }
 
-    template<> INLINE float Handle_t::attr<float>(const XMLCh* tag)  const  {
-      return _toFloat(attr_value(tag));
-    }
+    template<> INLINE float Handle_t::attr<float>(const Attribute tag)  const  
+      {      return _toFloat(attr_value(tag));           }
 
-    template<> INLINE double Handle_t::attr<double>(const XMLCh* tag)  const  {
-      return _toDouble(attr_value(tag));
-    }
+    template<> INLINE double Handle_t::attr<double>(const Attribute tag)  const  
+      {      return _toDouble(attr_value(tag));          }
 
-    template<> INLINE std::string Handle_t::attr<std::string>(const XMLCh* tag)  const  {
-      return _toString(attr_nothrow(tag));
-    }
+    template<> INLINE std::string Handle_t::attr<std::string>(const Attribute tag)  const  
+      {      return _toString(attr_value(tag));          }
 
     struct Collection_t : public Handle_t {
       mutable XMLSize_t     m_index;
diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp
index 622e82940..f5be04f41 100644
--- a/DDCore/src/Detector.cpp
+++ b/DDCore/src/Detector.cpp
@@ -123,8 +123,8 @@ static DetElement _par(DetElement o, DetElement top, vector<TGeoNode*>& det_node
 
 /// Default constructor
 DetElement::Object::Object()  
-  : magic(magic_word()), id(0), combine_hits(0), readout(), 
-    alignment(), placement(), placements(), parent(), children(),
+  : magic(magic_word()), id(0), combineHits(0), readout(), 
+    alignment(), placement(), parent(), children(),
     worldTrafo(0), parentTrafo(0), referenceTrafo(0)
 {
 }
@@ -135,14 +135,13 @@ Value<TNamed,DetElement::Object>* DetElement::Object::clone(int new_id, int flag
   const ExtensionMap& m = detelement_extensions();
   Ref_t det(obj);
   obj->id           = new_id;
-  obj->combine_hits = combine_hits;
+  obj->combineHits  = combineHits;
   obj->readout      = readout;
   obj->volume       = volume;
   obj->alignment    = Alignment();
   obj->conditions   = Conditions();
   obj->parent       = DetElement();
   obj->placement    = ((flag&COPY_PLACEMENT) == COPY_PLACEMENT) ? placement : PlacedVolume();
-  obj->placements   = ((flag&COPY_PLACEMENT) == COPY_PLACEMENT) ? placements : Placements();
 
   // This implicitly assumes that the children do not access the parent's extensions!
   obj->extensions.clear();
@@ -244,7 +243,7 @@ DetElement::DetElement(const string& name, int id)   {
 
 /// Constructor for a new subdetector element
 DetElement::DetElement(DetElement parent, const string& name, int id)   {
-  assign(new Value<TNamed,Object>(),name,"");
+  assign(new Value<TNamed,Object>(),name,parent.type());
   _data().id = id;
   parent.add(*this);
 }
@@ -308,6 +307,15 @@ string DetElement::type() const   {
   return m_element ? m_element->GetTitle() : "";
 }
 
+/// Set the type of the sensitive detector
+DetElement& DetElement::setType(const std::string& typ)   {
+  if ( isValid() )  {
+    m_element->SetTitle(typ.c_str());
+    return *this;
+  }
+  throw runtime_error("DetElement::setType: Self is not defined [Invalid Handle]");
+}
+
 string DetElement::path() const   {
   if ( m_element )  {
     Object& o = _data();
@@ -325,7 +333,13 @@ int DetElement::id() const   {
 }
 
 bool DetElement::combineHits() const   {
-  return _data().combine_hits != 0;
+  return _data().combineHits != 0;
+}
+
+DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens)   {
+  _data().combineHits = value;
+  if ( sens.isValid() ) sens.setCombineHits(value);
+  return *this;
 }
 
 Readout DetElement::readout() const   {
@@ -423,15 +437,7 @@ Volume DetElement::volume() const   {
   }
   throw runtime_error("DetElement::volume: Self is not defined [Invalid Handle]");
 }
-#if 0
-/// Set the logical volume of the placements (all daughters have the same!)
-void DetElement::setVolume(Volume vol) {
-  if ( isValid() )  {
-    _data().volume = vol;
-  }
-  throw runtime_error("DetElement::setVolume: Self is not defined [Invalid Handle]");
-}
-#endif
+
 DetElement& DetElement::setVisAttributes(const LCDD& lcdd, const string& name, const Volume& volume)  {
   if ( isValid() )  {
     volume.setVisAttributes(lcdd,name);
@@ -468,34 +474,6 @@ DetElement& DetElement::setAttributes(const LCDD& lcdd, const Volume& volume,
   return setRegion(lcdd,region,volume).setLimitSet(lcdd,limits,volume).setVisAttributes(lcdd,vis,volume);
 }
 
-DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens)   {
-  if ( isTracker() )  {
-    _data().combine_hits = value;
-    sens.setCombineHits(value);
-  }
-  return *this;
-}
-
-bool DetElement::isTracker() const   {
-  if ( isValid() )  {
-    string typ = type();
-    if ( typ.find("Tracker") != string::npos && _data().readout.isValid() )   {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool DetElement::isCalorimeter() const   {
-  if ( isValid() )  {
-    string typ = type();
-    if ( typ.find("Calorimeter") != string::npos && _data().readout.isValid() ) {
-      return true;
-    }
-  }
-  return false;
-}
-
 /// Set detector element for reference transformations. Will delete existing reference trafo.
 DetElement& DetElement::setReference(DetElement reference) {
   Object& o = _data();
@@ -552,7 +530,7 @@ bool DetElement::referenceToLocal(const Position& global, Position& local)  cons
 }
 
 /// Constructor
-SensitiveDetector::SensitiveDetector(const std::string& type, const std::string& name)  {
+SensitiveDetector::SensitiveDetector(const std::string& name, const std::string& type)  {
   /*
     <calorimeter ecut="0" eunit="MeV" hits_collection="EcalEndcapHits" name="EcalEndcap" verbose="0">
       <global_grid_xy grid_size_x="3.5" grid_size_y="3.5"/>
@@ -561,10 +539,18 @@ SensitiveDetector::SensitiveDetector(const std::string& type, const std::string&
   */
   assign(new Value<TNamed,Object>(),name,type);
   _data().ecut = 0e0;
-  _data().eunit = "MeV";
   _data().verbose = 0;
 }
 
+/// Set the type of the sensitive detector
+SensitiveDetector& SensitiveDetector::setType(const std::string& typ)   {
+  if ( isValid() )  {
+    m_element->SetTitle(typ.c_str());
+    return *this;
+  }
+  throw runtime_error("SensitiveDetector::setType: Self is not defined [Invalid Handle]");
+}
+
 /// Access the type of the sensitive detector
 string SensitiveDetector::type() const  {
   return m_element ? m_element->GetTitle() : "";
@@ -581,19 +567,52 @@ Readout SensitiveDetector::readout()  const  {
   return _data().readout;
 }
 
+/// Set energy cut off
+SensitiveDetector& SensitiveDetector::setEnergyCutoff(double value)   {
+  _data().ecut = value;
+  return *this;
+}
+
+/// Access energy cut off
+double SensitiveDetector::energyCutoff()  const {
+  return _data().ecut;
+}
+
 /// Assign the name of the hits collection
 SensitiveDetector& SensitiveDetector::setHitsCollection(const string& collection)  {
-  _data().hits_collection = collection;
+  _data().hitsCollection = collection;
   return *this;
 }
 
+/// Access the hits collection name
+const string& SensitiveDetector::hitsCollection() const {
+  return _data().hitsCollection;
+}
+
+/// Assign the name of the hits collection
+SensitiveDetector& SensitiveDetector::setVerbose(bool value)  {
+  int v = value ? 1 : 0;
+  _data().verbose = v;
+  return *this;
+}
+
+/// Access flag to combine hist
+bool SensitiveDetector::verbose() const {
+  return _data().verbose == 1;
+}
+
 /// Assign the name of the hits collection
 SensitiveDetector& SensitiveDetector::setCombineHits(bool value)  {
   int v = value ? 1 : 0;
-  _data().combine_hits = v;
+  _data().combineHits = v;
   return *this;
 }
 
+/// Access flag to combine hist
+bool SensitiveDetector::combineHits() const {
+  return _data().combineHits == 1;
+}
+
 /// Add an extension object to the detector element
 void* SensitiveDetector::i_addExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) {
   Object& o = _data();
diff --git a/DDCore/src/GeoHandler.cpp b/DDCore/src/GeoHandler.cpp
index f84421f56..49ecdcac5 100644
--- a/DDCore/src/GeoHandler.cpp
+++ b/DDCore/src/GeoHandler.cpp
@@ -73,10 +73,17 @@ GeoHandler& GeoHandler::collect(DetElement element, GeometryInfo& info) {
       TGeoMedium* m = v->GetMedium();
       Volume      vol = Handle<>(v);
       VisAttr     vis = vol.visAttributes();
+      //Region      reg = vol.region();
+      //LimitSet    lim = vol.limitSet();
+      //SensitiveDetector det = vol.sensitiveDetector();
 
       info.volumes.insert(v);
       info.materials.insert(m);
       if ( vis.isValid() ) info.vis.insert(vis.ptr());
+      //if ( lim.isValid() ) info.limits[lim.ptr()].insert(v);
+      //if ( reg.isValid() ) info.regions[reg.ptr()].insert(v);
+      //if ( det.isValid() ) info.sensitives[det.ptr()].insert(v);
+
       collectSolid(info,v->GetName(),n->GetName(),v->GetShape(),n->GetMatrix());
     }
   }
diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp
index f11a672d6..a898f94ae 100644
--- a/DDCore/src/Handle.cpp
+++ b/DDCore/src/Handle.cpp
@@ -61,6 +61,22 @@ double DD4hep::Geometry::_toDouble(const string& value)   {
   return result;
 }
 
+template <> int    _multiply<int>(const std::string& left, const std::string& right) {
+  return (int)_toDouble(left+"*"+right);
+}
+
+template <> long   _multiply<long>(const std::string& left, const std::string& right) {
+  return (long)_toDouble(left+"*"+right);
+}
+
+template <> float  _multiply<float>(const std::string& left, const std::string& right) {
+  return _toFloat(left+"*"+right);
+}
+
+template <> double _multiply<double>(const std::string& left, const std::string& right) {
+  return _toDouble(left+"*"+right);
+}
+
 void DD4hep::Geometry::_toDictionary(const string& name, const string& value)  {
   string n=name, v=value;
   size_t idx = v.find("(int)");
diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp
index 694cb00bf..fa24ab0a3 100644
--- a/DDCore/src/LCDDImp.cpp
+++ b/DDCore/src/LCDDImp.cpp
@@ -35,7 +35,7 @@ using namespace DD4hep;
 using namespace std;
 namespace {
   struct TopDetElement : public DetElement {
-    TopDetElement(const std::string& nam, Volume vol) : DetElement(nam,0) { _data().volume = vol;    }
+    TopDetElement(const std::string& nam, Volume vol) : DetElement(nam,/* "structure", */0) { _data().volume = vol;    }
   };
 }
 
@@ -120,64 +120,70 @@ namespace {
 }
 
 void LCDDImp::endDocument()  {
-  LCDD& lcdd = *this;
-  Material  air = material("Air");
-
-  m_worldVol.setMaterial(air);
-  m_trackingVol.setMaterial(air);
-
-  Region trackingRegion(lcdd,"TrackingRegion");
-  trackingRegion.setThreshold(1);
-  trackingRegion.setStoreSecondaries(true);
-  add(trackingRegion);
-  m_trackingVol.setRegion(trackingRegion);
+  TGeoManager* mgr = gGeoManager;
+  if ( !mgr->IsClosed() ) {
+    LCDD& lcdd = *this;
+    Material  air = material("Air");
+
+    m_worldVol.setMaterial(air);
+    m_trackingVol.setMaterial(air);
+
+    Region trackingRegion("TrackingRegion");
+    trackingRegion.setThreshold(1);
+    trackingRegion.setStoreSecondaries(true);
+    add(trackingRegion);
+    m_trackingVol.setRegion(trackingRegion);
     
-  // Set the world volume to invisible.
-  VisAttr worldVis(lcdd,"WorldVis");
-  worldVis.setVisible(false);
-  m_worldVol.setVisAttributes(worldVis);
-  add(worldVis);
+    // Set the world volume to invisible.
+    VisAttr worldVis(lcdd,"WorldVis");
+    worldVis.setVisible(false);
+    m_worldVol.setVisAttributes(worldVis);
+    add(worldVis);
   
-  // Set the tracking volume to invisible.
-  VisAttr trackingVis(lcdd,"TrackingVis");
-  trackingVis.setVisible(false);               
-  m_trackingVol.setVisAttributes(trackingVis);
-  add(trackingVis); 
-
-  /// Since we allow now for anonymous shapes,
-  /// we will rename them to use the name of the volume they are assigned to
-  TGeoManager* mgr = gGeoManager;
-  gGeoManager->SetTopVolume(m_worldVol);
-  mgr->CloseGeometry();
-  m_world.setPlacement(PlacedVolume(mgr->GetTopNode()));
-  ShapePatcher(m_world)();
+    // Set the tracking volume to invisible.
+    VisAttr trackingVis(lcdd,"TrackingVis");
+    trackingVis.setVisible(false);               
+    m_trackingVol.setVisAttributes(trackingVis);
+    add(trackingVis); 
+
+    /// Since we allow now for anonymous shapes,
+    /// we will rename them to use the name of the volume they are assigned to
+    gGeoManager->SetTopVolume(m_worldVol);
+    mgr->CloseGeometry();
+    m_world.setPlacement(PlacedVolume(mgr->GetTopNode()));
+    ShapePatcher(m_world)();
+  }
 }
 
 void LCDDImp::create()  {
-  gGeoManager = new TGeoManager();
+  if ( 0 == gGeoManager ) {
+    gGeoManager = new TGeoManager();
+  }
 }
 
 void LCDDImp::init()  {
-  LCDD& lcdd = *this;
-  Box worldSolid("world_box","world_x","world_y","world_z");
-  Material vacuum = material("Vacuum");
-  Volume world("world_volume",worldSolid,vacuum);
-  Tube trackingSolid("tracking_cylinder",
-		     0.,
-		     _toDouble("tracking_region_radius"),
-		     _toDouble("2*tracking_region_zmax"),2*M_PI);
-  Volume tracking("tracking_volume",trackingSolid, vacuum);
-  m_world          = TopDetElement("world",world);
-  m_trackers       = TopDetElement("tracking",tracking);
-  m_worldVol       = world;
-  m_trackingVol    = tracking;
-  m_materialAir    = material("Air");
-  m_materialVacuum = material("Vacuum");
-  m_detectors.append(m_world);
-  m_world.add(m_trackers);
+  if ( !m_world.isValid() ) {
+    Box worldSolid("world_box","world_x","world_y","world_z");
+    Material vacuum = material("Vacuum");
+    Volume world("world_volume",worldSolid,vacuum);
+    Tube trackingSolid("tracking_cylinder",
+		       0.,
+		       _toDouble("tracking_region_radius"),
+		       _toDouble("2*tracking_region_zmax"),2*M_PI);
+    Volume tracking("tracking_volume",trackingSolid, vacuum);
+    m_world          = TopDetElement("world",world);
+    m_trackers       = TopDetElement("tracking",tracking);
+    m_worldVol       = world;
+    m_trackingVol    = tracking;
+    m_materialAir    = material("Air");
+    m_materialVacuum = material("Vacuum");
+    m_detectors.append(m_world);
+    m_world.add(m_trackers);
+  }
 }
 
 void LCDDImp::fromCompact(const std::string& xmlfile) {
+  create();
 #if DD4HEP_USE_PYROOT
   string cmd;
   TPython::Exec("import lcdd");
diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp
index b879c72d9..e1f839927 100644
--- a/DDCore/src/Objects.cpp
+++ b/DDCore/src/Objects.cpp
@@ -245,37 +245,56 @@ int AlignmentEntry::align(const Position& pos, const Rotation& rot, bool check,
   throw std::runtime_error("Callot align non existing physical node.");
 }
 
-/// Constructor to be used when creating a limit object
-Limit::Limit(LCDD& /* lcdd */, const string& name)   {
-  Value<TNamed,Object>* obj = new Value<TNamed,Object>();
-  assign(obj,name,"*");
-  obj->first  = "mm";
-  obj->second = 1.0;
+
+/// Assignment operator
+Limit& Limit::operator=(const Limit& c) 	{ 
+  particles = c.particles;
+  name      = c.name;
+  unit      = c.unit;
+  value     = c.value; 
+  content   = c.content;
+  return *this;
 }
 
-void Limit::setParticles(const string& particleNames)   {
-  m_element->SetTitle(particleNames.c_str());
+/// Equality operator
+bool Limit::operator==(const Limit& c) const {
+  return value==c.value && name==c.name && particles == c.particles;
 }
 
-void Limit::setValue(double value)   {
-  _data().second = value;
+/// operator less
+bool Limit::operator< (const Limit& c) const {
+  if ( value    < c.value      ) return true;
+  if ( name     < c.name       ) return true;
+  if ( particles < c.particles ) return true;
+  return false;
 }
 
-void Limit::setUnit(const string& value)   {
-  _data().first = value;
+/// Conversion to a string representation
+std::string Limit::toString()  const {
+  string res = name + " = " + content;
+  if ( !unit.empty() ) res += unit + " ";
+  res + " (" + particles + ")";
+  return res;
 }
 
 /// Constructor to be used when creating a new DOM tree
-LimitSet::LimitSet(LCDD& /* lcdd */, const string& name)   {
-  assign(new Value<TNamed,TMap>(),name,"limitset");
+LimitSet::LimitSet(const string& name)   {
+  assign(new Value<TNamed,Object>(),name,"limitset");
 }
 
-void LimitSet::addLimit(const Ref_t& limit)   {
-  data<TMap>()->Add(limit.ptr(),limit.ptr());
+/// Add new limit. Returns true if the new limit was added, false if it already existed.
+bool LimitSet::addLimit(const Limit& limit)   {
+  pair<Object::iterator,bool> ret = data<Object>()->insert(limit);
+  return ret.second;
+}
+
+/// Accessor to limits container
+const LimitSet::Object& LimitSet::limits() const {
+  return *(data<Object>());
 }
 
 /// Constructor to be used when creating a new DOM tree
-Region::Region(LCDD& /* lcdd */, const string& name)   {
+Region::Region(const string& name)   {
   Value<TNamed,Object>* p = new Value<TNamed,Object>();
   assign(p, name, "region");
   p->magic = magic_word();
@@ -310,6 +329,27 @@ Region& Region::setEnergyUnit(const string& unit)  {
   _data().eunit = unit;
   return *this;
 }
+
+/// Access references to user limits
+vector<string>& Region::limits() const {
+  return _data().user_limits;
+}
+
+/// Access cut value
+double Region::cut() const {
+  return _data().cut;
+}
+
+/// Access production threshold
+double Region::threshold() const {
+  return _data().threshold;
+}
+
+/// Access secondaries flag
+bool Region::storeSecondaries() const {
+  return _data().store_secondaries;
+}
+
 #undef setAttr
 
 #if 0
diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp
index 2a389e138..61723b317 100644
--- a/DDCore/src/Readout.cpp
+++ b/DDCore/src/Readout.cpp
@@ -13,7 +13,7 @@ using namespace std;
 using namespace DD4hep::Geometry;
 
 /// Initializing constructor to create a new object
-Readout::Readout(const LCDD& /* lcdd */, const string& nam)
+Readout::Readout(const string& nam)
 {
   assign(new Value<TNamed,Object>(),nam,"readout");
 }
diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp
index 929f1f6ed..d72706489 100644
--- a/DDCore/src/Segementations.cpp
+++ b/DDCore/src/Segementations.cpp
@@ -13,6 +13,21 @@
 using namespace std;
 using namespace DD4hep::Geometry;
 
+Segmentation::Object::Object() : magic(magic_word()), type(REGULAR), useForHitPosition(0) {
+  ::memset(data.values,0,sizeof(data.values));
+}
+
+Segmentation::Object::~Object() {
+  if ( type == EXTENDED && data.extension.ptr != 0 ) {
+    if ( data.extension.destructor ) {
+      (*data.extension.destructor)(data.extension.ptr);
+      data.extension.destructor = 0;
+      data.extension.info = 0;
+      data.extension.ptr = 0;
+    }
+  }
+}
+
 Segmentation::Segmentation(const string& type)  {
   assign(new Value<TNamed,Segmentation::Object>(),"segmentation",type);
 }
@@ -25,6 +40,33 @@ const string Segmentation::type() const   {
   return m_element->GetTitle();
 }
 
+/// Add an extension object to the detector element
+void* Segmentation::i_setExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) {
+  Object& o = _data();
+  o.type = EXTENDED;
+  o.data.extension.ptr = ptr;
+  o.data.extension.info = &info;
+  o.data.extension.destructor = destruct;
+  return ptr;
+}
+
+/// Access an existing extension object from the detector element
+void* Segmentation::i_extension(const std::type_info& info)   const {
+  if ( isValid() ) {
+    Object::Data::Extension& o = _data().data.extension;
+    if ( o.ptr )   {
+      if ( &info == o.info ) {
+	return o.ptr;
+      }
+      throw runtime_error("extension: The segmentation object "+string(type())+
+			  " has the wrong type!");
+    }
+    throw runtime_error("extension: The segmentation object "+string(type())+
+			" has no extension defined.");
+  }
+  throw runtime_error("extension: The segmentation object is not valid!");
+}
+ 
 ProjectiveCylinder::ProjectiveCylinder() 
 : Segmentation("projective_cylinder")   {}
 
diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp
index 5fef0ee9e..e87aa741b 100644
--- a/DDCore/src/Volumes.cpp
+++ b/DDCore/src/Volumes.cpp
@@ -100,16 +100,23 @@ namespace DD4hep  { namespace Geometry  {
   
   template <> _VolWrap<TGeoVolume>::_VolWrap(const char* name, TGeoShape* s, TGeoMedium* m)
   : TGeoVolume(name,s,m) {}
-  template <> _VolWrap<TGeoVolumeAssembly>::_VolWrap(const char* name, TGeoShape* s, TGeoMedium* m)
+  template <> _VolWrap<TGeoVolumeAssembly>::_VolWrap(const char* name, TGeoShape* /* s */, TGeoMedium* /* m */)
   : TGeoVolumeAssembly(name) {}
   
   template <> struct Value<TGeoVolume,Volume::Object>
   : public _VolWrap<TGeoVolume>, public Volume::Object  {
-    Value(const char* name, TGeoShape* s=0, TGeoMedium* m=0) : _VolWrap<TGeoVolume>(name,s,m) {magic = magic_word();}
+    Value(const char* name, TGeoShape* s=0, TGeoMedium* m=0) 
+      : _VolWrap<TGeoVolume>(name,s,m) {magic = magic_word();}
     virtual ~Value() {}
+    TGeoVolume *_copyVol(TGeoShape *newshape) const {
+      typedef Value<TGeoVolume,Volume::Object> _Vol;
+      _Vol *vol = new _Vol(GetName(), newshape, fMedium);
+      vol->copy(*this);
+      return vol;
+    }
     virtual TGeoVolume* MakeCopyVolume(TGeoShape *newshape) {
       // make a copy of this volume. build a volume with same name, shape and medium
-      TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), newshape, fMedium);
+      TGeoVolume *vol = _copyVol(newshape);
       vol->SetVisibility(IsVisible());
       vol->SetLineColor(GetLineColor());
       vol->SetLineStyle(GetLineStyle());
@@ -123,7 +130,7 @@ namespace DD4hep  { namespace Geometry  {
       return vol;       
     }
     virtual TGeoVolume* CloneVolume() const    {
-      TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), fShape, fMedium);
+      TGeoVolume *vol = _copyVol(fShape);
       Int_t i;
       // copy volume attributes
       vol->SetLineColor(GetLineColor());
@@ -383,8 +390,10 @@ void Volume::setLimitSet(const LimitSet& obj)  const
 {  data<Object>()->limits = obj;                            }
 
 /// Assign the sensitive detector structure
-void Volume::setSensitiveDetector(const SensitiveDetector& obj) const  
-{  data<Object>()->sens_det = obj;                          }
+void Volume::setSensitiveDetector(const SensitiveDetector& obj) const   {
+  //cout << "Setting sensitive detector '" << obj.name() << "' to volume:" << ptr() << " " << name() << endl;
+  data<Object>()->sens_det = obj;                          
+}
 
 /// Access to the handle to the sensitive detector
 Ref_t Volume::sensitiveDetector() const
diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp
index f05a43700..e8de01f71 100644
--- a/DDCore/src/XML/DocumentHandler.cpp
+++ b/DDCore/src/XML/DocumentHandler.cpp
@@ -118,13 +118,13 @@ XercesDOMParser* DocumentHandler::makeParser(xercesc::ErrorHandler* err_handler)
 }
 
 Document DocumentHandler::load(const string& fname)  const  {
+  cout << "Loading document URI:" << fname << endl;
   XMLURL xerurl = (const XMLCh*)Strng_t(fname);
   string path   = _toString(xerurl.getPath());
   string proto  = _toString(xerurl.getProtocolName());
   auto_ptr<XercesDOMParser> parser(makeParser());
-  cout << "Loading document :" << path  << endl
-       << "         protocol:" << proto << endl
-       << "              URI:" << fname << endl;
+  cout << "            protocol:" << proto << endl
+       << "                path:" << path  << endl;
   try {
     parser->parse(path.c_str());
   }
diff --git a/DDCore/src/XML/XMLDetector.cpp b/DDCore/src/XML/XMLDetector.cpp
index 55b98b138..90cf63613 100644
--- a/DDCore/src/XML/XMLDetector.cpp
+++ b/DDCore/src/XML/XMLDetector.cpp
@@ -284,7 +284,9 @@ double DetElement::Component::thickness() const  {
 }
 
 bool DetElement::Component::isSensitive() const  {
-  return m_element.hasAttr(Attr_sensitive) && m_element.attr<bool>(Attr_sensitive);
+  char val = m_element.hasAttr(Attr_sensitive) ? m_element.attr<string>(Attr_sensitive)[0] : 'f';
+  val = ::toupper(val);
+  return val == 'T' || val == 'Y';
 }
 
 string DetElement::Component::visStr()  const  {
diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp
index 9ddbca10a..568694b47 100644
--- a/DDCore/src/XML/XMLElements.cpp
+++ b/DDCore/src/XML/XMLElements.cpp
@@ -323,6 +323,10 @@ const XMLCh* Handle_t::attr_value(const XMLCh* attr)  const   {
   return attr_ptr(attr)->getValue();
 }
 
+const XMLCh* Handle_t::attr_value(const Attribute attr)  const   {
+  return attr->getValue();
+}
+
 const XMLCh* Handle_t::attr_value_nothrow(const XMLCh* attr)  const   {
   Attribute a = attr_nothrow(attr);
   //Attribute a = attr_ptr(attr);
diff --git a/DDCore/src/compact/Compact2Objects.cpp b/DDCore/src/compact/Compact2Objects.cpp
index 1f5f0d2f6..256f99596 100644
--- a/DDCore/src/compact/Compact2Objects.cpp
+++ b/DDCore/src/compact/Compact2Objects.cpp
@@ -29,6 +29,61 @@ namespace {
   static UInt_t unique_mat_id = 0xAFFEFEED;
 }
 
+static Ref_t create_GridXYZ(lcdd_t& /* lcdd */, const xml_h& e)  {
+  GridXYZ obj;
+  if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX)));
+  if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY)));
+  if ( e.hasAttr(_A(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_A(gridSizeZ)));
+  return obj;
+}
+DECLARE_XMLELEMENT(GridXYZ,create_GridXYZ);
+
+namespace DD4hep { namespace Geometry { typedef GridXYZ RegularNgonCartesianGridXY; }}
+DECLARE_XMLELEMENT(RegularNgonCartesianGridXY,create_GridXYZ);
+
+static Ref_t create_GlobalGridXY(lcdd_t& /* lcdd */, const xml_h& e)  {
+  GlobalGridXY obj;
+  if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX)));
+  if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY)));
+  return obj;
+}
+DECLARE_XMLELEMENT(GlobalGridXY,create_GlobalGridXY);
+  
+static Ref_t create_CartesianGridXY(lcdd_t& /* lcdd */, const xml_h& e)  {
+  CartesianGridXY obj;
+  if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_A(gridSizeX)));
+  if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_A(gridSizeY)));
+  return obj;
+}
+DECLARE_XMLELEMENT(CartesianGridXY,create_CartesianGridXY);
+
+namespace DD4hep { namespace Geometry { typedef CartesianGridXY EcalBarrelCartesianGridXY; }}
+DECLARE_XMLELEMENT(EcalBarrelCartesianGridXY,create_CartesianGridXY);
+  
+static Ref_t create_ProjectiveCylinder(lcdd_t& /* lcdd */, const xml_h& e)  {
+  ProjectiveCylinder obj;
+  if ( e.hasAttr(_A(phiBins))   ) obj.setPhiBins(e.attr<int>(_A(phiBins)));
+  if ( e.hasAttr(_A(thetaBins)) ) obj.setThetaBins(e.attr<int>(_A(thetaBins)));
+  return obj;
+}
+DECLARE_XMLELEMENT(ProjectiveCylinder,create_ProjectiveCylinder);
+  
+static Ref_t create_NonProjectiveCylinder(lcdd_t& /* lcdd */, const xml_h& e)  {
+  NonProjectiveCylinder obj;
+  if ( e.hasAttr(_A(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_A(gridSizePhi)));
+  if ( e.hasAttr(_A(gridSizeZ))   ) obj.setPhiBinSize(e.attr<double>(_A(gridSizeZ)));
+  return obj;
+}
+DECLARE_XMLELEMENT(NonProjectiveCylinder,create_NonProjectiveCylinder);
+  
+static Ref_t create_ProjectiveZPlane(lcdd_t& /* lcdd */, const xml_h& e)  {
+  ProjectiveZPlane obj;
+  if ( e.hasAttr(_A(phiBins))   ) obj.setThetaBins(e.attr<int>(_A(phiBins)));
+  if ( e.hasAttr(_A(thetaBins)) ) obj.setPhiBins(e.attr<int>(_A(thetaBins)));
+  return obj;
+}
+DECLARE_XMLELEMENT(ProjectiveZPlane,create_ProjectiveZPlane);
+
 namespace DD4hep { namespace Geometry {
   struct Compact;
   struct Includes;
@@ -152,22 +207,21 @@ namespace DD4hep { namespace Geometry {
     return Ref_t(id);
   }
   
-  template <> Ref_t toRefObject<Limit>(lcdd_t& lcdd, const xml_h& e)  {
-    /*     <limit name="step_length_max" particles="*" value="5.0" unit="mm" />
-     */
-    Limit limit(lcdd,e.attr<string>(_A(name)));
-    limit.setParticles(e.attr<string>(_A(particles)));
-    limit.setValue(e.attr<double>(_A(value)));
-    limit.setUnit(e.attr<string>(_A(unit)));
-    return limit;
-  }
-  
   template <> Ref_t toRefObject<LimitSet>(lcdd_t& lcdd, const xml_h& e)  {
-    /*      <limitset name="...."> ... </limitset>
+    /*      <limitset name="...."> 
+     *        <limit name="step_length_max" particles="*" value="5.0" unit="mm" />
+     *  ... </limitset>
      */
-    LimitSet ls(lcdd,XML::Tag_t(e.attr<string>(_A(name))));
-    for (xml_coll_t c(e,XML::Tag_limit); c; ++c)
-      ls.addLimit(toRefObject<Limit>(lcdd,c));
+    LimitSet ls(e.attr<string>(_A(name)));
+    for (xml_coll_t c(e,XML::Tag_limit); c; ++c) {
+      Limit limit;
+      limit.particles = c.attr<string>(_A(particles));
+      limit.name      = c.attr<string>(_A(name));
+      limit.content   = c.attr<string>(_A(value));
+      limit.unit      = c.attr<string>(_A(unit));
+      limit.value     = _multiply<double>(limit.content,limit.unit);
+      ls.addLimit(limit);
+    }
     return ls;
   }
   
@@ -200,86 +254,25 @@ namespace DD4hep { namespace Geometry {
     if ( e.hasAttr(_A(showDaughters)) ) attr.setShowDaughters(e.attr<bool>(_A(showDaughters)));
     return attr;
   }
-  
-  template <> Elt_t toObject<GridXYZ>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    GridXYZ obj;
-    if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX)));
-    if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY)));
-    if ( e.hasAttr(_A(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_A(gridSizeZ)));
-    return obj;
-  }
-  template <> Elt_t toObject<GlobalGridXY>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    GlobalGridXY obj;
-    if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX)));
-    if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY)));
-    return obj;
-  }
-  
-  template <> Elt_t toObject<CartesianGridXY>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    CartesianGridXY obj;
-    if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_A(gridSizeX)));
-    if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_A(gridSizeY)));
-    return obj;
-  }
-  
-  template <> Elt_t toObject<ProjectiveCylinder>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    ProjectiveCylinder obj;
-    if ( e.hasAttr(_A(phiBins))   ) obj.setPhiBins(e.attr<int>(_A(phiBins)));
-    if ( e.hasAttr(_A(thetaBins)) ) obj.setThetaBins(e.attr<int>(_A(thetaBins)));
-    return obj;
-  }
-  
-  template <> Elt_t toObject<NonProjectiveCylinder>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    NonProjectiveCylinder obj;
-    if ( e.hasAttr(_A(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_A(gridSizePhi)));
-    if ( e.hasAttr(_A(gridSizeZ))   ) obj.setPhiBinSize(e.attr<double>(_A(gridSizeZ)));
-    return obj;
-  }
-  
-  template <> Elt_t toObject<ProjectiveZPlane>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    ProjectiveZPlane obj;
-    if ( e.hasAttr(_A(phiBins))   ) obj.setThetaBins(e.attr<int>(_A(phiBins)));
-    if ( e.hasAttr(_A(thetaBins)) ) obj.setPhiBins(e.attr<int>(_A(thetaBins)));
-    return obj;
-  }
-  
-  template <> Elt_t toObject<Segmentation>(lcdd_t& lcdd, const xml_h& e)  {
-    string seg_typ = e.attr<string>(_A(type));
-    if ( seg_typ == "GridXYZ" )
-      return toObject<GridXYZ>(lcdd,e);
-    else if ( seg_typ == "GlobalGridXY" )
-      return toObject<GlobalGridXY>(lcdd,e);
-    else if ( seg_typ == "CartesianGridXY" )
-      return toObject<CartesianGridXY>(lcdd,e);
-    else if ( seg_typ == "RegularNgonCartesianGridXY" )
-      return toObject<GridXYZ>(lcdd,e);
-    else if ( seg_typ == "EcalBarrelCartesianGridXY" )
-      return toObject<CartesianGridXY>(lcdd,e);
-    else if ( seg_typ == "ProjectiveCylinder" )
-      return toObject<ProjectiveCylinder>(lcdd,e);
-    else if ( seg_typ == "NonProjectiveCylinder" )
-      return toObject<NonProjectiveCylinder>(lcdd,e);
-    else if ( seg_typ == "ProjectiveZPlane" )
-      return toObject<ProjectiveZPlane>(lcdd,e);
-    else 
-      cout << "Request to create UNKNOWN segmentation of type:" << seg_typ << endl;
-    return Elt_t(0);
-  }
-  
+
   template <> Ref_t toRefObject<Readout>(lcdd_t& lcdd, const xml_h& e)  {
     /* <readout name="HcalBarrelHits">
      <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
      <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
      </readout>
      */
-    xml_h   id, seg;
+    const xml_h  id = e.child(_X(id));
+    const xml_h seg = e.child(_X(segmentation),false);
     string  name = e.attr<string>(_A(name));
-    Readout ro(lcdd,name);
-    if ( (seg=e.child(_X(segmentation),false)) )  { // Segmentation is not mandatory!
-      string seg_typ = seg.attr<string>(_A(type));
-      ro.setSegmentation(toObject<Segmentation>(lcdd,seg));
+    Readout ro(name);
+
+    if ( seg )  { // Segmentation is not mandatory!
+      string type = seg.attr<string>(_A(type));
+      Ref_t segment(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&seg));
+      if ( !segment.isValid() ) throw runtime_error("FAILED to create segmentation:"+type);
+      ro.setSegmentation(segment);
     }
-    if ( (id=e.child(_X(id))) )  {
+    if ( id )  {
       Ref_t idSpec = toRefObject<IDDescriptor>(lcdd,id);
       idSpec->SetName(ro.name());
       ro.setIDDescriptor(idSpec);
@@ -326,28 +319,19 @@ namespace DD4hep { namespace Geometry {
     {  return toRefObject<T>(lcdd,xml,sens); }
   }
   
-  template <> Ref_t toRefObject<SensitiveDetector>(lcdd_t& lcdd, const xml_h& e)  {
-    string    nam = e.attr<string>(_A(name));
-    string    typ = e.attr<string>(_A(type));
-    
-    if      ( e.hasAttr("calorimeterType") ) typ = "calorimeter";
-    else if ( typ.find("Tracker") != string::npos ) typ = "tracker";
-    else if ( nam.find("Tracker") != string::npos ) typ = "tracker";
-    
-    if ( e.hasAttr(_A(readout)) )  {
-      Readout            ro = lcdd.readout(e.attr<string>(_A(readout)));
-      SensitiveDetector  sd = SensitiveDetector(typ,nam);
-      sd.setReadout(ro);
-      sd.setHitsCollection(ro.name());
-      lcdd.addSensitiveDetector(sd);
-      return sd;
-    }
-    return SensitiveDetector();
-  }
-  
   template <> Ref_t toRefObject<Region>(lcdd_t& /* lcdd */, const xml_h& e)  {
-    xml_ref_t compact(e);
-    return Ref_t(0);
+    Region region(e.attr<string>(_A(name)));
+    vector<string>& limits = region.limits();
+    string ene = e.attr<string>(_A(eunit)), len = e.attr<string>(_A(lunit));    
+
+    region.setEnergyUnit(ene);
+    region.setLengthUnit(len);
+    region.setCut(_multiply<double>(e.attr<string>(_A(cut)),len));
+    region.setThreshold(_multiply<double>(e.attr<string>(_A(threshold)),ene));
+    region.setStoreSecondaries(e.attr<bool>(_A(store_secondaries)));
+    for(xml_coll_t user_limits(e,_X(limitsetref)); user_limits; ++user_limits)
+      limits.push_back(user_limits.attr<string>(_A(name)));
+    return region;
   }
   
   template <> void Converter<Constant>::operator()(const xml_h& element)  const  {
@@ -357,7 +341,6 @@ namespace DD4hep { namespace Geometry {
     lcdd.addMaterial(toRefObject<to_type>(lcdd,element));
   }
   template <> void Converter<Atom>::operator()(const xml_h& element)  const  {
-    //  lcdd.addMaterial(toRefObject<to_type>(lcdd,element));
     toRefObject<to_type>(lcdd,element);
   }
   template <> void Converter<VisAttr>::operator()(const xml_h& element)  const  {
@@ -386,6 +369,51 @@ namespace DD4hep { namespace Geometry {
     }
     for_each(children.begin(),children.end(),setChildTitles);
   }
+
+  template <> void Converter<SensitiveDetector>::operator()(const xml_h& element)  const {
+    string type = element.attr<string>(_A(type));
+    string name = element.attr<string>(_A(name));
+    try {
+      DetElement        det = lcdd.detector(name);
+      SensitiveDetector sd  = lcdd.sensitiveDetector(name);
+
+      xml_attr_t type  = element.attr_nothrow(_A(type));
+      if ( type ) {
+	sd.setType(element.attr<string>(type));
+      }
+      xml_attr_t verbose  = element.attr_nothrow(_A(verbose));
+      if ( verbose ) {
+	sd.setVerbose(element.attr<bool>(verbose));
+      }
+      xml_attr_t combine  = element.attr_nothrow(_A(combine_hits));
+      if ( combine ) {
+	sd.setCombineHits(element.attr<bool>(combine));
+      }
+      xml_attr_t hits  = element.attr_nothrow(_A(hits_collection));
+      if ( hits ) {
+	sd.setHitsCollection(element.attr<string>(hits));
+      }
+      xml_attr_t ecut  = element.attr_nothrow(_A(ecut));
+      xml_attr_t eunit = element.attr_nothrow(_A(eunit));
+      if ( ecut && eunit ) {
+	double value = _multiply<double>(_toString(ecut),_toString(eunit));
+	sd.setEnergyCutoff(value);
+      }
+      else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used!
+	sd.setEnergyCutoff(element.attr<double>(ecut));
+      }
+
+      cout << " sensitive detector:" << name << " of type " << type << endl;
+      //lcdd.addDetector(det);
+    }
+    catch(const exception& e) {
+      cout << "FAILED    to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl;
+    }
+    catch(...) {
+      cout << "FAILED    to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl;
+    }
+  }
+
   template <> void Converter<DetElement>::operator()(const xml_h& element)  const {
     static const char* req_dets = ::getenv("REQUIRED_DETECTORS");
     static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES");
@@ -400,26 +428,26 @@ namespace DD4hep { namespace Geometry {
     if ( ign_dets &&  strstr(ign_dets,name_match.c_str()) ) return;
     if ( ign_typs &&  strstr(ign_typs,type_match.c_str()) ) return;
     try {
+      bool has_ro = element.hasAttr(_A(readout));
+      Readout  ro = has_ro ? lcdd.readout(element.attr<string>(_A(readout))) : Readout();
       SensitiveDetector sd;
-      if ( element.hasAttr(_A(sensitive_detector)) ) {
-	string sensitive_type = element.attr<string>(_A(sensitive_detector));
-	sd = lcdd.sensitiveDetector(sensitive_type);
-	// Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(sensitive_type,&lcdd,&element));
-      }
-      if ( !sd.isValid() )   {
-	sd = toRefObject<SensitiveDetector>(lcdd,element);
+      if ( has_ro )  {
+	sd = SensitiveDetector(name,"structure");
+	sd.setHitsCollection(ro.name());
+	sd.setReadout(ro);
+	lcdd.addSensitiveDetector(sd);
       }
-
       DetElement det(Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&element,&sd)));
       if ( det.isValid() )  {
 	setChildTitles(make_pair(name,det));
 	if ( element.hasAttr(_A(readout)) )  {
-	  string rdo = element.attr<string>(_A(readout));
-	  det.setReadout(lcdd.readout(rdo));
+	  det.setReadout(ro);
 	}
       }
       cout << (det.isValid() ? "Converted" : "FAILED    ")
-	   << " subdetector:" << name << " of type " << type << endl;
+	   << " subdetector:" << name << " of type " << type;
+      if ( det.isValid() ) cout << " [" << sd.type() << "]";
+      cout << endl;
       lcdd.addDetector(det);
     }
     catch(const exception& e) {
@@ -449,13 +477,11 @@ namespace DD4hep { namespace Geometry {
   
   template <> void Converter<Compact>::operator()(const xml_h& element)  const  {
     XML::Element compact(element);
-    lcdd.create();
     xml_coll_t(compact,_X(includes)  ).for_each(_X(gdmlFile), Converter<GdmlFile>(lcdd));
     //Header(lcdd.header()).fromCompact(doc,compact.child(Tag_info),Strng_t("In memory"));
     xml_coll_t(compact,_X(define)    ).for_each(_X(constant), Converter<Constant>(lcdd));
     xml_coll_t(compact,_X(materials) ).for_each(_X(element),  Converter<Atom>(lcdd));
     xml_coll_t(compact,_X(materials) ).for_each(_X(material), Converter<Material>(lcdd));
-    
     lcdd.init();
     xml_coll_t(compact,_X(limits)    ).for_each(_X(limitset), Converter<LimitSet>(lcdd));
     xml_coll_t(compact,_X(display)   ).for_each(_X(vis),      Converter<VisAttr>(lcdd));
@@ -463,6 +489,7 @@ namespace DD4hep { namespace Geometry {
     xml_coll_t(compact,_X(detectors) ).for_each(_X(detector), Converter<DetElement>(lcdd));
     xml_coll_t(compact,_X(includes)  ).for_each(_X(alignment),Converter<AlignmentFile>(lcdd));
     xml_coll_t(compact,_X(alignments)).for_each(_X(alignment),Converter<AlignmentEntry>(lcdd));
+    xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(detector),Converter<SensitiveDetector>(lcdd));
     lcdd.endDocument();
   }
 }}
-- 
GitLab