From edf763a4e9d1eb8aeb1da37176d758c87da3c6cc Mon Sep 17 00:00:00 2001
From: Frank Gaede <frank.gaede@desy.de>
Date: Tue, 25 Jun 2013 07:20:54 +0000
Subject: [PATCH]   - added AhcalEndcap calorimeter (S.Lu)   - updated
 AHcalBarrel driver (simplified geometry) (S.Lu)

---
 DDExamples/ILDExDet/compact/ILDEx.xml         |  56 +++-
 .../compact/AhcalBarrelCalorimeter_geo.cpp    | 136 +++++----
 .../compact/AhcalEndcapCalorimeter_geo.cpp    | 286 ++++++++++++++++++
 3 files changed, 411 insertions(+), 67 deletions(-)
 create mode 100644 DDExamples/ILDExDet/src/compact/AhcalEndcapCalorimeter_geo.cpp

diff --git a/DDExamples/ILDExDet/compact/ILDEx.xml b/DDExamples/ILDExDet/compact/ILDEx.xml
index 998cfa74c..dcb9cfb94 100644
--- a/DDExamples/ILDExDet/compact/ILDEx.xml
+++ b/DDExamples/ILDExDet/compact/ILDEx.xml
@@ -53,6 +53,10 @@
         <!-- constant name="Hcal_Barrel_rotation" value="0.392699075"/-->
         <constant name="Hcal_Barrel_rotation" value="0."/>
 
+        <constant name="Hcal_endcap_modules" value="16"/>
+        <constant name="Hcal_endcap_layers" value="(int) 48"/>
+        <constant name="Hcal_endcap_zmin" value="2650*mm"/>
+
         <constant name="SolenoidalFieldRadius"  value="Hcal_outer_radius+10.0*mm"/>
     </define>
 
@@ -87,9 +91,16 @@
       <vis name="LumiCalVis"                                         showDaughters="false" visible="true"/>
 
       <vis name="HcalBarrelVis"          alpha="1" r="1"    g="1"    b="0.1" showDaughters="true" visible="true"/>
-      <vis name="HcalBarrelStavesVis"    alpha="1" r="1"    g="0"    b="0.3" showDaughters="true" visible="true"/>
-      <vis name="HcalBarrelLayerVis"     alpha="1" r="1"    g="0"    b="0.5" showDaughters="true" visible="true"/>
-      <vis name="HcalBarrelSensorVis"    alpha="1" r="1"    g="1"    b="0.7" showDaughters="true" visible="true"/>
+      <vis name="HcalBarrelStavesVis"    alpha="1" r="1"    g="0"    b="0.3" showDaughters="true" visible="false"/>
+      <vis name="HcalBarrelLayerVis"     alpha="1" r="1"    g="0"    b="0.5" showDaughters="true" visible="false"/>
+      <vis name="HcalBarrelSensorVis"    alpha="1" r="1"    g="1"    b="0.7" showDaughters="true" visible="false"/>
+
+      <vis name="HcalEndcapVis"          alpha="1" r="1"    g="1"    b="0.1" showDaughters="true" visible="true"/>
+      <vis name="HcalEndcapStavesVis"    alpha="1" r="1"    g="0"    b="0.3" showDaughters="true" visible="false"/>
+      <vis name="HcalEndcapLayerVis"     alpha="1" r="1"    g="0"    b="0.5" showDaughters="true" visible="false"/>
+      <vis name="HcalEndcapSensorVis"    alpha="1" r="1"    g="1"    b="0.7" showDaughters="true" visible="false"/>
+      <vis name="HcalEndcapAirVis"       alpha="1" r="1"    g="0"    b="0"   showDaughters="true" visible="false"/>
+
     </display>
 
     <detectors>
@@ -180,11 +191,42 @@
 
             <dimensions numsides="(int) HcalBarrel_staves" rmin="HcalBarrel_rmin" z="HcalBarrel_zmax"/>
             <layer repeat="(int) HcalBarrel_layers">
