From de2827ef9666f297548ae8963b69bed9cf57796d Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Mon, 4 Nov 2013 15:54:50 +0000
Subject: [PATCH] Please read doc/release.notes

---
 DDCore/include/DD4hep/Handle.h         |  38 ++--
 DDCore/include/DD4hep/InstanceCount.h  | 172 +++++++++----------
 DDCore/include/DD4hep/LCDD.h           |  17 ++
 DDCore/include/DD4hep/Primitives.h     |  46 +++++
 DDCore/include/DD4hep/Readout.h        |   7 +-
 DDCore/include/DD4hep/Segmentations.h  | 229 ++++++++++++-------------
 DDCore/include/XML/Conversions.h       |   8 +-
 DDCore/include/XML/XMLElements.h       |   4 +
 DDCore/src/Detector.cpp                |   2 +-
 DDCore/src/Handle.cpp                  |  87 ++++++----
 DDCore/src/InstanceCount.cpp           |   1 -
 DDCore/src/LCDDImp.cpp                 |  68 ++++++--
 DDCore/src/LCDDImp.h                   |   9 +
 DDCore/src/Readout.cpp                 |  41 +++--
 DDCore/src/Segementations.cpp          | 228 +++++++++++++-----------
 DDCore/src/VolumeManager.cpp           |   4 +-
 DDCore/src/plugins/Compact2Objects.cpp |  48 +++---
 DDCore/src/plugins/Geant4XML.cpp       |   6 +
 18 files changed, 582 insertions(+), 433 deletions(-)

diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h
index 302bdd5d2..c3db148c2 100644
--- a/DDCore/include/DD4hep/Handle.h
+++ b/DDCore/include/DD4hep/Handle.h
@@ -49,6 +49,9 @@ class TGeoManager;
  */
 namespace DD4hep {
   
+  /// Access to the CXX abi name 
+  std::string typeName(const std::type_info& type);
+
   /*
    *   Geometry sub-namespace declaration
    */
@@ -104,9 +107,8 @@ namespace DD4hep {
 
     long num_object_validations();
     void increment_object_validations();
-    std::string typeName(const std::type_info& type);
     
-    inline unsigned long magic_word() { return 0xFEEDAFFEDEADFACEL; }
+    inline unsigned long long int magic_word() { return 0xFEEDAFFEDEADFACEULL; }
     
     /** @class Value Handle.h
      *  
@@ -191,38 +193,36 @@ namespace DD4hep {
     typedef Handle<>       Elt_t;
     typedef Handle<TNamed> Ref_t;
     
-    /// Helper to delete objects from heap and reset the pointer
-    template <typename T> inline void destroyObject(T*& p) {
-      deletePtr(p);
-    }
     /// Helper to delete objects from heap and reset the handle
     template <typename T> inline void destroyHandle(T& h)   {
       deletePtr(h.m_element);
     }
-    /// Functor to delete objects from heap and reset the pointer
-    template <typename T> struct DestroyObject {
-      void operator()(T& p) const { 
-	destroyObject(p);
-      }
-    };
+    /// Helper to delete objects from heap and reset the handle
+    template <typename T> inline void releaseHandle(T& h)   {
+      releasePtr(h.m_element);
+    }
     /// Functor to destroy handles and delete the cached object
     template <typename T=Ref_t> struct DestroyHandle {
       void operator()(T p) const {
 	destroyHandle(p);
       }
     };
-    /// map Functor to delete objects from heap
-    template <typename K=std::string,typename T=Ref_t> struct DestroyObjects {
-      void operator()(std::pair<K,T> p) const {
-	DestroyObject<T>()(p.second); 
+    /// Functor to destroy handles and delete the cached object
+    template <typename T=Ref_t> struct ReleaseHandle {
+      void operator()(T p) const {
+	releaseHandle(p);
       }
     };
     /// map Functor to destroy handles and delete the cached object
-    template <typename K=std::string, typename T=Ref_t> struct DestroyHandles {
-      void operator()(std::pair<K,T> p) const {
-	DestroyHandle<T>()(p.second);
+    template <typename M> struct DestroyHandles {
+      M& object;
+      DestroyHandles(M& m) : object(m) {}
+      ~DestroyHandles() { object.clear(); }
+      void operator()(std::pair<typename M::key_type,typename M::mapped_type> p) const {
+	DestroyHandle<typename M::mapped_type>()(p.second);
       }
     };
+    template<typename M> DestroyHandles<M> destroyHandles(M& m) { return DestroyHandles<M>(m); }
     
 
   }       /* End namespace Geometry  */
diff --git a/DDCore/include/DD4hep/InstanceCount.h b/DDCore/include/DD4hep/InstanceCount.h
index 7612df0d6..d85e998d5 100644
--- a/DDCore/include/DD4hep/InstanceCount.h
+++ b/DDCore/include/DD4hep/InstanceCount.h
@@ -18,103 +18,97 @@
  */
 namespace DD4hep {
 
-  /*
-   *   Geoemtry namespace declaration
+  /** @class InstanceCount InstanceCount.h StorageSvc/InstanceCount.h
+   *
+   * Small class to enable object construction/destruction tracing
+   *
+   * @author  Markus Frank
+   * @version 1.0
    */
-  namespace Geometry  {
-
-    /** @class InstanceCount InstanceCount.h StorageSvc/InstanceCount.h
+  struct InstanceCount  {
+  public:
+    typedef long long int counter_t;
+    /// Enumeration to steer the output
+    enum {  NONE = 1<<0,
+	    STRING = 1<<1,
+	    TYPEINFO = 1<<2, 
+	    ALL=STRING|TYPEINFO
+    };
+    /** @class Counter
      *
-     * Small class to enable object construction/destruction tracing
+     * Small class to enable object construction/destruction tracing.
      *
      * @author  Markus Frank
      * @version 1.0
      */
-    struct InstanceCount  {
-    public:
-      typedef long long int counter_t;
-      /// Enumeration to steer the output
-      enum {  NONE = 1<<0,
-	      STRING = 1<<1,
-	      TYPEINFO = 1<<2, 
-	      ALL=STRING|TYPEINFO
-      };
-      /** @class Counter
-       *
-       * Small class to enable object construction/destruction tracing.
-       *
-       * @author  Markus Frank
-       * @version 1.0
-       */
-      class Counter  {
-      private:
-	/// Reference counter value
-	counter_t m_count;
-	/// Increment counter value
-	counter_t m_tot;
-      public:
-	/// Default constructor
-      Counter() : m_count(0), m_tot(0)    {                       }
-	/// Copy constructor
-      Counter(const Counter& c) 
-	: m_count(c.m_count), m_tot(c.m_tot){                       }
-	/// Destructor
-	~Counter()                          {                       }
-	/// Increment counter
-	void increment()                    {  ++m_count; ++m_tot;  }
-	/// Decrement counter
-	void decrement()                    {  --m_count;           }
-	/// Access counter value
-	counter_t value() const             {  return m_count;      }
-	/// Access counter value
-	counter_t total() const             {  return m_tot;        }
-      };
+    class Counter  {
+    private:
+      /// Reference counter value
+      counter_t m_count;
+      /// Increment counter value
+      counter_t m_tot;
     public:
-      /// Standard Constructor - No need to call explicitly
-      InstanceCount();
-      /// Standard Destructor - No need to call explicitly
-      virtual ~InstanceCount();
-      /// Access counter object for local caching on optimizations
-      static Counter* getCounter(const std::type_info& typ);
-      /// Access counter object for local caching on optimizations
-      static Counter* getCounter(const std::string& typ);
-      /// Increment count according to type information
-      template<class T> static void increment(T*) 
-      { getCounter(typeid(T))->increment();                 }
-      /// Decrement count according to type information
-      template<class T> static void decrement(T*) 
-      { getCounter(typeid(T))->decrement();                 }
-      /// Access current counter
-      template<class T> static counter_t get(T*)
-      { return getCounter(typeid(T))->value();              }
-      /// Increment count according to type information
-      static void increment(const std::type_info& typ)
-      { getCounter(typ)->increment();                       }
-      /// Decrement count according to type information
-      static void decrement(const std::type_info& typ)
-      { getCounter(typ)->decrement();                       }
-      /// Access current counter
-      static counter_t get(const std::type_info& typ)
-      { return getCounter(typ)->value();                    }
-      /// Increment count according to string information
-      static void increment(const std::string& typ)
-      { getCounter(typ)->increment();                       }
-      /// Decrement count according to string information
-      static void decrement(const std::string& typ)
-      { getCounter(typ)->decrement();                       }
-      /// Access current counter
-      static counter_t get(const std::string& typ)
-      { return getCounter(typ)->value();                    }
-      /// Dump list of instance counters
-      static void dump(int which=ALL);
-      /// Clear list of instance counters
-      static void clear(int which=ALL);
-      /// Check if tracing is enabled.
-      static bool doTrace();
-      /// Enable/Disable tracing
-      static void doTracing(bool value);
+      /// Default constructor
+    Counter() : m_count(0), m_tot(0)    {                       }
+      /// Copy constructor
+    Counter(const Counter& c) 
+      : m_count(c.m_count), m_tot(c.m_tot){                       }
+      /// Destructor
+      ~Counter()                          {                       }
+      /// Increment counter
+      void increment()                    {  ++m_count; ++m_tot;  }
+      /// Decrement counter
+      void decrement()                    {  --m_count;           }
+      /// Access counter value
+      counter_t value() const             {  return m_count;      }
+      /// Access counter value
+      counter_t total() const             {  return m_tot;        }
     };
+  public:
+    /// Standard Constructor - No need to call explicitly
+    InstanceCount();
+    /// Standard Destructor - No need to call explicitly
+    virtual ~InstanceCount();
+    /// Access counter object for local caching on optimizations
+    static Counter* getCounter(const std::type_info& typ);
+    /// Access counter object for local caching on optimizations
+    static Counter* getCounter(const std::string& typ);
+    /// Increment count according to type information
+    template<class T> static void increment(T*) 
+    { getCounter(typeid(T))->increment();                 }
+    /// Decrement count according to type information
+    template<class T> static void decrement(T*) 
+    { getCounter(typeid(T))->decrement();                 }
+    /// Access current counter
+    template<class T> static counter_t get(T*)
+    { return getCounter(typeid(T))->value();              }
+    /// Increment count according to type information
+    static void increment(const std::type_info& typ)
+    { getCounter(typ)->increment();                       }
+    /// Decrement count according to type information
+    static void decrement(const std::type_info& typ)
+    { getCounter(typ)->decrement();                       }
+    /// Access current counter
+    static counter_t get(const std::type_info& typ)
+    { return getCounter(typ)->value();                    }
+    /// Increment count according to string information
+    static void increment(const std::string& typ)
+    { getCounter(typ)->increment();                       }
+    /// Decrement count according to string information
+    static void decrement(const std::string& typ)
+    { getCounter(typ)->decrement();                       }
+    /// Access current counter
+    static counter_t get(const std::string& typ)
+    { return getCounter(typ)->value();                    }
+    /// Dump list of instance counters
+    static void dump(int which=ALL);
+    /// Clear list of instance counters
+    static void clear(int which=ALL);
+    /// Check if tracing is enabled.
+    static bool doTrace();
+    /// Enable/Disable tracing
+    static void doTracing(bool value);
+  };
 
-  }       /* End namespace Geometry           */
 }         /* End namespace DD4hep             */
 #endif    /* DD4HEP_GEOMETRY_INSTANCECOUNT_H     */
diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h
index 50dd2ba24..6f1281faa 100644
--- a/DDCore/include/DD4hep/LCDD.h
+++ b/DDCore/include/DD4hep/LCDD.h
@@ -206,8 +206,25 @@ namespace DD4hep {
       /// Manipulate geometry using facroy converter
       virtual void apply(const char* factory, int argc, char** argv) = 0;
 
+      /// Extend the sensitive detector element with an arbitrary structure accessible by the type
+      template<typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c)    
+      {  return (IFACE*)addUserExtension(dynamic_cast<IFACE*>(c),typeid(IFACE));  }      
+
+      /// Access extension element by the type
+      template <class T> T* extension()  const
+      {  return (T*)userExtension(typeid(T));      }
+
       ///---Factory method-------
       static LCDD& getInstance(void);
+      /// Destroy the instance
+      static void destroyInstance();
+
+    protected:
+      /// Add an extension object to the detector element
+      virtual void* addUserExtension(void* ptr, const std::type_info& info) = 0;
+      /// Access an existing extension object from the detector element
+      virtual void* userExtension(const std::type_info& info)  const = 0;
+
     };
 
 
diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index 2ce61365d..3c8799e1a 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -9,6 +9,9 @@
 #ifndef DD4HEP_DD4HEP_PRIMITIVES_H
 #define DD4HEP_DD4HEP_PRIMITIVES_H
 
+// C/C++ include files
+#include <algorithm>
+
 /*
  *   DD4hep namespace declaration
  */
@@ -22,6 +25,49 @@ namespace DD4hep {
     if ( 0 != p ) delete p;
     p = 0;
   }
+  /// Helper to delete objects from heap and reset the pointer
+  template <typename T> inline void destroyObject(T*& p) {
+    deletePtr(p);
+  }
+  /// Functor to delete objects from heap and reset the pointer
+  template <typename T> struct DestroyObject {
+    void operator()(T& p) const { 
+      destroyObject(p);
+    }
+  };
+  /// map Functor to delete objects from heap
+  template <typename M> struct DestroyObjects {
+    M& object;
+    DestroyObjects(M& m) : object(m) {}
+    ~DestroyObjects() { object.clear(); }
+    void operator()(std::pair<typename M::key_type,typename M::mapped_type> p) const {
+      DestroyObject<typename M::mapped_type>()(p.second); 
+    }
+  };
+  template<typename M> DestroyObjects<M> destroyObjects(M& m) { return DestroyObjects<M>(m); }
+
+  /// Helper to delete objects from heap and reset the pointer. Saves many many lines of code
+  template <typename T> inline void releasePtr(T*& p) {
+    if ( 0 != p ) p->release();
+    p = 0;
+  }
+
+  /// Functor to delete objects from heap and reset the pointer
+  template <typename T> struct ReleaseObject {
+    void operator()(T& p) const { 
+      releasePtr(p);
+    }
+  };
+  /// map Functor to delete objects from heap
+  template <typename M> struct ReleaseObjects {
+    M& object;
+    ReleaseObjects(M& m) : object(m) {}
+    ~ReleaseObjects() { object.clear(); }
+    void operator()(std::pair<typename M::key_type,typename M::mapped_type> p) const {
+      ReleaseObject<typename M::mapped_type>()(p.second); 
+    }
+  };
+  template<typename M> ReleaseObjects<M> releaseObjects(M& m) { return ReleaseObjects<M>(m); }
   
   /*
    *   Geometry namespace declaration
diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h
index 2083f7211..cdecee6d0 100644
--- a/DDCore/include/DD4hep/Readout.h
+++ b/DDCore/include/DD4hep/Readout.h
@@ -71,9 +71,10 @@ namespace DD4hep {
 
       /// ID decoder interface
       PlacedVolume getPlacement(const long64& cellID) const;
-      DetElement getSubDetector(const long64& cellID) const;
-      DetElement getDetectorElement(const long64& cellID) const;
-      Position getPosition(const long64& cellID) const;
+      DetElement   getSubDetector(const long64& cellID) const;
+      DetElement   getDetectorElement(const long64& cellID) const;
+      Position     getPosition(const long64& cellID) const;
+      Position     getLocalPosition(const long64& cellID) const;
       const TGeoMatrix& getWorldTransformation(const long64& cellID) const;
     };
 
diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h
index 2af67d584..089fa8518 100644
--- a/DDCore/include/DD4hep/Segmentations.h
+++ b/DDCore/include/DD4hep/Segmentations.h
@@ -12,8 +12,7 @@
 // Framework include files
 #include "DD4hep/Handle.h"
 #include "DD4hep/IDDescriptor.h"
-
-#include "DDSegmentation/Segmentation.h"
+#include "DDSegmentation/CartesianGridXYZ.h"
 
 // C/C++ include files
 #include <cmath>
@@ -28,127 +27,76 @@ namespace DD4hep {
    *   XML namespace declaration
    */
   namespace Geometry  {
-    
+
+    typedef DDSegmentation::BitField64 BitField64;
+
     /** @class Segmentation Segmentations.h DD4hep/Segmentations.h
      *
      * @author  M.Frank
      * @version 1.0
      */
-    struct Segmentation : public Ref_t   {
+    struct Segmentation : public Handle<DDSegmentation::Segmentation>  {
     public:
-      enum { REGULAR=0, EXTENDED=1 };
+      typedef DDSegmentation::Segmentation BaseSegmentation;
 
       /** @class Segmentation::Object Segmentations.h DD4hep/Segmentations.h
        *
        * @author  M.Frank
        * @version 1.0
        */
-      struct Object : public TNamed  {
+      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;
-        /// Spares to start 16 byte Byte aligned
-        unsigned char _spare[6];
-        /// The segmentation object
-        DDSegmentation::Segmentation* segmentation;
-        
-        union Data {
-          /// Maximal size and data buffer for specialized user segmentations
-          double values[32];
-          /// Extension buffer for specialized user segmentations, 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 CartesianGrid {
-            double grid_size_x;
-            double grid_size_y;
-            double grid_size_z;
-          } cartesian_grid;
-          struct CylindricalBinning  {
-            int nphi;
-            int ntheta;
-            int nz;
-          } cylindrical_binning;
-          struct CylindricalGrid   {
-            double grid_size_phi;
-            double grid_size_theta;
-            double grid_size_z;
-          } cylindrical_grid;
-          
-        } data;
+	/// Reference to base segmentation
+	BaseSegmentation* segmentation;
 	/// Standard constructor
         Object();
 	/// Default destructor
         virtual ~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>() {}
+      /// Initializing constructor creating new object
+      template <typename T> Segmentation(T* o, const std::string& nam, const std::string& typ)
+	: Handle<Implementation>()  {
+	o->segmentation = o;
+	assign(o,nam,typ);
+      }
       /// Constructor to be used when reading the already parsed object
-      template <typename Q> Segmentation(const Handle<Q>& e)
-      : Handle<Implementation>(e){}
-      /// Constructor to create a new segmentation object (to be called by super class only)
-      Segmentation(const std::string& type);
+      template <typename Q> Segmentation(const Handle<Q>& e) : Handle<Implementation>(e) {}
       /// Access flag for hit positioning
       bool useForHitPosition() const;
-      /// Segmentation type
-      const std::string type() const;
-      /// Assign segmentation object
-      void setSegmentation(DDSegmentation::Segmentation* segmentation);
+      /// Accessor: Segmentation type
+      std::string type() const;
+      /// Accessor: Set segmentation type
+      void setType(const std::string& new_type);
       /// Access segmentation object
-      DDSegmentation::Segmentation* segmentation();
-      /// Extend the segmentation object with an arbitrary structure accessible by the type
-      template<typename IFACE, typename CONCRETE> IFACE* setExtension(CONCRETE* c)
-      {  return (IFACE*)i_setExtension(dynamic_cast<IFACE*>(c),typeid(IFACE),_delete<IFACE>);   }
-      /// Access extension element by the type
-      template <class T> T* extensionUnchecked() const
-      {  return (T*)object<Object>().data.extension.ptr;                                        }
-      /// Access extension element by the type
-      template <class T> T* extension()  const         {  return (T*)i_extension(typeid(T));    }
-      /// 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));       }
+      BaseSegmentation* segmentation() const;
+      /// determine the local position based on the cell ID
+      std::vector<double> getLocalPosition(const long64& cellID) const;
+      /// determine the cell ID based on the local position
+      long64 getCellID(double x, double y, double z) const;
     };
-    
+
     /** @class SegmentationParams Segmentations.h DD4hep/Segmentations.h
      *
      * @author  M.Frank
      * @version 1.0
      */
-    struct SegmentationParams : public Ref_t   {
+    struct SegmentationParams : public Segmentation   {
     public:
       /// Segmentation parameter definition
       typedef std::pair<std::string,double> Parameter;
       /// Segmentation parameter container definition
       typedef std::vector<Parameter>        Parameters;
-      /// Object type
-      typedef Segmentation::Object Object;
-
       /// Constructor to be used when reading the already parsed object
-      SegmentationParams(const Segmentation& e) : Ref_t(e) {}
+      SegmentationParams(const Segmentation& e) : Segmentation(e) {}
       /// Segmentation type
-      const std::string type() const;
+      const std::string& type() const;
       /// Access to the parameters
       Parameters parameters() const;
     };
@@ -159,18 +107,36 @@ namespace DD4hep {
      * @version 1.0
      */
     struct ProjectiveCylinder : public Segmentation  {
+
+      struct Data : public Object, public BaseSegmentation {
+	int nphi;
+	int ntheta;
+	int nz;
+	/// Default constructor
+        Data(BitField64* decoder=0) : Object(), BaseSegmentation(decoder), nphi(0), ntheta(0), nz(0) {}
+	/// Default destructor
+	virtual ~Data();
+	/// determine the local position based on the cell ID
+	virtual std::vector<double> getLocalPosition(const long64& cellID) const;
+	/// determine the cell ID based on the local position
+	virtual long64 getCellID(double x, double y, double z) const;
+      };
       /// Constructor to be used when reading the already parsed object
       template <typename Q> ProjectiveCylinder(const Handle<Q>& e) : Segmentation(e) {}
       /// Constructor to create a new segmentation object
-      ProjectiveCylinder();
+      ProjectiveCylinder(LCDD& lcdd);
       /// Accessors: get number of bins in theta
       int thetaBins() const;
       /// Accessors: get number of bins in phi
       int phiBins() const;
+      /// Accessors: get number of bins in z
+      int zBins() const;
       /// Accessors: set number of bins in theta
       void setThetaBins(int value);
-      /// Accessors: set grid size in Y
+      /// Accessors: set number of bins in phi
       void setPhiBins(int value);
+      /// Accessors: set number of bins in Z
+      void setZBins(int value);
     };
     
     /** @class NonProjectiveCylinder Segmentations.h DD4hep/Segmentations.h
@@ -179,10 +145,23 @@ namespace DD4hep {
      * @version 1.0
      */
     struct NonProjectiveCylinder : public Segmentation  {
+      struct Data : public Object, public BaseSegmentation {
+	double grid_size_phi;
+	double grid_size_theta;
+	double grid_size_z;
+	/// Default constructor
+        Data(BitField64* decoder=0) : Object(), BaseSegmentation(decoder) { grid_size_phi=grid_size_theta=grid_size_z=0;}
+	/// Default destructor
+	virtual ~Data();
+	/// determine the local position based on the cell ID
+	virtual std::vector<double> getLocalPosition(const long64& cellID) const;
+	/// determine the cell ID based on the local position
+	virtual long64 getCellID(double x, double y, double z) const;
+      };
       /// Constructor to be used when reading the already parsed object
       template <typename Q> NonProjectiveCylinder(const Handle<Q>& e) : Segmentation(e) {}
       /// Constructor to create a new segmentation object
-      NonProjectiveCylinder();
+      NonProjectiveCylinder(LCDD& lcdd);
       /// Accessors: get size of bins in Z
       double gridSizeZ() const;
       /// Accessors: get size of bins in phi
@@ -199,10 +178,23 @@ namespace DD4hep {
      * @version 1.0
      */
     struct ProjectiveZPlane : public Segmentation  {
+      struct Data : public Object, public BaseSegmentation {
+	int nphi;
+	int ntheta;
+	int nz;
+	/// Default constructor
+        Data(BitField64* decoder=0) : Object(), BaseSegmentation(decoder) { nphi=ntheta=nz=0;}
+	/// Default destructor
+	virtual ~Data();
+	/// determine the local position based on the cell ID
+	virtual std::vector<double> getLocalPosition(const long64& cellID) const;
+	/// determine the cell ID based on the local position
+	virtual long64 getCellID(double x, double y, double z) const;
+      };
       /// Constructor to be used when reading the already parsed object
       template <typename Q> ProjectiveZPlane(const Handle<Q>& e) : Segmentation(e) {}
       /// Constructor to create a new segmentation object
-      ProjectiveZPlane();
+      ProjectiveZPlane(LCDD& lcdd);
       /// Accessors: get number of bins in theta
       int thetaBins() const;
       /// Accessors: get number of bins in phi
@@ -219,22 +211,24 @@ namespace DD4hep {
      * @version 1.0
      */
     struct GridXY : public Segmentation   {
+      struct Data : public Object, public DDSegmentation::CartesianGridXY {
+	/// Default constructor
+        Data(BitField64* decoder=0) : Object(), DDSegmentation::CartesianGridXY(decoder) {}
+	/// Default destructor
+	virtual ~Data();
+      };
       /// Constructor to be used when reading the already parsed object
       template <typename Q> GridXY(const Handle<Q>& e) : Segmentation(e) {}
       /// Constructor to create a new segmentation object
-      GridXY();
-      /// Constructor to be used when creating a new object. Data are taken from the input handle
-      GridXY(const std::string& tag);
-      /// Constructor to be used when creating a new object.
-      GridXY(const std::string& tag, double size_x, double size_y);
+      GridXY(LCDD& lcdd, const std::string& typ);
       /// Accessors: set grid size in X
       void setGridSizeX(double value);
       /// Accessors: set grid size in Y
       void setGridSizeY(double value);
       /// Accessors: get grid size in X
-      double getGridSizeX()const;
+      double getGridSizeX()  const;
       /// Accessors: get grid size in Y
-      double getGridSizeY()const;
+      double getGridSizeY()  const;
     };
     
     /** @class GridXYZ Segmentations.h DD4hep/Segmentations.h
@@ -242,42 +236,31 @@ namespace DD4hep {
      * @author  M.Frank
      * @version 1.0
      */
-    struct GridXYZ : public GridXY  {
+    struct GridXYZ : public Segmentation  {
+      struct Data : public Object, public DDSegmentation::CartesianGridXYZ {
+	/// Default constructor
+        Data(BitField64* decoder=0) : Object(), DDSegmentation::CartesianGridXYZ(decoder) {}
+	/// Default destructor
+	virtual ~Data();
+      };
       /// Constructor to be used when reading the already parsed object
       template <typename Q> GridXYZ(const Handle<Q>& e) : GridXY(e) {}
       /// Constructor to be used when creating a new object.
-      GridXYZ();
-      /// Constructor to be used when creating a new object.
-      GridXYZ(double size_x, double size_y, double size_z);
+      GridXYZ(LCDD& lcdd, const std::string& typ);
+      /// Accessors: set grid size in X
+      void setGridSizeX(double value);
+      /// Accessors: set grid size in Y
+      void setGridSizeY(double value);
       /// Accessors: set grid size in Z
       void setGridSizeZ(double value);
+      /// Accessors: get grid size in X
+      double getGridSizeX()  const;
+      /// Accessors: get grid size in Y
+      double getGridSizeY()  const;
+      /// Accessors: get grid size in Z
+      double getGridSizeZ()  const;
     };
-    
-    /** @class CartesianGridXY Segmentations.h DD4hep/Segmentations.h
-     *
-     * @author  M.Frank
-     * @version 1.0
-     */
-    struct CartesianGridXY : public GridXY   {
-      /// Constructor to be used when reading the already parsed object
-      template <typename Q> CartesianGridXY(const Handle<Q>& e) : GridXY(e) {}
-      /// Constructor to be used when creating a new object. Data are taken from the input handle
-      CartesianGridXY() : GridXY("cartesian_grid_xy") {}
-    };
-    
-    /** @class GlobalGridXY Segmentations.h DD4hep/Segmentations.h
-     *
-     * @author  M.Frank
-     * @version 1.0
-     */
-    struct GlobalGridXY : public GridXY   {
-      /// Constructor to be used when reading the already parsed object
-      template <typename Q> GlobalGridXY(const Handle<Q>& e) : GridXY(e) {}
-      /// Constructor to be used when creating a new object. Data are taken from the input handle
-      GlobalGridXY() : GridXY("global_grid_xy") {}
-    };
-    
-    
+
   }       /* End namespace Geometry              */
 }         /* End namespace DD4hep                */
 #endif    /* DD4HEP_GEOMETRY_SEGMENTATIONS_H     */
diff --git a/DDCore/include/XML/Conversions.h b/DDCore/include/XML/Conversions.h
index 9dca1d186..9ae37008e 100644
--- a/DDCore/include/XML/Conversions.h
+++ b/DDCore/include/XML/Conversions.h
@@ -20,7 +20,7 @@
 namespace DD4hep {
 
   // Forward declarations
-  namespace XML  {    struct Handle_t;  };
+  namespace XML  {    struct Handle_t;  }
 
     /** @class Converter Conversions.h  DD4hep/compact/Conversions.h
       *
@@ -42,6 +42,10 @@ namespace DD4hep {
       Converter(Geometry::LCDD& l, user_param p) : lcdd(l), param(p) {}
       /// Callback operator to be specialized depending on the element type
       void operator()(XML::Handle_t xml) const;
+      /// Typed access to the user parameter (unchecked)
+      template <typename TYPE> TYPE* _param()  const  {  return (TYPE*)param;  }
+      /// Typed object access to the user parameter (unchecked)
+      template <typename TYPE> TYPE& _object() const  {  return *(TYPE*)param; }
     };
-}         /* End namespace DD4hep   */
+}         /* End namespace DD4hep           */
 #endif    /* DD4hep_COMPACT_CONVERSION_H    */
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index 9514f4d30..ca65b0816 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -593,6 +593,10 @@ namespace DD4hep {
       bool hasAttr(const XmlChar* name) const                   {  return m_element.hasAttr(name);        }
       /// Access attribute with implicit return type conversion
       template <class T> T attr(const XmlChar* tag) const       {  return m_element.attr<T>(tag);         }
+      /// Access attribute name (throws exception if not present)
+      const XmlChar* attr_name(const Attribute attr)  const     {  return m_element.attr_name(attr);      }
+      /// Access attribute value by the attribute  (throws exception if not present)
+      const XmlChar* attr_value(const Attribute attr)  const    {  return m_element.attr_value(attr);     }
       /// Access the number of children of this DOM element with a given tag name
       size_t numChildren(const XmlChar* tag,bool exc=true) const{  return m_element.numChildren(tag,exc); }
       /// Remove own attributes and copy all attributes from handle 'e'
diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp
index c4495c249..1559c1642 100644
--- a/DDCore/src/Detector.cpp
+++ b/DDCore/src/Detector.cpp
@@ -133,7 +133,7 @@ DetElement::Object::Object()
 
 /// Internal object destructor: release extension object(s)
 DetElement::Object::~Object() {
-  for_each(children.begin(),children.end(), DestroyHandles<>());
+  for_each(children.begin(),children.end(),destroyHandles(children));
   deletePtr(worldTrafo);
   deletePtr(parentTrafo);
   deletePtr(referenceTrafo);
diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp
index d2bea8fac..aed9497bf 100644
--- a/DDCore/src/Handle.cpp
+++ b/DDCore/src/Handle.cpp
@@ -12,8 +12,6 @@
 #include "XML/Evaluator.h"
 #include <iostream>
 
-#include "DD4hep/LCDD.h"
-
 #if !defined(WIN32) && !defined(__ICC)
 #include "cxxabi.h"
 #endif
@@ -151,43 +149,43 @@ string DD4hep::Geometry::_toString(double value)   {
   ::snprintf(text,sizeof(text),"%f",value);
   return text;
 }
-namespace DD4hep { namespace Geometry {
-  static long s_numVerifies = 0;
-
-  long num_object_validations()         {    return s_numVerifies;  }
-  void increment_object_validations()   {    ++s_numVerifies;       }
-
-  template <typename T> void Handle<T>::bad_assignment(const type_info& from, const type_info& to) {
-    string msg = "Wrong assingment from ";
-    msg += from.name();
-    msg += " to ";
-    msg += to.name();
-    msg += " not possible!!";
-    throw runtime_error(msg);
-  }
-  template <typename T> void Handle<T>::assign(T* n, const string& nam, const string& tit) {
-    this->m_element = n;
-    if ( !nam.empty() ) n->SetName(nam.c_str());
-    if ( !tit.empty() ) n->SetTitle(tit.c_str());
-  }
+namespace DD4hep {
+  namespace Geometry {
+    static long s_numVerifies = 0;
+
+    long num_object_validations()         {    return s_numVerifies;  }
+    void increment_object_validations()   {    ++s_numVerifies;       }
+
+    template <typename T> void Handle<T>::bad_assignment(const type_info& from, const type_info& to) {
+      string msg = "Wrong assingment from ";
+      msg += from.name();
+      msg += " to ";
+      msg += to.name();
+      msg += " not possible!!";
+      throw runtime_error(msg);
+    }
+    template <typename T> void Handle<T>::assign(T* n, const string& nam, const string& tit) {
+      this->m_element = n;
+      if ( !nam.empty() ) n->SetName(nam.c_str());
+      if ( !tit.empty() ) n->SetTitle(tit.c_str());
+    }
 
-  template <typename T> const char* Handle<T>::name() const  
-  { return this->m_element ? this->m_element->GetName() : "";   }
+    template <typename T> const char* Handle<T>::name() const  
+    { return this->m_element ? this->m_element->GetName() : "";   }
 
-  template <> const char* Handle<TObject>::name() const  
-  { return "";   }
+    template <> const char* Handle<TObject>::name() const  
+    { return "";   }
 
-  template <> void Handle<TObject>::bad_assignment(const type_info& from, const type_info& to) {
-    string msg = "Wrong assingment from ";
-    msg += from.name();
-    msg += " to ";
-    msg += to.name();
-    msg += " not possible!!";
-    throw runtime_error(msg);
+    template <> void Handle<TObject>::bad_assignment(const type_info& from, const type_info& to) {
+      string msg = "Wrong assingment from ";
+      msg += from.name();
+      msg += " to ";
+      msg += to.name();
+      msg += " not possible!!";
+      throw runtime_error(msg);
+    }
   }
-}}
-
-
+}
 
 static const std::string __typeinfoName( const std::type_info& tinfo) {
   const char* class_name = tinfo.name();
@@ -307,10 +305,27 @@ static const std::string __typeinfoName( const std::type_info& tinfo) {
   return result;
 }
 
-string DD4hep::Geometry::typeName(const type_info& typ) {
+string DD4hep::typeName(const type_info& typ) {
   return __typeinfoName(typ);
 }
 
+
+
+#include "DDSegmentation/Segmentation.h"
+typedef DDSegmentation::Segmentation _Segmentation;
+//INSTANTIATE_UNNAMED(_Segmentation);
+namespace DD4hep { namespace Geometry {
+    template <> void Handle<_Segmentation>::assign(_Segmentation* s, const std::string& n, const std::string& t) {
+      this->m_element = s;
+      s->setType(t);
+      s->setName(n);
+    }
+    template <> const char* Handle<_Segmentation>::name() const
+    { return this->m_element ? this->m_element->name().c_str() : "";   }
+    template struct DD4hep::Geometry::Handle<_Segmentation>;
+}}
+
+#include "DD4hep/LCDD.h"
 #include "TMap.h"
 #include "TColor.h"
 
diff --git a/DDCore/src/InstanceCount.cpp b/DDCore/src/InstanceCount.cpp
index 8b8a1a803..82dd9093f 100644
--- a/DDCore/src/InstanceCount.cpp
+++ b/DDCore/src/InstanceCount.cpp
@@ -18,7 +18,6 @@
 
 using namespace std;
 using namespace DD4hep;
-using namespace DD4hep::Geometry;
 
 /// Do not clutter global namespace
 namespace {
diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp
index 29ccadf58..a41eea292 100644
--- a/DDCore/src/LCDDImp.cpp
+++ b/DDCore/src/LCDDImp.cpp
@@ -47,13 +47,30 @@ namespace {
     TypePreserve(LCDDBuildType& t) : m_t(t) { }
     ~TypePreserve() { m_t = BUILD_NONE; }
   };
+
+  struct ExtensionEntry {
+    int     id;
+  };
+  typedef map<const type_info*, ExtensionEntry> ExtensionMap;
+  static int s_extensionID = 0;
+  ExtensionMap& lcdd_extensions() {
+    static ExtensionMap s_map;
+    return s_map;
+  }
+  static LCDD* s_lcdd = 0;
 }
 
 LCDD& LCDD::getInstance() {
-  static LCDD* s_lcdd = new LCDDImp();
+  if ( !s_lcdd )  s_lcdd = new LCDDImp();
   return *s_lcdd; 
 }
 
+/// Destroy the instance
+void LCDD::destroyInstance()   {
+  if ( s_lcdd ) delete s_lcdd;
+  s_lcdd = 0;
+}
+
 /// Default constructor
 LCDDImp::LCDDImp() 
   : m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global"),
@@ -88,21 +105,20 @@ LCDDImp::LCDDImp()
 
 /// Standard destructor
 LCDDImp::~LCDDImp() {
-  DestroyHandles<> del;
   destroyHandle(m_world);
   destroyHandle(m_field);
   destroyHandle(m_header);
   destroyHandle(m_volManager);
   destroyObject(m_properties);
-  for_each(m_readouts.begin(),    m_readouts.end(),     del);
-  for_each(m_idDict.begin(),      m_idDict.end(),       del);
-  for_each(m_limits.begin(),      m_limits.end(),       del);
-  for_each(m_regions.begin(),     m_regions.end(),      del);
-  for_each(m_alignments.begin(),  m_alignments.end(),   del);
-  for_each(m_sensitive.begin(),   m_sensitive.end(),    del);
-  for_each(m_display.begin(),     m_display.end(),      del);
-  for_each(m_fields.begin(),      m_fields.end(),       del);
-  for_each(m_define.begin(),      m_define.end(),       del);
+  for_each(m_readouts.begin(),    m_readouts.end(),     destroyHandles(m_readouts));
+  for_each(m_idDict.begin(),      m_idDict.end(),       destroyHandles(m_idDict));
+  for_each(m_limits.begin(),      m_limits.end(),       destroyHandles(m_limits));
+  for_each(m_regions.begin(),     m_regions.end(),      destroyHandles(m_regions));
+  for_each(m_alignments.begin(),  m_alignments.end(),   destroyHandles(m_alignments));
+  for_each(m_sensitive.begin(),   m_sensitive.end(),    destroyHandles(m_sensitive));
+  for_each(m_display.begin(),     m_display.end(),      destroyHandles(m_display));
+  for_each(m_fields.begin(),      m_fields.end(),       destroyHandles(m_fields));
+  for_each(m_define.begin(),      m_define.end(),       destroyHandles(m_define));
 
   m_trackers.clear();
   m_worldVol.clear();
@@ -114,6 +130,36 @@ LCDDImp::~LCDDImp() {
   InstanceCount::decrement(this);
 }
 
+/// Add an extension object to the detector element
+void* LCDDImp::addUserExtension(void* ptr, const std::type_info& info)  {
+  Extensions::iterator j = m_extensions.find(&info);
+  if ( j == m_extensions.end() )   {
+    ExtensionMap& m = lcdd_extensions();
+    ExtensionMap::iterator i = m.find(&info);
+    if ( i == m.end() ) {
+      ExtensionEntry entry;
+      entry.id = ++s_extensionID;
+      m.insert(make_pair(&info,entry));
+      i = m.find(&info);
+    }
+    ExtensionEntry& e = (*i).second;
+    //cout << "Extension[" << name() << "]:" << ptr << " " << info.name() << endl;
+    return m_extensions[&info] = ptr;
+  }
+  throw runtime_error("DD4hep: LCDD::addUserExtension: The object "
+		      " already has an extension of type:"+string(info.name())+".");
+}
+
+/// Access an existing extension object from the detector element
+void* LCDDImp::userExtension(const std::type_info& info)  const    {
+  Extensions::const_iterator j = m_extensions.find(&info);
+  if ( j != m_extensions.end() )   {
+    return (*j).second;
+  }
+  throw runtime_error("DD4hep: LCDD::userExtension: The object "
+		      " has no extension of type:"+string(info.name())+".");
+}
+
 Volume LCDDImp::pickMotherVolume(const DetElement&) const  {     // throw if not existing
   return m_worldVol;
 }
diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h
index 9739a683a..2014dc4af 100644
--- a/DDCore/src/LCDDImp.h
+++ b/DDCore/src/LCDDImp.h
@@ -93,6 +93,10 @@ namespace DD4hep {
       Properties*         m_properties;
       LCDDBuildType       m_buildType;
 
+      /// Definition of the extension type
+      typedef std::map<const std::type_info*,void*>  Extensions;
+      Extensions          m_extensions;
+
       /// Default constructor
       LCDDImp();
 
@@ -117,6 +121,11 @@ namespace DD4hep {
       virtual void init();
       virtual void endDocument();
 
+      /// Add an extension object to the detector element
+      virtual void* addUserExtension(void* ptr, const std::type_info& info);
+      /// Access an existing extension object from the detector element
+      virtual void* userExtension(const std::type_info& info)  const;
+
       virtual Handle<TObject> getRefChild(const HandleMap& e, const std::string& name, bool throw_if_not=true)  const;
       virtual Volume          pickMotherVolume(const DetElement& sd) const;
 
diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp
index 240eb5728..1cd21eed6 100644
--- a/DDCore/src/Readout.cpp
+++ b/DDCore/src/Readout.cpp
@@ -24,7 +24,7 @@ Readout::Object::Object()  {
 
 /// Default destructor
 Readout::Object::~Object()  {
-  destroyHandle(segmentation);
+  //destroyHandle(segmentation);
   InstanceCount::decrement(this);
 }
 
@@ -42,7 +42,7 @@ void Readout::setIDDescriptor(const Ref_t& new_descriptor)  const   {
       Segmentation seg = data<Object>()->segmentation;
       IDDescriptor id = new_descriptor;
       if (seg.isValid()) {
-    	  seg.segmentation()->setDecoder(id.decoder());
+	//seg.segmentation()->setDecoder(id.decoder());
       }
       return;
     }
@@ -78,30 +78,35 @@ Segmentation Readout::segmentation() const  {
 
 /// full ID decoder interface
 PlacedVolume Readout::getPlacement(const long64& cellID) const {
-	VolumeManager volMan = LCDD::getInstance().volumeManager();
-	return volMan.lookupPlacement(cellID);
+  VolumeManager volMan = LCDD::getInstance().volumeManager();
+  return volMan.lookupPlacement(cellID);
 }
+
 DetElement Readout::getSubDetector(const long64& cellID) const{
-	VolumeManager volMan = LCDD::getInstance().volumeManager();
-	return volMan.lookupDetector(cellID);
+  VolumeManager volMan = LCDD::getInstance().volumeManager();
+  return volMan.lookupDetector(cellID);
 }
+
 DetElement Readout::getDetectorElement(const long64& cellID) const {
-	VolumeManager volMan = LCDD::getInstance().volumeManager();
-	return volMan.lookupDetElement(cellID);
+  VolumeManager volMan = LCDD::getInstance().volumeManager();
+  return volMan.lookupDetElement(cellID);
 }
+
 Position Readout::getPosition(const long64& cellID) const {
-	VolumeManager volMan = LCDD::getInstance().volumeManager();
-	std::vector<double> position = segmentation().segmentation()->getPosition(cellID);
-	if (segmentation().segmentation()->isLocal()) {
-		double global[3] = {0., 0., 0.};
-		volMan.worldTransformation(cellID).LocalToMaster(&position[0], global);
-		return Position(global[0]/tgeo::mm, global[1]/tgeo::mm, global[2]/tgeo::mm);
-	}
-	return Position(position[0]/tgeo::mm, position[1]/tgeo::mm, position[2]/tgeo::mm);
+  double global[3] = {0., 0., 0.};
+  VolumeManager volMan = LCDD::getInstance().volumeManager();
+  volMan.worldTransformation(cellID).LocalToMaster(&(segmentation().segmentation()->getLocalPosition(cellID))[0], global);
+  return Position(global[0]/tgeo::mm, global[1]/tgeo::mm, global[2]/tgeo::mm);
 }
+
+Position Readout::getLocalPosition(const long64& cellID) const {
+  std::vector<double> v = segmentation().segmentation()->getLocalPosition(cellID);
+  return Position(v[0], v[1], v[2]);
+}
+
 const TGeoMatrix& Readout::getWorldTransformation(const long64& cellID) const {
-	VolumeManager volMan = LCDD::getInstance().volumeManager();
-	return volMan.worldTransformation(cellID);
+  VolumeManager volMan = LCDD::getInstance().volumeManager();
+  return volMan.worldTransformation(cellID);
 }
 
 /// Standard constructor
diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp
index a055c3cd9..49e31d547 100644
--- a/DDCore/src/Segementations.cpp
+++ b/DDCore/src/Segementations.cpp
@@ -10,38 +10,33 @@
 #include "DD4hep/Segmentations.h"
 #include "DD4hep/InstanceCount.h"
 #include <iostream>
+#include <stdexcept>
 
 using namespace std;
+using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
+namespace {
+  void not_implemented_call(const char* tag)  {
+    throw runtime_error(tag);
+  }
+}
+
 /// Standard constructor
 Segmentation::Object::Object() 
-: magic(magic_word()), type(REGULAR), useForHitPosition(0) 
+  : magic(magic_word()), useForHitPosition(0) 
 {
-  segmentation = 0;
   InstanceCount::increment(this);
-  ::memset(data.values,0,sizeof(data.values));
-  _spare[5]=_spare[4]=_spare[3]=_spare[2]=_spare[1]=_spare[0]=0;
 }
 
 /// Default destructor
 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;
-    }
-  }
-  if (segmentation != 0) {
-	  delete segmentation;
-  }
   InstanceCount::decrement(this);
 }
 
-Segmentation::Segmentation(const string& type)  {
-  assign(new Object(),"segmentation",type);
+/// Accessor: Segmentation type
+std::string Segmentation::type() const   {
+  return segmentation()->type();
 }
 
 bool Segmentation::useForHitPosition() const   {
@@ -49,21 +44,17 @@ bool Segmentation::useForHitPosition() const   {
 }
 
 /// Segmentation type
-const string Segmentation::type() const   {
+const string& SegmentationParams::type() const   {
   return object<Object>().segmentation->type();
 }
 
-/// Assign segmentation object
-void Segmentation::setSegmentation(DD4hep::DDSegmentation::Segmentation* segmentation) {
-  Object& o = object<Object>();
-  if (o.segmentation != 0) {
-    delete o.segmentation;
-  }
-  o.segmentation = segmentation;
+/// Access to the parameters
+SegmentationParams::Parameters SegmentationParams::parameters() const  {
+  return object<Object>().segmentation->parameters();
 }
 
 /// Access segmentation object
-DD4hep::DDSegmentation::Segmentation* Segmentation::segmentation() {
+DD4hep::DDSegmentation::Segmentation* Segmentation::segmentation()  const  {
   Object& o = object<Object>();
   if (o.segmentation != 0)
     return o.segmentation;
@@ -71,167 +62,202 @@ DD4hep::DDSegmentation::Segmentation* Segmentation::segmentation() {
 		      " knows no implementation object [This is no longer allowed in the presence of DDSegmentation]");
 }
 
-/// Add an extension object to the detector element
-void* Segmentation::i_setExtension(void* ptr, const type_info& info, void (*destruct)(void*)) {
-  Object& o = object<Object>();
-  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 type_info& info)   const {
-  if ( isValid() ) {
-    Object::Data::Extension& o = object<Object>().data.extension;
-    if ( o.ptr )   {
-      if ( &info == o.info ) {
-	return o.ptr;
-      }
-      throw runtime_error("DD4hep: extension: The segmentation object "+string(type())+
-			  " has the wrong type!");
-    }
-    throw runtime_error("DD4hep: extension: The segmentation object "+string(type())+
-			" has no extension defined.");
-  }
-  throw runtime_error("DD4hep: extension: The segmentation object is not valid!");
+/// Default destructor
+ProjectiveCylinder::Data::~Data()  {
 }
- 
-/// Segmentation type
-const string SegmentationParams::type() const   {
-  return m_element->GetTitle();
+
+/// determine the local position based on the cell ID
+std::vector<double> ProjectiveCylinder::Data::getLocalPosition(const long64& cellID) const   {
+  not_implemented_call("GridXY::Data::getLocalPosition");
+  return vector<double>();
 }
 
-/// Access to the parameters
-SegmentationParams::Parameters SegmentationParams::parameters() const  {
-  return object<Object>().segmentation->parameters();
+/// determine the cell ID based on the local position
+long64 ProjectiveCylinder::Data::getCellID(double x, double y, double z) const   {
+  not_implemented_call("GridXY::Data::getCellID");
+  return 0;
 }
 
-ProjectiveCylinder::ProjectiveCylinder() : Segmentation("projective_cylinder")   
+/// Constructor to create a new segmentation object
+ProjectiveCylinder::ProjectiveCylinder(LCDD&) : Segmentation(new Data(),"segmentation","projective_cylinder")   
 {
 }
 
 /// Accessors: get number of bins in theta
 int ProjectiveCylinder::thetaBins() const    {
-  return object<Object>().data.cylindrical_binning.ntheta;
+  return object<Data>().ntheta;
 }
 
 /// Accessors: get number of bins in phi
 int ProjectiveCylinder::phiBins() const    {
-  return object<Object>().data.cylindrical_binning.nphi;
+  return object<Data>().nphi;
+}
+
+/// Accessors: get number of bins in z
+int ProjectiveCylinder::zBins() const  {
+  return object<Data>().nz;
 }
 
 /// Accessors: set number of bins in theta
 void ProjectiveCylinder::setThetaBins(int value)    {
-  object<Object>().data.cylindrical_binning.ntheta = value;
+  object<Data>().ntheta = value;
 }
 
 /// Accessors: set grid size in Y
 void ProjectiveCylinder::setPhiBins(int value)   {
-  object<Object>().data.cylindrical_binning.nphi = value;
+  object<Data>().nphi = value;
+}
+
+/// Accessors: set number of bins in Z
+void ProjectiveCylinder::setZBins(int value)  {
+  object<Data>().nz = value;
+}
+
+/// Default destructor
+NonProjectiveCylinder::Data::~Data()  {
+}
+
+/// determine the local position based on the cell ID
+std::vector<double> NonProjectiveCylinder::Data::getLocalPosition(const long64& cellID) const   {
+  not_implemented_call("GridXY::Data::getLocalPosition");
+  return vector<double>();
+}
+
+/// determine the cell ID based on the local position
+long64 NonProjectiveCylinder::Data::getCellID(double x, double y, double z) const   {
+  not_implemented_call("GridXY::Data::getCellID");
+  return 0;
 }
 
-NonProjectiveCylinder::NonProjectiveCylinder()
-: Segmentation("nonprojective_cylinder")
+/// Constructor to create a new segmentation object
+NonProjectiveCylinder::NonProjectiveCylinder(LCDD&) : Segmentation(new Data(),"segmentation","nonprojective_cylinder")
 {
 }
 
+/// Accessors: get size of bins in Z
 double NonProjectiveCylinder::gridSizeZ()  const   {
-  return object<Object>().data.cylindrical_grid.grid_size_z;
+  return object<Data>().grid_size_z;
 }
 
+/// Accessors: get size of bins in phi
 double NonProjectiveCylinder::gridSizePhi()  const   {
-  return object<Object>().data.cylindrical_grid.grid_size_phi;
+  return object<Data>().grid_size_phi;
 }
 
 /// Accessors: set number of bins in theta
 void NonProjectiveCylinder::setThetaBinSize(double value)   {
-  object<Object>().data.cylindrical_grid.grid_size_phi = value;
+  object<Data>().grid_size_phi = value;
 }
 
 /// Accessors: set grid size in Y
 void NonProjectiveCylinder::setPhiBinSize(double value)   {
-  object<Object>().data.cylindrical_grid.grid_size_z = value;
+  object<Data>().grid_size_z = value;
 }
 
+/// Default destructor
+ProjectiveZPlane::Data::~Data()  {
+}
+
+/// determine the local position based on the cell ID
+std::vector<double> ProjectiveZPlane::Data::getLocalPosition(const long64& cellID) const   {
+  not_implemented_call("GridXY::Data::getLocalPosition");
+  return vector<double>();
+}
 
-/// Constructor to be used when creating a new DOM tree.
-ProjectiveZPlane::ProjectiveZPlane() 
-: Segmentation("projective_zplane")
+/// determine the cell ID based on the local position
+long64 ProjectiveZPlane::Data::getCellID(double x, double y, double z) const   {
+  not_implemented_call("GridXY::Data::getCellID");
+  return 0;
+}
+
+/// Constructor to be used when creating a new object.
+ProjectiveZPlane::ProjectiveZPlane(LCDD&) : Segmentation(new Data(),"segmentation","projective_zplane")
 {
 }
 
 /// Accessors: get number of bins in phi
 int ProjectiveZPlane::phiBins() const  {
-  return object<Object>().data.cylindrical_binning.nphi;
+  return object<Data>().nphi;
 }
 
 /// Accessors: get number of bins in theta
 int ProjectiveZPlane::thetaBins() const  {
-  return object<Object>().data.cylindrical_binning.ntheta;
+  return object<Data>().ntheta;
 }
 
 /// Accessors: set number of bins in theta
 void ProjectiveZPlane::setThetaBins(int value)  {
-  object<Object>().data.cylindrical_binning.ntheta = value;
+  object<Data>().ntheta = value;
 }
 
 /// Accessors: set grid size in Y
 void ProjectiveZPlane::setPhiBins(int value)  {
-  object<Object>().data.cylindrical_binning.nphi = value;
+  object<Data>().nphi = value;
 }
 
-GridXY::GridXY() 
-: Segmentation("grid_xy")   {}
-
-/// Constructor to be used when creating a new object. Data are taken from the input handle
-GridXY::GridXY(const string& tag) 
-: Segmentation(tag) 
-{
+/// Default destructor
+GridXY::Data::~Data()  {
 }
 
 /// Constructor to be used when creating a new object.
-GridXY::GridXY(const string& tag, double size_x, double size_y)
-: Segmentation(tag)
-{
-  object<Object>().data.cartesian_grid.grid_size_x = size_x;
-  object<Object>().data.cartesian_grid.grid_size_y = size_y;
+GridXY::GridXY(LCDD&, const std::string& typ) : Segmentation(new Data(),"segmentation",typ)   {
 }
 
 /// Accessors: get grid size in X
 double GridXY::getGridSizeX() const {
-  return object<Object>().data.cartesian_grid.grid_size_x;
+  return object<Data>().getGridSizeX();
 }
 
 /// Accessors: get grid size in Y
 double GridXY::getGridSizeY() const {
-  return object<Object>().data.cartesian_grid.grid_size_y;
+  return object<Data>().getGridSizeY();
 }
 
 /// Accessors: set grid size in X
 void GridXY::setGridSizeX(double value)  {
-  object<Object>().data.cartesian_grid.grid_size_x = value;
+  object<Data>().setGridSizeX(value);
 }
 
 /// Accessors: set grid size in Y
 void GridXY::setGridSizeY(double value)  {
-  object<Object>().data.cartesian_grid.grid_size_y = value;
+  object<Data>().setGridSizeY(value);
 }
 
-/// Constructor to be used when creating a new DOM tree.
-GridXYZ::GridXYZ()   
-: GridXY("grid_xyz")
-{
+/// Default destructor
+GridXYZ::Data::~Data()  {
 }
 
 /// Constructor to be used when creating a new object.
-GridXYZ::GridXYZ(double size_x, double size_y, double size_z)
-: GridXY("grid_xyz", size_x, size_y)
-{
-  object<Object>().data.cartesian_grid.grid_size_z = size_z;
+GridXYZ::GridXYZ(LCDD& , const std::string& typ) : Segmentation(new Data(),"segmentation",typ)  {
+  assign(new Data(),"segmentation",typ);
+}
+
+/// Accessors: get grid size in X
+double GridXYZ::getGridSizeX() const {
+  return object<Data>().getGridSizeX();
+}
+
+/// Accessors: get grid size in Y
+double GridXYZ::getGridSizeY() const {
+  return object<Data>().getGridSizeY();
+}
+
+/// Accessors: get grid size in Z
+double GridXYZ::getGridSizeZ() const {
+  return object<Data>().getGridSizeZ();
+}
+
+/// Accessors: set grid size in X
+void GridXYZ::setGridSizeX(double value)  {
+  object<Data>().setGridSizeX(value);
+}
+
+/// Accessors: set grid size in Y
+void GridXYZ::setGridSizeY(double value)  {
+  object<Data>().setGridSizeY(value);
 }
 
+/// Accessors: set grid size in Z
 void GridXYZ::setGridSizeZ(double value)  {
-  object<Object>().data.cartesian_grid.grid_size_z = value;
+  object<Data>().setGridSizeZ(value);
 }
diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp
index 026006208..20c7aeeda 100644
--- a/DDCore/src/VolumeManager.cpp
+++ b/DDCore/src/VolumeManager.cpp
@@ -289,10 +289,10 @@ VolumeManager::Object::~Object()   {
   bool  hasTop = (flags&VolumeManager::ONE)==VolumeManager::ONE;
   bool  isSdet = (flags&VolumeManager::TREE)==VolumeManager::TREE && obj != this;
   /// Cleanup volume tree
-  for_each(volumes.begin(),volumes.end(),DestroyObjects<VolIdentifier,Context*>());
+  for_each(volumes.begin(),volumes.end(),destroyObjects(volumes));
   volumes.clear();
   /// Cleanup dependent managers
-  for_each(managers.begin(),managers.end(),DestroyHandles<VolumeID,VolumeManager>());
+  for_each(managers.begin(),managers.end(),destroyHandles(managers));
   managers.clear();
   subdetectors.clear();
 }
diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp
index a2ab5752b..816aeb9b5 100644
--- a/DDCore/src/plugins/Compact2Objects.cpp
+++ b/DDCore/src/plugins/Compact2Objects.cpp
@@ -68,65 +68,59 @@ namespace {
 
 }
 
-static Ref_t create_GridXYZ(lcdd_t& /* lcdd */, xml_h e)  {
-  GridXYZ obj;
-  DDSegmentation::CartesianGridXYZ* seg = new DDSegmentation::CartesianGridXYZ("");
-  obj.setSegmentation(seg);
-  if ( e.hasAttr(_U(gridSizeX)) ) seg->setGridSizeX(e.attr<float>(_U(gridSizeX)));
-  if ( e.hasAttr(_U(gridSizeY)) ) seg->setGridSizeY(e.attr<float>(_U(gridSizeY)));
-  if ( e.hasAttr(_U(gridSizeZ)) ) seg->setGridSizeZ(e.attr<float>(_U(gridSizeZ)));
+static Ref_t create_GridXYZ(lcdd_t& lcdd, xml_h e)  {
+  GridXYZ obj(lcdd,"grid_xyz");
+  if ( e.hasAttr(_U(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_U(gridSizeX)));
+  if ( e.hasAttr(_U(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_U(gridSizeY)));
+  if ( e.hasAttr(_U(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_U(gridSizeZ)));
   return obj;
 }
 DECLARE_XMLELEMENT(GridXYZ,create_GridXYZ);
 
-static Ref_t create_GlobalGridXY(lcdd_t& /* lcdd */, xml_h e)  {
-  GlobalGridXY obj;
-  DDSegmentation::CartesianGridXY* seg = new DDSegmentation::CartesianGridXY("");
-    obj.setSegmentation(seg);
-  if ( e.hasAttr(_U(gridSizeX)) ) seg->setGridSizeX(e.attr<float>(_U(gridSizeX)));
-  if ( e.hasAttr(_U(gridSizeY)) ) seg->setGridSizeY(e.attr<float>(_U(gridSizeY)));
+static Ref_t create_GlobalGridXY(lcdd_t& lcdd, xml_h e)  {
+  GridXY obj(lcdd,"global_grid_xy");
+  if ( e.hasAttr(_U(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_U(gridSizeX)));
+  if ( e.hasAttr(_U(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_U(gridSizeY)));
   return obj;
 }
 DECLARE_XMLELEMENT(GlobalGridXY,create_GlobalGridXY);
 
-static Ref_t create_CartesianGridXY(lcdd_t& /* lcdd */, xml_h e)  {
-  CartesianGridXY obj;
-  DDSegmentation::CartesianGridXY* seg = new DDSegmentation::CartesianGridXY("");
-  obj.setSegmentation(seg);
-  if ( e.hasAttr(_U(gridSizeX)) ) seg->setGridSizeX(e.attr<double>(_U(gridSizeX)));
-  if ( e.hasAttr(_U(gridSizeY)) ) seg->setGridSizeY(e.attr<double>(_U(gridSizeY)));
+static Ref_t create_CartesianGridXY(lcdd_t& lcdd, xml_h e)  {
+  GridXY obj(lcdd,"cartesian_grid_xy");
+  if ( e.hasAttr(_U(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_U(gridSizeX)));
+  if ( e.hasAttr(_U(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_U(gridSizeY)));
   return obj;
 }
 DECLARE_XMLELEMENT(CartesianGridXY,create_CartesianGridXY);
 
-namespace DD4hep { namespace Geometry { typedef CartesianGridXY RegularNgonCartesianGridXY; }}
+namespace DD4hep { namespace Geometry { typedef GridXY RegularNgonCartesianGridXY; }}
 DECLARE_XMLELEMENT(RegularNgonCartesianGridXY,create_CartesianGridXY);
 
 namespace DD4hep { namespace Geometry { 
     typedef GridXYZ CartesianGridXYZ;
-    typedef CartesianGridXY EcalBarrelCartesianGridXY;
+    typedef GridXY EcalBarrelCartesianGridXY;
 }}
 DECLARE_XMLELEMENT(CartesianGridXYZ,create_CartesianGridXY);
 DECLARE_XMLELEMENT(EcalBarrelCartesianGridXY,create_CartesianGridXY);
   
-static Ref_t create_ProjectiveCylinder(lcdd_t& /* lcdd */, xml_h e)  {
-  ProjectiveCylinder obj;
+static Ref_t create_ProjectiveCylinder(lcdd_t& lcdd, xml_h e)  {
+  ProjectiveCylinder obj(lcdd);
   if ( e.hasAttr(_U(phiBins))   ) obj.setPhiBins(e.attr<int>(_U(phiBins)));
   if ( e.hasAttr(_U(thetaBins)) ) obj.setThetaBins(e.attr<int>(_U(thetaBins)));
   return obj;
 }
 DECLARE_XMLELEMENT(ProjectiveCylinder,create_ProjectiveCylinder);
   
-static Ref_t create_NonProjectiveCylinder(lcdd_t& /* lcdd */, xml_h e)  {
-  NonProjectiveCylinder obj;
+static Ref_t create_NonProjectiveCylinder(lcdd_t& lcdd, xml_h e)  {
+  NonProjectiveCylinder obj(lcdd);
   if ( e.hasAttr(_U(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_U(gridSizePhi)));
   if ( e.hasAttr(_U(gridSizeZ))   ) obj.setPhiBinSize(e.attr<double>(_U(gridSizeZ)));
   return obj;
 }
 DECLARE_XMLELEMENT(NonProjectiveCylinder,create_NonProjectiveCylinder);
   
-static Ref_t create_ProjectiveZPlane(lcdd_t& /* lcdd */, xml_h e)  {
-  ProjectiveZPlane obj;
+static Ref_t create_ProjectiveZPlane(lcdd_t& lcdd, xml_h e)  {
+  ProjectiveZPlane obj(lcdd);
   if ( e.hasAttr(_U(phiBins))   ) obj.setThetaBins(e.attr<int>(_U(phiBins)));
   if ( e.hasAttr(_U(thetaBins)) ) obj.setPhiBins(e.attr<int>(_U(thetaBins)));
   return obj;
diff --git a/DDCore/src/plugins/Geant4XML.cpp b/DDCore/src/plugins/Geant4XML.cpp
index edacfff82..6ca96a01a 100644
--- a/DDCore/src/plugins/Geant4XML.cpp
+++ b/DDCore/src/plugins/Geant4XML.cpp
@@ -39,3 +39,9 @@ static long create_Geant4(lcdd_t& lcdd, const xml_h& element) {
   return 1;
 }
 DECLARE_XML_DOC_READER(geant4,create_Geant4);
+
+static Ref_t handle_Geant4(lcdd_t& lcdd, const xml_h& element) {
+  (Converter<Geant4>(lcdd))(element);
+  return Ref_t(0);
+}
+DECLARE_XMLELEMENT(geant4_xml_setup,handle_Geant4);
-- 
GitLab