From f3d954dc864dec8712fdb0dad72249f712cc5cbc Mon Sep 17 00:00:00 2001
From: Chengdong Fu <fucd@ihep.ac.cn>
Date: Fri, 11 Dec 2020 01:51:53 +0800
Subject: [PATCH] first import CEPC_v4 Hcal

---
 Detector/DetCEPCv4/CMakeLists.txt             |   3 +
 Detector/DetCEPCv4/compact/CepC_v4.xml        |  29 +-
 .../DetCEPCv4/compact/Hcal_Barrel_SD_v01.xml  |  47 ---
 .../compact/Hcal_EndcapRing_SD_v01.xml        |  56 ---
 .../DetCEPCv4/compact/Hcal_Endcaps_SD_v01.xml |  53 ---
 .../compact/SHcalRpc01_Barrel_01.xml          |  41 +++
 .../compact/SHcalRpc01_EndcapRing_01.xml      |  41 +++
 .../compact/SHcalRpc01_Endcaps_01.xml         |  38 ++
 Detector/DetCEPCv4/compact/envelope_defs.xml  |   3 +-
 Detector/DetCEPCv4/compact/hcal_defs.xml      | 122 +++----
 Detector/DetCEPCv4/compact/top_defs.xml       |   7 +-
 .../src/calorimeter/SHcalRpc01_Barrel.cpp     | 333 ++++++++++++++++++
 .../src/calorimeter/SHcalRpc01_EndcapRing.cpp | 266 ++++++++++++++
 .../src/calorimeter/SHcalRpc01_Endcaps.cpp    | 269 ++++++++++++++
 14 files changed, 1059 insertions(+), 249 deletions(-)
 delete mode 100644 Detector/DetCEPCv4/compact/Hcal_Barrel_SD_v01.xml
 delete mode 100644 Detector/DetCEPCv4/compact/Hcal_EndcapRing_SD_v01.xml
 delete mode 100644 Detector/DetCEPCv4/compact/Hcal_Endcaps_SD_v01.xml
 create mode 100644 Detector/DetCEPCv4/compact/SHcalRpc01_Barrel_01.xml
 create mode 100644 Detector/DetCEPCv4/compact/SHcalRpc01_EndcapRing_01.xml
 create mode 100644 Detector/DetCEPCv4/compact/SHcalRpc01_Endcaps_01.xml
 create mode 100644 Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Barrel.cpp
 create mode 100644 Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_EndcapRing.cpp
 create mode 100644 Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Endcaps.cpp

diff --git a/Detector/DetCEPCv4/CMakeLists.txt b/Detector/DetCEPCv4/CMakeLists.txt
index e969df42..69bcc73e 100644
--- a/Detector/DetCEPCv4/CMakeLists.txt
+++ b/Detector/DetCEPCv4/CMakeLists.txt
@@ -32,6 +32,9 @@ set(DetCEPCv4_src
     src/calorimeter/SEcal05_Barrel.cpp
     src/calorimeter/SEcal05_Endcaps.cpp
     src/calorimeter/SEcal05_ECRing.cpp
+    src/calorimeter/SHcalRpc01_Barrel.cpp
+    src/calorimeter/SHcalRpc01_Endcaps.cpp
+    src/calorimeter/SHcalRpc01_EndcapRing.cpp
     src/other/BoxSupport_o1_v01_geo.cpp
     src/other/TubeSupport_o1_v01_geo.cpp
 )
diff --git a/Detector/DetCEPCv4/compact/CepC_v4.xml b/Detector/DetCEPCv4/compact/CepC_v4.xml
index 393a40e9..e79cadaa 100644
--- a/Detector/DetCEPCv4/compact/CepC_v4.xml
+++ b/Detector/DetCEPCv4/compact/CepC_v4.xml
@@ -34,6 +34,15 @@
     <!-- Readout slice in hcal for reconstruction -->
     <constant name="Hcal_readout_segmentation_slice" value="3"/>
   </define>
+  <materials>
+    <material name="RPC2ECRMix" state="solid">
+      <D unit="g/cm3" value="Hcal_mix_density"/>
+      <composite n="Hcal_airgap_fraction" ref="Air"/>
+      <composite n="Hcal_graphite_fraction" ref="graphite"/>
+      <composite n="Hcal_mylar_fraction" ref="mylar"/>
+      <composite n="Hcal_g10_fraction" ref="g10"/>
+    </material>
+  </materials>
   <limits>
     <limitset name="cal_limits">
       <limit name="step_length_max" particles="*" value="cal_steplimit_val" unit="cal_steplimit_unit" />
@@ -46,19 +55,19 @@
     </limitset>
   </limits>
   <include ref="display.xml"/>
-  <include ref="Beampipe_o1_v01_01.xml"/>
-  <!--include ref="vxd07.xml"/>
-  <include ref="ftd_simple_staggered_02.xml"/>
-  <include ref="sit_simple_pixel_sensors_01.xml"/>
+  <!--include ref="Beampipe_o1_v01_01.xml"/>
+  <include ref="vxd07.xml"/>
+  <include ref="ftd_cepc.xml"/>
+  <include ref="sit_simple_planar_sensors_01.xml"/>
   <include ref="tpc10_01.xml"/>
-  <include ref="set_simple_planar_sensors_01.xml"/-->
+  <include ref="set_simple_planar_sensors_01.xml"/>
   <include ref="SEcal05_siw_Barrel.xml"/>
   <include ref="SEcal05_siw_Endcaps.xml"/>
-  <include ref="SEcal05_siw_ECRing.xml"/>
-  <!--include ref="Hcal_Barrel_SD_v01.xml"/>
-  <include ref="Hcal_Endcaps_SD_v01.xml"/>
-  <include ref="Hcal_EndcapRing_SD_v01.xml"/>
-  <include ref="Yoke05_Barrel.xml"/>
+  <include ref="SEcal05_siw_ECRing.xml"/-->
+  <include ref="SHcalRpc01_Barrel_01.xml"/>
+  <include ref="SHcalRpc01_Endcaps_01.xml"/>
+  <include ref="SHcalRpc01_EndcapRing_01.xml"/>
+  <!--include ref="Yoke05_Barrel.xml"/>
   <include ref="Yoke05_Endcaps.xml"/>
   <include ref="LumiCal.xml"/-->
 
