diff --git a/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
index 0ee29506b815f7fde51c3441334a42d8cd0d1678..f523514946a5126ca140f446dea6033d2b7c18ee 100644
--- a/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
+++ b/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
@@ -38,7 +38,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
 	double     router = r + x_slice.thickness();
 	Material   slice_mat  = lcdd.material(x_slice.materialStr());
 	string     slice_name = layer_name + _toString(m,"slice%d");
-	Tube       slice_tube(r,router,z * 2);
+	Tube       slice_tube(r,router,z*2);
 	Volume     slice_vol (slice_name,slice_tube,slice_mat);
           
 	if ( x_slice.isSensitive() ) slice_vol.setSensitiveDetector(sens);
@@ -48,14 +48,14 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
 	layer_vol.placeVolume(slice_vol,IdentityPos());
       }
       layer_vol.setVisAttributes(lcdd,x_layer.visStr());
-      layer_tub.setDimensions(rlayer,r,z * 2);
+      layer_tub.setDimensions(rlayer,r,z*2,0,2*M_PI);
         
       PlacedVolume layer_physvol = envelopeVol.placeVolume(layer_vol,IdentityPos());
       layer_physvol.addPhysVolID(_A(layer),n);
       ++n;
     }
   }
-  envelope.setDimensions(rmin,r,2.*z);
+  envelope.setDimensions(rmin,r,2*z,0,2*M_PI);
   // Set region of slice
   envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
     
diff --git a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
index 9282af5095cc36babbe1e31aaa6c09cd45869305..86661b81bf37c7e1dfba5cea0a08d079dce607e8 100644
--- a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
+++ b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
@@ -60,7 +60,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
       ++n;
     }
   }
-  envelope.setDimensions(rmin,rmax,totWidth,2.*M_PI);
+  envelope.setDimensions(rmin,rmax,totWidth,0,2*M_PI);
   // Set attributes of slice
   envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
 
diff --git a/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp b/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
index 1cd4ce24e1a80fbcaf817f2037628a61f59dbdca..64e5979fafd5459315f29fa108b52706cba7184b 100644
--- a/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
+++ b/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
@@ -48,7 +48,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
       // Slices have no extra id. Take the ID of the layer!
       spv.addPhysVolID(_X(layer),n);
     }
-    l_tub.setDimensions(rmin,r,z,2*M_PI);
+    l_tub.setDimensions(rmin,r,z,0,2*M_PI);
     cout << l_name << " " << rmin << " " << r << " " << z << endl;
     l_vol.setVisAttributes(lcdd,x_layer.visStr());
       
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
index 905b5db5c7427a8b2ae93decf9d356ec04ae171f..a97a54aab71eddce37bb3529ff013549540ed68d 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
@@ -18,8 +18,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   xml_comp_t  x_layer= e.child(_X(layer));
   string      name   = x_det.nameStr();
   Material    air    = lcdd.air();
-  DetElement  lcal(name,x_det.id());
-  Volume      mother = lcdd.pickMotherVolume(lcal);
+  DetElement  side("pos",x_det.id());
 
   // LumiCal dimensions
   int         n_layers        = x_layer.attr<int>(_A(nmodules));
@@ -83,7 +82,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   Tube        cell_tube(cal_innerradius,(cal_innerradius+thetastrip_dr), cell_thick);//, phistrip_dphi);
   Volume      cell_vol (name+"_cell",cell_tube,cell_mat);
   cell_vol.setVisAttributes(cell_vis);
- 
+  cell_vol.setSensitiveDetector(sens);
+
   //  here PHI silicon sector
   Tube        sector_tube(cal_innerradius,cal_outerradius,cell_thick);//,phistrip_dphi);
   Volume      sector_vol(name+"_sector",sector_tube,cell_mat);
@@ -97,6 +97,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   // Replicate strips within a theta and phi plane padded version
   Volume sens_theta_vol = Ref_t(sector_tube->Divide(sector_vol, (name+"_sector_theta").c_str(), 1, ncell_theta, 0., thetastrip_dr));
   sens_theta_vol.setVisAttributes(cell_vis);
+  
   Volume sens_phi_vol = Ref_t(sensor_tube->Divide(sensor_vol, (name+"_sensor_phi").c_str(), 2, ncell_phi, 0., phistrip_dphi*RAD_2_DEGREE));
   sens_phi_vol.setVisAttributes(cell_vis);
 
@@ -116,17 +117,35 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
 
   // position of first layer
   double lay_z = -cal_hz + layer_hz;
+
   // Put the layers into the LumiCal sub-module
+  PlacedVolume pv;
   for (int nLay = 1; nLay < n_layers+1; nLay++)  {
-    env_vol.placeVolume(lay_vol,Position(0,0,lay_z));
+    DetElement layer_det(side,_toString(nLay,"layer%d"),nLay);
+    pv = env_vol.placeVolume(lay_vol,Position(0,0,lay_z));
+    layer_det.setPlacement(pv);
     lay_z += (layer_hz*2.0+layer_gap);
   }
   // Place two LumiCal sub-modules into the world
   double z_center = z_begin+cal_hz;
+
   //Debug: one side centered only: mother.placeVolume(env_vol,Position(0,0,0),Rotation(0,bx_angle,0));
-  mother.placeVolume(env_vol,Position(0,0,z_center).rotateY(bx_angle),Rotation(0,bx_angle,0));
-  mother.placeVolume(env_vol,Position(0,0,z_center).rotateY(M_PI-bx_angle),Rotation(0,M_PI-bx_angle,0));
+  DetElement  lcal(name,x_det.id());
+  Volume      mother = lcdd.pickMotherVolume(lcal);
+  Assembly    assembly(name);
+
+  pv = assembly.placeVolume(env_vol,Position(0,0,z_center).rotateY(bx_angle),Rotation(0,bx_angle,0));
+  side.setPlacement(pv);
+  lcal.add(side);
+
+  DetElement other_side = side.clone("neg",-x_det.id());
+  pv = assembly.placeVolume(env_vol,Position(0,0,z_center).rotateY(M_PI-bx_angle),Rotation(0,M_PI-bx_angle,0));
+  other_side.setPlacement(pv);
+  lcal.add(other_side);
 
+  assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+  pv = mother.placeVolume(assembly);
+  lcal.setPlacement(pv);
   return lcal;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
index 2037f94eb1347914af817135f720b1995d90ef7c..fe912f8e3d8a1470fe27851a860bda2ad4947004 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
@@ -9,35 +9,12 @@
 #include "DD4hep/DetFactoryHelper.h"
 #include "TGeoBBox.h"
 