-                <slice material = "Air" thickness = "2.7*mm" />
+                <slice material = "Polystyrene" thickness = "3.0*mm" sensitive = "yes" limits="cal_limits" vis="HcalBarrelSensorVis"/>
+                <slice material = "FR4" thickness = "0.7*mm" />
                 <slice material = "Cu"  thickness = "0.1*mm" />
+                <slice material = "Air" thickness = "2.7*mm"  vis="HcalBarrelAirVis" />
+            </layer>
+        </detector>
+        <detector id="8" name="HcalEndcap" type="AhcalEndcapCalorimeter" readout="HcalEndcapHits"  calorimeterType="HAD_ENDCAP" gap="15.*mm">
+            <comment>Hadron Calorimeter Endcap</comment>
+
+            <material name="Steel235"/>
+
+            <layer repeat="(int) Hcal_endcap_layers">
+                <slice material = "Polystyrene" thickness = "3.0*mm" sensitive = "yes" limits="cal_limits" vis="HcalEndcapSensorVis"/>
                 <slice material = "FR4" thickness = "0.7*mm" />
-                <slice material = "Polystyrene" thickness = "3.0*mm" sensitive = "yes" limits="cal_limits" vis="HcalBarrelSensorVis"/>
+                <slice material = "Cu"  thickness = "0.1*mm" />
+                <slice material = "Air" thickness = "2.7*mm" vis="HcalEndcapAirVis" />
             </layer>
+
+            <dimensions numsides="(int) Hcal_endcap_modules" rmin="362.0*mm" z="Hcal_endcap_zmin">
+              <dimensions id="1"  y_offset= "543.5" dim_x="375.0" dim_y="1287.0" dim_z="1087.0"/>
+              <dimensions id="2"  y_offset= "905.5" dim_x="375.0" dim_y="1287.0" dim_z="1811.0"/>
+              <dimensions id="3"  y_offset="1086.5" dim_x="375.0" dim_y="1287.0" dim_z="2173.0"/>
+              <dimensions id="4"  y_offset="1268.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="5"  y_offset="1268.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="6"  y_offset="1449.0" dim_x="375.0" dim_y="1287.0" dim_z="2898.0"/>
+              <dimensions id="7"  y_offset="1449.0" dim_x="375.0" dim_y="1287.0" dim_z="2898.0"/>
+              <dimensions id="8"  y_offset="1630.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="9"  y_offset="1630.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="10" y_offset="1449.0" dim_x="375.0" dim_y="1287.0" dim_z="2898.0"/>
+              <dimensions id="11" y_offset="1449.0" dim_x="375.0" dim_y="1287.0" dim_z="2898.0"/>
+              <dimensions id="12" y_offset="1268.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="13" y_offset="1268.0" dim_x="375.0" dim_y="1287.0" dim_z="2536.0"/>
+              <dimensions id="14" y_offset="1086.5" dim_x="375.0" dim_y="1287.0" dim_z="2173.0"/>
+              <dimensions id="15" y_offset= "905.5" dim_x="375.0" dim_y="1287.0" dim_z="1811.0"/>
+              <dimensions id="16" y_offset= "543.5" dim_x="375.0" dim_y="1287.0" dim_z="1087.0"/>
+	    </dimensions>
         </detector>
     </detectors>
 
@@ -209,6 +251,10 @@
             <segmentation type="RegularNgonCartesianGridXY" gridSizeX="30.0*mm" gridSizeY="30.0*mm" />
             <id>system:6,stave:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
         </readout>
+        <readout name="HcalEndcapHits">
+            <segmentation type="GlobalGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:6,stave:1,module:1,endcapID:5,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
 
     </readouts>
  <fields>
diff --git a/DDExamples/ILDExDet/src/compact/AhcalBarrelCalorimeter_geo.cpp b/DDExamples/ILDExDet/src/compact/AhcalBarrelCalorimeter_geo.cpp
index 9ba13eb3b..38926058b 100644
--- a/DDExamples/ILDExDet/src/compact/AhcalBarrelCalorimeter_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/AhcalBarrelCalorimeter_geo.cpp
@@ -56,9 +56,10 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
   double      Hcal_lateral_structure_thickness = lcdd.constant<double>("Hcal_lateral_structure_thickness");
   double      Hcal_layer_air_gap               = lcdd.constant<double>("Hcal_layer_air_gap");
   double      Hcal_back_plate_thickness        = lcdd.constant<double>("Hcal_back_plate_thickness");