diff --git a/Detector/DetCEPCv4/compact/Hcal_Barrel_SD_v01.xml b/Detector/DetCEPCv4/compact/Hcal_Barrel_SD_v01.xml
deleted file mode 100644
index bfee3f1b..00000000
--- a/Detector/DetCEPCv4/compact/Hcal_Barrel_SD_v01.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<lccdd>
-
-  <detectors>
-    <detector name="HcalBarrel" type="Hcal_Barrel_SD_v01" id="ILDDetID_HCAL" readout="HCalBarrelRPCHits" vis="GreenVis" insideTrackingVolume="false" >
-      <comment>Hadron Calorimeter Barrel</comment>
-
-      <envelope vis="ILD_HCALVis">
-        <shape type="BooleanShape" operation="Subtraction" material="Air" >
-          <shape type="Cone" z="Hcal_half_length + env_safety/2" rmin1="0.0" rmax1="Hcal_outer_radius + env_safety" rmin2="0.0" rmax2="Hcal_outer_radius + env_safety"/>
-          <shape type="PolyhedraRegular"  numsides="Hcal_inner_symmetry" rmin="0.0"
-                 rmax="Hcal_inner_radius - env_safety" dz="2*(Hcal_half_length + env_safety)"/>
-        </shape>
-        <rotation x="0" y="0" z="90*deg-180*deg/Hcal_inner_symmetry"/>
-      </envelope>
-      <type_flags type=" DetType_CALORIMETER + DetType_BARREL + DetType_HADRONIC " />
-
-      <staves  material = "Steel304L"  vis="BlueVis"/>
-
-      <!-- The layer structure reference in the following paper-->
-      <!-- ???  -->
-      <layer repeat="HcalBarrelSD_nlayers" vis="SeeThrough">
-        <slice material = "Steel304L"      thickness = "HcalSD_radiator_thickness"                    vis="BlueVis"   />
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"   />
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   />
-        <slice material = "epoxy"          thickness = "HcalSD_electronics_mask_thickness"            vis="GreenVis" />
-        <slice material = "PCB"            thickness = "HcalSD_PCB_thickness"                         vis="CyanVis" />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_anode_thickness"                 vis="MagentaVis" />
-        <slice material = "graphite"       thickness = "HcalSD_graphite_anode_thickness"              vis="Invisible" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_anode_thickness"                 vis="RedVis" />
-        <slice material = "RPCGAS2"        thickness = "HcalSD_sensitive_gas_gap"   sensitive = "yes"   vis="YellowVis" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_cathode_thickness"               vis="RedVis" />
-        <slice material = "graphite"       thickness = "HcalSD_graphite_cathode_thickness"            vis="Invisible" />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_cathode_thickness"               vis="MagentaVis" />
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   />
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"   />
-      </layer>
-    </detector>
-  </detectors>
-
-  <readouts>
-    <readout name="HCalBarrelRPCHits">
-      <segmentation type="CartesianGridXY" grid_size_x="HcalSD_cells_size" grid_size_y="HcalSD_cells_size"/>
-      <id>system:5,module:3,stave:3,tower:5,layer:6,slice:4,x:32:-16,y:-16</id>
-    </readout>
-  </readouts>
-
-</lccdd>
diff --git a/Detector/DetCEPCv4/compact/Hcal_EndcapRing_SD_v01.xml b/Detector/DetCEPCv4/compact/Hcal_EndcapRing_SD_v01.xml
deleted file mode 100644
index ee89545a..00000000
--- a/Detector/DetCEPCv4/compact/Hcal_EndcapRing_SD_v01.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<lccdd>
-
-  <detectors>
-    <detector name="HcalRing" type="Hcal_EndcapRing_SD_v01" id="ILDDetID_HCAL_RING" readout="HCalECRingRPCHits" vis="SeeThrough" insideTrackingVolume="false" >
-      <comment>Hadron Calorimeter EndcapRing</comment>
-
-      <envelope vis="ILD_HCALVis">
-        <shape type="BooleanShape" operation="Subtraction" material="Air">
-          <shape type="BooleanShape" operation="Intersection" material="Air">
-            <shape type="Box" dx="HcalEndcapRing_outer_radius + 2.0*env_safety" dy="HcalEndcapRing_outer_radius + 2.0*env_safety"
-                   dz="HcalEndcapRing_max_z + 2.0*env_safety"/> <!--Box defined the coordinate system-->
-            <shape type="PolyhedraRegular" numsides="HcalEndcapRingSD_inner_symmetry" rmin="HcalEndcapRing_inner_radius - env_safety"
-                   rmax="HcalEndcapRing_outer_radius + env_safety" dz="2.0*HcalEndcapRing_max_z + env_safety" material="Air"/>
-            <rotation x="0" y="0" z="90*deg-180*deg/HcalEndcapRingSD_inner_symmetry"/>
-          </shape>
-
-          <shape type="Box" dx="HcalEndcapRing_outer_radius + 2.0*env_safety" dy="HcalEndcapRing_outer_radius + 2.0*env_safety"
-                 dz="HcalEndcapRing_min_z - env_safety"/>
-        </shape>
-      </envelope>
-
-      <type_flags type=" DetType_CALORIMETER + DetType_ENDCAP + DetType_HADRONIC + DetType_AUXILIARY " />
-
-      <!-- absorber material
-        -->
-      <staves  material = "Steel304L"  vis="GreenVis"/>
-      <material name="Steel304L"/>
-
-      <layer repeat="HcalEndcapRingSD_nlayers" vis="SeeThrough">
-        <slice material = "Steel304L"      thickness = "HcalSD_radiator_thickness"                    vis="BlueVis"   />
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"   />
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   />
-        <slice material = "epoxy"          thickness = "HcalSD_electronics_mask_thickness"            vis="GreenVis" />
-        <slice material = "PCB"            thickness = "HcalSD_PCB_thickness"                         vis="CyanVis" />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_anode_thickness"                 vis="MagentaVis" />
-        <slice material = "graphite"       thickness = "HcalSD_graphite_anode_thickness"              vis="Invisible" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_anode_thickness"                 vis="RedVis" />
-        <slice material = "RPCGAS2"        thickness = "HcalSD_sensitive_gas_gap"  sensitive = "yes"   vis="YellowVis" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_cathode_thickness"               vis="RedVis" />
-        <slice material = "graphite"       thickness = "HcalSD_graphite_cathode_thickness"            vis="Invisible" />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_cathode_thickness"               vis="MagentaVis" />
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   />
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"   />
-      </layer>
-    </detector>
-  </detectors>
-
-  <readouts>
-    <readout name="HCalECRingRPCHits">
-      <segmentation type="CartesianGridXY" grid_size_x="HcalSD_cells_size" grid_size_y="HcalSD_cells_size"/>
-      <id>system:5,module:3,stave:4,tower:3,layer:6,x:32:-16,y:-16</id>
-    </readout>
-  </readouts>
-
-</lccdd>
-
diff --git a/Detector/DetCEPCv4/compact/Hcal_Endcaps_SD_v01.xml b/Detector/DetCEPCv4/compact/Hcal_Endcaps_SD_v01.xml
deleted file mode 100644
index 3b77b0fa..00000000
--- a/Detector/DetCEPCv4/compact/Hcal_Endcaps_SD_v01.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<lccdd>
-
-<detectors>
-<detector id="ILDDetID_HCAL_ENDCAP" name="HcalEndcap" type="Hcal_Endcaps_SD_v01" readout="HCalEndcapRPCHits"  vis="SeeThrough" calorimeterType="HAD_ENDCAP">
- <comment>Hadron Calorimeter Endcap</comment>
-
-
-    <envelope vis="ILD_HCALVis">    
-      <shape type="BooleanShape" operation="Subtraction" material="Air"><!--2. create center box hole -->
-        <shape type="BooleanShape" operation="Subtraction" material="Air"><!--1. create Endcaps envelope -->
-          <shape type="Tube" rmin="0.0" rmax="HcalEndcap_outer_radius + env_safety" dz="HcalEndcap_max_z + env_safety"/>
-          <shape type="Tube" rmin="0.0" rmax="HcalEndcap_outer_radius + 2.0*env_safety" dz="HcalEndcap_min_z - env_safety"/>
-        </shape>
-        <shape type="Box" dx="HcalEndcap_inner_radius - env_safety" dy="HcalEndcap_inner_radius - env_safety" 
-               dz="HcalEndcap_max_z + 2.0*env_safety"/>
-      </shape>
-      <rotation x="0" y="0" z="0"/>
-    </envelope>
-
-    <type_flags type=" DetType_CALORIMETER + DetType_ENDCAP + DetType_HADRONIC " />
-    <material name="Steel304L"/><!-- radiator and the thickness has been defined in the main xml file-->
-    <staves  material = "Steel235"  vis="SeeThrough"/>
-
-
-      <!-- slice: from inner  to outer -->  
-    <layer repeat="HcalEndcapSD_nlayers" vis="SeeThrough">  
-        <slice material = "Steel304L"      thickness = "HcalSD_radiator_thickness"                    vis="BlueVis"   />   
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"  /> 
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   />
-        <slice material = "epoxy"          thickness = "HcalSD_electronics_mask_thickness"            vis="GreenVis"  />
-        <slice material = "PCB"            thickness = "HcalSD_PCB_thickness"                         vis="CyanVis"   />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_anode_thickness"                 vis="MagentaVis"/>
-        <slice material = "graphite"       thickness = "HcalSD_graphite_anode_thickness"              vis="Invisible" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_anode_thickness"                 vis="RedVis"    />
-        <slice material = "RPCGAS2"        thickness = "HcalSD_sensitive_gas_gap"   sensitive = "yes"   vis="YellowVis" />
-        <slice material = "FloatGlass"     thickness = "HcalSD_glass_cathode_thickness"               vis="RedVis"    />
-        <slice material = "graphite"       thickness = "HcalSD_graphite_cathode_thickness"            vis="Invisible" />
-        <slice material = "mylar"          thickness = "HcalSD_mylar_cathode_thickness"               vis="MagentaVis"/>
-        <slice material = "Steel304L"      thickness = "HcalSD_steel_casette_thickness"               vis="BlueVis"   /> 
-        <slice material = "Air"            thickness = "HcalSD_airgap_thickness"                      vis="WhiteVis"  />  
-    </layer>
-
-</detector>
-</detectors>
-
-<readouts>
-  <readout name="HCalEndcapRPCHits">
-    <segmentation type="CartesianGridXY" grid_size_x="HcalSD_cells_size" grid_size_y="HcalSD_cells_size" offset_x="HcalSD_cells_size/2.0" offset_y="HcalSD_cells_size/2.0" />
-    <id>system:5,module:3,stave:3,tower:5,layer:6,x:32:-16,y:-16</id>
-  </readout>
-</readouts>
-
-</lccdd>
diff --git a/Detector/DetCEPCv4/compact/SHcalRpc01_Barrel_01.xml b/Detector/DetCEPCv4/compact/SHcalRpc01_Barrel_01.xml
new file mode 100644
index 00000000..8ea02125
--- /dev/null
+++ b/Detector/DetCEPCv4/compact/SHcalRpc01_Barrel_01.xml
@@ -0,0 +1,41 @@
+<lccdd>
+  <detectors>
+    <detector name="HcalBarrel" type="SHcalRpc01_Barrel" id="ILDDetID_HCAL" readout="HcalBarrelCollection" vis="GreenVis" insideTrackingVolume="false" >
+      <comment>Hadron Calorimeter Barrel</comment>
+      <envelope vis="ILD_HCALVis">
+        <shape type="BooleanShape" operation="Subtraction" material="Air" >
+          <shape type="Cone" z="Hcal_half_length + env_safety/2" rmin1="0.0" rmax1="Hcal_outer_radius + env_safety" rmin2="0.0" rmax2="Hcal_outer_radius + env_safety"/>
+          <shape type="PolyhedraRegular"  numsides="Hcal_inner_symmetry" rmin="0.0"
+                 rmax="Hcal_inner_radius - env_safety" dz="2*(Hcal_half_length + env_safety)"/>
+	  <rotation x="0" y="0" z="-180*deg/Hcal_inner_symmetry"/>
+        </shape>
+        <!--rotation x="0" y="0" z="90*deg-180*deg/Hcal_inner_symmetry"/-->
+      </envelope>
+      <type_flags type=" DetType_CALORIMETER + DetType_BARREL + DetType_HADRONIC " />
+
+      <staves  material="stainless_steel"  vis="BlueVis"/>
+
+      <layer repeat="Hcal_nlayers" vis="SeeThrough">
+        <slice material="stainless_steel" thickness="Hcal_radiator_thickness"                    vis="BlueVis"   />
+        <slice material="Air"             thickness="Hcal_airgap_thickness"                      vis="WhiteVis"   />
+	<slice material="mylar"           thickness="Hcal_mylar_cathode_thickness"               vis="MagentaVis" />
+	<slice material="graphite"        thickness="Hcal_graphite_cathode_thickness"            vis="Invisible" />
+	<slice material="FloatGlass"      thickness="Hcal_glass_cathode_thickness"               vis="RedVis" />
+	<slice material="RPCGAS2"         thickness="Hcal_sensitive_gas_gap"   sensitive = "yes" vis="YellowVis" edge_material="PEEK-GF30" spacer_material="Nylon"/>
+	<slice material="FloatGlass"      thickness="Hcal_glass_anode_thickness"                 vis="RedVis" />
+	<slice material="graphite"        thickness="Hcal_graphite_anode_thickness"              vis="Invisible" />
+	<slice material="mylar"           thickness="Hcal_mylar_anode_thickness"                 vis="MagentaVis" />
+	<slice material="g10"             thickness="Hcal_PCB_thickness"                         vis="CyanVis" />
+	<slice material="g10"             thickness="Hcal_electronics_mask_thickness"            vis="GreenVis" />
+      </layer>
+    </detector>
+  </detectors>
+
+  <readouts>
+    <readout name="HcalBarrelCollection">
+      <segmentation type="CartesianGridXY" grid_size_x="Hcal_cells_size" grid_size_y="Hcal_cells_size"/>
+      <id>system:5,module:3,stave:3,tower:5,layer:6,slice:4,x:32:-16,y:-16</id>
+    </readout>
+  </readouts>
+
+</lccdd>
diff --git a/Detector/DetCEPCv4/compact/SHcalRpc01_EndcapRing_01.xml b/Detector/DetCEPCv4/compact/SHcalRpc01_EndcapRing_01.xml
new file mode 100644
index 00000000..824b932c
--- /dev/null
+++ b/Detector/DetCEPCv4/compact/SHcalRpc01_EndcapRing_01.xml
@@ -0,0 +1,41 @@
+<lccdd>
+  <detectors>
+    <detector name="HcalRing" type="SHcalRpc01_EndcapRing" id="ILDDetID_HCAL_RING" readout="HcalEndcapRingCollection" vis="SeeThrough" insideTrackingVolume="false" >
+      <comment>Hadron Calorimeter EndcapRing</comment>
+      <envelope vis="ILD_HCALVis">
+	<!--shape type="Assembly"/-->
+        <shape type="BooleanShape" operation="Subtraction" material="Air">
+          <shape type="BooleanShape" operation="Intersection" material="Air">
+            <shape type="Box" dx="HcalEndcapRing_outer_radius + 2.0*env_safety" dy="HcalEndcapRing_outer_radius + 2.0*env_safety"
+                   dz="HcalEndcapRing_max_z + 2.0*env_safety"/>
+            <shape type="PolyhedraRegular" numsides="Hcal_ring_inner_symmetry" rmin="HcalEndcapRing_inner_radius - env_safety"
+                   rmax="HcalEndcapRing_outer_radius + env_safety" dz="2.0*HcalEndcapRing_max_z + env_safety" material="Air"/>
+            <rotation x="0" y="0" z="90*deg-180*deg/Hcal_ring_inner_symmetry"/>
+          </shape>
+          <shape type="Box" dx="HcalEndcapRing_outer_radius + 2.0*env_safety" dy="HcalEndcapRing_outer_radius + 2.0*env_safety"
+                 dz="HcalEndcapRing_min_z - env_safety"/>
+        </shape>
+      </envelope>
+
+      <type_flags type=" DetType_CALORIMETER + DetType_ENDCAP + DetType_HADRONIC + DetType_AUXILIARY " />
+      <staves material="stainless_steel" vis="GreenVis"/>
+
+      <layer repeat="HcalEndcapRing_nlayers" vis="SeeThrough">
+	<slice material="stainless_steel" thickness="Hcal_radiator_thickness"                    vis="BlueVis"/>
+	<slice material="FloatGlass"      thickness="Hcal_glass_cathode_thickness"               vis="RedVis"/>
+        <slice material="RPCGAS2"         thickness="Hcal_sensitive_gas_gap"   sensitive = "yes" vis="YellowVis"/>
+        <slice material="FloatGlass"      thickness="Hcal_glass_anode_thickness"                 vis="RedVis"/>
+        <slice material="RPC2ECRMix"      thickness="Hcal_mix_thickness"                         vis="CyanVis"/>
+      </layer>
+    </detector>
+  </detectors>
+
+  <readouts>
+    <readout name="HcalEndcapRingCollection">
+      <segmentation type="CartesianGridXY" grid_size_x="Hcal_cells_size" grid_size_y="Hcal_cells_size"/>
+      <id>system:5,module:3,stave:4,tower:3,layer:6,x:32:-16,y:-16</id>
+    </readout>
+  </readouts>
+  
+</lccdd>
+
diff --git a/Detector/DetCEPCv4/compact/SHcalRpc01_Endcaps_01.xml b/Detector/DetCEPCv4/compact/SHcalRpc01_Endcaps_01.xml
new file mode 100644
index 00000000..677a23dd
--- /dev/null
+++ b/Detector/DetCEPCv4/compact/SHcalRpc01_Endcaps_01.xml
@@ -0,0 +1,38 @@
+<lccdd>
+  <detectors>
+    <detector id="ILDDetID_HCAL_ENDCAP" name="HcalEndcap" type="SHcalRpc01_Endcaps" readout="HcalEndcapsCollection"  vis="SeeThrough" calorimeterType="HAD_ENDCAP">
+      <comment>Hadron Calorimeter Endcap</comment>
+      <envelope vis="ILD_HCALVis">    
+	<shape type="BooleanShape" operation="Subtraction" material="Air">
+          <shape type="BooleanShape" operation="Subtraction" material="Air">
+            <shape type="Tube" rmin="0.0" rmax="HcalEndcap_outer_radius + env_safety" dz="HcalEndcap_max_z + env_safety"/>
+            <shape type="Tube" rmin="0.0" rmax="HcalEndcap_outer_radius + 2.0*env_safety" dz="HcalEndcap_min_z - env_safety"/>
+          </shape>
+          <shape type="Box" dx="HcalEndcap_inner_radius - env_safety" dy="HcalEndcap_inner_radius - env_safety" dz="HcalEndcap_max_z + 2.0*env_safety"/>
+	</shape>
+	<rotation x="0" y="0" z="0"/>
+      </envelope>
+      
+      <type_flags type="DetType_CALORIMETER + DetType_ENDCAP + DetType_HADRONIC " />
+      
+      <staves material="stainless_steel" vis="SeeThrough"/>
+
+      <layer repeat="Hcal_endcap_nlayers" vis="SeeThrough">  
+	<slice material="stainless_steel" thickness="Hcal_radiator_thickness"                    vis="BlueVis"/>
+	<slice material="FloatGlass"      thickness="Hcal_glass_cathode_thickness"               vis="RedVis"/>
+	<slice material="RPCGAS2"         thickness="Hcal_sensitive_gas_gap"   sensitive = "yes" vis="YellowVis"/>
+        <slice material="FloatGlass"      thickness="Hcal_glass_anode_thickness"                 vis="RedVis"/>
+        <slice material="RPC2ECRMix"      thickness="Hcal_mix_thickness"                         vis="CyanVis"/>
+      </layer>
+      
+    </detector>
+  </detectors>
+
+  <readouts>
+    <readout name="HcalEndcapsCollection">
+      <segmentation type="CartesianGridXY" grid_size_x="Hcal_cells_size" grid_size_y="Hcal_cells_size" offset_x="Hcal_cells_size/2.0" offset_y="Hcal_cells_size/2.0" />
+      <id>system:5,module:3,stave:3,tower:5,layer:6,x:32:-16,y:-16</id>
+    </readout>
+  </readouts>
+  
+</lccdd>
diff --git a/Detector/DetCEPCv4/compact/envelope_defs.xml b/Detector/DetCEPCv4/compact/envelope_defs.xml
index 920b90ee..5b900a1b 100644
--- a/Detector/DetCEPCv4/compact/envelope_defs.xml
+++ b/Detector/DetCEPCv4/compact/envelope_defs.xml
@@ -93,7 +93,8 @@
   <constant name="Ecal_symmetry"        value="Ecal_Hcal_symmetry"/>
 
   <constant name="Hcal_inner_radius"    value="Ecal_outer_radius+Hcal_Ecal_gap"/>