-using namespace std;
-using namespace DD4hep;
-using namespace DD4hep::Geometry;
-
-namespace {
-  struct ECAL : public DetElement {
+namespace DD4hep { namespace Geometry {
+  struct SEcal03Data : public DetElement::Object  {
     typedef Position Dimension;
-    enum { ECALBARREL };
-    LCDD&              lcdd;
-    SensitiveDetector& sens_det;
-
-    xml_det_t  x_det;
-    xml_comp_t x_barrel;
-    xml_comp_t x_endcap;
-    xml_comp_t x_support;
-    xml_comp_t x_front;
-
-    xml_comp_t x_shield;
-    struct XMLSlab : public xml_comp_t {
-      xml_comp_t shield;
-      xml_comp_t copper;
-      xml_comp_t sensitive;
-      xml_comp_t ground;
-      xml_comp_t glue;
-      XMLSlab() : xml_comp_t(0), shield(0), copper(0), sensitive(0), ground(0), glue(0) {}
-      XMLSlab& operator=(const xml_h& e) { this->Element::operator=(e); return *this; }
-    } m_xml_slab;
-
-    struct Slab_t {
+    enum { ECALBARREL=1, ECALENDCAPPLUS=2, ECALENDCAPMINUS=3 };
+    enum { SIDE_PLUS=0, SIDE_MINUS=1 };
+    struct Slab  {
       double     h_fiber_thickness;
       double     shield_thickness;
       VisAttr    vis;
@@ -56,12 +33,12 @@ namespace {
 
       double     glue_thickness;
       double     total_thickness;
-      Slab_t() : h_fiber_thickness(0), shield_thickness(0), ground_thickness(0),
-		 sensitive_thickness(0), copper_thickness(0), glue_thickness(0),
-		 total_thickness(0) {}
+      Slab() : h_fiber_thickness(0), shield_thickness(0), ground_thickness(0),
+	       sensitive_thickness(0), copper_thickness(0), glue_thickness(0),
+	       total_thickness(0) {}
     } m_slab;
 
-    struct Layer {
+    struct Layer   {
       int      nLayer;
       double   thickness;
       Material rad_mat;
@@ -70,7 +47,7 @@ namespace {
 
     Volume    m_center_tube;
     Position  m_alveolus;
-    struct Barrel_t : public Dimension   {
+    struct Barrel : public DetElement  {
       typedef std::vector<Layer*> Layers;
       
       int      numTowers;
@@ -78,186 +55,193 @@ namespace {
       double   top;
       double   thickness;
       double   inner_r;
+      double   dim_z;
       Material radiatorMaterial;
+      Material material;
+      VisAttr  vis;
       Layers   layers;
-      Volume   stave;
       int      numStaves, numModules;
-      PlacedVolume module[9][6];
+      DetElement module[9][6];
+      SensitiveDetector sensDet;
+      /// Helper function to allow assignment
+      DetElement& operator=(const DetElement& d)  { return this->DetElement::operator=(d); }
     } m_barrel;
 
-    struct Endcap_t {
+    struct Endcap : public DetElement  {
       typedef std::vector<Layer*> Layers;
       
       double rmin;
       double rmax;
-      double z;
+      double dim_z;
       double thickness;
-      Volume sideA;
-      Volume sideB;
-      PlacedVolume pvSideA;
-      PlacedVolume pvSideB;
+      VisAttr      vis;
       Layers layers;
+      SensitiveDetector sensDet;
+      SensitiveDetector ringSD;
+      DetElement side[2];
+      /// Helper function to allow assignment
+      DetElement& operator=(const DetElement& d)  { return this->DetElement::operator=(d); }
     } m_endcap;
 
+    struct Shield {
+      Material material;
+      VisAttr  vis;
+      double   thickness;
+    } m_shield;
     int       m_numLayer;
+    double    m_front_thickness;
     double    m_lateral_face_thickness;
     double    m_fiber_thickness;
+    double    m_support_thickness;
     double    m_guard_ring_size;
     double    m_cell_size;
     double    m_cables_gap;
     double    m_endcap_center_box_size;
     double    m_centerTubDisplacement;
     VisAttr   m_radiatorVis;
+    LimitSet  m_limits;
+
+    std::vector<Volume>    EC_TowerSlabs;
+    std::vector<Volume>    EC_Towers[3];
+    std::vector<Position>  EC_TowerXYCenters;
+    LCDD*       lcdd;
+    std::string name;
+    DetElement  self;
+  };
 
-    vector<Volume>    EC_TowerSlabs;
-    vector<Volume>    EC_Towers[3];
-    vector<Position>  EC_TowerXYCenters;
-
+  struct SEcal03 : public SEcal03Data  {
     /// Standard constructor
-    ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s);
-
+    SEcal03() : SEcal03Data() {}
+    /// Detector construction function
+    DetElement construct(LCDD& lcdd, xml_det_t e);
     /// Simple access to the radiator thickness depending on the layer
     double radiatorThickness(int layer_id)   const;
-
     /// Build Endcap Standard Module 
-    Volume buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot);
-
+    Volume buildEndcap(DetElement det,bool Zminus, const Endcap& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot);
     /// Build barrel volume
-    Volume buildBarrelStave(const Barrel_t& barrel);
-
+    std::pair<DetElement,Volume> buildBarrelStave(const Barrel& barrel);
     /// Build slab 
-    Volume buildSlab(bool barrel, const Dimension dim);
-
+    Volume buildSlab(bool barrel, const Dimension dim, SensitiveDetector& sd);
     // Build radiator solid
-    Volume buildRadiator(const string& name, const Dimension& dim, const Material& mat);
+    Volume buildRadiator(const std::string& name, const Dimension& dim, const Material& mat);
   };
-}
+}}
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
 
 #define N_FIBERS_ALVOULUS 3
 #define N_FIBERS_W_STRUCTURE 2
-
-ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
-  : DetElement(e.nameStr(), e.id()), lcdd(l), x_det(e), x_barrel(0), 
-    x_endcap(0), x_support(0), x_front(0), x_shield(0), sens_det(s)
-{
-  // EC_Initialize() builds the Slabs and the radiator plates for the several towers 
-  // to be placed latter into each module
-  string det_nam = name();
-  Volume motherVol = lcdd.pickMotherVolume(*this);
-  /*
-    <detector id="<id>" name="<name>" type="<type>"
-      inner_r="TPC_outer_radius+Ecal_Tpc_gap"
-      lateral_face_thickness="Ecal_lateral_face_thickness"
-      fiber_thickness="Ecal_fiber_thickness"
-      guard_ring_size="Ecal_guard_ring_size"
-      cell_size="Ecal_cell_size"
-      alveolus_gap="Ecal_Alveolus_Air_Gap"
-    >
-    <support   thickness="Ecal_support_thickness"/>
-    <front     thickness="Ecal_front_face_thickness"/>
-    <pcbshield thickness="Ecal_Slab_PCB_thickness + Ecal_Slab_copper_thickness + Ecal_Slab_shielding"/>
-
-    <layer id="1" repeat="Ecal_nlayers1" thickness="Ecal_radiator_thickness1" material="Ecal_radiator_material"/>
-    <layer id="2" repeat="Ecal_nlayers2" thickness="Ecal_radiator_thickness2" material="Ecal_radiator_material"/>
-    <layer id="3" repeat="Ecal_nlayers3" thickness="Ecal_radiator_thickness3" material="Ecal_radiator_material"/>
-    <slab h_fiber_thickness="Ecal_H_fiber_thickness" sensitive="Ecal_sensitive_material">
-      <shielding thickness="Ecal_Slab_shielding"/>
-      <copper    thickness="Ecal_Slab_copper_thickness"/>
-      <ground>   thickness="Ecal_Slab_ground_thickness"/>
-      <glue      thickness="Ecal_Slab_glue_gap"/>
-      <sensitive thickness="Ecal_Si_thickness"/>
-    </slab>
-    <barrel zhalf="Ecal_Barrel_halfZ" towers="Ecal_barrel_number_of_towers"/>
-    <endcap extra_size="Ecal_endcap_extra_size" center_box_size="Ecal_endcap_center_box_size"/>
-    </detector>
-  */
-  x_support      = x_det.child(Unicode("support"));
-  x_barrel       = x_det.child(_X(barrel));
-  x_endcap       = x_det.child(_X(endcap));
-  x_front        = x_det.child(Unicode("front"));
-  x_shield       = x_det.child(Unicode("pcbshield"));
-
-  m_xml_slab           = x_det.child(Unicode("slab"));
-  m_xml_slab.shield    = m_xml_slab.child(Unicode("shielding"));
-  m_xml_slab.copper    = m_xml_slab.child(Unicode("copper"));
-  m_xml_slab.sensitive = m_xml_slab.child(Unicode("sensitive"));
-  m_xml_slab.ground    = m_xml_slab.child(Unicode("ground"));
-  m_xml_slab.glue      = m_xml_slab.child(Unicode("glue"));
-
-  double endcap_extra_size       = x_endcap.attr<double>(Unicode("extra_size"));
-  double crossing_angle          = x_det.attr<double>(Unicode("crossing_angle"));
-  m_cables_gap                   = x_det.attr<double>(Unicode("cables_gap"));
-  m_lateral_face_thickness       = x_det.attr<double>(Unicode("lateral_face_thickness"));
-  m_fiber_thickness              = x_det.attr<double>(Unicode("fiber_thickness"));
-  m_cell_size                    = x_det.attr<double>(Unicode("cell_size"));
-  m_guard_ring_size              = x_det.attr<double>(Unicode("guard_ring_size"));
-
-  m_slab.vis                     = lcdd.visAttributes("EcalSlabVis");
-  m_slab.h_fiber_thickness       = m_xml_slab.attr<double>(Unicode("h_fiber_thickness"));
-  m_slab.shield_thickness        = m_xml_slab.shield.thickness();
-  m_slab.ground_thickness        = m_xml_slab.ground.thickness();
-  m_slab.ground_mat              = lcdd.material(m_xml_slab.ground.materialStr());
-  m_slab.ground_vis              = lcdd.visAttributes("EcalSlabGroundVis");
-  m_slab.sensitive_thickness     = m_xml_slab.sensitive.thickness();
-  m_slab.sensitive_mat           = lcdd.material(m_xml_slab.sensitive.materialStr());
-  m_slab.sensitive_vis           = lcdd.visAttributes("EcalSlabSensitiveVis");
-  m_slab.copper_thickness        = m_xml_slab.copper.thickness();
-  m_slab.copper_mat              = lcdd.material(m_xml_slab.copper.materialStr());
-  m_slab.glue_thickness          = m_xml_slab.glue.thickness();
-  m_slab.wafer_vis               = lcdd.visAttributes("EcalWaferVis");
-  m_radiatorVis                  = lcdd.visAttributes("EcalRadiatorVis");
+#define _U(text)  Unicode(#text)
+
+
+/// Detector construction function
+DetElement SEcal03::construct(LCDD& l, xml_det_t x_det)  {
+  lcdd     = &l;
+  name     = x_det.nameStr();
+  self.assign(dynamic_cast<Value<TNamed,SEcal03>*>(this),name,x_det.typeStr());
+  self._data().id = x_det.id();
+  xml_comp_t x_param             = x_det.child(_U(param));
+  xml_comp_t x_barrel            = x_det.child(_X(barrel));
+  xml_comp_t x_endcap            = x_det.child(_X(endcap));
+  xml_comp_t x_shield            = x_det.child(_U(pcbshield));
+  xml_comp_t m_xml_slab          = x_det.child(_U(slab));
+  xml_comp_t m_xml_slab_shield   = m_xml_slab.child(_U(shielding));
+  xml_comp_t m_xml_slab_copper   = m_xml_slab.child(_U(copper));
+  xml_comp_t m_xml_slab_sensitive= m_xml_slab.child(_U(sensitive));
+  xml_comp_t m_xml_slab_ground   = m_xml_slab.child(_U(ground));
+  xml_comp_t m_xml_slab_glue     = m_xml_slab.child(_U(glue));
+
+  double endcap_extra_size       = x_endcap.attr<double>(_U(extra_size));
+  double crossing_angle          = x_param.attr<double>(_U(crossing_angle));
+  Assembly  assembly(name+"_assembly");
+  // Hosting volume
+  Volume motherVol               = lcdd->pickMotherVolume(self);
+  // User limits for this sub detector
+  m_limits                       = lcdd->limitSet(x_det.limitsStr());
+
+  m_cables_gap                   = x_param.attr<double>(_U(cables_gap));
+  m_lateral_face_thickness       = x_param.attr<double>(_U(lateral_face_thickness));
+  m_fiber_thickness              = x_param.attr<double>(_U(fiber_thickness));
+  m_cell_size                    = x_param.attr<double>(_U(cell_size));
+  m_guard_ring_size              = x_param.attr<double>(_U(guard_ring_size));
+  m_front_thickness              = x_param.attr<double>(_U(front_face_thickness));
+  m_support_thickness            = x_param.attr<double>(_U(support_thickness));
+
+  m_shield.vis                   = lcdd->visAttributes(x_shield.visStr());
+  m_shield.material              = lcdd->material(x_shield.materialStr());
+  m_shield.thickness             = x_shield.thickness();
+
+  m_slab.vis                     = lcdd->visAttributes("EcalSlabVis");
+  m_slab.h_fiber_thickness       = m_xml_slab.attr<double>(_U(h_fiber_thickness));
+  m_slab.shield_thickness        = m_xml_slab_shield.thickness();
+  m_slab.ground_thickness        = m_xml_slab_ground.thickness();
+  m_slab.ground_mat              = lcdd->material(m_xml_slab_ground.materialStr());
+  m_slab.ground_vis              = lcdd->visAttributes("EcalSlabGroundVis");
+  m_slab.sensitive_thickness     = m_xml_slab_sensitive.thickness();
+  m_slab.sensitive_mat           = lcdd->material(m_xml_slab_sensitive.materialStr());
+  m_slab.sensitive_vis           = lcdd->visAttributes("EcalSlabSensitiveVis");
+  m_slab.copper_thickness        = m_xml_slab_copper.thickness();
+  m_slab.copper_mat              = lcdd->material(m_xml_slab_copper.materialStr());
+  m_slab.glue_thickness          = m_xml_slab_glue.thickness();
+  m_slab.wafer_vis               = lcdd->visAttributes("EcalWaferVis");
+  m_radiatorVis                  = lcdd->visAttributes("EcalRadiatorVis");
 
   size_t i=0;
   for(xml_coll_t c(x_det,_X(layer)); c; ++c, ++i) {
     xml_comp_t layer(c);
     m_layers[i].nLayer    = layer.repeat();
     m_layers[i].thickness = layer.thickness();
-    m_layers[i].rad_mat   = lcdd.material(layer.materialStr());
+    m_layers[i].rad_mat   = lcdd->material(layer.materialStr());
     m_barrel.layers.push_back(&m_layers[i]);
     m_endcap.layers.push_back(&m_layers[i]);
   }
   m_numLayer = m_layers[0].nLayer + m_layers[1].nLayer + m_layers[2].nLayer;
   m_slab.total_thickness  =   m_slab.shield_thickness +    m_slab.copper_thickness + 
-    x_shield.thickness()    + m_slab.sensitive_thickness + m_slab.glue_thickness +
-    m_slab.ground_thickness + x_det.attr<double>(Unicode("alveolus_gap")) / 2;
+    m_shield.thickness      + m_slab.sensitive_thickness + m_slab.glue_thickness +
+    m_slab.ground_thickness + x_param.attr<double>(_U(alveolus_gap)) / 2;
   double total_thickness =
     m_layers[0].nLayer * m_layers[0].thickness +
     m_layers[1].nLayer * m_layers[1].thickness +
     m_layers[2].nLayer * m_layers[2].thickness +
     int(m_numLayer/2) * (N_FIBERS_W_STRUCTURE * 2 *  m_fiber_thickness) + // fiber around W struct layers
     (m_numLayer + 1) * (m_slab.total_thickness + (N_FIBERS_ALVOULUS + 1 ) * m_fiber_thickness) + // slabs plus fiber around and inside
-    x_support.thickness() + x_front.thickness();
-  
-  m_barrel.numTowers        = x_barrel.attr<int>(Unicode("towers"));
+    m_support_thickness + m_front_thickness;
+
+  m_barrel.numTowers        = x_barrel.attr<int>(_U(towers));
   m_barrel.thickness        = total_thickness;
   m_barrel.inner_r          = x_barrel.inner_r();
-  m_barrel.z                = 2 * x_barrel.zhalf() / 5.;
+  m_barrel.dim_z            = 2 * x_barrel.zhalf() / 5.;
   m_barrel.bottom           = 2. * std::tan(M_PI/8.) * m_barrel.inner_r + 2.* std::tan(M_PI/8.) * m_barrel.thickness;
   m_barrel.top              = 2. * std::tan(M_PI/8.) * m_barrel.inner_r; //m_barrel.bottom -  2.0 * m_barrel.thickness;
-  m_barrel.radiatorMaterial = lcdd.material(x_barrel.attr<string>(Unicode("radiatorMaterial")));
+  m_barrel.vis              = lcdd->visAttributes(x_barrel.visStr());
+  m_barrel.material         = lcdd->material(x_barrel.materialStr());
+  m_barrel.radiatorMaterial = lcdd->material(x_barrel.attr<string>(_U(radiatorMaterial)));
 
-  double module_z_offset    = m_barrel.z*2.5 + m_cables_gap + m_barrel.thickness/2.;
+  double module_z_offset    = m_barrel.dim_z*2.5 + m_cables_gap + m_barrel.thickness/2.;
+  m_endcap.vis              = lcdd->visAttributes(x_endcap.visStr());
   m_endcap.thickness        = total_thickness;
   m_endcap.rmin             = x_barrel.inner_r();
   m_endcap.rmax             = x_barrel.inner_r() + m_endcap.thickness + endcap_extra_size;
-  m_endcap.z                = module_z_offset;
+  m_endcap.dim_z            = module_z_offset;
 
-  m_alveolus.z = (m_barrel.z - 2. * m_lateral_face_thickness) / m_barrel.numTowers - 
+  m_alveolus.z = (m_barrel.dim_z - 2. * m_lateral_face_thickness) / m_barrel.numTowers - 
     2 * N_FIBERS_ALVOULUS  * m_fiber_thickness  - 
     2 * m_slab.h_fiber_thickness -
     2 * m_slab.shield_thickness;
 
-  double siPlateSize = x_endcap.attr<double>(Unicode("center_box_size")) -
+  double siPlateSize = x_endcap.attr<double>(_U(center_box_size)) -
     2.0 * m_lateral_face_thickness -
-    2.0 * x_endcap.attr<double>(Unicode("ring_gap"));
+    2.0 * x_endcap.attr<double>(_U(ring_gap));
 
-  m_centerTubDisplacement = m_endcap.z * std::tan(crossing_angle/2000);
-  m_center_tube   = Tube(m_endcap.rmin,m_endcap.rmin,0.);
-  Box              ec_ringSiBox   (siPlateSize/2.,siPlateSize/2.,m_slab.sensitive_thickness/2.);
+  m_centerTubDisplacement = m_endcap.dim_z * std::tan(crossing_angle/2000);
+  m_center_tube   = Tube(0,m_endcap.rmin,total_thickness);
+  Box              ec_ringSiBox   (siPlateSize/2,siPlateSize/2,m_slab.sensitive_thickness/2);
   SubtractionSolid ec_ringSiSolid1(ec_ringSiBox,m_center_tube,Position(m_centerTubDisplacement,0,0),Rotation());
-  Volume           ec_ringSiVol1  (det_nam+"_ec_ring_volPlus",ec_ringSiSolid1,m_slab.sensitive_mat);
+  Volume           ec_ringSiVol1  ("ring_plus",ec_ringSiSolid1,m_slab.sensitive_mat);
   SubtractionSolid ec_ringSiSolid2(ec_ringSiBox,m_center_tube,Position(-m_centerTubDisplacement,0,0),Rotation());
-  Volume           ec_ringSiVol2  (det_nam+"_ec_ring_volNeg",ec_ringSiSolid2,m_slab.sensitive_mat);
+  Volume           ec_ringSiVol2  ("ring_minus",ec_ringSiSolid2,m_slab.sensitive_mat);
 
   //=================================================
   //
@@ -291,13 +275,13 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
     // While the towers have the same shape use the same logical volumes and parameters.
     if(last_dim_x != m_alveolus.x)      {
       //printf("%s> Build slab x=%f y=%f\n",name().c_str(),m_alveolus.x,m_alveolus.y);
-      EC_TowerSlabs.push_back(buildSlab(false,Dimension(m_alveolus.y,m_slab.total_thickness,m_alveolus.x)));
+      EC_TowerSlabs.push_back(buildSlab(false,Dimension(m_alveolus.y,m_slab.total_thickness,m_alveolus.x),m_endcap.sensDet));
       if( m_layers[0].nLayer > 0 )
-	EC_Towers[0].push_back(buildRadiator(det_nam+"_T1",Dimension(m_alveolus.y,m_layers[0].thickness,m_alveolus.x),m_layers[0].rad_mat));
+	EC_Towers[0].push_back(buildRadiator(name+"_T1",Dimension(m_alveolus.y,m_layers[0].thickness,m_alveolus.x),m_layers[0].rad_mat));
       if( m_layers[1].nLayer > 0 )
-	EC_Towers[1].push_back(buildRadiator(det_nam+"_T2",Dimension(m_alveolus.y,m_layers[1].thickness,m_alveolus.x),m_layers[1].rad_mat));
+	EC_Towers[1].push_back(buildRadiator(name+"_T2",Dimension(m_alveolus.y,m_layers[1].thickness,m_alveolus.x),m_layers[1].rad_mat));
       if( m_layers[2].nLayer > 0 )
-	EC_Towers[2].push_back(buildRadiator(det_nam+"_T3",Dimension(m_alveolus.y,m_layers[2].thickness,m_alveolus.x),m_layers[2].rad_mat));
+	EC_Towers[2].push_back(buildRadiator(name+"_T3",Dimension(m_alveolus.y,m_layers[2].thickness,m_alveolus.x),m_layers[2].rad_mat));
       last_dim_x = m_alveolus.x;
     }
     else   {
@@ -309,12 +293,50 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
     EC_TowerXYCenters.push_back(Position(-(y_curr + m_alveolus.y/2.),-(-m_alveolus.x/2. + x_right),0));
   }
 
-  m_endcap.sideA   = buildEndcap(false,m_endcap,ec_ringSiSolid1,ec_ringSiVol1,Rotation());
-  m_endcap.pvSideA = motherVol.placeVolume(m_endcap.sideA,Position(0,0,module_z_offset));
-  m_endcap.sideB   = buildEndcap(true,m_endcap,ec_ringSiSolid2,ec_ringSiVol2,Rotation());
-  m_endcap.pvSideA = motherVol.placeVolume(m_endcap.sideB,Position(0,0,-module_z_offset),Rotation(M_PI,0,0));
-
-  m_barrel.stave = buildBarrelStave(m_barrel);  
+  // Setup the sensitive detectors for barrel, endcap+ and endcap-
+  SensitiveDetector sd = m_barrel.sensDet = SensitiveDetector("EcalBarrel");
+  Readout ro = lcdd->readout(x_barrel.readoutStr());
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+
+  sd = m_endcap.sensDet = SensitiveDetector("EcalEndcapRings");
+  ro = lcdd->readout(x_endcap.attr<string>(_U(ring_readout)));
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+
+  sd = m_endcap.ringSD = SensitiveDetector("EcalEndcap");
+  ro = lcdd->readout(x_endcap.readoutStr());
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+
+  ec_ringSiVol1.setSensitiveDetector(m_endcap.ringSD);
+  ec_ringSiVol2.setSensitiveDetector(m_endcap.ringSD);
+  ec_ringSiVol1.setVisAttributes(m_endcap.vis);
+  ec_ringSiVol2.setVisAttributes(m_endcap.vis);
+  ec_ringSiVol1.setLimitSet(m_limits);
+  ec_ringSiVol2.setLimitSet(m_limits);
+
+  Volume vol;
+  PlacedVolume pv;
+  DetElement det;
+  m_barrel = DetElement(self,"barrel",ECALBARREL);
+  m_endcap = DetElement(self,"endcaps",0);
+  det = DetElement(m_endcap,"plus",ECALENDCAPPLUS);
+  vol = buildEndcap(det,false,m_endcap,ec_ringSiSolid1,ec_ringSiVol1,Rotation());
+  pv  = assembly.placeVolume(vol,Position(0,0,module_z_offset));
+  det.setPlacement(pv);
+  m_endcap.side[SIDE_PLUS] = det;
+
+  det = DetElement(m_endcap,"minus",ECALENDCAPMINUS);
+  vol = buildEndcap(det,true,m_endcap,ec_ringSiSolid2,ec_ringSiVol2,Rotation());
+  pv  = assembly.placeVolume(vol,Position(0,0,-module_z_offset),Rotation(M_PI,0,0));
+  det.setPlacement(pv);
+  m_endcap.side[SIDE_MINUS] = det;
+
+  std::pair<DetElement,Volume> stave = buildBarrelStave(m_barrel);  
   // BarrelStandardModule placements
   double X = 0;//m_barrel.thickness * std::tan(M_PI/4.);
   double Y = m_barrel.inner_r + m_barrel.thickness/2;
@@ -322,25 +344,49 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
   ::memset(&m_barrel.module[0][0],0,sizeof(m_barrel.module));
   m_barrel.numStaves = 8;
   m_barrel.numModules = 5;
-  for(int stav_id=1; stav_id < 9; ++stav_id) {
+
+  DetElement mod_det;
+  for(int stav_id=1; stav_id < 9; ++stav_id)   {
+    int stave_ident = ECALBARREL*100+stav_id;
+    DetElement stave_det(m_barrel,_toString(stav_id,"stave%d"),stave_ident);
+    Assembly staveVol(_toString(stav_id,"stave%d"));
     for(int mod_id=1; mod_id < 6; ++mod_id)   {
       double phi = (stav_id-1) * M_PI/4.;
-      double z_offset =  (2.*mod_id-6.)*m_barrel.z/2.;
+      double z_offset =  (2.*mod_id-6.)*m_barrel.dim_z/2.;
       Rotation rot(M_PI/2,phi,0);
       Position pos(X,Y,z_offset);
-      PlacedVolume pv = motherVol.placeVolume(m_barrel.stave,pos.rotateZ(phi),rot);
+      int mod_ident = stave_ident+mod_id;
+      pv = staveVol.placeVolume(stave.second,pos.rotateZ(phi),rot);
       pv.addPhysVolID("barrel",ECALBARREL*100+stav_id*10+mod_id);
-      m_barrel.module[stav_id-1][mod_id-1] = pv;
+      if ( !mod_det.isValid() ) { // same as if(first) ...
+	stave.first->SetName(_toString(mod_id,"module%d").c_str());
+	stave.first._data().id = mod_ident;
+	mod_det = stave.first;
+      }
+      else  {
+	mod_det = stave.first.clone(_toString(mod_id,"module%d"),mod_ident);
+      }
+      stave_det.add(mod_det);
+      mod_det.setPlacement(pv);
+      m_barrel.module[stav_id-1][mod_id-1] = mod_det;
       ::printf("Place Barrel stave:%d,%d Phi:%.4f Pos: %.2f %.2f %.2f \n",stav_id,mod_id,phi,
 	       pos.x,pos.y,pos.z);
       //theBarrelSD->SetStaveRotationMatrix(stav_id,phi);
       //theBarrelSD->SetModuleZOffset(mod_id,z_offset);
     }
+    pv = assembly.placeVolume(staveVol);
+    stave_det.setPlacement(pv);
   }
+  assembly.setVisAttributes(lcdd->visAttributes(x_det.visStr()));
+  pv = motherVol.placeVolume(assembly);
+  m_barrel.setPlacement(pv);
+  m_endcap.setPlacement(pv);
+  self.setPlacement(pv);
+  return self;
 }
 
 /// Simple access to the radiator thickness depending on the layer
-double ECAL::radiatorThickness(int layer_id)   const  {
+double SEcal03::radiatorThickness(int layer_id)   const  {
   if(layer_id <= m_layers[0].nLayer)
     return m_layers[0].thickness;
   else if(layer_id <= (m_layers[0].nLayer + m_layers[1].nLayer))
@@ -349,27 +395,25 @@ double ECAL::radiatorThickness(int layer_id)   const  {
 }
 
 // Build radiator solid
-Volume ECAL::buildRadiator(const string& name, const Dimension& dim, const Material& mat)   {
+Volume SEcal03::buildRadiator(const string& name, const Dimension& dim, const Material& mat)   {
   Box    box(dim.x/2,dim.z/2,dim.y/2);
   //::printf("%s> Radiator: %.2f %.2f %.2f\n",name.c_str(),dim.x/2,dim.z/2,dim.y/2);
-  Volume vol(name+"_radiator",box,mat);
+  Volume vol("radiator",box,mat);
   vol.setVisAttributes(m_radiatorVis);
   return vol;
 }
 
 /// Build slab 
-Volume ECAL::buildSlab(bool barrel, Dimension dim) {
-  string nam = name();
-
+Volume SEcal03::buildSlab(bool barrel, Dimension dim, SensitiveDetector& sd) {
   // Slab solid: hx, hz, hy
   Box slabBox(dim.x/2,dim.z/2,dim.y/2);
-  Volume slabVol(nam+"_slab",slabBox,lcdd.air());
+  Volume slabVol("slab",slabBox,lcdd->air());
   slabVol.setVisAttributes(m_slab.vis);
   double y_slab_floor  = -dim.y/2;
 
   // Ground plate
   Box    groundBox(dim.x/2,dim.z/2,m_slab.ground_thickness/2);
-  Volume groundVol(nam+"_ground",groundBox,m_slab.ground_mat);
+  Volume groundVol("ground",groundBox,m_slab.ground_mat);
   groundVol.setVisAttributes(m_slab.ground_vis);
   slabVol.placeVolume(groundVol,Position(0,0,y_slab_floor+m_slab.ground_thickness/2));
   y_slab_floor += m_slab.ground_thickness;
@@ -377,7 +421,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
   // Si layer
   // we place a big plane of Si and inside it the Si wafers, to simplify the gard ring placements
   Box     siBox(dim.x/2,dim.z/2,m_slab.sensitive_thickness/2);
-  Volume  siVol(nam+"_sensitive",siBox,m_slab.sensitive_mat);
+  Volume  siVol("sensitive",siBox,m_slab.sensitive_mat);
   siVol.setVisAttributes(m_slab.sensitive_vis);
   slabVol.placeVolume(siVol,Position(0,0,y_slab_floor + m_slab.sensitive_thickness/2));
 
@@ -400,13 +444,13 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
   double wafer_dim_z = N_cells_in_Z * cell_dim_z;
 
   Box     waferBox(wafer_dim_x/2, wafer_dim_z/2, m_slab.sensitive_thickness/2);
-  Volume  waferVol(nam+"_wafer",waferBox,m_slab.sensitive_mat);
+  Volume  waferVol("wafer",waferBox,m_slab.sensitive_mat);
   waferVol.setVisAttributes(m_slab.wafer_vis);
-  // waferVol.setLimits(pULimits);
-  // waferVol->SetSensitiveDetector(theSD);
+  waferVol.setSensitiveDetector(sd);
+  waferVol.setLimitSet(m_limits);
 
   //::printf("%s> ...slab dim: %.4f x %.4f x %.4f  Grnd:%.4f %.4f %.4f Sensitive:%.4f %.4f %.4f \n",
-  //  nam.c_str(), dim.x/2,dim.z/2,dim.y/2,dim.x/2,dim.z/2,m_slab.ground_thickness/2,
+  //  name.c_str(), dim.x/2,dim.z/2,dim.y/2,dim.x/2,dim.z/2,m_slab.ground_thickness/2,
   //  dim.x/2,dim.z/2,m_slab.sensitive_thickness/2);
 
   // As the same method builds both barrel and end cap
@@ -417,7 +461,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
     int    num_wafer_x       = int(floor(dim.x / real_wafer_size_x));
     double wafer_pos_x       = -dim.x/2 + m_guard_ring_size +	wafer_dim_x /2 ;
     // ::printf("%s> ...Building slab for barrel: wafer dim: %.4f x %.4f real:%.4f [%d] pos:%4.f\n",
-    //	     nam.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
+    //	     name.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
     for (int iwaf = 1; iwaf < num_wafer_x + 1; iwaf++)      {
       double wafer_pos_z = -dim.z/2 + m_guard_ring_size + wafer_dim_z /2;
       for (int n_wafer_z = 1;	       n_wafer_z < 3;	       n_wafer_z++)	    {
@@ -438,10 +482,10 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
       int N_cells_x_remaining =	int(floor((resting_dim_x - 2 * m_guard_ring_size)/cell_dim_x));
       wafer_dim_x = N_cells_x_remaining * cell_dim_x;
       Box    waf_box(wafer_dim_x/2, wafer_dim_z/2, m_slab.sensitive_thickness/2);
-      Volume waf_vol(nam+"_wafer_rest",waf_box,m_slab.sensitive_mat);
-      //waf_vol.setLimits(pULimits);
+      Volume waf_vol("wafer_rest",waf_box,m_slab.sensitive_mat);
       waf_vol.setVisAttributes(m_slab.wafer_vis);
-      //waf_vol->SetSensitiveDetector(theSD);
+      waf_vol.setSensitiveDetector(sd);
+      waf_vol.setLimitSet(m_limits);
 
       real_wafer_size_x  =  wafer_dim_x + 2 * m_guard_ring_size;
       wafer_pos_x        = -dim.x/2 + num_wafer_x * real_wafer_size_x + real_wafer_size_x/2;
@@ -458,7 +502,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
     double wafer_pos_x       = -dim.z/2 + m_guard_ring_size +	wafer_dim_z /2;
     int    num_wafer_x       =  int(floor(dim.z/real_wafer_size_x));      
     //::printf("%s> ...Building slab for endcap: wafer dim: %.4f x %.4f real:%.4f [%d] pos:%4.f\n",
-    //	       nam.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
+    //	       name.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
     for (int iwaf_x=1; iwaf_x < num_wafer_x + 1; iwaf_x++)	{
       double wafer_pos_z = -dim.x/2 + m_guard_ring_size + wafer_dim_x /2;
       for (int iwaf_z = 1; iwaf_z < 3; ++iwaf_z)    {
@@ -476,10 +520,10 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
       int N_cells_x_remaining = int(std::floor((resting_dim_x - 2 * m_guard_ring_size)/cell_dim_z));
       wafer_dim_x = N_cells_x_remaining * cell_dim_z;
       Box    waf_box(wafer_dim_z/2, wafer_dim_x/2, m_slab.sensitive_thickness/2);
-      Volume waf_vol(nam+"_wafer", waf_box, m_slab.sensitive_mat);
+      Volume waf_vol("wafer", waf_box, m_slab.sensitive_mat);
       waf_vol.setVisAttributes(m_slab.sensitive_vis);
-      //waf_vol.setLimits(pULimits);
-      //waf_vol->SetSensitiveDetector(theSD);
+      waf_vol.setSensitiveDetector(sd);
+      waf_vol.setLimitSet(m_limits);
       wafer_pos_x        = -dim.z/2 + num_wafer_x * real_wafer_size_x + (wafer_dim_x + 2 * m_guard_ring_size)/2;
       real_wafer_size_x  =  wafer_dim_x + 2 * m_guard_ring_size;
       double wafer_pos_z = -dim.x/2 + m_guard_ring_size + wafer_dim_z /2;
@@ -495,23 +539,23 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
   y_slab_floor += (m_slab.sensitive_thickness+m_slab.glue_thickness);
   // The PCB layer, the copper and the shielding are placed as a big G10 layer,
   // as the copper and the shielding ones are very tiny.
-  Box    pcbShieldBox(dim.x/2,dim.z/2,x_shield.thickness()/2);
-  Volume pcbShieldVol(nam+"_shield",pcbShieldBox,lcdd.material(x_shield.materialStr()));
-  pcbShieldVol.setVisAttributes(lcdd.visAttributes(x_shield.visStr()));
-  slabVol.placeVolume(pcbShieldVol,Position(0,0,y_slab_floor+x_shield.thickness()/2));
+  Box    pcbShieldBox(dim.x/2,dim.z/2,m_shield.thickness/2);
+  Volume pcbShieldVol("pcbshield",pcbShieldBox,m_shield.material);
+  pcbShieldVol.setVisAttributes(m_shield.vis);
+  slabVol.placeVolume(pcbShieldVol,Position(0,0,y_slab_floor+m_shield.thickness/2));
   return slabVol;
 }
 
 /// Build Endcap Standard Module 
-Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot)   {
-  // While waiting for more geometric details,
-  // build a simple Endcap using a fiber polyhedra
-  // and substract the center box
-  string  nam = name();
+Volume SEcal03::buildEndcap(DetElement det,bool Zminus, const Endcap& endcap, 
+			    const Solid& siSolid, const Volume& siVol, const Rotation& rot)
+{
+  // While waiting for more geometric details, build a simple Endcap using 
+  // a fiber polyhedra and substract the center box
   PolyhedraRegular hedra(8, 0, endcap.rmax, m_endcap.thickness);
   SubtractionSolid solid(hedra, m_center_tube, Position(), rot);
-  Volume           endcap_vol(nam+"_endcap", solid,lcdd.material(x_shield.materialStr()));
-  endcap_vol.setVisAttributes(lcdd.visAttributes(x_endcap.visStr()));
+  Volume           endcap_vol("endcap", solid,m_shield.material);
+  endcap_vol.setVisAttributes(m_endcap.vis);
 
   //----------------------------------------------------
   // Radiator plates in the EndCap structure also as polyhedra, 
@@ -523,39 +567,39 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
   double r_inner = m_lateral_face_thickness;
   double r_outer = endcap.rmax - m_lateral_face_thickness;
   double box_dim = (m_endcap_center_box_size - m_lateral_face_thickness)/ 2.;
-  VisAttr ring_vis = lcdd.visAttributes("EcalRingVis");
+  VisAttr ring_vis = lcdd->visAttributes("EcalRingVis");
 
   if(m_layers[0].nLayer > 0 )    {
     PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[0].thickness);
     SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
-    vol_radL1 = Volume(nam+"_ECL1_radiator",sol_rad, m_layers[0].rad_mat);
+    vol_radL1 = Volume("ECL1_radiator",sol_rad, m_layers[0].rad_mat);
     vol_radL1.setVisAttributes(m_radiatorVis);
     // plate for slab in ring
     Box              box_ring(box_dim,box_dim, m_layers[0].thickness/2);
     SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
-    vol_ringL1 = Volume(nam+"_ECL1_ring",sol_ring,m_layers[0].rad_mat);
+    vol_ringL1 = Volume(name+"_ECL1_ring",sol_ring,m_layers[0].rad_mat);
     vol_ringL1.setVisAttributes(ring_vis);
   }
   if(m_layers[1].nLayer > 0 )    {
     PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[1].thickness);
     SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
-    vol_radL2 = Volume(nam+"_ECL2_radiator",sol_rad, m_layers[0].rad_mat);
+    vol_radL2 = Volume("ECL2_radiator",sol_rad, m_layers[0].rad_mat);
     vol_radL2.setVisAttributes(m_radiatorVis);
     // plate for slab in ring
     Box              box_ring(box_dim,box_dim, m_layers[1].thickness/2);
     SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
-    vol_ringL2 = Volume(nam+"_ECL2_ring",sol_ring,m_layers[0].rad_mat);
+    vol_ringL2 = Volume(name+"_ECL2_ring",sol_ring,m_layers[0].rad_mat);
     vol_ringL2.setVisAttributes(ring_vis);
   }
   if(m_layers[2].nLayer > 0 )    {
     PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[2].thickness);
     SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
-    vol_radL3 = Volume(nam+"_ECL3_radiator",sol_rad, m_layers[0].rad_mat);
+    vol_radL3 = Volume("ECL3_radiator",sol_rad, m_layers[0].rad_mat);
     vol_radL3.setVisAttributes(m_radiatorVis);
     // plate for slab in ring
     Box box_ring(box_dim,box_dim, m_layers[2].thickness/2);
     SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
-    vol_ringL3 = Volume(nam+"_ECL3_ring",sol_ring,m_layers[2].rad_mat);
+    vol_ringL3 = Volume(name+"_ECL3_ring",sol_ring,m_layers[2].rad_mat);
     vol_ringL3.setVisAttributes(ring_vis);
   }
 
@@ -565,7 +609,7 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
 
   // We count the layers starting from IP and from 1, so odd layers should be 
   // inside slabs and even ones on the structure.
-  double z_floor = -m_endcap.thickness/2 + x_front.thickness() + N_FIBERS_ALVOULUS * m_fiber_thickness;
+  double z_floor = -m_endcap.thickness/2 + m_front_thickness + N_FIBERS_ALVOULUS * m_fiber_thickness;
   //
   // ATTENTION, TWO LAYERS PER LOOP AS THERE IS ONE INSIDE THE ALVEOLUS.
   //
@@ -578,9 +622,10 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
   PlacedVolume pv;
   //num_layers = 2;
   for(int layer_id = 1; layer_id <= num_layers; layer_id+=2)   {
+
     // place the tower layer for the four modules
     double rad_thickness = m_layers[0].thickness;
-    //::printf("%s> installing layer %d....\n",name(),layer_id);
+    //::printf("%s> installing layer %d....\n",name,layer_id);
     rad_thickness = radiatorThickness(layer_id);
     if(layer_id <= m_layers[0].nLayer) {
       vol_ring      = vol_ringL1;
@@ -684,22 +729,22 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
 }
 
 ///  Barrel Standard Module
-Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
-  string nam = name();
-  Trapezoid barrelTrd(barrel.bottom/2, barrel.top/2, barrel.z/2, barrel.z/2, barrel.thickness/2);
-  Volume    barrelVol(nam+"_barrel",barrelTrd,lcdd.material(x_barrel.materialStr()));
-  barrelVol.setVisAttributes(lcdd.visAttributes(x_barrel.visStr()));
+pair<DetElement,Volume> SEcal03::buildBarrelStave(const Barrel& barrel) {
+  DetElement staveDet("stave",0);
+  Trapezoid staveTrd(barrel.bottom/2, barrel.top/2, barrel.dim_z/2, barrel.dim_z/2, barrel.thickness/2);
+  Volume    staveVol("stave",staveTrd,m_barrel.material);
+  staveVol.setVisAttributes(m_barrel.vis);
 
   // We count the layers starting from IP and from 1, so odd layers should be inside slabs and
   // even ones on the structure.
   // The structure W layers are here big plans, as the gap between each W plate is too small 
   // to create problems. The even W layers are part of H structure placed inside the alveolus.
-  double y_floor = x_front.thickness() + N_FIBERS_ALVOULUS * m_fiber_thickness;
+  double y_floor = m_front_thickness + N_FIBERS_ALVOULUS * m_fiber_thickness;
   double z_pos;
   PlacedVolume pv;
   for(int layer_id = 1; layer_id < m_numLayer+1; layer_id+=2) {// ATTENTION, TWO LAYERS PER LOOP
-    // build and place the several Alveolus with 
-    // the slabs and the radiator layer inside.
+    DetElement layerDet(staveDet,_toString(layer_id,"layer%d"),layer_id);
+    // build and place the several Alveolus with the slabs and the radiator layer inside.
     double rad_thick = radiatorThickness(layer_id);
     double alveolus_dim_y = 2 * m_slab.total_thickness + rad_thick + 2 * m_fiber_thickness;
 
@@ -709,23 +754,22 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
     // To simplify we place each slab and the radiator layer directly into the fiber module.
     //
     // Build a slab:
-    Volume slabVol = buildSlab(true,Dimension(alveolus_dim_x,m_slab.total_thickness,m_alveolus.z));
+    Volume slabVol = buildSlab(true,Dimension(alveolus_dim_x,m_slab.total_thickness,m_alveolus.z),m_barrel.sensDet);
 
     // Place the Slab and radiator inside the H, here directly into the module fiber as the
     // H structure is also built in fiber.
-    double z_tower_center = -barrel.z /2 + m_lateral_face_thickness 
+    double z_tower_center = -barrel.dim_z /2 + m_lateral_face_thickness 
       + m_fiber_thickness * N_FIBERS_ALVOULUS + m_slab.shield_thickness
       + m_slab.h_fiber_thickness + m_alveolus.z /2;  
 
     Dimension radDim1(alveolus_dim_x,rad_thick,m_alveolus.z);
-    Volume radVol1 = buildRadiator(nam+"_barrel_radiator1",radDim1,barrel.radiatorMaterial);
+    Volume radVol1 = buildRadiator("radiator1",radDim1,barrel.radiatorMaterial);
     for (int itow = m_barrel.numTowers; itow > 0; --itow )    {
-      y_fl = y_floor;
+      y_fl  = y_floor;
       x_off = 0; // to be calculed
       y_off = y_fl - barrel.thickness/2 + m_slab.total_thickness/2;
-
       // Place First Slab
-      pv = barrelVol.placeVolume(slabVol,Position(x_off,z_tower_center,y_off),Rotation(M_PI,0,0));
+      pv = staveVol.placeVolume(slabVol,Position(x_off,z_tower_center,y_off),Rotation(M_PI,0,0));
       pv.addPhysVolID("tower",itow * 1000 + layer_id);
 #if 0
       if (itow == Ecal_barrel_number_of_towers)  {
@@ -739,13 +783,13 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
       
       // Radiator layer "inside" alveolus
       y_off  = -barrel.thickness/2 + y_fl + rad_thick/2.;
-      pv     =  barrelVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
+      pv     =  staveVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
       pv.addPhysVolID("tower",itow * 1000 + layer_id);
 
       y_fl  +=  rad_thick + m_fiber_thickness;
       y_off  = -barrel.thickness/2 + y_fl + m_slab.total_thickness/2;
       // Second Slab: starts from bottom to up
-      pv = barrelVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
+      pv = staveVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
       pv.addPhysVolID("tower",itow * 1000 + layer_id + 1);
 #if 0
       if (itow == Ecal_barrel_number_of_towers)  	{
@@ -769,20 +813,19 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
 
     // Build and place the structure radiator layer into the module
     double radiator_dim_x = barrel.bottom - 2*(y_floor+rad_thick)*std::tan(M_PI/8);
-    double radiator_dim_z = barrel.z - 2.*m_lateral_face_thickness - 2*N_FIBERS_W_STRUCTURE * m_fiber_thickness;
+    double radiator_dim_z = barrel.dim_z - 2.*m_lateral_face_thickness - 2*N_FIBERS_W_STRUCTURE * m_fiber_thickness;
     
     Dimension radDim2(radiator_dim_x,rad_thick,radiator_dim_z);
-    Volume radVol2 = buildRadiator(nam+"barrel_radiator2",radDim2,barrel.radiatorMaterial);
-    pv = barrelVol.placeVolume(radVol2,Position(0,0,-barrel.thickness/2+y_floor+rad_thick/2));
+    Volume radVol2 = buildRadiator("radiator2",radDim2,barrel.radiatorMaterial);
+    pv = staveVol.placeVolume(radVol2,Position(0,0,-barrel.thickness/2+y_floor+rad_thick/2));
 
     // update the y_floor
     y_floor += (rad_thick + (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE) * m_fiber_thickness);
   }
-  return barrelVol;
+  return make_pair(staveDet,staveVol);
 }
 
-static Ref_t create(LCDD& lcdd, const xml_h& elt, SensitiveDetector& sens)  {
-  ECAL ecal(lcdd,elt,sens);
-  return ecal;
+static Ref_t create_detector(LCDD& lcdd, const xml_h& element)  {
+  return (new Value<TNamed,SEcal03>())->construct(lcdd,element);
 }
-DECLARE_DETELEMENT(Tesla_SEcal03,create);
+DECLARE_SUBDETECTOR(Tesla_SEcal03,create_detector);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
index e6a30fb29be6ed6d7d5ee3800e3683303bbd6af6..b4057d80e9c64aecfbd0731ad93a24de3e957c39 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
@@ -85,7 +85,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   vxd.assign(vxd_data,name,x_det.typeStr());
   vxd_data->id = x_det.id();
 
-  Assembly    detector_vol(name+"_vol");
+  Assembly    assembly(name+"_vol");
   Volume motherVol = lcdd.pickMotherVolume(vxd);    
 
   
@@ -181,7 +181,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
 	double r   = layer.radius + (layer.isEven() ? thickness+layer.gap : -thickness);
 	double z   = ldd_len + end_electronics_zhalf + ldd_gap/2.;
 
-	layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,z), Rotation(PIby2,phi,0.));
+	layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi, z), Rotation(PIby2,phi,0.));
 	layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,-z),Rotation(PIby2,phi,0.));
       }
     }
@@ -243,7 +243,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
       pv = layer_vol.placeVolume(active_layer_vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,-z),Rotation(PIby2,phi,0.));
       pv.addPhysVolID("layer",layer.id);
     }
-    detector_vol.placeVolume(layer_vol);
+    assembly.placeVolume(layer_vol);
   }
 
   //****************************************
@@ -254,14 +254,14 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   Tube         support_tube(shell_rmin,shell_rmin+shell_thickess,shell_zhalf);
   Volume       support_vol (name+"_support",support_tube,support_mat);
   support_vol.setVisAttributes(lcdd, x_supp.visStr());
-  detector_vol.placeVolume(support_vol);
+  assembly.placeVolume(support_vol);
 
   // ************support endplates************
   Tube         endplate_tube(x_endpl.rmin(),x_endpl.rmax(),x_endpl.zhalf());
   Volume       endplate_vol (name+"_endcap",endplate_tube,support_mat);
   endplate_vol.setVisAttributes(lcdd, x_endpl.visStr());
-  detector_vol.placeVolume(endplate_vol,Position(0,0, (shell_zhalf + x_endpl.zhalf())));
-  detector_vol.placeVolume(endplate_vol,Position(0,0,-(shell_zhalf + x_endpl.zhalf())));
+  assembly.placeVolume(endplate_vol,Position(0,0, (shell_zhalf + x_endpl.zhalf())));
+  assembly.placeVolume(endplate_vol,Position(0,0,-(shell_zhalf + x_endpl.zhalf())));
 
   // ************support endplates for the layer 1************
   Tube         endplate_support_tube(x_endp1.rmin(),x_endp1.rmax(),x_endp1.zhalf());
@@ -269,8 +269,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   const LayerParams::Ladders& l1 = vxd_data->layers[0].ladders;
   double z = l1.len + 2.0*end_electronics_zhalf + shell_thickess/2. + (be_ladder_block_length*2) ;
   endplate_support_vol.setVisAttributes(lcdd, x_endp1.visStr());
-  detector_vol.placeVolume(endplate_support_vol,Position(0,0, z));
-  detector_vol.placeVolume(endplate_support_vol,Position(0,0,-z));
+  assembly.placeVolume(endplate_support_vol,Position(0,0, z));
+  assembly.placeVolume(endplate_support_vol,Position(0,0,-z));
 
 #if 0
   //*** Cryostat ***************************************************************
@@ -323,7 +323,9 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
 
   return true;
 #endif
-  PlacedVolume lpv = motherVol.placeVolume(detector_vol);
+
+  assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+  PlacedVolume lpv = motherVol.placeVolume(assembly);
 
   return vxd;
 }
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
index 05acb78a30e16e64d21c22624358967d6a052748..9b9c0a7e12d890188c4c003b23abeee742039fc2 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
@@ -17,15 +17,16 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   xml_det_t   x_det  = e;
   string      name   = x_det.nameStr();
   DetElement  sdet(name,x_det.id());
-  Assembly    assembly(name+"_assembly");
+  Assembly    assembly(name);
   xml_comp_t  x_coil = x_det.child(Unicode("coil"));
 
   Tube   coilTub(x_coil.inner_r(),x_coil.outer_r(),x_coil.zhalf());
-  Volume coilVol(name+"_coil",coilTub,lcdd.material(x_coil.materialStr()));
+  Volume coilVol("coil",coilTub,lcdd.material(x_coil.materialStr()));
   coilVol.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
   assembly.placeVolume(coilVol);
 
-  lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+  PlacedVolume pv=lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+  sdet.setPlacement(pv);
   return sdet;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
index 6521a6c491d4696023d3112d0a599e6db330d017..0ff59c3e628ac514effe8d94c0dc5d29bed66411 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
@@ -3,6 +3,11 @@
 //  AIDA Detector description implementation for LCD
 //--------------------------------------------------------------------
 //
+// This subdetector is rather simple: Just a set of disk
+// perpendicular to the beam.
+// - No special user limits required for simulation.
+// - 
+//
 //  Author     : M.Frank
 //
 //====================================================================
@@ -12,21 +17,49 @@
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
+#define _U(text)  Unicode(#text)
+
+/*
+ *   Tesla namespace declaration
+ */
+namespace Tesla {
+  
+  /** @class DiskExtension Ftd01.h Tesla/Ftd01.h
+   *
+   *  Example how to use a detector element extension object
+   *
+   *  @author  M.Frank
+   *  @version 1.0
+   */
+  struct DiskExtension {
+    PlacedVolume  sensitive, support;
+    DiskExtension() {}
+    DiskExtension(const DiskExtension& c) 
+      : sensitive(c.sensitive), support(c.support)  {}
+    DiskExtension(const DiskExtension& c, DetElement& /* org */) 
+      : sensitive(c.sensitive), support(c.support)  {}
+    DiskExtension& operator=(const DiskExtension& c) { 
+      sensitive=c.sensitive;
+      support=c.support;
+      return *this;
+    }
+  };
+}
 
 static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)  {
   xml_det_t   x_det  = e;
   string      name   = x_det.nameStr();
   Rotation    reflect_rot(M_PI,0,0);
   DetElement  sdet(name,x_det.id());
-  Assembly    ftdVol(name+"_assembly");
+  Assembly    ftdVol(name);
   Volume      motherVol   = lcdd.pickMotherVolume(sdet);
 
-  xml_comp_t  x_disks = x_det.child(Unicode("disks"));
-  xml_comp_t  x_cables = x_det.child(Unicode("cables"));
-  xml_comp_t  x_cylinder = x_det.child(Unicode("cylinder"));
-  xml_comp_t  x_support = x_det.child(Unicode("support"));
-  xml_comp_t  x_inner_support = x_support.child(Unicode("inner"));
-  xml_comp_t  x_outer_support = x_support.child(Unicode("outer"));
+  xml_comp_t  x_disks = x_det.child(_U(disks));
+  xml_comp_t  x_cables = x_det.child(_U(cables));
+  xml_comp_t  x_cylinder = x_det.child(_U(cylinder));
+  xml_comp_t  x_support = x_det.child(_U(support));
+  xml_comp_t  x_inner_support = x_support.child(_U(inner));
+  xml_comp_t  x_outer_support = x_support.child(_U(outer));
 
   VisAttr  supportVis  = lcdd.visAttributes(x_support.visStr());
   VisAttr  cablesVis   = lcdd.visAttributes(x_cables.visStr());
@@ -35,44 +68,56 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   Material supportMat  = lcdd.material(x_support.materialStr());
   Material diskMat     = lcdd.material(x_disks.materialStr());
 
-  double si_thickness  = x_disks.attr<double>(Unicode("si_thickness1"));
-  double si_thickness2 = x_disks.attr<double>(Unicode("si_thickness2"));
+  double si_thickness  = x_disks.attr<double>(_U(si_thickness1));
+  double si_thickness2 = x_disks.attr<double>(_U(si_thickness2));
   double inner_support_thickness = x_inner_support.thickness();
   double inner_support_length    = x_inner_support.length();
   double outer_support_thickness = x_outer_support.thickness();
   double outer_support_length    = x_outer_support.length();
 
   struct Cylinder { double z_start, z_stop, r1, r2; } inner_cyl, outer_cyl;
-
   PlacedVolume pv;
-  for(xml_coll_t c(x_disks,Unicode("disk")); c; ++c)  {
+  for(xml_coll_t c(x_disks,_U(disk)); c; ++c)  {
+    typedef Tesla::DiskExtension _Ext;
     xml_comp_t x_disk = c;
     int id = x_disk.id();
     double z_pos = x_disk.z();
     double inner_r = x_disk.inner_r();
     double outer_r = x_disk.outer_r();
+    DetElement disk_pos(sdet,_toString(id,"disk%d_neg"),id);
+    DetElement disk_neg(sdet,_toString(id,"disk%d_pos"),id);
+    _Ext *ext_pos=disk_pos.addExtension<_Ext>(new _Ext());
+    _Ext *ext_neg=disk_neg.addExtension<_Ext>(new _Ext());
     { //... Si sensitive
       Tube   tub(inner_r,outer_r,si_thickness/2.0);
-      Volume vol(name+_toString(id,"_disk%d_Si"),tub,diskMat);
+      Volume vol(_toString(id,"_disk%d_Si"),tub,diskMat);
       vol.setVisAttributes(lcdd.visAttributes(x_disk.visStr()));
+      // This is the sensitive element: add senssitive detector
+      vol.setSensitiveDetector(sens);
       pv = ftdVol.placeVolume(vol,Position(0,0, z_pos));
       pv.addPhysVolID("disk",id);
+      disk_pos.setPlacement(pv);
+      ext_pos->sensitive = pv;
       pv = ftdVol.placeVolume(vol,Position(0,0,-z_pos));
       pv.addPhysVolID("disk",-id);
+      disk_neg.setPlacement(pv);
+      ext_neg->sensitive = pv;
     }
     { //... Support
       Tube   tub(inner_r,outer_r,inner_support_thickness);
-      Volume vol(name+_toString(id,"_disk%d_Support"),tub,supportMat);
+      Volume vol(_toString(id,"_disk%d_support"),tub,supportMat);
       double z = z_pos + si_thickness + inner_support_thickness;
       vol.setVisAttributes(supportVis);
       pv = ftdVol.placeVolume(vol,Position(0,0, z));
       pv.addPhysVolID("disk",id);
+      ext_pos->support = pv;
       pv = ftdVol.placeVolume(vol,Position(0,0,-z));
       pv.addPhysVolID("disk",-id);
+      ext_neg->support = pv;
     }
     /* { //... Outer support rings
       Tube   tub(outer_r,outer_r+outer_support.thickness,outer_support_length);
-      Volume vol(name+_toString(id,"disk%d_outer_support"),tub,supportMat);
+      Volume vol(_toString(id,"disk%d_outer_support"),tub,supportMat);
       vol.setVisAttributes(supportVis);
       pv = ftdVol.placeVolume(vol,Position(0,0, z_pos));
       pv.addPhysVolID("disk",id);
@@ -114,16 +159,16 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     assert(zhalf>0);
     
     Tube   tub_cyl(outer_cyl.r1,outer_cyl.r1+outer_cyl_thickness+cables_thickness,zhalf);
-    Volume vol_cyl(name+"_outerCylinder",tub_cyl,supportMat);
+    Volume vol_cyl("outerCylinder",tub_cyl,supportMat);
     vol_cyl.setVisAttributes(cylinderVis);
     pv = ftdVol.placeVolume(vol_cyl,Position(0,0,cyl_z_pos));
     pv.addPhysVolID("side",1);
     pv = ftdVol.placeVolume(vol_cyl,Position(0,0,-cyl_z_pos));
     pv.addPhysVolID("side",-1);
-    
+
     /*
     Tube   tub_cables(outer_cyl.r1,outer_cyl.r1+cables_thickness,zhalf);
-    Volume vol_cables(name+"_cables",tub_cables,cablesMat);
+    Volume vol_cables("cables",tub_cables,cablesMat);
     vol_cables.setVisAttributes(cablesVis);
     ftdVol.placeVolume(vol_cables,Position());
      */
@@ -137,7 +182,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     
     Cone cone_cyl(inner_cyl.r1-outer_cyl_thickness-cables_thickness,inner_cyl.r1,
 	      inner_cyl.r2-outer_cyl_thickness-cables_thickness,inner_cyl.r2,zhalf);
-    Volume vol_cyl(name+"_innerCables",cone_cyl,supportMat);
+    Volume vol_cyl("innerCables",cone_cyl,supportMat);
     vol_cyl.setVisAttributes(cylinderVis);
     pv = ftdVol.placeVolume(vol_cyl,Position(0,0,cyl_z_pos));
     pv.addPhysVolID("side",1);
@@ -145,12 +190,13 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     pv.addPhysVolID("side",-1);
 
     Cone cone_cables(inner_cyl.r1-cables_thickness,inner_cyl.r1,
-	      inner_cyl.r2-cables_thickness,inner_cyl.r2,zhalf);
-    Volume vol_cables(name+"_innerCables",cone_cables,cablesMat);
+		     inner_cyl.r2-cables_thickness,inner_cyl.r2,zhalf);
+    Volume vol_cables("coneCables",cone_cables,cablesMat);
     vol_cables.setVisAttributes(cablesVis);
     ftdVol.placeVolume(vol_cables);
   }
-  motherVol.placeVolume(ftdVol);
+  pv = motherVol.placeVolume(ftdVol);
+  sdet.setPlacement(pv);
   return sdet;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
index 1e78c150847bf9ea10dd473d29cfba10e8da5bb0..3d23524d5f5facd2ee31bfe7b2e194c681cf71b5 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
@@ -7,233 +7,294 @@
 //
 //====================================================================
 #include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/Detector.h"
 #include "TGeoTube.h"
 
-using namespace std;
-using namespace DD4hep;
-using namespace DD4hep::Geometry;
-
-#define _U(text)  Unicode(#text)
-
 namespace DD4hep {
   namespace Geometry {
     struct Hcal04Data : public DetElement::Object {
       enum {HCALBARREL = 1, HCALENDCAPPLUS=2, HCALENDCAPMINUS=3 };
+      enum {SIDE_PLUS=0, SIDE_MINUS=1 };
 
-      typedef Position Dimension;
-      Material radiatorMat;
-      string model;
-      struct Barrel {
-	Dimension    bottom, middle, top;
-	Dimension    module;
-	Dimension    cells;
-	double       y1_for_x;
-	double       y2_for_x;
-        double       inner_r;
-	int          numLayer;
-      } barrel;
-
-      struct Layer : public Dimension {
+      struct Layer {
 	int       id;
-	union {
-	  struct { double y_offset, dim_x; } layer;
-	  struct { double z_offset, dim_z; } end_layer;
-	  struct { double z_offset, dim_z; } endcap_layer;
+	union Vals {
+	  struct BL { double y_offset, dim_x, dim_z; } layer;
+	  struct EL { double z_offset, dim_z;        } end_layer;
+	  struct EC { double z_offset, dummy;        } endcap_layer;
 	} values;
-        Dimension offset;
       };
-      struct Layers : public std::vector<Layer>  {
-      } barrel_layers, end_layers, endcap_layers;
-
+      struct Layers : public std::vector<Layer>    {      };
       struct Stave {
 	int    id;
 	double phi;
 	double inner_r;
 	double z_offset;
       };
-      struct Staves : public std::vector<Stave> {
-      } staves;
-
+      struct Staves : public std::vector<Stave>    {      };
       struct Module {
 	int    id;
+	int    type;
 	double z_offset;
       };
-      struct Modules : public std::vector<Module> {
-      } modules;
-
-      struct Chambers {
-	double x, thickness, z;
-      } chamber;
+      struct Modules : public std::vector<Module>  {      };
 
       struct RPC {
 	double g10_thickness;
-	double glass_thickness;
-	double gas_thickness;
 	double spacer_thickness;
 	double spacer_gap;
-      } rpc;
-      double fiberGap;
-      SensitiveDetector barrelSensitiveDetector;
-    };
+	struct { double thickness; Material material; VisAttr vis; } radiator, glass, gas;
+	struct { double thickness, gap; } spacer;
+      } m_rpc;
+
+      struct Barrel : public DetElement  {
+	double       bottom_dim_x;
+	double       middle_dim_x;
+	double       top_dim_x;
+	double       y1_for_x, y2_for_x;
+	double       y1_for_z, y2_for_z, y3_for_z, top_end_dim_z;
 
+        double       inner_r;
+	double       module_dim_z;
+	double       cell_dim_x, cell_dim_z;
+	double       chamber_thickness;
+	double       chamber_dim_z;
+	int          numLayer;
+	Layers       layers, end_layers;
+	Staves       staves;
+	Modules      modules;
+	SensitiveDetector sensRegular, sensEndModule;
+	/// Helper function to allow assignment
+	DetElement& operator=(const DetElement& d)  { return this->DetElement::operator=(d); }
+      } m_barrel;
+
+      struct Endcap : public DetElement  {
+	Layers layers;
+	double rmin, rmax, dz;
+	double chamber_thickness;
+	SensitiveDetector sensDet;
+	struct EndcapSide : public DetElement { 
+	  int id; 
+	  Position position; 
+	  DetElement& operator=(const DetElement& d) 
+	  { return this->DetElement::operator=(d); }
+	} side[2];
+      } m_endcap;
+
+      VisAttr     m_scintVis;
+      VisAttr     m_moduleVis;
+      VisAttr     m_endModuleVis;
+      VisAttr     m_endcapModuleVis;
+      VisAttr     m_chamberVis;
+      Material    m_scintMaterial;
+      Material    m_radiatorMat;
+      LimitSet    m_limits;
+      double      m_fiberGap;
+      std::string m_model;
+      DetElement  self;
+      LCDD*       lcdd;
+      std::string name;
+    };
     
     struct Hcal04 : public Hcal04Data  {
-      LCDD*       lcdd;
-      xml_det_t   x_det;
-      xml_comp_t  x_barrel;
-      xml_comp_t  x_endcap;
-      xml_comp_t  x_bottom;
-      xml_comp_t  x_middle;
-      xml_comp_t  x_top;
-      xml_comp_t  x_cells;
-      xml_comp_t  x_module;
-      xml_comp_t  x_rpc;
-      xml_comp_t  x_rad;
-      xml_comp_t  x_glass;
-      xml_comp_t  x_param;
-      
-      VisAttr m_chamberVis, m_moduleVis;
-      Material m_scintillatorMat;
-
-      Hcal04() 
-	: Hcal04Data(), x_det(0), x_barrel(0), x_endcap(0), x_bottom(0), x_middle(0), x_top(0),
-	  x_cells(0), x_module(0), x_rpc(0), x_rad(0), x_glass(0), x_param(0)  {}
-
-      void construct(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens);
+      /// Default constructor
+      Hcal04() : Hcal04Data()     {}
+      /// Detector construction function
+      DetElement construct(LCDD& lcdd, xml_det_t e);
       /// Build and place Barrel Regular Modules
       void buildBarrelRegularModules(Volume assembly);
+      /// Build and place Barrel End Modules
       void buildBarrelEndModules(Volume assembly);
-  
-      // EndCap Modules
+      // Build and place EndCap Modules
       void buildEndcaps(Volume assembly);
-
       /// Build Box with RPC1 chamber
-      Volume buildRPC1Box(const std::string& nam, Box box, const Layer& layer);
+      Volume buildRPC1Box(const std::string& nam, Box box, const Layer& layer, SensitiveDetector& sensdet);
     };
   }
 }
 
-void Hcal04::construct(LCDD& l, const xml_h& e, SensitiveDetector& sens)  {
-  /*
-    <constant name="Hcal_spacer_thickness" value="8*mm"/>
-    <constant name="Hcal_nlayers" value="38"/>
-    <constant name="Hcal_endcap_nlayers" value="38"/>
-
-    <endcap nlayers="Hcal_endcap_nlayers" fiber_gap="Hcal_fiber_gap">
-    <barrel sensitive_model="scintillator" nlayers="Hcal_nlayers">
-    <top    x=""/>
-    <middle x=""/>
-    <bottom x=""/>
-    <module x=""/>
-    <rpc g10_thickness="" glass_thickness="" gas_thickness="" spacer_thickness="Hcal_spacer_thickness" spacer_gap=""/>
-    </barrel>
-  */
-  lcdd     =  &l;
-  x_det    =  e;
-  x_barrel = x_det.child(_U(barrel));
-  x_endcap = x_det.child(_U(endcap));
-  x_param  = x_det.child(_U(param));
-
-  x_bottom = x_det.child(Unicode("bottom"));
-  x_middle = x_det.child(Unicode("middle"));
-  x_top    = x_det.child(Unicode("top"));
-  x_cells  = x_det.child(Unicode("cells"));
-  x_module = x_det.child(Unicode("module"));
-  x_rpc    = x_det.child(Unicode("rpc"));
-  x_rad    = x_det.child(Unicode("rpc"));
-
-  string   nam = x_det.nameStr();
-  Assembly assembly(nam+"_assembly");
-
-  Volume motherVol = lcdd->pickMotherVolume(Ref_t(this));
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+#define _U(text)  Unicode(#text)
+
+static double s_geo_tolerance = 1e-10;
+
+/// Detector construction function
+DetElement Hcal04::construct(LCDD& l, xml_det_t x_det)  {
+  lcdd     = &l;
+  name     = x_det.nameStr();
+  self.assign(dynamic_cast<Value<TNamed,Hcal04>*>(this),name,x_det.typeStr());
+
+  xml_comp_t  x_barrel        = x_det.child(_U(barrel));
+  xml_comp_t  x_endcap        = x_det.child(_U(endcap));
+  xml_comp_t  x_param         = x_det.child(_U(param));
+  xml_comp_t  x_rpc           = x_det.child(_U(rpc));
+  xml_comp_t  x_scintillator  = x_det.child(_U(scintillator));
+  xml_comp_t  x_module        = x_barrel.child(_U(module));
+  xml_comp_t  x_end_module    = x_barrel.child(_U(end_module));
+  xml_comp_t  x_endcap_module = x_endcap.child(_U(module));
+
+  Assembly assembly(name);
+  Volume motherVol  = lcdd->pickMotherVolume(Ref_t(this));
+
   // Visualisation attributes
-  VisAttr vis  = lcdd->visAttributes(x_det.visStr());
-  m_moduleVis  = lcdd->visAttributes("HcalVis");
-  m_chamberVis = lcdd->visAttributes("HcalChamberVis");
-  m_scintillatorMat = lcdd->material("polystyrene");
+  VisAttr vis       = lcdd->visAttributes(x_det.visStr());
+  m_moduleVis       = lcdd->visAttributes(x_module.visStr());
+  m_endModuleVis    = lcdd->visAttributes(x_end_module.visStr());
+  m_endcapModuleVis = lcdd->visAttributes(x_endcap_module.visStr());
+  m_chamberVis      = lcdd->visAttributes(x_param.attr<string>(_U(chamber_vis)));
+  m_scintVis        = lcdd->visAttributes(x_scintillator.visStr());
+  m_scintMaterial   = lcdd->material(x_scintillator.materialStr());
 
   //--------- BarrelHcal Sensitive detector -----
-  model    = x_det.attr<string>(Unicode("model"));
-  fiberGap = x_det.attr<double>(Unicode("fiber_gap"));
-  radiatorMat = lcdd->material(x_rad.materialStr());
-
-  barrel.numLayer = x_barrel.attr<int>(Unicode("num_layer"));
-  barrel.bottom.x = x_bottom.x();
-  barrel.middle.x = x_middle.x();
-  barrel.top.x    = x_top.x();
-  barrel.module.x = x_module.x();
-  barrel.y1_for_x = x_module.attr<double>(Unicode("y1_for_x"));
-  barrel.y2_for_x = x_module.attr<double>(Unicode("y2_for_x"));
-  //double chamber_tickness = x_params.attr<double>(Unicode("chamber_tickness"));
-  barrel.cells.x = x_cells.x();
-  barrel.cells.z = x_cells.z();
+  m_model           = x_param.attr<string>(_U(sensitive_model));
+  m_fiberGap        = x_param.attr<double>(_U(fiber_gap));
+  m_radiatorMat     = lcdd->material(x_param.attr<string>(_U(radiator_material)));
+
+  m_barrel.chamber_thickness = x_barrel.attr<double>(_U(chamber_thickness));
+  m_barrel.numLayer   = x_barrel.attr<int>(_U(num_layer));
+  m_barrel.inner_r    = x_barrel.inner_r();
+
+  // Paremeters for regular barrel modules
+  m_barrel.chamber_dim_z = x_module.attr<double>(_U(chamber_dim_z));
+  m_barrel.module_dim_z  = x_module.attr<double>(_U(dim_z));
+  m_barrel.bottom_dim_x  = x_module.attr<double>(_U(bottom_dim_x));
+  m_barrel.middle_dim_x  = x_module.attr<double>(_U(middle_dim_x));
+  m_barrel.top_dim_x     = x_module.attr<double>(_U(top_dim_x));
+  m_barrel.y1_for_x      = x_module.attr<double>(_U(y_dim1_for_x));
+  m_barrel.y2_for_x      = x_module.attr<double>(_U(y_dim2_for_x));
+  m_barrel.cell_dim_x    = x_module.attr<double>(_U(cell_dim_x));
+  m_barrel.cell_dim_z    = x_module.attr<double>(_U(cell_dim_z));
+
+  // Parameters for barrel end-module
+  m_barrel.y1_for_z      = x_end_module.attr<double>(_U(y_dim1_for_z));
+  m_barrel.y2_for_z      = x_end_module.attr<double>(_U(y_dim2_for_z));
+  m_barrel.y3_for_z      = x_end_module.attr<double>(_U(y_dim3_for_z));
+  m_barrel.top_end_dim_z = x_end_module.attr<double>(_U(top_end_dim_z));
 
-  
   // if RPC1 read the RPC parameters
-  if ( model == "RPC1" )   {
-    rpc.g10_thickness    =x_rpc.attr<double>(Unicode("g10_thickness"));
-    rpc.glass_thickness  =x_rpc.attr<double>(Unicode("glass_thickness"));
-    rpc.gas_thickness    =x_rpc.attr<double>(Unicode("gas_thickness"));
-    rpc.spacer_thickness =x_rpc.attr<double>(Unicode("spacer_thickness"));
-    rpc.spacer_gap       =x_rpc.attr<double>(Unicode("spacer_gap"));
+  if ( m_model == "RPC1" )   {
+    xml_comp_t x_rad       = x_rpc.child(_U(radiator));
+    xml_comp_t x_gas       = x_rpc.child(_U(gas));
+    xml_comp_t x_glass     = x_rpc.child(_U(glass));
+    xml_comp_t x_spacer    = x_rpc.child(_U(spacer));
+    m_rpc.spacer.thickness   = x_spacer.thickness();
+    m_rpc.spacer.gap         = x_spacer.gap();
+    m_rpc.radiator.thickness = x_rad.thickness();
+    m_rpc.radiator.material  = lcdd->material(x_rad.materialStr());
+    m_rpc.gas.thickness      = x_gas.thickness();
+    m_rpc.gas.material       = lcdd->material(x_gas.materialStr());
+    m_rpc.gas.vis            = lcdd->visAttributes(x_gas.visStr());
+    m_rpc.glass.thickness    = x_glass.thickness();
+    m_rpc.glass.material     = lcdd->material(x_glass.materialStr());
+    m_rpc.glass.vis          = lcdd->visAttributes(x_glass.visStr());
   }
   { // Read the barrel layers
+    Stave stave;
     Layer layer;
-    barrel_layers.clear();
+    Module module;
+    m_barrel.layers.clear();
     for(xml_coll_t c(x_barrel.child(_U(layers)),_X(layer)); c; ++c) {
       xml_comp_t l(c);
       layer.id = l.id();
       layer.values.layer.dim_x    = l.dim_x();
       layer.values.layer.y_offset = l.y_offset();
-      barrel_layers.push_back(layer);
+      m_barrel.layers.push_back(layer);
     }
-    assert(barrel.numLayer != barrel_layers.size());
-  }
-  { // Read the barrel end-layers
-    Layer layer;
-    end_layers.clear();
+    assert(m_barrel.numLayer != m_barrel.layers.size());
+    // Read the barrel end-layers
+    m_barrel.end_layers.clear();
     for(xml_coll_t c(x_barrel.child(_U(end_layers)),_U(end_layer)); c; ++c) {
       xml_comp_t l(c);
       layer.id = l.id();
       layer.values.end_layer.dim_z    = l.dim_z();
       layer.values.end_layer.z_offset = l.z_offset();
-      end_layers.push_back(layer);
+      m_barrel.end_layers.push_back(layer);
+    }
+    assert(m_barrel.numLayer != m_barrel.end_layers.size());
+    m_barrel.staves.clear();
+    for(xml_coll_t c(x_barrel.child(_X(staves)),_X(stave)); c; ++c) {
+      xml_comp_t s(c);
+      stave.id = s.id();
+      stave.phi = s.phi();
+      //stave.inner_r = s.inner_r();
+      //stave.z_offset = s.z_offset();
+      m_barrel.staves.push_back(stave);
+    }
+    m_barrel.modules.clear();
+    for(xml_coll_t c(x_barrel.child(_X(modules)),_X(module)); c; ++c) {
+      xml_comp_t m(c);
+      module.id = m.id();
+      module.type = m.attr<int>(_A(type));
+      module.z_offset = m.z_offset();
+      m_barrel.modules.push_back(module);
     }
-    assert(barrel.numLayer != end_layers.size());
   }
-  { // Read the endcap layers
+  { // Read the endcap structure
+    int cnt=0;
     Layer layer;
-    barrel_layers.clear();
+    for(xml_coll_t c(x_endcap.child(_U(positions)),_X(position)); c; ++c, ++cnt) {
+      xml_comp_t ec(c);
+      m_endcap.side[cnt].id = ec.id();
+      m_endcap.side[cnt].position = Position(ec.x(),ec.y(),ec.z());
+    }
+    m_endcap.rmin = x_endcap_module.rmin();
+    m_endcap.rmax = x_endcap_module.rmax();
+    m_endcap.dz   = x_endcap_module.dz();
+    m_endcap.chamber_thickness = m_barrel.chamber_thickness;
+
+    cout << name << ": End cap: rmin=" << m_endcap.rmin << " rmax=" << m_endcap.rmax << " dz=" << m_endcap.dz << endl;
+    // Read the endcap layers
+    m_endcap.layers.clear();
     for(xml_coll_t c(x_endcap.child(_X(layers)),_X(layer)); c; ++c) {
       xml_comp_t l(c);
       layer.id = l.id();
-      layer.values.end_layer.z_offset = l.z_offset();
-      endcap_layers.push_back(layer);
+      layer.values.endcap_layer.dummy = 0;
+      layer.values.endcap_layer.z_offset = l.z_offset();
+      m_endcap.layers.push_back(layer);
     }
-    assert(barrel.numLayer != end_layers.size());
-  }
- 
+  } 
 
 #if 0
   // The cell boundaries does not really exist as G4 volumes. So,
   // to avoid long steps over running  several cells, the 
   // theMaxStepAllowed inside the sensitive material is the
   // pad smaller x or z dimension.
-  theMaxStepAllowed= std::min(barrel.cells.x,barrel.cells.z);
-
+  theMaxStepAllowed= std::min(m_barrel.cells.x,m_barrel.cells.z);
   //  Hcal  barrel regular modules
-  theBarrilRegSD =     new SD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelReg");
-  RegisterSensitiveDetector(theBarrilRegSD);
-  
+  theBarrilRegSD =     new SD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelReg");
   // Hcal  barrel end modules
-  theBarrilEndSD = new SD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelEnd");
-  RegisterSensitiveDetector(theBarrilEndSD);
-
+  theBarrilEndSD = new SD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelEnd");
   // Hcal  endcap modules
-  theENDCAPEndSD = new HECSD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALENDCAPMINUS,"HcalEndCaps");
-  RegisterSensitiveDetector(theENDCAPEndSD);
+  theENDCAPEndSD = new HECSD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALENDCAPMINUS,"HcalEndCaps");
 #endif
 
+  m_barrel = DetElement(self,"barrel",HCALBARREL);
+
+  // Setup the sensitive detectors for barrel, endcap+ and endcap-
+  SensitiveDetector& sd = m_barrel.sensRegular = SensitiveDetector("HcalBarrelRegular");
+  Readout ro = lcdd->readout(x_module.readoutStr());
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+
+  sd = m_barrel.sensEndModule = SensitiveDetector("HcalBarrelEndModule");
+  ro = lcdd->readout(x_end_module.readoutStr());
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+  
+  sd = m_endcap.sensDet = SensitiveDetector("HcalEndcap");
+  ro = lcdd->readout(x_endcap_module.readoutStr());
+  sd.setHitsCollection(ro.name());
+  sd.setReadout(ro);
+  lcdd->addSensitiveDetector(sd);
+
+  // User limits for this sub detector
+  m_limits = lcdd->limitSet(x_det.limitsStr());
+  
   // Barrel
   buildBarrelRegularModules(assembly);
   buildBarrelEndModules(assembly);
@@ -241,574 +302,324 @@ void Hcal04::construct(LCDD& l, const xml_h& e, SensitiveDetector& sens)  {
   // EndCap Modules
   buildEndcaps(assembly);
 
-  motherVol.placeVolume(assembly);
+  PlacedVolume pv = motherVol.placeVolume(assembly);
+  m_barrel.setPlacement(pv);
+  self.setPlacement(pv);
+  return self;
 }
 
 /// Build and place Barrel Regular Modules
-void Hcal04::buildBarrelRegularModules(Volume parent)   {
-  string nam = x_det.nameStr();
+void Hcal04::buildBarrelRegularModules(Volume assembly)   {
+  DetElement module("module",0);
 
   // Attention: on bâtit le module dans la verticale à cause du G4Trd et on le tourne avant de le positioner
-  Trapezoid trdBottom(barrel.bottom.x/2, barrel.middle.x/2,barrel.module.z/2, barrel.module.z/2, barrel.y1_for_x/2);
-  Trapezoid trdTop   (barrel.middle.x/2, barrel.top.x/2,   barrel.module.z/2, barrel.module.z/2, barrel.y2_for_x/2);
+  Trapezoid trdBottom(m_barrel.bottom_dim_x/2, m_barrel.middle_dim_x/2,m_barrel.module_dim_z/2, m_barrel.module_dim_z/2, m_barrel.y1_for_x/2);
+  Trapezoid trdTop   (m_barrel.middle_dim_x/2, m_barrel.top_dim_x/2,   m_barrel.module_dim_z/2, m_barrel.module_dim_z/2, m_barrel.y2_for_x/2);
 
-  UnionSolid modSolid (trdBottom, trdTop, Position(0,0,(barrel.y1_for_x+barrel.y2_for_x)/2.));
-  Volume     modVolume(nam+"_module",modSolid,radiatorMat);
+  UnionSolid modSolid (trdBottom,trdTop,Position(0,0,(m_barrel.y1_for_x+m_barrel.y2_for_x)/2));
+  Volume     modVolume("regModule",modSolid,m_radiatorMat);
 
   modVolume.setVisAttributes(m_moduleVis);
-  double chambers_y_off_correction = barrel.y2_for_x/2;
-  double bottomDimY = barrel.y1_for_x/2;
-
-  //G4UserLimits* pULimits=    new G4UserLimits(theMaxStepAllowed);
+  double chambers_y_off_correction = m_barrel.y2_for_x/2;
+  double bottomDimY = m_barrel.y1_for_x/2;
 
   PlacedVolume pv;
-  double Xoff = 0;
-  double Yoff = x_module.offset();
-  for(Layers::const_iterator i=barrel_layers.begin(); i != barrel_layers.end(); ++i)  {
-    const Layer& layer = *i;
-    double thickness = layer.y/2;
-    Box  chamberBox(layer.x/2,layer.y/2,layer.z/2);
+  for(Layers::const_iterator i=m_barrel.layers.begin(); i != m_barrel.layers.end(); ++i)  {
+    const Layer& lay = *i;
+    DetElement det_layer(module,_toString(lay.id,"layer%d"),lay.id);
+    double dim_x = lay.values.layer.dim_x/2;
+    double thickness = m_barrel.chamber_thickness/2;
+    
+    Box  chamberBox(dim_x,m_barrel.chamber_dim_z/2,thickness);
     Volume chamberVol;
-    if ( model == "scintillator")      {	
+    if ( m_model == "scintillator")      {	
       //fg: introduce (empty) fiber gap - should be filled with fibres and cables
-      Box    scintBox(layer.x/2,layer.z/2,(thickness - fiberGap)/2);
-      Volume scintVol(nam+_toString(layer.id,"_scint%d"),scintBox,m_scintillatorMat);
-      scintVol.setSensitiveDetector(barrelSensitiveDetector);
-      scintVol.setVisAttributes(m_chamberVis);
-      //scintVol.setAttributes(lcdd,"",x_slice.limitsStr(),x_slice.visStr());
-      //scintVol.setLimits(pULimits);
-      //scintVol->SetSensitiveDetector(theBarrilRegSD);
-      chamberVol = Volume(nam+_toString(layer.id,"_chamber%d"),chamberBox,lcdd->air());
-      pv = chamberVol.placeVolume(scintVol,Position(0,0,-fiberGap/2));
+      Box    scintBox(dim_x,m_barrel.chamber_dim_z/2,thickness - m_fiberGap/2);
+      Volume scintVol(_toString(lay.id,"scint%d"),scintBox,m_scintMaterial);
+      scintVol.setSensitiveDetector(m_barrel.sensRegular);
+      scintVol.setVisAttributes(m_scintVis);
+      scintVol.setLimitSet(m_limits);
+      chamberVol = Volume(_toString(lay.id,"chamber%d"),chamberBox,lcdd->air());
+      pv = chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap/2));
     }
-    else if (model == "RPC1")	{
-      string nam = x_det.nameStr()+_toString(layer.id,"_barrel_layer_%d");
-      chamberVol = buildRPC1Box(nam,chamberBox,layer);
+    else if (m_model == "RPC1")	{
+      chamberVol = buildRPC1Box(_toString(lay.id,"layer_%d"),chamberBox,lay,m_barrel.sensRegular);
     }
     else    {
-      throw runtime_error("Unknown sensitive model:"+model+" for detector hcal04");
+      throw runtime_error("Unknown sensitive model:"+m_model+" for detector hcal04");
     }
     chamberVol.setVisAttributes(m_chamberVis);
-    const Position& pos = layer.offset;
-    pv = modVolume.placeVolume(chamberVol,Position(pos.x,pos.z,pos.y+chambers_y_off_correction));
-    pv.addPhysVolID("layer",layer.id);
-  }   
-  
-  double Y = barrel.inner_r+barrel.y1_for_x/2;
-  for(Staves::const_iterator i=staves.begin(); i!=staves.end(); ++i) {
+    pv = modVolume.placeVolume(chamberVol,Position(0,0,lay.values.layer.y_offset+chambers_y_off_correction));
+    pv.addPhysVolID("layer",lay.id);
+    det_layer.setPlacement(pv);
+  }
+
+  DetElement det_mod;
+  double Y = m_barrel.inner_r+m_barrel.y1_for_x/2;
+  for(Staves::const_iterator i=m_barrel.staves.begin(); i!=m_barrel.staves.end(); ++i) {
     const Stave& s = *i;
-    Rotation rot(M_PI/2,s.phi,0);
-    for(Modules::const_iterator j=modules.begin(); j!=modules.end(); ++j) {
+    Rotation rot(-M_PI/2,s.phi,0);
+    DetElement stave_det(m_barrel,_toString(s.id,"reg_stave%d"),s.id*10);
+    for(Modules::const_iterator j=m_barrel.modules.begin(); j!=m_barrel.modules.end(); ++j) {
       const Module& m = *j;
-      Position pos(0,Y,m.z_offset);
-      pv = parent.placeVolume(modVolume,pos.rotateZ(s.phi),rot);
-      pv.addPhysVolID("module",HCALBARREL*100+s.id*10+m.id);
+      if ( m.type == 1 )   {
+	Position pos(0,Y,m.z_offset);
+	if ( !det_mod.isValid() ) {
+	  module._data().id = m.id;
+	  module->SetName(_toString(m.id,"module%d").c_str());
+	  det_mod = module;
+	}
+	else {
+	  det_mod = module.clone(_toString(m.id,"module%d"),m.id);
+	}
+	pv = assembly.placeVolume(modVolume,pos.rotateZ(s.phi),rot);
+	pv.addPhysVolID("module",HCALBARREL*100+s.id*10+m.id);
+	stave_det.add(det_mod);
+	det_mod.setPlacement(pv);
+      }
     }
   }
 }
 
 ///  Barrel End Modules
 void Hcal04::buildBarrelEndModules(Volume assembly)    {
-
-#if 0
-  // End modules
-  db->exec("select y1_for_z/2. AS YZ1H,2_for_z/2. AS YZ2H, y3_for_z/2. AS YZ3H, top_end_dim_z/2.  AS TZ from barrel_end_module;");
-  db->getTuple();
-  double YZ1H = end_layers.y1_for_z/2;
-  double YZ2H = end_layers.y2_for_z/2;
-  double YZ3H = end_layers.y3_for_z/2;
-  double TZ = end_layers.z;
-  double chambers_y_off_correction = YZ3H;
-
-  db->exec("select bottom_dim_x/2 AS BHX,midle_dim_x/2. AS MHX, top_dim_x/2 AS THX, y1_for_x/2. AS YX1H,y_dim2_for_x/2. AS YX2H,module_dim_z/2. AS DHZ from barrel_module,barrel_regular_module;");
-  db->getTuple();
-  double BHX = db->fetchDouble("BHX");
-  double MHX = db->fetchDouble("MHX");
-  double THX = db->fetchDouble("THX");
-  double YX1H = db->fetchDouble("YX1H");
-  double YX2H = db->fetchDouble("YX2H");
-  double DHZ = db->fetchDouble("DHZ");
+  DetElement module("module",0);
+  double YZ1H = m_barrel.y1_for_z/2;
+  double YZ2H = m_barrel.y2_for_z/2;
+  double YZ3H = m_barrel.y3_for_z/2;
+  double TZ   = m_barrel.top_end_dim_z/2;
+  double BHX  = m_barrel.bottom_dim_x/2;
+  double MHX  = m_barrel.middle_dim_x/2;
+  double THX  = m_barrel.top_dim_x/2;
+  double YX1H = m_barrel.y1_for_x/2;
+  double YX2H = m_barrel.y2_for_x/2;
+  double DHZ  = m_barrel.module_dim_z/2;
 
   // Attention: on bâtit le module dans la verticale à cause des G4Trd et on le tourne avant de le positioner
-  //
-  // Base
-
-  double MHXZ = barrel.bottom.x/2 + (end_layers.y1_for_z/2 + end_layers.y2_for_z/2) * (barrel.middle.x/2 - barrel.bottom.x/2)/barrel.y1_for_x/2;
-  Trapezoid base1(barrel.bottom.x/2, MHXZ, barrel.module.z/2, barrelmodule.z/2,YZH1+YZH2);
-  Trapezoid base2(MHXZ, barrel.middle.x/2,end_layers.z,end_layers.z,YX1H-(YZ1H+YZ2H));
+  double MHXZ = BHX+(YZ1H+YZ2H)*(MHX-BHX)/YX1H;
+  Trapezoid  base1(BHX,MHXZ,DHZ,DHZ,YZ1H+YZ2H);
+  Trapezoid  base2(MHXZ,MHX,TZ,TZ,YX1H-(YZ1H+YZ2H));
   UnionSolid base(base1,base2,Position(0,TZ-DHZ,YX1H));
-  
-  Trapezoid topTrd(MHX,THX,TZ,TZ,YX2H);
+  Trapezoid  topTrd(MHX,THX,TZ,TZ,YX2H);
   UnionSolid trd(base,topTrd,Position(0,TZ-DHZ,2*YX1H-(YZ1H+YZ2H)+YX2H));
-  double MHXZ1 = BHX+((YZ1H+YZ2H)-(TZ-DHZ))*(MHX-BHX)/YX1H;
 
+  double MHXZ1  = BHX+((YZ1H+YZ2H)-(TZ-DHZ))*(MHX-BHX)/YX1H;
   double pDX    = TZ-DHZ;
-  double pDz    = std::sqrt(4*YZ2H*YZ2H+pDX*pDX)/2.;  
+  double pDz    = std::sqrt(4*YZ2H*YZ2H+pDX*pDX)/2;
   double pTheta = M_PI/2 - std::atan(2*pDz/pDX);
   Trap trap(pDz,-pTheta,0,MHXZ1,s_geo_tolerance,s_geo_tolerance,0,MHXZ,pDX,pDX,0);
-  UnionSolid ensemble(trd, trap,Rotation(0,0,M_PI/2),
-		      Position(0,DHZ+pDX-pDz*tan(pTheta),YZ1H+YZ2H-pDz));
-  Volume endBarrelVol(nam+"barrelHcalModule",ensemble,radiatorMat);
-  endBarrelVol.setVisAttributes(lcdd->visAttributes("HcalVis"));
+  UnionSolid ensemble(trd, trap,Position(0,DHZ+pDX-pDz*std::tan(pTheta),YZ1H+YZ2H-pDz),Rotation(0,0,M_PI/2));
+  Volume endBarrelVol("endModule",ensemble,m_radiatorMat);
+  endBarrelVol.setVisAttributes(m_endModuleVis);
 
   // Chambers in the Hcal Barrel 
   //------------------------------------------------------------------------------------------------------
-  //G4UserLimits* pULimits=    new G4UserLimits(theMaxStepAllowed);
+  double chambers_y_off_correction = m_barrel.y3_for_z/2;
   PlacedVolume pv;
   
-  G4VisAttributes *dBarrelVolVisAtt = new G4VisAttributes(G4Colour(.2,.8,.2));
-  VisAtt->SetForceWireframe(true);
-
-
-  db->exec("select barrel_regular_layer.layer_id,chamber_dim_x/2. AS xdh,chamber_tickness/2. AS ydh,chamber_dim_z/2. AS zdh, fiber_gap from hcal,barrel_regular_layer,barrel_end_layer where barrel_regular_layer.layer_id = barrel_end_layer.layer_id ;");
-  G4UserLimits* pULimits = new G4UserLimits(theMaxStepAllowed);
-
-  for(size_t i=barrel_layers.begin(); i != barrel_layers.end(); ++i)  {
-
-    const Layer& blay = barrel_layers[i];
-    const Layer& elay = end_layers[i];
-    Box chamberBox(layer.x/2,elay.z/2,chamber.thickness);
-    if( model == "scintillator" )	{
+  double ydh = m_barrel.chamber_thickness/2;
+  double zdh = m_barrel.chamber_dim_z/2;
+  for(size_t i=0; i < m_barrel.layers.size(); ++i)  {
+    int layer_id = m_barrel.layers[i].id;
+    DetElement det_layer(module,_toString(layer_id,"layer%d"),layer_id);
+    const Layer::Vals::BL& blay = m_barrel.layers[i].values.layer;
+    const Layer::Vals::EL& elay = m_barrel.end_layers[i].values.end_layer;
+    double xdh = blay.dim_x/2;
+    Box chamberBox(xdh,zdh,ydh);
+    Volume chamberVol;
+    if( m_model == "scintillator" )	{
       //fg: introduce (empty) fiber gap - should be filled with fibres and cables
-      chamberVol = Volume(nam+_toString(i,"_chamber%d"),chamberBox,lcdd->air());
-
-      double fiberGap = db->fetchDouble("fiber_gap")  ;
-      double scintHalfWidth =  db->fetchDouble("ydh") - fiberGap  / 2. ;
-
       // fiber gap can't be larger than total chamber
-      assert( scintHalfWidth > 0. ) ;
-
-      G4Box * ScintSolid = 
-	new G4Box("ScintSolid", 
-		  db->fetchDouble("xdh"),  //hx
-		  db->fetchDouble("zdh"),  //hz attention!
-		  scintHalfWidth ); //hy attention!
-      G4LogicalVolume* ScintLog =
-	new G4LogicalVolume(ScintSolid,
-			    CGAGeometryManager::GetMaterial("polystyrene"),
-			    "ScintLogical", 
-			    0, 0, pULimits);	   
-      // only scinitllator is sensitive
-      ScintLog->SetSensitiveDetector(theBarrilEndSD);
-      int layer_id = db->fetchInt("layer_id") ;
-      new MyPlacement(0, G4ThreeVector( 0,0,  - fiberGap / 2. ), ScintLog,
-		      "Scintillator", ChamberLogical, false, layer_id);   
-      ChamberLog [ layer_id ] = ChamberLogical ;
+      assert( (ydh - m_fiberGap/2) > 0.);
+      Box scintBox(xdh,zdh,ydh - m_fiberGap  / 2);
+      Volume scintVol(_toString(layer_id,"scint%d"),scintBox,m_scintMaterial);
+      scintVol.setSensitiveDetector(m_barrel.sensEndModule);
+      scintVol.setVisAttributes(m_scintVis);
+      scintVol.setLimitSet(m_limits);
+      chamberVol = Volume(_toString(layer_id,"chamber%d"),chamberBox,lcdd->air());
+      pv = chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap/2));
     }
-    else if (SensitiveModel == "RPC1")	{
-      G4int layer_id = db->fetchInt("layer_id");
-      ChamberLog [layer_id] =
-	BuildRPC1Box(nam,ChamberSolid,theBarrilEndSD,layer_id,pULimits);
+    else if (m_model == "RPC1")	{
+      string nam = _toString(layer_id,"layer_%d");
+      chamberVol = buildRPC1Box(nam,chamberBox,m_barrel.end_layers[i],m_barrel.sensEndModule);
     }
-    else Control::Abort("Invalid sensitive model in the dababase!",MOKKA_ERROR_BAD_DATABASE_PARAMETERS);
-    ChamberLog[db->fetchInt("layer_id")]->SetVisAttributes(VisAtt);
-  }
-   
-  // End Chamber Placements
-  // module x and y offsets (needed for the SD)
-  db->exec("select 0 AS module_x_offset, module_y_offset from barrel_module;");
-  db->getTuple();
-  double Xoff,Yoff;
-  Xoff = db->fetchDouble("module_x_offset");
-  Yoff = db->fetchDouble("module_y_offset");
-   
-  db->exec("select barrel_regular_layer.layer_id, 0. as chamber_x_offset,chamber_y_offset,chamber_z_offset as chamber_z_offset,chamber_dim_z/2 AS YHALF,chamber_dim_x/2. as XHALF from barrel_regular_layer,barrel_end_layer where barrel_regular_layer.layer_id = barrel_end_layer.layer_id;");
-   
-  while(db->getTuple()!=NULL){
-    G4int layer_id = db->fetchInt("layer_id");
-    new MyPlacement(0,
-		    G4ThreeVector(db->fetchDouble("chamber_x_offset"),
-				  db->fetchDouble("chamber_z_offset"),
-				  db->fetchDouble("chamber_y_offset")+
-				  chambers_y_off_correction),
-		    //!!attention!! y<->z
-		    ChamberLog [db->fetchInt("layer_id")],
-		    "ChamberBarrel",
-		    endBarrelVol,false,layer_id);
+    else    {
+      throw runtime_error("Unknown sensitive model:"+m_model+" for detector hcal04");
+    }
+    chamberVol.setVisAttributes(m_chamberVis);
+    pv = endBarrelVol.placeVolume(chamberVol,Position(0,elay.z_offset,blay.y_offset+chambers_y_off_correction));
+    pv.addPhysVolID("layer",layer_id);
   }
 
-
   //------------------------------------------------------------------------------------------------------
-  //   // Barrel End Module placements
-  db->exec("select stave_id,module_id,module_type,stave_phi_offset,inner_radius,module_z_offset from barrel,barrel_stave, barrel_module, barrel_modules where module_type = 2;");  // un module:  AND module_id = 1 AND stave_id = 1
-
-
-  // Take care of this return here: if is possible when building
-  // the Hcal prototype single module, where there isn't end modules
-  // at all !!!
-  if(db->getTuple()==NULL) return;
-
-  double Y;
-  Y = db->fetchDouble("inner_radius")+YZ1H+YZ2H;
-  G4int stave_inv [8] = {1,8,7,6,5,4,3,2};
-  do {
-    double phirot = db->fetchDouble("stave_phi_offset")*pi/180;
-    G4RotationMatrix *rot=new G4RotationMatrix();
-    double Z = db->fetchDouble("module_z_offset");
-    double Xplace = -Y*sin(phirot);
-    double Yplace = Y*cos(phirot);
-    G4int stave_number = db->fetchInt("stave_id");
-    rot->rotateX(pi*0.5); // on couche le module.
-
-    if(Z>0) {
-      rot->rotateZ(pi);
-      Xplace = - Xplace;
-      stave_number = stave_inv[stave_number-1];
+  // Barrel End Module placements
+  bool first = true;
+  double Y = m_barrel.inner_r+YZ1H+YZ2H;
+  int stave_inv [8] = {1,8,7,6,5,4,3,2};
+  for(Staves::const_iterator i=m_barrel.staves.begin(); i!=m_barrel.staves.end(); ++i) {
+    const Stave& s = *i;
+    DetElement stave_det(m_barrel,_toString(s.id,"end_stave%d"),s.id*10);
+    for(Modules::const_iterator j=m_barrel.modules.begin(); j!=m_barrel.modules.end(); ++j) {
+      const Module& m = *j;
+      if ( m.type == 2 )   {
+	int stave_id = m.z_offset>0 ? s.id : stave_inv[s.id-1];
+	Rotation rot(-M_PI/2,s.phi,(m.z_offset>0 ? M_PI : 0));
+	Position pos(0,Y,m.z_offset);
+	DetElement det_mod = first ? module : module.clone(_toString(m.id,"module%d"),m.id);
+	if (first) {
+	  first = false;
+	  module._data().id = m.id;
+	  module->SetName(_toString(m.id,"module%d").c_str());
+	}
+	pv = assembly.placeVolume(endBarrelVol,pos.rotateZ(/*m.z_offset>0?s.phi:- */s.phi),rot);
+	pv.addPhysVolID("module",HCALBARREL*100+stave_id*10+m.id);
+	stave_det.add(det_mod);
+	det_mod.setPlacement(pv);
+	//theBarrilEndSD->SetStaveRotationMatrix(stave_id,s.phi);
+	//theBarrilEndSD->SetModuleZOffset(m.id,m.z_offset);
+      }
     }
-    
-    rot->rotateY(phirot);
-    new MyPlacement(rot,
-		    G4ThreeVector(Xplace,
-				  Yplace,
-				  Z),
-		    EnvLogHcalModuleBarrel,
-		    "BarrelHcalModule",
-		    MotherLog,
-		    false,
-		    HCALBARREL*100+stave_number*10+db->fetchInt("module_id"));
-    theBarrilEndSD->SetStaveRotationMatrix(db->fetchInt("stave_id"),phirot);
-    theBarrilEndSD->
-      SetModuleZOffset(db->fetchInt("module_id"),
-		       db->fetchDouble("module_z_offset"));
-  } while(db->getTuple()!=NULL);
-#endif
+  }
 }
 
 /// Build EndCap Modules
 void Hcal04::buildEndcaps(Volume assembly) {
-
-
-#if 0
-  db->exec("select module_radius AS pRMax, module_dim_z/2. AS pDz, center_box_size/2. AS pRMin from endcap_standard_module;");
-  db->getTuple();
-
-  double zPlane[2];
-  zPlane[0]=-db->fetchDouble("pDz");
-  zPlane[1]=-zPlane[0];
-
-  double rInner[2],rOuter[2];
-  rInner[0]=rInner[1]=db->fetchDouble("pRMin");
-  rOuter[0]=rOuter[1]=db->fetchDouble("pRMax");
-  G4Polyhedra *EndCapSolid=
-    new G4Polyhedra("HcalEndCapSolid",
-		    0.,
-		    360.,
-		    32,
-		    2,
-		    zPlane,
-		    rInner,
-		    rOuter);
-		    
-
-  G4VisAttributes *VisAtt = new G4VisAttributes(G4Colour(.8,.8,.2));
-  VisAtt->SetForceWireframe(true);
-  VisAtt->SetDaughtersInvisible(true);
-  //VisAtt->SetForceSolid(true);
-
-  G4LogicalVolume* EndCapLogical =
-    new G4LogicalVolume(EndCapSolid,
-			RadiatorMaterial,
-			"EndCapLogical",
-			0, 0, 0);
-  EndCapLogical->SetVisAttributes(VisAtt);
+  int n_edges = 8;
+  DetElement       sdet("side_plus",HCALENDCAPPLUS);
+  PolyhedraRegular hedra(n_edges,m_endcap.rmin,m_endcap.rmax,m_endcap.dz*2);
+  Volume           modVolume("endcap",hedra,m_radiatorMat);
+  modVolume.setVisAttributes(m_endcapModuleVis);
+  modVolume.setVisAttributes(m_endModuleVis);
 
   // build and place the chambers in the Hcal Endcaps
-  EndcapChambers(EndCapLogical);
-
-  // Placements
-   
-  db->exec("select endcap_id,endcap_z_offset from endcap;");
-   
-  G4RotationMatrix *rotEffect=new G4RotationMatrix();
-  rotEffect->rotateZ(pi/8.);
-  G4int ModuleNumber = HCALENDCAPPLUS*100+16;
-  double Z1=0;
-  while(db->getTuple()!=NULL){    
-    Z1=db->fetchDouble("endcap_z_offset");
-    new MyPlacement(rotEffect,
-		    G4ThreeVector(0.,
-				  0.,
-				  Z1),
-		    EndCapLogical,
-		    "EndCapPhys",
-		    MotherLog,
-		    false,
-		    ModuleNumber);
-    rotEffect=new G4RotationMatrix();
-    rotEffect->rotateZ(pi/8.);
-    rotEffect->rotateY(pi); // On inverse les endcaps 
-    ModuleNumber -= (HCALENDCAPPLUS-HCALENDCAPMINUS)*100 + 6;
-  }
-  theENDCAPEndSD->
-    SetModuleZOffset(0,
-		     fabs(Z1));
-  theENDCAPEndSD->
-    SetModuleZOffset(6,
-		     fabs(Z1));
-#endif
-}
-#if 0
-void Hcal04::EndcapChambers(G4LogicalVolume* MotherLog)    {
-  // Chambers in the Hcal04::Endcaps
-  // standard endcap chamber solid:
-
-  db->exec("select chamber_radius AS pRMax, chamber_tickness/2. AS pDz, fiber_gap, center_box_size/2. AS pRMin from endcap_standard_module,hcal;");
-  db->getTuple();
-  
-  // G4Polyhedra Envelope parameters
-  G4int numSide = 32;
-  G4int numZPlanes = 2;
-
-  double zPlane[2];
-  zPlane[0]=-db->fetchDouble("pDz");
-  zPlane[1]=-zPlane[0];
-
-  double rInner[2],rOuter[2];
-  rInner[0]=rInner[1]=db->fetchDouble("pRMin");
-  rOuter[0]=rOuter[1]=db->fetchDouble("pRMax");
-
-  PolyHedraRegular hedra(2,endcap.rmin,endcap.rmax,endcap.z);
-		    
-  // G4UserLimits* pULimits=new G4UserLimits(theMaxStepAllowed);
-  // standard endcap chamber logical
-
-
-  G4LogicalVolume* EndCapChamberLogical=0;
-
-  if(SensitiveModel == "scintillator")    {
+  PolyhedraRegular chamberSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_endcap.chamber_thickness);
+  Volume chamberVol;
+  if(m_model == "scintillator")    {
     //fg: introduce (empty) fiber gap - should be filled with fibres and cables
-    Volume vol(
-    EndCapChamberLogical =
-      new G4LogicalVolume(EndCapChamberSolid,
-			  CGAGeometryManager::GetMaterial("air"), 
-			  "EndCapChamberLogical", 
-			  0, 0, 0);	   
-    double fiber_gap = db->fetchDouble("fiber_gap")  ;
-    double scintHalfWidth =  db->fetchDouble("pDz") - fiber_gap  / 2. ;
+    double scintHalfWidth = m_endcap.chamber_thickness - m_fiberGap/2;
+    double zplanes[2] = {-scintHalfWidth,scintHalfWidth};
 
     // fiber gap can't be larger than total chamber
     assert( scintHalfWidth > 0. ) ;
-	   
-    double zPlaneScint[2];
-    zPlaneScint[0]=-scintHalfWidth ;
-    zPlaneScint[1]=-zPlaneScint[0];
-    G4Polyhedra *EndCapScintSolid=new G4Polyhedra("EndCapScintSolid",
-						  phiStart,
-						  phiTotal,
-						  numSide,
-						  numZPlanes,
-						  zPlaneScint,
-						  rInner,
-						  rOuter);
-    G4LogicalVolume* ScintLog =
-      new G4LogicalVolume(EndCapScintSolid,
-			  CGAGeometryManager::GetMaterial("polystyrene"),
-			  "EndCapScintLogical", 
-			  0, 0, pULimits);  	   
+    chamberVol = Volume("chamber",chamberSolid,lcdd->air());
+    PolyhedraRegular scintSolid(n_edges,m_endcap.rmin,m_endcap.rmax,zplanes);
+    Volume           scintVol  ("scintillator",scintSolid,m_scintMaterial);
+    scintVol.setVisAttributes(m_scintVis);
     // only scinitllator is sensitive
-    ScintLog->SetSensitiveDetector(theENDCAPEndSD);
-    new MyPlacement(0, G4ThreeVector( 0,0,  - fiber_gap / 2.  ), ScintLog,
-		    "EndCapScintillator", EndCapChamberLogical, false, 0 );   
+    //ScintLog->SetSensitiveDetector(theENDCAPEndSD);
+    chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap));
   }
-  else     if (SensitiveModel == "RPC1")      {
-    EndCapChamberLogical =
-      BuildRPC1Polyhedra(EndCapChamberSolid,
-			 theENDCAPEndSD,
-			 phiStart,
-			 phiTotal,
-			 numSide,
-			 numZPlanes,
-			 zPlane,
-			 rInner,
-			 rOuter,
-			 pULimits);
+  else if (m_model == "RPC1")      {
+    chamberVol = Volume("rpc1",chamberSolid,m_rpc.radiator.material);
+    PolyhedraRegular glassSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_rpc.glass.thickness);
+    Volume           glassVol("glass",glassSolid,m_rpc.glass.material);
+    glassVol.setVisAttributes(m_rpc.glass.vis);
+
+    // build the gas gap
+    PolyhedraRegular gasSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_rpc.gas.thickness);
+    Volume           gasVol("gas",gasSolid,m_rpc.gas.material);
+    gasVol.setVisAttributes(m_rpc.gas.vis);
+    gasVol.setSensitiveDetector(m_endcap.sensDet);
+    gasVol.setLimitSet(m_limits);
+
+    // placing the all. 
+    // Z offset starts pointing to the chamber border.
+    double z_offset = m_endcap.dz;
+    // first glass after the g10_thickness
+    z_offset += m_rpc.radiator.thickness + m_rpc.glass.thickness/2.;
+    chamberVol.placeVolume(glassVol,Position(0,0,z_offset));
+    // set Z offset to the next first glass border
+    z_offset += m_rpc.glass.thickness/2;      
+    // gas gap placing 
+    z_offset += m_rpc.gas.thickness/2;
+    chamberVol.placeVolume(gasVol,Position(0,0,z_offset));
+    // set ZOffset to the next gas gap border
+    z_offset += m_rpc.gas.thickness/2;
+    // second glass, after the g10_thickness, the first glass and the gas gap.
+    z_offset += m_rpc.glass.thickness/2;
+    chamberVol.placeVolume(glassVol,Position(0,0,z_offset));
   }
-  else Control::Abort("Invalid sensitive model in the dababase!",MOKKA_ERROR_BAD_DATABASE_PARAMETERS);
-  
-  G4VisAttributes *VisAtt = new G4VisAttributes(G4Colour(1.,1.,1.));
-  EndCapChamberLogical->SetVisAttributes(VisAtt);
-
-
+  else  {
+    throw runtime_error("Invalid sensitive model in the dababase for "+name+"!");
+  }
+  PlacedVolume pv;
+  chamberVol.setVisAttributes(m_chamberVis);
   // standard endcap chamber placements
-  db->exec("select layer_id,chamber_z_offset AS Zoff from endcap_layer;");
-  
-  G4int layer_id;
-  while(db->getTuple()!=NULL){
-    layer_id=db->fetchInt("layer_id");
-    new MyPlacement(0,
-		    G4ThreeVector(0.,
-				  0.,
-				  db->fetchDouble("Zoff")),
-		    EndCapChamberLogical,
-		    "EndCapChamberPhys",
-		    MotherLog,false,layer_id);
-  }  
-}
-
-
-Volume Hcal04::buildRPC1Polyhedra(G4Polyhedra* ChamberSolid, 
-				  SD* theSD,
-				  double phiStart,
-				  double phiTotal,
-				  G4int numSide,
-				  G4int numZPlanes,
-				  const double zPlane[],
-				  const double rInner[],
-				  const double rOuter[],
-				  G4UserLimits* pULimits)
-{
-  // fill the Chamber Envelope with G10
-  G4LogicalVolume *ChamberLog =
-    new G4LogicalVolume(ChamberSolid,
-			CGAGeometryManager::GetMaterial("g10"),
-			"RPC1", 0, 0, 0);
-  //
-  // build the RPC glass 
-  double NewZPlane[2];
-  NewZPlane[0] = glass_thickness/2.;
-  NewZPlane[1] = -NewZPlane[0];
-  G4Polyhedra * GlassSolid =
-    new G4Polyhedra("RPC1Glass", 
-		    phiStart,
-		    phiTotal,
-		    numSide,
-		    numZPlanes,
-		    NewZPlane,
-		    rInner,
-		    rOuter);	
-      
-  G4LogicalVolume *GlassLogical =
-    new G4LogicalVolume(GlassSolid,
-			CGAGeometryManager::GetMaterial("pyrex"),
-			"RPC1glass", 
-			0, 0, 0);
-      
-  G4VisAttributes * VisAtt = new G4VisAttributes(G4Colour(.8,0,.2));
-  VisAtt->SetForceWireframe(true);
-  GlassLogical->SetVisAttributes(VisAtt);
-
-  // build the gas gap
-  NewZPlane[0] = gas_thickness/2.;
-  NewZPlane[1] = -NewZPlane[0];
-  G4Polyhedra * GasSolid = new G4Polyhedra("RPC1Gas", 
-					   phiStart,
-					   phiTotal,
-					   numSide,
-					   numZPlanes,
-					   NewZPlane,
-					   rInner,
-					   rOuter);
-      
-  G4LogicalVolume *GasLogical =
-    new G4LogicalVolume(GasSolid,CGAGeometryManager::GetMaterial("RPCGAS1"),
-			"RPC1gas",0, 0, pULimits);
-      
-  VisAtt = new G4VisAttributes(G4Colour(.1,0,.8));
-  VisAtt->SetForceWireframe(true);
-  //VisAtt->SetForceSolid(true);
-  GasLogical->SetVisAttributes(VisAtt);
+  for(Layers::const_iterator i=m_endcap.layers.begin(); i != m_endcap.layers.end(); ++i)  {
+    const Layer& layer = *i;
+    DetElement det_layer(sdet,_toString(layer.id,"layer%d"),layer.id);
+    pv = modVolume.placeVolume(chamberVol,Position(0,0,layer.values.endcap_layer.z_offset));
+    pv.addPhysVolID("layer",layer.id);
+    det_layer.setPlacement(pv);
+  }
 
-  // PLugs the sensitive detector HERE!
-  GasLogical->SetSensitiveDetector(theSD);
-  // placing the all. 
-  // ZOffset starts pointing to the chamber border.
-  double ZOffset = zPlane[0];
-      
-  // first glass after the g10_thickness
-  ZOffset += rpc.g10_thickness + glass_thickness/2.;
-  new MyPlacement(0,
-		  G4ThreeVector(0,0,ZOffset),
-		  GlassLogical,
-		  "RPCGlass",
-		  ChamberLog,
-		  false,
-		  0);
-      
-  // set ZOffset to the next first glass border
-  ZOffset += glass_thickness/2.;
-      
-  // gas gap placing 
-  ZOffset += gas_thickness/2.; // center !
-  new MyPlacement(0,
-		  G4ThreeVector(0,0,ZOffset),
-		  GasLogical,
-		  "RPCGas",
-		  ChamberLog,
-		  false,
-		  0);
-
-  // set ZOffset to the next gas gap border
-  ZOffset += gas_thickness/2.;
-      
-  // second glass, after the g10_thickness, the first glass
-  // and the gas gap.
-  ZOffset += glass_thickness/2.; // center !
-  new MyPlacement(0,
-		  G4ThreeVector(0,0,ZOffset),
-		  GlassLogical,
-		  "RPCGlass",
-		  ChamberLog,
-		  false,
-		  0);
-  return ChamberLog;      
+  // Now place the endcaps
+  pv = assembly.placeVolume(modVolume,m_endcap.side[SIDE_PLUS].position,Rotation(0,M_PI/8,0));
+  pv.addPhysVolID("module",HCALENDCAPPLUS*100+16);
+  sdet.setPlacement(pv);
+  self.add(sdet);
+  m_endcap.side[SIDE_PLUS] = sdet;
+
+  pv = assembly.placeVolume(modVolume,m_endcap.side[SIDE_MINUS].position,Rotation(M_PI,M_PI/8,M_PI));
+  pv.addPhysVolID("module",HCALENDCAPMINUS*100+16);
+  sdet = sdet.clone("endcap_minus",HCALENDCAPMINUS);
+  self.add(sdet);
+  sdet.setPlacement(pv);
+  m_endcap.side[SIDE_MINUS] = sdet;
+
+  //theENDCAPEndSD->SetModuleZOffset(0,fabs(Z1));
+  //theENDCAPEndSD->SetModuleZOffset(6,fabs(Z1));
 }
-#endif
 
 /// Build Box with RPC1 chamber
-Volume Hcal04::buildRPC1Box(const string& nam, Box box, const Layer& layer)   {
-  //		     SD* theSD, 
-  //		     G4UserLimits* pULimits)
+Volume Hcal04::buildRPC1Box(const string& nam, Box box, const Layer& layer, SensitiveDetector& sensdet)   {
   Material g10_mat = lcdd->material("G10");
 
   // fill the Chamber Envelope with G10
   Volume chamberVol(nam+"_rpc",box,g10_mat);
 	     
   // build the RPC glass !!attention!! y<->z
-  Box    glassBox(box.x(),box.y(),rpc.glass_thickness/2.0);
+  Box    glassBox(box.x(),box.y(),m_rpc.glass.thickness/2.0);
   Volume glassVol(nam+"_RPC_glass",glassBox,lcdd->material("pyrex"));
   glassVol.setVisAttributes(lcdd->visAttributes("HcalRpcGlassVis"));
 
   // build the standard spacer !!attention!! y<->z
-  Box    spacerBox(box.x(),rpc.spacer_thickness/2,rpc.gas_thickness/2);
+  Box    spacerBox(box.x(),m_rpc.spacer.thickness/2,m_rpc.gas.thickness/2);
   Volume spacerVol(nam+"_spacer",spacerBox,g10_mat);
   spacerVol.setVisAttributes(lcdd->visAttributes("HcalRpcSpacerVis"));
 
-  Box    gasBox(box.x(),box.y(),rpc.gas_thickness/2.0);
+  Box    gasBox(box.x(),box.y(),m_rpc.gas.thickness/2.0);
   Volume gasVol(nam+"_RPC_gas",glassBox,lcdd->material("RPCGAS1"));
   gasVol.setVisAttributes(lcdd->visAttributes("HcalRpcGasVis"));
+  gasVol.setSensitiveDetector(sensdet);
+  gasVol.setLimitSet(m_limits);
 
   // PLugs the sensitive detector HERE!
   // gasVol->SetSensitiveDetector(theSD);
       
   // placing the spacers inside the gas gap
-  double MaxY = box.y()-rpc.spacer_thickness/2;
-  for(double ypos=-box.y() + rpc.spacer_thickness/2; ypos < MaxY; ypos += rpc.spacer_gap)
+  double MaxY = box.y()-m_rpc.spacer.thickness/2;
+  for(double ypos=-box.y() + m_rpc.spacer.thickness/2; ypos < MaxY; ypos += m_rpc.spacer.gap)
     gasVol.placeVolume(spacerVol,Position(0,ypos,0));
 
   // placing the all. ZOffset starts pointing to the chamber border.
   double zpos = -box.z();
-
   // first glass border after the g10_thickness
-  zpos += rpc.g10_thickness + rpc.glass_thickness/2.;
+  zpos += m_rpc.radiator.thickness + m_rpc.glass.thickness/2.;
   chamberVol.placeVolume(glassVol,Position(0,0,zpos));
 
   // set zpos to the next first glass border + gas gap placing 
-  zpos += rpc.glass_thickness/2. + rpc.gas_thickness/2.;
+  zpos += m_rpc.glass.thickness/2. + m_rpc.gas.thickness/2.;
   PlacedVolume pv  = chamberVol.placeVolume(gasVol,Position(0,0,zpos));
   pv.addPhysVolID("layer",layer.id);
 
   // set zpos to the next gas gap border + second glass
-  zpos += rpc.gas_thickness/2. + rpc.glass_thickness/2.;
+  zpos += m_rpc.gas.thickness/2. + m_rpc.glass.thickness/2.;
   pv  = chamberVol.placeVolume(glassVol,Position(0,0,zpos));
   return chamberVol;
 }
 
-static Ref_t create(LCDD& lcdd, const xml_h& element, SensitiveDetector& sens)  {
-  DetElement  sdet;
-  xml_det_t   x_det = element;
-  Value<TNamed,Hcal04>* ptr = new Value<TNamed,Hcal04>();
-  sdet.assign(ptr,x_det.nameStr(),x_det.typeStr());
-  ptr->construct(lcdd,element,sens);
-  return sdet;
+static Ref_t create_detector(LCDD& lcdd, const xml_h& element)  {
+  return (new Value<TNamed,Hcal04>())->construct(lcdd,element);
 }
-DECLARE_DETELEMENT(Tesla_hcal04,create);
+DECLARE_SUBDETECTOR(Tesla_hcal04,create_detector);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
index 161ace0fbab6fb6362455220b2f6f309936f616d..9d76987fe2bc8a5de92994bbad4b4d536e86edd8 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
@@ -13,12 +13,12 @@ using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)  {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&)  {
   xml_det_t   x_det  = e;
   string      name   = x_det.nameStr();
   Rotation    reflect_rot(M_PI,0,0);
   DetElement  sdet(name,x_det.id());
-  Assembly    maskVol(name+"_assembly");
+  Assembly    maskVol(name);
   Volume      motherVol = lcdd.pickMotherVolume(sdet);
   xml_comp_t  x_masks = x_det.child(Unicode("masks"));
   xml_comp_t  x_quad  = x_det.child(Unicode("quadrupole"));
@@ -34,7 +34,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     z0 = (z1+z2)/2.0;
 
     Tube   tub(rmin,rmax,dz);
-    Volume vol(name+_toString(id,"_mask%d"),tub,lcdd.material(x_m.materialStr()));
+    Volume vol(_toString(id,"_mask%d"),tub,lcdd.material(x_m.materialStr()));
     vol.setVisAttributes(lcdd.visAttributes(x_m.visStr()));
     pv = maskVol.placeVolume(vol,Position(0,0,z0));
     pv.addPhysVolID("mask",id);
@@ -52,19 +52,20 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     Tube  iron(x_yoke.rmin(),x_yoke.rmax(),yoke_dz);
     Tube  cave(x_coil.rmin(),x_coil.rmax(),coil_dz+10.0);
     SubtractionSolid yoke(iron,cave,Position(0,0,coil_pos - yoke_pos + 10.),Rotation());
-    Volume vol(name+"_yoke",yoke,lcdd.material(x_yoke.materialStr()));
+    Volume vol("yoke",yoke,lcdd.material(x_yoke.materialStr()));
     vol.setVisAttributes(lcdd.visAttributes(x_yoke.visStr()));
     maskVol.placeVolume(vol,Position(0,0, yoke_pos));
     maskVol.placeVolume(vol,Position(0,0,-yoke_pos),reflect_rot);
   }
   {  // Place coil
     Tube   tub(x_coil.rmin(),x_coil.rmax(),coil_dz);
-    Volume vol(name+"_coil",tub,lcdd.material(x_coil.materialStr()));
+    Volume vol("coil",tub,lcdd.material(x_coil.materialStr()));
     vol.setVisAttributes(lcdd.visAttributes(x_coil.visStr()));
     maskVol.placeVolume(vol,Position(0,0, coil_pos));
     maskVol.placeVolume(vol,Position(0,0,-coil_pos),reflect_rot);
   }
-  motherVol.placeVolume(maskVol);
+  pv = motherVol.placeVolume(maskVol);
+  sdet.setPlacement(pv);
   return sdet;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
index 29f3388f9aa93a57525ce2869e8024312fb18656..a7f4f6e35235aac6984bd76b1dbbc411c5815a3d 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
@@ -14,21 +14,27 @@ using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
 static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)  {
-  xml_det_t   x_det  = e;
-  string      name   = x_det.nameStr();
-  DetElement  sdet(name,x_det.id());
-  Assembly    sitVol(name+"_assembly");
-  Volume      motherVol   = lcdd.pickMotherVolume(sdet);
+  xml_det_t    x_det  = e;
+  string       name   = x_det.nameStr();
+  DetElement   sdet(name,x_det.id());
+  Assembly     sitVol(name+"_assembly");
+  Volume       motherVol   = lcdd.pickMotherVolume(sdet);
+  PlacedVolume pv;
 
   for(xml_coll_t c(x_det,Unicode("layer")); c; ++c)  {
     xml_comp_t x_layer = c;
     double zhalf = x_layer.zhalf();
+    string layer_nam = _toString(x_layer.id(),"_layer%d");
+    DetElement layer_det(sdet,layer_nam,x_layer.id());
     Tube   tub(x_layer.inner_r(),x_layer.inner_r()+x_layer.thickness(),zhalf);
-    Volume vol(name+_toString(x_layer.id(),"_layer%d"),tub,lcdd.material(x_layer.materialStr()));
+    Volume vol(layer_nam,tub,lcdd.material(x_layer.materialStr()));
     vol.setVisAttributes(lcdd.visAttributes(x_layer.visStr()));
-    sitVol.placeVolume(vol);
+    vol.setSensitiveDetector(sens);
+    pv = sitVol.placeVolume(vol);
+    layer_det.setPlacement(pv);
   }
-  motherVol.placeVolume(sitVol);
+  pv = motherVol.placeVolume(sitVol);
+  sdet.setPlacement(pv);
   return sdet;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
index c011d1ea691ad18b43c83dd59255b0958e290929..55347be4d0d7b5af147526a77e13cff2a04804f8 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
@@ -13,7 +13,7 @@ using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
 
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_det)  {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e)  {
   xml_det_t   x_det  = e;
   string      name   = x_det.nameStr();
   DetElement  sdet(name,x_det.id());
@@ -25,6 +25,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
   xml_comp_t  x_sens      = x_det.child(Unicode("sensitive"));
   xml_comp_t  x_fch       = x_det.child(Unicode("fch"));
   Material    gasMat      = lcdd.material(x_sens.materialStr());
+  PlacedVolume pv;
 
   struct cylinder_t { double inner, outer, zhalf; };
   cylinder_t env  = { x_envelope.inner_r(),  x_envelope.outer_r(),  x_envelope.zhalf() };
@@ -32,6 +33,13 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
   cylinder_t fch  = { x_fch.inner_r(),       x_fch.outer_r(),       x_fch.thickness()/2.0 };
   cylinder_t sens = { x_sens.inner_r(),      x_sens.outer_r(), 0.0 };
 
+  // TPC sensitive detector
+  SensitiveDetector sens_det("TPC");
+  Readout ro = lcdd.readout(x_sens.readoutStr());
+  sens_det.setHitsCollection(ro.name());
+  sens_det.setReadout(ro);
+  lcdd.addSensitiveDetector(sens_det);
+
   // the TPC mother volume
   Tube    envTub(env.inner,env.outer,env.zhalf);
   Volume  envVol(name+"_envelope",envTub,lcdd.air());
@@ -61,8 +69,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
     double lay_thick = (sens.outer-sens.inner)/num_layer;
     Tube   layerTub(sens.inner+i*lay_thick,sens.inner+(i+1)*lay_thick,env.zhalf);
     Volume layerVol(name+_toString(i,"_layer%d"),layerTub,gasMat);      
+    layerVol.setSensitiveDetector(sens_det);
     layerVol.setVisAttributes(layerVis);
-    //TPCChamberLogical->SetSensitiveDetector(theTPCSD);
     envVol.placeVolume(layerVol);
   }
 
@@ -82,18 +90,22 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
 
   // FCH = two sensitive twin Si plates, just to register the particle step inside it.
   // Threshold is 20% of a MIP. For Si we have 0.34 KeV/micron as MIP.
+  SensitiveDetector fchSD("TPCfch");
+  ro = lcdd.readout(x_fch.readoutStr());
+  fchSD.setHitsCollection(ro.name());
+  fchSD.setReadout(ro);
+  lcdd.addSensitiveDetector(fchSD);
+
   Tube   fchTub(fch.inner,fch.outer,fch.zhalf);
-  Volume fchVol(name+"_fch",fchTub,lcdd.material(x_fch.materialStr()));
+  Volume fchVol("fch",fchTub,lcdd.material(x_fch.materialStr()));
   fchVol.setVisAttributes(lcdd.visAttributes(x_fch.visStr()));
+  fchVol.setSensitiveDetector(fchSD);
   envVol.placeVolume(fchVol,Position(0,0,  env.zhalf+wall.zhalf+fch.zhalf));
   envVol.placeVolume(fchVol,Position(0,0,-(env.zhalf+wall.zhalf+fch.zhalf)));
 
-  // FCH Sensitive detector
-  //theFCHSD = new TRKSD00("FCH", fch_thickness * mm * 340 * keV * 0.2);
-  //FCHLogical->SetSensitiveDetector(theFCHSD);
-
-  motherVol.placeVolume(envVol);
+  pv = motherVol.placeVolume(envVol);
+  sdet.setPlacement(pv);
   return sdet;
 }
 
-DECLARE_DETELEMENT(Tesla_tpc02,create_element);
+DECLARE_SUBDETECTOR(Tesla_tpc02,create_element);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
index bc84d0771a6cf5224ba04934af0fbd55963e3350..eb7fe41c7c5c6daa07d32b0f430111c0631194f7 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
@@ -12,8 +12,9 @@
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
+#define _U(text)  Unicode(#text)
 
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)  {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&)  {
   struct Tube_Desc {  double zhalf, thickness, radius;  };
   struct Cone_Desc {  double z, rmin, rmax; };
 
@@ -21,12 +22,12 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   string      name   = x_det.nameStr();
   Rotation    reflect_rot(M_PI,0,0);
   DetElement  beampipe(name,x_det.id());
-  Assembly    beampipeVol(name+"_assembly");
+  Assembly    beampipeVol("assembly");
   Volume      motherVol   = lcdd.pickMotherVolume(beampipe);
-  xml_comp_t  x_central   = x_det.child(Unicode("central_tube"));
-  xml_comp_t  x_lateral   = x_det.child(Unicode("lateral_tubes"));
-  xml_comp_t  x_ends      = x_det.child(Unicode("ends"));
-  xml_comp_t  x_vacuum    = x_det.child(Unicode("vacuum"));
+  xml_comp_t  x_central   = x_det.child(_U(central_tube));
+  xml_comp_t  x_lateral   = x_det.child(_U(lateral_tubes));
+  xml_comp_t  x_ends      = x_det.child(_U(ends));
+  xml_comp_t  x_vacuum    = x_det.child(_U(vacuum));
   Material    beampipeMat = lcdd.material(xml_comp_t(x_det).materialStr());
   Material    ironMat     = lcdd.material("Iron");
   Material    vacuumMat   = lcdd.vacuum();
@@ -34,8 +35,9 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   VisAttr     beampipeVis = lcdd.visAttributes(x_det.visStr());
   VisAttr     vacuumVis   = lcdd.visAttributes(x_vacuum.visStr());
   VisAttr     endVis      = lcdd.visAttributes(x_ends.visStr());
-  Tube_Desc   central     = {x_central.zhalf(), x_central.thickness(), x_central.inner_r()};
-  Tube_Desc   lateral     = {x_lateral.zmin(),x_lateral.thickness(),x_lateral.inner_r()};
+  Tube_Desc   central     = {x_central.zhalf(),x_central.thickness(),x_central.inner_r()};
+  Tube_Desc   lateral     = {x_lateral.zmin(), x_lateral.thickness(),x_lateral.inner_r()};
+  PlacedVolume pv;
 
   { // beam vacuum inside the tube  
     Tube   tube(0,central.radius,central.zhalf);
@@ -45,7 +47,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   }
   { // Be tube
     Tube   tube(central.radius,central.radius+central.thickness,central.zhalf);
-    Volume vol (name+"_BeTube",tube,beampipeMat);
+    Volume vol (name+"_Be_tube",tube,beampipeMat);
     vol.setVisAttributes(beampipeVis);
     beampipeVol.placeVolume(vol);
   }
@@ -83,7 +85,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   double z_tube = (end_zmin + inner_zmin)/2.0;
   { // inner beam vacuum lateral tubes
     Tube   tube(0,lateral.radius,inner_zhalf);
-    Volume vol (name+"_lat_vacuum",tube,vacuumMat);
+    Volume vol (name+"_lateral_vacuum",tube,vacuumMat);
     vol.setVisAttributes(vacuumVis);
     beampipeVol.placeVolume(vol,Position(0,0, z_tube));
     beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
@@ -91,17 +93,17 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
 
   { // inner Be lateral tubes
     Tube   tube(lateral.radius,lateral.radius+lateral.thickness,inner_zhalf);
-    Volume vol (name+"_lat_BeTube",tube, beampipeMat);
+    Volume vol (name+"_lateral_BeTube",tube, beampipeMat);
     vol.setVisAttributes(beampipeVis);
     beampipeVol.placeVolume(vol,Position(0,0, z_tube));
     beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
   }
 
   { // VXD strip lines on lateral tubes
-    xml_comp_t s = x_det.child(Unicode("strips"));
+    xml_comp_t s = x_det.child(_U(strips));
     Tube  tube(lateral.radius+lateral.thickness+s.gap(),
                lateral.radius+lateral.thickness+s.gap()+s.thickness(),inner_zhalf);
-    Volume vol(name+"_lat_Strips",tube,lcdd.material(s.materialStr()));
+    Volume vol(name+"_lateral_Strips",tube,lcdd.material(s.materialStr()));
     vol.setVisAttributes(lcdd.visAttributes(s.visStr()));
     beampipeVol.placeVolume(vol,Position(0,0, z_tube));
     beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
@@ -110,11 +112,11 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   // ends lateral cones and tubes
   size_t cnt = 0;
   Cone_Desc cones[5];
-  for(xml_coll_t c(x_det,Unicode("cone")); c; ++c, ++cnt)  {
+  for(xml_coll_t c(x_lateral,_U(cone)); c; ++c, ++cnt)  {
     xml_comp_t x_con = c;
-    cones[cnt].z = x_con.z();
-    cones[cnt].rmin = x_con.rmin();
-    cones[cnt].rmax = x_con.rmax();
+    cones[cnt].z     = x_con.z();
+    cones[cnt].rmin  = x_con.rmin();
+    cones[cnt].rmax  = x_con.rmax();
   }
   { // vacuum lateral cone
     double dz = (x_lateral.dz() - end_thickness)/2.0;
@@ -126,7 +128,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
 
     Cone   fe_end_cone (dz,lateral.radius,lateral.radius+end_thickness,
 			cones[0].rmin,cones[0].rmin+end_thickness);
-    Volume fe_end_vol( name+"_lat_fe",fe_end_cone,ironMat);
+    Volume fe_end_vol(name+"_lateral_fe",fe_end_cone,ironMat);
     fe_end_vol.setVisAttributes(endVis);
 
     // put vacuum and iron cones into world
@@ -140,7 +142,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     neg.z = -(pos.z = z_cone+dz);
     for(int i=0; i<5; ++i )  {
       Tube   vac_tub(0, cones[i].rmin, cones[i].z);
-      Volume vac_vol(name+_toString(i,"_vac_%d"),vac_tub,vacuumMat);
+      Volume vac_vol(_toString(i,"vac_%d"),vac_tub,vacuumMat);
       vac_vol.setVisAttributes(vacuumVis);
       // Update Z-placement
       neg.z = -(pos.z += cones[i].z);
@@ -148,7 +150,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
       beampipeVol.placeVolume(vac_vol,neg);
 
       Tube   fe_tub (cones[i].rmin, cones[i].rmax, cones[i].z);
-      Volume fe_vol (name+_toString(i,"_fe_%d"),fe_tub,ironMat);
+      Volume fe_vol (name+_toString(i,"_feTube%d"),fe_tub,ironMat);
       fe_vol.setVisAttributes(endVis);
       beampipeVol.placeVolume(fe_vol,pos);
       beampipeVol.placeVolume(fe_vol,neg);
@@ -156,7 +158,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
       neg.z = -(pos.z += cones[i].z);
     }
   }     
-  motherVol.placeVolume(beampipeVol);
+  pv = motherVol.placeVolume(beampipeVol);
+  beampipe.setPlacement(pv);
   return beampipe;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
index 12253bb2052f94d8d15337b820d1bb75201ce28b..be9b8cce3f7b26160d7c5da0ccbc720ddfe2f9b4 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
@@ -1,339 +1,74 @@
-#if 0
-  G4double crossingAngle = theGeometryEnvironment.GetParameterAsDouble("TUBE_crossing_angle");
-  G4double z_begin = theGeometryEnvironment.GetParameterAsDouble("Lcal_z_begin");
-  G4double   r_max = theGeometryEnvironment.GetParameterAsDouble("Lcal_outer_radius");
-  G4double   r_min = theGeometryEnvironment.GetParameterAsDouble("Lcal_inner_radius");
-  G4int    n_layer = theGeometryEnvironment.GetParameterAsInt("Lcal_n_layers");
-  G4double tungsten_thickness= theGeometryEnvironment.GetParameterAsDouble("Lcal_tungsten_thickness");
-  G4double support_thickness = theGeometryEnvironment.GetParameterAsDouble("Lcal_support_thickness");
-  G4double silicon_thickness = theGeometryEnvironment.GetParameterAsDouble("Lcal_silicon_thickness");
-  G4double layer_gap = theGeometryEnvironment.GetParameterAsDouble("Lcal_layer_gap");
-  G4double z_end = z_begin + (tungsten_thickness + support_thickness + silicon_thickness + layer_gap)*(double)n_layer;
-
-  G4double alpha = crossingAngle / 2.* mrad;
-  G4double width = z_end - z_begin;
-
-  G4double r_inner_min = (width + z_begin * cos(alpha )) * tan(2.*alpha);
-  G4double lcal_rot_extra_r = width * sin(alpha);
-  G4double lcal_rot_extra_z = r_max * sin(alpha);
-  G4double opening_angle = r_max/z_end;
-  actual_opening_angle = opening_angle;
-
-  //save for lcal
-  //check if inner radius change is needed
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_back\";");
-  dbtmp->getTuple();
-  G4double r = dbtmp->fetchDouble("rInnerStart");
-
-  if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
-  {
-	r = r_min - 0.5 - lcal_rot_extra_r;
-	G4cout << "   ...change r_min of tube (lcal rotation) r = " << r << G4endl;
-  }
-
-  if (dbtmp->fetchDouble("zEnd") * tan(alpha) > r)
-  {
-    r_min = r_inner_min;
-    G4cout << "    ...change r_min of lcal (lateral tubes crossAngle) r = " << r_min << G4endl; 
-  }
-
-//save for lcal
-  actual_lcal_rin = r_min;
-
-  G4double vxd_r = theGeometryEnvironment.GetParameterAsDouble("VXD_inner_radius");
-  G4double thickness;
-
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"ip_inner_parallel\";");
-  dbtmp->getTuple();
-  thickness = dbtmp->fetchDouble("rOuterStart") - dbtmp->fetchDouble("rInnerStart");
-
-  //ip_inner_parallel 0.5mm gap between pipe and vxd
-  dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str(vxd_r - 0.5) + " WHERE name = \"ip_inner_parallel\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(vxd_r - 0.5) + " WHERE name = \"ip_inner_parallel\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(vxd_r - 0.5 - thickness) + " WHERE name = \"ip_inner_parallel\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(vxd_r - 0.5 - thickness) + " WHERE name = \"ip_inner_parallel\";").data() );
-
-
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_front\";");
-  dbtmp->getTuple();
-  width = dbtmp->fetchDouble("zEnd") - dbtmp->fetchDouble("zStart");
-  r = dbtmp->fetchDouble("rInnerStart");
-
-  //ip_outer_bulge
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"ip_outer_bulge\";");
-  dbtmp->getTuple();
-  thickness = dbtmp->fetchDouble("rOuterEnd") - dbtmp->fetchDouble("rInnerEnd");
-
-  dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str(z_begin - width - lcal_rot_extra_z) + " WHERE name = \"ip_outer_bulge\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(r_max) + " WHERE name = \"ip_outer_bulge\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_max - thickness) + " WHERE name = \"ip_outer_bulge\";").data() );
-
-  //lumcal_front
-  //0.5 cm gap between lcal and tube ?
-
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_front\";");
-  dbtmp->getTuple();
-  r = dbtmp->fetchDouble("rInnerStart");
-
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_wall\";");
-  dbtmp->getTuple();
-  thickness = dbtmp->fetchDouble("rOuterEnd") - dbtmp->fetchDouble("rInnerEnd");
-
-  G4cout << "lumcal_wall thickness = " << thickness << G4endl;
-
-  dbtmp->exec( ("UPDATE tube SET zStart = " + double2str(z_begin - width - lcal_rot_extra_z) + " WHERE name = \"lumcal_front\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str(z_begin - lcal_rot_extra_z) + " WHERE name = \"lumcal_front\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str(r_max) + " WHERE name = \"lumcal_front\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(r_max) + " WHERE name = \"lumcal_front\";").data() );
-
-  if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
-  {
-    dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_front\";").data() );
-
-    dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_front\";").data() );
-  }
-
-  //lumcal_wall
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_wall\";");
-  dbtmp->getTuple();
-  r = dbtmp->fetchDouble("rOuterStart");
-
-  dbtmp->exec( ("UPDATE tube SET zStart = " + double2str(z_begin - lcal_rot_extra_z) + " WHERE name = \"lumcal_wall\";").data() );
-
-  dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str( z_end + lcal_rot_extra_z) + " WHERE name = \"lumcal_wall\";").data() );
-
-  if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
-  {
-    dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str( r_min - 0.5 - lcal_rot_extra_r ) + " WHERE name = \"lumcal_wall\";").data() );
-
-    dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str( r_min - 0.5 - lcal_rot_extra_r ) + " WHERE name = \"lumcal_wall\";").data() );
-
-    dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_wall\";").data() );
-
-    dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_wall\";").data() );
-  }
-
-  //lumcal_back
-  dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_back\";");
-  dbtmp->getTuple();
-  r = dbtmp->fetchDouble("rInnerStart");
-
-  dbtmp->exec( ("UPDATE tube SET zStart = " + double2str( z_end + lcal_rot_extra_z) + " WHERE name = \"lumcal_back\";").data() );
-
-  if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
-  {
-    dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_back\";").data() );
-
-    dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_back\";").data() );
-  }
-
-  return true;
-}
-
-G4bool STubeX00::PostLoadScriptAction(Database*  dbtmp, CGAGeometryEnvironment& )
-{
-  G4cout << "STubeX00 set the following geomerty parameters : " << endl;
-  dbtmp->exec("SELECT * FROM tube;");
-  while (dbtmp->getTuple())
-  {
-	G4cout << " " << dbtmp->fetchString("name") << " :  rIn1 = " << dbtmp->fetchDouble("rInnerStart");
-	G4cout << " rOut1 = " << dbtmp->fetchDouble("rOuterStart") << " rIn2 = " << dbtmp->fetchDouble("rInnerEnd");
-	G4cout << " rOut2 = " << dbtmp->fetchDouble("rOuterEnd") << " zStart = " << dbtmp->fetchDouble("zStart");
-	G4cout << " zEnd = " << dbtmp->fetchDouble("zEnd") << endl;
-  }
-
-//pass the opening angle to others
-  (*Control::globalModelParameters)["TUBE_opening_angle"] = double2str(actual_opening_angle);
-
-//pass updated lcal rin
-  (*Control::globalModelParameters)["Lcal_inner_radius"] = double2str(actual_lcal_rin);
-
-  G4cout << "STubeX00 PostLoadScriptAction set opening angle "
-	 << actual_opening_angle << G4endl;
-
-  G4cout << "STubeX00 PostLoadScriptAction set LCAL rIn "
-	 << actual_lcal_rin << G4endl;
-
-  return true;    
-}
-
-
-
-
-// *********************************************************
-// *                         Mokka                         *
-// *    -- A Detailed Geant 4 Simulation for the ILC --    *
-// *                                                       *
-// *  polywww.in2p3.fr/geant4/tesla/www/mokka/mokka.html   *
-// *********************************************************
+// $Id:$
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
 //