-  double      totalThickness_Hcal_Barrel = (Hcal_radiator_thickness + Hcal_chamber_thickness) 
-                                           * HcalBarrel_layers + Hcal_back_plate_thickness;
-  double      Hcal_module_radius         = Hcal_inner_radius + totalThickness_Hcal_Barrel;
+
+  double      totalThickness_Hcal_Barrel       = (Hcal_radiator_thickness + Hcal_chamber_thickness) 
+                                                 * HcalBarrel_layers + Hcal_back_plate_thickness;
+  double      Hcal_module_radius               = Hcal_inner_radius + totalThickness_Hcal_Barrel;
 
   double      Hcal_Barrel_rotation             = lcdd.constant<double>("Hcal_Barrel_rotation");
 
@@ -72,13 +73,22 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
   // ==========================================================================
 
   // Hcal Barrel module shapers
-  PolyhedraRegular polyhedra_shaper("polyhedra",numSides,Hcal_inner_radius,Hcal_module_radius,detZ*2);
-  Tube             tube_shaper(0.0,Hcal_outer_radius, detZ, 0.0, 2.0*M_PI);
+  PolyhedraRegular polyhedra_shaper("polyhedra",numSides,Hcal_inner_radius,Hcal_module_radius,detZ*2.);
+  Tube             tube_shaper(0.,Hcal_outer_radius, detZ, 0., 2.*M_PI);
+  
+  // keep the envelope rotation as the same as the stave
+  // the stave number can be changed in the compact XML.
+  Rotation rot(M_PI/2. - M_PI/numSides,0,0);
 
   // Create Hcal Barrel volume with material Steel235 
-  IntersectionSolid barrelModuleSolid(tube_shaper,polyhedra_shaper,Rotation(M_PI/numSides,0,0));
+  IntersectionSolid barrelModuleSolid(tube_shaper,polyhedra_shaper,rot);
+  
   Volume           envelopeVol(det_name+"_envelope",barrelModuleSolid,Steel235);
 
+  // Set envelope volume attributes.
+  envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
+
+
   // ========= Create Hcal Barrel Chmaber (i.e. Layers) =======================
   // It will be the sub volume for placing the slices.
   // Itself will be placed into the Hcal Barrel envelope.
@@ -86,26 +96,23 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
 
   // create Layer (air) and place the slices (Polystyrene,Cu,FR4,air) into it. 
   // place the Layer into the HcalBarrel envelope (Steel235).
-  double innerAngle      = 2*M_PI/numSides;
-  double halfInnerAngle  = innerAngle/2;
-  double tan_inner       = std::tan(halfInnerAngle) * 2;
+  double innerAngle      = 2.*M_PI/numSides;
+  double halfInnerAngle  = innerAngle/2.;
+  double tan_inner       = std::tan(halfInnerAngle) * 2.;
   double cos_inner       = std::cos(halfInnerAngle);
 
   double innerFaceLen    = (Hcal_inner_radius + Hcal_radiator_thickness) * tan_inner;
 
-  double layerOuterAngle = (M_PI-innerAngle)/2;
-  double layerInnerAngle = (M_PI/2 - layerOuterAngle);
+  double layerOuterAngle = (M_PI-innerAngle)/2.;
+  double layerInnerAngle = (M_PI/2. - layerOuterAngle);
 
   // First Hcal Barrel Chamber position, start after first radiator
-  double layer_pos_y     = Hcal_inner_radius + Hcal_radiator_thickness;                      
-  double layer_dim_x     = innerFaceLen/2 - gap/2;
+  double layer_pos_x     = Hcal_inner_radius + Hcal_radiator_thickness;                      
+  double layer_dim_y     = innerFaceLen/2. - gap/2.;
 
   // Create Hcal Barrel Chamber without radiator
   // Place into the Hcal Barrel envelope, after each radiator 
   int layer_num = 0;
-  Assembly staveVol("stave");
-  PlacedVolume pv;
-
   for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
     xml_comp_t   x_layer = c;
     int          repeat = x_layer.repeat();          // Get number of layers.