-  <constant name="Hcal_outer_radius"    value="(Hcal_inner_radius+Hcal_barrel_thickness)/cos(pi/Hcal_outer_symmetry)"/> <!-- cos(pi/16)   -->
+  <!--constant name="Hcal_outer_radius"    value="(Hcal_inner_radius+Hcal_barrel_thickness)/cos(pi/Hcal_outer_symmetry)"/--> <!-- cos(pi/16)   -->
+  <constant name="Hcal_outer_radius"    value="3144.43*mm"/>
   <constant name="Hcal_half_length"     value="TPC_Ecal_Hcal_barrel_halfZ"/>
   <constant name="Hcal_inner_symmetry"  value="Ecal_Hcal_symmetry"/>
 
diff --git a/Detector/DetCEPCv4/compact/hcal_defs.xml b/Detector/DetCEPCv4/compact/hcal_defs.xml
index 12f7ba31..c9d72eae 100644
--- a/Detector/DetCEPCv4/compact/hcal_defs.xml
+++ b/Detector/DetCEPCv4/compact/hcal_defs.xml
@@ -1,85 +1,49 @@
 <define>
-
-
   <constant name="Hcal_radiator_thickness" value="20.0*mm"/>
-  <constant name="Hcal_chamber_thickness" value="6.73*mm"/>
-  <constant name="Hcal_back_plate_thickness" value="15*mm"/>
-  <constant name="Hcal_lateral_structure_thickness" value="10*mm"/>
-  <constant name="Hcal_stave_gaps" value="3*mm"/>
-  <constant name="Hcal_modules_gap" value="0.001*mm"/>
-  <constant name="Hcal_layer_air_gap" value="2*mm"/>
-  <constant name="Hcal_middle_stave_gaps" value="10*mm"/>
+  <constant name="Hcal_airgap_thickness" value="1*mm"/>
+  <constant name="Hcal_mylar_cathode_thickness" value="0.18*mm"/>
+  <constant name="Hcal_graphite_cathode_thickness" value="0.05*mm"/>
+  <constant name="Hcal_glass_cathode_thickness" value="1.1*mm"/>
+  <constant name="Hcal_sensitive_gas_gap" value="1.2*mm"/>
+  <constant name="Hcal_glass_anode_thickness" value="0.7*mm"/>
+  <constant name="Hcal_graphite_anode_thickness" value="0.05*mm"/>
+  <constant name="Hcal_mylar_anode_thickness" value="0.05*mm"/>
+  <constant name="Hcal_PCB_thickness" value="0.8*mm"/>
+  <constant name="Hcal_electronics_mask_thickness" value="1.6*mm"/>
+  
   <constant name="Hcal_nlayers" value="40"/>
-  <constant name="Hcal_fiber_gap" value="1.5*mm"/>
-  <constant name="Hcal_Cu_thickness" value="0.1*mm"/>
-  <constant name="Hcal_PCB_thickness" value="0.7*mm"/>
-  <constant name="Hcal_scintillator_thickness" value="3.0*mm"/>
+  <constant name="Hcal_endcap_nlayers" value="Hcal_nlayers"/>
+  <constant name="Hcal_ring_nlayers"         value="7"/>
   <constant name="Hcal_cells_size" value="10*mm"/>