-// $Id: TubeX01.cc,v 1.5 2008/10/15 16:51:53 steve Exp $
-// $Name: mokka-07-00 $
+//  Author     : M.Frank
 //
-// History:
-// - first implementation as Tube00: Paulo Mora de Freitas, Sep 2002
-// - modified from Tube00 to Tube01DT: Ties Behnke, 2003-02-11
-// - modified for a crossing angle as TubeX00: Adrian Vogel, 2005-05-18
-// - modified for fancier geometries as TubeX01: Adrian Vogel, 2006-04-20
-
-#include "TubeX01.hh"
-#include "MySQLWrapper.hh"
-#include "CGAGeometryManager.hh"
-#include "CGAGeometryEnvironment.hh"
-#include "CGADefs.h"
-#include "Control.hh"
-
-#include "globals.hh"
-#include "G4ThreeVector.hh"
-#include "G4RotationMatrix.hh"
-#include "G4Transform3D.hh"
-
-#include "G4VisAttributes.hh"
-#include "G4Material.hh"
-#include "G4Cons.hh"
-#include "G4Tubs.hh"
-#include "G4SubtractionSolid.hh"
-#include "G4LogicalVolume.hh"
-#include "G4PVPlacement.hh"
-
-#ifdef MOKKA_GEAR
-#include "gearimpl/GearParametersImpl.h"
-#include "MokkaGear.h"
-#include "G4EmCalculator.hh"
-#include "G4ParticleTable.hh"
-#endif 
-
-
-INSTANTIATE(TubeX01)
-
-G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4LogicalVolume *worldLog)
-{
-  // useful values for construction of tubes and cones
-  const G4double phi1 =   0.0 * deg; // all cones start at zero...
-  const G4double phi2 = 360.0 * deg; // ...and cover the whole 360 degrees
-
-  // some visualization attributes for the tube wall and the vacuum inside
-  G4VisAttributes *wallVisAttrib = new G4VisAttributes(G4Colour(1.0, 0.7, 0.5)); // light brown
-  //wallVisAttrib->SetForceSolid(true);
-  G4VisAttributes *vacuumVisAttrib = new G4VisAttributes(G4Colour(0.0, 0.0, 0.5)); // dark blue
-  vacuumVisAttrib->SetVisibility(false); // there isn't anything, so what do you expect?
-
-  const G4double crossingAngle = env.GetParameterAsDouble("ILC_Main_Crossing_Angle") / 2 * mrad; // only half the angle
-  const G4String dbName = env.GetDBName() + "_" + env.GetParameterAsString("ILC_Main_Crossing_Angle");
-  Database *db = new Database(dbName.c_str());
-
-  G4bool usingOffsets = false;
-  TReferenceMap referenceOffsets;
-  db->exec("SELECT * FROM `_references`;");
-  while (db->getTuple()) {
-    const G4String globalName   = db->fetchString("globalName");
-    const G4String localName    = db->fetchString("localName");
-    const G4double assumedValue = db->fetchDouble("assumption") * mm;
-    const G4double currentValue = env.GetParameterAsDouble(globalName);
-    const G4double offsetValue  = currentValue - assumedValue;
-    referenceOffsets[localName] = offsetValue;
-
-    if (offsetValue != 0) {
-      G4cout
-        << "TubeX01: Using " << globalName << " = "
-        << currentValue / mm << " mm instead of "
-        << assumedValue / mm << " mm" << G4endl;
-      usingOffsets = true;
-    }
-  }
-  if (usingOffsets) Control::Log("TubeX01: Be sure you know what you're doing!");
-
-  bool firstPiece = true;
-  material = "";
-  beam_inner_radius = -99999;
-  beam_thickness = -99999;
-  
-  db->exec("SELECT * FROM `tube`;");
-  while (db->getTuple()) {
-    // reference values for r- and z-values
-    const G4String zStartRef         = db->fetchString("zStartRef");
-    const G4String zEndRef           = db->fetchString("zEndRef");
-    const G4String rInnerStartRef    = db->fetchString("rInnerStartRef");
-    const G4String rInnerEndRef      = db->fetchString("rInnerEndRef");
-    const G4String rOuterStartRef    = db->fetchString("rOuterStartRef");
-    const G4String rOuterEndRef      = db->fetchString("rOuterEndRef");
-    
-    const G4double zStartOffset      = (zStartRef      == "") ? (0) : (referenceOffsets[zStartRef]);
-    const G4double zEndOffset        = (zEndRef        == "") ? (0) : (referenceOffsets[zEndRef]);
-    const G4double rInnerStartOffset = (rInnerStartRef == "") ? (0) : (referenceOffsets[rInnerStartRef]);
-    const G4double rInnerEndOffset   = (rInnerEndRef   == "") ? (0) : (referenceOffsets[rInnerEndRef]);
-    const G4double rOuterStartOffset = (rOuterStartRef == "") ? (0) : (referenceOffsets[rOuterStartRef]);
-    const G4double rOuterEndOffset   = (rOuterEndRef   == "") ? (0) : (referenceOffsets[rOuterEndRef]);
-  
-    // fields in the data tuple
-    const ECrossType crossType  = ECrossType(db->fetchInt("crossType")); // positioning of the volume
-    const G4double zStart       = db->fetchDouble("zStart")      * mm + zStartOffset;
-    const G4double zEnd         = db->fetchDouble("zEnd")        * mm + zEndOffset;
-    const G4double rInnerStart  = db->fetchDouble("rInnerStart") * mm + rInnerStartOffset;
-    const G4double rInnerEnd    = db->fetchDouble("rInnerEnd")   * mm + rInnerEndOffset;
-    const G4double rOuterStart  = db->fetchDouble("rOuterStart") * mm + rOuterStartOffset;
-    const G4double thickness    = rOuterStart - rInnerStart;
-    const G4double rOuterEnd    = db->fetchDouble("rOuterEnd")   * mm + rOuterEndOffset;
-    const G4String materialName = db->fetchString("material");
-    const G4String volName      = "tube_" + db->fetchString("name");
-
-    if(volName == "tube_IPOuterTube"){
-
-      std::ostringstream oss1;
-      oss1 << zStart;
-      (*Control::globalModelParameters)["TUBE_IPOuterTube_start_z"] = oss1.str();
-      std::ostringstream oss2;
-      oss2 << zEnd;
-      (*Control::globalModelParameters)["TUBE_IPOuterTube_end_z"] = oss2.str();
-      std::ostringstream oss3;
-      oss3 << rOuterStart;
-      (*Control::globalModelParameters)["TUBE_IPOuterTube_start_radius"] = oss3.str();
-      std::ostringstream oss4;
-      oss4 << rOuterEnd;
-      (*Control::globalModelParameters)["TUBE_IPOuterTube_end_radius"] = oss4.str();
-   	
-    }
-    
-    if(volName == "tube_IPOuterBulge"){
-
-      std::ostringstream oss1;
-      oss1 << zEnd;
-      (*Control::globalModelParameters)["TUBE_IPOuterBulge_end_z"] = oss1.str();
-      std::ostringstream oss2;
-      oss2 << rOuterEnd;
-      (*Control::globalModelParameters)["TUBE_IPOuterBulge_end_radius"] = oss2.str();
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "TGeoTube.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+#define _U(text)  Unicode(#text)
+
+
+namespace {
+  typedef enum {                // These constants are also used in the MySQL database:
+    kCenter               =  0, // centered on the z-axis
+    kUpstream             =  1, // on the upstream branch, rotated by half the crossing angle
+    kDnstream             =  2, // on the downstream branch, rotated by half the crossing angle
+
+    kPunchedCenter        =  3, // centered, with one or two inner holes
+    kPunchedUpstream      =  4, // on the upstream branch, with two inner holes
+    kPunchedDnstream      =  5, // on the downstrem branch, with two inner holes
+
+    kUpstreamClippedFront =  6, // upstream, with the front face parallel to the xy-plane
+    kDnstreamClippedFront =  7, // downstream, with the front face parallel to the xy-plane
+    kUpstreamClippedRear  =  8, // upstream, with the rear face parallel to the xy-plane
+    kDnstreamClippedRear  =  9, // downstream, with the rear face parallel to the xy-plane
+    kUpstreamClippedBoth  = 10, // upstream, with both faces parallel to the xy-plane
+    kDnstreamClippedBoth  = 11, // downstream, with both faces parallel to the xy-plane
+
+    kUpstreamSlicedFront  = 12, // upstream, with the front face parallel to a tilted piece
+    kDnstreamSlicedFront  = 13, // downstream, with the front face parallel to a tilted piece
+    kUpstreamSlicedRear   = 14, // upstream, with the rear face parallel to a tilted piece
+    kDnstreamSlicedRear   = 15, // downstream, with the rear face parallel to a tilted piece
+    kUpstreamSlicedBoth   = 16, // upstream, with both faces parallel to a tilted piece
+    kDnstreamSlicedBoth   = 17  // downstream, with both faces parallel to a tilted piece
+  } ECrossType;
+}
 
-    }
-    
-    if(firstPiece)
-      { 
-	firstPiece = false;
-	material = materialName;
-	beam_inner_radius = rInnerStart;
-	beam_thickness = thickness;
-      }
-    // things which can be calculated immediately
-    zHalf        = fabs(zEnd - zStart) / 2; // half z length of the cone
-    const G4double zPosition    = fabs(zEnd + zStart) / 2; // middle z position
-    G4Material *coreMaterial    = CGAGeometryManager::GetMaterial("beam"); // always the same
-    G4Material *wallMaterial    = CGAGeometryManager::GetMaterial(materialName);
 
-    // this could mess up your geometry, so better check it
-    if (crossingAngle == 0 && crossType != kCenter) {
-      Control::Log("TubeX01: You are trying to build a crossing geometry without a crossing angle.\n"
-        "This is probably not what you want - better check your geometry data!");
-      return false; // premature exit, Mokka will abort now
-    }
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&)  {
+  xml_det_t   x_det  = e;
+  string      name   = x_det.nameStr();
+  Rotation    reflect_rot(M_PI,0,0);
+  DetElement  sdet(name,x_det.id());
+  Assembly    assembly(name);
+  double      crossingAngle = x_det.attr<double>(_U(crossing_angle));
+  Material    coreMat   = lcdd.vacuum();
+  VisAttr     vacuumVis = lcdd.visAttributes("TubeVacuumVis");
+
+  PlacedVolume pv;
+  struct dim_t { double inner_r, outer_r, z; };
+  for(xml_coll_t c(x_det.child(_U(tubes)),_U(tube)); c; ++c)  {
+    xml_comp_t x_c = c;
+    xml_comp_t x_end   = c.child(_A(end));
+    xml_comp_t x_start = c.child(_A(start));
+    dim_t  end   = { x_end.inner_r(), x_end.outer_r(), x_end.z()};
+    dim_t  start = { x_start.inner_r(), x_start.outer_r(), x_start.z()};
+    Material mat = lcdd.material(x_c.materialStr());
+    VisAttr  vis = lcdd.visAttributes(x_c.visStr());
+    int crossType = x_c.attr<int>(_U(crossType));
+
+    double angle = 0;
+    string nam = x_c.nameStr();
+    double zHalf = std::fabs(start.z - end.z) / 2; // half z length of the cone
+    double zPos  = std::fabs(start.z + end.z) / 2; // middle z position
 
-    register G4double tmpAngle;
     switch (crossType) {
       case kUpstream:
       case kPunchedUpstream:
@@ -343,7 +78,7 @@ G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4Logical
       case kUpstreamSlicedFront:
       case kUpstreamSlicedRear:
       case kUpstreamSlicedBoth:
-        tmpAngle = -crossingAngle; break;
+        angle = -crossingAngle; break;
       case kDnstream:
       case kPunchedDnstream:
       case kDnstreamClippedFront:
@@ -352,354 +87,244 @@ G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4Logical
       case kDnstreamSlicedFront:
       case kDnstreamSlicedRear:
       case kDnstreamSlicedBoth:
-        tmpAngle = +crossingAngle; break;
+        angle = +crossingAngle; break;
       default:
-        tmpAngle = 0; break;
+        angle = 0; break;
     }
-    const G4double rotateAngle = tmpAngle; // for the placement at +z (better make it const now)
-    const G4double mirrorAngle = 180 * deg - rotateAngle; // for the "mirrored" placement at -z
-    // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
-    
+
+    cout << name << "> Building " << nam << " " << crossType << " " << vis.name() << endl;
+    double reflect_angle = M_PI - angle;
+    Volume vol, wall;
+    SubtractionSolid solid;
     switch (crossType) {
       case kCenter:
       case kUpstream:
       case kDnstream: {
         // a volume on the z-axis, on the upstream branch, or on the downstream branch
-      
-        // absolute transformations for the placement in the world
-        G4Transform3D transformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
-        G4Transform3D transmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-        
-        // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-        
-        // tube consists of vacuum
-        G4LogicalVolume *tubeLog = new G4LogicalVolume(tubeSolid, coreMaterial, volName, 0, 0, 0, true);
-        tubeLog->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(transformer, tubeLog, volName, worldLog, false, 0);
-        new G4PVPlacement(transmirror, tubeLog, volName, worldLog, false, 1);
-        
+	ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+	vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+	vol.setVisAttributes(vacuumVis);
         // if inner and outer radii are equal, then omit the tube wall
-        if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
-          // the wall solid: a tubular cone
-          G4Cons *wallSolid = new G4Cons(volName + "_wall", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf, phi1, phi2);
-        
-          // the wall consists of the material given in the database
-          G4LogicalVolume *wallLog = new G4LogicalVolume(wallSolid, wallMaterial, volName + "_wall", 0, 0, 0, true);
-          wallLog->SetVisAttributes(wallVisAttrib);
-        
-          // placement as a daughter volume of the tube, will appear in both placements of the tube
-          new G4PVPlacement(0, 0, wallLog, volName + "_wall", tubeLog, false, 0);
-        }
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) { // the wall solid: a tubular cone
+	  ConeSegment wall(zHalf, start.inner_r, start.outer_r, start.inner_r, end.outer_r);
+	  Volume      vol_wall(name+"_"+nam+"_wall",cone,mat);
+	  vol.setVisAttributes(vis);
+	  vol.placeVolume(vol_wall);
+	}
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
         break;
       }
       case kPunchedCenter: {
         // a volume on the z-axis with one or two inner holes
         // (implemented as a cone from which tubes are punched out)
-      
-        const G4double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
-        const G4double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
-      
-        // relative transformations for the composition of the G4SubtractionVolumes
-        G4Transform3D upstreamTransformer(G4RotationMatrix().rotateY(-crossingAngle), G4ThreeVector(zPosition * tan(-crossingAngle), 0, 0));
-        G4Transform3D dnstreamTransformer(G4RotationMatrix().rotateY(+crossingAngle), G4ThreeVector(zPosition * tan(+crossingAngle), 0, 0));
-  
-        // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
-        G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
-        G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-  
-        // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-        
-        // tube consists of vacuum (will later have two different daughters)
-        G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_0", 0, 0, 0, true);
-        G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_1", 0, 0, 0, true);
-        tubeLog0->SetVisAttributes(vacuumVisAttrib);
-        tubeLog1->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
-        new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-        
+        double rUpstreamPunch = start.inner_r; // just alias names denoting what is meant here
+        double rDnstreamPunch = end.inner_r;   // (the database entries are "abused" in this case)
+	ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+	vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+	vol.setVisAttributes(vacuumVis);
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+
         // the wall solid and placeholders for possible G4SubtractionSolids
-        G4Cons *wholeSolid = new G4Cons(volName + "_wall_whole", 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-        G4VSolid *tmpSolid0, *tmpSolid1, *wallSolid0, *wallSolid1;
-  
+        ConeSegment wallCone(zHalf,0,start.outer_r,0,end.outer_r);
+	Solid solid1 = cone, solid2 = cone;
         // the punched subtraction solids can be asymmetric and therefore have to be created twice:
         // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
         // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
-        if (rUpstreamPunch) { // do we need a hole on the upstream branch?
-          G4Tubs *upstreamPunch = new G4Tubs(volName + "_wall_punch_up", 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
-          tmpSolid0 = new G4SubtractionSolid(volName + "_wall_tmp_0", wholeSolid, upstreamPunch, upstreamTransformer);
-          tmpSolid1 = new G4SubtractionSolid(volName + "_wall_tmp_1", wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
-        } else { // dont't do anything, just pass on the unmodified shape
-          tmpSolid0 = wholeSolid;
-          tmpSolid1 = wholeSolid;
-        }
-  
-        if (rDnstreamPunch) { // do we need a hole on the downstream branch?
-          G4Tubs *dnstreamPunch = new G4Tubs(volName + "_wall_punch_dn", 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
-          wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", tmpSolid0, dnstreamPunch, dnstreamTransformer);
-          wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
-        } else { // dont't do anything, just pass on the unmodified shape
-          wallSolid0 = tmpSolid0;
-          wallSolid1 = tmpSolid1;
-        }
-  
+        if ( start.inner_r ) { // do we need a hole on the upstream branch?
+	  Tube punch(0,start.inner_r,5*zHalf);
+	  solid1 = SubtractionSolid(wallCone,punch,Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+	  solid2 = SubtractionSolid(wallCone,punch,Position(zPos*std::tan(+crossingAngle),0,0),Rotation(0,+crossingAngle,0));
+	}
+        if ( end.inner_r ) { // do we need a hole on the downstream branch?
+	  Tube punch(0,start.inner_r,5*zHalf);
+	  solid1 = SubtractionSolid(solid1,punch,Position(zPos*std::tan(+crossingAngle),0,0),Rotation(0,+crossingAngle,0));
+	  solid2 = SubtractionSolid(solid2,punch,Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+	}
         // the wall consists of the material given in the database
-        G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
-        G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
-        wallLog0->SetVisAttributes(wallVisAttrib);
-        wallLog1->SetVisAttributes(wallVisAttrib);
-  
-        // placement as a daughter volumes of the tube
-        new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
-        new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
+	wall = Volume(name+"_"+nam+"_pos",solid1,mat);
+	wall.setVisAttributes(vis);
+	assembly.placeVolume(wall,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+	wall = Volume(name+"_"+nam+"_neg",solid2,mat);
+	wall.setVisAttributes(vis);
+	assembly.placeVolume(wall,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
         break;
       }
       case kPunchedUpstream:
       case kPunchedDnstream: {
         // a volume on the upstream or downstream branch with two inner holes
         // (implemented as a cone from which another tube is punched out)
-      
-        const G4double rCenterPunch = (crossType == kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
-        const G4double rOffsetPunch = (crossType == kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
-      
-        // relative transformations for the composition of the G4SubtractionVolumes
-        G4Transform3D punchTransformer(G4RotationMatrix().rotateY(-2 * rotateAngle), G4ThreeVector(zPosition * tan(-2 * rotateAngle), 0, 0));
-        G4Transform3D punchTransmirror(G4RotationMatrix().rotateY(+2 * rotateAngle), G4ThreeVector(zPosition * tan(+2 * rotateAngle), 0, 0));
-  
-        // absolute transformations for the final placement in the world
-        G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
-        G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-  
-        // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-        
-        // tube consists of vacuum (will later have two different daughters)
-        G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_0", 0, 0, 0, true);
-        G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_1", 0, 0, 0, true);
-        tubeLog0->SetVisAttributes(vacuumVisAttrib);
-        tubeLog1->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
-        new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-        
+	double rCenterPunch = (crossType == kPunchedUpstream) ? start.inner_r : end.inner_r; // radius of the central hole
+	double rOffsetPunch = (crossType == kPunchedDnstream) ? start.inner_r : end.inner_r; // radius of the off-axis hole
+	ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+	vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+	vol.setVisAttributes(vacuumVis);
+
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(0,reflect_angle,0));
+
         // the wall solid and the piece (only a tube, for the moment) which will be punched out
-        G4Cons *wholeSolid = new G4Cons(volName + "_wall_whole", rCenterPunch, rOuterStart, rCenterPunch, rOuterEnd, zHalf, phi1, phi2);
-        G4Tubs *punchSolid = new G4Tubs(volName + "_wall_punch", 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
-  
+	ConeSegment whole(zHalf,rCenterPunch,start.outer_r,rCenterPunch,end.outer_r);
+	Tube        punch(0,rOffsetPunch,5*zHalf);    
         // the punched subtraction solids can be asymmetric and therefore have to be created twice:
         // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
         // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
-        G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wholeSolid, punchSolid, punchTransformer);
-        G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wholeSolid, punchSolid, punchTransmirror);
-  
-        // the wall consists of the material given in the database
-        G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
-        G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
-        wallLog0->SetVisAttributes(wallVisAttrib);
-        wallLog1->SetVisAttributes(wallVisAttrib);
-  
-        // placement as a daughter volumes of the tube
-        new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
-        new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
-        break;
+        solid = SubtractionSolid(whole, punch, Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+	wall  = Volume(name+"_"+nam+"_wall_pos",solid,mat);
+	wall.setVisAttributes(vis);
+	assembly.placeVolume(wall,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+
+	solid = SubtractionSolid(whole, punch, Position(zPos*std::tan(crossingAngle),0,0),Rotation(0,crossingAngle,0));
+	wall  = Volume(name+"_"+nam+"_wall_neg",solid,mat);
+	wall.setVisAttributes(vis);
+	assembly.placeVolume(wall,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+	break;
       }
       case kUpstreamClippedFront:
       case kDnstreamClippedFront:
       case kUpstreamSlicedFront:
       case kDnstreamSlicedFront: {
         // a volume on the upstream or donwstream branch, but with the front face parallel to the xy-plane
-        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
         // (implemented as a slightly longer cone from which the end is clipped off)
       
         // the volume which will be used for clipping: a solid tube
-        const G4double clipSize = rOuterStart; // the right order of magnitude for the clipping volume (alias name)
-        G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-        
+        double clipSize = start.outer_r; // the right order of magnitude for the clipping volume (alias name)
+	Tube clip(0, 2 * clipSize, clipSize);
         // relative transformations for the composition of the G4SubtractionVolumes
-        const G4double clipAngle = (crossType == kUpstreamClippedFront || crossType == kDnstreamClippedFront) ? (rotateAngle) : (2 * rotateAngle);
-        const G4double clipShift = (zStart - clipSize) / cos(clipAngle) - (zPosition - clipSize / 2); // question: why is this correct?
-        G4Transform3D clipTransformer(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShift));
-        G4Transform3D clipTransmirror(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShift));
-  
-        // absolute transformations for the final placement in the world
-        G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition - clipSize / 2).rotateY(rotateAngle));
-        G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition - clipSize / 2).rotateY(mirrorAngle));
-  
-        // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-  
-        // clip away the protruding end
-        G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0", wholeSolid, clipSolid, clipTransformer);
-        G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1", wholeSolid, clipSolid, clipTransmirror);
-        
-        // tube consists of vacuum (will later have two different daughters)
-        G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
-        G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
-        tubeLog0->SetVisAttributes(vacuumVisAttrib);
-        tubeLog1->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
-        new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-       
-        if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
-          // the wall solid: a tubular cone
-          G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-        
-          // clip away the protruding end
-          G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wallWholeSolid, clipSolid, clipTransformer);
-          G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wallWholeSolid, clipSolid, clipTransmirror);
-        
-          // the wall consists of the material given in the database
-          G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
-          G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
-          wallLog0->SetVisAttributes(wallVisAttrib);
-          wallLog1->SetVisAttributes(wallVisAttrib);
-        
-          // placement as a daughter volumes of the tube
-          new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
-          new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
-        }
-        break;
+        double clipAngle = (crossType == kUpstreamClippedFront || crossType == kDnstreamClippedFront) ? (angle) : (2 * angle);
+        double clipShift = (start.z - clipSize) / cos(clipAngle) - (zPos - clipSize / 2); // question: why is this correct?
+	Position clip_pos(0,0,clipShift), clip_pos_pos(clip_pos), clip_pos_neg(clip_pos);
+	clip_pos_pos.rotateY(-clipAngle);
+	clip_pos_neg.rotateY(+clipAngle);
+
+	ConeSegment wallCone, whole(zHalf+clipSize/2, 0, start.outer_r, 0, end.outer_r);
+	solid = SubtractionSolid(whole, clip, clip_pos_pos,Rotation(0,-clipAngle,0));
+	wall = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+	wall.setVisAttributes(vacuumVis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  wallCone = ConeSegment(zHalf+clipSize/2,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
+	  SubtractionSolid wallSolid(wallCone,clip,clip_pos_pos,Rotation(0,-clipAngle,0));
+	  Volume           wall (name+"_"+nam+"_wall_solid",wallSolid,mat);
+	  wall.setVisAttributes(vis);
+	  wall.placeVolume(wall);
+	}
+	assembly.placeVolume(wall,Position(0,0,zPos-clipSize/2).rotateY(angle),Rotation(0,angle,0));
+	
+	solid = SubtractionSolid(whole, clip, clip_pos_neg,Rotation(0,clipAngle,0));
+	wall  = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+	wall.setVisAttributes(vis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  SubtractionSolid wallSolid(wallCone,clip, clip_pos_neg, Rotation(0,+clipAngle,0));
+	  Volume           wall (name+"_"+nam+"_wall_solid",wallSolid,mat);
+	  wall.placeVolume(wall);
+	}
+	assembly.placeVolume(wall,Position(0,0,zPos - clipSize / 2).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+	break;
       }
       case kUpstreamClippedRear:
       case kDnstreamClippedRear:
       case kUpstreamSlicedRear:
       case kDnstreamSlicedRear: {
         // a volume on the upstream or donwstream branch, but with the rear face parallel to the xy-plane
-        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
         // (implemented as a slightly longer cone from which the end is clipped off)
       
         // the volume which will be used for clipping: a solid tube
-        const G4double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
-        G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-        
+        double clipSize = start.outer_r; // the right order of magnitude for the clipping volume (alias name)
+	Tube clip(0, 2 * clipSize, clipSize);
         // relative transformations for the composition of the G4SubtractionVolumes
-        const G4double clipAngle = (crossType == kUpstreamClippedRear || crossType == kDnstreamClippedRear) ? (rotateAngle) : (2 * rotateAngle);
-        const G4double clipShift = (zEnd + clipSize) / cos(clipAngle) - (zPosition + clipSize / 2); // question: why is this correct?
-        G4Transform3D clipTransformer(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShift));
-        G4Transform3D clipTransmirror(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShift));
-  
-        // absolute transformations for the final placement in the world
-        G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition + clipSize / 2).rotateY(rotateAngle));
-        G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition + clipSize / 2).rotateY(mirrorAngle));
-  
-        // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-  
-        // clip away the protruding end
-        G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0", wholeSolid, clipSolid, clipTransformer);
-        G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1", wholeSolid, clipSolid, clipTransmirror);
-        
-        // tube consists of vacuum (will later have two different daughters)
-        G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
-        G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
-        tubeLog0->SetVisAttributes(vacuumVisAttrib);
-        tubeLog1->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
-        new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-       
-        if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
-          // the wall solid: a tubular cone
-          G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-        
-          // clip away the protruding end
-          G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wallWholeSolid, clipSolid, clipTransformer);
-          G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wallWholeSolid, clipSolid, clipTransmirror);
-        
-          // the wall consists of the material given in the database
-          G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
-          G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
-          wallLog0->SetVisAttributes(wallVisAttrib);
-          wallLog1->SetVisAttributes(wallVisAttrib);
-        
-          // placement as a daughter volumes of the tube
-          new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
-          new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
-        }
-        break;
+        double clipAngle = (crossType == kUpstreamClippedRear || crossType == kDnstreamClippedRear) ? (angle) : (2 * angle);
+        double clipShift = (end.z + clipSize) / cos(clipAngle) - (zPos + clipSize / 2); // question: why is this correct?
+	Position clip_pos(0,0,clipShift), clip_pos_pos(clip_pos), clip_pos_neg(clip_pos);
+	clip_pos_pos.rotateY(-clipAngle);
+	clip_pos_neg.rotateY(+clipAngle);
+
+	ConeSegment wallCone, whole(zHalf+clipSize/2,0, start.outer_r, 0, end.outer_r);
+	solid = SubtractionSolid(whole, clip, clip_pos_pos,Rotation(0,-clipAngle,0));
+	vol = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+	vol.setVisAttributes(vacuumVis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  wallCone = ConeSegment(zHalf + clipSize/2,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
+	  solid = SubtractionSolid(wallCone,clip,clip_pos_pos,Rotation(0,-clipAngle,0));
+	  Volume  wall (name+"_"+nam+"_wall_solid",solid,mat);
+	  wall.setVisAttributes(vis);
+	  vol.placeVolume(wall);
+	}
+	assembly.placeVolume(vol,Position(0,0,zPos+clipSize/2).rotateY(angle),Rotation(0,angle,0));
+	
+	solid = SubtractionSolid(whole, clip, clip_pos_neg,Rotation(0,clipAngle,0));
+	vol  = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+	vol.setVisAttributes(vis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  solid = SubtractionSolid(wallCone, clip, clip_pos_neg, Rotation(0,+clipAngle,0));
+	  Volume  wall (name+"_"+nam+"_wall_solid",solid,mat);
+	  wall.setVisAttributes(vis);
+	  vol.placeVolume(wall);
+	}
+	assembly.placeVolume(vol,Position(0,0,zPos+clipSize/2).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+	break;
       }
       case kUpstreamClippedBoth:
       case kDnstreamClippedBoth:
       case kUpstreamSlicedBoth:
       case kDnstreamSlicedBoth: {
         // a volume on the upstream or donwstream branch, but with both faces parallel to the xy-plane
-        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+        // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
         // (implemented as a slightly longer cone from which the end is clipped off)
-      
+
         // the volume which will be used for clipping: a solid tube
-        const G4double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
-        G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-        
+        double clipSize = end.outer_r; // the right order of magnitude for the clipping volume (alias name)
+	Tube clip(0, 2 * clipSize, clipSize);
         // relative transformations for the composition of the G4SubtractionVolumes
-        const G4double clipAngle = (crossType == kUpstreamClippedBoth || crossType == kDnstreamClippedBoth) ? (rotateAngle) : (2 * rotateAngle);
-        const G4double clipShiftFrnt = (zStart - clipSize) / cos(clipAngle) - zPosition;
-        const G4double clipShiftRear = (zEnd   + clipSize) / cos(clipAngle) - zPosition;
-        G4Transform3D clipTransformerFrnt(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShiftFrnt));
-        G4Transform3D clipTransformerRear(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShiftRear));
-        G4Transform3D clipTransmirrorFrnt(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShiftFrnt));
-        G4Transform3D clipTransmirrorRear(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShiftRear));
-  
-        // absolute transformations for the final placement in the world
-        G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
-        G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-  
+        double clipAngle = (crossType == kUpstreamClippedBoth || crossType == kDnstreamClippedBoth) ? (angle) : (2 * angle);
+        double clipShiftFrnt = (start.z - clipSize) / cos(clipAngle) - zPos;
+        double clipShiftRear = (end.z   + clipSize) / cos(clipAngle) - zPos;
         // solid for the tube (including vacuum and wall): a solid cone