@@ -117,22 +124,23 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
       DetElement  layer(layer_name,_toString(layer_num,"layer%d"),x_det.id());
 
       // Layer position in Z within the stave.
-      layer_pos_y += layer_thickness / 2.0;
+      layer_pos_x += layer_thickness/2.;
       // Active Layer box & volume
-      double active_layer_dim_x = layer_dim_x;
-      double active_layer_dim_y = (detZ-Hcal_lateral_structure_thickness)/2.;
-      double active_layer_dim_z = layer_thickness/2.0;
+      double active_layer_dim_x = layer_thickness/2.;
+      double active_layer_dim_y = layer_dim_y;
+      double active_layer_dim_z = (detZ-Hcal_lateral_structure_thickness)/2.;
 
       // The same Layer will be filled with skices, 
       // and placed into the HcalBarrel 16 times: 8 Staves * 2 modules: TODO 32 times.
       Volume layer_vol(layer_name, Box(active_layer_dim_x,active_layer_dim_y,active_layer_dim_z), air);
 
+
       // ========= Create sublayer slices =========================================
       // Create and place the slices into Layer
       // ==========================================================================
 
       // Create the slices (sublayers) within the Hcal Barrel Chamber.
-      double slice_pos_z = -(layer_thickness / 2);
+      double slice_pos_x = -(layer_thickness/2.);
       int slice_number = 0;
       for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
 	xml_comp_t x_slice = k;
@@ -141,11 +149,11 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
 	Material slice_material  = lcdd.material(x_slice.materialStr());
 	DetElement slice(layer,_toString(slice_number,"slice%d"),x_det.id());
 
-	slice_pos_z += slice_thickness / 2;
+	slice_pos_x += slice_thickness/2.;
 
 	// Slice volume & box
-	double slice_dim_x = active_layer_dim_x - Hcal_layer_air_gap ;
-	Volume slice_vol(slice_name,Box(slice_dim_x,active_layer_dim_y,slice_thickness/2.0),slice_material);
+	double slice_dim_y = active_layer_dim_y - Hcal_layer_air_gap ;
+	Volume slice_vol(slice_name,Box(slice_thickness/2.,slice_dim_y,active_layer_dim_z),slice_material);
 
 	if ( x_slice.isSensitive() ) {
 	  sens.setType("calorimeter");
@@ -154,11 +162,12 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
 	// Set region, limitset, and vis.
 	slice_vol.setAttributes(lcdd,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
 	// slice PlacedVolume
-	pv = layer_vol.placeVolume(slice_vol,Position(0,0,slice_pos_z));
-	pv.addPhysVolID("slice",slice_number);
-	slice.setPlacement(pv);
-	// Increment Z position for next slice.
-	slice_pos_z += slice_thickness / 2;
+	PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol,Position(slice_pos_x,0.,0.));
+	slice_phv.addPhysVolID("slice",slice_number);
+
+	slice.setPlacement(slice_phv);
+	// Increment x position for next slice.
+	slice_pos_x += slice_thickness/2.;
 	// Increment slice number.
 	++slice_number;             
       }
@@ -175,62 +184,65 @@ static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)
       // Acording to the number of staves and modules,
       // Place the same Layer into the HcalBarrel envelope
       // with the right position and rotation.