-  <constant name="Hcal_endcap_lateral_structure_thickness" value="5.0*mm"/>
-  <constant name="Hcal_endcap_layer_air_gap" value="2.5*mm"/>
-  <constant name="Hcal_endcap_nlayers" value="40"/> <!-- needed for ring only? -->
-
-  <!-- fg:
-      copy extra parameters for SDHcal from ILD_o2_v01 here
-      maybe they should all be renamed to SDHCal_ for clarity ? 
-     TK: Yes, here are they ... HcalSD_  
-  -->
-  <constant name="HcalSD_cells_size" value="10.406*mm"/>
-  <constant name="HcalSD_pad_separation" value="0.406*mm"/>
-  <constant name="HcalSD_radiator_thickness" value="15.0*mm"/>
-  <constant name="HcalSD_sensitive_gas_gap" value="1.2*mm"/>
-  <constant name="HcalSD_graphite_cathode_thickness" value="0.05*mm"/>
-  <constant name="HcalSD_graphite_anode_thickness" value="0.05*mm"/>
-  <constant name="HcalSD_glass_cathode_thickness" value="1.1*mm"/>
-  <constant name="HcalSD_glass_anode_thickness" value="0.7*mm"/>
-  <constant name="HcalSD_g10_thickness" value="1.4*mm"/>
-  <constant name="HcalSD_mylar_anode_thickness" value="0.05*mm"/>
-  <constant name="HcalSD_mylar_cathode_thickness" value="0.175*mm"/>
-  <constant name="HcalSD_mylar_thickness" value="0.2*mm"/>
-  <constant name="HcalSD_PCB_thickness" value="1.2*mm"/>
-  <constant name="HcalSD_electronics_mask_thickness" value="1.6*mm"/>
-  <constant name="HcalSD_steel_casette_thickness" value="2.5*mm"/>
-  <constant name="HcalSD_airgap_thickness" value="0.5*mm"/>
-  <constant name="HcalSD_back_plate_thickness" value="10*mm"/>
-  <constant name="HcalSD_barrel_end_module_type" value="1"/>
-  <constant name="HcalSD_stave_gaps" value="10*mm"/>
-  <constant name="HcalSD_lateral_structure_thickness" value="10*mm"/>
-  <constant name="HcalSD_layer_air_gap" value="2*mm"/>
-  <constant name="HcalSD_endcap_lateral_structure_thickness" value="5.0*mm"/>
-
-  <constant name="HcalSD_module_wall_thickness" value="10*mm"/>   
-
-  <constant name="HcalBarrelSD_nlayers" value="40"/>
-  <constant name="HcalSD_MinNumCellsInTransvPlane" value="1"/>
-  <constant name="HcalBarrelSD_number_modules" value="5"/>
-  <constant name="HcalEndcap_symmetry" value="Hcal_outer_symmetry"/>
-  <constant name="HcalEndcapRingSD_inner_symmetry"  value="Ecal_Hcal_symmetry"/>
-  <constant name="HcalEndcapRingSD_outer_symmetry"  value="HcalEndcap_symmetry"/>
-  <constant name="HcalEndcapRingSD_nlayers"         value="7"/>
-  <constant name="HcalEndcapSD_nlayers" value="40"/>
-
-  <constant name="HcalSD_gasInlet_length" value="3.0*mm"/>
-  <constant name="HcalSD_modules_gap" value="20*mm"/>
-  <constant name="HcalSD_spacer_separation" value="100*mm"/>
-  <constant name="HcalSD_spacer_thickness" value="8*mm"/>
-  <constant name="HcalSD_gasInlet_innerRadius" value="0.4*mm"/>
-  <constant name="HcalSD_gasInlet_outerRadius" value="0.5*mm"/>
-
-  
-
-  <!-- translations -->
-  <constant name="Hcal_endcap_zmin" value="HcalEndcap_min_z"/>
-
-  <!-- used for "hybrid" readout segmentation -->
-  <constant name="AHCal_cell_size" value="3.0*cm"/>
-  <constant name="SDHCal_cell_size" value="1.0*cm"/>
-  
-  <!-- TODO move these two element at the correct place -->
-  <!-- TODO create the additional detectors for the different options for l/s4 and l/s5 -->
-  <!-- TODO merge the two variables to only one for both barrel and endcap -->
-  <!-- barrel and endcvap constructors use the slices in reversed order ! -->
-  <!-- <constant name="Hcal_readout_segmentation_slice_barrel" value="3"/> -->
-  <!-- <constant name="Hcal_readout_segmentation_slice_endcap" value="3"/> -->
-
 
+  <constant name="Hcal_gas_edge_width" value="1*mm"/>
+  <constant name="Hcal_MinNumCellsInTransvPlane" value="11"/>
+  <constant name="Hcal_barrel_number_modules" value="5"/>
+  <constant name="Hcal_chamber_thickness" value="6.73*mm"/>
+  <constant name="Hcal_back_plate_thickness" value="15*mm"/>
+  <constant name="Hcal_lateral_structure_thickness" value="10*mm"/>
+  <constant name="Hcal_stave_gaps" value="0*mm"/>
+  <constant name="Hcal_modules_gap" value="2*mm"/>
+
+  <constant name="Hcal_pad_separation" value="0*mm"/>
+  <constant name="Hcal_gasInlet_length" value="3.0*mm"/>
+  <constant name="Hcal_spacer_separation" value="100*mm"/>
+  <constant name="Hcal_spacer_thickness" value="8*mm"/>
+  <constant name="Hcal_gasInlet_inner_radius" value="0.4*mm"/>
+  <constant name="Hcal_gasInlet_outer_radius" value="0.5*mm"/>
+
+  <constant name="Hcal_endcap_outer_symmetry" value="Hcal_outer_symmetry"/>
+  <constant name="Hcal_ring_inner_symmetry"  value="Ecal_Hcal_symmetry"/>
+  <constant name="Hcal_ring_outer_symmetry"  value="Hcal_endcap_outer_symmetry"/>
+
+  <constant name="Hcal_graphite_thickness" value="Hcal_graphite_cathode_thickness+Hcal_graphite_anode_thickness"/>
+  <constant name="Hcal_mylar_thickness" value="Hcal_mylar_cathode_thickness+Hcal_mylar_anode_thickness"/>
+  <constant name="Hcal_g10_thickness" value="Hcal_PCB_thickness+Hcal_electronics_mask_thickness"/>
+  <constant name="Hcal_mix_thickness" value="Hcal_airgap_thickness+Hcal_graphite_thickness+Hcal_mylar_thickness+Hcal_g10_thickness"/>
+  <constant name="Hcal_mix_density" value="Hcal_airgap_thickness/Hcal_mix_thickness*0.00120479 + Hcal_graphite_thickness/Hcal_mix_thickness*2.21 +
+                                           Hcal_mylar_thickness/Hcal_mix_thickness*1.4 + Hcal_g10_thickness/Hcal_mix_thickness*1.7"/>
+  <constant name="Hcal_airgap_fraction" value="Hcal_airgap_thickness/Hcal_mix_thickness*0.00120479/Hcal_mix_density"/>
+  <constant name="Hcal_graphite_fraction" value="Hcal_graphite_thickness/Hcal_mix_thickness*2.21/Hcal_mix_density"/>
+  <constant name="Hcal_mylar_fraction" value="Hcal_mylar_thickness/Hcal_mix_thickness*1.4/Hcal_mix_density"/>
+  <constant name="Hcal_g10_fraction" value="Hcal_g10_thickness/Hcal_mix_thickness*1.7/Hcal_mix_density"/>
 </define>
diff --git a/Detector/DetCEPCv4/compact/top_defs.xml b/Detector/DetCEPCv4/compact/top_defs.xml
index bb0f6ac7..6b09c8a3 100644
--- a/Detector/DetCEPCv4/compact/top_defs.xml
+++ b/Detector/DetCEPCv4/compact/top_defs.xml
@@ -58,16 +58,17 @@
   <constant name="Ecal_EC_Ring_gap" value="10*mm"/>
 
   <!-- HCAL -->
-  <constant name="Hcal_barrel_thickness" value="1272.3*mm"/>
+  <constant name="Hcal_barrel_thickness" value="1086.43*mm"/>
   <constant name="Hcal_Coil_additional_gap" value="29.5*mm"/>
   <!--constant name="Hcal_outer_symmetry" value="16"/-->
   <constant name="Hcal_outer_symmetry" value="8"/>
 
   <constant name="Hcal_endcap_center_box_size" value="700.0*mm"/>
   <constant name="Hcal_endcap_zmin" value="2650*mm" />
-  <constant name="Hcal_endcap_thickness" value="1287.0*mm"/>
+  <constant name="Hcal_endcap_thickness" value="1084.2*mm"/>
   <constant name="Hcal_radial_ring_inner_gap" value="50*mm"/>
-  <constant name="Hcal_endcap_cryostat_gap" value="170*mm"/>
+  <constant name="Hcal_endcap_cryostat_gap" value="0*mm"/>
+  <constant name="Hcal_endcap_ecal_gap" value="15*mm"/>
 
   <!-- coil -->
   <constant name="Coil_extra_size" value="1522*mm"/>