-        G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
-  
-        // clip away the protruding ends
-        G4SubtractionSolid *tmpSolid0  = new G4SubtractionSolid(volName + "_tmp_0", wholeSolid, clipSolid, clipTransformerFrnt);
-        G4SubtractionSolid *tmpSolid1  = new G4SubtractionSolid(volName + "_tmp_1", wholeSolid, clipSolid, clipTransmirrorFrnt);
-        G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0",     tmpSolid0,  clipSolid, clipTransformerRear);
-        G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1",     tmpSolid1,  clipSolid, clipTransmirrorRear);
-        
-        // tube consists of vacuum (will later have two different daughters)
-        G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
-        G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
-        tubeLog0->SetVisAttributes(vacuumVisAttrib);
-        tubeLog1->SetVisAttributes(vacuumVisAttrib);
-        
-        // placement of the tube in the world, both at +z and -z
-        new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
-        new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-       
-        if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
-          // the wall solid: a tubular cone
-          G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
-        
+	ConeSegment wallCone, whole(zHalf + clipSize, 0, start.outer_r, 0, end.outer_r);
+
+	// Primary side:
+	solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftFrnt),Rotation(0,-clipAngle,0));
+	solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftRear),Rotation(0,-clipAngle,0));
+	vol = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+	vol.setVisAttributes(vacuumVis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  wallCone = ConeSegment(zHalf + clipSize,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
           // clip away the protruding ends
-          G4SubtractionSolid *wallTmpSolid0 = new G4SubtractionSolid(volName + "_wall_tmp_0", wallWholeSolid, clipSolid, clipTransformerFrnt);
-          G4SubtractionSolid *wallTmpSolid1 = new G4SubtractionSolid(volName + "_wall_tmp_1", wallWholeSolid, clipSolid, clipTransmirrorFrnt);
-          G4SubtractionSolid *wallSolid0    = new G4SubtractionSolid(volName + "_wall_0",     wallTmpSolid0,  clipSolid, clipTransformerRear);
-          G4SubtractionSolid *wallSolid1    = new G4SubtractionSolid(volName + "_wall_1",     wallTmpSolid1,  clipSolid, clipTransmirrorRear);
-        
-          // the wall consists of the material given in the database
-          G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
-          G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
-          wallLog0->SetVisAttributes(wallVisAttrib);
-          wallLog1->SetVisAttributes(wallVisAttrib);
-        
-          // placement as a daughter volumes of the tube
-          new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
-          new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
-        }
+	  solid = SubtractionSolid(wallCone,clip,Position(0,0,clipShiftFrnt),Rotation(0,-clipAngle,0));
+	  solid = SubtractionSolid(solid,   clip,Position(0,0,clipShiftRear),Rotation(0,-clipAngle,0));
+	  wall  = Volume(name+"_"+nam+"_pos_wall",solid,mat);
+	  wall.setVisAttributes(vis);
+	  vol.placeVolume(wall);
+	}
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+
+	// Mirror side:
+	solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftFrnt),Rotation(0,+clipAngle,0));
+	solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftRear),Rotation(0,+clipAngle,0));
+	vol  = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+	vol.setVisAttributes(vis);
+        if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+	  solid = SubtractionSolid(wallCone,clip,Position(0,0,clipShiftFrnt),Rotation(0,+clipAngle,0));
+	  solid = SubtractionSolid(solid,   clip,Position(0,0,clipShiftRear),Rotation(0,+clipAngle,0));
+	  Volume  wall (name+"_"+nam+"_neg_wall",solid,mat);
+	  wall.setVisAttributes(vis);
+	  vol.placeVolume(wall);
+	}
+	assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
         break;
       }