-
-      // Layer physical volume.
-      double layer_pos_z = active_layer_dim_y + Hcal_lateral_structure_thickness;
-      for(int module_num=0;module_num<2;module_num++)   {
-	layer_pos_z = (module_num==0)?layer_pos_z:-layer_pos_z;
-	Position l_pos(0,layer_pos_y-Hcal_inner_radius,layer_pos_z);
-	pv = staveVol.placeVolume(layer_vol,Transform3D(RotationX(M_PI/2),l_pos));
-	// registry the ID of Layer, stave and module
-	pv.addPhysVolID("layer",layer_num).addPhysVolID("module",module_num);
-	// then setPlacement for it.
-	layer.setPlacement(pv);
+      for(int stave_num = 0; stave_num < numSides; stave_num++){
+	double ds = double(stave_num);
+	double delte_phi = M_PI/2. - innerAngle*ds;
+	string stave_layer = _toString(stave_num,"stave%d_layer");
+	// Layer physical volume.
+	double layer_pos_z = active_layer_dim_z + Hcal_lateral_structure_thickness;
+	for(int module_num = 0; module_num < 2; module_num++)
+	  {
+	    layer_pos_z = (module_num==0)?layer_pos_z:-layer_pos_z;
+	    PlacedVolume layer_phv = envelopeVol.placeVolume(layer_vol,
+							     Transform3D(Rotation(delte_phi,0.,0.),
+									 Translation3D(layer_pos_x*std::cos(delte_phi),
+										       layer_pos_x*std::sin(delte_phi),
+										       layer_pos_z)));
+							     
+	    // registry the ID of Layer, stave and module
+	    layer_phv.addPhysVolID("layer",layer_num);
+	    layer_phv.addPhysVolID("stave",stave_num);
+	    layer_phv.addPhysVolID("module",module_num);
+	    // then setPlacement for it.
+	    layer.setPlacement(layer_phv);
+
+	  }
       }
- 
+
+
       // ===== Prepare for next layer (i.e. next Chamber) =========================
       // Prepare the chamber placement position and the chamber dimension
       // ==========================================================================
 
       // Prepare for next Layer
-      // Increment the layer_pos_y, and calculate the next layer_dim_x
+      // Increment the layer_pos_x, and calculate the next layer_dim_y
       // Place Hcal Barrel Chamber after each radiator 
-      layer_pos_y += layer_thickness / 2;
-      layer_pos_y += Hcal_radiator_thickness;
+      layer_pos_x += layer_thickness/2.;
+      layer_pos_x += Hcal_radiator_thickness;
       // Increment the layer X dimension.
-      if((layer_pos_y + layer_thickness ) < (Hcal_outer_radius - Hcal_back_plate_thickness)* cos_inner)
-	layer_dim_x += (layer_thickness + Hcal_radiator_thickness) * std::tan(layerInnerAngle);
+      if((layer_pos_x + layer_thickness ) < (Hcal_outer_radius - Hcal_back_plate_thickness)* cos_inner)
+	layer_dim_y += (layer_thickness + Hcal_radiator_thickness) * std::tan(layerInnerAngle);
       else
-	layer_dim_x = std::sqrt((Hcal_outer_radius-Hcal_radiator_thickness)
+	layer_dim_y = std::sqrt((Hcal_outer_radius-Hcal_radiator_thickness)
 				*(Hcal_outer_radius-Hcal_radiator_thickness)
-				- layer_pos_y*layer_pos_y) - gap/2;
+				- layer_pos_x*layer_pos_x) - gap/2.;
       // Increment the layer number.
       ++layer_num;         
     }
   }
 
-  // Now place all staves
-  for(int stave_num=0;stave_num<numSides;stave_num++)  {
-    double r = Hcal_inner_radius+Hcal_radiator_thickness;
-    double phi = (2.*M_PI/numSides)*stave_num;
-    Position pos(r*std::sin(phi),r*std::cos(phi),0);
-    pv = envelopeVol.placeVolume(staveVol,Transform3D(Rotation(phi,M_PI,0),pos));
-    // registry the ID of Layer, stave and module
-    pv.addPhysVolID("stave",stave_num);
-  }
 
   // =========== Place Hcal Barrel envelope ===================================
   // Finally place the Hcal Barrel envelope into the world volume.
   // Registry the system ID.
   // ==========================================================================
 
-  // Set envelope volume attributes.
-  envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
   // Place Hcal Barrel volume into the world volume
-  pv = motherVol.placeVolume(envelopeVol,Rotation(0,0,Hcal_Barrel_rotation));
+  PlacedVolume env_phv = motherVol.placeVolume(envelopeVol,Rotation(0.,0.,Hcal_Barrel_rotation));
+
   // registry the system id
-  pv.addPhysVolID("system", sdet.id());
-  sdet.setPlacement(pv);
+  env_phv.addPhysVolID("system", sdet.id());
+  sdet.setPlacement(env_phv);
   return sdet;
 }
 