diff --git a/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Barrel.cpp b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Barrel.cpp
new file mode 100644
index 00000000..9801a0a1
--- /dev/null
+++ b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Barrel.cpp
@@ -0,0 +1,333 @@
+//====================================================================
+//  SHcalRpc01 - Implementation from ILCSoft's Mokka version                              
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "XML/Utilities.h"
+
+using namespace std;
+
+using dd4hep::Ref_t;
+using dd4hep::BUILD_ENVELOPE;
+using dd4hep::DetElement;
+using dd4hep::Detector;
+using dd4hep::SensitiveDetector;
+using dd4hep::Segmentation;
+using dd4hep::Readout;
+using dd4hep::Material;
+using dd4hep::Volume;
+using dd4hep::PlacedVolume;
+using dd4hep::Position;
+using dd4hep::RotationZYX;
+using dd4hep::Transform3D;
+using dd4hep::Box;
+using dd4hep::Tube;
+using dd4hep::PolyhedraRegular;
+using dd4hep::SubtractionSolid;
+using dd4hep::_toString;
+using dd4hep::pi;
+using dd4hep::rec::LayeredCalorimeterData;
+
+/** Construction of SHcalRpc01 detector, ported from Mokka driver SHcalRpc01.cc
+ *
+ *  Mokka History:
+ * - first implementation from ILCSoft
+ * - http://cepcgit.ihep.ac.cn/cepcsoft/MokkaC
+ */
+static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens)  {
+  cout << "--------------------------" << endl;
+  cout << "creating SHcalRpc01_Barrel" << endl;
+  cout << "--------------------------" << endl;
+
+  xml_det_t    x_det  = element;
+  string       name   = x_det.nameStr();
+  int          det_id = x_det.id();
+  DetElement   det(name, det_id);
+
+  Volume envelope = dd4hep::xml::createPlacedEnvelope(theDetector, element , det ) ;
+
+  dd4hep::xml::setDetectorTypeFlag(element, det) ;
+
+  if( theDetector.buildType() == BUILD_ENVELOPE ) return det ;
+
+  xml_comp_t    x_staves          = x_det.staves();
+  string   Hcal_radiator_material = x_staves.materialStr();
+  Material      stavesMaterial    = theDetector.material(Hcal_radiator_material);
+  Material      air               = theDetector.air();
+
+  sens.setType("calorimeter");
+
+  Readout readout = sens.readout();
+  Segmentation seg = readout.segmentation();
+
+  std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0);
+  double cell_sizeX      = cellSizeVector[0];
+  double cell_sizeZ      = cellSizeVector[1];
+
+  double      Hcal_inner_radius   = theDetector.constant<double>("Hcal_inner_radius");
+  double      Hcal_outer_radius_set   = theDetector.constant<double>("Hcal_outer_radius");
+  double      Hcal_half_length    = theDetector.constant<double>("Hcal_half_length");
+  int         Hcal_inner_symmetry = theDetector.constant<int>("Hcal_inner_symmetry");
+  int         Hcal_outer_symmetry = 0;
+  double      Hcal_lateral_plate_thickness     = theDetector.constant<double>("Hcal_lateral_structure_thickness");
+  double      Hcal_modules_gap                 = theDetector.constant<double>("Hcal_modules_gap");
+  int         Hcal_nlayers                     = theDetector.constant<int>("Hcal_nlayers");
+  double      TPC_outer_radius               = theDetector.constant<double>("TPC_outer_radius");
+  double      Ecal_outer_radius               = theDetector.constant<double>("Ecal_outer_radius");
+  int Hcal_barrel_number_modules = theDetector.constant<int>("Hcal_barrel_number_modules");
+  
+  double hPrime =    Ecal_outer_radius + theDetector.constant<double>("Hcal_Ecal_gap");
+  Hcal_inner_radius = hPrime / cos(pi/8.);
+  
+  double Hcal_normal_dim_z = (2*Hcal_half_length - (Hcal_barrel_number_modules-1)*Hcal_modules_gap)/Hcal_barrel_number_modules;
+
+  xml_coll_t c(x_det,_U(layer));
+  xml_comp_t x_layer = c;
+
+  double Hcal_radiator_thickness = 0;
+  double layerThickness = 0.0;
+  for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+    xml_comp_t x_slice = k;
+    layerThickness += x_slice.thickness();
+    if(x_slice.materialStr()==Hcal_radiator_material) Hcal_radiator_thickness = x_slice.thickness();
+  }
+  cout << " layer_thickness (from slices) = " << layerThickness << " and radiator_thickness = " << Hcal_radiator_thickness << endl;
+  double Hcal_chamber_thickness = layerThickness - Hcal_radiator_thickness; 
+
+  int MinNumCellsInTransvPlane  = theDetector.constant<int>("Hcal_MinNumCellsInTransvPlane");
+  double RPC_EdgeWidth          = theDetector.constant<double>("Hcal_gas_edge_width");
+  double RPCGazInletInnerRadius = theDetector.constant<double>("Hcal_gasInlet_inner_radius");
+  double RPCGazInletOuterRadius = theDetector.constant<double>("Hcal_gasInlet_outer_radius");
+  double RPCGazInletLength      = theDetector.constant<double>("Hcal_gasInlet_length");
+  double RPC_PadSeparation      = theDetector.constant<double>("Hcal_pad_separation");
+  double Hcal_spacer_thickness  = theDetector.constant<double>("Hcal_spacer_thickness");
+  double Hcal_spacer_separation = theDetector.constant<double>("Hcal_spacer_separation");
+
+  //========== fill data for reconstruction ============================
+  LayeredCalorimeterData* caloData = new LayeredCalorimeterData ;
+  caloData->layoutType = LayeredCalorimeterData::BarrelLayout ;
+  caloData->inner_symmetry = Hcal_inner_symmetry  ;
+  caloData->outer_symmetry = Hcal_outer_symmetry  ;
+  caloData->phi0 = 0 ; // fg: also hardcoded below
+
+  // general calculated parameters
+  double AngleRatio=0.76536686;//"k"
+  double d_InnerOctoSize=AngleRatio*Hcal_inner_radius;//"d"
+  double LMin = 2*RPC_EdgeWidth+cell_sizeX*MinNumCellsInTransvPlane+(MinNumCellsInTransvPlane+1)*RPC_PadSeparation;
+
+  double Ynl = 0.5*d_InnerOctoSize - Hcal_nlayers*layerThickness;
+  double Hcal_outer_radius = sqrt((LMin-Ynl)*(LMin-Ynl) + (hPrime + Hcal_nlayers*layerThickness)*(hPrime + Hcal_nlayers*layerThickness));
+  if(Hcal_outer_radius!=Hcal_outer_radius_set){
+    cout << "calculated Hcal_outer_radius != input, will impact HcalEndcap and HcalEndcapRing. Hcal_outer_radius = " << Hcal_outer_radius
+	 << " but set as " << Hcal_outer_radius_set << " difference = " << Hcal_outer_radius-Hcal_outer_radius_set << endl;  
+  }
+
+  /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in cm.
+  caloData->extent[0] = Hcal_inner_radius ;
+  caloData->extent[1] = Hcal_outer_radius ;
+  caloData->extent[2] = 0. ; // Barrel zmin is "0" by default.
+  caloData->extent[3] = Hcal_half_length ;
+
+  double Hcal_total_dim_y = Hcal_outer_radius - hPrime;
+  
+  // the  y_dim1_for_z kept as the original value in TDR
+  double Hcal_regular_chamber_dim_z = Hcal_normal_dim_z - 2 *(Hcal_lateral_plate_thickness);
+  //int N_cells_z =  static_cast <int> ( (Hcal_regular_chamber_dim_z - 2*RPC_EdgeWidth - RPC_PadSeparation) / (Hcal_cell_dim_x + RPC_PadSeparation) );
+  //  Hcal_cell_dim_z=(Hcal_regular_chamber_dim_z-RPC_PadSeparation )/N_cells_z
+  //                      - RPC_PadSeparation;
+  Tube solidCaloTube(0, Hcal_outer_radius, Hcal_half_length);
+
+  PolyhedraRegular solidOctogon(8, 0, hPrime, 4*Hcal_half_length);
+  RotationZYX rotOctogon(dd4hep::twopi/16,0,0);
+  SubtractionSolid solidCalo(solidCaloTube, solidOctogon, rotOctogon);
+  Volume logicCalo(name+"_radiator", solidCalo, stavesMaterial);
+  logicCalo.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
+  PlacedVolume calo_pv = envelope.placeVolume(logicCalo, Position(0,0,0));
+  DetElement calo(det, "envelope", det_id);
+  calo.setPlacement(calo_pv);
+
+  for(int layer_id=1; layer_id<=Hcal_nlayers; layer_id++){
+    double yn = sqrt(Hcal_outer_radius*Hcal_outer_radius - (hPrime + layer_id*layerThickness)*(hPrime + layer_id*layerThickness));
+    double Yn = 0.5*d_InnerOctoSize - layer_id*layerThickness;
+
+    double halfX = Hcal_chamber_thickness/2.;
+    double halfZ = (yn+Yn)/2.;
+    
+    LayeredCalorimeterData::Layer caloLayer ;
+    caloLayer.cellSize0 = cell_sizeX;
+    caloLayer.cellSize1 = cell_sizeZ;
+
+    //double halfY = Hcal_normal_dim_z / 2.;
+    double halfY = Hcal_regular_chamber_dim_z / 2.;
+
+    double localXPos = hPrime + Hcal_radiator_thickness + Hcal_chamber_thickness/2. + (layer_id-1)*layerThickness;
+    double localYPos = -Yn + 0.5*(Yn + yn);
+    Box chamberSolid(halfX, halfY, halfZ);
+    string chamberLogical_name      = name+_toString(layer_id,"_layer%d");
+    Volume chamberLogical(chamberLogical_name, chamberSolid, air);
+    chamberLogical.setAttributes(theDetector, x_layer.regionStr(), x_layer.limitsStr(), x_layer.visStr());
+
+    string layer_name      = name+_toString(layer_id,"_layer%d");
+
+    double nRadiationLengths=0.;
+    double nInteractionLengths=0.;
+    double thickness_sum=0;
+
+    nRadiationLengths   = Hcal_radiator_thickness/(stavesMaterial.radLength());
+    nInteractionLengths = Hcal_radiator_thickness/(stavesMaterial.intLength());
+
+    double slice_pos_z = -halfX;
+    int slice_number = 0;
+    for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+      xml_comp_t x_slice = k;
+      if(x_slice.materialStr()==Hcal_radiator_material) continue;
+      string   slice_name      = layer_name + _toString(slice_number,"_slice%d");
+      double   slice_thickness = x_slice.thickness();
+      Material slice_material  = theDetector.material(x_slice.materialStr());
+      if(layer_id==1) cout<<"  Layer_slice:  "<<  slice_name<<" slice_thickness:  "<< slice_thickness<< endl;
+      
+      slice_pos_z += slice_thickness/2.;
+      nRadiationLengths   += slice_thickness/(2.*slice_material.radLength());
+      nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+      thickness_sum       += slice_thickness/2;
+
+      // Slice volume & box
+      Box sliceSolid(slice_thickness/2., halfY, halfZ);
+      Volume sliceVol(slice_name, sliceSolid, slice_material);
+      
+      if ( x_slice.isSensitive() ) {
+	sliceVol.setSensitiveDetector(sens);
+	if(RPC_EdgeWidth>0){
+	  double RPC_GazInlet_In_Y  = halfY - RPC_EdgeWidth - RPCGazInletOuterRadius;
+	  double RPC_GazInlet_In_Z  = halfZ - RPC_EdgeWidth/2;
+	  double RPC_GazInlet_Out_Y = -RPC_GazInlet_In_Y;
+	  double RPC_GazInlet_Out_Z =  RPC_GazInlet_In_Z;
+
+	  string mateialName = x_slice.attr<string>(_Unicode(edge_material));
+	  Material edge_material = theDetector.material(mateialName);
+	  Box solidRPCEdge1(slice_thickness/2.,halfY, halfZ);
+	  Box solidRPCEdge2(slice_thickness/2.,halfY-RPC_EdgeWidth, halfZ-RPC_EdgeWidth);
+	  SubtractionSolid solidRPCEdge(solidRPCEdge1, solidRPCEdge2, Position(0,0,0));
+	  Volume logicRPCEdge(slice_name+"_edge", solidRPCEdge, edge_material);
+	  logicRPCEdge.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+	  sliceVol.placeVolume(logicRPCEdge);
+
+	  Tube solidRPCGazInlet(RPCGazInletInnerRadius,RPCGazInletOuterRadius,RPC_EdgeWidth/*RPCGazInletLength*//2);
+	  Volume logicRPCGazInlet(slice_name+"_GazInlet", solidRPCGazInlet, edge_material);
+	  logicRPCGazInlet.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+	  logicRPCEdge.placeVolume(logicRPCGazInlet, Position(0,RPC_GazInlet_In_Y,RPC_GazInlet_In_Z));
+	  logicRPCEdge.placeVolume(logicRPCGazInlet, Position(0,RPC_GazInlet_Out_Y,RPC_GazInlet_Out_Z));
+	  
+	  Tube solidRPCGazInsideInlet(0,RPCGazInletInnerRadius,RPC_EdgeWidth/*RPCGazInletLength*//2);
+	  Volume logicRPCGazInsideInlet(slice_name+"_GazInsideInlet", solidRPCGazInsideInlet, slice_material);
+	  logicRPCGazInsideInlet.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),"SeeThrough");
+	  logicRPCEdge.placeVolume(logicRPCGazInsideInlet, Position(0,RPC_GazInlet_In_Y,RPC_GazInlet_In_Z));
+	  logicRPCEdge.placeVolume(logicRPCGazInsideInlet, Position(0,RPC_GazInlet_Out_Y,RPC_GazInlet_Out_Z));
+	}
+	if(Hcal_spacer_thickness>0){
+	  Tube solidRPCSpacer(0,Hcal_spacer_thickness/2,slice_thickness/2);
+	  Material space_material = theDetector.material(x_slice.attr<string>(_Unicode(spacer_material)));
+	  Volume logicRPCSpacer(slice_name+"_spacer", solidRPCSpacer, space_material);
+	  logicRPCSpacer.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+	  RotationZYX rotSpacer(0, pi/2., 0);
+	  
+	  double gap_hZ = halfZ-RPC_EdgeWidth;
+	  double gap_hY = halfY-RPC_EdgeWidth;
+	  int y_number_of_separations = (int)(2*gap_hY/Hcal_spacer_separation);
+	  int z_number_of_separations = (int)(2*gap_hZ/Hcal_spacer_separation);
+	  double y_lateral_space = (2*gap_hY - y_number_of_separations*Hcal_spacer_separation)/2;
+	  double z_lateral_space = (2*gap_hZ - z_number_of_separations*Hcal_spacer_separation)/2;
+	  if(y_lateral_space < Hcal_spacer_thickness/2.){
+	    y_number_of_separations = (int)((2*gap_hY-Hcal_spacer_thickness)/Hcal_spacer_separation);
+	    y_lateral_space = (2*gap_hY - y_number_of_separations*Hcal_spacer_separation)/2;
+	  }
+	  if(z_lateral_space < Hcal_spacer_thickness/2.){
+	    z_number_of_separations = (int)((2*gap_hZ-Hcal_spacer_thickness)/Hcal_spacer_separation);
+	    z_lateral_space = (2*gap_hZ - z_number_of_separations*Hcal_spacer_separation)/2;
+	  }
+	  for(int y_counter = 0; y_counter <=y_number_of_separations; y_counter++){
+	    double SpacerY = gap_hY - y_lateral_space - y_counter*Hcal_spacer_separation;
+	    for(int z_counter = 0; z_counter <=z_number_of_separations; z_counter++){
+	      double SpacerZ = gap_hZ - z_lateral_space - z_counter*Hcal_spacer_separation;
+	      PlacedVolume space_pv = sliceVol.placeVolume(logicRPCSpacer, Transform3D(rotSpacer, Position(0,SpacerY,SpacerZ)));
+	    }
+	  }
+	}
+
+	caloLayer.inner_nRadiationLengths = nRadiationLengths;
+	caloLayer.inner_nInteractionLengths = nInteractionLengths;
+	caloLayer.inner_thickness = thickness_sum;
+	if(layer_id==1) cout<<"Hcal_Barrel:  inner_thickness= "<<thickness_sum<<endl;
+        //Store readout gasgap thickness
+	caloLayer.sensitive_thickness = slice_thickness;
+        //Reset counters to measure "outside" quantitites
+	nRadiationLengths=0.;
+	nInteractionLengths=0.;
+	thickness_sum = 0.;
+	
+	sliceVol.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),"SeeThrough");
+      }
+      else{
+	sliceVol.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+      }
+      nRadiationLengths += slice_thickness/(2.*slice_material.radLength());
+      nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+      thickness_sum += slice_thickness/2;
+
+      // slice PlacedVolume
+      PlacedVolume slice_phv = chamberLogical.placeVolume(sliceVol,Position(slice_pos_z,0,0));
+      if ( x_slice.isSensitive() ) {
+	int slice_id  = (layer_id > Hcal_nlayers)? 1:-1;
+	slice_phv.addPhysVolID("layer",layer_id).addPhysVolID("slice",slice_id);
+      }
+      DetElement sliceDetE(layer_name,_toString(slice_number,"slice%d"),x_det.id());
+      sliceDetE.setPlacement(slice_phv);
+      // Increment x position for next slice.
+      slice_pos_z += slice_thickness/2.;
+      // Increment slice number.
+      ++slice_number;
+    }
+    caloLayer.outer_nRadiationLengths = nRadiationLengths;
+    caloLayer.outer_nInteractionLengths = nInteractionLengths;
+    caloLayer.outer_thickness = thickness_sum;
+    if(layer_id==1) cout << "Hcal_Barrel:  outer_thickness= " << thickness_sum << endl;
+    
+    double chamber_y_offset = -(-Hcal_total_dim_y/2. + (layer_id-1)*layerThickness + layerThickness/2.);
+
+    caloLayer.distance = Hcal_inner_radius + Hcal_total_dim_y/2.0 + chamber_y_offset ;
+    caloLayer.absorberThickness = Hcal_radiator_thickness ;
+
+    caloData->layers.push_back( caloLayer ) ;
+    
+    double stave_phi_offset, module_z_offset;
+    
+    stave_phi_offset = pi*0.5;
+    for(int stave_id = 1; stave_id <= 8; stave_id++){
+      double phirot = stave_phi_offset+(stave_id-1)*pi/4.;
+
+      RotationZYX rot(0, phirot, pi*0.5);
+      RotationZYX rotInverse(0,-phirot, -pi*0.5);
+      for(int module_id = 1; module_id <= Hcal_barrel_number_modules; module_id++){
+        module_z_offset = - Hcal_half_length + Hcal_normal_dim_z/2. + (module_id-1)*(Hcal_normal_dim_z+Hcal_modules_gap);
+	
+        Position localPos(localXPos,-module_z_offset,localYPos);
+        Position newPos = rotInverse*localPos;
+	Transform3D tran3D(rot, newPos);
+	PlacedVolume pv = logicCalo.placeVolume(chamberLogical, tran3D);
+	pv.addPhysVolID("stave",stave_id).addPhysVolID("module",module_id).addPhysVolID("layer",layer_id);
+	DetElement layer(calo, name+_toString(stave_id,"_stave%d")+_toString(module_id,"_module%d")+_toString(layer_id,"_layer%d"), det_id);
+	layer.setPlacement(pv);
+      }
+    }
+  }
+
+  det.addExtension< LayeredCalorimeterData >( caloData ) ;
+
+  return det;
+}
+
+DECLARE_DETELEMENT(SHcalRpc01_Barrel, create_detector)
diff --git a/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_EndcapRing.cpp b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_EndcapRing.cpp
new file mode 100644
index 00000000..3a9978cc
--- /dev/null
+++ b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_EndcapRing.cpp
@@ -0,0 +1,266 @@
+//====================================================================
+//  SHcalRpc01 - Implementation from ILCSoft's Mokka version                              
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "XML/Utilities.h"
+
+using namespace std;
+
+using dd4hep::Ref_t;
+using dd4hep::BUILD_ENVELOPE;
+using dd4hep::DetElement;
+using dd4hep::Detector;
+using dd4hep::SensitiveDetector;
+using dd4hep::Segmentation;
+using dd4hep::Readout;
+using dd4hep::Material;
+using dd4hep::Volume;
+using dd4hep::PlacedVolume;
+using dd4hep::Position;
+using dd4hep::RotationZYX;
+using dd4hep::Transform3D;
+using dd4hep::Box;
+using dd4hep::Tube;
+using dd4hep::PolyhedraRegular;
+using dd4hep::SubtractionSolid;
+using dd4hep::IntersectionSolid;
+using dd4hep::_toString;
+using dd4hep::pi;
+using dd4hep::rec::LayeredCalorimeterData;
+
+/** Construction of SHcalRpc01 detector, ported from Mokka driver SHcalRpc01.cc
+ *
+ *  Mokka History:
+ * - first implementation from ILCSoft
+ * - http://cepcgit.ihep.ac.cn/cepcsoft/MokkaC
+ */
+static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens)  {
+  cout << "------------------------------" << endl;
+  cout << "creating SHcalRpc01_EndcapRing" << endl;
+  cout << "------------------------------" << endl;
+
+  xml_det_t    x_det = element;
+  string       name  = x_det.nameStr();
+  
+  int          det_id    = x_det.id();
+  DetElement   det(name, det_id) ;
+  
+  xml_comp_t    x_staves          = x_det.staves();
+  string   Hcal_radiator_material = x_staves.materialStr();
+  Material      stavesMaterial    = theDetector.material(Hcal_radiator_material);
+  Material      air               = theDetector.air();
+
+  Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  element , det ) ;
+
+  dd4hep::xml::setDetectorTypeFlag( element, det ) ;
+
+  if( theDetector.buildType() == BUILD_ENVELOPE ) return det ;
+
+  sens.setType("calorimeter");
+
+  DetElement module(det,"module0",det_id);
+  DetElement layer(module, "stave_layer", det_id);
+  DetElement slice(layer, "slice", det_id);
+
+  Readout readout = sens.readout();
+  Segmentation seg = readout.segmentation();
+  
+  std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0);
+  double cell_sizeX      = cellSizeVector[0];
+  double cell_sizeY      = cellSizeVector[1];
+
+  double Hcal_outer_radius            = theDetector.constant<double>("Hcal_outer_radius");
+  int    Hcal_endcap_outer_symmetry   = theDetector.constant<int>("Hcal_endcap_outer_symmetry");
+  double Hcal_stave_gaps              = theDetector.constant<double>("Hcal_stave_gaps");
+  int    Hcal_nlayers                 = theDetector.constant<int>("Hcal_endcap_nlayers");
+  double Hcal_start_z                 = theDetector.constant<double>("Hcal_endcap_zmin");
+  double Hcal_lateral_plate_thickness = theDetector.constant<double>("Hcal_lateral_structure_thickness");
+  double Ecal_endcap_zmin             = theDetector.constant<double>("Ecal_endcap_zmin");
+  double Hcal_endcap_ecal_gap         = theDetector.constant<double>("Hcal_endcap_ecal_gap");
+  double Ecal_endcap_outer_radius     = theDetector.constant<double>("EcalEndcap_outer_radius");
+  double Hcal_radial_ring_inner_gap   = theDetector.constant<double>("Hcal_radial_ring_inner_gap");
+
+  xml_coll_t c(x_det,_U(layer));
+  xml_comp_t x_layer = c;
+
+  double Hcal_radiator_thickness = 0;
+  double layerThickness = 0.0;
+  for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+    xml_comp_t x_slice = k;
+    layerThickness += x_slice.thickness();
+    if(x_slice.materialStr()==Hcal_radiator_material) Hcal_radiator_thickness = x_slice.thickness();
+  }
+  cout << " layer_thickness (from slices) = " << layerThickness << " and radiator_thickness = " << Hcal_radiator_thickness << endl;
+  double Hcal_chamber_thickness = layerThickness - Hcal_radiator_thickness;
+
+  int numSide = Hcal_endcap_outer_symmetry;
+  double Hcal_endcap_rmax = Hcal_outer_radius * cos(pi/numSide);
+
+  LayeredCalorimeterData* caloData = new LayeredCalorimeterData ;
+  caloData->layoutType = LayeredCalorimeterData::EndcapLayout ;
+  caloData->inner_symmetry = numSide;
+  caloData->outer_symmetry = numSide;
+  caloData->phi0           = 0;
+  
+  double start_z        = Ecal_endcap_zmin;
+  double SpaceForLayers = Hcal_start_z - Hcal_endcap_ecal_gap - Ecal_endcap_zmin - 2*Hcal_lateral_plate_thickness;
+  int MaxNumberOfLayers = (int)(SpaceForLayers / (Hcal_chamber_thickness + Hcal_radiator_thickness));
+  double stop_z         = start_z + MaxNumberOfLayers*layerThickness + 2*Hcal_lateral_plate_thickness;
+
+  double pRMax = Hcal_endcap_rmax;
+  double pDz   = (stop_z - start_z)/2.;
+  double pRMin = Ecal_endcap_outer_radius + Hcal_radial_ring_inner_gap;
+
+  cout << "Rings will have " << MaxNumberOfLayers << " layers." << endl;
+  cout << " Z: " << start_z << " -> " << stop_z << endl;
+  cout << " R: " << pRMin   << " -> " << pRMax  << endl;
+
+  caloData->extent[0] = pRMin;
+  caloData->extent[1] = pRMax;
+  caloData->extent[2] = start_z;
+  caloData->extent[3] = stop_z;
+  
+  PolyhedraRegular EndCapRingSolidPoly(numSide, -pi/numSide, pRMin, pRMax, 2*pDz);
+  Volume EndCapRingLogical(name+"_radiator", EndCapRingSolidPoly, stavesMaterial);
+  EndCapRingLogical.setAttributes(theDetector,x_staves.regionStr(),x_staves.limitsStr(),x_staves.visStr());
+
+  int number_of_chambers = Hcal_nlayers;
+  if(MaxNumberOfLayers < number_of_chambers) number_of_chambers = MaxNumberOfLayers;
+  
+  double rInner = pRMin + Hcal_lateral_plate_thickness;
+  double rOuter = pRMax - Hcal_lateral_plate_thickness;
+  
+  PolyhedraRegular EndCapRingChamberPoly(numSide, -pi/numSide, rInner, rOuter, Hcal_chamber_thickness);
+  Box IntersectionStaveBox(rOuter/2., rOuter/2., Hcal_chamber_thickness/2);
+  Position IntersectPos(rOuter/2. + Hcal_stave_gaps/2., rOuter/2. + Hcal_stave_gaps/2., 0.);
+  IntersectionSolid  EndCapRingStaveSolid(EndCapRingChamberPoly, IntersectionStaveBox, IntersectPos);
+  Volume EndCapRingChamberLogical(name+"_chamber", EndCapRingStaveSolid, air);
+  EndCapRingChamberLogical.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
+  
+  double nRadiationLengthsInside=0.;
+  double nInteractionLengthsInside=0.;
+  double inner_thickness=0;
+  double sensitive_thickness=0;
+  double nRadiationLengths=0.;
+  double nInteractionLengths=0.;
+  double thickness_sum=0;
+
+  double slice_pos_z = -Hcal_chamber_thickness/2.;
+  int slice_number = 0;
+  for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+    xml_comp_t x_slice = k;
+    string   slice_name      = name + _toString(slice_number,"_slice%d");
+    double   slice_thickness = x_slice.thickness();
+    Material slice_material  = theDetector.material(x_slice.materialStr());
+    cout<<"  Layer_slice:  " <<  slice_name << " slice_thickness:  " << slice_thickness<< endl;
+
+    nRadiationLengths   += slice_thickness/(2.*slice_material.radLength());
+    nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+    thickness_sum       += slice_thickness/2;
+    if(x_slice.materialStr()==Hcal_radiator_material) continue;
+
+    slice_pos_z += slice_thickness/2.;
+
+    PolyhedraRegular slicePoly(numSide, -pi/numSide, rInner, rOuter, slice_thickness);
+    IntersectionSolid sliceStaveSolid(slicePoly, IntersectionStaveBox, IntersectPos);
+    Volume sliceVol(name + _toString(slice_number,"_slice%d"), sliceStaveSolid, slice_material);
+    sliceVol.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+    if(x_slice.isSensitive()){
+      sliceVol.setSensitiveDetector(sens);
+      nRadiationLengthsInside   = nRadiationLengths;
+      nInteractionLengthsInside = nInteractionLengths;
+      inner_thickness           = thickness_sum;
+      sensitive_thickness       = slice_thickness;
+      
+      nRadiationLengths=0.;
+      nInteractionLengths=0.;
+      thickness_sum = 0.;
+    }
+
+    nRadiationLengths   += slice_thickness/(2.*slice_material.radLength());
+    nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+    thickness_sum       += slice_thickness/2;
+    // slice PlacedVolume
+    PlacedVolume slice_phv = EndCapRingChamberLogical.placeVolume(sliceVol,Position(0,0,slice_pos_z));
+    //DetElement slice(layer_name,_toString(slice_number,"slice%d"),x_det.id());
+    slice.setPlacement(slice_phv);
+    // Increment x position for next slice.
+    slice_pos_z += slice_thickness/2.;
+    // Increment slice number.
+    ++slice_number;
+  }
+  
+  // chamber placements
+  for(int stave_id = 1; stave_id <= 4; stave_id++){
+    double angle = pi/2.*(stave_id-1);
+    RotationZYX lrot(angle,0,0);
+    for (int layer_id = 1; layer_id <= number_of_chambers; layer_id++){
+      double Zoff = -pDz + (layer_id-1)*layerThickness + Hcal_radiator_thickness + Hcal_chamber_thickness/2.;
+      Position l_pos(0., 0., Zoff);
+      Position l_new = lrot*l_pos;
+      Transform3D ltran3D(lrot,l_new);
+      PlacedVolume layer_phv = EndCapRingLogical.placeVolume(EndCapRingChamberLogical, ltran3D);
+      layer_phv.addPhysVolID("layer",layer_id);
+      layer_phv.addPhysVolID("stave",stave_id);
+      
+      //string l_name = _toString(layer_id,"layer%d");
+      //string stave_name = _toString(stave_id,"stave%d");
+      //DetElement layer(module_det, l_name+stave_name, det_id);
+      layer.setPlacement(layer_phv);
+
+      if(stave_id==1&&layer_id==1){
+	cout << "Hcal_EndcapRing:  inner_thickness= " << inner_thickness << endl;
+	cout << "Hcal_EndcapRing:  outer_thickness= " << thickness_sum << endl;
+      }
+      LayeredCalorimeterData::Layer caloLayer ;
+      caloLayer.cellSize0 = cell_sizeX;
+      caloLayer.cellSize1 = cell_sizeY;
+      caloLayer.inner_nRadiationLengths   = nRadiationLengthsInside;
+      caloLayer.inner_nInteractionLengths = nInteractionLengthsInside;
+      caloLayer.inner_thickness           = inner_thickness;
+      caloLayer.sensitive_thickness       = sensitive_thickness;
+      caloLayer.outer_nRadiationLengths   = nRadiationLengths;
+      caloLayer.outer_nInteractionLengths = nInteractionLengths;
+      caloLayer.outer_thickness           = thickness_sum;
+      
+      caloLayer.distance = start_z + (layer_id-1)*layerThickness;
+      caloLayer.absorberThickness = Hcal_radiator_thickness ;
+      
+      caloData->layers.push_back( caloLayer ) ;
+    }
+  }
+  
+  // Placements
+  double endcap_z_offset = start_z + pDz;
+  for(int side = 0; side <= 1; side++){
+    int module_id = (side==0) ? 0 : 6;
+    double this_module_z_offset = (side==0) ? endcap_z_offset : -endcap_z_offset;
+    // use reflect volume for z<0, therefore, same rotation
+    // segmentation violation happen if EndCapRingLogical.reflect(), back to rotate Y
+    // double this_module_rotY = (side==0) ? 0.0 : 0.0;
+    double this_module_rotY = (side==0) ? 0.0 : pi;
+    //double this_module_rotZ = (side==0) ? pi/8. : pi/8;
+    RotationZYX rot(0,this_module_rotY,0);
+    Transform3D tran3D(rot,Position(0,0,this_module_z_offset));
+    
+    PlacedVolume module_phv;
+    //if(side==0) module_phv = envelope.placeVolume(EndCapRingLogical, tran3D);
+    //else        module_phv = envelope.placeVolume(EndCapRingLogical.reflect(), tran3D);
+    module_phv = envelope.placeVolume(EndCapRingLogical, tran3D);
+    
+    module_phv.addPhysVolID("module", module_id);
+    //DetElement sd = (module_id==0) ? module_det : module_det.clone(_toString(side,"module%d"));
+    module.setPlacement(module_phv);
+  }
+
+  det.addExtension<LayeredCalorimeterData>(caloData) ;
+
+  return det;
+}
+
+DECLARE_DETELEMENT(SHcalRpc01_EndcapRing, create_detector)
diff --git a/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Endcaps.cpp b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Endcaps.cpp
new file mode 100644
index 00000000..abe42b65
--- /dev/null
+++ b/Detector/DetCEPCv4/src/calorimeter/SHcalRpc01_Endcaps.cpp
@@ -0,0 +1,269 @@
+//====================================================================
+//  SHcalRpc01 - Implementation from ILCSoft's Mokka version                              
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "XML/Utilities.h"
+
+using namespace std;
+
+using dd4hep::Ref_t;
+using dd4hep::BUILD_ENVELOPE;
+using dd4hep::DetElement;
+using dd4hep::Detector;
+using dd4hep::SensitiveDetector;
+using dd4hep::Segmentation;
+using dd4hep::Readout;
+using dd4hep::Material;
+using dd4hep::Volume;
+using dd4hep::PlacedVolume;
+using dd4hep::Position;
+using dd4hep::RotationZYX;
+using dd4hep::Transform3D;
+using dd4hep::Box;
+using dd4hep::Tube;
+using dd4hep::PolyhedraRegular;
+using dd4hep::SubtractionSolid;
+using dd4hep::IntersectionSolid;
+using dd4hep::_toString;
+using dd4hep::pi;
+using dd4hep::rec::LayeredCalorimeterData;
+
+/** Construction of SHcalRpc01 detector, ported from Mokka driver SHcalRpc01.cc
+ *
+ *  Mokka History:
+ * - first implementation from ILCSoft
+ * - http://cepcgit.ihep.ac.cn/cepcsoft/MokkaC
+ */
+static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens)  {
+  cout << "--------------------------" << endl;
+  cout << "creating SHcalRpc01_Endcap" << endl;
+  cout << "--------------------------" << endl;
+
+  xml_det_t    x_det = element;
+  string       name  = x_det.nameStr();
+  
+  int          det_id    = x_det.id();
+  DetElement   det(name, det_id) ;
+  
+  xml_comp_t    x_staves          = x_det.staves();
+  string   Hcal_radiator_material = x_staves.materialStr();
+  Material      stavesMaterial    = theDetector.material(Hcal_radiator_material);
+  Material      air               = theDetector.air();
+
+  Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  element , det ) ;
+
+  dd4hep::xml::setDetectorTypeFlag( element, det ) ;
+
+  if( theDetector.buildType() == BUILD_ENVELOPE ) return det ;
+
+  sens.setType("calorimeter");
+
+  DetElement module(det,"module0",det_id);
+  DetElement layer(module, "stave_layer", det_id);
+  DetElement slice(layer, "slice", det_id);
+
+  Readout readout = sens.readout();
+  Segmentation seg = readout.segmentation();
+
+  std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0);
+  double cell_sizeX      = cellSizeVector[0];
+  double cell_sizeY      = cellSizeVector[1];
+
+  //double      Hcal_inner_radius   = theDetector.constant<double>("Hcal_inner_radius");
+  double Hcal_outer_radius            = theDetector.constant<double>("Hcal_outer_radius");
+  //double      Hcal_half_length    = theDetector.constant<double>("Hcal_half_length");
+  int    Hcal_endcap_outer_symmetry   = theDetector.constant<int>("Hcal_endcap_outer_symmetry");
+  //double      Hcal_cells_size                  = theDetector.constant<double>("Hcal_cells_size");
+  double Hcal_stave_gaps              = theDetector.constant<double>("Hcal_stave_gaps");
+  int    Hcal_nlayers                 = theDetector.constant<int>("Hcal_endcap_nlayers");
+  double Hcal_start_z                 = theDetector.constant<double>("Hcal_endcap_zmin");
+  double Hcal_back_plate_thickness    = theDetector.constant<double>("Hcal_back_plate_thickness");
+  double Hcal_lateral_plate_thickness = theDetector.constant<double>("Hcal_lateral_structure_thickness");
+  double Hcal_endcap_center_box_size  = theDetector.constant<double>("Hcal_endcap_center_box_size");
+  
+  xml_coll_t c(x_det,_U(layer));
+  xml_comp_t x_layer = c;
+
+  double Hcal_radiator_thickness = 0;
+  double layerThickness = 0.0;
+  for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+    xml_comp_t x_slice = k;
+    layerThickness += x_slice.thickness();
+    if(x_slice.materialStr()==Hcal_radiator_material) Hcal_radiator_thickness = x_slice.thickness();
+  }
+  cout << " layer_thickness (from slices) = " << layerThickness << " and radiator_thickness = " << Hcal_radiator_thickness << endl;
+  double Hcal_chamber_thickness = layerThickness - Hcal_radiator_thickness;
+
+  int numSide = Hcal_endcap_outer_symmetry;
+  double Hcal_endcap_thickness = Hcal_nlayers*layerThickness + Hcal_back_plate_thickness;
+  double Hcal_endcap_rmax = Hcal_outer_radius * cos(pi/numSide);
+
+  LayeredCalorimeterData* caloData = new LayeredCalorimeterData;
+  caloData->layoutType = LayeredCalorimeterData::EndcapLayout;
+  caloData->inner_symmetry = 4;
+  caloData->outer_symmetry = Hcal_endcap_outer_symmetry;
+  caloData->phi0           = 0;
+
+  caloData->extent[0] = Hcal_endcap_center_box_size/2.;
+  caloData->extent[1] = Hcal_outer_radius;
+  caloData->extent[2] = Hcal_start_z;
+  caloData->extent[3] = Hcal_start_z+Hcal_endcap_thickness;
+
+  double pRMax = Hcal_endcap_rmax;
+  double pDz   = Hcal_endcap_thickness/2.;
+  double pRMin = Hcal_endcap_center_box_size/2.;
+  
+  PolyhedraRegular EndCapSolidPoly(numSide, -pi/numSide, 0., pRMax, 2*pDz);
+  Box hcalECInnerHole(pRMin, pRMin, pDz);
+  SubtractionSolid solidHCalEC(EndCapSolidPoly,hcalECInnerHole);
+  Volume EndCapLogical(name+"_radiator", solidHCalEC, stavesMaterial);
+  EndCapLogical.setAttributes(theDetector,x_staves.regionStr(),x_staves.limitsStr(),x_staves.visStr());
+
+  int number_of_chambers = Hcal_nlayers;
+  int possible_number_of_chambers = (int) (floor(abs(Hcal_endcap_thickness-Hcal_back_plate_thickness) / (Hcal_chamber_thickness + Hcal_radiator_thickness)));
+  if(possible_number_of_chambers < number_of_chambers) number_of_chambers = possible_number_of_chambers;
+  
+  double rInner = 0.;
+  double rOuter= Hcal_endcap_rmax - Hcal_lateral_plate_thickness;
+  
+  PolyhedraRegular EndCapChamberPoly(numSide, -pi/numSide, rInner, rOuter, Hcal_chamber_thickness);
+  Box hcalECChamberInnerHole(pRMin + Hcal_lateral_plate_thickness, pRMin + Hcal_lateral_plate_thickness, Hcal_chamber_thickness/2);
+  SubtractionSolid EndCapChamberSolid(EndCapChamberPoly, hcalECChamberInnerHole);
+  Box IntersectionStaveBox(rOuter/2., rOuter/2., Hcal_chamber_thickness/2);
+  Position pos(rOuter/2. + Hcal_stave_gaps/2., rOuter/2. + Hcal_stave_gaps/2., 0.);
+  Position IntersectPos = pos;
+  IntersectionSolid  EndCapStaveSolid(EndCapChamberSolid, IntersectionStaveBox, IntersectPos);
+  Volume EndCapChamberLogical(name+"_chamber", EndCapStaveSolid, air);
+  EndCapChamberLogical.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
+
+  double nRadiationLengthsInside=0.;
+  double nInteractionLengthsInside=0.;
+  double inner_thickness=0;
+  double sensitive_thickness=0;
+  double nRadiationLengths=0.;
+  double nInteractionLengths=0.;
+  double thickness_sum=0;
+
+  double slice_pos_z = -Hcal_chamber_thickness/2.;
+  int slice_number = 0;
+  for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
+    xml_comp_t x_slice = k;
+    string   slice_name      = name + _toString(slice_number,"_slice%d");
+    double   slice_thickness = x_slice.thickness();
+    Material slice_material  = theDetector.material(x_slice.materialStr());
+    cout<<"  Layer_slice:  " <<  slice_name << " slice_thickness:  " << slice_thickness<< endl;
+
+    nRadiationLengths   += slice_thickness/(2.*slice_material.radLength());
+    nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+    thickness_sum       += slice_thickness/2;
+    if(x_slice.materialStr()==Hcal_radiator_material) continue;
+
+    slice_pos_z += slice_thickness/2.;
+
+    PolyhedraRegular slicePoly(numSide, -pi/numSide, rInner, rOuter, slice_thickness);
+    SubtractionSolid sliceSolid(slicePoly, hcalECChamberInnerHole);
+    IntersectionSolid sliceStaveSolid(sliceSolid, IntersectionStaveBox, IntersectPos);
+
+    Volume sliceVol(name + _toString(slice_number,"_slice%d"), sliceStaveSolid, slice_material);
+    sliceVol.setAttributes(theDetector,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+    if(x_slice.isSensitive()){
+      sliceVol.setSensitiveDetector(sens);
+      nRadiationLengthsInside = nRadiationLengths;
+      nInteractionLengthsInside = nInteractionLengths;
+      inner_thickness = thickness_sum;
+      sensitive_thickness = slice_thickness;
+      
+      nRadiationLengths=0.;
+      nInteractionLengths=0.;
+      thickness_sum = 0.;
+    }
+
+    nRadiationLengths   += slice_thickness/(2.*slice_material.radLength());
+    nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
+    thickness_sum       += slice_thickness/2;
+    // slice PlacedVolume
+    PlacedVolume slice_phv = EndCapChamberLogical.placeVolume(sliceVol,Position(0,0,slice_pos_z));
+    //DetElement slice(layer_name,_toString(slice_number,"slice%d"),x_det.id());
+    slice.setPlacement(slice_phv);
+    // Increment x position for next slice.
+    slice_pos_z += slice_thickness/2.;
+    // Increment slice number.
+    ++slice_number;
+  }
+
+  if(possible_number_of_chambers < number_of_chambers) number_of_chambers = possible_number_of_chambers;
+  // chamber placements
+  for(int stave_id = 1; stave_id <= 4; stave_id++){
+    double angle = pi/2.*(stave_id-1);
+    //RotationZ lrotz(angle);
+    RotationZYX lrot(angle,0,0);
+    for (int layer_id = 1; layer_id <= number_of_chambers; layer_id++){
+      double Zoff = -Hcal_endcap_thickness/2. + (layer_id-1) *(Hcal_chamber_thickness + Hcal_radiator_thickness) + Hcal_radiator_thickness + Hcal_chamber_thickness/2.;
+      Position l_pos(0., 0., Zoff);
+      Position l_new = lrot*l_pos;
+      Transform3D ltran3D(lrot,l_new);
+      PlacedVolume layer_phv = EndCapLogical.placeVolume(EndCapChamberLogical, ltran3D);
+      layer_phv.addPhysVolID("layer",layer_id);
+      layer_phv.addPhysVolID("stave",stave_id);
+      
+      //string l_name = _toString(layer_id,"layer%d");
+      //string stave_name = _toString(stave_id,"stave%d");
+      //DetElement layer(module_det, l_name+stave_name, det_id);
+      layer.setPlacement(layer_phv);
+
+      if(stave_id==1&&layer_id==1){
+	cout << "Hcal_Endcap:  inner_thickness= " << inner_thickness << endl;
+	cout << "Hcal_Endcap:  outer_thickness= " << thickness_sum << endl;
+      }
+      LayeredCalorimeterData::Layer caloLayer ;
+      caloLayer.cellSize0 = cell_sizeX;
+      caloLayer.cellSize1 = cell_sizeY;
+      caloLayer.inner_nRadiationLengths = nRadiationLengthsInside;
+      caloLayer.inner_nInteractionLengths = nInteractionLengthsInside;
+      caloLayer.inner_thickness = inner_thickness;
+      caloLayer.sensitive_thickness = sensitive_thickness;
+      caloLayer.outer_nRadiationLengths = nRadiationLengths;
+      caloLayer.outer_nInteractionLengths = nInteractionLengths;
+      caloLayer.outer_thickness = thickness_sum;
+      
+      caloLayer.distance = Hcal_start_z + (layer_id-1)*layerThickness;
+      caloLayer.absorberThickness = Hcal_radiator_thickness ;
+      
+      caloData->layers.push_back( caloLayer ) ;
+    }
+  }
+  
+  // Placements
+  double endcap_z_offset = Hcal_start_z + Hcal_endcap_thickness/2.;
+  for(int side = 0; side <= 1; side++){
+    int module_id = (side==0) ? 0 : 6;
+    double this_module_z_offset = (side==0) ? endcap_z_offset : -endcap_z_offset;
+    // use reflect volume for z<0, therefore, same rotation
+    // segmentation violation happen if EndCapRingLogical.reflect(), back to rotate Y
+    // double this_module_rotY = (side==0) ? 0.0 : 0.0;
+    double this_module_rotY = (side==0) ? 0.0 : pi;
+    //double this_module_rotZ = (side==0) ? pi/8. : pi/8;
+    RotationZYX rot(0,this_module_rotY,0);
+    Transform3D tran3D(rot,Position(0,0,this_module_z_offset));
+
+    PlacedVolume module_phv;
+    //if(side==0) module_phv = envelope.placeVolume(EndCapRingLogical, tran3D);
+    //else        module_phv = envelope.placeVolume(EndCapRingLogical.reflect(), tran3D);
+    module_phv = envelope.placeVolume(EndCapLogical, tran3D);
+
+    module_phv.addPhysVolID("module", module_id);
+    //DetElement sd = (module_id==0) ? module_det : module_det.clone(_toString(side,"module%d"));
+    module.setPlacement(module_phv);
+  }
+
+  det.addExtension<LayeredCalorimeterData>(caloData) ;
+
+  return det;
+}
+
+DECLARE_DETELEMENT(SHcalRpc01_Endcaps, create_detector)
-- 
GitLab