-      default: {
-        Control::Log("TubeX01: Unimplemented \"crossType\" code.");
-        return false; // fatal failure
-      }
-    } // switch (crossType)
-  } // while (db->getTuple())
-  delete db;
-  return true;
+    default: {
+      cout << "MaskX01: Unimplemented \"crossType\" code:" << crossType << endl;
+      throw runtime_error("MaskX01: Unimplemented \"crossType\" code.");
+      break;
+    }
+    }
+  }
+  assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+  sdet.setPlacement(lcdd.pickMotherVolume(sdet).placeVolume(assembly));
+  return sdet;
 }
-#endif
+
+DECLARE_DETELEMENT(Tesla_tubeX01,create_element);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
index 6ece95496f5567e246c50168ef9190def38e489f..88365203ee326336a17c2a3e823184ebe522b59f 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
@@ -18,7 +18,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
   xml_det_t   x_det  = e;
   string      name   = x_det.nameStr();
   DetElement  sdet(name,x_det.id());
-  Assembly    assembly(name+"_assembly");
+  Assembly    assembly(name);
   xml_comp_t  x_barrel = x_det.child(Unicode("barrel"));
   xml_comp_t  x_endcap = x_det.child(Unicode("endcap"));
   param_t barrel = { x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.zhalf()};
@@ -43,7 +43,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
     assembly.placeVolume(volume,Position(0,0,-x_endcap.z()));
   }
 
-  lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+  PlacedVolume pv = lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+  sdet.setPlacement(pv);
   return sdet;
 }