diff --git a/DDExamples/ILDExDet/src/compact/AhcalEndcapCalorimeter_geo.cpp b/DDExamples/ILDExDet/src/compact/AhcalEndcapCalorimeter_geo.cpp
new file mode 100644
index 000000000..8c1948276
--- /dev/null
+++ b/DDExamples/ILDExDet/src/compact/AhcalEndcapCalorimeter_geo.cpp
@@ -0,0 +1,286 @@
+//====================================================================
+//  AIDA Detector description implementation
+//  for LDC AHCAL Endcap
+//--------------------------------------------------------------------
+//
+//  Author     : S.Lu
+//
+// Basic idea:
+// 1. Create the Hcal Endcap module envelope (16 modules).
+//    Note: with default material Steel235.
+//    
+// 2. Create the Hcal Endcap Chamber(i.e. Layer) for each module.
+//    Create the Layer with slices (Polystyrene,Cu,FR4,air).
+//    Place each slice into the chamber with the right position,
+//    And registry the IDs for slice
+//
+// 3. Place the same Layer into the endcap module envelope.
+//    It will be repeated repeat 48 times.
+//    And registry the IDs for layer, and endcapID.
+//
+// 4. Place the endcap module into the world volume,
+//    with the right position and rotation.
+//    And registry the IDs for stave,module and endcapID.
+//
+// 5. Customer material FR4 and Steel235 defined in materials.xml
+//
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "XML/Layering.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens)  {
+  xml_det_t   x_det     = element;
+  Layering    layering(x_det);
+  xml_dim_t   dim         = x_det.dimensions();
+  string      det_name    = x_det.nameStr();
+  string      det_type    = x_det.typeStr();
+  Material    air         = lcdd.air();
+  Material    Steel235    = lcdd.material(x_det.materialStr());
+  double      gap         = xml_dim_t(x_det).gap();
+  //  int         numSides    = dim.numsides();
+  double      detZ              = dim.z();    // Hcal endcap modules z start
+  double      Hcal_inner_radius = dim.rmin(); // Endcap cernter box hole half length: 362.0
+  
+  // The way to reaad constant from XML/LCDD file.
+  //double      Hcal_outer_radius                = lcdd.constant<double>("Hcal_outer_radius");       // 3395.46 mm
+  double      Hcal_radiator_thickness          = lcdd.constant<double>("Hcal_radiator_thickness"); // 20.0mm
+  //double      Hcal_chamber_thickness           = lcdd.constant<double>("Hcal_chamber_thickness");  // 6.5mm
+  //int         Hcal_endcap_layers               = lcdd.constant<int>("Hcal_endcap_layers");         // 48
+  // ========  Note============================================================
+  // In the XML/LCDD file, make sure the above constant parameters 
+  // are agree with the layering/slices in the detector Ahcal. 
+  // ==========================================================================
+  
+  
+  double      Hcal_lateral_structure_thickness = lcdd.constant<double>("Hcal_lateral_structure_thickness");
+  double      Hcal_layer_air_gap               = lcdd.constant<double>("Hcal_layer_air_gap");
+  double      Hcal_endcap_zmin                 = lcdd.constant<double>("Hcal_endcap_zmin");
+  //double      Hcal_back_plate_thickness        = lcdd.constant<double>("Hcal_back_plate_thickness");
+  
+  // ========= Create Hcal Endcap Modules envelope ============================
+  //  Read the Endcap Modules dimensions,
+  //  Which defined in the compact XML files. 
+  // ==========================================================================
+  double dim_x[16];
+  double dim_y[16];
+  double dim_z[16];
+  double pos_x[16];
+  double pos_y[16];
+  double pos_z[16];
+  
+  int endcapID =0;
+  for(xml_coll_t c(x_det.child(_U(dimensions)),_U(dimensions)); c; ++c) {
+    
+    xml_comp_t l(c);
+    
+    dim_x[endcapID] = l.attr<double>(_Unicode(dim_x));
+    dim_y[endcapID] = l.attr<double>(_Unicode(dim_y));
+    dim_z[endcapID] = l.attr<double>(_Unicode(dim_z));
+    pos_y[endcapID] = l.attr<double>(_Unicode(y_offset));
+    //std::cout<<" dim_z["<<endcapID<<"]: "<< dim_z[endcapID]/2.0<<std::endl;
+    endcapID++;
+  }
+  
+  
+  DetElement   sdet(det_name,x_det.id());
+  Volume      motherVol = lcdd.pickMotherVolume(sdet); 
+  
+  // ========= Create Hcal Endcap Modules envelope ============================
+  //  They will be the volume for palcing the Hcal Chamber(i.e. Layers).
+  //  Themself will be placed into the world volume.
+  // ==========================================================================
+  
+  // build 16 Endcap Modules
+  for(int ecID=0; ecID<endcapID; ecID++)
+    {
+      // Hcal Endcap module shape
+      double box_half_x= dim_x[ecID]/2.0; // module width, all are same
+      double box_half_y= dim_y[ecID]/2.0; // total thickness, all are same
+      double box_half_z= dim_z[ecID]/2.0; // module length, changed, 
+      
+      double x_offset = box_half_x*endcapID-box_half_x*ecID*2.0-box_half_x;
+      double y_offset = pos_y[ecID];
+      
+      Box    EndcapModule(box_half_x,box_half_y,box_half_z);
+      
+      // define the name of each endcap Module
+      string envelopeVol_name   = det_name+_toString(ecID,"_EndcapModule%d");
+      
+      Volume envelopeVol(envelopeVol_name,EndcapModule,Steel235);
+      
+      // Set envelope volume attributes.
+      envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
+      
+      
+      // ========= Create Hcal Chamber (i.e. Layers) ==============================
+      // It will be the sub volume for placing the slices.
+      // Itself will be placed into the Hcal Endcap modules envelope.
+      // ==========================================================================
+      
+      // create Layer (air) and place the slices (Polystyrene,Cu,FR4,air) into it. 
+      // place the Layer into the Hcal Endcap Modules envelope (Steel235).
+      
+      // First Hcal Chamber position, start after first radiator
+      double layer_pos_y     = - box_half_y + Hcal_radiator_thickness;                      
+      
+      // Create Hcal Endcap Chamber without radiator
+      // Place into the Hcal Encap module envelope, after each radiator 
+      int layer_num = 0;
+      for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
+	xml_comp_t   x_layer = c;
+	int          repeat = x_layer.repeat();          // Get number of layers.
+	const Layer* lay    = layering.layer(layer_num); // Get the layer from the layering engine.
+	
+	string layer_name      = envelopeVol_name+"_layer";
+	double layer_thickness = lay->thickness();
+	DetElement  layer(layer_name,layer_name,x_det.id());
+	
+	// Active Layer box & volume
+	double active_layer_dim_x = box_half_x - Hcal_lateral_structure_thickness;
+	double active_layer_dim_y = layer_thickness/2.0;
+	double active_layer_dim_z = box_half_z;
+	
+	// Build chamber including air gap
+	// The Layer will be filled with slices, 
+	Volume layer_vol(layer_name, Box((active_layer_dim_x + Hcal_layer_air_gap),
+					 active_layer_dim_y,active_layer_dim_z), air);
+	
+	
+	// ========= Create sublayer slices =========================================
+	// Create and place the slices into Layer
+	// ==========================================================================
+	
+	// Create the slices (sublayers) within the Hcal Chamber.
+	double slice_pos_y = -(layer_thickness / 2.0);
+	int slice_number = 0;
+	for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+	  xml_comp_t x_slice = k;
+	  string   slice_name      = layer_name + _toString(slice_number,"_slice%d");
+	  double   slice_thickness = x_slice.thickness();
+	  Material slice_material  = lcdd.material(x_slice.materialStr());
+	  DetElement slice(layer,_toString(slice_number,"slice%d"),x_det.id());
+	  
+	  slice_pos_y += slice_thickness / 2.0;
+	  
+	  // Slice volume & box
+	  Volume slice_vol(slice_name,Box(active_layer_dim_x,slice_thickness/2.0,active_layer_dim_z),slice_material);
+	  
+	  if ( x_slice.isSensitive() ) {
+	    sens.setType("calorimeter");
+	    slice_vol.setSensitiveDetector(sens);
+	  }
+	  // Set region, limitset, and vis.
+	  slice_vol.setAttributes(lcdd,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+	  // slice PlacedVolume
+	  PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol,Position(0,slice_pos_y,0));
+	  slice_phv.addPhysVolID("slice",slice_number);
+	  
+	  slice.setPlacement(slice_phv);
+	  // Increment Z position for next slice.
+	  slice_pos_y += slice_thickness / 2.0;
+	  // Increment slice number.
+	  ++slice_number;             
+	}
+	// Set region, limitset, and vis.
+	layer_vol.setAttributes(lcdd,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
+	
+	
+	// ========= Place the Layer (i.e. Chamber) =================================
+	// Place the Layer into the Hcal Endcap module envelope.
+	// with the right position and rotation.
+	// Registry the IDs (layer, stave, module).
+	// Place the same layer 48 times into Endcap module
+	// ==========================================================================
+	
+	for (int j = 0; j < repeat; j++)    {
+	  
+	  // Layer position in y within the Endcap Modules.
+	  layer_pos_y += layer_thickness / 2.0;
+	  
+	  PlacedVolume layer_phv = envelopeVol.placeVolume(layer_vol,
+							   Position(0,layer_pos_y,0));
+	  // registry the ID of Layer, stave and module
+	  layer_phv.addPhysVolID("layer",layer_num);
+	  layer_phv.addPhysVolID("endcapID",ecID);
+	  // then setPlacement for it.
+	  layer.setPlacement(layer_phv);
+	  
+	  
+	  // ===== Prepare for next layer (i.e. next Chamber) =========================
+	  // Prepare the chamber placement position and the chamber dimension
+	  // ==========================================================================
+	  
+	  // Increment the layer_pos_y
+	  // Place Hcal Chamber after each radiator 
+	  layer_pos_y += layer_thickness / 2.0;
+	  layer_pos_y += Hcal_radiator_thickness;
+	  ++layer_num;         
+	}
+	
+	
+      }
+      
+      
+      // =========== Place Hcal Endcap envelope ===================================
+      // Finally place the Hcal Endcap envelope into the world volume.
+      // Registry the stave(up/down), module(left/right) and endcapID.
+      // ==========================================================================
+      
+      // Acording to the number of staves and modules,
+      // Place the same Hcal Endcap module volume into the world volume
+      // with the right position and rotation.
+      for(int stave_num=0;stave_num<2;stave_num++){
+	
+	double EndcapModule_pos_x;
+	double EndcapModule_pos_y;
+	double EndcapModule_pos_z = Hcal_endcap_zmin + box_half_y;
+	double rot_EM = 0;
+	
+	switch (stave_num)
+	  {
+	  case 0 : 
+	    EndcapModule_pos_x = x_offset;
+	    EndcapModule_pos_y = y_offset;
+	    break;
+	  case 1 : 
+	    EndcapModule_pos_x = -x_offset;
+	    EndcapModule_pos_y = -y_offset;
+	    break;
+	  }
+	
+	for(int module_num=0;module_num<2;module_num++) {
+	  
+	  rot_EM = (module_num==0)?(M_PI/2.0):(-M_PI/2.0);
+	  
+	  EndcapModule_pos_z = (module_num==0)?EndcapModule_pos_z:-EndcapModule_pos_z;
+
+	  PlacedVolume env_phv = motherVol.placeVolume(envelopeVol,
+						       Transform3D(Rotation(0.,0.,rot_EM),
+								   Translation3D(EndcapModule_pos_x,
+										 EndcapModule_pos_y,
+										 EndcapModule_pos_z)));
+	  
+	  env_phv.addPhysVolID("stave",stave_num);   // y: up /down
+	  env_phv.addPhysVolID("module",module_num); // z: +/-
+	  env_phv.addPhysVolID("system",x_det.id());
+	  sdet.setPlacement(env_phv);
+	  
+	}
+	
+      }
+      
+    }
+  
+  
+  
+  return sdet;
+}
+
+
+
+
+DECLARE_DETELEMENT(AhcalEndcapCalorimeter, create_detector);
-- 
GitLab