diff --git a/.build.ci.sh b/.build.ci.sh
old mode 100644
new mode 100755
index 6e4c3265fe63ab5c6d4acf1c9d01e13c5e44658d..3710b9a60e58ff641bb95065c31ffc1b232cbc55
--- a/.build.ci.sh
+++ b/.build.ci.sh
@@ -1,31 +1,51 @@
 #!/bin/bash
 # This is wrapper to run the build.sh on CI
 
-echo "LCG_RELEASE: ${LCG_RELEASE}"
+echo "CEPCSW_LCG_RELEASE: ${CEPCSW_LCG_RELEASE}"
+echo "CEPCSW_LCG_PLATFORM: ${CEPCSW_LCG_PLATFORM}"
+echo "CEPCSW_LCG_VERSION: ${CEPCSW_LCG_VERSION}"
 echo "CEPCSW_BLDTOOL: ${CEPCSW_BLDTOOL}"
-buildpid=
-logfile=mylog.txt
 
-if [ "$LCG_RELEASE" = "KEY4HEP_STACK" ]; then
-    logfile=mylog-k4.sh
-    ./build-k4.sh >& ${logfile} &
-    buildpid=$!
-else
-    source setup.sh
-    ./build.sh >& ${logfile} &
-    buildpid=$!
-fi
+function build-with-log() {
+    buildpid=
+    logfile=mylog.txt
+
+    if [ "$CEPCSW_LCG_RELEASE" = "KEY4HEP_STACK" ]; then
+        logfile=mylog-k4.sh
+        ./build-k4.sh >& ${logfile} &
+        buildpid=$!
+    else
+        source setup.sh
+        ./build.sh >& ${logfile} &
+        buildpid=$!
+    fi
+
+    while ps -p $buildpid 2>/dev/null ; do
+        sleep 60
+    done &
+    echoer=$!
 
-while ps -p $buildpid 2>/dev/null ; do
-    sleep 60
-done &
-echoer=$!
+    trap 'kill $echoer' 0
 
-trap 'kill $echoer' 0
+    wait $buildpid
+    statuspid=$?
 
-wait $buildpid
-statuspid=$?
+    tail -n100 ${logfile}
 
-tail -n100 ${logfile}
+    exit $statuspid
+}
 
-exit $statuspid
+function build-with-stdout() {
+    if [ "$CEPCSW_LCG_RELEASE" = "KEY4HEP_STACK" ]; then
+        ./build-k4.sh
+    else
+        source setup.sh
+        ./build.sh
+    fi
+}
+
+if [ -n "${GITHUB_ACTION}" ]; then
+    build-with-log
+else
+    build-with-stdout
+fi
diff --git a/.gitignore b/.gitignore
index 7853163353f7e852e3f472d7a6675292940be6e0..ff7ac6feeaead84301a0b30a66a0445fe80e49cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@ build.*
 build
 spack*
 ./Generator/output/
-./Generator/options/
\ No newline at end of file
+./Generator/options/
+
+InstallArea/
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index efd284358d4d0f3af8210fe838e90093a0103476..9064c2acfba738c7dd9b91c8884e04afdb15d769 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -26,19 +26,23 @@ workflow:
 
 stages:
   - build
-  # - test
 
 ##############################################################################
-# Build Template
+# Template for Build and Test
 ##############################################################################
+# Due to cmake/ctest will hardcode the path in build directory,
+# the test job will be failed if it is executed on a different nodes.
+# Therefore, put the build script and test script together.
+
 .build_template:
   stage: build
   variables:
-    LCG_RELEASE:
-    CEPCSW_BLDTOOL: ninja
+    CEPCSW_LCG_RELEASE:
+    CEPCSW_LCG_PLATFORM:
+    CEPCSW_LCG_VERSION:
   script:
     - bash ./.build.ci.sh
-
+    - bash ./.test.ci.sh
 
 ##############################################################################
 # Build CentOS 7 (LCG)
@@ -46,17 +50,13 @@ stages:
 build:lcg:el7:
   extends: .build_template
   variables:
-    LCG_RELEASE: LCG
+    CEPCSW_LCG_RELEASE: LCG
+    CEPCSW_LCG_PLATFORM: x86_64-centos7-gcc11-opt
+    CEPCSW_LCG_VERSION: 103.0.2
   tags:
     - centos7
-
-##############################################################################
-# Build CentOS 7 (KEY4HEP)
-##############################################################################
-# build:k4:el7:
-#   extends: .build_template
-#   variables:
-#     LCG_RELEASE: KEY4HEP_STACK
-#   tags:
-#     - centos7
-
+  artifacts:
+    paths:
+      - InstallArea
+    reports:
+      junit: build.${CEPCSW_LCG_VERSION}.${CEPCSW_LCG_PLATFORM}/cepcsw-ctest-result.xml
diff --git a/.test.ci.sh b/.test.ci.sh
new file mode 100755
index 0000000000000000000000000000000000000000..45f07bafae13e32e98555ae70c8320fe8f552c4f
--- /dev/null
+++ b/.test.ci.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Description:
+#   Run the tests using ctest
+#
+# Author:
+#   Tao Lin <lintao AT ihep.ac.cn>
+
+##############################################################################
+# Utilities
+##############################################################################
+function build-dir() {
+    local blddir=build
+
+    if [ -n "${CEPCSW_BLDTOOL}" ]; then
+        blddir=${blddir}.${CEPCSW_BLDTOOL}
+    fi
+
+    # If detect the extra env var, append it to the build dir
+    if [ -n "${CEPCSW_LCG_VERSION}" ]; then
+        blddir=${blddir}.${CEPCSW_LCG_VERSION}
+    fi
+    if [ -n "${CEPCSW_LCG_PLATFORM}" ]; then
+        blddir=${blddir}.${CEPCSW_LCG_PLATFORM}
+    fi
+
+    echo $blddir
+}
+
+function junit-output() {
+    local default=cepcsw-ctest-result.xml
+    echo ${CEPCSW_JUNIT_OUTPUT:-$default}
+}
+
+##############################################################################
+# Main
+##############################################################################
+
+
+echo "CEPCSW_LCG_RELEASE: ${CEPCSW_LCG_RELEASE}"
+echo "CEPCSW_LCG_PLATFORM: ${CEPCSW_LCG_PLATFORM}"
+echo "CEPCSW_LCG_VERSION: ${CEPCSW_LCG_VERSION}"
+echo "CEPCSW_BLDTOOL: ${CEPCSW_BLDTOOL}"
+
+source setup.sh
+
+ctest --output-junit $(junit-output) --test-dir $(build-dir)
diff --git a/Analysis/TotalInvMass/src/TotalInvMass.cc b/Analysis/TotalInvMass/src/TotalInvMass.cc
index 536739b25b1939bb841dbb54216c21671c78a28c..53eab8c6cbdfa6949d367ad46562917beaf561b3 100644
--- a/Analysis/TotalInvMass/src/TotalInvMass.cc
+++ b/Analysis/TotalInvMass/src/TotalInvMass.cc
@@ -11,13 +11,13 @@
 #include <EVENT/LCFloatVec.h>
 #include <EVENT/LCParameters.h>
 #include <stdexcept>
-#include <TFile.h> 
+#include <TFile.h>
 #include <TTree.h>
 #include <TH1F.h>
 #include <TVector3.h>
 #include <TRandom.h>
-#include <Rtypes.h> 
-#include <sstream>		
+#include <Rtypes.h>
+#include <sstream>
 #include <cmath>
 #include <vector>
 #include <TMath.h>
@@ -47,14 +47,14 @@ TotalInvMass::TotalInvMass(const std::string& name, ISvcLocator* svcLoc)
       _colName ,
       _colName);
     */
-	
+
     /*
       _leptonID = 13;
       registerProcessorParameter( "LeptonIDTag" ,
       "Lepton ID that will be used in this analysis." ,
       _leptonID ,
       _leptonID);
-    */	
+    */
 
 }
 
@@ -74,7 +74,7 @@ StatusCode TotalInvMass::initialize() {
     _outputTree->SetAutoSave(32*1024*1024);  // autosave every 32MB
     _outputTree->Branch("EventNr", &_eventNr, "EventNr/I");
     _outputTree->Branch("Num", &_Num, "Num/I");
-	
+
     _outputTree->Branch("OriQuarkID", &_OriQuarkID, "OriQuarkID/I");
 
     _outputTree->Branch("ISREn", &_ISREn, "ISREn/F");
@@ -88,6 +88,9 @@ StatusCode TotalInvMass::initialize() {
     _outputTree->Branch("N3En", &_N3En, "N3En/F");
     _outputTree->Branch("N3Pt", &_N3Pt, "N3Pt/F");
 
+    _outputTree->Branch("ArborPFO_E", &_ArborPFO_E);
+	_outputTree->Branch("ArborPFO_Charge", &_ArborPFO_Charge);
+
 
     _outputTree->Branch("OriJ1CosTheta", &_OriJ1CosTheta, "OriJ1CosTheta/F");
     _outputTree->Branch("OriJ2CosTheta", &_OriJ2CosTheta, "OriJ2CosTheta/F");
@@ -115,7 +118,7 @@ StatusCode TotalInvMass::initialize() {
 
     _outputTree->Branch("FrPh", FrPh, "FrPh[4]/F");
     _outputTree->Branch("FrNe", FrNe, "FrNe[4]/F");
-	
+
     _outputTree->Branch("KPF", KPF, "KPF[4]/F");
 
     _outputTree->Branch("UdP", UdP, "UdP[4]/F");
@@ -172,13 +175,16 @@ StatusCode TotalInvMass::initialize() {
 
 }
 
-StatusCode TotalInvMass::execute() 
-{		
+StatusCode TotalInvMass::execute()
+{
     info() << "TotalInvMass::executing..." << endmsg;
 
     EVENT::LCEvent* evtP = nullptr;
 
-    // if (evtP) {		
+    MCParticleColHandler m_mcParticle{_MCPCollectionName, Gaudi::DataHandle::Reader, this};
+
+
+    // if (evtP) {
 
     TLorentzVector ArborTotalP(0, 0, 0, 0);
     TLorentzVector ArborChP(0, 0, 0, 0);
@@ -194,6 +200,9 @@ StatusCode TotalInvMass::execute()
     TLorentzVector ArborISR(0, 0, 0, 0);
     TLorentzVector PandoraISR(0, 0, 0, 0);
 
+    _ArborPFO_E.clear();
+    _ArborPFO_Charge.clear();
+
     // TODO: using the event header
     // _eventNr = evtP->getEventNumber();
 
@@ -221,23 +230,23 @@ StatusCode TotalInvMass::execute()
         }
     }
 
-    nCHPFO_a = 0; 
+    nCHPFO_a = 0;
     nCHPFO_p = 0;
-    nNEPFO_a = 0; 
+    nNEPFO_a = 0;
     nNEPFO_p = 0;
     Type = -100;
-    Charge = -100; 
+    Charge = -100;
     Energy = 0;
-    CluEn = 0; 
-    TrkSumEn = 0; 
+    CluEn = 0;
+    TrkSumEn = 0;
 
-    _EcalTotalE = 0; _HcalTotalE = 0; _EcalCluE = 0; _HcalCluE = 0; 
+    _EcalTotalE = 0; _HcalTotalE = 0; _EcalCluE = 0; _HcalCluE = 0;
     _EcalCluE_p = 0; _HcalCluE_p = 0;
     _HcalEn1=0;_HcalEn2=0;_HcalEn3=0;_HcalEn4=0;_HcalEn5=0;
     _EcalEn1=0;_EcalEn2=0;_EcalEn3=0;_EcalEn4=0;_EcalEn5=0;
 
-    _HDPID = -1; 
-    _OriQuarkID = 0; 
+    _HDPID = -1;
+    _OriQuarkID = 0;
     _OQDir = -10;
     _HDir = -10;
     _visE=0;
@@ -323,12 +332,12 @@ StatusCode TotalInvMass::execute()
     try{
         auto MCPCol = m_mcParticle.get();
 
-        TVector3 tmpP; 
+        TVector3 tmpP;
         TVector3 ISRP(0, 0, 0);
         _N3En = 0;
         _N3Pt = 0;
- 
-        int NNeutrinoCount = 0; 
+
+        int NNeutrinoCount = 0;
 
         for (int s0 = 0; s0 < MCPCol->size(); ++s0) {
             auto MCP = (*MCPCol)[s0];
@@ -340,10 +349,20 @@ StatusCode TotalInvMass::execute()
             TVector3 VTX(VTX0.x, VTX0.y, VTX0.z);
             TVector3 EndP(EndP0.x, EndP0.y, EndP0.z);
 
+            int GenStatus = MCP.getGeneratorStatus();
+            int SimuStatus = MCP.getSimulatorStatus();
+
+            if(0) debug()<<"MCP "<<s0<<": tmpPID = "<<tmpPID<<", NParent = "<<NParent<<", NDaughter = "<<NDaughter<<", GenStatus = "<<GenStatus<<", SimuStatus = "<<SimuStatus<<endmsg;
+
+            // auto aDau = MCP.getDaughters(0);
+            // if(aDau){
+            //     debug()<<"Dau 0: PDG = "<<aDau->getPDG()<<endmsg;
+
+
             if(tmpPID == 22 && NParent == 0 && s0 < 4) {
                 auto tmpP0 = MCP.getMomentum();
                 tmpP = TVector3(tmpP0.x, tmpP0.y, tmpP0.z);
-                ISRP += tmpP; 
+                ISRP += tmpP;
             }
 
             if( (abs(tmpPID) == 12 || abs(tmpPID) == 14 || abs(tmpPID) == 16) && NParent != 0 && NDaughter == 0 && VTX.Mag() < 100 && EndP.Mag() > 100) {
@@ -355,20 +374,25 @@ StatusCode TotalInvMass::execute()
                     tmpP = TVector3(tmpP0.x, tmpP0.y, tmpP0.z);
                     _N3En += tmpP.Mag();
                     _N3Pt += tmpP.Perp();
-                    cout<<"Found Neutrino: "<<NNeutrinoCount<<" En "<<_N3En<<" Pt "<<_N3Pt<<endl;
+                    debug()<<"Found Neutrino: "<<NNeutrinoCount<<" En "<<_N3En<<" Pt "<<_N3Pt<<endmsg;
                 }
             }
 
             if(tmpPID == 25 && NDaughter > 1 && NParent !=0 ) { //Higgs
-                // cout<<"tmpPID:HDPID"<<tmpPID<<" "<<NDaughter<<" "<<NParent<<endl;
+                // debug()<<"tmpPID:HDPID"<<tmpPID<<" "<<NDaughter<<" "<<NParent<<endmsg;
                 _HDPID = abs(MCP.getDaughters(0).getPDG());
                 _HDir = MCP.getMomentum()[2]/MCP.getEnergy();
 
+                // debug()<<"This is Higgs, has "<<NDaughter<<" daughters"<<endmsg;
+                debug()<<"This is Higgs, has "<<NDaughter<<" daughters"<<endmsg;
+
                 if(NDaughter == 2) {
                     auto D1 = MCP.getDaughters(0);
                     _J1CosTheta = D1.getMomentum()[2]/D1.getEnergy();
                     auto D2 = MCP.getDaughters(1);
                     _J2CosTheta = D2.getMomentum()[2]/D2.getEnergy();
+
+                    debug()<<"---> PDG: "<<D1.getPDG()<<" + "<<D2.getPDG()<<endmsg;
                 }
             }
             if(abs(tmpPID)<7 && NParent == 0) {
@@ -379,9 +403,9 @@ StatusCode TotalInvMass::execute()
             }
 
             if(abs(tmpPID)<7 && NParent == 0) {
-                _OriQuarkID = abs(tmpPID); 
+                _OriQuarkID = abs(tmpPID);
                 _OQDir = MCP.getMomentum()[2]/MCP.getEnergy();
-            }	
+            }
 
 
             if(abs(_J1CosTheta) > abs(_J2CosTheta))
@@ -413,17 +437,21 @@ StatusCode TotalInvMass::execute()
             auto a_RecoP = (*col_RecoNeP)[i0];
             TLorentzVector currP( a_RecoP.getMomentum()[0], a_RecoP.getMomentum()[1], a_RecoP.getMomentum()[2], a_RecoP.getEnergy());
             ArborTotalP += currP;
+
+            _ArborPFO_E.push_back(a_RecoP.getEnergy());
+            _ArborPFO_Charge.push_back(a_RecoP.getCharge());
+
             auto currMom0 = a_RecoP.getMomentum();
             TVector3 currMom(currMom0.x, currMom0.y, currMom0.z);
             //				if(a_RecoP->getType() == 22 && a_RecoP->getEnergy() > 2)	//Compensate...
             //					ArborTotalP += 0.98*currP;
-            //				else 
+            //				else
             //					ArborTotalP += currP;
 
             if(a_RecoP.getCharge() != 0) {
                 ArborChP += currP;
             } else if(a_RecoP.getType() == 310) {
-                ArborKPF += currP; 
+                ArborKPF += currP;
             } else if(a_RecoP.getType() == 22) {
                 if(a_RecoP.getEnergy() < 3.0)
                     ArborFrPh += currP;
@@ -436,21 +464,36 @@ StatusCode TotalInvMass::execute()
                     ArborNeP += currP;
             } else if(a_RecoP.getEnergy() < 3.0) {
                 ArborFrP += currP;
-                cout<<"Undef "<<a_RecoP.getType()<<endl;  
+                if(0) debug()<<"Undef "<<a_RecoP.getType()<<endmsg;
             } else {
                 ArborUdP += currP;
-                cout<<"Undef "<<a_RecoP.getType() << "En "<<a_RecoP.getEnergy()<<endl;
+                if(0) debug()<<"Undef "<<a_RecoP.getType() << "En "<<a_RecoP.getEnergy()<<endmsg;
             }
 
+
+            if(0) debug()<<"[YX debug - BMR] PFO "<<i0<<", E = "<<a_RecoP.getEnergy()<<", Charge = "<<a_RecoP.getCharge()<<endmsg;
+
+
             if(a_RecoP.clusters_size() > 0) {
+
+                int nTrkHit = 0;
+                if(a_RecoP.getCharge()){
+                    auto a_Trk = a_RecoP.getTracks(0);
+                    nTrkHit = a_Trk.trackerHits_size();
+                }
+
                 auto a_clu = a_RecoP.getClusters(0);
                 auto CluPos0 = a_clu.getPosition();
                 TVector3 CluPos(CluPos0.x, CluPos0.y, CluPos0.z);
                 if( CluPos.Perp() < 300 && abs(CluPos.Z()) < 1300 && a_RecoP.getCharge() == 0 )	// 1150-1300
-                    ArborLCAL += currP; 
+                    ArborLCAL += currP;
+
+
+                if(0) debug()<<"[YX debug - BMR] ---> nTrkHit = "<<nTrkHit<<", CluE = "<<a_clu.getEnergy()<<", CluPos = ("<<CluPos.X()<<", "<<CluPos.Y()<<", "<<CluPos.Z()<<")"<<endmsg;
+
 
                 float MinAngleToCH = 1.0E6;
-                float MinAngleToNE = 1.0E6;  
+                float MinAngleToNE = 1.0E6;
 
                 if(a_RecoP.getEnergy() > 5 && a_RecoP.getCharge() == 0) {
                     for(int i1 = 0; i1 < col_RecoNeP->size(); i1++) {
@@ -464,7 +507,7 @@ StatusCode TotalInvMass::execute()
                                     if(tmpAngle < MinAngleToCH) {
                                         MinAngleToCH = tmpAngle;
                                     }
-                                } else {	
+                                } else {
                                     if(tmpAngle < MinAngleToNE) {
                                         MinAngleToNE = tmpAngle;
                                     }
@@ -474,19 +517,19 @@ StatusCode TotalInvMass::execute()
                     }
 
                     if( MinAngleToNE > 0.5 || MinAngleToCH > 0.5 ) {
-                        ArborISR += currP; 
+                        ArborISR += currP;
                     }
                 }
             }
 
-            TrackHit = 0; 
+            TrackHit = 0;
             for(int k = 0; k < 3; k++) {
                 StartPos[k] = 0;
                 EndPos[k] = 0;
-            }		
+            }
 
             Charge = int(a_RecoP.getCharge());
-            CluEn = 0; 
+            CluEn = 0;
             CluEnCom[0] = 0;
             CluEnCom[1] = 0;
 
@@ -510,7 +553,7 @@ StatusCode TotalInvMass::execute()
 
                 if((!Charge) and (currClu.subdetectorEnergies_size() > 2)) {
                     CluEnCom[0] = currClu.getSubdetectorEnergies(0);
-                    CluEnCom[1] = currClu.getSubdetectorEnergies(1);	
+                    CluEnCom[1] = currClu.getSubdetectorEnergies(1);
                     NeCaloE_a[0] += currClu.getSubdetectorEnergies(0);
                     NeCaloE_a[1] += currClu.getSubdetectorEnergies(1);
                 }
@@ -522,7 +565,7 @@ StatusCode TotalInvMass::execute()
 
 
                 if(Charge) {
-                    TrkSumEn += Energy; 
+                    TrkSumEn += Energy;
 
                     if (a_RecoP.tracks_size()>0) {
                         auto a_Trk = a_RecoP.getTracks(0);
@@ -535,19 +578,19 @@ StatusCode TotalInvMass::execute()
 
                             EndPos[0] = (a_Trk.getTrackerHits(TrackHit - 1)).getPosition()[0];
                             EndPos[1] = (a_Trk.getTrackerHits(TrackHit - 1)).getPosition()[1];
-                            EndPos[2] = (a_Trk.getTrackerHits(TrackHit - 1)).getPosition()[2];	
+                            EndPos[2] = (a_Trk.getTrackerHits(TrackHit - 1)).getPosition()[2];
                         }
                     }
 
                     if( Energy > CluEn + sqrt(Energy)) {
-                        ElargeP[0] += Energy; 
-                        ElargeP[1] += CluEn; 
+                        ElargeP[0] += Energy;
+                        ElargeP[1] += CluEn;
                     } else if( fabs(Energy - CluEn) < sqrt(Energy) ) {
                         EequP[0] += Energy;
-                        EequP[1] += CluEn; 
+                        EequP[1] += CluEn;
                     } else {
                         EsmallP[0] += Energy;
-                        EsmallP[1] += CluEn; 
+                        EsmallP[1] += CluEn;
                     }
 
                 }
@@ -559,18 +602,18 @@ StatusCode TotalInvMass::execute()
     }catch (lcio::DataNotAvailableException err) { }
 
     try{
-        //LCCollection* col_RecoPandora = evtP->getCollection( "PandoraPFOs" );			
+        //LCCollection* col_RecoPandora = evtP->getCollection( "PandoraPFOs" );
         //for(int i2 = 0; i2 < col_RecoPandora->getNumberOfElements(); i2++)
         for(int s = 0; s < 1; s++) {
             auto col_PFO_iter = m_arbopfo.get();
-            /* 
+            /*
                if(s==0)
                col_PFO_iter = evtP->getCollection( "ArborChargedCore" );
                else
-               col_PFO_iter = evtP->getCollection( "ArborNeutralCore" );	
+               col_PFO_iter = evtP->getCollection( "ArborNeutralCore" );
             */
 
-            for(int i2 = 0; i2 < col_PFO_iter->size(); i2++) {         
+            for(int i2 = 0; i2 < col_PFO_iter->size(); i2++) {
                 auto a_RecoP = (*col_PFO_iter)[i2];
                 TLorentzVector currP( a_RecoP.getMomentum()[0], a_RecoP.getMomentum()[1], a_RecoP.getMomentum()[2], a_RecoP.getEnergy());
                 PandoraTotalP += currP;
@@ -580,7 +623,7 @@ StatusCode TotalInvMass::execute()
                 } else {
                     nNEPFO_p++;
                 }
-                        
+
                 auto currMom0 = a_RecoP.getMomentum();
                 TVector3 currMom(currMom0.x, currMom0.y, currMom0.z);
 
@@ -592,7 +635,7 @@ StatusCode TotalInvMass::execute()
                     auto currClu = a_RecoP.getClusters(0);
                     CluEn = currClu.getEnergy();
 
-                    _EcalCluE_p += CluEn;	
+                    _EcalCluE_p += CluEn;
                     _HcalCluE_p += currClu.getSubdetectorEnergies(1);
 
                     if(a_RecoP.getEnergy() > 5 && a_RecoP.getCharge() == 0) {
@@ -625,11 +668,11 @@ StatusCode TotalInvMass::execute()
         }
     }catch (lcio::DataNotAvailableException err) { }
 
-    _Mass_a = 0; 
-    _Mass_p = 0; 
+    _Mass_a = 0;
+    _Mass_p = 0;
     _Mass_a_Pisr = 0;
-    _Mass_a_Plcal = 0; 
-    _Mass_p_Pisr = 0; 
+    _Mass_a_Plcal = 0;
+    _Mass_p_Pisr = 0;
 
     _Mass_a = ArborTotalP.M();
     _Mass_p = PandoraTotalP.M();
@@ -656,7 +699,7 @@ StatusCode TotalInvMass::execute()
     PhP[0] = ArborPhP.X();
     PhP[1] = ArborPhP.Y();
     PhP[2] = ArborPhP.Z();
-    PhP[3] = ArborPhP.T();	
+    PhP[3] = ArborPhP.T();
 
     NeP[0] = ArborNeP.X();
     NeP[1] = ArborNeP.Y();
@@ -688,18 +731,18 @@ StatusCode TotalInvMass::execute()
     KPF[2] = ArborKPF.Z();
     KPF[3] = ArborKPF.T();
 
-    cout<<_Mass_a<<" : "<<_Mass_p<<endl;		
+    info()<<_Mass_a<<" : "<<_Mass_p<<endmsg;
 
     _outputTree->Fill();
     _Num++;
-    // }  	  
+    // }
 
 
     info() << "TotalInvMass::execute done" << endmsg;
 
     return StatusCode::SUCCESS;
 
-}	
+}
 
 StatusCode TotalInvMass::finalize()
 {
diff --git a/Analysis/TotalInvMass/src/TotalInvMass.hh b/Analysis/TotalInvMass/src/TotalInvMass.hh
index 97d48d5ad80a82aa59ab6c3769b04bbae016afd8..4084b6133a1cf21a813e843dccc1acb29c4df07a 100644
--- a/Analysis/TotalInvMass/src/TotalInvMass.hh
+++ b/Analysis/TotalInvMass/src/TotalInvMass.hh
@@ -34,7 +34,11 @@ public:
 
 protected:
     typedef DataHandle<edm4hep::MCParticleCollection> MCParticleColHandler;
-    MCParticleColHandler m_mcParticle{"MCParticle", Gaudi::DataHandle::Reader, this};
+    // MCParticleColHandler m_mcParticle{"MCParticle", Gaudi::DataHandle::Reader, this};
+    // MCParticleColHandler m_mcParticle{"MCParticleGen", Gaudi::DataHandle::Reader, this};
+    Gaudi::Property<std::string> _MCPCollectionName{this,
+            "MCPCollectionName", "MCParticle",
+            "MCPCollectionName"};
 
     typedef DataHandle<edm4hep::CalorimeterHitCollection> CaloHitColHandler;
     CaloHitColHandler m_ecalbarrelhitcol{"ECALBarrel", Gaudi::DataHandle::Reader, this};
@@ -45,8 +49,9 @@ protected:
     CaloHitColHandler m_hcalotherhitcol {"HCALOther", Gaudi::DataHandle::Reader, this};
 
     typedef DataHandle<edm4hep::ReconstructedParticleCollection> RecParticleColHandler;
-    RecParticleColHandler m_reconep{"AncientPFOs", Gaudi::DataHandle::Reader, this};
-    RecParticleColHandler m_arbopfo{"ArborLICHPFOs", Gaudi::DataHandle::Reader, this};
+    RecParticleColHandler m_reconep{"ArborPFO", Gaudi::DataHandle::Reader, this};
+    RecParticleColHandler m_arbopfo{"ArborPFO", Gaudi::DataHandle::Reader, this};
+
 
     Gaudi::Property<std::string> _treeFileName{this,
             "TreeOutputFile", "MCTruth.root",
@@ -61,36 +66,36 @@ protected:
             "OverwriteFile", 0,
             "If zero an already existing file will not be overwritten."};
     int _leptonID;
-    float _cmsE; 
+    float _cmsE;
     TTree *_outputTree, *_outputPFO;
     float _ISRP[3];
-    float _ISREn, _ISRPt; 
-    float _N3En, _N3Pt; 
-    float _NEn, _NPt; 
+    float _ISREn, _ISRPt;
+    float _N3En, _N3Pt;
+    float _NEn, _NPt;
 
-    int _HDPID, _OriQuarkID; 
+    int _HDPID, _OriQuarkID;
     float _OQDir, _HDir;
     int _NMuP, _NMuM, _NChP, _NChM;
     float _P_MuP[4], _P_MuM[4], _P_DL[4];
-    int _EventType; 
-    float _InvMass, _RecoilMass; 
-    float _J1CosTheta, _J2CosTheta, _MaxJetCosTheta; 
-    float _OriJ1CosTheta, _OriJ2CosTheta, _MaxOriJetCosTheta; 
-    float _Mass_a, _Mass_p; 
+    int _EventType;
+    float _InvMass, _RecoilMass;
+    float _J1CosTheta, _J2CosTheta, _MaxJetCosTheta;
+    float _OriJ1CosTheta, _OriJ2CosTheta, _MaxOriJetCosTheta;
+    float _Mass_a, _Mass_p;
 
     int _PID1, _PID2;
     float _PL1[4], _PL2[4], _RPL1[4], _RPL2[4], _SM[4], _P_allCharged[4], _P_allNeutral[4], _P_Higgs[4], _P_allReco[4];
-    float _Hmass; 
+    float _Hmass;
     int _Num;
-    int _NHDaug; 
-    int _HdaughterPID; 
-    int _ZdaughterPID; 
+    int _NHDaug;
+    int _HdaughterPID;
+    int _ZdaughterPID;
     float _Pz[4], _Ph[4], _PzD1[4], _PzD2[4], _PhD1[4], _PhD2[4], _RPzD1[4], _RPzD2[4], _RPhD1[4], _RPhD2[4];
     float _P[4], _SumP[4], _VisP[4], _MissP[4];
-    int _PID, _NFMCP, _MotherFlag, _NNeutrino; 
-    float _ENeutrino, _DiPhMass, _DiPhMassCorr; 
+    int _PID, _NFMCP, _MotherFlag, _NNeutrino;
+    float _ENeutrino, _DiPhMass, _DiPhMassCorr;
     //		float _CosTheta, _Phi, _Charge;
-    float _Mz, _Mrecoil, _MzReco, _MhReco, _MrecoilReco; 
+    float _Mz, _Mrecoil, _MzReco, _MhReco, _MrecoilReco;
     float KthEn[7][9];
     unsigned int _eventNr;
 
@@ -102,12 +107,12 @@ protected:
     float ElargeP[2], EequP[2], EsmallP[2];
 
     float ChP[4], FrP[4], PhP[4], NeP[4], UdP[4], FrPh[4], FrNe[4], KPF[4];
-    float _EcalTotalE, _HcalTotalE, _EcalCluE, _HcalCluE, _EcalCluE_p, _HcalCluE_p; 
+    float _EcalTotalE, _HcalTotalE, _EcalCluE, _HcalCluE, _EcalCluE_p, _HcalCluE_p;
     float _HcalEn1, _HcalEn2,_HcalEn3,_HcalEn4,_HcalEn5;
     float _EcalEn1, _EcalEn2,_EcalEn3,_EcalEn4,_EcalEn5;
 
     int Type, Charge;
-    float Energy, TrkSumEn; 
+    float Energy, TrkSumEn;
     float P[3], CluEnCom[2];
     float CluEn;
 
@@ -115,6 +120,17 @@ protected:
     float StartPos[3], EndPos[3];
     float _visE;
 
+    std::vector<int> _ArborPFO_Charge;
+    std::vector<double> _ArborPFO_E;
+    // std::vector<double> _ArborPFO_CosTheta;
+    // std::vector<int> _ArborPFO_nTrk;
+    // std::vector<int> _ArborPFO_nClu;
+    // std::vector<TVector3> _ArborPFO_TrkP3;
+    // std::vector<double> _ArborPFO_CluE;
+    // std::vector<double> _ArborPFO_CluHitESum;
+    // std::vector<double> _ArborPFO_CluHitESum;
+
+
     std::string _fileName;
     std::ostream *_output;
     std::string _histFileName;
diff --git a/Detector/DetCEPCv4/compact/CEPCV4_FullDet_GearOutput.xml b/Detector/DetCEPCv4/compact/CEPCV4_FullDet_GearOutput.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c434ae54c043be5f20f21c1881b339b255cd4b04
--- /dev/null
+++ b/Detector/DetCEPCv4/compact/CEPCV4_FullDet_GearOutput.xml
@@ -0,0 +1,334 @@
+<gear>
+    <global detectorName="CEPC_v4" />
+    <!--Gear XML file automatically created with GearXML::createXMLFile ....-->
+    <BField type="ConstantBField" x="0.000000000e+00" y="0.000000000e+00" z="3.000000000e+00" />
+    <detectors>
+        <detector geartype="TPCParameters" name="TPC">
+            <maxDriftLength value="2.225000000e+03" />
+            <driftVelocity value="0.000000000e+00" />
+            <coordinateType value="polar" />
+            <modules>
+                <module>
+                    <moduleID value="0" />
+                    <readoutFrequency value="0.000000000e+00" />
+                    <PadRowLayout2D type="FixedPadSizeDiskLayout" rMin="3.840000000e+02" rMax="1.716000000e+03" padHeight="6.000000000e+00" padWidth="1.000000000e+00" maxRow="222" padGap="0.000000000e+00" phiMax="6.283185307e+00" />
+                    <offset x_r="0.000000000e+00" y_phi="0.000000000e+00" />
+                    <angle value="0.000000000e+00" />
+                    <enlargeActiveAreaBy value="0.000000000e+00" />
+                </module>
+            </modules>
+            <parameter name="TPCGasProperties_RadLen" type="double" value="1.155205461e+05" />
+            <parameter name="TPCGasProperties_dEdx" type="double" value="2.668179899e-07" />
+            <parameter name="TPCInnerWallProperties_RadLen" type="double" value="2.740688665e+03" />
+            <parameter name="TPCInnerWallProperties_dEdx" type="double" value="1.241647394e-05" />
+            <parameter name="TPCOuterWallProperties_RadLen" type="double" value="6.495646008e+03" />
+            <parameter name="TPCOuterWallProperties_dEdx" type="double" value="5.300932694e-06" />
+            <parameter name="TPCWallProperties_RadLen" type="double" value="2.740688665e+03" />
+            <parameter name="TPCWallProperties_dEdx" type="double" value="1.241647394e-05" />
+            <parameter name="tpcInnerRadius" type="double" value="3.290000000e+02" />
+            <parameter name="tpcInnerWallThickness" type="double" value="2.500000000e+01" />
+            <parameter name="tpcOuterRadius" type="double" value="1.808000000e+03" />
+            <parameter name="tpcOuterWallThickness" type="double" value="6.000000000e+01" />
+            <parameter name="tpcZAnode" type="double" value="4.600000000e+03" />
+        </detector>
+        <detector name="EcalBarrel" geartype="CalorimeterParameters">
+            <layout type="Barrel" symmetry="8" phi0="0.000000000e+00" />
+            <dimensions inner_r="1.847415655e+03" outer_z="2.350000000e+03" />
+            <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+        </detector>
+        <detector name="EcalEndcap" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="4.000000000e+02" outer_r="2.088800000e+03" inner_z="2.450000000e+03" />
+            <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+        </detector>
+        <detector name="EcalPlug" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="2.400000000e+02" outer_r="4.000000000e+02" inner_z="2.450000000e+03" />
+            <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+            <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" />
+        </detector>
+        <detector name="YokeBarrel" geartype="CalorimeterParameters">
+            <layout type="Barrel" symmetry="12" phi0="0.000000000e+00" />
+            <dimensions inner_r="4.173929932e+03" outer_z="4.072000000e+03" />
+            <layer repeat="1" thickness="4.000000000e+01" absorberThickness="0.000000000e+00" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+            <layer repeat="9" thickness="1.400000000e+02" absorberThickness="1.000000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+            <layer repeat="3" thickness="6.000000000e+02" absorberThickness="5.600000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+            <layer repeat="1" thickness="4.000000000e+01" absorberThickness="4.027623145e-320" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+        </detector>
+        <detector name="YokeEndcap" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="3.200000000e+02" outer_r="7.414929932e+03" inner_z="4.072000000e+03" />
+            <layer repeat="1" thickness="1.000000000e+02" absorberThickness="1.000000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+            <layer repeat="9" thickness="1.400000000e+02" absorberThickness="1.000000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+            <layer repeat="2" thickness="6.000000000e+02" absorberThickness="5.600000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" />
+        </detector>
+        <detector name="YokePlug" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="3.200000000e+02" outer_r="2.849254326e+03" inner_z="3.781430000e+03" />
+            <parameter name="YokePlugThickness" type="double" value="2.905700000e+02" />
+        </detector>
+        <detector name="HcalBarrel" geartype="CalorimeterParameters">
+            <layout type="Barrel" symmetry="8" phi0="1.570796327e+00" />
+            <dimensions inner_r="2.058000000e+03" outer_z="2.350000000e+03" />
+            <layer repeat="40" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" />
+            <parameter name="Hcal_barrel_number_modules" type="int" value="5" />
+            <parameter name="N_cells_z" type="int" value="91" />
+            <parameter name="FrameWidth" type="double" value="1.000000000e+00" />
+            <parameter name="Hcal_lateral_structure_thickness" type="double" value="1.000000000e+01" />
+            <parameter name="Hcal_modules_gap" type="double" value="2.000000000e+00" />
+            <parameter name="Hcal_outer_radius" type="double" value="3.144432447e+03" />
+            <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" />
+            <parameter name="InnerOctoSize" type="double" value="1.704903012e+03" />
+            <parameter name="RPC_PadSeparation" type="double" value="0.000000000e+00" />
+            <parameter name="TPC_Ecal_Hcal_barrel_halfZ" type="double" value="2.350000000e+03" />
+        </detector>
+        <detector name="HcalEndcap" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="3.500000000e+02" outer_r="3.144432447e+03" inner_z="2.650000000e+03" />
+            <layer repeat="40" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" />
+            <parameter name="FrameWidth" type="double" value="0.000000000e+00" />
+            <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" />
+        </detector>
+        <detector name="HcalRing" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" />
+            <dimensions inner_r="2.138800000e+03" outer_r="3.144432447e+03" inner_z="2.450000000e+03" />
+            <layer repeat="6" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" />
+            <parameter name="FrameWidth" type="double" value="0.000000000e+00" />
+            <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" />
+        </detector>
+        <detector name="Lcal" geartype="CalorimeterParameters">
+            <layout type="Endcap" symmetry="1" phi0="0.000000000e+00" />
+            <dimensions inner_r="3.225828541e+01" outer_r="9.880000000e+01" inner_z="9.519000000e+02" />
+            <layer repeat="30" thickness="4.290000000e+00" absorberThickness="3.500000000e+00" cellSize0="1.039714290e+00" cellSize1="1.308996939e-01" />
+            <parameter name="beam_crossing_angle" type="double" value="0.000000000e+00" />
+        </detector>
+        <detector name="VXD" geartype="ZPlanarParameters">
+            <type technology="HYBRID" />
+            <shell halfLength="1.450000000e+02" gap="0.000000000e+00" innerRadius="6.500000000e+01" outerRadius="6.549392000e+01" radLength="3.527597571e+02" />
+            <layers>
+                <layer nLadders="10" phi0="-1.570796327e+00">
+                    <ladder distance="1.600000000e+01" thickness="1.000000000e+00" width="1.150000000e+01" length="6.250000000e+01" offset="-1.874869853e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="1.595000000e+01" thickness="5.000000000e-02" width="1.100000000e+01" length="6.250000000e+01" offset="-1.624869853e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="10" phi0="-1.570796327e+00">
+                    <ladder distance="1.700000000e+01" thickness="1.000000000e+00" width="1.150000000e+01" length="6.250000000e+01" offset="-1.874869853e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="1.800000000e+01" thickness="5.000000000e-02" width="1.100000000e+01" length="6.250000000e+01" offset="-1.624869853e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="11" phi0="-1.570796327e+00">
+                    <ladder distance="3.700000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-1.837940563e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="3.695000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-1.587940563e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="11" phi0="-1.570796327e+00">
+                    <ladder distance="3.800000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-1.837940563e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="3.900000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-1.587940563e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="17" phi0="-1.570796327e+00">
+                    <ladder distance="5.800000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-2.636744400e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="5.795000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-2.386744400e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="17" phi0="-1.570796327e+00">
+                    <ladder distance="5.900000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-2.636744400e+00" radLength="1.014262421e+03" />
+                    <sensitive distance="6.000000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-2.386744400e+00" radLength="9.366070445e+01" />
+                </layer>
+            </layers>
+        </detector>
+        <detector name="FTD" geartype="FTDParameters">
+            <layers>
+                <layer nPetals="16" nSensors="1" isDoubleSided="0" sensorType="PIXEL" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="0.000000000e+00" zsign0="1.000000000e+00" zposition="2.205200000e+02">
+                    <support thickness="1.000000000e+00" width="1.224000000e+02" lengthMin="1.173582968e+01" lengthMax="6.042957721e+01" rInner="2.950000000e+01" radLength="2.807467352e+02" />
+                    <sensitive thickness="2.000000000e-02" width="1.224000000e+02" lengthMin="1.173582968e+01" lengthMax="6.042957721e+01" rInner="2.950000000e+01" radLength="9.366070445e+01" />
+                </layer>
+                <layer nPetals="16" nSensors="1" isDoubleSided="0" sensorType="PIXEL" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="0.000000000e+00" zsign0="1.000000000e+00" zposition="3.715200000e+02">
+                    <support thickness="1.000000000e+00" width="1.213600000e+02" lengthMin="1.214956740e+01" lengthMax="6.042957721e+01" rInner="3.054000000e+01" radLength="2.807467352e+02" />
+                    <sensitive thickness="2.000000000e-02" width="1.213600000e+02" lengthMin="1.214956740e+01" lengthMax="6.042957721e+01" rInner="3.054000000e+01" radLength="9.366070445e+01" />
+                </layer>
+                <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="0.000000000e+00" zsign0="1.000000000e+00" zposition="6.462000000e+02">
+                    <support thickness="2.000000000e+00" width="2.665000000e+02" lengthMin="1.292930388e+01" lengthMax="1.189495957e+02" rInner="3.250000000e+01" radLength="2.807467352e+02" />
+                    <sensitive thickness="2.000000000e-01" width="2.665000000e+02" lengthMin="1.292930388e+01" lengthMax="1.189495957e+02" rInner="3.250000000e+01" radLength="9.366070445e+01" />
+                </layer>
+                <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="0.000000000e+00" zsign0="1.000000000e+00" zposition="8.472000000e+02">
+                    <support thickness="2.000000000e+00" width="2.750000000e+02" lengthMin="1.352604098e+01" lengthMax="1.229278430e+02" rInner="3.400000000e+01" radLength="2.807467352e+02" />
+                    <sensitive thickness="2.000000000e-01" width="2.750000000e+02" lengthMin="1.352604098e+01" lengthMax="1.229278430e+02" rInner="3.400000000e+01" radLength="9.366070445e+01" />
+                </layer>
+                <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="0.000000000e+00" zsign0="1.000000000e+00" zposition="9.262000000e+02">
+                    <support thickness="2.000000000e+00" width="2.735000000e+02" lengthMin="1.412277808e+01" lengthMax="1.229278430e+02" rInner="3.550000000e+01" radLength="2.807467352e+02" />
+                    <sensitive thickness="2.000000000e-01" width="2.735000000e+02" lengthMin="1.412277808e+01" lengthMax="1.229278430e+02" rInner="3.550000000e+01" radLength="9.366070445e+01" />
+                </layer>
+            </layers>
+            <parameter name="strip_angle_deg" type="double" value="5.000000000e+00" />
+            <parameter name="strip_length_mm" type="double" value="1.600000000e+03" />
+            <parameter name="strip_pitch_mm" type="double" value="1.000000000e-02" />
+            <parameter name="strip_width_mm" type="double" value="1.000000000e-03" />
+        </detector>
+        <detector name="SIT" geartype="ZPlanarParameters">
+            <type technology="CCD" />
+            <shell halfLength="0.000000000e+00" gap="0.000000000e+00" innerRadius="0.000000000e+00" outerRadius="0.000000000e+00" radLength="0.000000000e+00" />
+            <layers>
+                <layer nLadders="10" phi0="0.000000000e+00">
+                    <ladder distance="1.531000000e+02" thickness="1.000000000e+00" width="9.916044311e+01" length="3.680000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="1.529000000e+02" thickness="2.000000000e-01" width="9.916044311e+01" length="3.680000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="10" phi0="0.000000000e+00">
+                    <ladder distance="1.544000000e+02" thickness="1.000000000e+00" width="1.001352022e+02" length="3.680000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="1.554000000e+02" thickness="2.000000000e-01" width="1.001352022e+02" length="3.680000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="19" phi0="0.000000000e+00">
+                    <ladder distance="3.001000000e+02" thickness="1.000000000e+00" width="9.988891763e+01" length="6.440000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="2.999000000e+02" thickness="2.000000000e-01" width="9.988891763e+01" length="6.440000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="19" phi0="0.000000000e+00">
+                    <ladder distance="3.014000000e+02" thickness="1.000000000e+00" width="1.003895291e+02" length="6.440000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="3.024000000e+02" thickness="2.000000000e-01" width="1.003895291e+02" length="6.440000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+            </layers>
+            <parameter name="sensor_length_mm" type="double" value="9.200000000e+01" />
+            <parameter name="strip_angle_deg" type="double" value="7.000000000e+00" />
+            <parameter name="strip_length_mm" type="double" value="9.200000000e+01" />
+            <parameter name="strip_pitch_mm" type="double" value="5.000000000e-02" />
+            <parameter name="strip_width_mm" type="double" value="1.250000000e-02" />
+            <parameter name="n_sensors_per_ladder" type="IntVec" value="8 8 14 14" />
+        </detector>
+        <detector name="SET" geartype="ZPlanarParameters">
+            <type technology="CCD" />
+            <shell halfLength="0.000000000e+00" gap="0.000000000e+00" innerRadius="0.000000000e+00" outerRadius="0.000000000e+00" radLength="0.000000000e+00" />
+            <layers>
+                <layer nLadders="24" phi0="0.000000000e+00">
+                    <ladder distance="1.811100000e+03" thickness="1.000000000e+00" width="4.766190158e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="1.810900000e+03" thickness="2.000000000e-01" width="4.766190158e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+                <layer nLadders="24" phi0="0.000000000e+00">
+                    <ladder distance="1.812400000e+03" thickness="1.000000000e+00" width="4.770139733e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="2.134851878e+02" />
+                    <sensitive distance="1.813400000e+03" thickness="2.000000000e-01" width="4.770139733e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="9.366070445e+01" />
+                </layer>
+            </layers>
+            <parameter name="sensor_length_mm" type="double" value="9.200000000e+01" />
+            <parameter name="strip_angle_deg" type="double" value="7.000000000e+00" />
+            <parameter name="strip_length_mm" type="double" value="9.200000000e+01" />
+            <parameter name="strip_pitch_mm" type="double" value="5.000000000e-02" />
+            <parameter name="strip_width_mm" type="double" value="1.250000000e-02" />
+            <parameter name="n_sensors_per_ladder" type="IntVec" value="50 50" />
+        </detector>
+        <detector name="BeamPipe" geartype="GearParameters">
+            <parameter name="BeamPipeHalfZ" type="double" value="7.300000000e+02" />
+            <parameter name="BeamPipeProperties_RadLen" type="double" value="3.527597571e+02" />
+            <parameter name="BeamPipeProperties_dEdx" type="double" value="2.941795296e-04" />
+            <parameter name="BeamPipeRadius" type="double" value="1.400000000e+01" />
+            <parameter name="BeamPipeThickness" type="double" value="5.000000000e-01" />
+            <parameter name="RInner" type="DoubleVec" value="1.400000000e+01 1.400000000e+01 2.500000000e+00 1.300000000e+01 1.300000000e+01 1.300000000e+01 1.550000000e+01 1.550000000e+01 1.900000000e+01 1.900000000e+01 2.500000000e+01 2.500000000e+01 1.300000000e+01 1.300000000e+01 2.050000000e+01 2.050000000e+01 2.300000000e+01 2.300000000e+01 2.600000000e+01 2.600000000e+01 3.200000000e+01 3.200000000e+01" />
+            <parameter name="ROuter" type="DoubleVec" value="1.450000000e+01 1.450000000e+01 1.800000000e+01 1.800000000e+01 1.550000000e+01 1.550000000e+01 1.900000000e+01 1.900000000e+01 2.500000000e+01 2.500000000e+01 3.300000000e+01 3.300000000e+01 1.550000000e+01 1.550000000e+01 2.300000000e+01 2.300000000e+01 2.600000000e+01 2.600000000e+01 3.200000000e+01 3.200000000e+01 4.000000000e+01 4.000000000e+01" />
+            <parameter name="Z" type="DoubleVec" value="0.000000000e+00 5.000000000e+02 7.000000000e+02 7.010000000e+02 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 3.950000000e+03 3.950000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03" />
+        </detector>
+        <detector name="CoilParameters" geartype="GearParameters">
+            <parameter name="Coil_cryostat_c_modules_half_z" type="double" value="1.224000000e+03" />
+            <parameter name="Coil_cryostat_c_modules_inner_radius" type="double" value="3.348930000e+03" />
+            <parameter name="Coil_cryostat_c_modules_outer_radius" type="double" value="3.599930000e+03" />
+            <parameter name="Coil_cryostat_half_z" type="double" value="3.872000000e+03" />
+            <parameter name="Coil_cryostat_inner_cyl_half_z" type="double" value="3.872000000e+03" />
+            <parameter name="Coil_cryostat_inner_cyl_inner_radius" type="double" value="3.173930000e+03" />
+            <parameter name="Coil_cryostat_inner_cyl_outer_radius" type="double" value="3.963930000e+03" />
+            <parameter name="Coil_cryostat_inner_radius" type="double" value="3.173930000e+03" />
+            <parameter name="Coil_cryostat_mandrel_half_z" type="double" value="3.675000000e+03" />
+            <parameter name="Coil_cryostat_mandrel_inner_radius" type="double" value="3.599930000e+03" />
+            <parameter name="Coil_cryostat_mandrel_outer_radius" type="double" value="3.827930000e+03" />
+            <parameter name="Coil_cryostat_modules_half_z" type="double" value="7.960000000e+02" />
+            <parameter name="Coil_cryostat_modules_inner_radius" type="double" value="3.348930000e+03" />
+            <parameter name="Coil_cryostat_modules_outer_radius" type="double" value="3.599930000e+03" />
+            <parameter name="Coil_cryostat_outer_cyl_half_z" type="double" value="3.872000000e+03" />
+            <parameter name="Coil_cryostat_outer_cyl_inner_radius" type="double" value="3.893930000e+03" />
+            <parameter name="Coil_cryostat_outer_cyl_outer_radius" type="double" value="3.923930000e+03" />
+            <parameter name="Coil_cryostat_outer_radius" type="double" value="3.923930000e+03" />
+            <parameter name="Coil_cryostat_scint1_inner_radius" type="double" value="3.263930000e+03" />
+            <parameter name="Coil_cryostat_scint1_outer_radius" type="double" value="3.273930000e+03" />
+            <parameter name="Coil_cryostat_scint1_zposend" type="double" value="3.972000000e+03" />
+            <parameter name="Coil_cryostat_scint1_zposin" type="double" value="3.772000000e+03" />
+            <parameter name="Coil_cryostat_scint2_inner_radius" type="double" value="3.278930000e+03" />
+            <parameter name="Coil_cryostat_scint2_outer_radius" type="double" value="3.288930000e+03" />
+            <parameter name="Coil_cryostat_scint2_zposend" type="double" value="3.972000000e+03" />
+            <parameter name="Coil_cryostat_scint2_zposin" type="double" value="3.772000000e+03" />
+            <parameter name="Coil_cryostat_scint3_inner_radius" type="double" value="3.833930000e+03" />
+            <parameter name="Coil_cryostat_scint3_outer_radius" type="double" value="3.843930000e+03" />
+            <parameter name="Coil_cryostat_scint3_zposend" type="double" value="3.972000000e+03" />
+            <parameter name="Coil_cryostat_scint3_zposin" type="double" value="3.772000000e+03" />
+            <parameter name="Coil_cryostat_scint4_inner_radius" type="double" value="3.818930000e+03" />
+            <parameter name="Coil_cryostat_scint4_outer_radius" type="double" value="3.828930000e+03" />
+            <parameter name="Coil_cryostat_scint4_zposend" type="double" value="3.972000000e+03" />
+            <parameter name="Coil_cryostat_scint4_zposin" type="double" value="3.772000000e+03" />
+            <parameter name="Coil_cryostat_side_l_half_z" type="double" value="2.500000000e+01" />
+            <parameter name="Coil_cryostat_side_l_inner_radius" type="double" value="3.213930000e+03" />
+            <parameter name="Coil_cryostat_side_l_outer_radius" type="double" value="3.893930000e+03" />
+            <parameter name="Coil_cryostat_side_r_half_z" type="double" value="2.500000000e+01" />
+            <parameter name="Coil_cryostat_side_r_inner_radius" type="double" value="3.213930000e+03" />
+            <parameter name="Coil_cryostat_side_r_outer_radius" type="double" value="3.893930000e+03" />
+            <parameter name="Coil_material_c_modules" type="string" value="aluminium" />
+            <parameter name="Coil_material_inner_cyl" type="string" value="aluminium" />
+            <parameter name="Coil_material_mandrel" type="string" value="aluminium" />
+            <parameter name="Coil_material_modules" type="string" value="aluminium" />
+            <parameter name="Coil_material_outer_cyl" type="string" value="aluminium" />
+            <parameter name="Coil_material_scint1" type="string" value="polystyrene" />
+            <parameter name="Coil_material_scint2" type="string" value="polystyrene" />
+            <parameter name="Coil_material_scint3" type="string" value="polystyrene" />
+            <parameter name="Coil_material_scint4" type="string" value="polystyrene" />
+            <parameter name="Coil_material_side_l" type="string" value="aluminium" />
+            <parameter name="Coil_material_side_r" type="string" value="aluminium" />
+        </detector>
+        <detector name="MokkaParameters" geartype="GearParameters">
+            <parameter name="Ecal_endcap_outer_radius" type="string" value="2088.8" />
+            <parameter name="Ecal_endcap_plug_rmin" type="string" value="240" />
+            <parameter name="Ecal_endcap_zmax" type="string" value="2635" />
+            <parameter name="Ecal_endcap_zmin" type="string" value="2450" />
+            <parameter name="Ecal_outer_radius" type="string" value="2028" />
+            <parameter name="Hcal_R_max" type="string" value="3144.43" />
+            <parameter name="Hcal_endcap_zmin" type="string" value="2650" />
+            <parameter name="Lcal_z_begin" type="string" value="951.9" />
+            <parameter name="Lcal_z_thickness" type="string" value="128.1" />
+            <parameter name="MokkaModel" type="string" value="CEPC_v4" />
+            <parameter name="MokkaVersion" type="string" value="void" />
+            <parameter name="SIT1_Half_Length_Z" type="string" value="368" />
+            <parameter name="SIT1_Radius" type="string" value="152.9" />
+            <parameter name="SIT2_Half_Length_Z" type="string" value="644" />
+            <parameter name="SIT2_Radius" type="string" value="299.9" />
+            <parameter name="SiTrackerEndcap" type="string" value="FTD_PIXEL,29.5,151.9,220,16;FTD_PIXEL,30.54,151.9,371,16;FTD_STRIP,32.5,299,645,16;FTD_STRIP,34,309,846,16;FTD_STRIP,35.5,309,925,16" />
+            <parameter name="SiTrackerLayerStructure" type="string" value="FTD_PIXEL,Si:-0.02,CarbonFiber:1;FTD_STRIP,Si:-0.2,CarbonFiber:2,Si:-0.2" />
+            <parameter name="TPC_Ecal_Hcal_barrel_halfZ" type="string" value="2350" />
+            <parameter name="Yoke_Z_start_endcaps" type="string" value="4072" />
+            <parameter name="Yoke_barrel_inner_radius" type="string" value="4173.929931640625" />
+            <parameter name="calorimeter_region_rmax" type="string" value="3144.43" />
+            <parameter name="calorimeter_region_zmax" type="string" value="3736.43" />
+            <parameter name="tracker_region_rmax" type="string" value="1842.9" />
+            <parameter name="tracker_region_zmax" type="string" value="2350" />
+            <parameter name="world_box_hx" type="string" value="" />
+            <parameter name="world_box_hy" type="string" value="" />
+            <parameter name="world_box_hz" type="string" value="" />
+        </detector>
+        <detector name="VXDInfra" geartype="GearParameters">
+            <parameter name="ActiveLayerProperties_dEdx" type="double" value="3.870163611e-04" />
+            <parameter name="BeSupportEndplateThickness" type="double" value="2.000000000e+00" />
+            <parameter name="BeSupport_dEdx" type="double" value="2.941795296e-04" />
+            <parameter name="CryostatAlHalfZ" type="double" value="1.766000000e+02" />
+            <parameter name="CryostatAlInnerR" type="double" value="2.420000000e+01" />
+            <parameter name="CryostatAlRadius" type="double" value="1.000000000e+02" />
+            <parameter name="CryostatAlThickness" type="double" value="5.000000000e-01" />
+            <parameter name="CryostatAlZEndCap" type="double" value="1.768500000e+02" />
+            <parameter name="CryostatFoamRadius" type="double" value="9.000000000e+01" />
+            <parameter name="CryostatFoamThickness" type="double" value="1.000000000e+01" />
+            <parameter name="Cryostat_RadLen" type="double" value="8.896317758e+01" />
+            <parameter name="Cryostat_dEdx" type="double" value="4.350185478e-04" />
+            <parameter name="ElectronicEndLength" type="double" value="1.000000000e+01" />
+            <parameter name="ElectronicEndThickness" type="double" value="1.000000000e-01" />
+            <parameter name="StripLineBeamPipeRadius" type="double" value="2.430000000e+01" />
+            <parameter name="VXDEndPlateInnerRadius" type="double" value="3.000000000e+01" />
+            <parameter name="VXDSupport_dEdx" type="double" value="5.431907412e-05" />
+            <parameter name="LadderGaps" type="DoubleVec" value="0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00" />
+            <parameter name="StripLineFinalZ" type="DoubleVec" value="1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02" />
+        </detector>
+    </detectors>
+    <materials>
+        <material name="VXDFoamShellMaterial" A="1.043890843e+01" Z="5.612886646e+00" density="2.500000000e+01" radLength="1.751650267e+04" intLength="6.594366018e+01" />
+        <material name="VXDSupportMaterial" A="2.075865162e+01" Z="1.039383117e+01" density="2.765900000e+02" radLength="1.014262421e+03" intLength="1.206635688e+02" />
+    </materials>
+</gear>
diff --git a/Detector/DetCRD/CMakeLists.txt b/Detector/DetCRD/CMakeLists.txt
index d1bf4f675c84d9b11a5bf957abf0c13f55615db0..f762843115db2b45e57697aa7239835938cc8cf8 100644
--- a/Detector/DetCRD/CMakeLists.txt
+++ b/Detector/DetCRD/CMakeLists.txt
@@ -27,6 +27,8 @@ gaudi_add_module(DetCRD
                          src/Muon/Muon_Endcap_v01.cpp
                          src/Tracker/SiTrackerSkewRing_v01_geo.cpp
                          src/Tracker/SiTrackerStaggeredLadder_v01_geo.cpp
+                         src/Tracker/TPC_Simple_o1_v01.cpp
+                         src/Tracker/TPC_ModularEndcap_o1_v01.cpp
 
 		 LINK ${DD4hep_COMPONENT_LIBRARIES}
 )
@@ -40,3 +42,19 @@ install(TARGETS DetCRD
   RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
   LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
   COMPONENT dev)
+
+################################################################################
+# Add tests
+################################################################################
+
+add_test(
+  NAME Test_TDR_o1_v01_Sim
+  COMMAND gaudirun.py Detector/DetCRD/scripts/TDR_o1_v01/sim.py
+  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+)
+
+add_test(
+  NAME Test_TDR_o1_v01_Rec
+  COMMAND gaudirun.py Detector/DetCRD/scripts/TDR_o1_v01/tracking.py
+  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+)
diff --git a/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v01.xml b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v01.xml
new file mode 100644
index 0000000000000000000000000000000000000000..92f9487c126759ccc7a145e4b8871581ec35777e
--- /dev/null
+++ b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v01.xml
@@ -0,0 +1,220 @@
+<lccdd>
+    <info
+        name   ="TPC_ModularEndcap_TDR_o1_v01"
+        status ="developing"
+        version = "TPC_ModularEndcap_TDR_o1_v01"
+        author = "Xin She">
+        <comment> The compact format for the CEPC TPC used for the TDR </comment>
+    </info>
+
+    <define> 
+        <!--from CDR baseline-->
+        <!--Readout pad size-->
+        <constant name="TPC_pad_height"              value="0.5*mm"      />
+        <constant name="TPC_pad_width"               value="0.5*mm"      />
+        <constant name="TPC_max_step_length"         value="5*mm"      />
+        <constant name="TPC_sensitive_threshold_eV"      value="32*eV"     />
+        <!--Wall/Cathode/Readout/Endplate-->
+        <constant name="TPC_dr_InnerWall"            value="25.*mm"     />
+        <constant name="TPC_dr_InnerServiceArea"     value="10*mm"     />
+        <constant name="TPC_dr_OuterServiceArea"     value="23*mm"     />
+        <constant name="TPC_dr_OuterWall"            value="25.*mm"     />
+        <constant name="TPC_dz_Cathode"              value="0.06*mm"   />
+        <constant name="TPC_dz_Readout"              value="3.50*mm"     />
+        <constant name="TPC_dz_Endplate"             value="135*mm"    />
+        <constant name="TPC_dz_Cathode_Insulator"    value="0.0275*mm" />
+        <constant name="TPC_dz_Cathode_Conductor"    value="0.0025*mm" />
+        <constant name="TPC_dr_Cathode_Grip"         value="10.*mm"     />
+        <constant name="TPC_dz_Cathode_Grip"         value="15*mm"     />
+        <!-- Inermeidate variables                                --> 
+        <constant name="TPC_rMin_GasVolume"          value="TPC_inner_radius+TPC_dr_InnerWall"/>
+        <constant name="TPC_rMax_GasVolume"          value="TPC_outer_radius-TPC_dr_OuterWall"/>
+        <constant name="TPC_dz_GasVolume"            value="TPC_half_length-TPC_dz_Endplate"/>
+        <constant name="TPC_rMin_Sensitive"          value="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea"/>
+        <constant name="TPC_rMax_Sensitive"          value="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"/>
+        <constant name="TPC_dz_Wall"                 value="2*TPC_dz_GasVolume"/>
+        <constant name="TPC_dz_Sensitive"            value="TPC_dz_GasVolume-TPC_dz_Readout-TPC_dz_Cathode/2."/>
+        <constant name="TPC_numberOfPadrows"         value="int((TPC_rMax_Sensitive-TPC_rMin_Sensitive)/TPC_pad_height)"/>
+    </define>
+
+    <display>
+      <vis name="CuVis"   alpha="1.0" r="0.5" g=".5"  b=".5"   showDaughters="true"  visible="true"/>
+      <vis name="KaptonVis"   alpha="0.8" r="1" g="0."  b="0."   showDaughters="true"  visible="true"/>
+      <vis name="gasVis" alpha="0.2" r="0.0" g="1.0" b="0.0"  showDaughters="true"  visible="true"/>
+      <vis name="transVis" alpha="0.1" r="1.0" g="1.0" b="1.0"  showDaughters="true"  visible="true"/>
+      <vis name="readoutVis" alpha="0.8" r="1.0" g=".0" b=".0"  showDaughters="true"  visible="true"/>
+      <vis name="aramidVis" alpha="1.0" r="0.0" g="0.3" b="0.7"  showDaughters="true"  visible="true"/>
+      <vis name="epoxyVis" alpha="0.2" r="0.0" g="0.3" b="0.3"  showDaughters="true"  visible="true"/>
+      <vis name="TPCMotherVis1"     alpha="0.5" r="0.96"  g="0.64"    b="0.90"  showDaughters="true"  visible="true"/>
+    </display>
+
+    <detectors>
+      <detector name="TPC" type="TPC_ModularEndcap_o1_v01" vis="TPCVis" id="DetID_TPC" limits="tracker_limits" readout="TPCCollection" insideTrackingVolume="true">
+
+      <envelope vis="TPCVis">
+        <shape type="Tube" rmin="TPC_inner_radius" rmax="TPC_outer_radius" dz="TPC_half_length" material="Air"/>
+      </envelope>
+      
+      <type_flags type="DetType_TRACKER +  DetType_BARREL + DetType_GASEOUS "/>
+    
+       <component name="TPCinnerWall" type="TPCinnerWall" R_start="TPC_inner_radius" R_end="TPC_rMin_GasVolume" Z_fulllength="TPC_dz_Wall"> 
+           <!--HoneyComb wall  -->
+           <!--layer material="G4_Cu"           thickness = "0.01*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Aramid"          thickness = "0.07*mm"  vis="aramidVis" />
+           <layer material="AramidHoneycomb" thickness = "23.5*mm"  vis="aramidVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Kapton"          thickness = "0.0125*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="epoxy"           thickness = "0.042*mm"  vis="epoxy" /-->
+           <!--CF wall  -->
+           <layer material="G4_Cu"           thickness = "0.010*mm"  vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="Polyimide"       thickness = "0.05*mm"  vis="KaptonVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+       </component>
+       <component name="TPCouterWall" type="TPCouterWall" R_start="TPC_rMax_GasVolume" R_end="TPC_outer_radius" Z_fulllength="TPC_dz_Wall"> 
+           <!--HoneyComb wall  -->
+           <!--layer material="Copper80P"       thickness = "0.01*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.03*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.07*mm"  vis="KaptonVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="AramidHoneycomb" thickness = "23.5*mm"  vis="aramidVis" />
+           <layer material="Aramid"          thickness = "0.07*mm"  vis="aramidVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="G4_Cu"           thickness = "0.01*mm"  vis="CuVis" />
+           <layer material="epoxy"           thickness = "0.042*mm"  vis="epoxy" /-->
+           <!--CF wall  -->
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"   vis="CuVis"/>
+           <layer material="Polyimide"       thickness = "0.05*mm"   vis="KaptonVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"   vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.010*mm"  vis="CuVis"/>
+       </component>
+       <component name="Grip" type="TPCGrip" material="SiC_foam">
+           <layer name="TPCinnerGrip" rmin="TPC_rMin_GasVolume"  rmax="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> 
+            <layer name="TPCouterGrip" rmin="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"  rmax="TPC_rMax_GasVolume" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> 
+       </component>
+       <component name="Cathode" type="TPCCathode">
+           <layer name="Cathodeinsulator" material= "Kapton" rmin="TPC_rMin_Sensitive"  rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Insulator" vis="KaptonVis">
+                  <position x="0.*mm" y="0.*mm" z="+ TPC_dz_Cathode_Insulator/2."/>
+                  <position x="0.*mm" y="0.*mm" z="- TPC_dz_Cathode_Insulator/2."/>
+           </layer>
+           <layer name="Cathodeconductor" material= "G4_Cu" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Conductor" vis="CuVis">
+                  <position x="0.*mm" y="0.*mm" z="+ (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/>
+                  <position x="0.*mm" y="0.*mm" z="- (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/>
+           </layer>
+       </component>
+       <component name="TPCreadout" type="TPCreadout" material="T2KGas1">
+           <dimensions rmin = "TPC_rMin_GasVolume" rmax = "TPC_rMax_GasVolume" z_length = "TPC_dz_Readout"/>
+           <position x="0.*mm" y="0.*mm" z="+(TPC_half_length-TPC_dz_Endplate-TPC_dz_Readout/2.)"/>
+           <!--Triple Gem readout structure from CEPCV4-->
+           <!--layer material="G4_Cu"       dz="0.003*mm"  comment="gating" vis="CuVis" />
+           <layer material="G4_KAPTON"   dz="0.030*mm"  comment="gating" vis="KaptonVis"  />
+           <layer material="G4_Cu"       dz="0.003*mm"  comment="gating"    vis="CuVis"/>
+           <layer material="T2KGas1"     dz="4.447*mm"  comment="gating"  vis="gasVis"/>
+           <layer material="G4_Cu"       dz="0.003*mm"  comment="mpgd"      vis="CuVis"/>
+           <layer material="G4_KAPTON"   dz="0.030*mm"  comment="mpgd"   vis="Kapton"/>
+           <layer material="G4_Cu"       dz="0.003*mm"  comment="mpgd"      vis="CuVis"/>
+           <layer material="T2KGas1"     dz="4.447*mm"  comment="mpgd"    vis="gasVis"/>
+           <layer material="G4_Cu"       dz="0.003*mm"  comment="mpgd"      vis="CuVis"/>
+           <layer material="G4_KAPTON"   dz="0.030*mm"  comment="mpgd"   vis="KaptonVis"/>
+           <layer material="G4_Cu"       dz="0.003*mm"  comment="mpgd"      vis="CuVis"/>
+           <layer material="T2KGas1"     dz="4.447*mm"  comment="mpgd"    vis="gasVis"/>
+           <layer material="G4_Cu"       dz="0.050*mm"  comment="pads"       vis="CuVis"/>
+           <layer material="g10"         dz="2.000*mm"  comment="structural"      vis="gasVis"/>
+           <layer material="G4_Si"       dz="0.500*mm"  comment="electronics" vis="epoxyVis" />
+           <layer material="epoxy"       dz="2*mm"      comment="structural"    vis="epoxyVis"/>
+           <layer material="G4_KAPTON"   dz="1*mm"      comment="structural" vis="KaptonVis"  />
+           <layer material="G4_Al"       dz="2*mm"      comment="Cooling"       vis="GrayVis"/>
+           <layer material="G4_KAPTON"   dz="1*mm"      comment="structural"  vis="KaptonVis"/>
+           <layer material="CarbonFiber" dz="3*mm"      comment="structural" vis="GrayVis"  /-->
+           <!--MicroMegas readout structure-->
+           <layer material="G4_Fe"       dz="0.025*mm"  comment="Mesh"           vis="GrayVis"/>
+           <layer material="T2KGas1"     dz="0.128*mm"  comment="GasAmpRegion"   vis="gasVis"/>
+           <layer material="G4_KAPTON"   dz="0.050*mm"  comment="Kaptonfoil"     vis="KaptonVis"/>
+           <layer material="Acrylicglue" dz="0.008*mm"  comment="gule"           vis="BlueVis"/>
+           <layer material="G4_Cu"       dz="0.017*mm"  comment="ReadoutPad"     vis="CuVis"/>
+           <layer material="PCB"         dz="1.000*mm"  comment="PCBboard"       vis="GreenVis"/>
+           <layer material="G4_Si"       dz="0.500*mm"  comment="electronics"    vis="BlackVis"/>
+           <layer material="epoxy"       dz="1.500*mm"  comment="structural"     vis="epoxyVis"/>
+       </component>
+       <component name="TPCSensitiveVol" type="TPCSensitiveVol" material="T2KGas1">
+           <dimensions rmin = "TPC_rMin_Sensitive" rmax = "TPC_rMax_Sensitive" z_length = "TPC_dz_Sensitive"/>
+           <layer      repeat="TPC_numberOfPadrows" thickness="TPC_pad_height"/>
+       </component>
+       <component name="TPCEndplate" type="TPCEndplate" z_frame="20.*mm" s_frame="20.*mm" >
+           <dimensions rmin = "TPC_inner_radius" rmax = "TPC_outer_radius" z_length = "TPC_dz_Endplate"/>
+           <layer name="InnerPlate" type="Frame" thickness="25.*mm"/>
+           <layer name="ring1"      type="Frame" thickness="10.*mm"/>
+           <layer name="module1"    type="Module" thickness="151.*mm" repeat="23" phi0_offset="0.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer>
+           <layer name="ring2"      type="Frame" thickness="20.*mm"/>
+           <layer name="module2"    type="Module" thickness="141.*mm" repeat="27" phi0_offset="+10.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+             <slice material="PCB"   dz="10.0*mm" comment="cooling"/>
+           </layer>
+           <layer name="ring3"      type="Frame" thickness="20.*mm"/>
+           <layer name="module3"    type="Module" thickness="141.*mm" repeat="32" phi0_offset="-5.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer> 
+           <layer name="ring4"      type="Frame" thickness="20.*mm"/>
+           <layer name="module4"    type="Module" thickness="141.*mm" repeat="34" phi0_offset="0.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer>
+           <layer name="ring5"      type="Frame" thickness="20.*mm"/>
+           <layer name="module5"    type="Module" thickness="141.*mm" repeat="39" phi0_offset="+5.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer>
+           <layer name="ring6"      type="Frame" thickness="20.*mm"/>
+           <layer name="module6"    type="Module" thickness="141.*mm" repeat="44" phi0_offset="-5.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer>
+           <layer name="ring7"      type="Frame" thickness="20.*mm"/>
+           <layer name="module7"    type="Module" thickness="141.*mm" repeat="49" phi0_offset="0.*deg">
+             <slice material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+             <slice material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+             <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+             <slice material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+           </layer>
+           <layer name="ring8"      type="Frame" thickness="23.*mm"/>
+           <layer name="Outerplate" type="Frame" thickness="25.*mm"/>
+       </component>
+    
+    </detector>
+  </detectors>
+
+  <readouts>
+    <readout name="TPCCollection">
+      <id>system:5,side:-2,layer:13,module:6,sensor:6</id>
+    </readout>
+  </readouts>
+
+</lccdd>
diff --git a/Detector/DetCRD/compact/CRD_common_v02/TPC_Simple_o1_v01.xml b/Detector/DetCRD/compact/CRD_common_v02/TPC_Simple_o1_v01.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6b8298977f24449f0d28114e9c63f54bd057f1ea
--- /dev/null
+++ b/Detector/DetCRD/compact/CRD_common_v02/TPC_Simple_o1_v01.xml
@@ -0,0 +1,160 @@
+<lccdd>
+    <info
+        name   ="TPC_Simple_TDR_o1_v01"
+        status ="developing"
+        version = "TPC_Simple_TDR_o1_v01">
+        <comment> The compact format for the CEPC TPC used for the TDR </comment>
+    </info>
+
+    <define> 
+        <!--from CDR baseline-->
+        <!--Readout pad size-->
+        <constant name="TPC_pad_height"          value="0.5*mm"      />
+        <constant name="TPC_pad_width"           value="0.5*mm"      />
+        <constant name="TPC_max_step_length"     value="5*mm"      />
+        <!--Wall/Cathode/Readout/Endplate  Honeycomb barrel-->
+        <constant name="TPC_dr_InnerWall"            value="25.*mm"     />
+        <constant name="TPC_dr_InnerServiceArea"     value="10*mm"     />
+        <constant name="TPC_dr_OuterServiceArea"     value="23*mm"     />
+        <constant name="TPC_dr_OuterWall"            value="25.*mm"     />
+        <constant name="TPC_dz_Cathode"              value="0.06*mm"   />
+        <constant name="TPC_dz_Readout"              value="3.50*mm"     />
+        <constant name="TPC_dz_Endplate"             value="135*mm"    />
+        <constant name="TPC_sensitive_threshold_eV"  value="32*eV"     />
+        <constant name="TPC_dz_Cathode_Insulator"    value="0.0275*mm" />
+        <constant name="TPC_dz_Cathode_Conductor"    value="0.0025*mm" />
+        <constant name="TPC_dr_Cathode_Grip"         value="10.*mm"/>
+        <constant name="TPC_dz_Cathode_Grip"         value="15*mm"     />
+        <!-- Inermeidate variables                                --> 
+        <constant name="TPC_rMin_GasVolume"          value="TPC_inner_radius+TPC_dr_InnerWall"/>
+        <constant name="TPC_rMax_GasVolume"          value="TPC_outer_radius-TPC_dr_OuterWall"/>
+        <constant name="TPC_dz_GasVolume"            value="TPC_half_length-TPC_dz_Endplate"/>
+        <constant name="TPC_rMin_Sensitive"          value="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea"/>
+        <constant name="TPC_rMax_Sensitive"          value="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"/>
+        <constant name="TPC_dz_Wall"                 value="2*TPC_dz_GasVolume"/>
+        <constant name="TPC_dz_Sensitive"            value="TPC_dz_GasVolume-TPC_dz_Readout-TPC_dz_Cathode/2."/>
+        <constant name="TPC_numberOfPadrows"         value="int((TPC_rMax_Sensitive-TPC_rMin_Sensitive)/TPC_pad_height)"/>
+    </define>
+
+    <display>
+      <vis name="CuVis"   alpha="1.0" r="0.5" g=".5"  b=".5"   showDaughters="true"  visible="true"/>
+      <vis name="KaptonVis"   alpha="0.8" r="1" g="0."  b="0."   showDaughters="true"  visible="true"/>
+      <vis name="gasVis" alpha="0.2" r="0.0" g="1.0" b="0.0"  showDaughters="true"  visible="true"/>
+      <vis name="readoutVis" alpha="0.8" r="1.0" g=".0" b=".0"  showDaughters="true"  visible="true"/>
+      <vis name="aramidVis" alpha="1.0" r="0.0" g="0.3" b="0.7"  showDaughters="true"  visible="true"/>
+      <vis name="epoxyVis" alpha="0.2" r="0.0" g="0.3" b="0.3"  showDaughters="true"  visible="true"/>
+      <vis name="TPCMotherVis1"     alpha="0.5" r="0.96"  g="0.64"    b="0.90"  showDaughters="true"  visible="true"/>
+    </display>
+
+    <detectors>
+      <detector name="TPC" type="TPC_Simple_o1_v01" vis="TPCVis" id="DetID_TPC" limits="tracker_limits" readout="TPCCollection" insideTrackingVolume="true">
+
+      <envelope vis="TPCVis">
+        <shape type="Tube" rmin="TPC_inner_radius" rmax="TPC_outer_radius" dz="TPC_half_length" material="Air"/>
+      </envelope>
+      
+      <type_flags type="DetType_TRACKER +  DetType_BARREL + DetType_GASEOUS "/>
+    
+       <component name="TPCinnerWall" type="TPCinnerWall" R_start="TPC_inner_radius" R_end="TPC_rMin_GasVolume" Z_fulllength="TPC_dz_Wall"> 
+           <!--HoneyComb wall  -->
+           <!--layer material="G4_Cu"           thickness = "0.01*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Aramid"          thickness = "0.07*mm"  vis="aramidVis" />
+           <layer material="AramidHoneycomb" thickness = "23.5*mm"  vis="aramidVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Kapton"          thickness = "0.0125*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="epoxy"           thickness = "0.042*mm"  vis="epoxy" /-->
+           <!--CF wall  -->
+           <layer material="G4_Cu"           thickness = "0.010*mm"  vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="Polyimide"       thickness = "0.05*mm"  vis="KaptonVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+       </component>
+       <component name="TPCouterWall" type="TPCouterWall" R_start="TPC_rMax_GasVolume" R_end="TPC_outer_radius" Z_fulllength="TPC_dz_Wall"> 
+           <!--HoneyComb wall  -->
+           <!--layer material="G4_Cu"           thickness = "0.01*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Aramid"          thickness = "0.07*mm"  vis="aramidVis" />
+           <layer material="AramidHoneycomb" thickness = "23.5*mm"  vis="aramidVis" />
+           <layer material="g10-TPC"         thickness = "0.3*mm"  vis="gasVis" />
+           <layer material="Kapton"          thickness = "0.0125*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="Kapton"          thickness = "0.05*mm"  vis="KaptonVis" />
+           <layer material="Copper80P"       thickness = "0.035*mm"  vis="CuVis" />
+           <layer material="epoxy"           thickness = "0.042*mm"  vis="epoxy" /-->
+           <!--CF wall  -->
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="Polyimide"       thickness = "0.05*mm"  vis="KaptonVis"/>
+           <layer material="G4_Cu"           thickness = "0.03*mm"  vis="CuVis"/>
+           <layer material="CarbonFiber"     thickness = "0.1*mm"    vis="aramidVis"/>
+           <layer material="G4_Cu"           thickness = "0.010*mm"  vis="CuVis"/>
+       </component>
+       <component name="Grip" type="TPCGrip" material="SiC_foam">
+           <layer name="TPCinnerGrip"  rmin="TPC_rMin_GasVolume"   rmax="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea"  z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> 
+           <layer name="TPCouterGrip"  rmin="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"  rmax="TPC_rMax_GasVolume" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> 
+       </component>
+       <component name="Cathode" type="TPCCathode">
+           <layer name="Cathodeinsulator" material= "Kapton" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Insulator" vis="KaptonVis">
+                  <position x="0.*mm" y="0.*mm" z="+ TPC_dz_Cathode_Insulator/2."/>
+                  <position x="0.*mm" y="0.*mm" z="- TPC_dz_Cathode_Insulator/2."/>
+            </layer>
+            <layer name="Cathodeconductor" material= "G4_Cu" rmin="TPC_rMin_Sensitive"  rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Conductor" vis="CuVis">
+                  <position x="0.*mm" y="0.*mm" z="+ (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/>
+                  <position x="0.*mm" y="0.*mm" z="- (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/>
+            </layer>
+       </component>
+       <component name="TPCreadout" type="TPCreadout" material="T2KGas1">
+           <dimensions rmin = "TPC_rMin_GasVolume" rmax = "TPC_rMax_GasVolume" z_length = "TPC_dz_Readout"/>
+           <position x="0.*mm" y="0.*mm" z="+(TPC_half_length-TPC_dz_Endplate-TPC_dz_Readout/2.)"/>
+           <!--layer thickness="0.003*mm" material="G4_Cu" comment="gating" vis="CuVis" />
+           <layer thickness="0.03*mm" material="G4_KAPTON" comment="gating" vis="KaptonVis"  />
+           <layer thickness="0.003*mm" material="G4_Cu" comment="gating"    vis="CuVis"/>
+           <layer thickness="4.447*mm" material="T2KGas1" comment="gating"  vis="gasVis"/>
+           <layer thickness="0.003*mm" material="G4_Cu" comment="mpgd"      vis="CuVis"/>
+           <layer thickness="0.03*mm" material="G4_KAPTON" comment="mpgd"   vis="Kapton"/>
+           <layer thickness="0.003*mm" material="G4_Cu" comment="mpgd"      vis="CuVis"/>
+           <layer thickness="4.447*mm" material="T2KGas1" comment="mpgd"    vis="gasVis"/>
+           <layer thickness="0.003*mm" material="G4_Cu" comment="mpgd"      vis="CuVis"/>
+           <layer thickness="0.03*mm" material="G4_KAPTON" comment="mpgd"   vis="KaptonVis"/>
+           <layer thickness="0.003*mm" material="G4_Cu" comment="mpgd"      vis="CuVis"/>
+           <layer thickness="4.447*mm" material="T2KGas1" comment="mpgd"    vis="gasVis"/-->
+           <!--MicroMegas readout structure-->
+           <layer material="G4_Fe"       dz="0.025*mm"  comment="Mesh"           vis="GrayVis"/>
+           <layer material="T2KGas1"     dz="0.128*mm"  comment="GasAmpRegion"   vis="gasVis"/>
+           <layer material="G4_KAPTON"   dz="0.050*mm"  comment="Kaptonfoil"     vis="KaptonVis"/>
+           <layer material="Acrylicglue" dz="0.008*mm"  comment="gule"           vis="BlueVis"/>
+           <layer material="G4_Cu"       dz="0.017*mm"  comment="ReadoutPad"     vis="CuVis"/>
+           <layer material="PCB"         dz="1.000*mm"  comment="PCBboard"       vis="GreenVis"/>
+           <layer material="G4_Si"       dz="0.500*mm"  comment="electronics"    vis="BlackVis"/>
+           <layer material="epoxy"       dz="1.500*mm"  comment="structural"     vis="epoxyVis"/>
+       </component>
+       <component name="TPCSensitiveVol" type="TPCSensitiveVol" material="T2KGas1">
+           <dimensions  rmin = "TPC_rMin_Sensitive" rmax = "TPC_rMax_Sensitive" z_length = "TPC_dz_Sensitive"/>
+           <layer repeat="TPC_numberOfPadrows" thickness="TPC_pad_height"/>
+       </component>
+       <component name="TPCEndplate" type="TPCEndplate">
+           <dimensions  rmin = "TPC_inner_radius" rmax = "TPC_outer_radius" z_length = "TPC_dz_Endplate"/>
+           <layer material="PCB"              dz="5.0*mm"  comment="FEE_BEEPCB"/>
+           <layer material="G4_Al"            dz="1.5*mm"  comment="cooling"/>
+           <layer material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/>
+           <layer material="CarbonFiber"      dz="3.0*mm"  comment="structural"/>
+       </component>
+
+    </detector>
+  </detectors>
+
+  <readouts>
+    <readout name="TPCCollection">
+      <id>system:5,side:-2,layer:13,module:6,sensor:6</id>
+    </readout>
+  </readouts>
+
+</lccdd>
diff --git a/Detector/DetCRD/compact/CRD_common_v02/materials.xml b/Detector/DetCRD/compact/CRD_common_v02/materials.xml
index 0cb4540c9e4eef5802afbe8b026314927ad9b417..d59e16913ed1379dd354177529ce493d338ad93c 100644
--- a/Detector/DetCRD/compact/CRD_common_v02/materials.xml
+++ b/Detector/DetCRD/compact/CRD_common_v02/materials.xml
@@ -685,6 +685,27 @@
      <composite n="1"  ref="O" />
    </material>
 
+   <material name="T2KGas1" state="gas">
+       <MEE unit="eV" value="177.374841770826"/>
+       <D value="0.0017357" unit="g/cm3"/>
+       <fraction n="0.908928"    ref="Ar"/>
+       <fraction n="0.031643"    ref="C"/>
+       <fraction n="0.004828"    ref="H"/>
+       <fraction n="0.054601"    ref="F"/>
+   </material>      
+
+   <material name="Polyimide" state="solide">
+       <D value="1.38"   unit="g/cm3"/>
+       <composite n="22" ref="C"/>
+       <composite n="10" ref="H"/>
+       <composite n="2"  ref="N"/>
+       <composite n="5"  ref="O"/>
+   </material>
+   <material name="TPC_Alframe" state="solid">
+       <D value="1.8" unit="g/cm3"/>
+       <fraction n="1." ref="Al" />
+   </material>
+
    <material name="LYSO" state="solid">
       <MEE unit="eV" value="9.5"/>
       <D value="7.15" unit="g/cm3" />
diff --git a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01-onlyTracker.xml b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01-onlyTracker.xml
index 355f336d741c0d936deb5cf2edc442475131bd67..bbfe7dce380359128b828a8a4ff1b407df1ccadb 100644
--- a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01-onlyTracker.xml
+++ b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01-onlyTracker.xml
@@ -27,9 +27,9 @@
   <include ref="./TDR_Dimensions_v01_01.xml"/>
 
   <!--TODO: vertex cooling-->
-  <include ref="../CRD_common_v02/Beampipe_v01_03.xml"/>
+  <!--include ref="../CRD_common_v02/Beampipe_v01_03.xml"/-->
   <!--preliminary vertex and tracker, to update/-->
-  <include ref="../CRD_common_v02/VXD_StaggeredLadder_v02_01.xml"/>
+  <!--include ref="../CRD_common_v02/VXD_StaggeredLadder_v02_01.xml"/>
   <include ref="../CRD_common_v02/FTD_SkewRing_v01_05.xml"/>
   <include ref="../CRD_common_v02/SIT_SimplePixel_v01_03.xml"/>
   <include ref="../CRD_common_v01/TPC_Simple_v10_02.xml"/>
diff --git a/Detector/DetCRD/scripts/TDR_o1_v01/tracking.py b/Detector/DetCRD/scripts/TDR_o1_v01/tracking.py
index 6c7a4e89577607fcdbd1771be3fe4fd12ebd80e1..1cc1894f7f1d0b33ad38a1123060b2c3902d2ee7 100644
--- a/Detector/DetCRD/scripts/TDR_o1_v01/tracking.py
+++ b/Detector/DetCRD/scripts/TDR_o1_v01/tracking.py
@@ -39,6 +39,11 @@ gearsvc = GearSvc("GearSvc")
 from Configurables import TrackSystemSvc
 tracksystemsvc = TrackSystemSvc("TrackSystemSvc")
 
+from Configurables import SimplePIDSvc
+pidsvc = SimplePIDSvc("SimplePIDSvc")
+cepcswdatatop = "/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest"
+pidsvc.ParFile = os.path.join(cepcswdatatop, "CEPCSWData/offline-data/Service/SimplePIDSvc/data/dNdx_TPC.root")
+
 from Configurables import PodioInput
 podioinput = PodioInput("PodioReader", collections=[
 #    "EventHeader",
@@ -207,12 +212,25 @@ full.SETHitToTrackDistance = 5.
 full.MinChi2ProbForSiliconTracks = 0
 #full.OutputLevel = DEBUG
 
+from Configurables import TPCDndxAlg
+tpc_dndx = TPCDndxAlg("TPCDndxAlg")
+tpc_dndx.Method = "Simple"
+
 from Configurables import TrackParticleRelationAlg
 tpr = TrackParticleRelationAlg("Track2Particle")
 tpr.MCParticleCollection = "MCParticle"
-tpr.TrackList = ["CompleteTracks"]
+tpr.TrackList = ["CompleteTracks", "ClupatraTracks"]
+tpr.TrackerAssociationList = ["VXDTrackerHitAssociation", "SITTrackerHitAssociation", "SETTrackerHitAssociation", "FTDTrackerHitAssociation", "TPCTrackerHitAss"]
 #tpr.OutputLevel = DEBUG
 
+from Configurables import TrueMuonTagAlg
+tmt = TrueMuonTagAlg("TrueMuonTag")
+tmt.MCParticleCollection = "MCParticle"
+tmt.TrackList = ["CompleteTracks"]
+tmt.MuonTagEfficiency = 0.95 # muon true tag efficiency, default is 1.0 (100%)
+tmt.MuonDetTanTheta = 1.2 # muon det barrel/endcap separation tan(theta)
+#tmt.OutputLevel = DEBUG
+
 # output
 from Configurables import PodioOutput
 out = PodioOutput("outputalg")
@@ -222,10 +240,10 @@ out.outputCommands = ["keep *"]
 # ApplicationMgr
 from Configurables import ApplicationMgr
 mgr = ApplicationMgr(
-    TopAlg = [podioinput, digiVXD, digiSIT, digiSET, digiFTD, digiTPC, tracking, forward, subset, clupatra, full, tpr, out],
+    TopAlg = [podioinput, digiVXD, digiSIT, digiSET, digiFTD, digiTPC, tracking, forward, subset, clupatra, full, tpr, tpc_dndx, tmt, out],
     EvtSel = 'NONE',
     EvtMax = 5,
-    ExtSvc = [rndmengine, rndmgensvc, dsvc, evtseeder, geosvc, gearsvc, tracksystemsvc],
+    ExtSvc = [rndmengine, rndmgensvc, dsvc, evtseeder, geosvc, gearsvc, tracksystemsvc, pidsvc],
     HistogramPersistency = 'ROOT',
     OutputLevel = ERROR
 )
diff --git a/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01.cpp b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..140f1f811be4081dfe2c6dd84a7c6aa7f7738cee
--- /dev/null
+++ b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01.cpp
@@ -0,0 +1,520 @@
+/*********************************************************************
+ * Author           : Lan-sx & origin author: F. Gaede, Desy
+ * Email            : shexin@ihep.ac.cn
+ * Last modified    : 2024-06-02 20:37
+ * Filename         : TPC_ModularEndcap_o1_v01.cpp
+ * Description      : 
+ * ******************************************************************/
+
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+//#include "./include/LcgeoExceptions.h"
+//#include "./include/lcgeo.h"
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "XML/Utilities.h"
+//#include "XMLHandlerDB.h"
+
+#include <math.h>
+
+using namespace std;
+using namespace dd4hep;
+//using namespace lcgeo;
+
+using dd4hep::rec::Vector3D;
+using dd4hep::rec::VolCylinder;
+using dd4hep::rec::SurfaceType;
+using dd4hep::rec::volSurfaceList;
+using dd4hep::rec::VolPlane;
+using dd4hep::rec::FixedPadSizeTPCData;
+
+/** Construction of TPC detector, ported from Mokka driver TPC10.cc
+ * Mokka History:
+ * - modified version of TPC driver by Ties Behnke
+ * - modified version of TPC02 as TPC03 with selectable chamber gas -- Adrian Vogel, 2005-06-09
+ * - modified version of TPC03 as TPC04 with limit of step length   -- Adrian Vogel, 2006-02-01
+ * - introduced self-scalability, no superdriver needed anymore     -- Adrian Vogel, 2006-03-11
+ * - modified version of TPC04 as TPC05 in order to have full MC
+ *   information both at entry and exit hits in the TPC ,
+ *   more realistic central electrode and endplate             -- Predrag Krstonosic, 2006-07-12
+ * - implemented new GEAR interface -- K. Harder, T. Pinto Jayawardena                2007-07-31
+ * - TPC10 implemented readout within the Gas volume and layered inner and outer wall -- SJA -- 2010-11-19
+ *
+ *  @author: F.Gaede, DESY, Nov 2013
+ *
+ * - Modular Endcap TPC Geo implemention for CEPC TDR TPC
+ *  @author: X.She, IHEP, May 2024
+ */
+
+static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens)  {
+
+
+    //------------------------------------------
+    //  See comments starting with '//**' for
+    //     hints on porting issues
+    //------------------------------------------
+    xml_det_t    x_det = e;
+    string       name  = x_det.nameStr();
+
+    DetElement   tpc(  name, x_det.id()  ) ;
+
+    // --- create an envelope volume and position it into the world ---------------------
+
+    Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  e , tpc ) ;
+
+    dd4hep::xml::setDetectorTypeFlag( e, tpc ) ;
+
+    if( theDetector.buildType() == BUILD_ENVELOPE ) return tpc ;
+
+    //-----------------------------------------------------------------------------------
+
+    PlacedVolume pv;  
+
+    sens.setType("tracker");
+
+    std::cout << " **Lan Lan building TPC_ModularEndcap_TDR_o1_v01 construction" << std::endl ;
+
+    //######################################################################################################################################################################
+    const double phi1 =   0.0 ;
+    const double phi2 =  2*M_PI ;
+    const double dzTotal            = theDetector.constant<double>("TPC_half_length") * 2. ; 
+    const double rInner             = theDetector.constant<double>("TPC_inner_radius") ;
+    const double rOuter             = theDetector.constant<double>("TPC_outer_radius") ;
+    const double drInnerWall        = theDetector.constant<double>("TPC_dr_InnerWall");
+    const double drOuterWall        = theDetector.constant<double>("TPC_dr_OuterWall");
+    const double dz_Cathode         = theDetector.constant<double>("TPC_dz_Cathode");
+    const double dz_Endplate        = theDetector.constant<double>("TPC_dz_Endplate");
+    const double dz_Readout         = theDetector.constant<double>("TPC_dz_Readout");
+    const double tpcpadheight       = theDetector.constant<double>("TPC_pad_height");
+    const double tpcpadwidth        = theDetector.constant<double>("TPC_pad_width");
+    const int    tpcnumberOfPadRows = theDetector.constant<int>("TPC_numberOfPadrows");
+
+
+    std::cout<< "============ TPC_HoneyComb_TDR_o1_v01 mother Volume(Tube) (Dz,Ri,Ro) : (" << dzTotal/dd4hep::mm/2. << "\t" 
+                                                                    << rInner/dd4hep::mm  << "\t"
+                                                                    << rOuter/dd4hep::mm  <<" )"<<std::endl;
+    Material materialT2Kgas  = theDetector.material("T2KGas1");
+    Material materialAir     = theDetector.material("Air");
+    Material materialAlframe = theDetector.material("TPC_Alframe");
+    //-------------------------------------------------------------------------------------------------------//
+    //-------------------------------- TPC mother volume ----------------------------------------------------//
+    //------------ Volume for the whole TPC, Field Cage, Cathode, and Endplate and Sensitive ----------------//
+
+    Tube tpc_motherSolid(rInner ,rOuter ,dzTotal/2.0 , phi1 , phi1+phi2 ); 
+    Volume tpc_motherLog(  "TPCLog", tpc_motherSolid, materialT2Kgas);
+    pv = envelope.placeVolume( tpc_motherLog ) ;
+    tpc.setVisAttributes(theDetector,  "TPCMotherVis1" ,  tpc_motherLog ) ;
+
+    double gasRegion = ((rOuter-drOuterWall)-(rInner+drInnerWall))/dd4hep::mm;
+    std::cout << "================================================================"<< std::endl; 
+    std::cout << "TPC_HoneyComb_TDR_o1_v01: Total Gas material corresponds to " << ( ( gasRegion ) / (materialT2Kgas->GetMaterial()->GetRadLen() / dd4hep::mm ) * 100.0 ) 
+              << "% of a radiation length." << std::endl;
+    std::cout << "================================================================"<< std::endl; 
+    
+    //-------------------------------------------------------------------------------------------------------//
+    //Loop all sections
+    //-------------------------------------------------------------------------------------------------------//
+
+    for(xml_coll_t si(x_det, Unicode("component"));si;++si)
+    {
+        xml_comp_t x_section(si);
+        std::string types = x_section.attr<std::string>(_Unicode(type));
+        const std::string volName = x_section.nameStr();
+
+        //-------------------------------- inner/outer wall construction ----------------------------------------//
+        if(types == "TPCinnerWall" || types == "TPCouterWall")
+        {
+            double r_start = x_section.attr<double>(_Unicode(R_start));
+            double r_end =  x_section.attr<double>(_Unicode(R_end));
+            double z_fulllength = x_section.attr<double>(_Unicode(Z_fulllength));
+
+            //Create Inner/Outer Wall mother logic volume
+            std::string volNameLog = volName + "Log";
+            Tube WallSolid(r_start,r_end,z_fulllength/2., phi1 , phi1+phi2);
+            Volume WallLog(volNameLog,WallSolid,materialT2Kgas);
+            pv=tpc_motherLog.placeVolume(WallLog);
+            tpc.setVisAttributes(theDetector,"CyanVis",WallLog);
+            
+            Vector3D ocyl;
+            //SurfaceList data, same as TPC10(CEPCV4)
+            double dr_wall = r_end-r_start;
+            if(types == "TPCinnerWall")
+                ocyl.fill(r_start+0.5*dr_wall,0.,0.);
+            else
+                ocyl.fill(r_end-0.5*dr_wall,0.,0.);
+
+            //std::cout<<"======>   Vector3D cout : "<<ocyl.x()<<"\t"<<ocyl.y()<<"\t"<<ocyl.z()<<std::endl;
+            VolCylinder surfWall(WallLog,SurfaceType( SurfaceType::Helper ),0.5*dr_wall,0.5*dr_wall,ocyl);
+            volSurfaceList( tpc )->push_back( surfWall );
+
+            //Loop all layers of inner/outer wall
+            int ilayer =0;
+            double rCursor = r_start;
+            double fracRadLengthWall = 0.;
+            for(xml_coll_t li(x_section,_U(layer)); li;++li,++ilayer)
+            {
+                xml_comp_t x_layer(li);
+
+                double thickness = x_layer.thickness();
+                Material layerMaterial = theDetector.material( x_layer.materialStr() );
+                char suffix[20];
+                sprintf(suffix,"_%d",ilayer);
+                std::string layerName = volNameLog + suffix;
+
+                Tube layerSolid(rCursor,rCursor+thickness,z_fulllength/2.,phi1,phi1+phi2);
+                Volume layerLog(layerName,layerSolid,layerMaterial);
+                //layerLog.setVisAttributes(theDetector,x_layer.visStr());
+                pv=WallLog.placeVolume(layerLog);
+
+                rCursor += thickness; 
+                double layerRadLength = thickness/(layerMaterial->GetMaterial()->GetRadLen());
+                fracRadLengthWall += layerRadLength; 
+
+                std::cout<<"-> "<<volName<<"layer"<<ilayer<<" : "<< thickness/dd4hep::mm << "mm \t Materials: "<<layerMaterial.name()
+                         <<" X0= "<<layerMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"mm \t"
+                         <<layerRadLength<<" X0"<<std::endl;
+            }
+            
+            double drSumThickness = rCursor - r_start;
+            if(drSumThickness > (r_end-r_start))
+            {
+                std::cout<<"Warning!  sum_{i}layerThickness_{i} > drWall !\n"<<std::endl;
+                throw "$!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Wall - check your xml file -component <TPCInnerWall/TPCOuterWall>";
+            }
+
+            std::cout << "================================================================"<< std::endl; 
+            std::cout<<"=====>$ "<<volName<<" material corresponds to "<< int(fracRadLengthWall*1000)/10. << "% of a radiation length."<<std::endl;
+            std::cout<<"=====>$ "<<volName<<" effective X0=  "<<std::setw(4)<< (r_end-r_start)/fracRadLengthWall <<" cm "<<std::endl; 
+            std::cout<<"=====>$ Sum of layer thickness = "<< drSumThickness/dd4hep::mm <<" mm "<<" \t Wall thickness = "<<(r_end-r_start)/dd4hep::mm <<" mm "<<std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+        //-------------------------------- TPCGrip construction ----------------------------------------//
+        if(types == "TPCGrip")
+        {
+            Material gripMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ;
+            for(xml_coll_t li(x_section,_U(layer));li;++li)
+            {
+                xml_comp_t x_layer(li);
+
+                //std::string volNameLog = x_layer.nameStr()+"Log"; 
+                Tube gripSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2., phi1 , phi1+phi2);
+                Volume gripLog(x_layer.nameStr()+"Log",gripSolid,gripMaterial);
+                pv=tpc_motherLog.placeVolume(gripLog);
+                tpc.setVisAttributes(theDetector,x_layer.visStr(),gripLog);
+                std::cout << "================================================================"<< std::endl; 
+                std::cout<<"=====>$ "<<x_layer.nameStr()<<" Constructed ! "<<std::endl;
+                std::cout << "================================================================"<< std::endl; 
+            }
+        }
+        //-------------------------------- TPCCathode construction ----------------------------------------//
+        if(types == "TPCCathode")
+        {
+            for(xml_coll_t li(x_section,_U(layer));li;++li)
+            {
+                xml_comp_t x_layer(li);
+                Material cathodeMaterial = theDetector.material( x_layer.materialStr());
+                
+                Tube cathodeSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2,phi1,phi1+phi2);
+                Volume cathodeLog(x_layer.nameStr()+"Log",cathodeSolid,cathodeMaterial);
+
+                for(xml_coll_t pj(x_layer,_U(position));pj;++pj)
+                {
+                    xml_dim_t x_pos(pj);
+                    pv = tpc_motherLog.placeVolume(cathodeLog,Position(x_pos.x(),x_pos.y(),x_pos.z()));
+                    tpc.setVisAttributes(theDetector, x_layer.visStr(),cathodeLog);
+                    std::cout<<"============>Cathod Z Position: "<<x_pos.z() / dd4hep::mm <<" mm "<<std::endl;
+                }
+            }
+        }
+        //-------------------------------- TPC Sensitive Volume construction ----------------------------------------//
+        if(types == "TPCSensitiveVol")
+        {
+            //Material T2KgasMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ;
+            std::cout<<"============>T2K gas RadLen= "<< materialT2Kgas->GetMaterial()->GetRadLen()/dd4hep::mm<<" mm"<<std::endl;
+
+            xml_dim_t dimSD = x_section.dimensions();
+            std::cout<<"============>rmin,rmax,dz "<< dimSD.rmin()<<"\t"<<dimSD.rmax()<<"\t"<<dimSD.z_length()<<std::endl; 
+
+            Tube sensitiveGasSolid(dimSD.rmin(),dimSD.rmax(),dimSD.z_length()/2.,phi1,phi1+phi2);
+            Volume sensitiveGasLog(volName+"Log",sensitiveGasSolid,materialT2Kgas);
+
+            DetElement sensGasDEfwd(tpc, "tpc_senGas_fwd",x_det.id());
+            DetElement sensGasDEbwd(tpc, "tpc_senGas_bwd",x_det.id());
+
+            pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(0.),Position(0,0,+(dz_Cathode/2+dimSD.z_length()/2.))));
+            pv.addPhysVolID("side",+1);
+            sensGasDEfwd.setPlacement(pv);
+
+            pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(pi),Position(0,0,-(dz_Cathode/2+dimSD.z_length()/2.))));
+            pv.addPhysVolID("side",-1);
+            sensGasDEbwd.setPlacement(pv);
+
+            tpc.setVisAttributes(theDetector, "gasVis", sensitiveGasLog);
+            
+            //Pad row doublets construction
+            xml_coll_t cc(x_section,_U(layer));
+            xml_comp_t x_layer = cc;
+            int numberPadRows = x_layer.repeat();
+            double padHeight  = x_layer.thickness();
+            std::cout<<"##################$$$$$$$$$$$$$$ Number of Pad Rows: > "<<numberPadRows<<"\t padHeight= "<<padHeight/dd4hep::mm<<" mm"<<std::endl;
+            
+            //Sensitive Volume construction  : readout pad layers
+            for(int ilayer=0; ilayer < numberPadRows; ++ilayer)
+            {
+                // create twice the number of rings as there are pads, producing an lower and upper part of the pad with the boundry between them the pad-ring centre
+                const double inner_lowerlayer_radius = dimSD.rmin()+ (ilayer * (padHeight));
+                const double outer_lowerlayer_radius = inner_lowerlayer_radius + (padHeight/2.0);
+
+                const double inner_upperlayer_radius = outer_lowerlayer_radius ;
+                const double outer_upperlayer_radius = inner_upperlayer_radius + (padHeight/2.0);
+
+                Tube lowerlayerSolid( inner_lowerlayer_radius, outer_lowerlayer_radius, dimSD.z_length() / 2.0, phi1, phi2);
+                Tube upperlayerSolid( inner_upperlayer_radius, outer_upperlayer_radius, dimSD.z_length() / 2.0, phi1, phi2);
+
+                Volume lowerlayerLog( _toString( ilayer ,"TPC_lowerlayer_log_%02d") ,lowerlayerSolid, materialT2Kgas );
+                Volume upperlayerLog( _toString( ilayer ,"TPC_upperlayer_log_%02d") ,upperlayerSolid, materialT2Kgas );
+
+                tpc.setVisAttributes(theDetector,  "Invisible" ,  lowerlayerLog) ;
+                tpc.setVisAttributes(theDetector,  "Invisible" ,  upperlayerLog) ;
+                //tpc.setVisAttributes(theDetector,  "RedVis" ,  lowerlayerLog) ;
+                //tpc.setVisAttributes(theDetector,  "RedVis" ,  upperlayerLog) ;
+
+                DetElement   layerDEfwd( sensGasDEfwd ,   _toString( ilayer, "tpc_row_fwd_%03d") , x_det.id() );
+                DetElement   layerDEbwd( sensGasDEbwd ,   _toString( ilayer, "tpc_row_bwd_%03d") , x_det.id() );
+
+                Vector3D o(  inner_upperlayer_radius + 1e-10  , 0. , 0. ) ;
+                // create an unbounded surface (i.e. an infinite cylinder) and assign it to the forward gaseous volume only
+                VolCylinder surf( upperlayerLog , SurfaceType(SurfaceType::Sensitive, SurfaceType::Invisible, SurfaceType::Unbounded ) ,  (padHeight/2.0) ,  (padHeight/2.0) ,o ) ;
+
+                volSurfaceList( layerDEfwd )->push_back( surf ) ;
+                // volSurfaceList( layerDEbwd )->push_back( surf ) ;
+
+                pv = sensitiveGasLog.placeVolume( lowerlayerLog ) ;
+                pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 1 ) ;
+
+                pv = sensitiveGasLog.placeVolume( upperlayerLog ) ;
+                pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 0 ) ;
+                layerDEfwd.setPlacement( pv ) ;
+                layerDEbwd.setPlacement( pv ) ;
+
+                lowerlayerLog.setSensitiveDetector(sens);
+                upperlayerLog.setSensitiveDetector(sens);
+            }
+
+        }
+        //-------------------------------- TPC Endplate and readout construction ----------------------------------------//
+        if(types == "TPCEndplate")
+        {
+            xml_dim_t dimEndCap = x_section.dimensions();
+            std::cout<<"============>(rmin,rmax,dz): "<< dimEndCap.rmin() / dd4hep::mm<<"mm "
+                                                      << dimEndCap.rmax() / dd4hep::mm<<" mm "
+                                                      << dimEndCap.z_length() / dd4hep::mm<< " mm" <<std::endl; 
+            //Create endcap Log volume
+            Tube endcapSolid(dimEndCap.rmin(),dimEndCap.rmax(),dimEndCap.z_length()/2.,phi1,phi1+phi2);
+            Volume endcapLog(volName+"Log",endcapSolid,materialAir);
+
+            DetElement endcapDEfwd(tpc, "tpc_endcap_fwd",x_det.id());
+            DetElement endcapDEbwd(tpc, "tpc_endcap_bwd",x_det.id());
+
+            //Vectors for endplate plane
+            Vector3D u(0.,1.,0.);
+            Vector3D v(1.,0.,0.);
+            Vector3D n(0.,0.,1.);
+
+            ////need to set the origin of the helper plane to be inside the material (otherwise it would pick up the vacuum at the origin)
+            double mid_r = 0.5*(rOuter + rInner);
+            Vector3D o(0., mid_r, 0.);
+
+            VolPlane surf( endcapLog, SurfaceType( SurfaceType::Helper ), (dz_Endplate+dz_Readout)/2.,dz_Endplate/2.,u,v,n,o);
+            volSurfaceList(endcapDEfwd) -> push_back(surf);
+            volSurfaceList(endcapDEbwd) -> push_back(surf);
+            
+            pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(0.),Position(0,0,+(dzTotal/2.-dz_Endplate/2.))));
+            endcapDEfwd.setPlacement(pv);
+
+            pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(pi),Position(0,0,-(dzTotal/2.-dz_Endplate/2.))));
+            endcapDEbwd.setPlacement(pv);
+            
+            tpc.setVisAttributes(theDetector, "transVis", endcapLog);
+
+            //================================================================================================
+            //Modular Endplate construction
+            //================================================================================================
+            double dz_Endpaltelength     = dimEndCap.z_length();
+            double r_start        = dimEndCap.rmin();  
+            double ds_reinforce   = x_section.attr<double>(_Unicode(s_frame));
+            double dz_Alframe     = x_section.attr<double>(_Unicode(z_frame));
+            double rCursor        = r_start;
+
+            //Loop all layers to construct frame-module
+            for(xml_coll_t ilayer(x_section,_U(layer)); ilayer; ++ilayer)
+            {
+                xml_comp_t x_layer(ilayer);
+
+                const std::string layerName = x_layer.nameStr();
+                const std::string layerType = x_layer.attr<std::string>(_Unicode(type));
+                double layerThickness       = x_layer.thickness();
+
+                double r_end = rCursor + layerThickness;
+                std::cout<<"===============>$ "<<layerName<<"\t"<<layerType
+                    <<" thickness = "<<layerThickness / dd4hep::mm << "mm "
+                    <<" inner radius = "<<rCursor / dd4hep::mm<<" mm"
+                    <<" outer radius = "<<r_end /dd4hep::mm<<" mm"
+                    <<std::endl;
+
+                //--------------------------------------
+                if(layerType == "Frame")
+                {
+                    double phi_start = 0.;
+                    double phi_end   = 2*M_PI;
+                    Tube   ringSolid(rCursor, r_end, dz_Alframe/2., phi_start,  phi_end) ;
+                    Volume ringLog( layerName+"Log", ringSolid, materialAlframe) ;
+                    pv = endcapLog.placeVolume( ringLog, Position(0., 0., -dz_Endpaltelength/2. + dz_Alframe) ) ;
+                    tpc.setVisAttributes(theDetector,"GrayVis",ringLog);
+                }
+                if(layerType == "Module")
+                {
+                    int numberofModules = x_layer.repeat(); 
+                    double phi_start    = x_layer.phi0_offset();
+                    double phiCursor    = phi_start;
+                    double phiModule    = (2*M_PI*rCursor-numberofModules*ds_reinforce)/numberofModules/rCursor;
+                    double phiReinforce = ds_reinforce/rCursor;
+
+                    //Construct each module 
+                    for(int k=0; k<numberofModules;++k)
+                    {
+                        Tube moduleSolid1(rCursor,r_end,dz_Endpaltelength/2.,phiCursor,phiCursor+phiModule);
+                        std::string moduleLogName1 = layerName + _toString(k,"Log%00d");
+                        Volume moduleLog1(moduleLogName1,moduleSolid1,materialAir);
+
+                        double z_cursor = -dz_Endpaltelength/2.; 
+                        int    m_sli = 0;
+                        for(xml_coll_t sli(x_layer,_U(slice)); sli; ++sli,++m_sli)
+                        {
+                            xml_comp_t x_slice = sli; 
+                            double dz_modulepiece = sli.attr<double>(_Unicode(dz));
+                            std::string moduleSliceName = moduleLogName1 + _toString(m_sli,"slice%d");
+                            Material slice_mat = theDetector.material(x_slice.materialStr());
+
+                            Tube moduleSliceSolid(rCursor,r_end,dz_modulepiece/2.,phiCursor,phiCursor+phiModule);
+                            Volume moduleSliceLog(moduleSliceName,moduleSliceSolid,slice_mat);
+
+                            pv = moduleLog1.placeVolume(moduleSliceLog,Position(0.,0.,z_cursor+dz_modulepiece/2.));
+                            tpc.setVisAttributes(theDetector,  "Invisible" ,  moduleSliceLog) ;
+                            z_cursor += dz_modulepiece;
+
+                            if(z_cursor > dz_Endpaltelength/2.)
+                            {
+                                //std::cout<<" Warning ! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - section <Endpalte>." <<std::endl;
+                                throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - component <Endpalte>.";
+                            }
+                        }
+
+                        pv = endcapLog.placeVolume(moduleLog1);
+                        tpc.setVisAttributes(theDetector,"RedVis",moduleLog1);
+
+                        phiCursor = phiCursor+phiModule;
+
+                        //Construct the Al frame between each module 
+                        Tube moduleSolid2(rCursor,r_end,dz_Alframe/2.,phiCursor,phiCursor+phiReinforce);
+                        std::string moduleLogName2 = layerName + _toString(k,"Log_rein%00d");
+                        Volume moduleLog2(moduleLogName2,moduleSolid2,materialAlframe);
+                        pv = endcapLog.placeVolume(moduleLog2, Position(0., 0., -dz_Endpaltelength/2.+dz_Alframe/2.));
+                        tpc.setVisAttributes(theDetector,"GrayVis",moduleLog2);
+
+                        phiCursor = phiCursor+phiReinforce;
+                    }
+                }
+                rCursor = r_end;
+            }
+
+            double RadlenOfAl_Frame = materialAlframe->GetMaterial()->GetRadLen();
+            std::cout << "================================================================"<< std::endl; 
+            std::cout << "TPC_ModularEndcap_TDR_o1_v01: Endplate Al frame corresponds to " << (2. / RadlenOfAl_Frame*100)<< "% of a radiation length." << std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+        //-------------------------------- TPCreadout construction ----------------------------------------//
+        if(types == "TPCreadout")
+        {
+            xml_dim_t dimReadout = x_section.dimensions();
+            double dzReadout = dimReadout.z_length();
+            Tube readoutSolid(dimReadout.rmin(),dimReadout.rmax(),dimReadout.z_length()/2.,phi1,phi1+phi2);
+            Volume readoutLog(volName+"Log",readoutSolid, materialT2Kgas);
+
+            tpc.setVisAttributes(theDetector,"CyanVis",readoutLog);
+
+            xml_dim_t posReadout = x_section.position();
+            pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(0.),Position(0,0,posReadout.z())));  
+            pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(pi),Position(0,0,-posReadout.z())));  
+
+            std::cout<<"=========ReadOut dim: "<< dimReadout.rmin() / dd4hep::mm<<" mm "
+                                               << dimReadout.rmax() / dd4hep::mm<<" mm "
+                                               << dzReadout / dd4hep::mm <<" mm "<<std::endl;
+            std::cout<<"=========ReadOut Z_pos: "<<posReadout.z() / dd4hep::mm << " mm "<<std::endl;
+
+            int pieceCounter = 0;
+            double fracRadLengthReadout = 0;
+            double zCursor = -dzReadout/ 2;
+
+            for(xml_coll_t li(x_section,_U(layer)); li;++li)
+            {
+                xml_comp_t  x_layer( li );
+            
+                const double dzPiece = x_layer.attr<double>(_Unicode(dz)); 
+                Material pieceMaterial = theDetector.material( x_layer.materialStr() );
+                Tube pieceSolid( dimReadout.rmin(),dimReadout.rmax(), dzPiece / 2, phi1, phi2);
+                Volume pieceLog (  _toString( pieceCounter ,"TPCReadoutPieceLog_%02d"), pieceSolid, pieceMaterial ) ;
+
+                pieceLog.setVisAttributes(theDetector,x_layer.visStr());
+
+                pv = readoutLog.placeVolume( pieceLog  , Position(0, 0,  zCursor + dzPiece/2. ) ) ;
+
+                ++pieceCounter;
+                fracRadLengthReadout += dzPiece / pieceMaterial->GetMaterial()->GetRadLen();
+                zCursor += dzPiece;
+                
+                std::cout<<"==========> "<<dzPiece/dd4hep::mm<<" mm Material= "<<x_layer.materialStr()<<"\t"
+                         <<"X0= "<<pieceMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"\t"
+                         <<dzPiece / pieceMaterial->GetMaterial()->GetRadLen()  <<" X0"<< std::endl;
+
+                if (zCursor > +dzReadout / 2) 
+                {
+                    //throw GeometryException(  "TPC11: Overfull TPC readout - check your xml file - section <readout>."   ) ;
+                    //std::cout<<" TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>." <<std::endl;
+                    throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>.";
+                }
+            }
+            std::cout << "================================================================"<< std::endl; 
+            std::cout << "TPC_ModularEndcap_TDR_o1_v01: Readout material corresponds to " << int(fracRadLengthReadout * 1000) / 10.0 << "% of a radiation length." << std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+
+    }
+    
+    //TPC data
+    FixedPadSizeTPCData* tpcData = new FixedPadSizeTPCData();
+    tpcData->zHalf = dzTotal/2.;
+    tpcData->rMin  = rInner;
+    tpcData->rMax  = rOuter;
+    tpcData->innerWallThickness = drInnerWall;
+    tpcData->outerWallThickness = drOuterWall;
+    tpcData->rMinReadout = rInner + drInnerWall;
+    tpcData->rMaxReadout = rInner + drInnerWall + tpcnumberOfPadRows*tpcpadheight;
+    tpcData->maxRow = tpcnumberOfPadRows;
+    tpcData->padHeight = tpcpadheight;
+    tpcData->padWidth =  tpcpadwidth;
+    tpcData->driftLength = dzTotal/2.- dz_Endplate - dz_Readout - dz_Cathode/2.0; // SJA: cathode has to be added as the sensitive region does not start at 0.00    
+    tpcData->zMinReadout = dz_Cathode/2.0; 
+
+    //tpc.setVisAttributes( theDetector, x_det.visStr(), envelope );
+    tpc.setVisAttributes( theDetector, "TPCMotherVis1", envelope );
+    //  if( tpc.isValid() ) 
+    // tpc.setPlacement(pv);
+    std::cout << "================================================================"<< std::endl; 
+    std::cout << "TPC_ModularEndcap_TDR_o1_v01 Constructed!"<< std::endl; 
+    std::cout << "================================================================"<< std::endl; 
+
+    return tpc;
+}
+DECLARE_DETELEMENT(TPC_ModularEndcap_o1_v01,create_element)
diff --git a/Detector/DetCRD/src/Tracker/TPC_Simple_o1_v01.cpp b/Detector/DetCRD/src/Tracker/TPC_Simple_o1_v01.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ce7ec73a64af36138604f83fd7f30cc0a74803c
--- /dev/null
+++ b/Detector/DetCRD/src/Tracker/TPC_Simple_o1_v01.cpp
@@ -0,0 +1,464 @@
+/*********************************************************************
+ * Author           : Lan-sx & origin author: F. Gaede, Desy
+ * Email            : shexin@ihep.ac.cn
+ * Last modified    : 2024-06-02 20:40
+ * Filename         : TPC_Simple_o1_v01.cpp
+ * Description      : 
+ * ******************************************************************/
+
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/DetType.h"
+//#include "./include/LcgeoExceptions.h"
+//#include "./include/lcgeo.h"
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "XML/Utilities.h"
+//#include "XMLHandlerDB.h"
+
+#include <math.h>
+
+using namespace std;
+using namespace dd4hep;
+//using namespace lcgeo;
+
+using dd4hep::rec::Vector3D;
+using dd4hep::rec::VolCylinder;
+using dd4hep::rec::SurfaceType;
+using dd4hep::rec::volSurfaceList;
+using dd4hep::rec::VolPlane;
+using dd4hep::rec::FixedPadSizeTPCData;
+
+/** Construction of TPC detector, ported from Mokka driver TPC10.cc
+ * Mokka History:
+ * - modified version of TPC driver by Ties Behnke
+ * - modified version of TPC02 as TPC03 with selectable chamber gas -- Adrian Vogel, 2005-06-09
+ * - modified version of TPC03 as TPC04 with limit of step length   -- Adrian Vogel, 2006-02-01
+ * - introduced self-scalability, no superdriver needed anymore     -- Adrian Vogel, 2006-03-11
+ * - modified version of TPC04 as TPC05 in order to have full MC
+ *   information both at entry and exit hits in the TPC ,
+ *   more realistic central electrode and endplate             -- Predrag Krstonosic, 2006-07-12
+ * - implemented new GEAR interface -- K. Harder, T. Pinto Jayawardena                2007-07-31
+ * - TPC10 implemented readout within the Gas volume and layered inner and outer wall -- SJA -- 2010-11-19
+ *
+ *  @author: F.Gaede, DESY, Nov 2013
+ *
+ * - Simple TPC Geo implemention for CEPC TDR TPC
+ *  @author: X.She, IHEP, May 2024
+ */
+
+static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens)  {
+
+    //------------------------------------------
+    //  See comments starting with '//**' for
+    //     hints on porting issues
+    //------------------------------------------
+    xml_det_t    x_det = e;
+    string       name  = x_det.nameStr();
+
+    DetElement   tpc(  name, x_det.id()  ) ;
+
+    // --- create an envelope volume and position it into the world ---------------------
+
+    Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  e , tpc ) ;
+
+    dd4hep::xml::setDetectorTypeFlag( e, tpc ) ;
+
+    if( theDetector.buildType() == BUILD_ENVELOPE ) return tpc ;
+
+    //-----------------------------------------------------------------------------------
+
+    PlacedVolume pv;  
+
+    sens.setType("tracker");
+
+    std::cout << " **Lan Lan building TPC_Simple_TDR_o1_v01 construction" << std::endl ;
+
+    //######################################################################################################################################################################
+    
+    const double phi1 =   0.0 ;
+    const double phi2 =  2*M_PI ;
+    const double dzTotal            = theDetector.constant<double>("TPC_half_length") * 2. ; 
+    const double rInner             = theDetector.constant<double>("TPC_inner_radius") ;
+    const double rOuter             = theDetector.constant<double>("TPC_outer_radius") ;
+    const double drInnerWall        = theDetector.constant<double>("TPC_dr_InnerWall");
+    const double drOuterWall        = theDetector.constant<double>("TPC_dr_OuterWall");
+    const double dz_Cathode         = theDetector.constant<double>("TPC_dz_Cathode");
+    const double dz_Endplate        = theDetector.constant<double>("TPC_dz_Endplate");
+    const double dz_Readout         = theDetector.constant<double>("TPC_dz_Readout");
+    const double tpcpadheight       = theDetector.constant<double>("TPC_pad_height");
+    const double tpcpadwidth        = theDetector.constant<double>("TPC_pad_width");
+    const int    tpcnumberOfPadRows = theDetector.constant<int>("TPC_numberOfPadrows");
+
+
+    std::cout<< "============ TPC_Simple_TDR_o1_v01 mother Volume(Tube) (Dz,Ri,Ro) : (" << dzTotal/dd4hep::mm/2. << "\t" 
+                                                                    << rInner/dd4hep::mm  << "\t"
+                                                                    << rOuter/dd4hep::mm  <<" )"<<std::endl;
+    Material materialT2Kgas = theDetector.material("T2KGas1");
+    Material materialAir    = theDetector.material("Air");
+    //-------------------------------------------------------------------------------------------------------//
+    //-------------------------------- TPC mother volume ----------------------------------------------------//
+    //------------ Volume for the whole TPC, Field Cage, Cathode, and Endplate and Sensitive ----------------//
+
+    Tube tpc_motherSolid(rInner ,rOuter ,dzTotal/2.0 , phi1 , phi1+phi2 ); 
+    Volume tpc_motherLog(  "TPCLog", tpc_motherSolid, materialT2Kgas);
+    pv = envelope.placeVolume( tpc_motherLog ) ;
+    tpc.setVisAttributes(theDetector,  "TPCMotherVis1" ,  tpc_motherLog ) ;
+
+    double gasRegion = ((rOuter-drOuterWall)-(rInner+drInnerWall))/dd4hep::mm;
+    std::cout << "================================================================"<< std::endl; 
+    std::cout << "TPC_Simple_TDR_o1_v01: Total Gas material corresponds to " << ( ( gasRegion ) / (materialT2Kgas->GetMaterial()->GetRadLen() / dd4hep::mm ) * 100.0 ) 
+              << "% of a radiation length." << std::endl;
+    std::cout << "================================================================"<< std::endl; 
+    
+    //-------------------------------------------------------------------------------------------------------//
+    //Loop all TPC components
+    //-------------------------------------------------------------------------------------------------------//
+
+    for(xml_coll_t si(x_det, Unicode("component"));si;++si)
+    {
+        xml_comp_t x_section(si);
+        std::string types = x_section.attr<std::string>(_Unicode(type));
+        const std::string volName = x_section.nameStr();
+
+        //-------------------------------- inner/outer wall construction ----------------------------------------//
+        if(types == "TPCinnerWall" || types == "TPCouterWall")
+        {
+            double r_start = x_section.attr<double>(_Unicode(R_start));
+            double r_end =  x_section.attr<double>(_Unicode(R_end));
+            double z_fulllength = x_section.attr<double>(_Unicode(Z_fulllength));
+
+            //Create Inner/Outer Wall mother logic volume
+            std::string volNameLog = volName + "Log";
+            Tube WallSolid(r_start,r_end,z_fulllength/2., phi1 , phi1+phi2);
+            Volume WallLog(volNameLog,WallSolid,materialT2Kgas);
+            pv=tpc_motherLog.placeVolume(WallLog);
+            tpc.setVisAttributes(theDetector,"CyanVis",WallLog);
+            
+            Vector3D ocyl;
+            //SurfaceList data, keep the CEPCV4 
+            double dr_wall = r_end-r_start;
+            if(types == "TPCinnerWall")
+                ocyl.fill(r_start+0.5*dr_wall,0.,0.);
+            else
+                ocyl.fill(r_end-0.5*dr_wall,0.,0.);
+
+            //std::cout<<"======>   Vector3D cout : "<<ocyl.x()<<"\t"<<ocyl.y()<<"\t"<<ocyl.z()<<std::endl;
+            VolCylinder surfWall(WallLog,SurfaceType( SurfaceType::Helper ),0.5*dr_wall,0.5*dr_wall,ocyl);
+            volSurfaceList( tpc )->push_back( surfWall );
+
+            //Loop all layers of TPC inner/outer wall
+            int ilayer =0;
+            double rCursor = r_start;
+            double fracRadLengthWall = 0.;
+            for(xml_coll_t li(x_section,_U(layer)); li;++li,++ilayer)
+            {
+                xml_comp_t x_layer(li);
+
+                double thickness = x_layer.thickness();
+                Material layerMaterial = theDetector.material( x_layer.materialStr() );
+                char suffix[20];
+                sprintf(suffix,"_%d",ilayer);
+                std::string layerName = volNameLog + suffix;
+
+                Tube layerSolid(rCursor,rCursor+thickness,z_fulllength/2.,phi1,phi1+phi2);
+                Volume layerLog(layerName,layerSolid,layerMaterial);
+                //layerLog.setVisAttributes(theDetector,x_layer.visStr());
+                pv=WallLog.placeVolume(layerLog);
+
+                rCursor += thickness; 
+                double layerRadLength = thickness/(layerMaterial->GetMaterial()->GetRadLen());
+                fracRadLengthWall += layerRadLength; 
+
+                std::cout<<"-> "<<volName<<"layer"<<ilayer<<" : "<< thickness/dd4hep::mm << "mm \t Materials: "<<layerMaterial.name()
+                         <<" X0= "<<layerMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"mm \t"
+                         <<layerRadLength<<" X0"<<std::endl;
+            }
+            
+            double drSumThickness = rCursor - r_start;
+            if(drSumThickness > (r_end-r_start))
+            {
+                std::cout<<"Warning!  sum_{i}layerThickness_{i} > drWall !\n"<<std::endl;
+                throw "$!!! TPC_Simple_TDR_o1_v01: Overfull TPC Wall - check your xml file -component <TPCInnerWall/TPCOuterWall>";
+            }
+
+            std::cout << "================================================================"<< std::endl; 
+            std::cout<<"=====>$ "<<volName<<" material corresponds to "<< int(fracRadLengthWall*1000)/10. << "% of a radiation length."<<std::endl;
+            std::cout<<"=====>$ "<<volName<<" effective X0=  "<<std::setw(4)<< (r_end-r_start)/fracRadLengthWall <<" cm "<<std::endl; 
+            std::cout<<"=====>$ Sum of layer thickness = "<< drSumThickness/dd4hep::mm <<" mm "<<" \t Wall thickness = "<<(r_end-r_start)/dd4hep::mm <<" mm "<<std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+        //-------------------------------- TPCGrip construction ----------------------------------------//
+        if(types == "TPCGrip")
+        {
+            Material gripMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ;
+            for(xml_coll_t li(x_section,_U(layer));li;++li)
+            {
+                xml_comp_t x_layer(li);
+
+                //std::string volNameLog = x_layer.nameStr()+"Log"; 
+                Tube gripSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2., phi1 , phi1+phi2);
+                Volume gripLog(x_layer.nameStr()+"Log",gripSolid,gripMaterial);
+                pv=tpc_motherLog.placeVolume(gripLog);
+
+                tpc.setVisAttributes(theDetector,x_layer.visStr(),gripLog);
+                std::cout << "================================================================"<< std::endl; 
+                std::cout << "=====>$ "<<x_layer.nameStr()<<" Constructed ! "<<std::endl;
+                std::cout << "================================================================"<< std::endl; 
+            }
+        }
+        //-------------------------------- TPCCathode construction ----------------------------------------//
+        if(types == "TPCCathode")
+        {
+            for(xml_coll_t li(x_section,_U(layer));li;++li)
+            {
+                xml_comp_t x_layer(li);
+                Material cathodeMaterial = theDetector.material( x_layer.materialStr());
+                
+                Tube cathodeSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2,phi1,phi1+phi2);
+                Volume cathodeLog(x_layer.nameStr()+"Log",cathodeSolid,cathodeMaterial);
+
+                for(xml_coll_t pj(x_layer,_U(position));pj;++pj)
+                {
+                    xml_dim_t x_pos(pj);
+                    pv = tpc_motherLog.placeVolume(cathodeLog,Position(x_pos.x(),x_pos.y(),x_pos.z()));
+                    tpc.setVisAttributes(theDetector, x_layer.visStr(),cathodeLog);
+                    std::cout<<"============>Cathod Z Position: "<<x_pos.z() / dd4hep::mm <<" mm "<<std::endl;
+                }
+            }
+        }
+        //-------------------------------- TPC Sensitive Volume construction ----------------------------------------//
+        if(types == "TPCSensitiveVol")
+        {
+            //Material T2KgasMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ;
+            std::cout<<"============>T2K gas RadLen= "<< materialT2Kgas->GetMaterial()->GetRadLen()/dd4hep::mm<<" mm"<<std::endl;
+
+            xml_dim_t dimSD = x_section.dimensions();
+            std::cout<<"============>rmin,rmax,dz "<< dimSD.rmin()<<"\t"<<dimSD.rmax()<<"\t"<<dimSD.z_length()<<std::endl; 
+
+            Tube sensitiveGasSolid(dimSD.rmin(),dimSD.rmax(),dimSD.z_length()/2.,phi1,phi1+phi2);
+            Volume sensitiveGasLog(volName+"Log",sensitiveGasSolid,materialT2Kgas);
+
+            DetElement sensGasDEfwd(tpc, "tpc_senGas_fwd",x_det.id());
+            DetElement sensGasDEbwd(tpc, "tpc_senGas_bwd",x_det.id());
+
+            pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(0.),Position(0,0,+(dz_Cathode/2+dimSD.z_length()/2.))));
+            pv.addPhysVolID("side",+1);
+            sensGasDEfwd.setPlacement(pv);
+
+            pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(pi),Position(0,0,-(dz_Cathode/2+dimSD.z_length()/2.))));
+            pv.addPhysVolID("side",-1);
+            sensGasDEbwd.setPlacement(pv);
+
+            tpc.setVisAttributes(theDetector, "gasVis", sensitiveGasLog);
+            
+            //Pad row doublets construction
+            xml_coll_t cc(x_section,_U(layer));
+            xml_comp_t x_layer = cc;
+            int numberPadRows = x_layer.repeat();
+            double padHeight  = x_layer.thickness();
+            std::cout<<"##################$$$$$$$$$$$$$$ Number of Pad Rows: > "<<numberPadRows<<"\t padHeight= "<<padHeight/dd4hep::mm<<" mm"<<std::endl;
+            
+            //Sensitive Volume construction  : readout pad layers
+            for(int ilayer=0; ilayer < numberPadRows; ++ilayer)
+            {
+                // create twice the number of rings as there are pads, producing an lower and upper part of the pad with the boundry between them the pad-ring centre
+                const double inner_lowerlayer_radius = dimSD.rmin()+ (ilayer * (padHeight));
+                const double outer_lowerlayer_radius = inner_lowerlayer_radius + (padHeight/2.0);
+
+                const double inner_upperlayer_radius = outer_lowerlayer_radius ;
+                const double outer_upperlayer_radius = inner_upperlayer_radius + (padHeight/2.0);
+
+                Tube lowerlayerSolid( inner_lowerlayer_radius, outer_lowerlayer_radius, dimSD.z_length() / 2.0, phi1, phi2);
+                Tube upperlayerSolid( inner_upperlayer_radius, outer_upperlayer_radius, dimSD.z_length() / 2.0, phi1, phi2);
+
+                Volume lowerlayerLog( _toString( ilayer ,"TPC_lowerlayer_log_%02d") ,lowerlayerSolid, materialT2Kgas );
+                Volume upperlayerLog( _toString( ilayer ,"TPC_upperlayer_log_%02d") ,upperlayerSolid, materialT2Kgas );
+
+                tpc.setVisAttributes(theDetector,  "Invisible" ,  lowerlayerLog) ;
+                tpc.setVisAttributes(theDetector,  "Invisible" ,  upperlayerLog) ;
+                //tpc.setVisAttributes(theDetector,  "RedVis" ,  lowerlayerLog) ;
+                //tpc.setVisAttributes(theDetector,  "RedVis" ,  upperlayerLog) ;
+
+
+                DetElement   layerDEfwd( sensGasDEfwd ,   _toString( ilayer, "tpc_row_fwd_%03d") , x_det.id() );
+                DetElement   layerDEbwd( sensGasDEbwd ,   _toString( ilayer, "tpc_row_bwd_%03d") , x_det.id() );
+
+                Vector3D o(  inner_upperlayer_radius + 1e-10  , 0. , 0. ) ;
+                // create an unbounded surface (i.e. an infinite cylinder) and assign it to the forward gaseous volume only
+                VolCylinder surf( upperlayerLog , SurfaceType(SurfaceType::Sensitive, SurfaceType::Invisible, SurfaceType::Unbounded ) ,  (padHeight/2.0) ,  (padHeight/2.0) ,o ) ;
+
+                volSurfaceList( layerDEfwd )->push_back( surf ) ;
+                // volSurfaceList( layerDEbwd )->push_back( surf ) ;
+
+                pv = sensitiveGasLog.placeVolume( lowerlayerLog ) ;
+                pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 1 ) ;
+
+                pv = sensitiveGasLog.placeVolume( upperlayerLog ) ;
+                pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 0 ) ;
+                layerDEfwd.setPlacement( pv ) ;
+                layerDEbwd.setPlacement( pv ) ;
+
+                lowerlayerLog.setSensitiveDetector(sens);
+                upperlayerLog.setSensitiveDetector(sens);
+            }
+
+        }
+        //-------------------------------- TPC Endplate construction ----------------------------------------//
+        if(types == "TPCEndplate")
+        {
+            //Material endplateMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ;
+            //std::cout<<"============>Endplate Log material RadLen= "<< endplateMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<" mm "<<std::endl;
+
+            xml_dim_t dimEndCap = x_section.dimensions();
+            std::cout<<"============>(rmin,rmax,dz): "<< dimEndCap.rmin() / dd4hep::mm<<"mm "
+                                                      << dimEndCap.rmax() / dd4hep::mm<<" mm "
+                                                      << dimEndCap.z_length() / dd4hep::mm<< " mm" <<std::endl; 
+
+            Tube endcapSolid(dimEndCap.rmin(),dimEndCap.rmax(),dimEndCap.z_length()/2.,phi1,phi1+phi2);
+            Volume endcapLog(volName+"Log",endcapSolid,materialAir);
+
+            DetElement endcapDEfwd(tpc, "tpc_endcap_fwd",x_det.id());
+            DetElement endcapDEbwd(tpc, "tpc_endcap_bwd",x_det.id());
+
+            //Vectors for endplate plane
+            Vector3D u(0.,1.,0.);
+            Vector3D v(1.,0.,0.);
+            Vector3D n(0.,0.,1.);
+
+            //need to set the origin of the helper plane to be inside the material (otherwise it would pick up the vacuum at the origin)
+            double mid_r = 0.5*(rOuter + rInner);
+            Vector3D o(0., mid_r, 0.);
+
+            VolPlane surf( endcapLog, SurfaceType( SurfaceType::Helper ), (dz_Endplate+dz_Readout)/2.,dz_Endplate/2.,u,v,n,o);
+            volSurfaceList(endcapDEfwd) -> push_back(surf);
+            volSurfaceList(endcapDEbwd) -> push_back(surf);
+            
+            pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(0.),Position(0,0,+(dzTotal/2.-dz_Endplate/2.))));
+            endcapDEfwd.setPlacement(pv);
+
+            pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(pi),Position(0,0,-(dzTotal/2.-dz_Endplate/2.))));
+            endcapDEbwd.setPlacement(pv);
+
+            tpc.setVisAttributes(theDetector, "readoutVis", endcapLog);
+
+            int pieceCounter = 0;
+            double fracRadLengthEndplate = 0;
+            double zCursor = -dz_Endplate/ 2;
+
+            for(xml_coll_t li(x_section,_U(layer)); li;++li)
+            {
+                xml_comp_t  x_layer( li );
+                
+                const double dzPiece = x_layer.attr<double>(_Unicode(dz)); 
+                Material pieceMaterial = theDetector.material( x_layer.materialStr() );
+                Tube pieceSolid( dimEndCap.rmin(),dimEndCap.rmax(), dzPiece / 2, phi1, phi2);
+                Volume pieceLog (  _toString( pieceCounter ,"TPCReadoutPieceLog_%02d"), pieceSolid, pieceMaterial ) ;
+
+                pieceLog.setVisAttributes(theDetector,x_layer.visStr());
+
+                pv = endcapLog.placeVolume( pieceLog  , Position(0, 0,  zCursor + dzPiece/2. ) ) ;
+
+                ++pieceCounter;
+                fracRadLengthEndplate += dzPiece / pieceMaterial->GetMaterial()->GetRadLen();
+                zCursor += dzPiece;
+                
+                std::cout<<"==========> z_pos ="<<zCursor/dd4hep::mm<<" mm "<<dzPiece/dd4hep::mm<<" mm Material= "<<x_layer.materialStr()<<"\t"
+                         <<"X0= "<<pieceMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"\t"
+                         <<dzPiece / pieceMaterial->GetMaterial()->GetRadLen()  <<" X0"<< std::endl;
+
+                if (zCursor > + dz_Endplate/ 2) 
+                {
+                    //throw GeometryException(  "TPC11: Overfull TPC endplate - check your xml file - section <readout>."   ) ;
+                    throw " $!!! TPC_Simple_TDR_o1_v01: Overfull TPC endplate - check your xml file - component <TPCEndplate>.";
+                }
+
+            }
+
+            std::cout << "================================================================"<< std::endl; 
+            std::cout << "TPC_Simple_TDR_o1_v01: Endplate material corresponds to " << int(fracRadLengthEndplate* 1000) / 10.0 << "% of a radiation length." << std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+        //-------------------------------- TPCreadout construction ----------------------------------------//
+        if(types == "TPCreadout")
+        {
+            xml_dim_t dimReadout = x_section.dimensions();
+            double dzReadout = dimReadout.z_length();
+            Tube readoutSolid(dimReadout.rmin(),dimReadout.rmax(),dimReadout.z_length()/2.,phi1,phi1+phi2);
+            Volume readoutLog(volName+"Log",readoutSolid, materialT2Kgas);
+
+            tpc.setVisAttributes(theDetector,"CyanVis",readoutLog);
+
+            xml_dim_t posReadout = x_section.position();
+            pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(0.),Position(0,0,posReadout.z())));  
+            pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(pi),Position(0,0,-posReadout.z())));  
+            
+            std::cout<<"=========ReadOut dim: "<< dimReadout.rmin() / dd4hep::mm<<" mm "
+                                               << dimReadout.rmax() / dd4hep::mm<<" mm"
+                                               << dzReadout / dd4hep::mm <<" mm "<<std::endl;
+            std::cout<<"=========ReadOut Z_pos: "<<posReadout.z() / dd4hep::mm << " mm "<<std::endl;
+
+            int pieceCounter = 0;
+            double fracRadLengthReadout = 0;
+            double zCursor = -dzReadout/ 2;
+
+            for(xml_coll_t li(x_section,_U(layer)); li;++li)
+            {
+                xml_comp_t  x_layer( li );
+            
+                const double dzPiece = x_layer.attr<double>(_Unicode(dz)); 
+                Material pieceMaterial = theDetector.material( x_layer.materialStr() );
+                Tube pieceSolid( dimReadout.rmin(),dimReadout.rmax(), dzPiece / 2, phi1, phi2);
+                Volume pieceLog (  _toString( pieceCounter ,"TPCReadoutPieceLog_%02d"), pieceSolid, pieceMaterial ) ;
+
+                pieceLog.setVisAttributes(theDetector,x_layer.visStr());
+
+                pv = readoutLog.placeVolume( pieceLog  , Position(0, 0,  zCursor + dzPiece/2. ) ) ;
+
+                ++pieceCounter;
+                fracRadLengthReadout += dzPiece / pieceMaterial->GetMaterial()->GetRadLen();
+                zCursor += dzPiece;
+                
+                std::cout<<"==========> z_pos ="<<zCursor/dd4hep::mm<<" mm "<<dzPiece/dd4hep::mm<<" mm Material= "<<x_layer.materialStr()<<"\t"
+                         <<"X0= "<<pieceMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"\t"
+                         <<dzPiece / pieceMaterial->GetMaterial()->GetRadLen()  <<" X0"<< std::endl;
+
+                if (zCursor > + dzReadout / 2) 
+                {
+                    //throw GeometryException(  "TPC11: Overfull TPC readout - check your xml file - section <readout>."   ) ;
+                    throw " $!!! TPC_Simple_TDR_o1_v01: Overfull TPC readout - check your xml file - comment <TPCreadout>.";
+                }
+            }
+            std::cout << "================================================================"<< std::endl; 
+            std::cout << "TPC_Simple_TDR_o1_v01: Readout material corresponds to " << int(fracRadLengthReadout * 1000) / 10.0 << "% of a radiation length." << std::endl;
+            std::cout << "================================================================"<< std::endl; 
+        }
+
+    }
+    
+    //TPC data
+    FixedPadSizeTPCData* tpcData = new FixedPadSizeTPCData();
+    tpcData->zHalf = dzTotal/2.;
+    tpcData->rMin  = rInner;
+    tpcData->rMax  = rOuter;
+    tpcData->innerWallThickness = drInnerWall;
+    tpcData->outerWallThickness = drOuterWall;
+    tpcData->rMinReadout = rInner + drInnerWall;
+    tpcData->rMaxReadout = rInner + drInnerWall + tpcnumberOfPadRows*tpcpadheight;
+    tpcData->maxRow = tpcnumberOfPadRows;
+    tpcData->padHeight = tpcpadheight;
+    tpcData->padWidth =  tpcpadwidth;
+    tpcData->driftLength = dzTotal/2.- dz_Endplate - dz_Readout - dz_Cathode/2.0; // SJA: cathode has to be added as the sensitive region does not start at 0.00    
+    tpcData->zMinReadout = dz_Cathode/2.0; 
+
+    //tpc.setVisAttributes( theDetector, x_det.visStr(), envelope );
+    tpc.setVisAttributes( theDetector, "TPCMotherVis1", envelope );
+    //  if( tpc.isValid() ) 
+    // tpc.setPlacement(pv);
+    std::cout << "================================================================"<< std::endl; 
+    std::cout << "TPC_Simple_TDR_o1_v01 Constructed!"<< std::endl; 
+    std::cout << "================================================================"<< std::endl; 
+
+    return tpc;
+}
+DECLARE_DETELEMENT(TPC_Simple_o1_v01,create_element)
diff --git a/Digitisers/G2CDArbor/CMakeLists.txt b/Digitisers/G2CDArbor/CMakeLists.txt
index 85949dbbe28e38d8c68c1868f327ebe30f260579..2bd2057d6ace2c94b993eee6637556d037b2f82f 100644
--- a/Digitisers/G2CDArbor/CMakeLists.txt
+++ b/Digitisers/G2CDArbor/CMakeLists.txt
@@ -3,12 +3,13 @@ gaudi_add_module(G2CDArbor
                  SOURCES src/G2CDArborAlg.cpp
                  LINK k4FWCore::k4FWCore
                       GearSvc
+                      DecoderHelperLib
                       DetInterface
                       Gaudi::GaudiKernel
-                      Gaudi::GaudiAlgLib 
+                      Gaudi::GaudiAlgLib
                       ${CLHEP_LIBRARIES}
-                      ${GEAR_LIBRARIES} 
-                      ${GSL_LIBRARIES} 
+                      ${GEAR_LIBRARIES}
+                      ${GSL_LIBRARIES}
                       ${LCIO_LIBRARIES}
                       EDM4HEP::edm4hep EDM4HEP::edm4hepDict
                       DD4hep::DDRec
diff --git a/Digitisers/G2CDArbor/src/G2CDArborAlg.cpp b/Digitisers/G2CDArbor/src/G2CDArborAlg.cpp
index 2fbda2cc75388448ff365edff01e8a38019a183a..0cb54fada5d0fb6ce74769e9e386790d23e9542e 100644
--- a/Digitisers/G2CDArbor/src/G2CDArborAlg.cpp
+++ b/Digitisers/G2CDArbor/src/G2CDArborAlg.cpp
@@ -9,6 +9,8 @@
 #include "DD4hep/IDDescriptor.h"
 #include "DD4hep/Plugins.h"
 
+#include "DecoderHelper/DD4hep2Lcio.h"
+
 
 #include <values.h>
 #include <string>
@@ -33,23 +35,23 @@ DECLARE_COMPONENT( G2CDArborAlg )
 // const double pi = acos(-1.0);
 
 struct DigiHit {
-     int   digihitCellID0; 
+     int   digihitCellID0;
      int   digihitCellID1;
-     float digihitCharge; 
-     float digihitEnergyDepo; 
-     int   digihitNum1mmCell; 
+     float digihitCharge;
+     float digihitEnergyDepo;
+     int   digihitNum1mmCell;
      float PosX;
      float PosY;
-     float PosZ; 
-     float LeadChargeDepo; 
-     float ChargeShare; 
-     edm4hep::SimCalorimeterHit * LeadSimCaloHit; 
+     float PosZ;
+     float LeadChargeDepo;
+     float ChargeShare;
+     edm4hep::SimCalorimeterHit * LeadSimCaloHit;
 } ;
 
 //std::map <int, std::pair<float, float> >WeightVector;
 
 float ChanceOfKink = 0.1;
-float KinkHitChargeBoost = 2.2; 
+float KinkHitChargeBoost = 2.2;
 
 // G2CDArborAlg aG2CDArborAlg ;
 
@@ -138,7 +140,7 @@ G2CDArborAlg::G2CDArborAlg(const std::string& name, ISvcLocator* svcLoc)
      // 				_caloTruthLinkCollection,
      // 				caloTruthLinkCollection);
 
-     // std::vector<float> ChargeSpatialDistri; 
+     // std::vector<float> ChargeSpatialDistri;
      // ChargeSpatialDistri.push_back(0.1);
      // ChargeSpatialDistri.push_back(0.2);
      // ChargeSpatialDistri.push_back(0.4);
@@ -149,7 +151,7 @@ G2CDArborAlg::G2CDArborAlg(const std::string& name, ISvcLocator* svcLoc)
      // 				_ChargeSpatialDistri,
      // 				ChargeSpatialDistri);
 
-     // std::vector<float> ShowerPositionShiftID; 
+     // std::vector<float> ShowerPositionShiftID;
      // ShowerPositionShiftID.push_back(0);
      // ShowerPositionShiftID.push_back(0);
      // ShowerPositionShiftID.push_back(0);
@@ -186,7 +188,7 @@ G2CDArborAlg::G2CDArborAlg(const std::string& name, ISvcLocator* svcLoc)
      // registerProcessorParameter( "PolyaParaC" ,
      // 				 "Polya: x^a*exp(-b*x) + C" ,
      // 				 _PolyaParaC,
-     // 				 float(0.03) );	
+     // 				 float(0.03) );
 
      // registerProcessorParameter( "ChanceOfKink" ,
      // 				 "Chance of one boundary hit to create a multiple hit with boosted charge" ,
@@ -317,7 +319,7 @@ StatusCode G2CDArborAlg::initialize() {
      else
      {
      	  ChanceOfKink = _ChanceOfKink;
-     	  KinkHitChargeBoost = _KinkHitChargeBoost; 
+     	  KinkHitChargeBoost = _KinkHitChargeBoost;
      }
 
      float PolyaDomain = 100;
@@ -341,10 +343,10 @@ StatusCode G2CDArborAlg::initialize() {
      int tmpIndex = 0;
      float NormalWeightFactor = 0;
      float NormalWeight[SizeCSD];
-     int IndexA = 0; 
+     int IndexA = 0;
      int IndexB = 0;		//Used to denote charge distributions...
-     float WeightA = 0; 
-     float WeightB = 0; 
+     float WeightA = 0;
+     float WeightB = 0;
 
      for( int i0 = 0; i0 < SizeCSD; i0++ )
      {
@@ -370,37 +372,37 @@ StatusCode G2CDArborAlg::initialize() {
      	       WeightA = 0;
      	       WeightB = 0;
 
-     	       if( i2 < CoverAreaLength ) 
+     	       if( i2 < CoverAreaLength )
      	       {
      		    IndexA = CoverAreaLength - i2;
-     		    SignX = -1; 
+     		    SignX = -1;
      	       }
      	       else if( i2 > _DigiCellSize - CoverAreaLength - 1)
      	       {
      		    IndexA = CoverAreaLength + i2 - _DigiCellSize + 1;
-     		    SignX = 1; 
+     		    SignX = 1;
      	       }
 
-     	       if( j2 < CoverAreaLength ) 
+     	       if( j2 < CoverAreaLength )
      	       {
      		    IndexB = CoverAreaLength - j2;
-     		    SignY = -1; 
+     		    SignY = -1;
      	       }
      	       else if( j2 > _DigiCellSize - CoverAreaLength - 1)
      	       {
      		    IndexB = CoverAreaLength + j2 - _DigiCellSize + 1;
-     		    SignY = 1; 
+     		    SignY = 1;
      	       }
 
-     	       for(int i3 = 0; i3 < CoverAreaLength; i3 ++)        
+     	       for(int i3 = 0; i3 < CoverAreaLength; i3 ++)
      	       {
      		    if(i3 < IndexA) WeightA += NormalWeight[i3];
      		    if(i3 < IndexB) WeightB += NormalWeight[i3];
      	       }
 
-     	       WMatrix.first = SignX*WeightA; 
-     	       WMatrix.second = SignY*WeightB; 
-     	       WeightVector[tmpIndex] = WMatrix;	
+     	       WMatrix.first = SignX*WeightA;
+     	       WMatrix.second = SignY*WeightB;
+     	       WeightVector[tmpIndex] = WMatrix;
 
      	       cout<<WMatrix.first<<"/"<<WMatrix.second<<", ";
      	  }
@@ -419,41 +421,41 @@ StatusCode G2CDArborAlg::execute()
      _eventNr++;
 
      float HitEn = 0;
-     float DigiHitEn = 0; 
+     float DigiHitEn = 0;
      int LayerNum = 0;
      // TVector3 HitPos;   //to be solved
      int tmpM, tmpS, tmpI, tmpJ, tmpK;
-     int CurrI = 0; 
-     int CurrJ = 0; 
+     int CurrI = 0;
+     int CurrJ = 0;
      int DHIndexI = 0;
-     int DHIndexJ = 0; 
+     int DHIndexJ = 0;
      float DHChargeWeight = 0;
-     int DHCellID0 = 0; 
+     int DHCellID0 = 0;
      float RndCharge = 0;
-     int SingleMCPPID = 0; 
-     //float SingleMCPPEn = 0; 
+     int SingleMCPPID = 0;
+     //float SingleMCPPEn = 0;
      float RefPosX = 0;
      float RefPosY = 0;
      float RefPosZ = 0;
      float DeltaPosI = 0;
      float DeltaPosJ = 0;
-     std::vector<float> CurrWeightVec;			
-     float WeiI = 0; 
+     std::vector<float> CurrWeightVec;
+     float WeiI = 0;
      float WeiJ = 0;
      int DeltaI = 0;
-     int DeltaJ = 0; 
-     int MapI = 0; 
-     int MapJ = 0; 
-     int MapIndex = 0; 
+     int DeltaJ = 0;
+     int MapI = 0;
+     int MapJ = 0;
+     int MapIndex = 0;
      float FHitPos[3] = {0, 0, 0};
      float currTime = 0;
      float HitStepEn = 0;
      float EmaxStep = 0;
 
      // LCCollectionVec *relcol = new LCCollectionVec(LCIO::LCRELATION);
-     // LCFlagImpl linkflag; 
+     // LCFlagImpl linkflag;
      // linkflag.setBit(LCIO::CHBIT_LONG);
-     // relcol->setFlag(linkflag.getFlag());	
+     // relcol->setFlag(linkflag.getFlag());
      edm4hep::MCRecoCaloAssociationCollection* relcol = _caloTruthLinkCollection.createAndPut();
 
      // LCCollection * MCPCol = evtP->getCollection("MCParticle");
@@ -464,7 +466,7 @@ StatusCode G2CDArborAlg::execute()
      // 	    {
      // 		 SingleMCPPID = a_MCP->getPDG();
      // 		 //SingleMCPPEn = a_MCP->getEnergy();
-     // 		 break; 
+     // 		 break;
      // 	    }
      // }
 
@@ -485,99 +487,142 @@ StatusCode G2CDArborAlg::execute()
 	  // LCCollectionVec *ecalcol = new LCCollectionVec(LCIO::CALORIMETERHIT);
 	  // ecalcol->setFlag(flag.getFlag());
 	  // string EcalinitString = Ecalcol->getParameters().getStringVal(LCIO::CellIDEncoding);
-	  // ecalcol->parameters().setValue(LCIO::CellIDEncoding, EcalinitString);	
+	  // ecalcol->parameters().setValue(LCIO::CellIDEncoding, EcalinitString);
 
 	  // for(int k1 = 0; k1 < NumEcalhit; k1++)
-	  // {	
-	  if(m_readLCIO==false){
-	      std::string tmp_readout = m_col_readout_map[m_ecalColNames.value().at(k0)];
-              // get the DD4hep readout
-              m_decoder = m_geosvc->getDecoder(tmp_readout);
-              if (!m_decoder) {
-                error() << "Failed to get the decoder. Skip this collection:"<<m_ecalColNames.value().at(k0)<< endmsg;
-                continue;
-              }
-          }
-
-	  edm4hep::CalorimeterHitCollection* ecalcol = _outputEcalCollections[k0]->createAndPut();
-	  auto Ecalcol = _ecalCollections[k0]->get();
-	  for (auto SimEcalhit: *Ecalcol){
-		   auto cellid = SimEcalhit.getCellID();
-	       // SimCalorimeterHit * SimEcalhit = dynamic_cast<SimCalorimeterHit*>( Ecalcol->getElementAt( k1 ) ) ;
-	       // HitEn = SimEcalhit->getEnergy();
-	       // LayerNum = idDecoder(SimEcalhit)["K-1"];
-
-	       // edm4hep::SimCalorimeterHit aa(SimEcalhit.getCellID(), SimEcalhit.getEnergy(), SimEcalhit.getPosition());
-               ID_UTIL::CellIDDecoder< decltype(SimEcalhit) > cellIdDecoder(m_encoder_str);
-	       const std::string layerCodingString(m_encoder_str);
-	       const std::string layerCoding(this->GetLayerCoding(layerCodingString));
-	       if(m_readLCIO==false) LayerNum = m_decoder->get(cellid, "layer");//from 0 - 29, 0 is preshower
-	       else LayerNum = cellIdDecoder(&SimEcalhit)[layerCoding.c_str()] + 1 ;//now it is 0 - 29, 0 is preshower
-	       //cout << "LayerNum = " << LayerNum << endl;
-
-	       HitEn = SimEcalhit.getEnergy();
-	       unsigned long long cellID = SimEcalhit.getCellID();
-
-	       currTime = 0;
-	       EmaxStep = 0;
-	       HitStepEn = 0;
-	       // for(int k=0; k<SimEcalhit->getNMCContributions(); k++)
-	       // {
-	       for(int k=0; k<SimEcalhit.contributions_size(); k++){
-		    edm4hep::CaloHitContribution hitContribution = SimEcalhit.getContributions(k);
-	  	    // HitStepEn = SimEcalhit->getEnergyCont(k);
-		    HitStepEn = hitContribution.getEnergy();
-	  	    if(HitStepEn > EmaxStep)
-	  	    {
-	  		 EmaxStep = HitStepEn;
-	  		 // currTime = SimEcalhit->getTimeCont(k);
-			 currTime = hitContribution.getTime();
-	  	    }
-	       }
-
-	       // _calibCoeffEcal[0] = 48.16;
-	       // _calibCoeffEcal[1] = 96.32;
-	       //if(LayerNum < _NEcalThinLayer) 
-	       if(LayerNum <= _NEcalThinLayer) //layer from 0 - 20 should be thin, total 21 thin layers, _NEcalThinLayer should be 20
-	  	    DigiHitEn = HitEn * _calibCoeffEcal[0];
-	       else 	
-	  	    DigiHitEn = HitEn * _calibCoeffEcal[1];
-	       if( LayerNum==0) DigiHitEn = HitEn; // 0 is preshower layer
-
-	       totalEnergy += DigiHitEn;
-	       if(HitEn > _thresholdEcal)
-	       {
-	  	    // CalorimeterHitImpl * DigiEcalhit = new CalorimeterHitImpl();
-	  	    // FHitPos[0] = SimEcalhit->getPosition()[0] + _ShowerPositionShiftID[0]*10.0;
-	  	    // FHitPos[1] = SimEcalhit->getPosition()[1] + _ShowerPositionShiftID[1]*10.0;
-	  	    // FHitPos[2] = SimEcalhit->getPosition()[2] + _ShowerPositionShiftID[2]*10.0;
-
-		    edm4hep::Vector3f hitPos = SimEcalhit.getPosition();
-	  	    FHitPos[0] = hitPos.x + _ShowerPositionShiftID[0]*10.0;
-	  	    FHitPos[1] = hitPos.y + _ShowerPositionShiftID[1]*10.0;
-	  	    FHitPos[2] = hitPos.z + _ShowerPositionShiftID[2]*10.0;
-		    edm4hep::Vector3f FHitPosition(FHitPos[0], FHitPos[1], FHitPos[2]);
-
-	  	    // DigiEcalhit->setTime(currTime);
-	  	    // DigiEcalhit->setPosition( FHitPos );
-	  	    // DigiEcalhit->setCellID0(SimEcalhit->getCellID0());
-	  	    // DigiEcalhit->setCellID1(SimEcalhit->getCellID1());
-	  	    // DigiEcalhit->setEnergy(DigiHitEn);
-	  	    // ecalcol->addElement(DigiEcalhit);
-		    auto DigiEcalhit = ecalcol->create();
-		    DigiEcalhit.setTime(currTime);
-		    DigiEcalhit.setPosition(FHitPosition);
-		    DigiEcalhit.setCellID(cellID);
-		    DigiEcalhit.setEnergy(DigiHitEn);
-
-	  	    // LCRelationImpl *rel = new LCRelationImpl(DigiEcalhit, SimEcalhit, 1.0);    //only keep the leading contribution
-	  	    // relcol->addElement(rel);
-		    auto rel = relcol->create();
-		    rel.setRec(DigiEcalhit);
-		    rel.setSim(SimEcalhit);
-		    rel.setWeight(1.0);
-	       }
-	  }
+	  // {
+    if(m_readLCIO==false){
+        std::string tmp_readout = m_col_readout_map[m_ecalColNames.value().at(k0)];
+        // get the DD4hep readout
+        m_decoder = m_geosvc->getDecoder(tmp_readout);
+        if (!m_decoder) {
+            error() << "Failed to get the decoder. Skip this collection:"<<m_ecalColNames.value().at(k0)<< endmsg;
+            continue;
+        }
+    }
+
+    edm4hep::CalorimeterHitCollection* ecalcol = _outputEcalCollections[k0]->createAndPut();
+    auto Ecalcol = _ecalCollections[k0]->get();
+
+    int iHit = 0;
+    double ESum_ECALSimu = 0;
+    double ESum_ECALDigi = 0;
+    cout<<"[YX debug - G2CD] ECAL Collection Simu "<<k0<<", nSimuHit = "<<Ecalcol->size()<<", "<<m_ecalColNames.value().at(k0)<<endl;
+
+    for (auto SimEcalhit: *Ecalcol){
+        auto cellid = SimEcalhit.getCellID();
+        // SimCalorimeterHit * SimEcalhit = dynamic_cast<SimCalorimeterHit*>( Ecalcol->getElementAt( k1 ) ) ;
+        // HitEn = SimEcalhit->getEnergy();
+        // LayerNum = idDecoder(SimEcalhit)["K-1"];
+
+        // edm4hep::SimCalorimeterHit aa(SimEcalhit.getCellID(), SimEcalhit.getEnergy(), SimEcalhit.getPosition());
+
+        ID_UTIL::CellIDDecoder< decltype(SimEcalhit) > cellIdDecoder(m_encoder_str);
+        const std::string layerCodingString(m_encoder_str);
+        const std::string layerCoding(this->GetLayerCoding(layerCodingString));
+        if(m_readLCIO){
+            // LayerNum = cellIdDecoder(&SimEcalhit)[layerCoding.c_str()] + 1 ;//now it is 0 - 29, 0 is preshower
+            // actually 1-30
+
+            LayerNum = cellIdDecoder(&SimEcalhit)[layerCoding.c_str()];  // 0 - 29
+
+        }else{
+            // LayerNum = m_decoder->get(cellid, "layer");  //from 0 - 29, 0 is preshower
+
+            int Raw_Layer = m_decoder->get(cellid, "layer");  // 0 - 29
+            LayerNum = DD4hep2Lcio::CEPCv4::getEcalLayer(Raw_Layer);  // -1 - 28, -1 is preshower
+        }
+
+
+        HitEn = SimEcalhit.getEnergy();
+        unsigned long long cellID = SimEcalhit.getCellID();
+
+        currTime = 0;
+        EmaxStep = 0;
+        HitStepEn = 0;
+        // for(int k=0; k<SimEcalhit->getNMCContributions(); k++)
+        // {
+        for(int k=0; k<SimEcalhit.contributions_size(); k++){
+            edm4hep::CaloHitContribution hitContribution = SimEcalhit.getContributions(k);
+            // HitStepEn = SimEcalhit->getEnergyCont(k);
+            HitStepEn = hitContribution.getEnergy();
+            if(HitStepEn > EmaxStep)
+            {
+                EmaxStep = HitStepEn;
+                // currTime = SimEcalhit->getTimeCont(k);
+                currTime = hitContribution.getTime();
+            }
+        }
+
+        // _calibCoeffEcal[0] = 48.16;
+        // _calibCoeffEcal[1] = 96.32;
+        // if(LayerNum <= _NEcalThinLayer) //layer from 0 - 20 should be thin, total 21 thin layers, _NEcalThinLayer should be 20
+        if(LayerNum < _NEcalThinLayer)  // _NEcalThinLayer = 20
+            DigiHitEn = HitEn * _calibCoeffEcal[0];
+        else
+            DigiHitEn = HitEn * _calibCoeffEcal[1];
+
+        if(LayerNum==-1) DigiHitEn = HitEn; // -1 is preshower layer
+
+        totalEnergy += DigiHitEn;
+
+        // TVector3 HitPos = SimEcalhit.getPosition();
+        edm4hep::Vector3f HitPos = SimEcalhit.getPosition();
+        double HitDis = sqrt(HitPos.x*HitPos.x + HitPos.y*HitPos.y + HitPos.z*HitPos.z);
+        double HitTime = currTime - HitDis / 300;
+
+
+        if(0){
+            cout<<"Hit Pos(x,y,z,perp) = ("<<HitPos.x<<", "<<HitPos.y<<", "<<HitPos.z<<", "<<sqrt(HitPos.x*HitPos.x+HitPos.y*HitPos.y)<<")"<<endl;
+            cout<<"---> LayerNum = "<<LayerNum<<endl;
+        }
+
+        //    if(HitEn > _thresholdEcal)
+        if(HitEn > _thresholdEcal && HitTime < _TimeThreshold)
+        {
+            // CalorimeterHitImpl * DigiEcalhit = new CalorimeterHitImpl();
+            // FHitPos[0] = SimEcalhit->getPosition()[0] + _ShowerPositionShiftID[0]*10.0;
+            // FHitPos[1] = SimEcalhit->getPosition()[1] + _ShowerPositionShiftID[1]*10.0;
+            // FHitPos[2] = SimEcalhit->getPosition()[2] + _ShowerPositionShiftID[2]*10.0;
+
+            edm4hep::Vector3f hitPos = SimEcalhit.getPosition();
+            FHitPos[0] = hitPos.x + _ShowerPositionShiftID[0]*10.0;
+            FHitPos[1] = hitPos.y + _ShowerPositionShiftID[1]*10.0;
+            FHitPos[2] = hitPos.z + _ShowerPositionShiftID[2]*10.0;
+            edm4hep::Vector3f FHitPosition(FHitPos[0], FHitPos[1], FHitPos[2]);
+
+            // DigiEcalhit->setTime(currTime);
+            // DigiEcalhit->setPosition( FHitPos );
+            // DigiEcalhit->setCellID0(SimEcalhit->getCellID0());
+            // DigiEcalhit->setCellID1(SimEcalhit->getCellID1());
+            // DigiEcalhit->setEnergy(DigiHitEn);
+            // ecalcol->addElement(DigiEcalhit);
+            auto DigiEcalhit = ecalcol->create();
+            DigiEcalhit.setTime(currTime);
+            DigiEcalhit.setPosition(FHitPosition);
+            DigiEcalhit.setCellID(cellID);
+            DigiEcalhit.setEnergy(DigiHitEn);
+
+            // LCRelationImpl *rel = new LCRelationImpl(DigiEcalhit, SimEcalhit, 1.0);    //only keep the leading contribution
+            // relcol->addElement(rel);
+            auto rel = relcol->create();
+            rel.setRec(DigiEcalhit);
+            rel.setSim(SimEcalhit);
+            rel.setWeight(1.0);
+
+            ESum_ECALSimu += SimEcalhit.getEnergy();
+            ESum_ECALDigi += DigiEcalhit.getEnergy();
+            // cout<<"[YX debug - G2CD] ECAL DigiHit "<<iHit<<", E = "<<DigiEcalhit.getEnergy()<<", T = "<<DigiEcalhit.getTime()<<", Pos ("<<FHitPos[0]<<", "<<FHitPos[1]<<", "<<FHitPos[2]<<")"<<endl;
+
+        }
+
+        iHit+=1;
+    }
+
+
+        int nDigiHit_ECAL = ecalcol->size();
+        cout<<"[YX debug - G2CD] ECAL Collection Digi "<<k0<<", nDigiHit = "<<nDigiHit_ECAL<<", "<<m_ecalOutputColNames.value().at(k0)<<", DigiESum= "<<ESum_ECALSimu<<", SimuESum = "<<ESum_ECALDigi<<endl;
+
 
 	  // evtP->addCollection(ecalcol,_outputEcalCollections[k0].c_str());
 
@@ -598,7 +643,7 @@ StatusCode G2CDArborAlg::execute()
      // 	    //if(k=="CEPC_v1"  || k=="ild_o2_v05")	// 1cm cell simulation...
      // {
 
-     // 	  cout<<"Detector Tpype: "<<k<<endl; 
+     // 	  cout<<"Detector Tpype: "<<k<<endl;
 
      for (unsigned int k3 = 0; k3 < _hcalCollections.size(); ++k3)
      {
@@ -609,12 +654,20 @@ StatusCode G2CDArborAlg::execute()
      	  // hcalcol->setFlag(flag.getFlag());
      	  // string HcalinitString = Hcalcol->getParameters().getStringVal(LCIO::CellIDEncoding);
      	  // hcalcol->parameters().setValue(LCIO::CellIDEncoding, HcalinitString);
-				
+
      	  // for(int k4 = 0; k4 < NumHcalhit; k4++)
      	  // {
 
+
+
      	  edm4hep::CalorimeterHitCollection* hcalcol = _outputHcalCollections[k3]->createAndPut();
      	  auto Hcalcol = _hcalCollections[k3]->get();
+
+            int iHit = 0;
+            double ESum_HCALSimu = 0;
+            double ESum_HCALDigi = 0;
+            cout<<"[YX debug - G2CD] HCAL Collection Simu "<<k3<<", nSimuHit = "<<Hcalcol->size()<<", "<<m_hcalColNames.value().at(k3)<<endl;
+
      	  for(auto SimHcalhit: *Hcalcol){
      	  //      SimCalorimeterHit * SimHcalhit = dynamic_cast<SimCalorimeterHit*>( Hcalcol->getElementAt( k4 ) ) ;
 
@@ -638,8 +691,12 @@ StatusCode G2CDArborAlg::execute()
      	  	    }
      	       }
 
-     	       // if(SimHcalhit->getEnergy() > 0)	//some threshold can be added.
-     	       if(SimHcalhit.getEnergy() > 0)	//some threshold can be added.
+     	       edm4hep::Vector3f HitPos = SimHcalhit.getPosition();
+            double HitDis = sqrt(HitPos.x*HitPos.x + HitPos.y*HitPos.y + HitPos.z*HitPos.z);
+            double HitTime = currTime - HitDis / 300;
+
+     	    //    if(SimHcalhit.getEnergy() > 0)	//some threshold can be added.
+     	       if(SimHcalhit.getEnergy() > 0 && HitTime < _TimeThreshold)	//some threshold can be added.
      	       {
      	  	    // CalorimeterHitImpl * DigiHcalhit = new CalorimeterHitImpl();
 
@@ -672,9 +729,23 @@ StatusCode G2CDArborAlg::execute()
      		    rel.setRec(DigiHcalhit);
      		    rel.setSim(SimHcalhit);
      		    rel.setWeight(1.0);
+
+
+                ESum_HCALSimu += SimHcalhit.getEnergy();
+                ESum_HCALDigi += DigiHcalhit.getEnergy();
+                // cout<<"[YX debug - G2CD] HCAL DigiHit "<<iHit<<", E = "<<DigiHcalhit.getEnergy()<<", T = "<<DigiHcalhit.getTime()<<", Pos ("<<FHitPos[0]<<", "<<FHitPos[1]<<", "<<FHitPos[2]<<")"<<endl;
+
      	       }
+
+                iHit+=1;
+
      	  }
 
+            int nDigiHit_HCAL = hcalcol->size();
+            cout<<"[YX debug - G2CD] HCAL Collection Digi "<<k3<<", nDigiHit = "<<nDigiHit_HCAL<<", "<<m_hcalOutputColNames.value().at(k3)<<", DigiESum= "<<ESum_HCALSimu<<", SimuESum = "<<ESum_HCALDigi<<endl;
+
+
+
      	  // evtP->addCollection(hcalcol,_outputHcalCollections[k3].c_str());
 
      	  // }catch(lcio::DataNotAvailableException zero) { }
@@ -685,7 +756,7 @@ StatusCode G2CDArborAlg::execute()
      // 	    string EcalPSinitString = "M:3,S-1:3,I:9,J:9,K-1:6";
      // 	    ecalPScol->parameters().setValue(LCIO::CellIDEncoding, EcalPSinitString);
 
-     // 	    //  parameter CellIDEncoding [string]: M:3,S-1:3,I:9,J:9,K-1:6, 
+     // 	    //  parameter CellIDEncoding [string]: M:3,S-1:3,I:9,J:9,K-1:6,
 
      // 	    for(unsigned int s0 = 0; s0 < _EcalPreShowerCollections.size(); s0++)   //I think should digitize and give a very small energy; even a new collection called PS Hits
      // 	    {
@@ -708,7 +779,7 @@ StatusCode G2CDArborAlg::execute()
      // 				     EmaxStep = HitStepEn;
      // 				     currTime = a_hit->getTimeCont(k);
      // 				}
-     // 			   }                                                               
+     // 			   }
 
      // 			   CalorimeterHitImpl * PShit = new CalorimeterHitImpl();
 
@@ -732,16 +803,16 @@ StatusCode G2CDArborAlg::execute()
      // }
      // else
      // {
-     // 	    for (unsigned int i(0); i < _hcalCollections.size(); ++i) 
+     // 	    for (unsigned int i(0); i < _hcalCollections.size(); ++i)
      // 	    {		//strictly follow barrel, endcap, ring order
 
-     // 		 std::map <int, DigiHit> IDtoDigiHit; 
+     // 		 std::map <int, DigiHit> IDtoDigiHit;
      // 		 IDtoDigiHit.clear();
-     // 		 std::map <int, TVector3> IDtoPos; 
+     // 		 std::map <int, TVector3> IDtoPos;
      // 		 IDtoPos.clear();
      // 		 std::map <int, float> IDtoTime;
      // 		 IDtoTime.clear();
-					
+
 
      // 		 try{
      // 		      LCCollection * col = evtP->getCollection( _hcalCollections[i].c_str() ) ;
@@ -782,12 +853,12 @@ StatusCode G2CDArborAlg::execute()
      // 			   RefPosY = hit->getPosition()[1];
      // 			   RefPosZ = hit->getPosition()[2];
 
-     // 			   CurrI = tmpI/_DigiCellSize; 
+     // 			   CurrI = tmpI/_DigiCellSize;
      // 			   CurrJ = tmpJ/_DigiCellSize;
      // 			   MapI = tmpI % _DigiCellSize;
      // 			   MapJ = tmpJ % _DigiCellSize;
-     // 			   MapIndex = MapI * _DigiCellSize + MapJ; 
-     // 			   WeiI = WeightVector[MapIndex].first; 
+     // 			   MapIndex = MapI * _DigiCellSize + MapJ;
+     // 			   WeiI = WeightVector[MapIndex].first;
      // 			   WeiJ = WeightVector[MapIndex].second;
 
      // 			   DeltaPosI = (float(_DigiCellSize) - 1.0)/2 - MapI;
@@ -795,11 +866,11 @@ StatusCode G2CDArborAlg::execute()
 
      // 			   // cout<<"DeltaI "<<DeltaPosI<<", "<<DeltaPosJ<<endl;
 
-     // 			   DeltaI = 0; 
-     // 			   DeltaJ = 0; 
+     // 			   DeltaI = 0;
+     // 			   DeltaJ = 0;
 
-     // 			   if(fabs(WeiI) > 1E-9) 
-     // 			   {	
+     // 			   if(fabs(WeiI) > 1E-9)
+     // 			   {
      // 				DeltaI = ((WeiI > 0) ? 1: -1);
      // 			   }
      // 			   if(fabs(WeiJ) > 1E-9)
@@ -840,7 +911,7 @@ StatusCode G2CDArborAlg::execute()
      // 				     if(DeltaI)
      // 				     {
      // 					  DHIndexI = CurrI + DeltaI;
-     // 					  DHIndexJ = CurrJ; 
+     // 					  DHIndexJ = CurrJ;
      // 				     }
      // 				     if(DeltaJ)
      // 				     {
@@ -876,9 +947,9 @@ StatusCode G2CDArborAlg::execute()
      // 				     {
      // 					  IDtoDigiHit[DHCellID0].PosX = RefPosX + (DeltaPosI + int(DHIndexI - CurrI)*_DigiCellSize) * cos(tmpS*pi/4.0) + _ShowerPositionShiftID[0]*_DigiCellSize; //(mm in unit)
      // 					  IDtoDigiHit[DHCellID0].PosY = RefPosY + (DeltaPosI + int(DHIndexI - CurrI)*_DigiCellSize)* sin(tmpS*pi/4.0) + _ShowerPositionShiftID[1]*_DigiCellSize;
-     // 					  IDtoDigiHit[DHCellID0].PosZ = RefPosZ + DeltaPosJ + int(DHIndexJ - CurrJ)*_DigiCellSize + _ShowerPositionShiftID[2]*_DigiCellSize;	//Rotation is needed, based on S; 
+     // 					  IDtoDigiHit[DHCellID0].PosZ = RefPosZ + DeltaPosJ + int(DHIndexJ - CurrJ)*_DigiCellSize + _ShowerPositionShiftID[2]*_DigiCellSize;	//Rotation is needed, based on S;
      // 				     }
-     // 				     else	//endcap or ring;  
+     // 				     else	//endcap or ring;
      // 				     {
      // 					  IDtoDigiHit[DHCellID0].PosX = RefPosX + DeltaPosI + (DHIndexI - CurrI)*_DigiCellSize + _ShowerPositionShiftID[0]*_DigiCellSize; //(mm in unit)
      // 					  IDtoDigiHit[DHCellID0].PosY = RefPosY + DeltaPosJ + (DHIndexJ - CurrJ)*_DigiCellSize + _ShowerPositionShiftID[1]*_DigiCellSize;
@@ -888,7 +959,7 @@ StatusCode G2CDArborAlg::execute()
      // 				     HitPos.SetXYZ(IDtoDigiHit[DHCellID0].PosX, IDtoDigiHit[DHCellID0].PosY, IDtoDigiHit[DHCellID0].PosZ);
 
      // 				     IDtoPos[DHCellID0] = HitPos;
-     // 				     IDtoTime[DHCellID0] = currTime;	
+     // 				     IDtoTime[DHCellID0] = currTime;
      // 				}
      // 				else
      // 				{
@@ -898,7 +969,7 @@ StatusCode G2CDArborAlg::execute()
      // 				     if(RndCharge * DHChargeWeight > IDtoDigiHit[DHCellID0].LeadChargeDepo)
      // 				     {
      // 					  IDtoDigiHit[DHCellID0].LeadChargeDepo = RndCharge * DHChargeWeight;
-     // 					  IDtoDigiHit[DHCellID0].LeadSimCaloHit = hit; 
+     // 					  IDtoDigiHit[DHCellID0].LeadSimCaloHit = hit;
      // 					  IDtoDigiHit[DHCellID0].ChargeShare = DHChargeWeight;
      // 				     }
 
@@ -917,14 +988,14 @@ StatusCode G2CDArborAlg::execute()
      // 			   CalorimeterHitImpl * calhit = new CalorimeterHitImpl();
      // 			   LCRelationImpl *rel = new LCRelationImpl(calhit, ff->second.LeadSimCaloHit, ff->second.ChargeShare);	//only keep the leading contribution
      // 			   relcol->addElement(rel);
-							
+
      // 			   calhit->setCellID0( ff->first );	//Assume 100% efficiency
      // 			   //calhit->setEnergy( DHCALCalibrationConstant );		//Charge
      // 			   calhit->setEnergy( _thresholdHcal );		//Charge
      // 			   calhit->setCellID1(SingleMCPPID);	//Use ID1 & Energy Error to denote the MCP info...
      // 			   calhit->setEnergyError(ff->second.digihitCharge); // (SingleMCPPEn);
      // 			   /*
-     // 			     DigiHitPos[0] = ff->second.PosX; 
+     // 			     DigiHitPos[0] = ff->second.PosX;
      // 			     DigiHitPos[1] = ff->second.PosY;
      // 			     DigiHitPos[2] = ff->second.PosZ;
      // 			   */
@@ -933,7 +1004,7 @@ StatusCode G2CDArborAlg::execute()
      // 			   DigiHitPos[2] = IDtoPos[ff->first].Z();
 
      // 			   calhit->setTime(IDtoTime[ff->first]);
-     // 			   calhit->setPosition(DigiHitPos);		
+     // 			   calhit->setPosition(DigiHitPos);
      // 			   hcalcol->addElement(calhit);
      // 		      }
 
diff --git a/Digitisers/G2CDArbor/src/G2CDArborAlg.h b/Digitisers/G2CDArbor/src/G2CDArborAlg.h
index 08c04f0335266d3ecfbd035c0b30c6c798509161..45e1d1cfef34f6789f4044e2cf74144853d03a7b 100644
--- a/Digitisers/G2CDArbor/src/G2CDArborAlg.h
+++ b/Digitisers/G2CDArbor/src/G2CDArborAlg.h
@@ -38,7 +38,7 @@ public:
      /* G2CDArborAlg(); */
      /* ~G2CDArborAlg() {}; */
 
-     /** Called at the begin of the job before anything is read.    
+     /** Called at the begin of the job before anything is read.
       * Use to initialize the processor, e.g. book histograms.
       */
      virtual StatusCode initialize() ;
@@ -98,6 +98,7 @@ protected:
      Gaudi::Property<int>    _NEcalThinLayer{this, "NumThinEcalLayer", 20, "Num of thiner Ecal layers"};
      Gaudi::Property<float>  _thresholdEcal{this, "ECALThreshold", (float)5.0e-5, "Threshold for ECAL Hits in GeV"};
      Gaudi::Property<float>  _thresholdHcal{this, "HCALThreshold", (float)0.11, "Threshold for HCAL Hits in GeV"};
+     Gaudi::Property<float>  _TimeThreshold{this, "TimeThreshold", (float)1000, "Time Threshold for both ECAL and HCAL Hits in ns"};
      Gaudi::Property<int>    _DigiCellSize{this, "DigiCellSize", 10, "Size of Digitized Cell (in mm)"};
      Gaudi::Property<float>  _ShiftInX{this, "ShiftInX", (float)0.0, "Shift Distance in X directoin (in mm) NP only"};
      Gaudi::Property<int>    _UsingDefaultDetector{this, "UsingDefaultDetector", 0, "Flag Parameter Setting (0 ~ self definition, 1 ~ MircoMegas, 2 ~ GRPC_PS, 3 ~ GRPC_SPS)"};
@@ -133,18 +134,18 @@ protected:
      /* float _PolyaParaA, _PolyaParaB, _PolyaParaC;  */
      /* float _ChanceOfKink, _KinkHitChargeBoost;  */
      TTree *_outputTree;
-     TH1F *_NH1stLayer, *_NH8thLayer; 
-     TF1 * _QPolya; 
+     TH1F *_NH1stLayer, *_NH8thLayer;
+     TF1 * _QPolya;
 
      int _Num;
-     int _eventNr; 
+     int _eventNr;
 
      int _M, _S, _I, _J, _K, _Seg;
-     float _PosX, _PosY, _PosZ; 
+     float _PosX, _PosY, _PosZ;
      /* float _EDepo, _Charge, _ShiftInX;  */
      int _NHit1mm, _NHit1mmCenter, _NHit1mmCorner, _NHit1mmSide;
-     int _TotalNHit1mm, _TotalNHit, _TotalMultiHit; 
-     int _N1, _N2, _N3; 
+     int _TotalNHit1mm, _TotalNHit, _TotalMultiHit;
+     int _N1, _N2, _N3;
 
      std::string _fileName;
      std::ostream *_output;
diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt
index 6d37ea639a5354eb09dd50e37a86ce23a596654a..2a4bf50bdd5a09f4f6fcb973bbb20f5ba242b925 100644
--- a/Examples/CMakeLists.txt
+++ b/Examples/CMakeLists.txt
@@ -8,12 +8,14 @@ gaudi_add_module(Examples
                          src/Edm4hepTest/Edm4hepReadAlg.cpp
                          src/Edm4hepTest/Edm4hepReadDCAlg.cpp
                          src/Edm4hepTest/Edm4hepWriteAlg.cpp
+                         src/Edm4hepTest/Edm4cepcWriteAlg.cpp
                          src/DumpIDAlg/DumpIDAlg.cpp
                  LINK DetInterface
                       k4FWCore::k4FWCore
                       Gaudi::GaudiAlgLib Gaudi::GaudiKernel
                       ${LCIO_LIBRARIES} 
                       ${DD4hep_COMPONENT_LIBRARIES}
+                      EDM4CEPC::edm4cepc EDM4CEPC::edm4cepcDict
                       EDM4HEP::edm4hep EDM4HEP::edm4hepDict
                       ${podio_LIBRARIES} podio::podioRootIO
 )
diff --git a/Examples/options/CEPCV4_simu_reco_Arbor.py b/Examples/options/CEPCV4_simu_reco_Arbor.py
new file mode 100644
index 0000000000000000000000000000000000000000..dbd5e7212b64f3b4851cb3f99c490b7d8501a87f
--- /dev/null
+++ b/Examples/options/CEPCV4_simu_reco_Arbor.py
@@ -0,0 +1,313 @@
+#!/usr/bin/env python
+
+import os
+
+from Gaudi.Configuration import *
+
+# NTupleSvc().Output = ["MyTuples DATAFILE='Examples/options/TPC_out.root' OPT='NEW' TYP='ROOT'"]
+
+from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_
+rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_()
+rndmengine.SetSingleton = True
+rndmengine.Seeds = [1]
+
+from Configurables import k4DataSvc
+dsvc = k4DataSvc("EventDataSvc")
+
+from Configurables import MarlinEvtSeeder
+evtseeder = MarlinEvtSeeder("EventSeeder")
+
+geometry_option = "CepC_v4.xml"
+
+if not os.getenv("DETCEPCV4ROOT"):
+    print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." )
+    sys.exit(-1)
+
+geometry_path = os.path.join(os.getenv("DETCEPCV4ROOT"), "compact", geometry_option)
+if not os.path.exists(geometry_path):
+    print("Can't find the compact geometry file: %s"%geometry_path)
+    sys.exit(-1)
+
+from Configurables import GeomSvc
+geosvc = GeomSvc("GeomSvc")
+geosvc.compact = geometry_path
+
+from Configurables import GearSvc
+gearsvc = GearSvc("GearSvc")
+#gearsvc.GearXMLFile = "Detector/DetCEPCv4/compact/FullDetGear.xml"
+
+##############################################################################
+# Generator
+from Configurables import GenAlgo
+from Configurables import GtGunTool
+from Configurables import StdHepRdr
+from Configurables import SLCIORdr
+from Configurables import HepMCRdr
+from Configurables import GenPrinter
+
+gun = GtGunTool("GtGunTool")
+gun.Particles = ["e-"]
+#gun.EnergyMins = [1]
+#gun.EnergyMaxs = [50]
+#gun.ThetaMins = [50]
+#gun.ThetaMaxs = [130]
+#gun.PhiMins = [-90]
+#gun.PhiMaxs = [90]
+gun.EnergyMins = [10]
+gun.EnergyMaxs = [10]
+gun.ThetaMins = [90]
+gun.ThetaMaxs = [90]
+gun.PhiMins = [0]
+gun.PhiMaxs = [0]
+
+stdheprdr = StdHepRdr("StdHepRdr")
+stdheprdr.Input = "/cefs/data/stdhep/CEPC240/higgs/Higgs_10M/data/E240.Pnnh_gg.e0.p0.whizard195/nnh_gg.e0.p0.00001.stdhep"
+# stdheprdr.Input = "GenFile"
+
+genprinter = GenPrinter("GenPrinter")
+
+genalg = GenAlgo("GenAlgo")
+# genalg.GenTools = ["GtGunTool"]
+genalg.GenTools = ["StdHepRdr"]
+
+##############################################################################
+# Detector simulation
+from Configurables import DetSimSvc
+detsimsvc = DetSimSvc("DetSimSvc")
+
+from Configurables import DetSimAlg
+detsimalg = DetSimAlg("DetSimAlg")
+# detsimalg.VisMacs = ["vis.mac"]
+detsimalg.RunCmds = [
+#    "/physics_lists/factory/addOptical"
+]
+detsimalg.PhysicsList = "FTFP_BERT"
+detsimalg.AnaElems = ["Edm4hepWriterAnaElemTool"]
+detsimalg.RootDetElem = "WorldDetElemTool"
+
+from Configurables import AnExampleDetElemTool
+example_dettool = AnExampleDetElemTool("AnExampleDetElemTool")
+
+##############################################################################
+# Tracker
+
+from Configurables import TimeProjectionChamberSensDetTool
+tpc_sensdettool = TimeProjectionChamberSensDetTool("TimeProjectionChamberSensDetTool")
+tpc_sensdettool.TypeOption = 1
+
+from Configurables import TrackSystemSvc
+tracksystemsvc = TrackSystemSvc("TrackSystemSvc")
+
+vxdhitname  = "VXDTrackerHits"
+sithitname  = "SITTrackerHits"
+sitspname   = "SITSpacePoints"
+tpchitname  = "TPCTrackerHits"
+sethitname  = "SETTrackerHits"
+setspname   = "SETSpacePoints"
+ftdspname   = "FTDSpacePoints"
+ftdhitname = "FTDTrackerHits"
+from Configurables import PlanarDigiAlg
+digiVXD = PlanarDigiAlg("VXDDigi")
+digiVXD.SimTrackHitCollection = "VXDCollection"
+digiVXD.TrackerHitCollection = vxdhitname
+digiVXD.TrackerHitAssociationCollection = "VXDTrackerHitAssociation"
+digiVXD.ResolutionU = [0.0028, 0.006, 0.004, 0.004, 0.004, 0.004]
+digiVXD.ResolutionV = [0.0028, 0.006, 0.004, 0.004, 0.004, 0.004]
+
+digiSIT = PlanarDigiAlg("SITDigi")
+digiSIT.IsStrip = 1
+digiSIT.SimTrackHitCollection = "SITCollection"
+digiSIT.TrackerHitCollection = sithitname
+digiSIT.TrackerHitAssociationCollection = "SITTrackerHitAssociation"
+digiSIT.ResolutionU = [0.007]
+digiSIT.ResolutionV = [0.000]
+
+digiSET = PlanarDigiAlg("SETDigi")
+digiSET.IsStrip = 1
+digiSET.SimTrackHitCollection = "SETCollection"
+digiSET.TrackerHitCollection = sethitname
+digiSET.TrackerHitAssociationCollection = "SETTrackerHitAssociation"
+digiSET.ResolutionU = [0.007]
+digiSET.ResolutionV = [0.000]
+
+digiFTD = PlanarDigiAlg("FTDDigi")
+digiFTD.SimTrackHitCollection = "FTDCollection"
+digiFTD.TrackerHitCollection = ftdhitname
+digiFTD.TrackerHitAssociationCollection = "FTDTrackerHitAssociation"
+digiFTD.ResolutionU = [0.003, 0.003, 0.007, 0.007, 0.007, 0.007, 0.007, 0.007]
+digiFTD.ResolutionV = [0.003, 0.003, 0,     0,     0,     0,     0,     0    ]
+#digiFTD.OutputLevel = DEBUG
+
+from Configurables import SpacePointBuilderAlg
+spSIT = SpacePointBuilderAlg("SITBuilder")
+spSIT.TrackerHitCollection = sithitname
+spSIT.TrackerHitAssociationCollection = "SITTrackerHitAssociation"
+spSIT.SpacePointCollection = sitspname
+spSIT.SpacePointAssociationCollection = "SITSpacePointAssociation"
+#spSIT.OutputLevel = DEBUG
+
+spFTD = SpacePointBuilderAlg("FTDBuilder")
+spFTD.TrackerHitCollection = ftdhitname
+spFTD.TrackerHitAssociationCollection = "FTDTrackerHitAssociation"
+spFTD.SpacePointCollection = ftdspname
+spFTD.SpacePointAssociationCollection = "FTDSpacePointAssociation"
+#spFTD.OutputLevel = DEBUG
+
+from Configurables import TPCDigiAlg
+digiTPC = TPCDigiAlg("TPCDigi")
+digiTPC.TPCCollection = "TPCCollection"
+digiTPC.TPCLowPtCollection = "TPCLowPtCollection"
+digiTPC.TPCTrackerHitsCol = tpchitname
+digiTPC.TPCTrackerHitAssCol = "TPCTrackerHitAssociation"
+#digiTPC.OutputLevel = DEBUG
+
+from Configurables import ClupatraAlg
+clupatra = ClupatraAlg("Clupatra")
+clupatra.TPCHitCollection = tpchitname
+#clupatra.OutputLevel = DEBUG
+
+from Configurables import SiliconTrackingAlg
+tracking = SiliconTrackingAlg("SiliconTracking")
+tracking.HeaderCol = "EventHeader"
+tracking.VTXHitCollection = vxdhitname
+tracking.SITHitCollection = sitspname
+tracking.FTDPixelHitCollection = ftdhitname
+tracking.FTDSpacePointCollection = ftdspname
+tracking.SITRawHitCollection = sithitname
+tracking.FTDRawHitCollection = ftdhitname
+tracking.UseSIT = 1
+tracking.SmoothOn = 0
+#tracking.OutputLevel = DEBUG
+
+from Configurables import ForwardTrackingAlg
+forward = ForwardTrackingAlg("ForwardTracking")
+forward.FTDPixelHitCollection = ftdhitname
+forward.FTDSpacePointCollection = ftdspname
+forward.FTDRawHitCollection = ftdhitname
+forward.Chi2ProbCut = 0.0
+forward.HitsPerTrackMin = 3
+forward.BestSubsetFinder = "SubsetSimple"
+forward.Criteria = ["Crit2_DeltaPhi","Crit2_StraightTrackRatio","Crit3_3DAngle","Crit3_ChangeRZRatio","Crit3_IPCircleDist","Crit4_3DAngleChange","Crit4_DistToExtrapolation",
+                    "Crit2_DeltaRho","Crit2_RZRatio","Crit3_PT"]
+forward.CriteriaMin = [0,  0.9,  0,  0.995, 0,  0.8, 0,   20,  1.002, 0.1,      0,   0.99, 0,    0.999, 0,   0.99, 0]
+forward.CriteriaMax = [30, 1.02, 10, 1.015, 20, 1.3, 1.0, 150, 1.08,  99999999, 0.8, 1.01, 0.35, 1.001, 1.5, 1.01, 0.05]
+#forward.OutputLevel = DEBUG
+
+from Configurables import TrackSubsetAlg
+subset = TrackSubsetAlg("TrackSubset")
+subset.TrackInputCollections = ["ForwardTracks", "SiTracks"]
+subset.RawTrackerHitCollections = [vxdhitname, sithitname, ftdhitname, sitspname, ftdspname]
+subset.TrackSubsetCollection = "SubsetTracks"
+#subset.OutputLevel = DEBUG
+
+from Configurables import FullLDCTrackingAlg
+full = FullLDCTrackingAlg("FullTracking")
+full.VTXTrackerHits = vxdhitname
+full.SITTrackerHits = sitspname
+full.TPCTrackerHits = tpchitname
+full.SETTrackerHits = setspname
+full.FTDPixelTrackerHits = ftdhitname
+full.FTDSpacePoints = ftdspname
+full.SITRawHits     = sithitname
+full.SETRawHits     = sethitname
+full.FTDRawHits     = ftdhitname
+full.TPCTracks = "ClupatraTracks"
+full.SiTracks  = "SubsetTracks"
+full.OutputTracks  = "MarlinTrkTracks"
+#full.OutputLevel = DEBUG
+'''
+from Configurables import DumpMCParticleAlg
+dumpMC = DumpMCParticleAlg("DumpMC")
+dumpMC.MCParticleCollection = "MCParticle"
+
+from Configurables import DumpTrackAlg
+dumpFu = DumpTrackAlg("DumpFu")
+dumpFu.TrackCollection = "MarlinTrkTracks"
+#dumpFu.OutputLevel = DEBUG
+
+dumpCl = DumpTrackAlg("DumpCl")
+dumpCl.TrackCollection = "ClupatraTracks"
+#dumpCl.OutputLevel = DEBUG
+
+dumpSu = DumpTrackAlg("DumpSu")
+dumpSu.TrackCollection = "SubsetTracks"
+#dumpSu.OutputLevel = DEBUG
+
+dumpSi = DumpTrackAlg("DumpSi")
+dumpSi.TrackCollection = "SiTracks"
+#dumpSi.OutputLevel = DEBUG
+
+dumpFo = DumpTrackAlg("DumpFo")
+dumpFo.TrackCollection = "ForwardTracks"
+#dumpFo.OutputLevel = DEBUG
+'''
+##############################################################################
+# Calorimeter
+
+from Configurables import SimHitMergeAlg
+simHitMerge = SimHitMergeAlg("SimHitMergeAlg")
+simHitMerge.sanity_check = False
+simHitMerge.InputCollections=["EcalBarrelCollection", "EcalEndcapsCollection","EcalEndcapRingCollection", "HcalBarrelCollection", "HcalEndcapsCollection", "HcalEndcapRingCollection"]
+simHitMerge.OutputCollections=["EcalBarrelCollectionMerged", "EcalEndcapsCollectionMerged", "EcalEndcapRingCollectionMerged", "HcalBarrelCollectionMerged", "HcalEndcapsCollectionMerged", "HcalEndcapRingCollectionMerged"]
+
+# simHitMerge.InputCollections=["EcalBarrelCollection", "EcalEndcapsCollection"]
+# simHitMerge.OutputCollections=["EcalBarrelCollectionMerged", "EcalEndcapsCollectionMerged"]
+##############################################################################
+from Configurables import G2CDArborAlg
+caloDigi = G2CDArborAlg("G2CDArborAlg")
+caloDigi.ReadLCIO = False
+caloDigi.ECALCollections = ["EcalBarrelCollectionMerged", "EcalEndcapsCollectionMerged", "EcalEndcapRingCollectionMerged"]
+caloDigi.HCALCollections = ["HcalBarrelCollectionMerged", "HcalEndcapsCollectionMerged", "HcalEndcapRingCollectionMerged"]
+caloDigi.ECALReadOutNames = ["EcalBarrelCollection", "EcalEndcapsCollection", "EcalEndcapRingCollection"]
+caloDigi.HCALReadOutNames = ["HcalBarrelCollection", "HcalEndcapsCollection", "HcalEndcapRingCollection"]
+caloDigi.DigiECALCollection = ["ECALBarrel", "ECALEndcap", "ECALOther"]
+caloDigi.DigiHCALCollection = ["HCALBarrel", "HCALEndcap", "HCALOther"]
+caloDigi.EventReportEvery = 100
+# caloDigi.CalibrECAL = [46.538, 93.0769]  # Yudan
+caloDigi.CalibrECAL = [48.16, 96.32]
+caloDigi.HCALThreshold = 0.12
+
+caloDigi.PolyaParaA = 1.1
+caloDigi.PolyaParaB = 1.0
+caloDigi.PolyaParaC = 0.0
+##############################################################################
+# Reconstruction: Arbor
+
+from Configurables import MarlinArbor
+marlinArbor = MarlinArbor("MarlinArbor")
+marlinArbor.ReadLCIO = False
+marlinArbor.ECALCollections =["ECALBarrel","ECALEndcap","ECALOther"]
+marlinArbor.HCALCollections =["HCALBarrel","HCALEndcap","HCALOther"]
+marlinArbor.ECALReadOutNames = ["EcalBarrelCollection", "EcalEndcapsCollection", "EcalEndcapRingCollection"]
+marlinArbor.HCALReadOutNames = ["HcalBarrelCollection", "HcalEndcapsCollection", "HcalEndcapRingCollection"]
+##############################################################################
+from Configurables import BushConnect
+bushconnect = BushConnect("BushConnect")
+bushconnect.ReadLCIO = False
+##############################################################################
+# BMR analysis
+from Configurables import TotalInvMass
+totalInvM = TotalInvMass("TotalInvMass")
+totalInvM.TreeOutputFile = "Examples/options/CEPCV4_simu_reco_Arbor_nnHgg_BMRAna.root"
+# totalInvM.TreeOutputFile = "BMRFile"
+totalInvM.MCPCollectionName = "MCParticleGen"
+# totalInvM.MCPCollectionName = "MCParticle"
+##############################################################################
+# write PODIO file
+from Configurables import PodioOutput
+write = PodioOutput("write")
+write.filename = "Examples/options/CEPCV4_simu_reco_Arbor_nnHgg_Reco.root"
+# write.filename = "RecoFile"
+write.outputCommands = ["keep *"]
+##############################################################################
+# ApplicationMgr
+from Configurables import ApplicationMgr
+ApplicationMgr(
+    # TopAlg = [genalg, detsimalg, digiVXD, digiSIT, digiSET, digiFTD, spSIT, spFTD, digiTPC, clupatra, tracking, forward, subset, full, simHitMerge, caloDigi, write],
+    TopAlg = [genalg, detsimalg, digiVXD, digiSIT, digiSET, digiFTD, spSIT, spFTD, digiTPC, clupatra, tracking, forward, subset, full, simHitMerge, caloDigi, marlinArbor, bushconnect, totalInvM, write],
+    EvtSel = 'NONE',
+    EvtMax = 1,
+    ExtSvc = [rndmengine, dsvc, evtseeder, geosvc, gearsvc, tracksystemsvc],
+    HistogramPersistency='ROOT',
+    OutputLevel=INFO
+)
diff --git a/Examples/options/LCIO_read_Arbor.py b/Examples/options/LCIO_read_Arbor.py
new file mode 100644
index 0000000000000000000000000000000000000000..df01a342338a7e5b7411cc2a490e958e9ed648c1
--- /dev/null
+++ b/Examples/options/LCIO_read_Arbor.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+import os
+from Gaudi.Configuration import *
+from Configurables import k4DataSvc
+dsvc = k4DataSvc("EventDataSvc")
+#########################################################################
+# read LCIO files
+from Configurables import LCIOInput
+read = LCIOInput("read")
+read.inputs = [
+"/cefs/higgs/PFAData/Sample/Generator/FullGeo_Baseline/E240_nnH_gg/Reco/Reco_Baseline_E240_nnH_gg_00001_0.slcio"
+]
+read.mode = 1
+read.collections = [
+        "MCParticle:MCParticle",
+        "SimCalorimeterHit:EcalBarrelSiliconCollection",
+        "SimCalorimeterHit:EcalBarrelSiliconPreShowerCollection",
+        "SimCalorimeterHit:EcalEndcapRingCollection",
+        "SimCalorimeterHit:EcalEndcapRingPreShowerCollection",
+        "SimCalorimeterHit:EcalEndcapSiliconCollection",
+        "SimCalorimeterHit:EcalEndcapSiliconPreShowerCollection",
+        "SimCalorimeterHit:HcalBarrelCollection",
+        "SimCalorimeterHit:HcalEndCapRingsCollection",
+        "SimCalorimeterHit:HcalEndCapsCollection",
+        "SimCalorimeterHit:LumiCalCollection",
+        "SimCalorimeterHit:MuonEndCapCollection",
+        "Track:ClupatraTrackSegments",
+        "Track:ClupatraTracks",
+        "Track:ForwardTracks",
+        "Track:MarlinTrkTracks",
+        "Track:SiTracks",
+        "Track:SubsetTracks",
+        "TrackerHit:FTDSpacePoints",
+        "TrackerHit:SETSpacePoints",
+        "TrackerHit:SITSpacePoints",
+        "TrackerHit:TPCTrackerHits",
+        "TrackerHitPlane:FTDPixelTrackerHits",
+        "TrackerHitPlane:FTDStripTrackerHits",
+        "TrackerHitPlane:SETTrackerHits",
+        "TrackerHitPlane:SITTrackerHits",
+        "TrackerHitPlane:VXDTrackerHits",
+        "SimTrackerHit:COILCollection",
+        "SimTrackerHit:FTD_PIXELCollection",
+        "SimTrackerHit:FTD_STRIPCollection",
+        "SimTrackerHit:SETCollection",
+        "SimTrackerHit:SITCollection",
+        "SimTrackerHit:TPCCollection",
+        "SimTrackerHit:TPCSpacePointCollection",
+        "SimTrackerHit:VXDCollection",
+        "CalorimeterHit:LCAL",
+        "CalorimeterHit:LHCAL"
+]
+#########################################################################
+geometry_option = "CepC_v4.xml"
+
+if not os.getenv("DETCEPCV4ROOT"):
+    print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." )
+    sys.exit(-1)
+
+geometry_path = os.path.join(os.getenv("DETCEPCV4ROOT"), "compact", geometry_option)
+if not os.path.exists(geometry_path):
+    print("Can't find the compact geometry file: %s"%geometry_path)
+    sys.exit(-1)
+
+from Configurables import GeomSvc
+geosvc = GeomSvc("GeomSvc")
+geosvc.compact = geometry_path
+########################################################################
+from Configurables import GearSvc
+gearSvc  = GearSvc("GearSvc")
+# gearSvc.GearXMLFile = "Detector/DetCEPCv4/compact/FullDetGear.xml"
+# gearSvc.GearXMLFile = "/cefs/higgs/PFAData/Sample/Generator/FullGeo_Baseline/E240_nnH_gg/Simu/GearOutput.xml"
+gearSvc.GearXMLFile = "Detector/DetCEPCv4/compact/CEPCV4_FullDet_GearOutput.xml"
+##############################################################################
+from Configurables import G2CDArborAlg
+caloDigi = G2CDArborAlg("G2CDArborAlg")
+caloDigi.ReadLCIO = True
+caloDigi.ECALCollections = ["EcalBarrelSiliconCollection","EcalEndcapSiliconCollection","EcalEndcapRingCollection"]
+caloDigi.HCALCollections = ["HcalBarrelCollection","HcalEndCapsCollection","HcalEndCapRingsCollection"]
+caloDigi.DigiECALCollection = ["ECALBarrel","ECALEndcap","ECALOther"]
+caloDigi.DigiHCALCollection = ["HCALBarrel","HCALEndcap","HCALOther"]
+
+caloDigi.CalibrECAL = [48.16, 96.32]
+caloDigi.HCALThreshold = 0.12
+
+caloDigi.PolyaParaA = 1.1
+caloDigi.PolyaParaB = 1.0
+caloDigi.PolyaParaC = 0.0
+
+caloDigi.EventReportEvery = 1
+##############################################################################
+from Configurables import MarlinArbor
+marlinArbor = MarlinArbor("MarlinArbor")
+marlinArbor.ReadLCIO = True
+marlinArbor.ECALCollections =["ECALBarrel","ECALEndcap","ECALOther"]
+marlinArbor.HCALCollections =["HCALBarrel","HCALEndcap","HCALOther"]
+marlinArbor.ECALReadOutNames= ["EcalBarrelCollection","EcalEndcapsCollection","EcalEndcapRingCollection"]
+marlinArbor.HCALReadOutNames= ["HcalBarrelCollection","HcalEndcapsCollection","HcalEndcapRingCollection"]
+##############################################################################
+from Configurables import BushConnect
+bushconnect = BushConnect("BushConnect")
+bushconnect.ReadLCIO = True
+##############################################################################
+from Configurables import TotalInvMass
+totalInvM = TotalInvMass("TotalInvMass")
+totalInvM.TreeOutputFile = "Examples/options/LCIO_read_Arbor_nnHgg_BMRAna.root"
+##############################################################################
+from Configurables import PodioOutput
+write = PodioOutput("write")
+write.filename = "Examples/options/LCIO_read_Arbor_nnHgg_Reco.root"
+write.outputCommands = ["keep *"]
+#########################################################################
+# ApplicationMgr
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [read, caloDigi, marlinArbor, bushconnect, totalInvM, write],
+                EvtSel = 'NONE',
+                EvtMax = 2,
+                ExtSvc = [dsvc, geosvc, gearSvc],
+                OutputLevel=DEBUG
+)
diff --git a/Examples/options/edm4cepc_write.py b/Examples/options/edm4cepc_write.py
new file mode 100644
index 0000000000000000000000000000000000000000..133b24709b7dd83e9d0a4f9953494d81c94ab63f
--- /dev/null
+++ b/Examples/options/edm4cepc_write.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+from Gaudi.Configuration import *
+
+from Configurables import k4DataSvc
+dsvc = k4DataSvc("EventDataSvc")
+
+from Configurables import Edm4cepcWriteAlg
+alg = Edm4cepcWriteAlg("Edm4cepcWriteAlg")
+
+from Configurables import PodioOutput
+out = PodioOutput("out")
+out.filename = "test.root"
+out.outputCommands = ["keep *"]
+
+# ApplicationMgr
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [alg, out],
+                EvtSel = 'NONE',
+                EvtMax = 10,
+                ExtSvc=[dsvc],
+                OutputLevel=DEBUG
+)
diff --git a/Examples/src/Edm4hepTest/Edm4cepcWriteAlg.cpp b/Examples/src/Edm4hepTest/Edm4cepcWriteAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..87b2e219598bc722e8a46581e74a4059d9717a99
--- /dev/null
+++ b/Examples/src/Edm4hepTest/Edm4cepcWriteAlg.cpp
@@ -0,0 +1,57 @@
+/*
+ * Description:
+ *   This algorithm is used to test the EDM4hep extension for cepc.
+ *
+ *   In the extension, we keep the same namespace as edm4hep. 
+ *   The header file path is different.
+ *
+ * Author: 
+ *   Tao Lin <lintao AT ihep.ac.cn>
+ */
+
+#include "k4FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+#include "edm4cepc/RecTofCollection.h"
+
+class Edm4cepcWriteAlg: public GaudiAlgorithm {
+public:
+
+    Edm4cepcWriteAlg(const std::string& name, ISvcLocator* svcLoc)
+        : GaudiAlgorithm(name, svcLoc) {
+
+    }
+
+    StatusCode initialized() {
+
+        return GaudiAlgorithm::initialize();
+    }
+
+    StatusCode execute() {
+
+        auto rectofCol = m_rectofCol.createAndPut();
+
+        for (size_t i = 0; i < 3; ++i) {
+            auto rectof = rectofCol->create();
+
+            rectof.setTime(100.);
+            rectof.setTimeExp({99.,99.5,100,100.5,101});
+            rectof.setSigma(1.);
+            rectof.setPathLength({50,50.5,51,51.5,52});
+            rectof.setPosition({100,100,10});
+        }
+
+        return StatusCode::SUCCESS;
+    }
+
+    StatusCode finalize() {
+
+        return GaudiAlgorithm::finalize();
+    }
+
+private:
+    DataHandle<edm4hep::RecTofCollection> m_rectofCol{"RecTofCollection", Gaudi::DataHandle::Writer, this};
+
+};
+
+DECLARE_COMPONENT(Edm4cepcWriteAlg)
diff --git a/Reconstruction/CMakeLists.txt b/Reconstruction/CMakeLists.txt
index 414e1160d5b422546cd1b4d9b32a556b36567d83..793d8828b8f2d6ee08f04c20dcef10b7e041c78f 100644
--- a/Reconstruction/CMakeLists.txt
+++ b/Reconstruction/CMakeLists.txt
@@ -5,4 +5,4 @@ add_subdirectory(SiliconTracking)
 add_subdirectory(Tracking)
 add_subdirectory(RecGenfitAlg)
 add_subdirectory(RecAssociationMaker)
-add_subdirectory(TofRecAlg)
+add_subdirectory(ParticleID)
diff --git a/Reconstruction/PFA/Arbor/CMakeLists.txt b/Reconstruction/PFA/Arbor/CMakeLists.txt
index 6508c401d98b504e4f462baaaff87302ef95619d..82dc846271f4a64f1cf60e132ad36d135439213d 100644
--- a/Reconstruction/PFA/Arbor/CMakeLists.txt
+++ b/Reconstruction/PFA/Arbor/CMakeLists.txt
@@ -4,20 +4,21 @@ gaudi_add_module(Arbor
                  SOURCES src/Arbor.cc
 		 	src/ArborHit.cc
 		 	src/ArborTool.cc
-		 	src/ArborToolLCIO.cc 
-		 	src/ClusterAna.cc 
-		 	src/DetectorPos.cc 
-		 	src/HelixClassD.cc 
+		 	src/ArborToolLCIO.cc
+		 	src/ClusterAna.cc
+		 	src/DetectorPos.cc
+		 	src/HelixClassD.cc
 			 src/MarlinArbor.cc
 		 	src/BushConnect.cc
                  LINK EventSeeder
                       GearSvc
                       DataHelperLib
+                      DecoderHelperLib
                       DetInterface
                       Gaudi::GaudiKernel
                       k4FWCore::k4FWCore
                       ${LCContent_LIBRARIES}
-                      ${CLHEP_LIBRARIES} 
+                      ${CLHEP_LIBRARIES}
                       ${ROOT_LIBRARIES}
                       ${LCIO_LIBRARIES}
                       ${GEAR_LIBRARIES}
diff --git a/Reconstruction/PFA/Arbor/src/Arbor.cc b/Reconstruction/PFA/Arbor/src/Arbor.cc
index c51a6fae8f51d261d6a4830b8866922d97fcdb25..0e96c3c7e84f40f2e77bce10ec762a795118a094 100644
--- a/Reconstruction/PFA/Arbor/src/Arbor.cc
+++ b/Reconstruction/PFA/Arbor/src/Arbor.cc
@@ -8,19 +8,19 @@
 
 //#define DEBUG
 
-using namespace std; 
+using namespace std;
 
 typedef std::unordered_multimap<unsigned,unsigned> HitLinkMap;
 
 std::vector<ArborHit> cleanedHits;
 
-std::vector<int> LeafHitsIndex; 
-std::vector<int> JointHitsIndex; 
-std::vector<int> StarJointHitsIndex; 
+std::vector<int> LeafHitsIndex;
+std::vector<int> JointHitsIndex;
+std::vector<int> StarJointHitsIndex;
 std::vector<int> IsoHitsIndex;
 std::vector<int> SimpleSeedHitsIndex;
 std::vector<int> StarSeedHitsIndex;
-std::map<int, int> HitsFlag; 	// Tell Hits type; 
+std::map<int, int> HitsFlag; 	// Tell Hits type;
 
 /*
 HitLinkMap BackLinksMap;
@@ -30,15 +30,15 @@ HitLinkMap IterBackLinks;
 
 linkcoll Links;
 linkcoll InitLinks;
-linkcoll IterInputLinks; 
+linkcoll IterInputLinks;
 linkcoll alliterlinks;
-linkcoll links_debug; 
-linkcoll IterLinks; 
-linkcoll IterLinks_1; 
+linkcoll links_debug;
+linkcoll IterLinks;
+linkcoll IterLinks_1;
 branchcoll LengthSortBranchCollection;
-branchcoll Trees; 
+branchcoll Trees;
 
-int NHits = 0; 
+int NHits = 0;
 
 void init() {
 	cleanedHits.clear();
@@ -71,7 +71,7 @@ void HitsCleaning( std::vector<ArborHit> inputHits )
 void HitsClassification( linkcoll inputLinks )
 {
 	int NLinks =  inputLinks.size();
-	
+
 	LeafHitsIndex.clear();
         JointHitsIndex.clear();
 	StarJointHitsIndex.clear();
@@ -106,7 +106,7 @@ void HitsClassification( linkcoll inputLinks )
 		else if(BeginIndex[i1] == 1 && EndIndex[i1] == 1)
 		{
 			JointHitsIndex.push_back(i1);
-			HitsFlag[i1] = 4; 
+			HitsFlag[i1] = 4;
 		}
 		else if(BeginIndex[i1] > 1 && EndIndex[i1] == 1)
 		{
@@ -130,7 +130,7 @@ void HitsClassification( linkcoll inputLinks )
 		}
 		else
 		{
-			cout<<"WARNING: UNCLASSIFIED HITS, Begin Index: "<<BeginIndex[i1]<<",  End Index:  "<<EndIndex[i1]<<endl; 
+			cout<<"WARNING: UNCLASSIFIED HITS, Begin Index: "<<BeginIndex[i1]<<",  End Index:  "<<EndIndex[i1]<<endl;
 		}
         }
 
@@ -139,14 +139,14 @@ void HitsClassification( linkcoll inputLinks )
 	cout<<"Seed - Simple/Star: "<<SimpleSeedHitsIndex.size()<<" : "<<StarSeedHitsIndex.size()<<endl;
 	cout<<"Joint - Simple/Star: "<<JointHitsIndex.size()<<" : "<<StarJointHitsIndex.size()<<endl;
 	cout<<"Leaves: "<<LeafHitsIndex.size()<<endl;
-	cout<<"IsoHits: "<<IsoHitsIndex.size()<<endl; 
-	cout<<"TotalHits: "<<NHits<<endl; 
+	cout<<"IsoHits: "<<IsoHitsIndex.size()<<endl;
+	cout<<"TotalHits: "<<NHits<<endl;
 #endif
 }
 
 linkcoll LinkClean( std::vector<ArborHit> allhits, linkcoll alllinks )
 {
-	linkcoll cleanedlinks; 
+	linkcoll cleanedlinks;
 
 	int NLinks = alllinks.size();
         int Ncurrhitlinks = 0;
@@ -158,7 +158,9 @@ linkcoll LinkClean( std::vector<ArborHit> allhits, linkcoll alllinks )
         std::pair<int, int> SelectedPair;
 
         TVector3 PosA, PosB, PosDiffAB;
-	
+
+        cout<<"[YX debug - LinkClean] Input NLinks = "<<NLinks<<endl;
+
         std::vector< std::vector<int> > LinkHits;
         LinkHits.clear();
         for(int s1 = 0; s1 < NHits; s1++)
@@ -212,11 +214,15 @@ linkcoll LinkClean( std::vector<ArborHit> allhits, linkcoll alllinks )
 
 void BuildInitLink( std::vector<float>Thresholds )
 {
+    cout<<"[YX debug - BuildInitLink] Thresholds = "<<Thresholds[0]<<", "<<Thresholds[1]<<", "<<Thresholds[2]<<", "<<Thresholds[3]<<endl;
+
 	KDTreeLinkerAlgo<unsigned,3> kdtree;
         typedef KDTreeNodeInfoT<unsigned,3> KDTreeNodeInfo;
 	std::array<float,3> minpos{ {0.0f,0.0f,0.0f} }, maxpos{ {0.0f,0.0f,0.0f} };
         std::vector<KDTreeNodeInfo> nodes, found;
 
+    cout<<"[YX debug - BuildInitLink] Input NHits = "<<NHits<<endl;
+
 	for(int i0 = 0; i0 < NHits; ++i0 )
         {
                 const auto& hit = cleanedHits[i0].GetPosition();
@@ -243,26 +249,26 @@ void BuildInitLink( std::vector<float>Thresholds )
         nodes.clear();
 
 	Links.clear();	//all tmp links
-	
-	TVector3 PosA, PosB, PosDiffAB, PosDiffBA; 
+
+	TVector3 PosA, PosB, PosDiffAB, PosDiffBA;
 	int NLayer_A = 0;
-	int NLayer_B = 0; 
-	int NStave_A = 0; 
+	int NLayer_B = 0;
+	int NStave_A = 0;
 	int NStave_B = 0;
 	int SubD_A = 0;
 	int SubD_B = 0;
 	float Depth_A = 0;
-	float Depth_B = 0; 
-	float DisAB = 0; 
-	float MagA = 0; 
+	float Depth_B = 0;
+	float DisAB = 0;
+	float MagA = 0;
 	float MagB = 0;
 	float ECCorr = 0;
 	int FlagTrkPS = 0;
-	int FlagPSEE = 0;	
+	int FlagPSEE = 0;
 	int FlagEH = 0;
 	int FlagHH = 0;
-	int FlagStaveSame = 0; 
-	int FlagStaveDiff = 0; 
+	int FlagStaveSame = 0;
+	int FlagStaveDiff = 0;
 
 	for(int i0 = 0; i0 < NHits; i0++)
 	{
@@ -275,6 +281,11 @@ void BuildInitLink( std::vector<float>Thresholds )
 		SubD_A = cleanedHits[i0].GetSubD();	//SubD_Index, 0 = track endpoint, 1 = Ecal, 2 = Hcal, 3 = EcalPS
 		Depth_A = cleanedHits[i0].GetDepth();
 
+        // cout<<"[YX debug - BuildInitLink] Hit "<<i0<<", NLayer_A = "<<NLayer_A<<", NStave_A = "<<NStave_A<<", SubD_A = "<<SubD_A<<", Depth_A = "<<Depth_A
+            // <<", Pos = ("<<PosA.X()<<", "<<PosA.Y()<<", "<<PosA.Z()<<")"<<endl;
+
+
+
 		const float side = 200;	//could also be sub detector dependent
                 const float xplus(PosA.X() + side), xminus(PosA.X() - side);
                 const float yplus(PosA.Y() + side), yminus(PosA.Y() - side);
@@ -287,33 +298,40 @@ void BuildInitLink( std::vector<float>Thresholds )
                                 zmin, zmax );
                 kdtree.search(searchcube,found);
 
+        // cout<<"[YX debug - BuildInitLink] Hit "<<i0<<", found.size() = "<<found.size()<<endl;
+
+        int nLink_pushback = 0;
+
 		for(unsigned int j0 = 0; j0 < found.size(); j0++)
 		{
 			if( found[j0].data <= (unsigned)i0 ) continue;
 			PosB = cleanedHits[found[j0].data].GetPosition();
 			NLayer_B = cleanedHits[found[j0].data].GetLayer();
-			NStave_B = cleanedHits[found[j0].data].GetStave();	
+			NStave_B = cleanedHits[found[j0].data].GetStave();
 			SubD_B = cleanedHits[found[j0].data].GetSubD();
 			Depth_B = cleanedHits[found[j0].data].GetDepth();
 
 			PosDiffAB = PosA - PosB;
-			PosDiffBA = PosB - PosA; 
-			DisAB = PosDiffAB.Mag();		
-			ECCorr = 0; 
+			PosDiffBA = PosB - PosA;
+			DisAB = PosDiffAB.Mag();
+			ECCorr = 0;
 			if( (fabs(PosA.Z()) - 2600 )*(fabs(PosB.Z()) - 2600) < 0 )
 				ECCorr = 40;
 
+            // cout<<"[YX debug - BuildInitLink] ---> Hit "<<j0<<", NLayer_B = "<<NLayer_B<<", NStave_B = "<<NStave_B<<", SubD_B = "<<SubD_B<<", Depth_B = "<<Depth_B
+            //     <<", Pos = ("<<PosB.X()<<", "<<PosB.Y()<<", "<<PosB.Z()<<"), DisAB = "<<DisAB<<endl;
+
 			// For the XX seed, using triangle method...
 			FlagTrkPS = 0; FlagPSEE = 0; FlagEH = 0; FlagHH = 0; FlagStaveSame = 0; FlagStaveDiff = 0;
 
 			if( SubD_A*SubD_B == 0 && SubD_A + SubD_B == 3 && DisAB < 180 && (PosDiffAB.Angle(PosA) < 0.1 || PosDiffBA.Angle(PosA) < 0.1) )
 				FlagTrkPS = 1;
-			else if( (SubD_A == 1 || SubD_A == 3) && (SubD_B == 1 || SubD_B == 3) && DisAB < Thresholds[0] + 0.05*(Depth_A + Depth_B) )	
-				FlagPSEE = 1; 
+			else if( (SubD_A == 1 || SubD_A == 3) && (SubD_B == 1 || SubD_B == 3) && DisAB < Thresholds[0] + 0.05*(Depth_A + Depth_B) )
+				FlagPSEE = 1;
 			else if( (SubD_A * SubD_B == 2 && DisAB < Thresholds[1] + ECCorr) )
 				FlagEH = 1;
 			else if( SubD_A == 2 && SubD_B == 2 && DisAB < Thresholds[2] + 0.03*(Depth_A + Depth_B) )
-				FlagHH = 1; 
+				FlagHH = 1;
 
 			if( FlagTrkPS || FlagPSEE || FlagEH || FlagHH )
 			{
@@ -343,7 +361,10 @@ void BuildInitLink( std::vector<float>Thresholds )
 			}
 		}
 	}
-	links_debug = Links; 
+	links_debug = Links;
+
+    cout<<"[YX debug - BuildInitLink] Output Links.size() = "<<Links.size()<<endl;
+
 }
 
 void LinkIteration( int time )	//Energy corrections, semi-local correction
@@ -402,25 +423,25 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 	}
 	int NcurrLinks = alliterlinks.size();
 
-	TVector3 hitPos, PosA, PosB, PosDiffAB, PosDiffBA, linkDir; 
-	int NLayer_A = 0; 
-	int NLayer_B = 0; 
+	TVector3 hitPos, PosA, PosB, PosDiffAB, PosDiffBA, linkDir;
+	int NLayer_A = 0;
+	int NLayer_B = 0;
 	int NStave_A = 0;
-	int NStave_B = 0; 
-	int SubD_A = 0; 
+	int NStave_B = 0;
+	int SubD_A = 0;
 	int SubD_B = 0;
 	int FlagEE = 0;
         int FlagHH = 0;
-	int AngleAccIndex = 0; 
+	int AngleAccIndex = 0;
         float DisAB = 0;
-	float MagA = 0; 
+	float MagA = 0;
 	float MagB = 0;
-	std::pair<int, int> currlink; 
-	std::pair<int, int> a_Link; 
+	std::pair<int, int> currlink;
+	std::pair<int, int> a_Link;
 	std::pair<int, int> a_tmpLink, b_tmpLink;
 	int FlagNoJoint = 0;
 	int FlagNoIso = 0;
-//	int FlagNoExisting = 0; 
+//	int FlagNoExisting = 0;
 
 	for(int i = 0; i < NHits; i++)
 	{
@@ -432,16 +453,16 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 
 	// std::vector<int> ---> all the hits linked to this hit
 	std::vector< std::vector<int> > hitLinksArray;
-	hitLinksArray.resize(NHits); 
+	hitLinksArray.resize(NHits);
 	for(int j = 0; j < NcurrLinks; j++)
 	{
 		currlink = alliterlinks[j];
 		PosA = cleanedHits[ currlink.first ].GetPosition();
 		PosB = cleanedHits[ currlink.second ].GetPosition();
 		linkDir = (PosA - PosB);		//Links are always from first point to second - verify
-		linkDir *= 1.0/linkDir.Mag(); 
+		linkDir *= 1.0/linkDir.Mag();
 		RefDir[currlink.first] += 4*linkDir; 	//Weights... might be optimized...
-		RefDir[currlink.second] += 6*linkDir; 
+		RefDir[currlink.second] += 6*linkDir;
 		Nin_hit[currlink.first] ++;
 		Nout_hit[currlink.second] ++;
 		hitLinksArray[currlink.first].push_back(currlink.second);
@@ -469,16 +490,16 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
                                 zmin, zmax );
                 kdtree.search(searchcube,found);
 
-		for(unsigned int j1 = 0; j1 < found.size(); j1++)	
+		for(unsigned int j1 = 0; j1 < found.size(); j1++)
 		{
 			if( found[j1].data <= (unsigned)i1 ) continue;
 
 			FlagNoJoint = Nout_hit[j1] * Nin_hit[i1] * Nout_hit[i1] * Nin_hit[j1];
 			FlagNoIso = Nout_hit[j1] + Nin_hit[i1] + Nout_hit[i1] + Nin_hit[j1];
-			a_tmpLink.first = i1; 
-			a_tmpLink.second = j1; 
-			b_tmpLink.first = j1; 
-			b_tmpLink.second = i1; 
+			a_tmpLink.first = i1;
+			a_tmpLink.second = j1;
+			b_tmpLink.first = j1;
+			b_tmpLink.second = i1;
 
 			bool isConnected = false;
 
@@ -510,24 +531,24 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 
 			if( FlagNoJoint == 0 && FlagNoIso != 0 )
 			{
-				if(!isConnected) 
-				{	
+				if(!isConnected)
+				{
 					PosB = cleanedHits[found[j1].data].GetPosition();
 					NLayer_B = cleanedHits[found[j1].data].GetLayer();
 					NStave_B = cleanedHits[found[j1].data].GetStave();
 					SubD_B = cleanedHits[found[j1].data].GetSubD();
-					PosDiffAB = PosB - PosA; 
-					PosDiffBA = PosA - PosB; 
-					DisAB = PosDiffAB.Mag();			
+					PosDiffAB = PosB - PosA;
+					PosDiffBA = PosA - PosB;
+					DisAB = PosDiffAB.Mag();
 
-					FlagEE = 0; 
-					FlagHH = 0; 
+					FlagEE = 0;
+					FlagHH = 0;
 					AngleAccIndex = 0;
 
 					if( PosDiffAB.Angle(RefDir[i1]) < 0.6/time )
 						AngleAccIndex = 1;
 					else if( PosDiffAB.Angle(RefDir[j1]) < 0.6/time )
-						AngleAccIndex = 2; 
+						AngleAccIndex = 2;
 					else if( PosDiffBA.Angle(RefDir[i1]) < 0.6/time )
 						AngleAccIndex = 3;
 					else if( PosDiffBA.Angle(RefDir[j1]) < 0.6/time )
@@ -547,7 +568,7 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 						MagB = PosB.Mag();
 
 					//	if(NLayer_A != NLayer_B)
-					//	{	
+					//	{
 							if( NStave_A != NStave_B || ( NLayer_A == 0 && NLayer_B != 0 ) || ( NLayer_B == 0 && NLayer_A != 0 ) )
 							{
 								if( MagA > MagB && AngleAccIndex < 3 )
@@ -581,7 +602,7 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 					//	}
 					}
 				}
-			} 
+			}
 		}
 	}
 
@@ -589,11 +610,11 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 
 	int NLinks = alliterlinks.size();
 	int MinAngleIndex = -10;
-	int Ncurrhitlinks = 0; 
-	float MinAngle = 1E6; 
+	int Ncurrhitlinks = 0;
+	float MinAngle = 1E6;
 	float tmpOrder = 0;
-	float DirAngle = 0; 
-	std::pair<int, int> SelectedPair; 
+	float DirAngle = 0;
+	std::pair<int, int> SelectedPair;
 
 	std::vector< std::vector<int> > LinkHits;
 	LinkHits.clear();
@@ -639,7 +660,7 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 			if(SelectedPair.first == SelectedPair.second)
 			{
 				cout<<"WTTTTTTTTFFFFFFFFFFFFFF"<<endl;
-				continue; 
+				continue;
 			}
 			if(time == 1)
 			{
@@ -651,7 +672,7 @@ void LinkIteration( int time )	//Energy corrections, semi-local correction
 				IterBackLinks.emplace(SelectedPair.second,SelectedPair.first);
 			}
 		}
-	}	
+	}
 
 #ifdef DEBUG
 	cout<<"Init-Iter Size "<<InitLinks.size()<<" : "<<IterLinks.size()<<endl;
@@ -693,7 +714,7 @@ void BranchBuilding(float SeedThreshold)
 		if(HitBeginIndex[i2] == 0 && HitEndIndex[i2] == 1)        //EndPoint
 		{
 			NBranches ++;
-			std::vector<int> currBranchhits;      //array of indexes 
+			std::vector<int> currBranchhits;      //array of indexes
 
 			iterhitindex = i2;
 			currBranchhits.push_back(i2);
@@ -711,7 +732,7 @@ void BranchBuilding(float SeedThreshold)
 						iterhitindex = PairIterator.first;
 						break;
 					}
-				}  
+				}
 				*/
 				auto iterlink_range = IterBackLinks.equal_range(iterhitindex);
 				assert( std::distance(iterlink_range.first,iterlink_range.second) == 1 );
@@ -902,22 +923,22 @@ void BushMerging()
 std::vector< std::vector<int> > Arbor( std::vector<ArborHit> inputHits, std::vector<float>Thresholds )
 {
 	//cout<<"Thresholds"<<Thresholds[0]<<" "<<Thresholds[1]<<" "<<Thresholds[2]<<endl;
-	
+
 	if(Thresholds.size() != 4)
 	{
-		cout<<"Threshold Set Wrong, Threshold Size is "<<Thresholds.size()<<" Should be 4"<<endl; 
-		exit(2); 
+		cout<<"Threshold Set Wrong, Threshold Size is "<<Thresholds.size()<<" Should be 4"<<endl;
+		exit(2);
 	}
 
-	init();	
+	init();
 	HitsCleaning(inputHits);
 	BuildInitLink(Thresholds);
 	InitLinks = LinkClean( cleanedHits, Links );
 
 	LinkIteration(1);
 	LinkIteration(2);
-	HitsClassification(IterLinks);	
-	BranchBuilding(Thresholds[3]);	
+	HitsClassification(IterLinks);
+	BranchBuilding(Thresholds[3]);
 
 	return LengthSortBranchCollection;
 }
diff --git a/Reconstruction/PFA/Arbor/src/ArborToolLCIO.cc b/Reconstruction/PFA/Arbor/src/ArborToolLCIO.cc
index 6a1e0cc20da795c05f1e7bc328060f5b232f91a8..4725b56c9552cab7a33b02663739cb6aae4731a1 100644
--- a/Reconstruction/PFA/Arbor/src/ArborToolLCIO.cc
+++ b/Reconstruction/PFA/Arbor/src/ArborToolLCIO.cc
@@ -9,6 +9,9 @@
 #include <stdexcept>
 #include <sstream>
 
+#include "DDSegmentation/MegatileLayerGridXY.h"
+#include "DecoderHelper/DD4hep2Lcio.h"
+
 #include "TVector3.h"
 #include <string>
 #include <iostream>
@@ -31,6 +34,7 @@
 #include "DD4hep/IDDescriptor.h"
 #include "DD4hep/Plugins.h"
 
+#include "cellIDDecoder.h"
 #include <DDRec/DetectorData.h>
 #include <DDRec/CellIDPositionConverter.h>
 #include "DetInterface/IGeomSvc.h"
@@ -38,7 +42,61 @@
 #include "podio/podioVersion.h"
 
 using namespace std;
-/* 
+// bool _USE_LCIO=0;
+
+// struct segInfo;
+struct segInfo {
+    double megaTileSizeX = 0;
+    double megaTileSizeY = 0;
+    double megaTileOffsetX = 0;
+    double megaTileOffsetY = 0;
+    unsigned int nCellsX = 0;
+    unsigned int nCellsY = 0;
+    segInfo() = default;
+};
+
+struct SegParameters {
+//   unsigned int layer;
+//   unsigned int tile;
+  double sizex;
+  double sizey;
+  double offsetx;
+  double offsety;
+  unsigned int ncellsx;
+  unsigned int ncellsy;
+};
+
+class MyMegatileLayerGridXY: public dd4hep::DDSegmentation::MegatileLayerGridXY {
+public:
+    int get_nCellsX(){
+        return _unif_nCellsX;
+    }
+
+    SegParameters getSegParameters(){
+        SegParameters Pars;
+        // Pars.layer = 1;
+        // Pars.tile = 2;
+        Pars.sizex = _megaTileSizeX;
+        Pars.sizey = _megaTileSizeY;
+        Pars.offsetx = _megaTileOffsetX;
+        Pars.offsety = _megaTileOffsetY;
+        Pars.ncellsx = _unif_nCellsX;
+        Pars.ncellsy = _unif_nCellsY;
+        return Pars;
+    }
+
+    std::map < std::pair < unsigned int, unsigned int > , segInfo > get_specialMegaTiles_layerWafer(){
+        return specialMegaTiles_layerWafer;
+    }
+    // void setSpecialMegaTile( unsigned int layer, unsigned int tile,
+    //                         double sizex, double sizey,
+    //                         double offsetx, double offsety,
+    //                         unsigned int ncellsx, unsigned int ncellsy );
+
+
+};
+
+/*
 void ClusterBuilding( LCEvent * evtPP, std::string Name, std::vector<CalorimeterHit*> Hits, std::vector< std::vector<int> > BranchOrder, int DHCALFlag )
 {
 	LCCollection *currbranchcoll = new LCCollectionVec(LCIO::CLUSTER);
@@ -51,8 +109,8 @@ void ClusterBuilding( LCEvent * evtPP, std::string Name, std::vector<Calorimeter
 	float currBranchEnergy = 0;
 	TVector3 SeedPos, currPos;
 	float MinMag = 1E9;
-	float currMag = 0; 
-	float ECALTotalEn = 0; 
+	float currMag = 0;
+	float ECALTotalEn = 0;
 	float HCALTotalEn = 0;
 
 	for(int i0 = 0; i0 < NBranch; i0++)
@@ -113,12 +171,14 @@ void ClusterBuilding( LCEvent * evtPP, std::string Name, std::vector<Calorimeter
 */
 
 
-ArborToolLCIO::ArborToolLCIO(const std::string& name,ISvcLocator* svcLoc)
+ArborToolLCIO::ArborToolLCIO(const std::string& name,ISvcLocator* svcLoc, bool m_readLCIO)
      : GaudiAlgorithm(name, svcLoc)
 {
 	m_geosvc=service<IGeomSvc>("GeomSvc");
+    m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6";
+    _USE_LCIO = m_readLCIO;
 }
-	
+
 
 ArborToolLCIO::~ArborToolLCIO()
 {
@@ -135,10 +195,12 @@ void ArborToolLCIO::ClusterBuilding( DataHandle<edm4hep::ClusterCollection>& _cu
 	TVector3 SeedPos, currPos;
 
 	float MinMag = 1E9;
-	float currMag = 0; 
-	float ECALTotalEn = 0; 
+	float currMag = 0;
+	float ECALTotalEn = 0;
 	float HCALTotalEn = 0;
 
+    cout<<"[YX debug - ClusterBuilding] NBranch = "<<NBranch<<endl;
+
 	for(int i0 = 0; i0 < NBranch; i0++)
 	{
 		auto a_branch=currbranchcoll->create();
@@ -149,6 +211,10 @@ void ArborToolLCIO::ClusterBuilding( DataHandle<edm4hep::ClusterCollection>& _cu
 		HCALTotalEn = 0;
 		MinMag = 1E9;
 
+
+        // cout<<"[YX debug - ClusterBuilding] Branch "<<i0<<", BranchSize = "<<BranchSize<<endl;
+
+
 		for(int j = 0; j < BranchSize; j++)
 		{
 			auto a_hit= Hits[currbranchorder[j]];
@@ -189,6 +255,10 @@ void ArborToolLCIO::ClusterBuilding( DataHandle<edm4hep::ClusterCollection>& _cu
 
 	}
 
+
+	int nBranch_out = currbranchcoll->size();
+    cout<<"[YX debug - ClusterBuilding] nBranch_out = "<<nBranch_out<<endl;
+
 }
 
 
@@ -215,10 +285,25 @@ int ArborToolLCIO::NHScaleV2( std::vector<edm4hep::CalorimeterHit> clu0, int Rat
 		auto hit = clu0[i];
 		auto cellid = hit.getCellID();
 
+        if(_USE_LCIO){
+	      		ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+	      		const std::string idCodingString(m_encoder_str);
+	      		const std::string layerCoding(GetLayerCoding(idCodingString));
+	      		const std::string cellICoding(GetCellICoding(idCodingString));
+	      		const std::string cellJCoding(GetCellJCoding(idCodingString));
+
+			tmpI=cellIdDecoder(&hit)[cellICoding.c_str()]/RatioX;
+			tmpJ=cellIdDecoder(&hit)[cellJCoding.c_str()]/RatioY;
+			tmpK=(cellIdDecoder(&hit)[layerCoding.c_str()]+1)/RatioZ;
+		}
 
+		else{
 		tmpI = m_decoder->get(cellid, "cellX")/RatioX;
 		tmpJ = m_decoder->get(cellid, "cellY")/RatioY;
 		tmpK = (m_decoder->get(cellid, "layer")+1)/RatioZ;
+
+
+        }
 		tmpEn = hit.getEnergy();
 
 		NewCellID0 = (tmpK<<24) + (tmpJ<<12) + tmpI;
@@ -251,8 +336,8 @@ float ArborToolLCIO::FDV2( std::vector<edm4hep::CalorimeterHit> clu)
 		FractalDim += 0.1 * TMath::Log(float(OriNHit)/NReSizeHit[j])/TMath::Log(float(Scale[j]));
 	}
 
-	if(clu.size() == 0) 
-		FractalDim = -1; 
+	if(clu.size() == 0)
+		FractalDim = -1;
 
 	return FractalDim;
 }
@@ -269,24 +354,169 @@ int ArborToolLCIO::NHScaleV3( edm4hep::Cluster clu0, int RatioX, int RatioY, int
 	float tmpEn = 0;
 	int NewCellID0 = 0;
 	int NewCellID1 = 0;
-	//m_geosvc=service<IGeomSvc>("GeomSvc");	
+	//m_geosvc=service<IGeomSvc>("GeomSvc");
 
-	m_decoder = m_geosvc->getDecoder("EcalBarrelCollection");
-	if(!m_decoder) m_decoder = m_geosvc->getDecoder("EcalEndcapsCollection");
+	m_decoder = m_geosvc->getDecoder("EcalBarrelCollection");  // raw_system==20
+	// if(!m_decoder) m_decoder = m_geosvc->getDecoder("EcalEndcapsCollection");
+
+
+    // ----------------------------------------------------------------------------
+    dd4hep::Detector* m_dd4hep = m_geosvc->lcdd();
+    if ( !m_dd4hep ) throw "ArborToolLCIO: Failed to get dd4hep::Detector ...";
+    dd4hep::Readout readout = m_dd4hep->readout("EcalBarrelCollection");
+
+    // auto m_segmentation = dynamic_cast<dd4hep::DDSegmentation::MegatileLayerGridXY*>(readout.segmentation().segmentation());
+    auto m_segmentation = static_cast<MyMegatileLayerGridXY*>(readout.segmentation().segmentation());
+    auto m_segPars = m_segmentation->getSegParameters();
+    auto m_seg = m_segmentation->get_specialMegaTiles_layerWafer();
+
+    // std::cout<<m_segmentation<<std::endl;
+    if(0) std::cout<<"get_nCellsX = "<<m_segmentation->get_nCellsX()<<std::endl;
+    if(0) std::cout<<"m_segPars->ncellsx = "<<m_segPars.ncellsx<<std::endl;
+    // ----------------------------------------------------------------------------
 
 	std::map <double, float> testIDtoEnergy;
 	double testlongID = 0;
-	
+
 	for(int i = 0; i < NumHit; i++)
 	{
 		auto hit = clu0.getHits(i);
 		auto cellid = hit.getCellID();
-
-		tmpI = m_decoder->get(cellid, "cellX")/RatioX;
-		tmpJ = m_decoder->get(cellid, "cellY")/RatioY;
-		tmpK = (m_decoder->get(cellid, "layer")+1)/RatioZ;
 		tmpEn = hit.getEnergy();
 
+        if(_USE_LCIO){
+            ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+            const std::string idCodingString(m_encoder_str);
+            const std::string layerCoding(GetLayerCoding(idCodingString));
+            const std::string cellICoding(GetCellICoding(idCodingString));
+            const std::string cellJCoding(GetCellJCoding(idCodingString));
+
+			tmpI=cellIdDecoder(&hit)[cellICoding.c_str()]/RatioX;
+			tmpJ=cellIdDecoder(&hit)[cellJCoding.c_str()]/RatioY;
+			tmpK=(cellIdDecoder(&hit)[layerCoding.c_str()]+1)/RatioZ;
+		}
+		else{
+            // initial decoder: ECAL barrel
+            // <id>system:5,module:3,stave:4,tower:5,layer:6,wafer:6,cellX:32:-16,cellY:-16</id>
+	        m_decoder = m_geosvc->getDecoder("EcalBarrelCollection");  // raw_system==20
+            int raw_system = m_decoder->get(cellid, "system");
+            int raw_module = m_decoder->get(cellid, "module");
+            int raw_stave = m_decoder->get(cellid, "stave");
+            int raw_layer = m_decoder->get(cellid, "layer");
+            int raw_cellX = m_decoder->get(cellid, "cellX");
+            int raw_cellY = m_decoder->get(cellid, "cellY");
+            int raw_tower = m_decoder->get(cellid, "tower");
+            int raw_wafer = m_decoder->get(cellid, "wafer");
+
+        	if(raw_system==29){  // ECAL endcap
+                // <id>system:5,module:3,stave:4,tower:5,layer:6,wafer:6,x:32:-16,y:-16</id>
+                m_decoder = m_geosvc->getDecoder("EcalEndcapsCollection");
+                raw_stave = m_decoder->get(cellid, "stave");
+                raw_layer = m_decoder->get(cellid, "layer");
+                raw_cellX = m_decoder->get(cellid, "x");
+                raw_cellY = m_decoder->get(cellid, "y");
+                raw_tower = m_decoder->get(cellid, "tower");
+                raw_wafer = m_decoder->get(cellid, "wafer");
+            }else if(raw_system==22){  // HCAL barrel
+                // <id>system:5,module:3,stave:3,tower:5,layer:6,slice:4,x:32:-16,y:-16</id>
+                m_decoder = m_geosvc->getDecoder("HcalBarrelCollection");
+                raw_stave = m_decoder->get(cellid, "stave");
+                raw_layer = m_decoder->get(cellid, "layer");
+                raw_cellX = m_decoder->get(cellid, "x");
+                raw_cellY = m_decoder->get(cellid, "y");
+            }else if(raw_system==30){  // HCAL endcap
+                // <id>system:5,module:3,stave:3,tower:5,layer:6,y:32:-16,x:-16</id>
+                m_decoder = m_geosvc->getDecoder("HcalEndcapsCollection");
+                raw_stave = m_decoder->get(cellid, "stave");
+                raw_layer = m_decoder->get(cellid, "layer");
+                raw_cellX = m_decoder->get(cellid, "y");
+                raw_cellY = m_decoder->get(cellid, "x");
+            }
+
+
+
+            // ---------------------------------------------
+            std::pair<unsigned int, unsigned int> layer_wafer = std::make_pair(raw_layer, raw_wafer);
+            // segInfo seginfo = m_seg.find(layer_wafer);
+            // ---------------------------------------------
+
+            TVector3 currHitPos =  TVector3(hit.getPosition().x, hit.getPosition().y, hit.getPosition().z);
+            double hitposx = currHitPos.X();
+            double hitposy = currHitPos.Y();
+            double hitposz = currHitPos.Z();
+            double hitposp = currHitPos.Perp();
+
+            // ---------------------------------------------
+
+            int new_layer = DD4hep2Lcio::CEPCv4::getEcalLayer(raw_layer);
+            int new_stave = DD4hep2Lcio::CEPCv4::getEcalBarrelStave(raw_stave);
+            if(raw_system==29){// ECAL endcap
+                new_stave = DD4hep2Lcio::CEPCv4::getEcalEndcapStave(raw_stave);
+            }
+            if(raw_system==22 || raw_system==30){  // HCAL, barrel 22, endcap 30
+                new_layer = DD4hep2Lcio::CEPCv4::getHcalLayer(raw_layer);
+                new_stave = DD4hep2Lcio::CEPCv4::getHcalStave(raw_stave);
+            }
+
+            int new_I = raw_cellX;
+            int new_J = raw_cellY;
+            int new_K = new_layer;
+
+            int nwaferx = (raw_wafer-1)/2;
+            int nwafery = raw_wafer%2 ==0 ? 1 : 0;
+            int ncellsx = 9;
+            int ncellsy = 9;
+            // int cellX_constant = raw_cellX<0 ? 4 : 0;
+            // int cellY_constant = raw_cellY<0 ? 4 : 0;
+            int cellX_constant = 0;
+            int cellY_constant = 0;
+
+
+            // if(raw_system==20 || raw_system==22){  // barrel, ECAL 20, HCAL 22
+            if(raw_system==20){  // barrel, ECAL 20
+                new_I = raw_cellX + nwaferx * 9 + cellX_constant;
+                new_J = (8-raw_cellY) + (4-raw_tower) * 2 * 9 + (1-nwafery) * 9 + cellY_constant;
+
+            // }else if(raw_system==29 || raw_system==30){  // endcap, ECAL 29, HCAL 30
+            }else if(raw_system==29){  // endcap, ECAL 29
+                // new_I = raw_cellX + raw_tower * 2 * 9 + nwaferx * 9 + 4;
+                // new_J = raw_cellY + nwafery * 9 + 4;
+
+                new_I = raw_cellY + raw_tower * 2 * 9 + nwafery * 9 + 4;
+                new_J = raw_cellX + nwaferx * 9 + 4;
+            }
+
+            if(0){
+
+                cout<<"\n[ArborToolLCIO::NHScaleV3] Hit Pos ("<<hitposx<<", "<<hitposy<<", "<<hitposz<<", "<<hitposp<<")mm:"<<endl;
+
+                cout<<"[ArborToolLCIO::NHScaleV3] ---> Raw M = "<<raw_module<<", stave = "<<raw_stave<<", layer = "<<raw_layer<<", I(x) = "<<raw_cellX<<", J(y) = "<<raw_cellY<<", wafer = "<<raw_wafer<<", tower = "<<raw_tower<<", system = "<<raw_system<<endl;
+
+                cout<<"[ArborToolLCIO::NHScaleV3] ------> system = "<<raw_system<<", layer = "<<raw_layer<<", tower = "<<raw_tower<<", wafer = "<<raw_wafer<<", nwaferx = "<<nwaferx<<", nwafery = "<<nwafery<<", ncellsx = "<<ncellsx<<", ncellsy = "<<ncellsx<<", const x = "<<cellX_constant<<", y = "<<cellY_constant<<endl;
+
+                cout<<"[ArborToolLCIO::NHScaleV3] ---> New M = "<<raw_module<<", stave = "<<new_stave<<", layer = "<<new_layer<<", I(x) = "<<new_I<<", J(y) = "<<new_J<<", wafer = "<<raw_wafer<<", tower = "<<raw_tower<<", system = "<<raw_system<<endl;
+
+
+                // cout<<"[ArborToolLCIO::NHScaleV3] ---> megaTileSizeX = "<<seginfo.megaTileSizeX<<", megaTileSizeY = "<<seginfo.megaTileSizeY<<", megaTileOffsetX = "<<seginfo.megaTileOffsetX<<", megaTileOffsetY = "<<seginfo.megaTileOffsetY<<", nCellsX = "<<seginfo.nCellsX<<", nCellsY = "<<seginfo.nCellsY<<endl;
+                // cout<<"[ArborToolLCIO::NHScaleV3] ---> sizex = "<<m_segPars.sizex<<", sizey = "<<m_segPars.sizey<<", offsetx = "<<m_segPars.offsetx<<", offsety = "<<m_segPars.offsety<<", ncellsx = "<<m_segPars.ncellsx<<", ncellsy = "<<m_segPars.ncellsy<<endl;
+            }
+
+            // ----------------------------------------------------------------------------
+            // tmpI = m_decoder->get(cellid, "cellX")/RatioX;
+            // tmpJ = m_decoder->get(cellid, "cellY")/RatioY;
+            // tmpK = (m_decoder->get(cellid, "layer")+1)/RatioZ;
+
+            tmpI = new_I/RatioX;
+            tmpJ = new_J/RatioY;
+            tmpK = (new_K+1)/RatioZ;
+
+        }
+
+        if(0) cout<<"[ArborToolLCIO::NHScaleV3] ---> RatioX = "<<RatioX<<", RatioY = "<<RatioY<<", RatioZ = "<<RatioZ<<endl;
+        if(0) cout<<"[ArborToolLCIO::NHScaleV3] ---> tmpI = "<<tmpI<<", tmpJ = "<<tmpJ<<", tmpK = "<<tmpK<<endl;
+
+
+
 		NewCellID0 = (tmpK<<24) + (tmpJ<<12) + tmpI;
 
 		testlongID = NewCellID1*1073741824 + NewCellID0;
@@ -327,14 +557,14 @@ float ArborToolLCIO::FDV3( edm4hep::Cluster clu ){
 
 float ArborToolLCIO::BushDis( edm4hep::Cluster clu1, edm4hep::Cluster clu2)
 {
-	float DisBetweenBush = 1.0E10; 
+	float DisBetweenBush = 1.0E10;
 
 	int cluSize1 = clu1.hits_size();
 	int cluSize2 = clu2.hits_size();
 
-	TVector3 HitPos1, HitPos2; 
-	TVector3 PosDiff; 
-	// TVector3 XXXPos; 
+	TVector3 HitPos1, HitPos2;
+	TVector3 PosDiff;
+	// TVector3 XXXPos;
 
 	for(int i = 0; i < cluSize1; i++)
 	{
@@ -352,41 +582,41 @@ float ArborToolLCIO::BushDis( edm4hep::Cluster clu1, edm4hep::Cluster clu2)
 	}
 
 
-	return DisBetweenBush; 
+	return DisBetweenBush;
 }
 
 
 float ArborToolLCIO::DisPointToBush(TVector3 Pos1, edm4hep::Cluster clu1)
 {
-	float Dis = 1.0E9; 
+	float Dis = 1.0E9;
 	float HitDis = 1.0E8;
 	int clusize = clu1.hits_size();
 
-	TVector3 HitPos; 
+	TVector3 HitPos;
 
 	for(int s = 0; s < clusize; s++)
 	{
 		HitPos = TVector3((clu1.getHits(s)).getPosition().x,(clu1.getHits(s)).getPosition().y,(clu1.getHits(s)).getPosition().z);
 		HitDis = (HitPos - Pos1).Mag();
-		if(HitDis < Dis) 
+		if(HitDis < Dis)
 		{
-			Dis = HitDis; 
+			Dis = HitDis;
 		}
 	}
 
-	return Dis; 
+	return Dis;
 }
 
 
 TVector3 ArborToolLCIO::ClusterCoG(edm4hep::Cluster inputCluster)
 {
-	TVector3 CenterOfGravity; 
+	TVector3 CenterOfGravity;
 
 	int inputClusterSize = inputCluster.hits_size();
 
-	TVector3 tmphitPos; 
+	TVector3 tmphitPos;
 	float tmphitEnergy;
-	float sumhitEnergy = 0; 
+	float sumhitEnergy = 0;
 
 	for(int i = 0; i < inputClusterSize; i++)
 	{
@@ -395,12 +625,12 @@ TVector3 ArborToolLCIO::ClusterCoG(edm4hep::Cluster inputCluster)
 		tmphitEnergy = tmpHit.getEnergy();
 
 		CenterOfGravity += tmphitPos*tmphitEnergy;
-		sumhitEnergy += tmphitEnergy; 
+		sumhitEnergy += tmphitEnergy;
 	}
 
-	CenterOfGravity = 1.0/sumhitEnergy * CenterOfGravity; 
+	CenterOfGravity = 1.0/sumhitEnergy * CenterOfGravity;
 
-	return CenterOfGravity; 
+	return CenterOfGravity;
 }
 
 
@@ -410,10 +640,10 @@ edm4hep::ClusterCollection* ArborToolLCIO::ClusterVecColl( std::vector<edm4hep::
 	edm4hep::ClusterCollection* vec_coll_Clusters = m_clucol.createAndPut();
 
 	int NClu = inputClusters.size();
-	int CurrBranchSize = 0; 
-	TVector3 SeedPos; 
-	std::vector<float> CluEn; 
-	std::vector<int> CluIndex; 
+	int CurrBranchSize = 0;
+	TVector3 SeedPos;
+	std::vector<float> CluEn;
+	std::vector<int> CluIndex;
 
 	for(int i0 = 0; i0 < NClu; i0++)
 	{
@@ -448,7 +678,7 @@ edm4hep::ClusterCollection* ArborToolLCIO::ClusterVecColl( std::vector<edm4hep::
 
 std::vector<edm4hep::Cluster> ArborToolLCIO::CollClusterVec(const edm4hep::ClusterCollection * input_coll )
 {
-	std::vector<edm4hep::Cluster> outputClusterVec; 
+	std::vector<edm4hep::Cluster> outputClusterVec;
 
 
 	outputClusterVec.clear();
@@ -459,7 +689,7 @@ std::vector<edm4hep::Cluster> ArborToolLCIO::CollClusterVec(const edm4hep::Clust
 		outputClusterVec.push_back(a_clu);
 	}
 
-	return outputClusterVec; 
+	return outputClusterVec;
 }
 
 
@@ -468,7 +698,7 @@ void ArborToolLCIO::NaiveCluConst(edm4hep::MutableCluster a0_clu,edm4hep::Mutabl
 	b0_clu.setPosition(a0_clu.getPosition());
 	b0_clu.setEnergy(a0_clu.getEnergy());
 	int NCaloHit = a0_clu.hits_size();
-	float HitEn = 0; 
+	float HitEn = 0;
 	float SubDEn[6] = {0, 0, 0, 0, 0, 0};
 
 	for(int t0 = 0; t0 < NCaloHit; t0++)
@@ -481,7 +711,7 @@ void ArborToolLCIO::NaiveCluConst(edm4hep::MutableCluster a0_clu,edm4hep::Mutabl
 			SubDEn[1] += HitEn;
 		}
 		else
-		{	
+		{
 			SubDEn[0] += HitEn;
 		}
 	}
@@ -490,7 +720,7 @@ void ArborToolLCIO::NaiveCluConst(edm4hep::MutableCluster a0_clu,edm4hep::Mutabl
 	{
 		b0_clu.addToSubdetectorEnergies(SubDEn[i]);
 	}
-	
+
 }
 
 
@@ -500,7 +730,7 @@ edm4hep::Cluster ArborToolLCIO::NaiveCluImpl(edm4hep::MutableCluster a0_clu)
 	b0_clu.setPosition(a0_clu.getPosition());
 	b0_clu.setEnergy(a0_clu.getEnergy());
 	int NCaloHit = a0_clu.hits_size();
-	float HitEn = 0; 
+	float HitEn = 0;
 	float SubDEn[6] = {0, 0, 0, 0, 0, 0};
 
 	for(int t0 = 0; t0 < NCaloHit; t0++)
@@ -513,7 +743,7 @@ edm4hep::Cluster ArborToolLCIO::NaiveCluImpl(edm4hep::MutableCluster a0_clu)
 			SubDEn[1] += HitEn;
 		}
 		else
-		{	
+		{
 			SubDEn[0] += HitEn;
 		}
 	}
@@ -522,8 +752,8 @@ edm4hep::Cluster ArborToolLCIO::NaiveCluImpl(edm4hep::MutableCluster a0_clu)
 	{
 		b0_clu.addToSubdetectorEnergies(SubDEn[i]);
 	}
-	
-	return b0_clu; 
+
+	return b0_clu;
 }
 
 std::vector<edm4hep::CalorimeterHit> ArborToolLCIO::CollHitVec(const edm4hep::CalorimeterHitCollection * input_coll, float EnergyThreshold)
@@ -545,23 +775,28 @@ std::vector<edm4hep::CalorimeterHit> ArborToolLCIO::CollHitVec(const edm4hep::Ca
 }
 
 
-std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::vector<edm4hep::Cluster> MainClusters, std::vector<edm4hep::CalorimeterHit> IsoHits, float DisThreshold )	// Projective Distance + Hit Depth correlation; 
+std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::vector<edm4hep::Cluster> MainClusters, std::vector<edm4hep::CalorimeterHit> IsoHits, float DisThreshold )	// Projective Distance + Hit Depth correlation;
 {
 	std::vector<edm4hep::MutableCluster> outputClusterVec;
 
 	int N_Core = MainClusters.size();
 	int N_Hit = IsoHits.size();
 	TVector3 HitPos, MBSeedPos;
-	float currHitCoreDis = 0;  
-	float MinHitCoreDis = 1.0E10; 
-	int MinDisIndex = -1; 
+	float currHitCoreDis = 0;
+	float MinHitCoreDis = 1.0E10;
+	int MinDisIndex = -1;
 	std::vector<std::pair<int, int> > Frag_Core_Links;
 	std::pair<int, int> a_frag_core_link;
 
+
+    double ESum_IsoHit = 0;
+    double ESum_Core = 0;
+
+
 	for(int i0 = 0; i0 < N_Hit; i0++)
 	{
 		auto a_hit = IsoHits[i0];
-		HitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);		
+		HitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 		MinHitCoreDis = 1.0E10;
 
 		for(int j0 = 0; j0 < N_Core; j0++)
@@ -570,7 +805,7 @@ std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::v
 			currHitCoreDis = DisPointToBush(HitPos, a_core);
 			if(currHitCoreDis < MinHitCoreDis)
 			{
-				MinHitCoreDis = currHitCoreDis; 
+				MinHitCoreDis = currHitCoreDis;
 				MinDisIndex = j0;
 			}
 		}
@@ -580,11 +815,14 @@ std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::v
 			a_frag_core_link.second = MinDisIndex;
 			Frag_Core_Links.push_back(a_frag_core_link);
 		}
+
+        ESum_IsoHit += a_hit.getEnergy();
+
 	}
 
 	int N_frag_core_links = Frag_Core_Links.size();
 	std::vector<edm4hep::CalorimeterHit> tomerge_hits;
-	float ClusterEn = 0; 
+	float ClusterEn = 0;
 
 	for(int i2 = 0; i2 < N_Core; i2 ++)
 	{
@@ -601,7 +839,7 @@ std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::v
 			}
 		}
 		edm4hep::MutableCluster a_mergedfrag_core;
-		ClusterEn = 0; 
+		ClusterEn = 0;
 
 		for(unsigned int j2 = 0; j2 < a_core.hits_size(); j2++)
 		{
@@ -624,9 +862,17 @@ std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterHitAbsorbtion( std::v
 		a_mergedfrag_core.setPhi( MBSeedPos.Phi()  );
 
 		outputClusterVec.push_back(a_mergedfrag_core);
+
+
+        ESum_Core += ClusterEn;
+        // cout<<"[YX debug - ClusterHitAbsorbtion] Core "<<i2<<", merged E = "<<ClusterEn<<endl;
+
 	}
 
-	return outputClusterVec; 
+    cout<<"[YX debug - ClusterHitAbsorbtion] N_Core = "<<N_Core<<", N_IsoHit = "<<N_Hit<<", ESum_IsoHit = "<<ESum_IsoHit<<", ESum_Core = "<<ESum_Core<<endl;
+
+
+	return outputClusterVec;
 }
 
 
@@ -634,10 +880,10 @@ void ArborToolLCIO::NaiveMergeCluConst(std::vector<edm4hep::Cluster> inputCluVec
 {
 
 	int NClu = inputCluVec.size();
-	float SeedDis = 1E9; 
-	float MaxDis = 0; 
-	float MergedCluEnergy = 0; 
-	float HitEn = 0; 
+	float SeedDis = 1E9;
+	float MaxDis = 0;
+	float MergedCluEnergy = 0;
+	float HitEn = 0;
 	float SubDEn[6] = {0, 0, 0, 0, 0, 0};
 
 	TVector3 CurrSeedPos, SeedPos, CurrHitPos, CluEndPos, CluRefDir;	//Seed Depth... CoG Comp...
@@ -650,7 +896,7 @@ void ArborToolLCIO::NaiveMergeCluConst(std::vector<edm4hep::Cluster> inputCluVec
 
 		if(CurrSeedPos.Mag() < SeedDis)
 		{
-			SeedPos = CurrSeedPos; 
+			SeedPos = CurrSeedPos;
 			SeedDis = CurrSeedPos.Mag();
 		}
 
@@ -662,19 +908,19 @@ void ArborToolLCIO::NaiveMergeCluConst(std::vector<edm4hep::Cluster> inputCluVec
 			MergedClu.addToHits(a_hit);
 			CurrHitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 			HitEn = a_hit.getEnergy();
-			if(fabs(HitEn - DHCALCalibrationConstant) < 1.0E-6)	// ECAL, HCAL, Should use better criteria. 
+			if(fabs(HitEn - DHCALCalibrationConstant) < 1.0E-6)	// ECAL, HCAL, Should use better criteria.
 			{
-				SubDEn[1] += HitEn; 
+				SubDEn[1] += HitEn;
 			}
 			else
 			{
-				SubDEn[0] += HitEn; 
+				SubDEn[0] += HitEn;
 			}
 
 			if(CurrHitPos.Mag() > MaxDis)
 			{
 				MaxDis = CurrHitPos.Mag();
-				CluEndPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);	
+				CluEndPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 			}
 		}
 	}
@@ -699,10 +945,10 @@ edm4hep::MutableCluster ArborToolLCIO::NaiveMergeClu(std::vector<edm4hep::Cluste
 	edm4hep::MutableCluster MergedClu;
 
 	int NClu = inputCluVec.size();
-	float SeedDis = 1E9; 
-	float MaxDis = 0; 
-	float MergedCluEnergy = 0; 
-	float HitEn = 0; 
+	float SeedDis = 1E9;
+	float MaxDis = 0;
+	float MergedCluEnergy = 0;
+	float HitEn = 0;
 	float SubDEn[6] = {0, 0, 0, 0, 0, 0};
 
 	TVector3 CurrSeedPos, SeedPos, CurrHitPos, CluEndPos, CluRefDir;	//Seed Depth... CoG Comp...
@@ -715,7 +961,7 @@ edm4hep::MutableCluster ArborToolLCIO::NaiveMergeClu(std::vector<edm4hep::Cluste
 
 		if(CurrSeedPos.Mag() < SeedDis)
 		{
-			SeedPos = CurrSeedPos; 
+			SeedPos = CurrSeedPos;
 			SeedDis = CurrSeedPos.Mag();
 		}
 
@@ -727,19 +973,19 @@ edm4hep::MutableCluster ArborToolLCIO::NaiveMergeClu(std::vector<edm4hep::Cluste
 			MergedClu.addToHits(a_hit);
 			CurrHitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 			HitEn = a_hit.getEnergy();
-			if(fabs(HitEn - DHCALCalibrationConstant) < 1.0E-6)	// ECAL, HCAL, Should use better criteria. 
+			if(fabs(HitEn - DHCALCalibrationConstant) < 1.0E-6)	// ECAL, HCAL, Should use better criteria.
 			{
-				SubDEn[1] += HitEn; 
+				SubDEn[1] += HitEn;
 			}
 			else
 			{
-				SubDEn[0] += HitEn; 
+				SubDEn[0] += HitEn;
 			}
 
 			if(CurrHitPos.Mag() > MaxDis)
 			{
 				MaxDis = CurrHitPos.Mag();
-				CluEndPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);	
+				CluEndPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 			}
 		}
 	}
@@ -772,14 +1018,14 @@ std::vector<edm4hep::MutableCluster> ArborToolLCIO::ClusterAbsorbtion( std::vect
 
 	//tag minimal distance
 
-	float MinFragCoreDis = 1.0E10; 
+	float MinFragCoreDis = 1.0E10;
 	float CurrFragCoreDis = 0;
-	int MinDisIndex = -1;  
+	int MinDisIndex = -1;
 	std::vector<std::pair<int, int> > Frag_Core_Links;
 	std::pair<int, int> a_frag_core_link;
 	std::map<int, int> TouchedFrag;
 	TouchedFrag.clear();
-	TVector3 fragPos; 
+	TVector3 fragPos;
 
 	for(int i0 = 0; i0 < N_frag; i0 ++)
 	{
@@ -868,7 +1114,7 @@ edm4hep::ClusterCollection* ArborToolLCIO::ClusterVecMerge( std::vector<edm4hep:
 #endif
 
 
-	TVector3 tmpClusterSeedPos, MBSeedPos;	
+	TVector3 tmpClusterSeedPos, MBSeedPos;
 
 	int CurrBranchSize = 0;
 	float SeedPosMin = 1.0E10;
@@ -925,7 +1171,7 @@ edm4hep::ClusterCollection* ArborToolLCIO::ClusterVecMerge( std::vector<edm4hep:
 					auto tmpHit = tmpMergebranch.getHits(j1);
 					branchtmp.addToHits(tmpHit);
 				}
-				
+
 			}
 			branchtmp.setPosition( Mainbranch.getPosition() );
 			branchtmp.setEnergy(BranchEnergy);
@@ -942,10 +1188,10 @@ edm4hep::ClusterCollection* ArborToolLCIO::ClusterVecMerge( std::vector<edm4hep:
 }
 int ArborToolLCIO::JointsBetweenBush(edm4hep::Cluster a_Clu, edm4hep::Cluster b_Clu, float CellSize)
 {
-	int NJoint = 0; 
+	int NJoint = 0;
 	int a_CluSize = a_Clu.hits_size();
 	int b_CluSize = b_Clu.hits_size();
-	TVector3 aHitPos, bHitPos, PosDiff, aCluPos, bCluPos; 	
+	TVector3 aHitPos, bHitPos, PosDiff, aCluPos, bCluPos;
 	aCluPos = TVector3(a_Clu.getPosition().x,a_Clu.getPosition().y,a_Clu.getPosition().z);
 	bCluPos = TVector3(b_Clu.getPosition().x,b_Clu.getPosition().y,b_Clu.getPosition().z);
 
@@ -957,7 +1203,7 @@ int ArborToolLCIO::JointsBetweenBush(edm4hep::Cluster a_Clu, edm4hep::Cluster b_
 		{
 			auto bhit = b_Clu.getHits(j);
 			bHitPos = TVector3(bhit.getPosition().x,bhit.getPosition().y,bhit.getPosition().z);
-			PosDiff = aHitPos - bHitPos; 
+			PosDiff = aHitPos - bHitPos;
 			if(PosDiff.Mag() < 1.5*CellSize)	//allow Diag connect... else use 1.2
 			{
 				// if((aCluPos - bHitPos).Mag() < 60 || (bCluPos - aHitPos).Mag() < 60)
@@ -966,7 +1212,7 @@ int ArborToolLCIO::JointsBetweenBush(edm4hep::Cluster a_Clu, edm4hep::Cluster b_
 		}
 	}
 
-	return NJoint; 
+	return NJoint;
 }
 
 
@@ -1029,7 +1275,7 @@ float ArborToolLCIO::SimpleBushTimeTrackClu(edm4hep::Track a_trk, edm4hep::Clust
 int ArborToolLCIO::SimpleBushNC(edm4hep::Track  a_trk, edm4hep::Cluster  a_clu)
 {
 	float Distance = 1.0E9;
-	//float Time = 0; 
+	//float Time = 0;
 	int NC = 0;
 	float BushDist[3] = {0, 0 ,0};
 	HelixClassD * a_Helix = new HelixClassD();
@@ -1065,7 +1311,7 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 	//       non-matched     111
 	//  HAD: matched         211
 	//       non-matched     212
-	
+
 	int CluIDFlag = 999;
 	int ClusterID = 211;
 	int EcalNHit, HcalNHit, NLEcal, NLHcal, NH[16];
@@ -1220,7 +1466,19 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 			auto a_hit = a_tree.getHits(s1);
 			allhits.push_back(a_hit);
 			auto cellid= a_hit.getCellID();
-			int NLayer =  m_decoder->get(cellid, "layer");
+			// int NLayer =  m_decoder->get(cellid, "layer");
+            int NLayer;
+
+			if(_USE_LCIO){
+		      		ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+		      		const std::string idCodingString(m_encoder_str);
+		      		const std::string layerCoding(GetLayerCoding(idCodingString));
+				NLayer=cellIdDecoder(&a_hit)[layerCoding.c_str()]+1;
+			}
+
+			else{
+				NLayer =  m_decoder->get(cellid, "layer");
+			}
 
 			HitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 
@@ -1307,11 +1565,11 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 				else if(NLayer < 15)
 				{
 					EH_3.push_back(a_hit);
-				} 
+				}
 				else if(NLayer < 20)
 				{
 					EH_4.push_back(a_hit);
-				} 
+				}
 				else if(NLayer < 25)
 				{
 					EH_5.push_back(a_hit);
@@ -1378,7 +1636,7 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 
 		NLEcal = ActiveLayers(Ecalhits);
 		NLHcal = ActiveLayers(Hcalhits);
-		cout<<"NLEcal "<<NLEcal<<" "<<Ecalhits.size()<<" "<<endl;
+		if(0) cout<<"NLEcal "<<NLEcal<<" "<<Ecalhits.size()<<" "<<endl;
 
 
 		float sum_NHE = 0, sum_NHH = 0;
@@ -1408,7 +1666,7 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 		rms_Ecal = 0;
 		rms_Hcal = 0;
 		rms_Ecal2 = 0;
-		rms_Hcal2 = 0;	
+		rms_Hcal2 = 0;
 		for(int r0 = 0; r0 < 16; r0++)
 		{
 			if(r0 < 6)
@@ -1539,21 +1797,36 @@ int ArborToolLCIO::ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk)
 
 int ArborToolLCIO::ActiveLayers(  std::vector<edm4hep::CalorimeterHit> clu )
 {
-	std::vector<int> hitlayers; 
+	std::vector<int> hitlayers;
 	hitlayers.clear();
 
-	int NHits = clu.size();	
+	int NHits = clu.size();
 	int tmpK = 0;	//Layer Number
-	int tmpS = 0; 
+	int tmpS = 0;
 	int tmpID = 0;
-	
+
 	for(int i = 0; i < NHits; i++)
 	{
 		auto hit = clu[i];
 		auto cellid= hit.getCellID();
+
+
+		if(_USE_LCIO){
+	      		ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+	      		const std::string idCodingString(m_encoder_str);
+	      		const std::string layerCoding(GetLayerCoding(idCodingString));
+	      		const std::string staveCoding(GetStaveCoding(idCodingString));
+
+
+			tmpK=cellIdDecoder(&hit)[layerCoding.c_str()]+1;
+			tmpS=cellIdDecoder(&hit)[staveCoding.c_str()]+1;
+		}
+
+		else{
 		tmpK = m_decoder->get(cellid, "layer")+1 ;
 		tmpS = m_decoder->get(cellid, "stave")+1 ;
-		// cout<<"tmpK "<<tmpK<<endl; 
+        }
+		// cout<<"tmpK "<<tmpK<<endl;
 		tmpID = tmpS * 50 + tmpK;
 
 		if( std::find(hitlayers.begin(), hitlayers.end(), tmpID) == hitlayers.end() )
@@ -1568,9 +1841,9 @@ int ArborToolLCIO::ActiveLayers(  std::vector<edm4hep::CalorimeterHit> clu )
 
 float ArborToolLCIO::ClusterT0(edm4hep::Cluster a_Clu)
 {
-	float T0 = 1E9; 
-	float tmpTime = 0; 
-	TVector3 CluHitPos; 
+	float T0 = 1E9;
+	float tmpTime = 0;
+	TVector3 CluHitPos;
 	for(unsigned int i = 0; i < a_Clu.hits_size(); i++)
 	{
 		auto a_hit = a_Clu.getHits(i);
@@ -1579,7 +1852,7 @@ float ArborToolLCIO::ClusterT0(edm4hep::Cluster a_Clu)
 		tmpTime = a_hit.getTime() - 1.0/300*CluHitPos.Mag();
 		if(tmpTime < T0 && tmpTime > 0)
 		{
-			T0 = tmpTime; 
+			T0 = tmpTime;
 		}
 	}
 	return T0;
@@ -1591,19 +1864,21 @@ int ArborToolLCIO::newPhotonTag(edm4hep::Cluster a_clu)
 	int flag=0;
 
 	TVector3 PosClu = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
-	float Depth = 0; 
+	float Depth = 0;
 	Depth = DisSeedSurface(PosClu);
 
 	int CluSize= a_clu.hits_size();
 	float ClusFD=FDV3(a_clu);
 	float ClusT0=ClusterT0(a_clu);
 
-	
+    // cout<<"[YX debug - newPhotonTag] CluSize = "<<CluSize<<", ClusFD = "<<ClusFD<<", ClusT0 = "<<ClusT0<<", Depth = "<<Depth<<endl;
+
+
 	if(ClusFD>0.18*TMath::Log((float)CluSize)-0.53&&ClusFD<0.16*TMath::Log((float)CluSize)+0.025&&ClusFD>-0.2*TMath::Log((float)CluSize)+0.4&&((log10(ClusT0)<-2&&log10(Depth)<2&&log10(CluSize)>2)||(log10(ClusT0)<-1.5&&log10(CluSize)<2)))
 	{
 		flag=1;
 	}
-	
+
 
 	return flag;
 
@@ -1619,7 +1894,7 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 	float avEnDisHtoL;
 	float EcalEn, HcalEn, EClu, cluDepth, maxDepth, minDepth, FD_all, FD_ECAL, FD_HCAL;
 	float FD_ECALF10;
-	
+
 
 	TVector3 CluPos;
 	CluPos = TVector3(a_tree.getPosition().x,a_tree.getPosition().y,a_tree.getPosition().z);
@@ -1686,7 +1961,18 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 		auto a_hit = a_tree.getHits(s1);
 		allhits.push_back(a_hit);
 		auto cellid = a_hit.getCellID();
-		int NLayer = m_decoder->get(cellid, "layer");
+		// int NLayer = m_decoder->get(cellid, "layer");
+        int NLayer;
+		if(_USE_LCIO){
+	      		ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+	      		const std::string idCodingString(m_encoder_str);
+	      		const std::string layerCoding(GetLayerCoding(idCodingString));
+			NLayer=cellIdDecoder(&a_hit)[layerCoding.c_str()]+1;
+		}
+
+		else{
+			NLayer = m_decoder->get(cellid, "layer");
+		}
 		float tmpHitEn = a_hit.getEnergy();
 		HitPos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 
@@ -1762,7 +2048,7 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 	bool cute3;
 	if (x < 0.9)  cute3 = FD_ECALF10 > 0.3/sqrt(sqrt(0.9))*sqrt(sqrt(0.9-x));
 	else cute3 = 1;
-	bool cute4 = HcalNHit/EClu < 0.3;                
+	bool cute4 = HcalNHit/EClu < 0.3;
 	bool cute;
 	cute = cute1 && cute2 && cute3 && cute4;
 
@@ -1777,7 +2063,7 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 	if(currCluNHits <= 4) ClusterID = 1;
 	else if(cute) ClusterID = 11;
 	else if (cutmu)  ClusterID = 13;
-	else 
+	else
 	{
 		bool cutef1 = FD_HCAL == -1;
 		bool cutef2 = minDepth < 50;
@@ -1793,7 +2079,7 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 		bool cutef;
 
 		cutef = (cutef1 && cutef2 && cutef3 && cutef3b && cutef4) || cutef5;
-		if(cutef) ClusterID = 11;  
+		if(cutef) ClusterID = 11;
 	}
 
 	if(ClusterID == 211)
@@ -1804,7 +2090,7 @@ int ArborToolLCIO::ClusterFlag1st(edm4hep::Cluster a_tree)
 		bool cutmuf = cutmuf1 || (cutmuf2 && cutmuf3);
 		if(cutmuf) ClusterID = 13;
 		else if(minDepth < 0.77+0.23*EClu) ClusterID = 211;
-		else ClusterID = 2; 
+		else ClusterID = 2;
 	}
 
 	return ClusterID;
@@ -1849,11 +2135,11 @@ float ArborToolLCIO::ClusterEE(edm4hep::Cluster inputCluster)
 				tmpCluEn += hitEn;
 			}
 		}
-		
+
 		EnCorrector = 1;
 		if(tmpCluEn > 1.5 && tmpCluEn < 22 && 1 == 0)
 		{
-			EnCorrector = 0.6*(1 + 1.0/log10(tmpCluEn)); 
+			EnCorrector = 0.6*(1 + 1.0/log10(tmpCluEn));
 		}
 		ClusterEnergy = tmpCluEn*EnCorrector;
 		//ClusterEnergy = HADClusterEE(tmpCluEn,inputCluster);
@@ -1876,17 +2162,29 @@ float ArborToolLCIO::EMClusterEE( edm4hep::Cluster inputCluster )
 	float _costheta = 0;
 	float Ethetacorr = 1;
 	float Ephicorr = 1;
-	float EMC = inputCluster.getEnergy(); 
-	TVector3 CluPos = TVector3(inputCluster.getPosition().x,inputCluster.getPosition().y,inputCluster.getPosition().z); 
+	float EMC = inputCluster.getEnergy();
+	TVector3 CluPos = TVector3(inputCluster.getPosition().x,inputCluster.getPosition().y,inputCluster.getPosition().z);
 	float CluTheta = CluPos.Theta();
-	float CluPhi = CluPos.Phi()*5.72957795130823229e+01;	
-	
+	float CluPhi = CluPos.Phi()*5.72957795130823229e+01;
+
 	int NCluHits = inputCluster.hits_size();
 	for(int s1 = 0; s1 < NCluHits; s1++)
 	{
 		auto a_hit = inputCluster.getHits(s1);
 		auto cellid=a_hit.getCellID();
-		int NLayer = m_decoder->get(cellid, "layer");
+		// int NLayer = m_decoder->get(cellid, "layer");
+
+        int NLayer;
+		if(_USE_LCIO){
+	      		ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+	      		const std::string idCodingString(m_encoder_str);
+	      		const std::string layerCoding(GetLayerCoding(idCodingString));
+			NLayer=cellIdDecoder(&a_hit)[layerCoding.c_str()]+1;
+		}
+
+		else{
+			NLayer = m_decoder->get(cellid, "layer");
+		}
 		if(NLayer > 20){
 			if (NLayer%2 ==0){
 				ArNhite10 ++;
@@ -1953,16 +2251,16 @@ float ArborToolLCIO::EMClusterEE( edm4hep::Cluster inputCluster )
 
 std::vector<float> ArborToolLCIO::ClusterTime(edm4hep::Cluster inputCluster)
 {
-	std::vector<float> CluTimeVector; 
+	std::vector<float> CluTimeVector;
 	CluTimeVector.clear();
 
 	int NHit = inputCluster.hits_size();
 	float currhitTime = 0;
-	float currhitoriTime = 0; 
-	TVector3 hitpos; 
+	float currhitoriTime = 0;
+	TVector3 hitpos;
 
 	std::vector<float> Time;
-	Time.clear(); 
+	Time.clear();
 	std::map<int, float> CluHitToTime;
 	CluHitToTime.clear();
 	std::vector<float> OriginalTime;
@@ -1976,8 +2274,8 @@ std::vector<float> ArborToolLCIO::ClusterTime(edm4hep::Cluster inputCluster)
 		hitpos = TVector3(a_hit.getPosition().x,a_hit.getPosition().y,a_hit.getPosition().z);
 		if(a_hit.getTime() == 0)
 		{
-			currhitTime = 1001;	
-			currhitoriTime = 1001; 
+			currhitTime = 1001;
+			currhitoriTime = 1001;
 		}
 		else
 		{
@@ -1987,17 +2285,17 @@ std::vector<float> ArborToolLCIO::ClusterTime(edm4hep::Cluster inputCluster)
 		}
 		Time.push_back( currhitTime );
 		OriginalTime.push_back( currhitoriTime );
-		CluHitToTime[i] = currhitTime;			
+		CluHitToTime[i] = currhitTime;
 	}
 
 	std::vector<int> TimeOrder = SortMeasure(Time, 0);
 	std::vector<int> OriTimeOrder = SortMeasure(OriginalTime, 0);
 	float PeakTime = 0;
-	float AverageTime = 0; 
-	int NCount = 0; 
-	float ptime = 0; 
-	int Break = 0; 
-	TVector3 StartP, EndP, hitP; 
+	float AverageTime = 0;
+	int NCount = 0;
+	float ptime = 0;
+	int Break = 0;
+	TVector3 StartP, EndP, hitP;
 
 	for(int j0= 0; j0 < N_PropTimeHit; j0++)
 	{
@@ -2037,22 +2335,22 @@ std::vector<float> ArborToolLCIO::ClusterTime(edm4hep::Cluster inputCluster)
 			{
 				if( Break == 0 )
 				{
-					PeakTime += ptime; 
-					NCount ++; 
+					PeakTime += ptime;
+					NCount ++;
 				}
-			}	
+			}
 			else
 			{
 				Break = 1;
 			}
 		}
 
-		AverageTime += ptime; 
+		AverageTime += ptime;
 	}
 	if(NCount)
-		PeakTime = float(PeakTime)/NCount; 
+		PeakTime = float(PeakTime)/NCount;
 
-	CluTimeVector.push_back(float(AverageTime)/NHit);	
+	CluTimeVector.push_back(float(AverageTime)/NHit);
 	CluTimeVector.push_back(PeakTime);
 	CluTimeVector.push_back(NCount);
 	if( N_PropTimeHit > 1 )	// Direction: Cos Theta Between Time Flow And Position
@@ -2060,9 +2358,65 @@ std::vector<float> ArborToolLCIO::ClusterTime(edm4hep::Cluster inputCluster)
 	else
 		CluTimeVector.push_back(1001);
 
-	return CluTimeVector; 
+	return CluTimeVector;
 }
 
 
+std::string ArborToolLCIO::GetStaveCoding(const std::string &encodingString) const
+{
+     if (encodingString.find("stave") != std::string::npos)
+	  return std::string("stave");
+
+     if (encodingString.find("S-1") != std::string::npos)
+	  return std::string("S-1");
+
+     if (encodingString.find("S") != std::string::npos)
+	  return std::string("S");
+
+     return std::string("unknown_stave_encoding");
+}
+
+std::string ArborToolLCIO::GetLayerCoding(const std::string &encodingString) const
+{
+     if (encodingString.find("layer") != std::string::npos)
+	  return std::string("layer");
+
+     if (encodingString.find("K-1") != std::string::npos)
+	  return std::string("K-1");
+
+     if (encodingString.find("K") != std::string::npos)
+	  return std::string("K");
+
+     return std::string("unknown_layer_encoding");
+}
+
+
+std::string ArborToolLCIO::GetCellICoding(const std::string &encodingString) const
+{
+     if (encodingString.find("cell_x") != std::string::npos)
+	  return std::string("cell_x");
+
+     if (encodingString.find("I-1") != std::string::npos)
+	  return std::string("I-1");
+
+     if (encodingString.find("I") != std::string::npos)
+	  return std::string("I");
+
+     return std::string("unknown_cellI_encoding");
+}
+
+std::string ArborToolLCIO::GetCellJCoding(const std::string &encodingString) const
+{
+     if (encodingString.find("cell_y") != std::string::npos)
+	  return std::string("cell_y");
+
+     if (encodingString.find("J-1") != std::string::npos)
+	  return std::string("J-1");
+
+     if (encodingString.find("J") != std::string::npos)
+	  return std::string("J");
+
+     return std::string("unknown_cellJ_encoding");
+}
 
 
diff --git a/Reconstruction/PFA/Arbor/src/ArborToolLCIO.hh b/Reconstruction/PFA/Arbor/src/ArborToolLCIO.hh
index 8a5a13d9fb3c9e9361f6f4c22613d3d298aae221..b61955b46336a3556c4c3000288f514e48bfb0d3 100644
--- a/Reconstruction/PFA/Arbor/src/ArborToolLCIO.hh
+++ b/Reconstruction/PFA/Arbor/src/ArborToolLCIO.hh
@@ -12,7 +12,7 @@
 #include "edm4hep/CalorimeterHitCollection.h"
 #include "edm4hep/VertexCollection.h"
 #include "edm4hep/TrackCollection.h"
-#include "edm4hep/MCParticle.h" 
+#include "edm4hep/MCParticle.h"
 #include "edm4hep/MCParticleCollection.h"
 #include "edm4hep/MCRecoCaloAssociation.h"
 #include "edm4hep/MCRecoTrackerAssociation.h"
@@ -51,81 +51,89 @@ public:
 class ArborToolLCIO  : public GaudiAlgorithm
 {
 	public:
-		ArborToolLCIO(const std::string& name, ISvcLocator* svcLoc);
+		ArborToolLCIO(const std::string& name, ISvcLocator* svcLoc,  bool m_readLCIO);
 		//ArborToolLCIO(ISvcLocator* svcLoc);
 		~ArborToolLCIO();
 		typedef DataHandle<edm4hep::Cluster>  ClusterType;
 
+        // bool _USE_LCIO;
 
-		void Clean(); 
+
+    void Clean();
 	void ClusterBuilding(DataHandle<edm4hep::ClusterCollection>& _currbranchcoll, std::vector<edm4hep::CalorimeterHit> Hits, branchcoll BranchOrder, int DHCALFlag);
-	
+
 	float ClusterT0(edm4hep::Cluster a_Clu);
 
 	int NHScaleV2( std::vector<edm4hep::CalorimeterHit> clu0, int RatioX, int RatioY, int RatioZ );
 	float FDV2( std::vector<edm4hep::CalorimeterHit> clu);
-	
+
 	int NHScaleV3( edm4hep::Cluster clu0, int RatioX, int RatioY, int RatioZ );
-	
+
 	float FDV3( edm4hep::Cluster clu);
-	
+
 	int ActiveLayers(  std::vector<edm4hep::CalorimeterHit> clu );
-	
+
 	float BushDis( edm4hep::Cluster clu1, edm4hep::Cluster clu2);
-	
-	
+
+
 	float* SimpleDisTrackClu(edm4hep::Track a_trk, edm4hep::Cluster a_clu);
-	
+
 	float SimpleBushTimeTrackClu(edm4hep::Track a_trk, edm4hep::Cluster a_clu);
-	
+
 	int SimpleBushNC(edm4hep::Track a_trk, edm4hep::Cluster a_clu);
-	
+
 	float DisPointToBush( TVector3 Pos1, edm4hep::Cluster clu1);
-	
+
 	TVector3 ClusterCoG(edm4hep::Cluster inputCluser);
-	
+
 	edm4hep::ClusterCollection* ClusterVecMerge( std::vector<edm4hep::Cluster> inputClusters, TMatrixF ConnectorMatrix, DataHandle<edm4hep::ClusterCollection>& clucol );
-	
+
 	edm4hep::ClusterCollection* ClusterVecColl( std::vector<edm4hep::MutableCluster> inputClusters, DataHandle<edm4hep::ClusterCollection>& m_clucol);
 
 	edm4hep::Cluster NaiveCluImpl(edm4hep::MutableCluster a0_clu);
 	void NaiveCluConst(edm4hep::MutableCluster a0_clu, edm4hep::MutableCluster b0_clu);
-	
+
 	std::vector<edm4hep::Cluster> CollClusterVec(const edm4hep::ClusterCollection * input_coll );
-	
+
 	std::vector<edm4hep::CalorimeterHit> CollHitVec(const edm4hep::CalorimeterHitCollection * input_coll, float EnergyThreshold);
-	
+
 	std::vector<edm4hep::MutableCluster> ClusterHitAbsorbtion( std::vector<edm4hep::Cluster> MainClusters, std::vector<edm4hep::CalorimeterHit> IsoHits, float DisThreshold );
-	
+
 	edm4hep::MutableCluster NaiveMergeClu(std::vector<edm4hep::Cluster> inputCluVec);
 
 	void NaiveMergeCluConst(std::vector<edm4hep::Cluster> inputCluVec,edm4hep::MutableCluster MergedClu);
 	std::vector<edm4hep::MutableCluster> ClusterAbsorbtion( std::vector<edm4hep::Cluster> MainClusters, std::vector<edm4hep::MutableCluster> FragClusters, float thresholds, float DepthSlope );
-	
-	
+
+
 	int JointsBetweenBush(edm4hep::Cluster a_Clu, edm4hep::Cluster b_Clu, float CellSize);
-	
+
 	TVector3 CluEndP(edm4hep::Cluster a_clu);
-	
+
 	int ClusterFlag(edm4hep::Cluster a_tree, edm4hep::Track a_trk);
-	
+
 	int ClusterFlag1st(edm4hep::Cluster a_tree);
-	
+
 	int newPhotonTag(edm4hep::Cluster a_clu);
 	float ClusterEE(edm4hep::Cluster inputCluster);
-	
+
 	float EMClusterEE( edm4hep::Cluster inputCluster );
-	
+
 	std::vector<float> ClusterTime(edm4hep::Cluster inputCluster);
 
+    std::string GetCellICoding(const std::string &encodingString) const;
+    std::string GetCellJCoding(const std::string &encodingString) const;
+    std::string GetStaveCoding(const std::string &encodingString) const;
+    std::string GetLayerCoding(const std::string &encodingString) const;
+
 	private:
 	SmartIF<IGeomSvc> m_geosvc;//=service<IGeomSvc>("GeomSvc");
 	dd4hep::DDSegmentation::BitFieldCoder*	m_decoder;// = m_geosvc->getDecoder("ECALBarrel");
 
 
+    std::string m_encoder_str;
 //	m_geosvc= service<IGeomSvc>("GeomSvc");
 //	m_decoder = m_geosvc->getDecoder("ECALBarrel");
-	
+    bool _USE_LCIO;
 
 };
 #endif //
diff --git a/Reconstruction/PFA/Arbor/src/BushConnect.cc b/Reconstruction/PFA/Arbor/src/BushConnect.cc
index 052f49db319d300059ca6da58751798102b4c557..5ba4be966f37ac3d2946ef0c6342ff2e8be5fe0b 100644
--- a/Reconstruction/PFA/Arbor/src/BushConnect.cc
+++ b/Reconstruction/PFA/Arbor/src/BushConnect.cc
@@ -2,6 +2,7 @@
 #include "ArborTool.h"
 #include "ArborToolLCIO.hh"
 #include "DetectorPos.hh"
+#include "HelixClassD.hh"
 
 #include "k4FWCore/DataHandle.h"
 #include "GaudiAlg/GaudiAlgorithm.h"
@@ -45,7 +46,6 @@
 #include <vector>
 #include <algorithm>
 
-#include "HelixClassD.hh"		
 
 using namespace std;
 
@@ -63,13 +63,16 @@ BushConnect::BushConnect(const std::string& name, ISvcLocator* svcLoc)
 StatusCode BushConnect::initialize() {
 
       ISvcLocator* svcloc = serviceLocator();
-      m_ArborToolLCIO=new ArborToolLCIO("arborTools",svcloc);
+      m_ArborToolLCIO=new ArborToolLCIO("arborTools",svcloc, m_readLCIO);
+    //   m_ArborToolLCIO->_USE_LCIO = m_readLCIO;
 //printParameters();
 	//Cluflag.setBit(LCIO::CHBIT_LONG);
 	return GaudiAlgorithm::initialize();
 }
 
 void BushConnect::Clean(){
+    cout<<"[YX debug] BushConnect::Clean Begin:"<<endl;
+
 	MCPTrack_Type.clear();
 	Track_Energy.clear();
 	Track_Type.clear();
@@ -87,38 +90,43 @@ void BushConnect::Clean(){
 	CluT0.clear();
 	CluCoG.clear();
 	Clu_Depth.clear();
+
+    cout<<"[YX debug] BushConnect::Clean End."<<endl;
+
 }
 
 void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Track*, float> Track_Energy)
 {
+    // cout<<"[YX debug] TrackSort Begin:"<<endl;
 	try{
 		auto TrackColl = m_trkcol.get();
 
 
 		int NTrk = TrackColl->size();
-		cout<<NTrk<<endl;
+		// cout<<"[YX debug] NTrk = "<<NTrk<<endl;
+
 		float D0 = 0;
 		float Z0 = 0;
 		int NTrkHit = 0;
 		const float mass = 0.139;	//Pion Mass
-		TVector3 EndPointPos, StartPointPos; 
-		int TrackType = 0; 
+		TVector3 EndPointPos, StartPointPos;
+		int TrackType = 0;
 
-		std::vector<edm4hep::Track> tracks_HQ_Barrel; 
+		std::vector<edm4hep::Track> tracks_HQ_Barrel;
 		std::vector<edm4hep::Track> tracks_HQ_Endcap;
 		std::vector<edm4hep::Track> tracks_HQ_Shoulder;
-		std::vector<edm4hep::Track> tracks_HQ_Forward; 
+		std::vector<edm4hep::Track> tracks_HQ_Forward;
 		std::vector<edm4hep::Track> tracks_MQ_Barrel;
 		std::vector<edm4hep::Track> tracks_MQ_Endcap;
 		std::vector<edm4hep::Track> tracks_MQ_Shoulder;
 		std::vector<edm4hep::Track> tracks_MQ_Forward;
-		std::vector<edm4hep::Track> tracks_Vtx; 
-		std::vector<edm4hep::Track> tracks_LQ; 
-		std::vector<edm4hep::Track> tracks_LE; 
+		std::vector<edm4hep::Track> tracks_Vtx;
+		std::vector<edm4hep::Track> tracks_LQ;
+		std::vector<edm4hep::Track> tracks_LE;
 		std::vector<edm4hep::Track> curr_tracks;
-	
+
 		Track_EndPoint.clear();
-	
+
 		tracks_HQ_Barrel.clear();
 		tracks_HQ_Endcap.clear();
 		tracks_HQ_Shoulder.clear();
@@ -137,57 +145,71 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 		tracks_preInteraction.clear();	//Used to denote pion and electron interaction inside TPC/Tracker. Simply vetoed for avoid double counting... but muon may still be problematic. Better way of treating would be find the cascade photons & tracks - clusters, and veto all the daughters instead of mother. Similar can done for Kshort...
 	// Condition, tracks_head to others tail. head position far from boundary. and, track energy >= sum of cascade
 
-		std::vector<int> TrackOrder; 
-		TrackOrder.clear();	
-		std::map<edm4hep::Track, int> Track_Index; 
+		std::vector<int> TrackOrder;
+		TrackOrder.clear();
+		std::map<edm4hep::Track, int> Track_Index;
 		Track_Index.clear();
 		Track_Energy.clear();
 		Track_Type.clear();
 		Track_P3.clear();
 		Track_EndPoint.clear();
 		TrackStartPoint.clear();
-	
+
+        // cout<<"[YX debug] i0 for loop begin."<<endl;
+
 		for(int i0 = 0; i0 < NTrk; i0++)
 		{
 			auto a_Trk = (*TrackColl)[i0];
-			NTrkHit = a_Trk.getTrackerHits().size();		
-			EndPointPos = TVector3((a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().x,(a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().y,(a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().z);	
+			NTrkHit = a_Trk.getTrackerHits().size();
+
+            // cout<<"[YX debug] Trk "<<i0<<", NTrkHit = "<<NTrkHit<<", a_Trk = "<<a_Trk<<endl;
+
+            // if(NTrkHit==0) continue;
+
+			EndPointPos = TVector3((a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().x,(a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().y,(a_Trk.getTrackerHits(NTrkHit - 1)).getPosition().z);
 			StartPointPos = TVector3((a_Trk.getTrackerHits(0)).getPosition().x,(a_Trk.getTrackerHits(0)).getPosition().y,(a_Trk.getTrackerHits(0)).getPosition().z);
 			Track_EndPoint[a_Trk] = EndPointPos;
 			TrackStartPoint[a_Trk] = StartPointPos;
-	
+
 			HelixClassD * TrkInit_Helix = new HelixClassD();
 			TrkInit_Helix->Initialize_Canonical(a_Trk.getTrackStates(0).phi, a_Trk.getTrackStates(0).D0, a_Trk.getTrackStates(0).Z0, a_Trk.getTrackStates(0).omega, a_Trk.getTrackStates(0).tanLambda, BField);
 			float TrackEn = mass*mass;
-	
+
 			for (int q3 = 0; q3 < 3; q3 ++)
 			{
 				TrackEn += (TrkInit_Helix->getMomentum()[q3])*(TrkInit_Helix->getMomentum()[q3]);
 			}
 			TVector3 TrkMom(TrkInit_Helix->getMomentum()[0],TrkInit_Helix->getMomentum()[1],TrkInit_Helix->getMomentum()[2]);
-	
+
 			TrackEn = sqrt(TrackEn);
 			Track_Energy[a_Trk] = TrackEn;
 			Track_Theta[a_Trk] = TrkMom.Theta();
 			// Track_Phi[a_Trk] = TrkMom.Phi();
-			Track_P3[a_Trk] = TrkMom;		
-	
+			Track_P3[a_Trk] = TrkMom;
+
+            // cout<<"[YX debug - TrackSort] Input Trk "<<i0<<", PMag = "<<TrkMom.Mag()<<", NTrkHit = "<<NTrkHit<<endl;  // 能对上
+
+
 			delete TrkInit_Helix;
 		}
-	
+        // cout<<"[YX debug] i0 for loop end."<<endl;
+
 		TVector3 currEp, currSp;
 		float currMotherEn = 0;
-		float sumDauEn = 0; 
-	
+		float sumDauEn = 0;
+
 		for(int i1 = 0; i1 < NTrk; i1++)
 		{
 			auto a_Trk = (*TrackColl)[i1];
 			currEp = Track_EndPoint[a_Trk];
-	
-			if( currEp.Perp() < 1600 && currEp.Perp() > 400 && abs(currEp.Z()) < 2000 )	//Only check 
+
+            // cout<<"[YX debug - TrackSort] if_preInteraction Trk "<<i1<<", PMag = "<<Track_P3[a_Trk].Mag()<<", NTrkHit = "<<a_Trk.getTrackerHits().size()<<endl;
+
+
+			if( currEp.Perp() < 1600 && currEp.Perp() > 400 && abs(currEp.Z()) < 2000 )	//Only check
 			{
 				currMotherEn = Track_Energy[a_Trk];
-				sumDauEn = 0;	
+				sumDauEn = 0;
 				for(int i2 = 0; i2 < NTrk; i2++)
 				{
 					auto b_Trk = (*TrackColl)[i2];
@@ -201,10 +223,18 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 				if(currMotherEn + 0.1 > 0.9*sumDauEn && currMotherEn > 3 && sumDauEn > 0 )	//Some protection is always needed...
 				{
 					tracks_preInteraction.push_back(a_Trk);
+
+                    // cout<<"[YX debug - TrackSort] ---> is preInteraction push back!!!"<<endl;
+
 				}
 			}
 		}
-	
+
+        cout<<"[YX debug - TrackSort] tracks_preInteraction.size() = "<<tracks_preInteraction.size()<<endl;
+
+        cout<<"[YX debug - TrackSort] Geo TPCInnerRadius = "<<TPCInnerRadius<<", TPCOuterRadius = "<<TPCOuterRadius<<", ECALHalfZ = "<<ECALHalfZ<<", LStar = "<<LStar<<endl;
+        // cout<<"[YX debug] i1 for loop end."<<endl;
+
 		for(int t0 = 0; t0 < NTrk; t0++)
 		{
 			auto a_Trk = (*TrackColl)[t0];
@@ -216,18 +246,18 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 			Track_EndPoint[a_Trk] = EndPointPos;
 			StartPointPos = TVector3((a_Trk.getTrackerHits(0)).getPosition().x,(a_Trk.getTrackerHits(0)).getPosition().y,(a_Trk.getTrackerHits(0)).getPosition().z);
 			Track_Index[a_Trk] = t0;
-	
+
 			if( NTrkHit > 9 || (fabs(EndPointPos.Z()) > LStar - 500 && EndPointPos.Perp() < TPCInnerRadius ) || fabs(EndPointPos.Z()) > ECALHalfZ - 200  )		// Min requirement for track quality
 			{	// LStar - 500, suppose to be the last Disk Position
-	
+
 				if( find(tracks_preInteraction.begin(), tracks_preInteraction.end(), a_Trk ) != tracks_preInteraction.end() )
 				{
-					cout<<"So We Drop it! "<<Track_Energy[a_Trk]<<endl; 
-					continue; 
+					cout<<"So We Drop it! "<<Track_Energy[a_Trk]<<endl;
+					continue;
 				}
-	
+
 				TrackType = 0;
-	
+
 				if((Track_Energy[a_Trk] < 1.0 && fabs(Track_Theta[a_Trk]-1.57)< 0.4) || (fabs(Track_Theta[a_Trk]-1.57) >= 0.4 && log10(Track_Energy[a_Trk]) < -(fabs(Track_Theta[a_Trk]-1.57)-0.4)*0.2/0.3 ))
 				{
 					TrackType = 100;
@@ -246,16 +276,16 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 				}
 				else if( fabs(EndPointPos.Z()) > ECALHalfZ - 200 )		//Endcap
 				{
-					TrackType = 20; 
+					TrackType = 20;
 				}
-	
+
 				if( fabs(D0) < 1 && fabs(Z0) < 1 )
 				{
 					TrackType += 1;
 				}
-	
-				Track_Type[a_Trk] = TrackType; 
-	
+
+				Track_Type[a_Trk] = TrackType;
+
 				if(TrackType == 11)
 					tracks_HQ_Barrel.push_back(a_Trk);
 				else if(TrackType == 21)
@@ -282,12 +312,18 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 				else
 					tracks_LQ.push_back(a_Trk);
 			}
+
+
+            // cout<<"[YX debug - TrackSort] TrackType Trk "<<t0<<", TrackType = "<<TrackType<<", NTrkHit = "<<a_Trk.getTrackerHits().size()<<", PMag = "<<Track_P3[a_Trk].Mag()<<", E = "<<Track_Energy[a_Trk]<<", Theta = "<<Track_Theta[a_Trk]<<", EndPointPos (Perp, Z) = ("<<EndPointPos.Perp()<<", "<<EndPointPos.Z()<<"), D0 = "<<D0<<", Z0 = "<<Z0<<endl;  //  只是有些 TrackType 对不上,但好像不是后面 TagCore 里对不上的
+
 		}
-		cout<<"LQ"<<tracks_LQ.size()<<" "<<tracks_ILL.size()<<endl;
-	
+		if(1) cout<<"LQ "<<tracks_LQ.size()<<" "<<tracks_ILL.size()<<endl;
+
+        // cout<<"[YX debug] t0 for loop end."<<endl;
+
 		std::vector<float > currTrkMomentum;
 		std::vector<int> currTrkIndex;
-	
+
 		for(int t1 = 0; t1 < 11; t1++)
 		{
 			currTrkMomentum.clear();
@@ -311,22 +347,22 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 				curr_tracks = tracks_MQ_Forward;
 			else if(t1 == 8)
 				curr_tracks = tracks_Vtx;
-			else if(t1 == 9)			
-				curr_tracks = tracks_LQ; 
-			else if(t1 == 10)			
-				curr_tracks = tracks_LE; 
-	
-	
+			else if(t1 == 9)
+				curr_tracks = tracks_LQ;
+			else if(t1 == 10)
+				curr_tracks = tracks_LE;
+
+
 			int N_currTrack = curr_tracks.size();
-	
+
 			for(int t2 = 0; t2 < N_currTrack; t2++)
 			{
 				auto tmpTrk = curr_tracks[t2];
 				currTrkMomentum.push_back(Track_Energy[tmpTrk]);
 			}
-	
+
 			currTrkIndex = SortMeasure(currTrkMomentum, 1);
-	
+
 			for(int t3 = 0; t3 < N_currTrack; t3++)
 			{
 				auto b_tmpTrk = curr_tracks[currTrkIndex[t3]];
@@ -334,40 +370,54 @@ void BushConnect::TrackSort() //, &std::map<Track*, int>Track_Tpye, &std::map<Tr
 					TrackOrder.push_back(Track_Index[b_tmpTrk]);
 			}
 		}
-	
+        // cout<<"[YX debug] 11 for loop end."<<endl;
+
+
 		for(unsigned int t4 = 0; t4 < TrackOrder.size(); t4++)
 		{
-			auto b_Trk =  (*TrackColl)[t4];
+			// auto b_Trk =  (*TrackColl)[t4];  /// !!!
+			auto b_Trk =  (*TrackColl)[TrackOrder[t4]];
 			SortedTracks.push_back(b_Trk);
 		}
+
+        // cout<<"[YX debug] TrackOrder for loop end."<<endl;
+
 	}catch(GaudiException &e){}
+
+    // cout<<"[YX debug] TrackSort End."<<endl;
+
 }
 
 void BushConnect::BushSelfMerge()
 {
+    // cout<<"[YX debug] BushSelfMerge Begin:"<<endl;
+
 	auto CaloClu = m_clucol.get();
 	int NClu = CaloClu->size();
 
-	std::vector<edm4hep::Cluster > Core_1st; 
+    cout<<"[YX debug - BushSelfMerge] Input EHBushes nClu = "<<NClu<<endl;
+
+	std::vector<edm4hep::Cluster > Core_1st;
 	std::vector<edm4hep::MutableCluster > Frag_1st;
-	std::vector<edm4hep::Cluster > UnId_1st; 
+	std::vector<edm4hep::Cluster > UnId_1st;
 	Core_1st.clear();
 	Frag_1st.clear();
 	UnId_1st.clear();
 
-	float CluDepth = 0; 
+	float CluDepth = 0;
 	float CluEn = 0;
-	int CluSize = 0; 
-	TVector3 PosCluSeed, PosSeedDiff, PosCoGDiff, PosSeedA, PosSeedB; 
+	int CluSize = 0;
+	TVector3 PosCluSeed, PosSeedDiff, PosCoGDiff, PosSeedA, PosSeedB;
 
-	int NJoints = 0; 	
-	int SmallCluSize = 0; float DeeperDepth = 0; float LaterT0 = 0; 
+	int NJoints = 0;
+	int SmallCluSize = 0; float DeeperDepth = 0; float LaterT0 = 0;
 	float Depth_A = 0; float Depth_B = 0;
-	int Size_A = 0; int Size_B = 0; 
+	int Size_A = 0; int Size_B = 0;
 
 	TMatrixF FlagMerge(NClu, NClu);
 
-	cout<<NClu<<" clusters"<<endl;
+	double ESum_Clu_Input = 0;
+	// cout<<NClu<<" clusters"<<endl;
 	for(int i0 = 0; i0 < NClu; i0++)
 	{
 		auto a_clu = (*CaloClu)[i0];
@@ -376,8 +426,15 @@ void BushConnect::BushSelfMerge()
 		CluCoG[a_clu] = m_ArborToolLCIO->ClusterCoG(a_clu);
 		PosCluSeed = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
 		Clu_Depth[a_clu] = DisSeedSurface(PosCluSeed);
+
+        ESum_Clu_Input += a_clu.getEnergy();
+        // cout<<"[YX debug - BushSelfMerge] Input EHBushes Clu "<<i0<<", E = "<<a_clu.getEnergy()<<", Pos = ("<<PosCluSeed.X()<<", "<<PosCluSeed.Y()<<", "<<PosCluSeed.Z()<<")"<<endl;
+
 	}
 	// CluCoG_Top20Percent Might be used to improve Photon Split Remerge performance
+    cout<<"[YX debug - BushSelfMerge] Input EHBushes ESum_Clu_Input =  "<<ESum_Clu_Input<<endl;
+
+
 
 	for(int s0 = 0; s0 < NClu; s0++)
 	{
@@ -407,7 +464,7 @@ void BushConnect::BushSelfMerge()
 				if( SmallCluSize < 10 || LaterT0 > 10 || DeeperDepth > 40 || (NJoints > 8 && PosCoGDiff.Mag()*PosCoGDiff.Angle(PosSeedB) < 15 ) || NJoints>16)
 
 					//if( SmallCluSize < 10 || LaterT0 > 10 || DeeperDepth > 40 || (NJoints > 8 ) )
-				{	
+				{
 					FlagMerge[s0][s1] = 1.0;
 					FlagMerge[s1][s0] = 1.0;
 				}
@@ -440,8 +497,8 @@ void BushConnect::BushSelfMerge()
 			auto b_clu = (*CloseMergedCaloClu)[i1];
 			if(i1 != i0)
 			{
-				if(m_ArborToolLCIO->DisPointToBush(PosCluSeed,b_clu) < tmpmindis) 
-					tmpmindis = m_ArborToolLCIO->DisPointToBush(PosCluSeed,b_clu);  
+				if(m_ArborToolLCIO->DisPointToBush(PosCluSeed,b_clu) < tmpmindis)
+					tmpmindis = m_ArborToolLCIO->DisPointToBush(PosCluSeed,b_clu);
 			}
 		}
 		MinDisSeedToBush[a_clu] = tmpmindis;
@@ -476,10 +533,17 @@ void BushConnect::BushSelfMerge()
 	std::vector<edm4hep::MutableCluster > UndefFrag_1stAB = m_ArborToolLCIO->ClusterAbsorbtion(UnId_1st, Frag_1st, 50, 0.02);
 	selfmergedcluster = m_ArborToolLCIO->ClusterAbsorbtion(Core_1st, UndefFrag_1stAB, 50, 0.02);
 	auto CluAB_1st=m_ArborToolLCIO->ClusterVecColl(selfmergedcluster,m_1stclucol);
+
+    cout<<"[YX debug - BushSelfMerge] Output CluAB_1st nClu = "<<selfmergedcluster.size()<<endl;
+
+    // cout<<"[YX debug] BushSelfMerge End."<<endl;
+
 }
 
-void BushConnect::TagCore() 
+void BushConnect::TagCore()
 {
+    // cout<<"[YX debug] TagCore Begin:"<<endl;
+
 	int NTrk = SortedTracks.size();
 	int NClu = selfmergedcluster.size();
 	int currTrackType = 0;
@@ -489,9 +553,13 @@ void BushConnect::TagCore()
 	float CluDepth = 0;
 	float CoreMergeDistanceDepthCorrector = 0;
 
-	TVector3 TrkEndPoint(0, 0, 0);	
+
+    cout<<"[YX debug - TagCore] Input NTrk = "<<NTrk<<", nClu = "<<NClu<<endl;
+
+
+	TVector3 TrkEndPoint(0, 0, 0);
 	TVector3 CluPos(0, 0, 0);
-	std::map<edm4hep::Cluster, int> BushTouchFlag; 
+	std::map<edm4hep::Cluster, int> BushTouchFlag;
 	std::map<edm4hep::Track, edm4hep::MutableCluster> FCMap_Track_CHCore;
 	std::map<edm4hep::Track, std::vector<edm4hep::Cluster>> FCMap_Track_CHCore_new;
 	std::map<int, int> Closest_Trk_Clu_Map;
@@ -509,24 +577,31 @@ void BushConnect::TagCore()
 		for(int s1 = 0; s1 < NClu; s1++)
 		{
 			DisMatrix_Track_Clu_E[s0][s1] = 1.0E10;
-			TimeMatrix_Track_Clu_E[s0][s1] = 1.0E10; 
+			TimeMatrix_Track_Clu_E[s0][s1] = 1.0E10;
 		}
 	}
 
+    double ESum_Clu_Input =0;
 	for(int t0 = 0; t0 < NClu; t0++)
 	{
 		auto a_clu = selfmergedcluster[t0];
 		TVector3 PosCluSeed = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
 		Clu_Depth[a_clu] = DisSeedSurface(PosCluSeed);
+
+        ESum_Clu_Input += a_clu.getEnergy();
+        // cout<<"[YX debug - TagCore] Input AB_1st Clu "<<t0<<", E = "<<a_clu.getEnergy()<<", Pos = ("<<a_clu.getPosition().x<<", "<<a_clu.getPosition().y<<", "<<a_clu.getPosition().z<<")"<<endl;
+
 	}
 
+    cout<<"[YX debug - TagCore] Input AB_1st ESum_Clu_Input =  "<<ESum_Clu_Input<<endl;
+
 	//~~~~~~~ find the closest cluster first...
 
 	for(int g0 = 0; g0 < NTrk; g0++)
 	{
 		auto a_trk = SortedTracks[g0];
-		float ClosestDis = 1.0E9;  
-		int ClosestCluIndex = -1; 
+		float ClosestDis = 1.0E9;
+		int ClosestCluIndex = -1;
 		int ClosestNC = 1E9;
 		float TrackEn = Track_Energy[a_trk];
 		TrkEndPoint = Track_EndPoint[a_trk];
@@ -534,6 +609,8 @@ void BushConnect::TagCore()
 		currTrackType = Track_Type[a_trk];
 		TVector3 TrkP3 = Track_P3[a_trk];
 
+        // cout<<"[YX debug - TagCore] SortedTrack "<<g0<<", PMag = "<<TrkP3.Mag()<<", TrackEn = "<<TrackEn<<endl;
+
 		for(int g1 = 0; g1 < NClu; g1++)
 		{
 			auto fccand_bush = selfmergedcluster[g1];
@@ -546,7 +623,7 @@ void BushConnect::TagCore()
 				TimeMatrix_Track_Clu_E[g0][g1] = Time;
 				if( Dis[2] < ClosestDis ) // && ThetaDiff < 0.05 + 0.1/Track_Energy[a_trk] )
 				{
-					ClosestDis = Dis[2]; 
+					ClosestDis = Dis[2];
 					ClosestCluIndex = g1;
 					ClosestNC = NC;
 				}
@@ -554,10 +631,10 @@ void BushConnect::TagCore()
 		}
 
 		//Diag for mimic
-		cout<<" Z R "<<TrkEndPoint.Z()<<" MM "<<TrkEndPoint.Perp()<< " ClosestCluIndex "<<ClosestCluIndex<<" ClosestDis "<<ClosestDis <<endl; 
+		if(0) cout<<" Z R "<<TrkEndPoint.Z()<<" MM "<<TrkEndPoint.Perp()<< " ClosestCluIndex "<<ClosestCluIndex<<" ClosestDis "<<ClosestDis <<endl;
 		//End Diag
 
-		if( ClosestDis < 15 + 15./TrackEn && ClosestCluIndex > -0.1 && (ClosestNC < 3 || abs(TrkP3.Theta() - 1.57) < 0.01 ) ) 
+		if( ClosestDis < 15 + 15./TrackEn && ClosestCluIndex > -0.1 && (ClosestNC < 3 || abs(TrkP3.Theta() - 1.57) < 0.01 ) )
 		{
 			auto candiclu= selfmergedcluster[ClosestCluIndex];
 			CluPos = TVector3(candiclu.getPosition().x,candiclu.getPosition().y,candiclu.getPosition().z);
@@ -570,7 +647,7 @@ void BushConnect::TagCore()
 		}
 	}	//~~~~~~~ end of finding closest cluster
 
-	cout<<"NTrk "<<NTrk<<endl;
+	// cout<<"NTrk "<<NTrk<<endl;
 	for(int i0 = 0; i0 < NTrk; i0++)  //Dropped Size can exist
 	{
 		auto a_trk = SortedTracks[i0];
@@ -587,7 +664,7 @@ void BushConnect::TagCore()
 
 		for(int j0 = 0; j0 < NClu; j0++)
 		{
-			auto fccand_bush = selfmergedcluster[j0]; 
+			auto fccand_bush = selfmergedcluster[j0];
 			float Dis = DisMatrix_Track_Clu_E[i0][j0]; //SimpleDisTrackClu(a_trk, fccand_bush);
 			float BushTime = TimeMatrix_Track_Clu_E[i0][j0];
 			CluDepth = Clu_Depth[fccand_bush];
@@ -670,6 +747,11 @@ void BushConnect::TagCore()
 
 	edm4hep::ReconstructedParticleCollection* chargeparticleCol = m_chargeparticleCol.createAndPut();
 	edm4hep::ClusterCollection* chargedcoreclusterCol = m_chargedcoreclusterCol.createAndPut();
+
+    cout<<"[YX debug - TagCore] NTrk = "<<NTrk<<endl;
+    double ESum_ChCore_All = 0;
+    double ESum_ChCore_in = 0;
+
 	for(int j5 = 0; j5 < NTrk; j5++)
 	{
 		auto a_trk = SortedTracks[j5];
@@ -680,9 +762,16 @@ void BushConnect::TagCore()
 		chargeparticle.setCharge(a_trk.getTrackStates(0).omega/fabs(a_trk.getTrackStates(0).omega));
 		TVector3 Ptrack = Track_P3[a_trk];
 		edm4hep::Vector3f currTrkP = edm4hep::Vector3f( Ptrack.X(), Ptrack.Y(), Ptrack.Z() );
-		chargeparticle.setMomentum(currTrkP); 
+		chargeparticle.setMomentum(currTrkP);
 		chargeparticle.addToTracks( a_trk );
 		auto a_clu = FCMap_Track_CHCore[a_trk];
+
+        double Clu_ChCore_E = a_clu.getEnergy();
+        int nCluHit = a_clu.hits_size();
+        if(0) cout<<"[YX debug - TagCore] Trk "<<j5<<", PMag = "<<Ptrack.Mag()<<", CluCore E = "<<Clu_ChCore_E<<", nHit = "<<nCluHit<<endl;
+        ESum_ChCore_All += Clu_ChCore_E;
+
+
 		if( FCMap_Track_CHCore[a_trk].hits_size()>0 )		// No really need to pertect, as quality will be controled in Part.Reco
 		{
 			auto chargedcorecluster = chargedcoreclusterCol->create();
@@ -691,16 +780,43 @@ void BushConnect::TagCore()
 			edm4hep::Cluster chargedcoreclusterCon=chargedcorecluster;
 			chargeparticle.addToClusters(chargedcoreclusterCon);
 			Track_Core_ID = m_ArborToolLCIO->ClusterFlag(a_clu, a_trk);
+
+            if(0) cout<<"[YX debug - TagCore] ---> ChCore in"<<endl;
+            ESum_ChCore_in += Clu_ChCore_E;
+
 		}
 		chargeparticle.setType(Track_Core_ID);
 		ChCoreID[chargeparticle] = Track_Core_ID;
 	}
 
+//  auto ChCoreCluCol = m_chargedcoreclusterCol.get();
+
+
+
+    int nPFO_ChCore = chargeparticleCol->size();
+    int nClu_ChCore = chargedcoreclusterCol->size();
+    // int nClu_NeCore = arborneutralcorecluster.size();
+    // int nPFO_NeCore = arborrecoparticle_ne.size();
+
+    int nClu_NonChCore = non_chargedclustercore.size();
+
+    cout<<"[YX debug - TagCore] Output nPFO_ChCore = "<<nPFO_ChCore<<endl;
+    cout<<"[YX debug - TagCore] Output nClu_ChCore = "<<nClu_ChCore<<", ESum_ChCore_All = "<<ESum_ChCore_All<<", ESum_ChCore_in = "<<ESum_ChCore_in<<endl;
+    cout<<"[YX debug - TagCore] Output nClu_NonChCore = "<<nClu_NonChCore<<endl;
+    // cout<<"[YX debug - TagCore] Output nClu_NeCore = "<<nClu_NeCore<<endl;
+    // cout<<"[YX debug - TagCore] Output nPFO_NeCore = "<<nPFO_NeCore<<endl;
+
+
+
+
+
+    // cout<<"[YX debug] TagCore End."<<endl;
 
 }
 
 void BushConnect::ParticleReco()
 {
+    // cout<<"[YX debug] ParticleReco Begin:"<<endl;
 
 	auto col_IsoHit = m_col_IsoHit.get();
 	std::vector<edm4hep::CalorimeterHit> IsoHits = m_ArborToolLCIO->CollHitVec(col_IsoHit, 0);
@@ -710,30 +826,71 @@ void BushConnect::ParticleReco()
 	edm4hep::ClusterCollection* mergedclu_chCol = m_mergedclu_chCol.createAndPut();
 	edm4hep::ClusterCollection* mergedclu_neCol = m_mergedclu_neCol.createAndPut();
 
-	auto ChargedCore = m_chargeparticleCol.get(); 
+	auto ChargedCore = m_chargeparticleCol.get();
 	int NChargedObj = ChargedCore->size();
 	int NNeutralCluster = non_chargedclustercore.size();
-	double DisMatrix_Core_Neutral[NChargedObj][NNeutralCluster][2];		//Define different types of distances; 
+	double DisMatrix_Core_Neutral[NChargedObj][NNeutralCluster][2];		//Define different types of distances;
+
+
+    // ------------------------------------------------------------------------------------------
+    double ESum_ChCore = 0;
+    double ESum_NeClu = 0;
+	for(int i = 0; i < NChargedObj; i++)
+	{
+		auto a_recoP_ch = (*ChargedCore)[i];
+		auto aTrk = a_recoP_ch.getTracks()[0];
+		float Trk_E = Track_Energy[aTrk];
+        float Clu_E = 0;
+		if(a_recoP_ch.clusters_size() != 0)
+		{
+			edm4hep::Cluster aClu = a_recoP_ch.getClusters()[0];
+			Clu_E = aClu.getEnergy();
+		}
+        ESum_ChCore+=Trk_E;
+
+        // cout<<"[YX debug - ParticleReco] Input Trk "<<i<<", E = "<<Trk_E<<", Clu_E = "<<Clu_E<<endl;
+
+    }
+
+    for(int j = 0; j < NNeutralCluster; j++)
+    {
+        auto aClu = non_chargedclustercore[j];
+        int Clu_nHit = aClu.hits_size();
+        float Clu_E = aClu.getEnergy();
+        TVector3 Clu_Pos = TVector3(aClu.getPosition().x,aClu.getPosition().y,aClu.getPosition().z);
+        double Clu_Depth = DisSeedSurface(Clu_Pos);
+
+        ESum_NeClu+=Clu_E;
+
+        // cout<<"[YX debug - ParticleReco] Input NeClu "<<j<<", E = "<<Clu_E<<", nHit = "<<Clu_nHit<<", Depth = "<<Clu_Depth<<endl;
+
+    }
+
+    cout<<"[YX debug - ParticleReco] NChargedObj = "<<NChargedObj<<", ESum_ChCore = "<<ESum_ChCore<<endl;
+    cout<<"[YX debug - ParticleReco] NNeutralCluster = "<<NNeutralCluster<<", ESum_NeClu = "<<ESum_NeClu<<endl;
+    // ------------------------------------------------------------------------------------------
+
+
 
 	float CluDepth = 0;
-	std::map<edm4hep::Cluster, double> CluDepthMap; 
+	std::map<edm4hep::Cluster, double> CluDepthMap;
 	CluDepthMap.clear();
-	int currChargeCoreType = 0;  
-	TVector3 CluPos; 
+	int currChargeCoreType = 0;
+	TVector3 CluPos;
 
-	std::vector<edm4hep::Cluster> loosecandicluster; 
+	std::vector<edm4hep::Cluster> loosecandicluster;
 	std::vector<edm4hep::Cluster> tightcandicluster;		//Muon potential candi?
 	std::vector<edm4hep::Cluster> mergedcluster; 			//tmp for each charged P
 	std::vector<edm4hep::Cluster> chargedclustercore_merged; 	//overall
 	chargedclustercore_merged.clear();
 
-	std::vector<double> reftightdis; 
-	std::vector<double> refloosedis; 
-	std::map<edm4hep::Cluster, int> NNCTouchFlag; 
+	std::vector<double> reftightdis;
+	std::vector<double> refloosedis;
+	std::map<edm4hep::Cluster, int> NNCTouchFlag;
 	std::vector<edm4hep::Track> SecondIterTracks;
 	SecondIterTracks.clear();
 
-	TVector3 currTrkEnd, neighbourTrkEnd, LeadP; 
+	TVector3 currTrkEnd, neighbourTrkEnd, LeadP;
 
 	for(int i = 0; i < NChargedObj; i++)
 	{
@@ -759,7 +916,7 @@ void BushConnect::ParticleReco()
 			mergedcluster.push_back(a_chargedClu);		//Actually can use this chance to question if previous energy are balance...
 		}
 
-		float MinDisToNoClusterTrk = 1.0E10; 
+		float MinDisToNoClusterTrk = 1.0E10;
 		float MinDisToOtherTrack = 1.0E10;
 
 		for( int is = 0; is < NChargedObj; is++ )
@@ -780,12 +937,12 @@ void BushConnect::ParticleReco()
 		for(int j = 0; j < NNeutralCluster; j++)
 		{
 			auto a_NeCandiClu = non_chargedclustercore[j];
-			float NeCandEn = a_NeCandiClu.getEnergy(); 
+			float NeCandEn = a_NeCandiClu.getEnergy();
 			CluPos = TVector3(a_NeCandiClu.getPosition().x,a_NeCandiClu.getPosition().y,a_NeCandiClu.getPosition().z);
 			CluDepth = DisSeedSurface(CluPos);
-			CluDepthMap[a_NeCandiClu] = CluDepth; 	
+			CluDepthMap[a_NeCandiClu] = CluDepth;
 
-			if( ClusterType_1stID[a_NeCandiClu] == 22)   continue; 
+			if( ClusterType_1stID[a_NeCandiClu] == 22)   continue;
 
 			for(int k = 0; k < 2; k++)
 			{
@@ -800,7 +957,7 @@ void BushConnect::ParticleReco()
 			DisMatrix_Core_Neutral[i][j][1] = Dis[2];
 
 			if( NNCTouchFlag.find(a_NeCandiClu) == NNCTouchFlag.end() && ( currChargeCoreType == 0 || DisMatrix_Core_Neutral[i][j][0] < 1000 ) && currTrkType != 101)
-			{			
+			{
 				if( currChargeCoreType == 130 )			//Matched Muon, should ignore
 				{
 					if( DisMatrix_Core_Neutral[i][j][1] < 0.2*CluDepth && CluDepth > 200  )	//&& FD?
@@ -814,14 +971,14 @@ void BushConnect::ParticleReco()
 					if( DisMatrix_Core_Neutral[i][j][1] < 0.3*CluDepth && CluDepth > 150 )
 					{
 						tightcandicluster.push_back(a_NeCandiClu);
-						reftightdis.push_back( DisMatrix_Core_Neutral[i][j][1] );	
+						reftightdis.push_back( DisMatrix_Core_Neutral[i][j][1] );
 					}
 					else if( DisMatrix_Core_Neutral[i][j][1] < 0.5*CluDepth && CluDepth > 100 )
 					{
 						loosecandicluster.push_back(a_NeCandiClu);
 						refloosedis.push_back( DisMatrix_Core_Neutral[i][j][1] );
 					}
-				}	
+				}
 				else if( currChargeCoreType == 110  )		// Electron
 				{
 					if( DisMatrix_Core_Neutral[i][j][0] < 0.15*CluDepth + 15 )
@@ -829,7 +986,7 @@ void BushConnect::ParticleReco()
 						tightcandicluster.push_back(a_NeCandiClu);
 						reftightdis.push_back( DisMatrix_Core_Neutral[i][j][0] );
 					}
-				}			
+				}
 				else if( currChargeCoreType == 111 )		// look behind... might be pion...
 				{
 					if( DisMatrix_Core_Neutral[i][j][0] < 0.1*CluDepth + 15 && DisMatrix_Core_Neutral[i][j][1] < 0.1*CluDepth + 10 )	//Define Brems Photon region for correct
@@ -845,7 +1002,7 @@ void BushConnect::ParticleReco()
 						}
 					}
 					else if( DisMatrix_Core_Neutral[i][j][0] < 0.2*CluDepth + 15 || DisMatrix_Core_Neutral[i][j][1] < 0.2*CluDepth + 15  )
-					{	
+					{
 						loosecandicluster.push_back(a_NeCandiClu);
 
 						if(DisMatrix_Core_Neutral[i][j][0] < DisMatrix_Core_Neutral[i][j][1])   // not fully adequate.
@@ -896,13 +1053,13 @@ void BushConnect::ParticleReco()
 				}
 				else
 				{
-					cout<<"Over balanced/Un matched/defined case: "<<a_recoP_ch.getEnergy()<<" ??? "<<currChargeCoreType<<endl; 
+					cout<<"Over balanced/Un matched/defined case: "<<a_recoP_ch.getEnergy()<<" ??? "<<currChargeCoreType<<endl;
 				}
 			}
 		}
 
-		float totaltightcandiEn = 0; 
-		float totalloosecandiEn = 0; 
+		float totaltightcandiEn = 0;
+		float totalloosecandiEn = 0;
 		for(unsigned int s = 0; s < tightcandicluster.size(); s++)
 		{
 			totaltightcandiEn += tightcandicluster[s].getEnergy();
@@ -954,7 +1111,7 @@ void BushConnect::ParticleReco()
 			for(unsigned int i1 = 0; i1 < tightcandicluster.size(); i1++)
 			{
 				auto a_clu = tightcandicluster[i1];
-				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 0.5*sqrt(CurrTrackEnergy))  
+				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 0.5*sqrt(CurrTrackEnergy))
 				{
 					mergedcluster.push_back( a_clu );
 					CurrClusterEnergy += a_clu.getEnergy();
@@ -967,7 +1124,7 @@ void BushConnect::ParticleReco()
 			{
 				auto a_clu = tightcandicluster[i1];
 
-				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 0.5*sqrt(CurrTrackEnergy))  
+				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 0.5*sqrt(CurrTrackEnergy))
 				{
 					mergedcluster.push_back( a_clu );
 					CurrClusterEnergy += a_clu.getEnergy();
@@ -982,7 +1139,7 @@ void BushConnect::ParticleReco()
 					mergedcluster.push_back( a_clu );
 					CurrClusterEnergy += a_clu.getEnergy();
 				}
-			}	
+			}
 		}
 		else if( currChargeCoreType == 211 )	// Matched
 		{
@@ -990,7 +1147,7 @@ void BushConnect::ParticleReco()
 			{
 				auto a_clu = tightcandicluster[i1];
 
-				if( CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 1.5*sqrt(CurrTrackEnergy))  
+				if( CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 1.5*sqrt(CurrTrackEnergy))
 				{
 					mergedcluster.push_back( a_clu );
 					CurrClusterEnergy += a_clu.getEnergy();
@@ -1002,7 +1159,7 @@ void BushConnect::ParticleReco()
 			for(unsigned int i1 = 0; i1 < tightcandicluster.size(); i1++)
 			{
 				auto a_clu = tightcandicluster[i1];
-				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 1.5*sqrt(CurrTrackEnergy))  
+				if(  CurrClusterEnergy + a_clu.getEnergy() < CurrTrackEnergy + 1.5*sqrt(CurrTrackEnergy))
 				{
 					mergedcluster.push_back( a_clu );
 					CurrClusterEnergy += a_clu.getEnergy();
@@ -1024,14 +1181,14 @@ void BushConnect::ParticleReco()
 		else if( currChargeCoreType == 0 && reftightdis.size() > 0)
 		{
 			float mindis = 1.0E10;
-			int minindex = 0; 
+			int minindex = 0;
 
 			for(unsigned int i1 = 0; i1 < reftightdis.size(); i1 ++)
 			{
 				if(reftightdis[i1] < mindis)
 				{
 					mindis = reftightdis[i1];
-					minindex = i1; 
+					minindex = i1;
 				}
 			}
 
@@ -1041,13 +1198,13 @@ void BushConnect::ParticleReco()
 		}
 		else
 		{
-			cout<<"No_match, currChargeCoreType "<<currChargeCoreType<<endl; 
+			cout<<"No_match, currChargeCoreType "<<currChargeCoreType<<endl;
 		}
 
 		float CHCluEnergy = 0;
 
 		for(int is = 0; is < int(mergedcluster.size()); is++)
-		{       
+		{
 			auto a_TBM_clu = mergedcluster[is];
 			CHCluEnergy +=a_TBM_clu.getEnergy();
 		}
@@ -1079,16 +1236,16 @@ void BushConnect::ParticleReco()
 			chargedclustercore_merged.push_back(chclustermerged);
 			currChargeCoreType2 = m_ArborToolLCIO->ClusterFlag(chclustermerged, a_chargedTrk);
 
-			if( currChargeCoreType2 == 130 || currChargeCoreType2 == 131 ) 
+			if( currChargeCoreType2 == 130 || currChargeCoreType2 == 131 )
 			{
 				chargeparticle.setType( int(-13*charge) );
 			}
-			else if( currChargeCoreType2 == 110 || currChargeCoreType2 == 111 ) 
+			else if( currChargeCoreType2 == 110 || currChargeCoreType2 == 111 )
 			{
 				chargeparticle.setType( int(-11*charge) );
 				if(CHCluEnergy > CurrTrackEnergy + 0.5*sqrt(CurrTrackEnergy) + 1)
 				{
-					flagEnergyFlow = 1; 
+					flagEnergyFlow = 1;
 				}
 			}
 			else
@@ -1100,10 +1257,10 @@ void BushConnect::ParticleReco()
 				}
 			}
 
-			if( (currChargeCoreType2 != 130 && currChargeCoreType2 != 131 &&  CurrTrackEnergy > 15 && CHCluEnergy > 0.5 && CurrTrackEnergy > CHCluEnergy + 2.5*sqrt(CHCluEnergy) )  || (( currChargeCoreType2 == 130 || currChargeCoreType2 == 131 ) && CurrTrackEnergy > 100 && CHCluEnergy < 3 && chclustermerged.hits_size() < 20 ) ) 
+			if( (currChargeCoreType2 != 130 && currChargeCoreType2 != 131 &&  CurrTrackEnergy > 15 && CHCluEnergy > 0.5 && CurrTrackEnergy > CHCluEnergy + 2.5*sqrt(CHCluEnergy) )  || (( currChargeCoreType2 == 130 || currChargeCoreType2 == 131 ) && CurrTrackEnergy > 100 && CHCluEnergy < 3 && chclustermerged.hits_size() < 20 ) )
 			{
 				chargeparticle.setEnergy( CHCluEnergy );
-				edm4hep::Vector3f CorrMom = edm4hep::Vector3f(CHCluEnergy/CurrTrackEnergy*currTrkP[0], CHCluEnergy/CurrTrackEnergy*currTrkP[1], CHCluEnergy/CurrTrackEnergy*currTrkP[2] ); 
+				edm4hep::Vector3f CorrMom = edm4hep::Vector3f(CHCluEnergy/CurrTrackEnergy*currTrkP[0], CHCluEnergy/CurrTrackEnergy*currTrkP[1], CHCluEnergy/CurrTrackEnergy*currTrkP[2] );
 				chargeparticle.setMomentum( CorrMom );
 			}
 			else
@@ -1117,50 +1274,68 @@ void BushConnect::ParticleReco()
 				auto a_Ef_Ne_particle = arborrecoparticleCol->create();
 				a_Ef_Ne_particle.setEnergy( CHCluEnergy - CurrTrackEnergy );
 				TVector3 corePos = TVector3(chclustermerged.getPosition().x,chclustermerged.getPosition().y,chclustermerged.getPosition().z);
-				float WFactor = (CHCluEnergy - CurrTrackEnergy)/corePos.Mag(); 
+				float WFactor = (CHCluEnergy - CurrTrackEnergy)/corePos.Mag();
 				edm4hep::Vector3f PFNEMom = edm4hep::Vector3f(WFactor*float(corePos.X()), WFactor*float(corePos.Y()), WFactor*float(corePos.Z()));
 				a_Ef_Ne_particle.setMomentum(PFNEMom);
 				a_Ef_Ne_particle.setMass( 0.0 );
 				a_Ef_Ne_particle.setCharge( 0.0 );
 				a_Ef_Ne_particle.setType(501);
 
-				cout<<"Energy Flow Neutral Tagged "<<CHCluEnergy - CurrTrackEnergy<<endl; 
+				cout<<"Energy Flow Neutral Tagged "<<CHCluEnergy - CurrTrackEnergy<<endl;
+
+                cout<<"[YX debug - ParticleReco] EfPFO E = "<<a_Ef_Ne_particle.getEnergy()<<endl;
+
 			}
-			cout<<"a charged particle reconstructed with en:"<<chargeparticle.getEnergy()<<endl;
+			if(0) cout<<"a charged particle reconstructed with en:"<<chargeparticle.getEnergy()<<endl;
+
+            if(0) cout<<"[YX debug - ParticleReco] ChPFO E = "<<chargeparticle.getEnergy()<<endl;
 
 		}
 		else	// push non valid tracks, etc to second iteration, as those for PreInteracting ones
 		{
 			SecondIterTracks.push_back(a_chargedTrk);
-			cout<<"Second Iter Track Found"<<endl; 
-		}	
+			cout<<"Second Iter Track Found"<<endl;
+		}
 	}
 
-	std::vector<edm4hep::MutableCluster> BBCore; 
+	std::vector<edm4hep::MutableCluster> BBCore;
 	BBCore.clear();
 	for(int p6 = 0; p6 < NNeutralCluster; p6 ++)
 	{
 		auto c_clu = non_chargedclustercore[p6];
+
+
 		if( NNCTouchFlag.find(c_clu) == NNCTouchFlag.end() )
 		{
 			BBCore.push_back(c_clu);
-		} 
+
+            if(0) cout<<"[YX debug - BBCore] Clu "<<p6<<" push back"<<endl;
+
+		}
+
+        if(0) cout<<"[YX debug - BBCore] Clu "<<p6<<", NNCTouchFlag = "<<NNCTouchFlag[c_clu]<<", CluE = "<<c_clu.getEnergy()<<endl;
+
 	}
 
 	float NAMom[3] = {0, 0, 0};
 
 	//Final Re-absorption
-	std::vector<edm4hep::Cluster> NBBNeutral; 
+	std::vector<edm4hep::Cluster> NBBNeutral;
 	NBBNeutral.clear();
 
 	for(int s = 0; s < int (BBCore.size()); s++)
 	{
 		auto a_clu = BBCore[s];
 		TVector3 PosClu = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
-		float Depth = 0; 
+		float Depth = 0;
 		Depth = DisSeedSurface(PosClu);
 		float CoreEnCorr = m_ArborToolLCIO->ClusterEE(a_clu);
 
+        int PhotonTag = m_ArborToolLCIO->newPhotonTag(a_clu);
+        double CluE = a_clu.getEnergy();
+        if(0) cout<<"[YX debug - BBCore] Clu "<<s<<", newPhotonTag = "<<PhotonTag<<", CluE = "<<CluE<<", CoreEnCorr = "<<CoreEnCorr<<endl;
+
+
 		if(m_ArborToolLCIO->newPhotonTag(a_clu)==1)
 		{
 			TVector3 BushSeedPos = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
@@ -1179,13 +1354,18 @@ void BushConnect::ParticleReco()
 			a_neclu.setEnergy( CoreEnCorr );	//Reset...
 			edm4hep::Cluster a_necluCon=a_neclu;
 			neutralparticle.addToClusters(a_neclu);
+
+            cout<<"[YX debug - BBCore] ---> Is photon "<<endl;
+
+            cout<<"[YX debug - ParticleReco] Photon E = "<<neutralparticle.getEnergy()<<endl;
+
 		}
 		else	// Distance to Charged Core > sth;
 		{
 			float MinDisToChCore = 1.0E9;
-			float currDis = 0; 
+			float currDis = 0;
 			int NChCore = mergedclu_chCol->size();
-			float closestChCluEn = 0; 			
+			float closestChCluEn = 0;
 			for(int t = 0; t < NChCore; t++)
 			{
 				auto a_chclu = (*mergedclu_chCol)[t];
@@ -1196,30 +1376,50 @@ void BushConnect::ParticleReco()
 					closestChCluEn = a_chclu.getEnergy();	// Or the Trk En??
 				}
 			}
+
+            if(0) cout<<"[YX debug - BBCore] ---> Is others: NChCore = "<<NChCore<<", MinDisToChCore = "<<MinDisToChCore<<", closestChCluEn = "<<closestChCluEn<<endl;
+
 			if( MinDisToChCore > 0.4*(15 + closestChCluEn + Depth*0.01) || a_clu.getEnergy() > 2.0 )	//Joint Depth??
 			{
 				NBBNeutral.push_back(a_clu);
+
+                if(0) cout<<"[YX debug - BBCore] ---|---> NBBNeutral push back "<<endl;
+
 			}
 		}
+
+
 	}
 
+
+    cout<<"[YX debug - ParticleReco] BBCore.size() = "<<BBCore.size()<<", NBBNeutral.size() = "<<NBBNeutral.size()<<", IsoHits.size() = "<<IsoHits.size()<<endl;
+
+
 	// Add: Neural Core Remerge & Energy Scale Recalculate, IsoHit Abso
 	std::vector<edm4hep::MutableCluster> NBBAbs = m_ArborToolLCIO->ClusterHitAbsorbtion(NBBNeutral, IsoHits, 100); //_HitAbsCut);	// Huge??
 
-	std::vector<float> BBAbsEn; 
+	std::vector<float> BBAbsEn;
 	BBAbsEn.clear();
 
+    // double ESum_NBBAbs = 0;
+
 	for(unsigned s1 = 0; s1 < NBBAbs.size(); s1++)
 	{
 		BBAbsEn.push_back(NBBAbs[s1].getEnergy());
+
+        // ESum_NBBAbs+=NBBAbs[s1].getEnergy();
+
 	}
 
+    // cout<<"[YX debug - ParticleReco] NBBAbs.size() = "<<NBBAbs.size()<<", ESum_NBBAbs = "<<ESum_NBBAbs<<endl;
+
+
 	std::vector<int> BBAbsIndex = SortMeasure(BBAbsEn, 1);
 
 	std::vector<edm4hep::Cluster > NeutronCore;
 	std::vector<edm4hep::MutableCluster > NeutronFlag;
 	NeutronCore.clear();
-	NeutronFlag.clear();	
+	NeutronFlag.clear();
 
 	for(unsigned int s2 = 0; s2 < NBBAbs.size(); s2++)	//Sort it; the first one must be a neutral core?
 	{
@@ -1238,6 +1438,10 @@ void BushConnect::ParticleReco()
 
 	std::vector<edm4hep::MutableCluster > Neutrons = m_ArborToolLCIO->ClusterAbsorbtion(NeutronCore, NeutronFlag, 200, 0.01);
 
+
+    cout<<"[YX debug - ParticleReco] NeutronCore.size() = "<<NeutronCore.size()<<", NeutronFlag.size() = "<<NeutronFlag.size()<<endl;
+
+
 	for(unsigned int s3 = 0; s3 < Neutrons.size(); s3++)
 	{
 		auto a_clu = Neutrons[s3];
@@ -1245,7 +1449,7 @@ void BushConnect::ParticleReco()
 		TVector3 PosClu = TVector3(a_clu.getPosition().x,a_clu.getPosition().y,a_clu.getPosition().z);
 		float MinDisToChCore = 1.0E9;
 		float RecoT0 = m_ArborToolLCIO->ClusterT0(a_clu);
-		float currDis = 0; 
+		float currDis = 0;
 		int NChCore = mergedclu_chCol->size();
 		for(int t = 0; t < NChCore; t++)
 		{
@@ -1257,10 +1461,14 @@ void BushConnect::ParticleReco()
 			}
 		}
 
+
+        if(0) cout<<"[YX debug - Neutrons] Clu "<<s3<<", MinDisToChCore = "<<MinDisToChCore<<", CluE = "<<a_clu.getEnergy()<<", CoreEnCorr = "<<CoreEnCorr<<endl;
+
+
 		if( !(RecoT0>0.1 && RecoT0<1E8 && MinDisToChCore <12) )
 		{
 			if(m_ArborToolLCIO->newPhotonTag(a_clu)==1)
-				cout<<"WARNING... Photons after neutron merge merged"<<endl; 
+				cout<<"WARNING... Photons after neutron merge merged"<<endl;
 			auto neutralparticle = arborrecoparticleCol->create();
 			neutralparticle.setType(21120);
 			TVector3 PP = m_ArborToolLCIO->ClusterCoG(a_clu);
@@ -1301,27 +1509,34 @@ void BushConnect::ParticleReco()
 			a_neclu.setEnergy( CoreEnCorr );       //Reset...
 			edm4hep::Cluster a_necluCon=a_neclu;
 			neutralparticle.addToClusters(a_necluCon);
+
+            if(0) cout<<"[YX debug - ParticleReco] NePFO E = "<<neutralparticle.getEnergy()<<endl;
+
 		}
 	}
-	
+
+// cout<<"[YX debug] ParticleReco End."<<endl;
 
 }
 
 StatusCode BushConnect::execute()
 {
 		try{
-		BushConnect::Clean();	
+		cout<<"[YX debug - BushConnect] Begin:"<<endl;
 		BushConnect::TrackSort(  );
-		BushConnect::BushSelfMerge(  ); 	
-		BushConnect::TagCore(  );		
+		BushConnect::BushSelfMerge(  );
+		BushConnect::TagCore(  );
 		BushConnect::ParticleReco(  );
+
+        BushConnect::Clean();
+
 		}catch(GaudiException &e){}
 	return StatusCode::SUCCESS;
 }
 
 StatusCode BushConnect::finalize()
 {
-	std::cout<<"Bush Connection Finished, ArborObject Formed"<<std::endl;	
+	std::cout<<"Bush Connection Finished, ArborObject Formed"<<std::endl;
 	return GaudiAlgorithm::finalize();
 }
 
diff --git a/Reconstruction/PFA/Arbor/src/BushConnect.hh b/Reconstruction/PFA/Arbor/src/BushConnect.hh
index 7cf32b9a248d449e1dbf9277827530d237f05b6c..075773b171b2bc196b0f6cafd5b633e511a1d9e3 100644
--- a/Reconstruction/PFA/Arbor/src/BushConnect.hh
+++ b/Reconstruction/PFA/Arbor/src/BushConnect.hh
@@ -41,11 +41,11 @@ class BushConnect  : public GaudiAlgorithm
 		virtual StatusCode execute() ;
 
 		virtual StatusCode finalize() ;
-		void Clean(); 
-		void TrackSort(); 
-		void BushSelfMerge(); 
-		void TagCore(); 
-		void ParticleReco(); 
+		void Clean();
+		void TrackSort();
+		void BushSelfMerge();
+		void TagCore();
+		void ParticleReco();
 
 
 	protected:
@@ -56,10 +56,10 @@ class BushConnect  : public GaudiAlgorithm
 		std::map<edm4hep::Track, TVector3> Track_P3;
 		std::map<edm4hep::Track, int> Track_Type;
 		std::map<edm4hep::Track, float> Track_Theta;
-		std::map<edm4hep::Track, float> Track_Phi;	
+		std::map<edm4hep::Track, float> Track_Phi;
 
 		std::map<edm4hep::Cluster, int> ClusterType_1stID;
-		std::map<edm4hep::ReconstructedParticle, int> ChCoreID; 
+		std::map<edm4hep::ReconstructedParticle, int> ChCoreID;
 
 		std::vector<edm4hep::Cluster> ecalchcore_tight;         //TightCores
 		std::vector<edm4hep::Cluster> ecalchcore_medium;
@@ -79,7 +79,7 @@ class BushConnect  : public GaudiAlgorithm
 		std::vector<edm4hep::Cluster> chargedclustercore;
 		std::vector<edm4hep::Cluster> chargedclustercore_abs;
 
-		std::vector<edm4hep::MutableCluster> selfmergedcluster; 
+		std::vector<edm4hep::MutableCluster> selfmergedcluster;
 		std::vector<edm4hep::MutableCluster> non_chargedclustercore;
 		std::vector<edm4hep::Cluster> onlyNeutralCore;
 
@@ -89,9 +89,9 @@ class BushConnect  : public GaudiAlgorithm
 		std::map<edm4hep::Track, int>MCPTrack_Type;
 		std::map<edm4hep::Track, TVector3> Track_EndPoint;       //Last hit
 		std::map<edm4hep::Track, TVector3> TrackStartPoint;
-		std::map<edm4hep::Cluster, float> CluFD; 
+		std::map<edm4hep::Cluster, float> CluFD;
 		std::map<edm4hep::Cluster, float> CluT0;
-		std::map<edm4hep::Cluster, float> Clu_Depth; 
+		std::map<edm4hep::Cluster, float> Clu_Depth;
 		std::map<edm4hep::Cluster, TVector3> CluCoG;
 	typedef DataHandle<edm4hep::MCParticleCollection> MCParticleColHandler;
 	MCParticleColHandler m_mcParticle{"MCParticle", Gaudi::DataHandle::Reader, this};
@@ -113,8 +113,10 @@ class BushConnect  : public GaudiAlgorithm
 	DataHandle<edm4hep::ReconstructedParticleCollection> m_chargeparticleCol{"ArborCharged",Gaudi::DataHandle::Writer, this};
 	DataHandle<edm4hep::ReconstructedParticleCollection> nerecoparticleCol{"ArborNeutral",Gaudi::DataHandle::Writer, this};
 	DataHandle<edm4hep::ReconstructedParticleCollection> m_arborrecoparticleCol{"ArborPFO",Gaudi::DataHandle::Writer, this};
-     ArborToolLCIO * m_ArborToolLCIO;
-	
+    ArborToolLCIO * m_ArborToolLCIO;
+
+    Gaudi::Property<bool>   m_readLCIO{this, "ReadLCIO", true, "Read sim file with LCIO"};
+
 };
 
 
diff --git a/Reconstruction/PFA/Arbor/src/DetectorPos.cc b/Reconstruction/PFA/Arbor/src/DetectorPos.cc
index cc70613b44bc445fa51e4e885d57fad0224a3106..ed32f0bc02161876f7377bbfacefa510ecd82249 100644
--- a/Reconstruction/PFA/Arbor/src/DetectorPos.cc
+++ b/Reconstruction/PFA/Arbor/src/DetectorPos.cc
@@ -1,22 +1,23 @@
 #include <TMath.h>
 #include "DetectorPos.hh"
+// #include "Arbor/DetectorPos.hh"
 
 using namespace std;
 
-const double pi = acos(-1.0); 
+const double pi = acos(-1.0);
 
 //Geometric Parameter - ... need to be changed for different detector models
 
 int BarrelFlag( TVector3 inputPos)
 {
-	int isBarrel = 0;	
+	int isBarrel = 0;
 
 	if(fabs(inputPos[2]) < ECALHalfZ)
 	{
-		isBarrel = 1; 
+		isBarrel = 1;
 	}
 
-	return isBarrel; 
+	return isBarrel;
 }
 
 int DepthFlag( TVector3 inputPos )      //Used to calculate depth of given position...
@@ -79,7 +80,7 @@ TVector3 CalVertex( TVector3 Pos1, TVector3 Dir1, TVector3 Pos2, TVector3 Dir2 )
 
 int TPCPosition( TVector3 inputPos )
 {
-	int flagPos(-1); // == 0 means inside TPC, == 1 means outside; 
+	int flagPos(-1); // == 0 means inside TPC, == 1 means outside;
 
 	if( fabs(inputPos[2]) > ECALHalfZ || sqrt( inputPos[0]*inputPos[0] + inputPos[1]*inputPos[1] ) > TPCRadius ) flagPos = 1;
 	else flagPos = 0;
@@ -135,7 +136,7 @@ float DisSeedSurfaceSimple( TVector3 SeedPos )        //ECAL, HCAL, EndCapRing..
 	float DisR = SeedPos.Perp() - ECALRadius;
 	if(DisR < 0 && DisZ > 0)
 	{
-		DisSS = DisZ; 
+		DisSS = DisZ;
 	}
 	else if(DisZ < 0 && DisR > 0)
 	{
@@ -167,25 +168,25 @@ float DisSeedSurfaceClu( Cluster * a_clu )        //ECAL, HCAL, EndCapRing...
 float DisTPCBoundary( TVector3 Pos )
 {
 	float DisZ = TMath::Min( fabs(ECALHalfZ-Pos.Z()),fabs(ECALHalfZ+Pos.Z()) );
-	float DisR = ECALRadius - Pos.Perp();  
+	float DisR = ECALRadius - Pos.Perp();
 	float Dis = TMath::Min(DisZ, DisR);
 
-	return Dis; 
+	return Dis;
 }
 
 float DistanceChargedParticleToCluster(TVector3 CPRefPos, TVector3 CPRefMom, TVector3 CluPosition)	//Extend to Track/MCP
 {
 	// Line extrapolation from RefPos with RefMom, calculate the minimal distance to Cluster
 
-	float DisCPClu = 0; 
-	TVector3 Diff_Clu_CPRef, NormCPRefMom; 
+	float DisCPClu = 0;
+	TVector3 Diff_Clu_CPRef, NormCPRefMom;
 
-	Diff_Clu_CPRef = CluPosition - CPRefPos; 
+	Diff_Clu_CPRef = CluPosition - CPRefPos;
 	NormCPRefMom = 1.0/CPRefMom.Mag()*CPRefMom;
-	float ProDis = Diff_Clu_CPRef.Dot(NormCPRefMom);	
+	float ProDis = Diff_Clu_CPRef.Dot(NormCPRefMom);
 
 	DisCPClu = sqrt(Diff_Clu_CPRef.Mag()*Diff_Clu_CPRef.Mag() - ProDis*ProDis);
 
-	return DisCPClu; 
+	return DisCPClu;
 }
 
diff --git a/Reconstruction/PFA/Arbor/src/HelixClassD.cc b/Reconstruction/PFA/Arbor/src/HelixClassD.cc
index 20b79466237d97a8d7bf5314ec00d3867cb5e453..023a336eebcbd70ec18b73be056726d4aaead65b 100644
--- a/Reconstruction/PFA/Arbor/src/HelixClassD.cc
+++ b/Reconstruction/PFA/Arbor/src/HelixClassD.cc
@@ -40,7 +40,7 @@ void HelixClassD::Initialize_VP(float * pos, float * mom, float q, float B) {
     double radius = pxy/double(_FCT*B);
     double xCentre = double(pos[0]) + radius*double(cos(_phiMomRefPoint-_const_pi2*q));
     double yCentre = double(pos[1]) + radius*double(sin(_phiMomRefPoint-_const_pi2*q));
-    
+
     double d0;
 
     if (q>0) {
@@ -54,17 +54,17 @@ void HelixClassD::Initialize_VP(float * pos, float * mom, float q, float B) {
 
 //     if (fabs(_d0)>0.001 ) {
 //       std::cout << "New helix : " << std::endl;
-//       std::cout << " Position : " << pos[0] 
+//       std::cout << " Position : " << pos[0]
 // 		<< " " << pos[1]
 // 		<< " " << pos[2] << std::endl;
 //       std::cout << " Radius = " << _radius << std::endl;
-//       std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl;  
+//       std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl;
 //       std::cout << " D0 = " << _d0 << std::endl;
 //     }
 
     _pxAtPCA = _pxy*cos(_phi0);
     _pyAtPCA = _pxy*sin(_phi0);
-    float deltaPhi = _phiRefPoint - _phiAtPCA;    
+    float deltaPhi = _phiRefPoint - _phiAtPCA;
     float xCircles = -pos[2]*q/(_radius*_tanLambda) - deltaPhi;
     xCircles = xCircles/_const_2pi;
     int nCircles;
@@ -78,7 +78,7 @@ void HelixClassD::Initialize_VP(float * pos, float * mom, float q, float B) {
 	n1 = int(xCircles) - 1;
 	n2 = n1 + 1;
     }
-    
+
     if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
 	nCircles = n1;
     }
@@ -89,7 +89,7 @@ void HelixClassD::Initialize_VP(float * pos, float * mom, float q, float B) {
 
 }
 
-void HelixClassD::Initialize_Canonical(float phi0, float d0, float z0, 
+void HelixClassD::Initialize_Canonical(float phi0, float d0, float z0,
 				      float omega, float tanLambda, float B) {
     _omega = omega;
     _d0 = d0;
@@ -99,20 +99,20 @@ void HelixClassD::Initialize_Canonical(float phi0, float d0, float z0,
     _charge = omega/fabs(omega);
     _radius = 1./fabs(omega);
     _xAtPCA = -_d0*sin(_phi0);
-    _yAtPCA = _d0*cos(_phi0);    
+    _yAtPCA = _d0*cos(_phi0);
     _referencePoint[0] = _xAtPCA;
     _referencePoint[1] = _yAtPCA;
     _referencePoint[2] = _z0;
     _pxy = _FCT*B*_radius;
     _momentum[0] = _pxy*cos(_phi0);
     _momentum[1] = _pxy*sin(_phi0);
-    _momentum[2] = _tanLambda * _pxy;    
+    _momentum[2] = _tanLambda * _pxy;
     _pxAtPCA = _momentum[0];
     _pyAtPCA = _momentum[1];
     _phiMomRefPoint = atan2(_momentum[1],_momentum[0]);
-    _xCentre = _referencePoint[0] + 
+    _xCentre = _referencePoint[0] +
       _radius*cos(_phi0-_const_pi2*_charge);
-    _yCentre = _referencePoint[1] + 
+    _yCentre = _referencePoint[1] +
       _radius*sin(_phi0-_const_pi2*_charge);
     _phiAtPCA = atan2(-_yCentre,-_xCentre);
     _phiRefPoint =  _phiAtPCA ;
@@ -120,7 +120,7 @@ void HelixClassD::Initialize_Canonical(float phi0, float d0, float z0,
 }
 
 
-void HelixClassD::Initialize_BZ(float xCentre, float yCentre, float radius, 
+void HelixClassD::Initialize_BZ(float xCentre, float yCentre, float radius,
 			       float bZ, float phi0, float B, float signPz,
 			       float zBegin) {
 
@@ -148,8 +148,8 @@ void HelixClassD::Initialize_BZ(float xCentre, float yCentre, float radius,
   _tanLambda = _momentum[2]/_pxy;
   _momentum[0] = _pxy*cos(_phiMomRefPoint);
   _momentum[1] = _pxy*sin(_phiMomRefPoint);
-  
-  float deltaPhi = _phiRefPoint - _phiAtPCA;    
+
+  float deltaPhi = _phiRefPoint - _phiAtPCA;
   float xCircles = bZ*_referencePoint[2] - deltaPhi;
   xCircles = xCircles/_const_2pi;
   int nCircles;
@@ -163,14 +163,14 @@ void HelixClassD::Initialize_BZ(float xCentre, float yCentre, float radius,
     n1 = int(xCircles) - 1;
     n2 = n1 + 1;
   }
-  
+
   if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
     nCircles = n1;
   }
   else {
     nCircles = n2;
-  }  
-  _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ;  
+  }
+  _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ;
   _bField = B;
 
 }
@@ -225,7 +225,7 @@ float HelixClassD::getCharge() {
     return _charge;
 }
 
-float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay, 
+float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
 			      float * ref , float * point) {
 
   float time;
@@ -234,7 +234,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
 
 
   if (AA <= 0) {
-    time = -1.0e+20; 
+    time = -1.0e+20;
     return time;
   }
 
@@ -242,7 +242,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
   float BB = ax*(x0-_xCentre) + ay*(y0-_yCentre);
   BB = BB / AA;
 
-  float CC = (x0-_xCentre)*(x0-_xCentre) 
+  float CC = (x0-_xCentre)*(x0-_xCentre)
     + (y0-_yCentre)*(y0-_yCentre) - _radius*_radius;
 
   CC = CC / AA;
@@ -250,7 +250,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
   float DET = BB*BB - CC;
   float tt1 = 0.;
   float tt2 = 0.;
-  float xx1,xx2,yy1,yy2; 
+  float xx1,xx2,yy1,yy2;
 
 
   if (DET < 0 ) {
@@ -260,8 +260,8 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
     point[2]=0.0;
     return time;
   }
-  
-  
+
+
   tt1 = - BB + sqrt(DET);
   tt2 = - BB - sqrt(DET);
 
@@ -269,7 +269,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
   yy1 = y0 + tt1*ay;
   xx2 = x0 + tt2*ax;
   yy2 = y0 + tt2*ay;
-  
+
   float phi1 = atan2(yy1-_yCentre,xx1-_xCentre);
   float phi2 = atan2(yy2-_yCentre,xx2-_xCentre);
   float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre);
@@ -280,14 +280,14 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
   if (dphi1 < 0 && _charge < 0) {
     dphi1 = dphi1 + _const_2pi;
   }
-  else if (dphi1 > 0 && _charge > 0) { 
+  else if (dphi1 > 0 && _charge > 0) {
     dphi1 = dphi1 - _const_2pi;
   }
 
   if (dphi2 < 0 && _charge < 0) {
     dphi2 = dphi2 + _const_2pi;
   }
-  else if (dphi2 > 0 && _charge > 0) { 
+  else if (dphi2 > 0 && _charge > 0) {
     dphi2 = dphi2 - _const_2pi;
   }
 
@@ -299,7 +299,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
     std::cout << "WARNING " << tt1 << std::endl;
   if (tt2 < 0. )
     std::cout << "WARNING " << tt2 << std::endl;
-  
+
 
   if (tt1 < tt2) {
     point[0] = xx1;
@@ -314,7 +314,7 @@ float HelixClassD::getPointInXY(float x0, float y0, float ax, float ay,
 
   point[2] = ref[2]+time*_momentum[2];
 
-  
+
 
   return time;
 
@@ -340,17 +340,17 @@ float HelixClassD::getPointOnCircle(float Radius, float * ref, float * point) {
   }
 
   float phiCentre = atan2(_yCentre,_xCentre);
-  float phiStar   = Radius*Radius + distCenterToIP*distCenterToIP 
+  float phiStar   = Radius*Radius + distCenterToIP*distCenterToIP
                                     - _radius*_radius;
 
   phiStar = 0.5*phiStar/fmax(1.0e-20,Radius*distCenterToIP);
-  
-  if (phiStar > 1.0) 
+
+  if (phiStar > 1.0)
     phiStar = 0.9999999;
-  
+
   if (phiStar < -1.0)
     phiStar = -0.9999999;
-  
+
   phiStar = acos(phiStar);
 
   float tt1,tt2,time;
@@ -372,14 +372,14 @@ float HelixClassD::getPointOnCircle(float Radius, float * ref, float * point) {
   if (dphi1 < 0 && _charge < 0) {
     dphi1 = dphi1 + _const_2pi;
   }
-  else if (dphi1 > 0 && _charge > 0) { 
+  else if (dphi1 > 0 && _charge > 0) {
     dphi1 = dphi1 - _const_2pi;
   }
 
   if (dphi2 < 0 && _charge < 0) {
     dphi2 = dphi2 + _const_2pi;
   }
-  else if (dphi2 > 0 && _charge > 0) { 
+  else if (dphi2 > 0 && _charge > 0) {
     dphi2 = dphi2 - _const_2pi;
   }
 
@@ -391,7 +391,7 @@ float HelixClassD::getPointOnCircle(float Radius, float * ref, float * point) {
     std::cout << "WARNING " << tt1 << std::endl;
   if (tt2 < 0. )
     std::cout << "WARNING " << tt2 << std::endl;
-  
+
 
   float time2;
   if (tt1 < tt2) {
@@ -413,7 +413,7 @@ float HelixClassD::getPointOnCircle(float Radius, float * ref, float * point) {
 
   point[2] = ref[2]+time*_momentum[2];
   point[5] = ref[2]+time2*_momentum[2];
-  
+
 
   return time;
 
@@ -490,7 +490,7 @@ float HelixClassD::getDistanceToPoint(float * xPoint, float * Distance) {
   float DistXY = (_xCentre-xPoint[0])*(_xCentre-xPoint[0]) + (_yCentre-xPoint[1])*(_yCentre-xPoint[1]);
   DistXY = sqrt(DistXY);
   DistXY = fabs(DistXY - _radius);
-  
+
   int nCircles = 0;
 
   if (fabs(_tanLambda*_radius)>1.0e-20) {
@@ -506,7 +506,7 @@ float HelixClassD::getDistanceToPoint(float * xPoint, float * Distance) {
 	n1 = int(xCircles) - 1;
 	n2 = n1 + 1;
     }
-    
+
     if (fabs(n1-xCircles) < fabs(n2-xCircles)) {
 	nCircles = n1;
     }
@@ -515,7 +515,7 @@ float HelixClassD::getDistanceToPoint(float * xPoint, float * Distance) {
     }
 
   }
-  
+
   float DPhi = _const_2pi*((float)nCircles) + phi - phi0;
 
   zOnHelix = _referencePoint[2] - _charge*_radius*_tanLambda*DPhi;
@@ -601,10 +601,10 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
 
   float x01 = getXC();
   float y01 = getYC();
-  
+
   float x02 = helix->getXC();
   float y02 = helix->getYC();
-  
+
   float rad1 = getRadius();
   float rad2 = helix->getRadius();
 
@@ -635,7 +635,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     phi1 = phi0 + alpha;
     phi2 = phi0 - alpha;
   }
-  
+
 
   float ref1[3];
   float ref2[3];
@@ -643,7 +643,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     ref1[i]=_referencePoint[i];
     ref2[i]=helix->getReferencePoint()[i];
   }
-  
+
   float pos1[3];
   float pos2[3];
   float mom1[3];
@@ -661,9 +661,9 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
 
     getPointOnCircle(R1,ref1,pos1);
     helix->getPointOnCircle(R2,ref2,pos2);
-    
+
   }
-  else {    
+  else {
 
     float xSect1 = x02 + rad2*cos(phi1);
     float ySect1 = y02 + rad2*sin(phi1);
@@ -676,7 +676,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     float temp21[3];
     float temp22[3];
 
-    float phiI2  = atan2(ref2[1]-y02,ref2[0]-x02); 
+    float phiI2  = atan2(ref2[1]-y02,ref2[0]-x02);
     float phiF21 = atan2(ySect1-y02,xSect1-x02);
     float phiF22 = atan2(ySect2-y02,xSect2-x02);
     float deltaPhi21 = phiF21 - phiI2;
@@ -687,14 +687,14 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     if (deltaPhi21 < 0 && charge2 < 0) {
       deltaPhi21 += _const_2pi;
     }
-    else if (deltaPhi21 > 0 && charge2 > 0) { 
+    else if (deltaPhi21 > 0 && charge2 > 0) {
       deltaPhi21 -= _const_2pi;
     }
 
     if (deltaPhi22 < 0 && charge2 < 0) {
       deltaPhi22 += _const_2pi;
     }
-    else if (deltaPhi22 > 0 && charge2 > 0) { 
+    else if (deltaPhi22 > 0 && charge2 > 0) {
       deltaPhi22 -= _const_2pi;
     }
 
@@ -706,7 +706,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
 
     temp21[0] = xSect1; temp21[1] = ySect1; temp21[2] = Z21;
     temp22[0] = xSect2; temp22[1] = ySect2; temp22[2] = Z22;
-    
+
 
 //     std::cout << "temp21 = " << temp21[0] << " " << temp21[1] << " " << temp21[2] << std::endl;
 //     std::cout << "temp22 = " << temp22[0] << " " << temp22[1] << " " << temp22[2] << std::endl;
@@ -715,7 +715,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     float temp11[3];
     float temp12[3];
 
-    float phiI1  = atan2(ref1[1]-y01,ref1[0]-x01); 
+    float phiI1  = atan2(ref1[1]-y01,ref1[0]-x01);
     float phiF11 = atan2(ySect1-y01,xSect1-x01);
     float phiF12 = atan2(ySect2-y01,xSect2-x01);
     float deltaPhi11 = phiF11 - phiI1;
@@ -726,14 +726,14 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
     if (deltaPhi11 < 0 && charge1 < 0) {
       deltaPhi11 += _const_2pi;
     }
-    else if (deltaPhi11 > 0 && charge1 > 0) { 
+    else if (deltaPhi11 > 0 && charge1 > 0) {
       deltaPhi11 -= _const_2pi;
     }
 
     if (deltaPhi12 < 0 && charge1 < 0) {
       deltaPhi12 += _const_2pi;
     }
-    else if (deltaPhi12 > 0 && charge1 > 0) { 
+    else if (deltaPhi12 > 0 && charge1 > 0) {
       deltaPhi12 -= _const_2pi;
     }
 
@@ -745,7 +745,7 @@ float HelixClassD::getDistanceToHelix(HelixClassD * helix, float * pos, float *
 
     temp11[0] = xSect1; temp11[1] = ySect1; temp11[2] = Z11;
     temp12[0] = xSect2; temp12[1] = ySect2; temp12[2] = Z12;
-    
+
 //     std::cout << "temp11 = " << temp11[0] << " " << temp11[1] << " " << temp11[2] << std::endl;
 //     std::cout << "temp12 = " << temp12[0] << " " << temp12[1] << " " << temp12[2] << std::endl;
 
diff --git a/Reconstruction/PFA/Arbor/src/MarlinArbor.cc b/Reconstruction/PFA/Arbor/src/MarlinArbor.cc
index fb930a683b1f6fb98db07028e453d2f8fc08a5dc..3ebba5dcbe7f8ea7c97f15f0b3e14c99d0073027 100644
--- a/Reconstruction/PFA/Arbor/src/MarlinArbor.cc
+++ b/Reconstruction/PFA/Arbor/src/MarlinArbor.cc
@@ -18,6 +18,11 @@
 #include "edm4hep/MCParticleCollection.h"
 
 #include "cellIDDecoder.h"
+#include <DDRec/DetectorData.h>
+#include <DDRec/CellIDPositionConverter.h>
+#include "DetInterface/IGeomSvc.h"
+
+#include "DecoderHelper/DD4hep2Lcio.h"
 
 #include "DD4hep/Detector.h"
 #include "DD4hep/IDDescriptor.h"
@@ -42,11 +47,11 @@
 
 using namespace std;
 
-extern linkcoll InitLinks; 
-extern linkcoll IterLinks_1; 
-extern linkcoll IterLinks; 
-extern linkcoll links_debug; 
-extern branchcoll Trees; 
+extern linkcoll InitLinks;
+extern linkcoll IterLinks_1;
+extern linkcoll IterLinks;
+extern linkcoll links_debug;
+extern branchcoll Trees;
 extern std::vector<int> IsoHitsIndex;
 
 //std::vector<std::string> CaloHitCollections;
@@ -54,23 +59,30 @@ extern std::vector<int> IsoHitsIndex;
 DECLARE_COMPONENT(MarlinArbor)
 
 MarlinArbor::MarlinArbor(const std::string& name, ISvcLocator* svcLoc)
-     : GaudiAlgorithm(name, svcLoc), 
+     : GaudiAlgorithm(name, svcLoc),
           _eventNr(0),_output(0)
 {
 }
 
 StatusCode MarlinArbor::initialize() {
 
-	
-	_cepc_thresholds.push_back(10);
+// ???
+	// _cepc_thresholds.push_back(10);
+	// _cepc_thresholds.push_back(90);
+	// _cepc_thresholds.push_back(50);
+	// _cepc_thresholds.push_back(7.5);
+
+	m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6";
+    _cepc_thresholds.push_back(20);
 	_cepc_thresholds.push_back(90);
 	_cepc_thresholds.push_back(50);
-	_cepc_thresholds.push_back(7.5);
+	_cepc_thresholds.push_back(11);
 
      m_geosvc = service<IGeomSvc>("GeomSvc");
 
       ISvcLocator* svcloc = serviceLocator();
-      m_ArborToolLCIO=new ArborToolLCIO("arborTools",svcloc);
+    //   m_ArborToolLCIO=new ArborToolLCIO("arborTools",svcloc);
+      m_ArborToolLCIO=new ArborToolLCIO("arborTools",svcloc,m_readLCIO);
          for(unsigned int i = 0; i < m_ecalReadoutNames.value().size(); i++){
              m_col_readout_map[m_ecalColNames.value().at(i)] = m_ecalReadoutNames.value().at(i);
          }
@@ -117,66 +129,181 @@ StatusCode MarlinArbor::execute()
      //if(_eventNr % m_reportEvery == 0) cout<<"eventNr: "<<_eventNr<<endl;
      _eventNr++;
 
-	MarlinArbor::HitsPreparation();	//Absorb isolated hits; 
+	MarlinArbor::HitsPreparation();	//Absorb isolated hits;
 
 	TVector3 currHitPos;
 
 	std::vector< TVector3 > inputHitsPos;
-	std::vector< ArborHit > inputABHit; 
-	std::vector< edm4hep::CalorimeterHit > inputHits;  
-	std::vector< edm4hep::CalorimeterHit > inputECALHits;  
-	std::vector< edm4hep::CalorimeterHit > inputHCALHits;  
-	std::vector< std::vector<int> > Sequence; 
-	int LayerNum = 0; 
-	int StaveNum = 0; 
-	int SubDId = -10; 
-	float Depth = 0; 
-	int KShift = 0; 
-	TVector3 TrkEndPointPos; 
+	std::vector< ArborHit > inputABHit;
+	std::vector< edm4hep::CalorimeterHit > inputHits;
+	std::vector< edm4hep::CalorimeterHit > inputECALHits;
+	std::vector< edm4hep::CalorimeterHit > inputHCALHits;
+	std::vector< std::vector<int> > Sequence;
+	int LayerNum = 0;
+	int StaveNum = 0;
+	int SubDId = -10;
+	float Depth = 0;
+	int KShift = 0;
+	TVector3 TrkEndPointPos;
 	std::vector<edm4hep::CalorimeterHit> IsoHits;
 
+
+    cout<<"[YX debug - MarlinArbor] InputCollections.size() = "<<_calCollections.size()<<endl;
+
+    unsigned int nECALCol = m_ecalColNames.size();
+    unsigned int nHCALCol = m_hcalColNames.size();
+
 	for(unsigned int i1 = 0; i1 < _calCollections.size(); i1++)
 	{
 
-		std::cout<<i1<<"th collection"<<m_col_readout_map[m_ecalColNames.value().at(i1)]<<std::endl;
+		// cout<<"[YX debug - MarlinArbor] CaloHitCollections "<<i1<<endl;
+
+		if(i1<nECALCol)
+            std::cout<<"[YX debug - MarlinArbor] CaloHitCollections "<<i1<<": "<<m_col_readout_map[m_ecalColNames.value().at(i1)]<<std::endl;
+        else
+            std::cout<<"[YX debug - MarlinArbor] CaloHitCollections "<<i1<<": "<<m_col_readout_map[m_hcalColNames.value().at(i1-nECALCol)]<<std::endl;
+
+
 		std::string tmp_readout;
-		
-	      if(i1<2)tmp_readout = m_col_readout_map[m_ecalColNames.value().at(i1)];
-	      else
-		      tmp_readout = m_col_readout_map[m_hcalColNames.value().at(i1-2)];
-
-	      std::cout<<tmp_readout<<std::endl;
-              // get the DD4hep readout
-              m_decoder = m_geosvc->getDecoder(tmp_readout);
-			KShift = 0;
-			SubDId = -1; 
 
-			if( i1 < _EcalCalCollections.size() )
-				SubDId = 1; 
-			else if( i1 < _EcalCalCollections.size() + _HcalCalCollections.size() )
+	      //   if(i1<2)tmp_readout = m_col_readout_map[m_ecalColNames.value().at(i1)];
+        if(i1<nECALCol)
+            tmp_readout = m_col_readout_map[m_ecalColNames.value().at(i1)];
+        else
+            tmp_readout = m_col_readout_map[m_hcalColNames.value().at(i1-nECALCol)];
+        //   tmp_readout = m_col_readout_map[m_hcalColNames.value().at(i1-2)];
+
+	      std::cout<<"tmp_readout: "<<tmp_readout<<std::endl;
+
+            // // get the DD4hep readout
+              // m_decoder = m_geosvc->getDecoder(tmp_readout);
+
+			KShift = 0;
+			SubDId = -1;
+
+			// ???
+			// if( i1 < _EcalCalCollections.size() )
+            // 	SubDId = 1;
+			// else if( i1 < _EcalCalCollections.size() + _HcalCalCollections.size() )
+			// 	SubDId = 2;
+			// else
+			// 	SubDId = 3;
+
+			// if(i1 >  _EcalCalCollections.size() - 1)
+			// 	KShift = 100;
+			// else if( i1 == _calCollections.size() - 2)	//HCAL Ring
+			// 	KShift = 50;
+
+			if( i1 < _ecalCollections.size() )
+				SubDId = 1;
+			else if( i1 < _ecalCollections.size() + _hcalCollections.size() )
 				SubDId = 2;
 			else
-				SubDId = 3; 
+				SubDId = 3;
 
-			if(i1 >  _EcalCalCollections.size() - 1)
-				KShift = 100; 
+			if(i1 >  _ecalCollections.size() - 1)
+				KShift = 100;
 			else if( i1 == _calCollections.size() - 2)	//HCAL Ring
 				KShift = 50;
+            // !!!
 
 			auto CaloHitColl = _calCollections[i1]->get();
-		
+
+            int i2 = 0;
+
 			//int NHitsCurrCol = CaloHitColl->getNumberOfElements();
 			//CellIDDecoder<CalorimeterHit> idDecoder(CaloHitColl);
-			for (auto a_hit: *CaloHitColl){
-		       		currHitPos =  TVector3(a_hit.getPosition().x, a_hit.getPosition().y, a_hit.getPosition().z);
-		       		Depth = DisSeedSurface(currHitPos);
-
-				auto cellid = a_hit.getCellID();
-			       LayerNum = m_decoder->get(cellid, "layer")+ KShift;
-			       StaveNum=m_decoder->get(cellid, "stave");
-		       		
-		       		if(SubDId!=2 ){
+			for(auto a_hit: *CaloHitColl){
+                ID_UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str);
+                const std::string layerCodingString(m_encoder_str);
+                const std::string staveCodingString(m_encoder_str);
+	      		const std::string idCodingString(m_encoder_str);
+
+                const std::string staveCoding(m_ArborToolLCIO->GetStaveCoding(staveCodingString));
+                const std::string layerCoding(m_ArborToolLCIO->GetLayerCoding(layerCodingString));
+                // const std::string layerCoding(m_ArborToolLCIO->GetLayerCoding(idCodingString));
+	      		const std::string cellICoding(m_ArborToolLCIO->GetCellICoding(idCodingString));
+	      		const std::string cellJCoding(m_ArborToolLCIO->GetCellJCoding(idCodingString));
+
+                if(!m_readLCIO)
+                    m_decoder = m_geosvc->getDecoder(tmp_readout);
+
+                // m_decoder = m_geosvc->getDecoder("EcalBarrelCollection");
+                // if(!m_decoder) m_decoder = m_geosvc->getDecoder("EcalEndcapsCollection");
+
+                currHitPos =  TVector3(a_hit.getPosition().x, a_hit.getPosition().y, a_hit.getPosition().z);
+                Depth = DisSeedSurface(currHitPos);
+
+                if(m_readLCIO){
+                    LayerNum=cellIdDecoder(&a_hit)[layerCoding.c_str()] + 1 + KShift;
+                    StaveNum=cellIdDecoder(&a_hit)[staveCoding.c_str()] + 1 ;
+
+                    if(1){
+                        double hitposx = currHitPos.X();
+                        double hitposy = currHitPos.Y();
+                        double hitposz = currHitPos.Z();
+                        double hitposp = currHitPos.Perp();
+
+                        // int tmp_M = idDecoder(a_hit)["M"];
+                        int tmp_S = cellIdDecoder(&a_hit)[staveCoding.c_str()];
+                        int tmp_K = cellIdDecoder(&a_hit)[layerCoding.c_str()];
+                        int tmp_I = cellIdDecoder(&a_hit)[cellICoding.c_str()];
+                        int tmp_J = cellIdDecoder(&a_hit)[cellJCoding.c_str()];
+
+                        if(0) cout<<"[MarlinArbor] Hit Pos ("<<hitposx<<", "<<hitposy<<", "<<hitposz<<", "<<hitposp<<")mm:"<<endl;
+                        if(0) cout<<"[MarlinArbor] ---> M = xx, stave = "<<tmp_S<<", layer = "<<tmp_K<<", I(x) = "<<tmp_I<<", J(y) = "<<tmp_J<<endl;
+                        if(0) cout<<"[MarlinArbor] ---> StaveNum = "<<StaveNum<<", LayerNum = "<<LayerNum<<endl;
+                    }
+
+                }else{
+				    auto cellid = a_hit.getCellID();
+
+
+                    // SEcal05_siw_Barrel       <id>system:5,module:3,stave:4,tower:5,layer:6,wafer:6,cellX:32:-16,cellY:-16</id>
+                    // SEcal05_siw_Endcaps      <id>system:5,module:3,stave:4,tower:5,layer:6,wafer:6,x:32:-16,y:-16</id>
+                    // SEcal05_siw_ECRing_01    <id>system:5,module:3,stave:4,tower:3,layer:6,x:32:-16,y:-16</id>
+                    // SHcalRpc01_Barrel_01     <id>system:5,module:3,stave:3,tower:5,layer:6,slice:4,x:32:-16,y:-16</id>
+                    // SHcalRpc01_Endcaps_01    <id>system:5,module:3,stave:3,tower:5,layer:6,y:32:-16,x:-16</id>
+                    // SHcalRpc01_EndcapRing_01 <id>system:5,module:3,stave:4,tower:3,layer:6,y:32:-16,x:-16</id>
+
+                    int Raw_system = m_decoder->get(cellid, "system");
+                    int Raw_module = m_decoder->get(cellid, "module");
+                    int Raw_Stave = m_decoder->get(cellid, "stave");
+                    int Raw_Layer = m_decoder->get(cellid, "layer");
+
+                    int New_Layer = DD4hep2Lcio::CEPCv4::getEcalLayer(Raw_Layer);
+                    int New_Stave = DD4hep2Lcio::CEPCv4::getEcalBarrelStave(Raw_Stave);
+                    if(Raw_system==29){// ECAL endcap
+                        New_Stave = DD4hep2Lcio::CEPCv4::getEcalEndcapStave(Raw_Stave);
+                    }
+                    if(Raw_system==22 || Raw_system==30){
+                        New_Layer = DD4hep2Lcio::CEPCv4::getHcalLayer(Raw_Layer);
+                        New_Stave = DD4hep2Lcio::CEPCv4::getHcalStave(Raw_Stave);
+                    }
+                    LayerNum = New_Layer + KShift + 1;
+                    StaveNum = New_Stave + 1;
+
+                    // LayerNum = m_decoder->get(cellid, "layer") + KShift;
+                    // StaveNum = m_decoder->get(cellid, "stave");
+
+
+                    if(0){
+                        double hitposx = currHitPos.X();
+                        double hitposy = currHitPos.Y();
+                        double hitposz = currHitPos.Z();
+                        double hitposp = currHitPos.Perp();
+
+                        cout<<"[MarlinArbor] Hit Pos ("<<hitposx<<", "<<hitposy<<", "<<hitposz<<", "<<hitposp<<")mm:"<<endl;
+                        // cout<<"---> stave = "<<Raw_Stave<<", layer = "<<Raw_Layer<<", X = "<<Raw_cellX<<", Y = "<<Raw_cellY<<", wafer = "<<Raw_Wafer<<", tower = "<<Raw_Tower<<endl;
+
+                        cout<<"[MarlinArbor] ---> Raw M = "<<Raw_module<<", stave = "<<Raw_Stave<<", layer = "<<Raw_Layer<<", system = "<<Raw_system<<endl;
+                        cout<<"[MarlinArbor] ---> New M = "<<Raw_module<<", stave = "<<New_Stave<<", layer = "<<New_Layer<<", system = "<<Raw_system<<endl;
+                        cout<<"[MarlinArbor] ---> StaveNum = "<<StaveNum<<", LayerNum = "<<LayerNum<<endl;
+                    }
+
+                }
 
+		       		if(SubDId!=2 ){
 		       			inputECALHits.push_back(a_hit);
 		       		}
 		       		else{
@@ -185,15 +312,29 @@ StatusCode MarlinArbor::execute()
 		       		ArborHit a_abhit(currHitPos, LayerNum, 0, Depth, StaveNum, SubDId);
 		       		inputABHit.push_back(a_abhit);
 		       		inputHits.push_back(a_hit);
+
+
+                    // cout<<"[YX debug - MarlinArbor] Hit "<<i2<<", KShift = "<<KShift<<", LayerNum = "<<LayerNum<<", StaveNum = "<<StaveNum<<", SubDId = "<<SubDId<<", Depth = "<<Depth<<endl;
+                    // // auto cellID = a_hit.getCellID();
+                    // // cout<<"[YX debug - MarlinArbor] ---> raw layerNum = "<<m_decoder->get(cellID, "layer")<<", staveNum = "<<m_decoder->get(cellID, "stave")<<endl;
+                    // // cout<<"[YX debug - MarlinArbor] ---> raw cellID (DigiHit) = "<<cellID<<endl;
+
+
+
+
+                    i2+=1;
 		       }
-		
 
-			// cout<<i1<<"  Stat  "<<SubDId<<" ~~~ "<<inputABHit.size()<<endl; 
+
+			// cout<<i1<<"  Stat  "<<SubDId<<" ~~~ "<<inputABHit.size()<<endl;
 
 	}
 	//cout<<"hit size"<<inputHits.size()<<endl;
 
-	Sequence = Arbor(inputABHit, _cepc_thresholds);   
+	Sequence = Arbor(inputABHit, _cepc_thresholds);
+
+    cout<<"[YX debug - MarlinArbor] inputABHit.size() = "<<inputABHit.size()<<endl;
+    cout<<"[YX debug - MarlinArbor] Sequence.size() = "<<Sequence.size()<<endl;
 
 	m_ArborToolLCIO->ClusterBuilding( branchCol, inputHits, Trees, 0 );
 
@@ -207,6 +348,9 @@ StatusCode MarlinArbor::execute()
 	}
 
 	MakeIsoHits(IsoHits, m_isohitcol);
+
+    cout<<"[YX debug - MarlinArbor] End."<<endl;
+
 	return StatusCode::SUCCESS;
 }
 
diff --git a/Reconstruction/PFA/Arbor/src/MarlinArbor.hh b/Reconstruction/PFA/Arbor/src/MarlinArbor.hh
index e768ea3ff207d0dd91bbb8e1a5ddec1766190c8a..c68128af02d1b0c16588986dafa658a77d85f4ee 100644
--- a/Reconstruction/PFA/Arbor/src/MarlinArbor.hh
+++ b/Reconstruction/PFA/Arbor/src/MarlinArbor.hh
@@ -66,7 +66,7 @@ class MarlinArbor  : public GaudiAlgorithm
 		std::vector<std::string> _EcalPreShowerCollections;
 		std::vector<std::string> _EcalCalCollections;
 		std::vector<std::string> _HcalCalCollections;
-		std::vector<float> _cepc_thresholds; 
+		std::vector<float> _cepc_thresholds;
 
 
 	     typedef DataHandle<edm4hep::CalorimeterHitCollection>  CaloType;
@@ -76,6 +76,7 @@ class MarlinArbor  : public GaudiAlgorithm
 
      Gaudi::Property<std::vector<std::string>> m_ecalReadoutNames{this, "ECALReadOutNames", {"EcalBarrelCollection", "EcalEndcapsCollection","EcalEndcapRingCollection"}, "Name of readouts"};
      Gaudi::Property<std::vector<std::string>> m_hcalReadoutNames{this, "HCALReadOutNames", {"HcalBarrelCollection", "HcalEndcapsCollection","HcalEndcapRingCollection"}, "Name of readouts"};
+    Gaudi::Property<bool>   m_readLCIO{this, "ReadLCIO", true, "Read sim file with LCIO"};
      std::map<std::string, std::string> m_col_readout_map;
 
 	     std::vector<CaloType*> _ecalCollections;
@@ -83,34 +84,34 @@ class MarlinArbor  : public GaudiAlgorithm
 	     std::vector<CaloType*> _calCollections;
 
 		TTree *_outputTree;
-		std::string _treeFileName; 
-		int _EH; 
+		std::string _treeFileName;
+		int _EH;
 		float _HitPos[3];
 		float _BushP[3];
-		float _CloseDis; 
+		float _CloseDis;
 		float _HitEnergy;
 
-		int _CellSize; 
+		int _CellSize;
 		int _CaloTrackLengthCut;
 
 		int _Num, _Seg, _eventNr;
 		int numElements;
 
-		float _DHCALFirstThreshold; 
+		float _DHCALFirstThreshold;
 		float _InitLinkDisThreshold;
 
-		bool _DHCALSimuDigiMode; 
+		bool _DHCALSimuDigiMode;
 		bool _FlagInputSimHit;
 		bool _FlagMutePhoton;
 		bool _FlagMuteChargeParticle;
 		bool _FlagMuteGarlicHits;
-		bool _FlagUseTrackerEndHit; 
+		bool _FlagUseTrackerEndHit;
 		std::string m_encoder_str;
 
 		DataHandle<edm4hep::ClusterCollection>   branchCol{"EHBushes",Gaudi::DataHandle::Writer, this};
 		DataHandle<edm4hep::CalorimeterHitCollection>   m_isohitcol{"IsoHits",Gaudi::DataHandle::Writer, this};
-		TH2F *_h1, *_h2, *_h7; 
-		TH1F *_h3, *_h4, *_h5, *_h6; 
+		TH2F *_h1, *_h2, *_h7;
+		TH1F *_h3, *_h4, *_h5, *_h6;
 		std::ostream _output;
 		float _HLayerCut;
 
diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt
index dade7622c8f3144db1a18916bd5af4852739efdd..9f250bd8cce7ff83c0397e3fac9ca7775ab9d466 100644
--- a/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt
+++ b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt
@@ -17,7 +17,7 @@ gaudi_add_module(GaudiPandora
                       k4FWCore::k4FWCore
                       ${PandoraSDK_LIBRARIES}
                       ${LCContent_LIBRARIES}
-                      ${CLHEP_LIBRARIES} 
+                      ${CLHEP_LIBRARIES}
                       ${ROOT_LIBRARIES}
                       ${LCIO_LIBRARIES}
                       ${GEAR_LIBRARIES}
diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp
index bb63363fe1b6719569888bcdfeaa91d39a1a6481..503e802312d0ba15e64d4242e647f9bc840b4c03 100644
--- a/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp
+++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp
@@ -1,7 +1,7 @@
 /**
- * 
+ *
  *  @brief  Implementation of the calo hit creator class.
- * 
+ *
  *  $Log: $
  */
 
@@ -31,10 +31,10 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
     m_settings(settings),
     m_pPandora(pPandora)
 {
-    m_encoder_str = ""; 
-    m_encoder_str_MUON = ""; 
-    m_encoder_str_LCal = ""; 
-    m_encoder_str_LHCal = ""; 
+    m_encoder_str = "";
+    m_encoder_str_MUON = "";
+    m_encoder_str_LCal = "";
+    m_encoder_str_LHCal = "";
     if(encoder_style==0) // LCIO style
     {
         m_encoder_str     = "M:3,S-1:3,I:9,J:9,K-1:6";
@@ -44,7 +44,7 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
     }
     IGearSvc*  iSvc = 0;
     StatusCode sc = svcloc->service("GearSvc", iSvc, false);
-    if ( !sc ) 
+    if ( !sc )
     {
         throw "Failed to find GearSvc ...";
     }
@@ -55,7 +55,7 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
     }
     if(m_settings.m_use_dd4hep_geo){
         const dd4hep::rec::LayeredCalorimeterData * eCalBarrelExtension= PanUtil::getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::BARREL), ( dd4hep::DetType::AUXILIARY  |  dd4hep::DetType::FORWARD ) );
-        if(eCalBarrelExtension){ 
+        if(eCalBarrelExtension){
             m_eCalBarrelOuterZ        = eCalBarrelExtension->extent[3]/dd4hep::mm;
             m_eCalBarrelInnerPhi0     = eCalBarrelExtension->inner_phi0/dd4hep::rad;
             m_eCalBarrelInnerSymmetry = eCalBarrelExtension->inner_symmetry;
@@ -72,9 +72,9 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
             m_eCalBarrelInnerPhi0     = (_GEAR->getEcalBarrelParameters().getPhi0());
             m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder());
         }
-        //Get HCal Barrel extension by type, ignore plugs and rings 
+        //Get HCal Barrel extension by type, ignore plugs and rings
         const dd4hep::rec::LayeredCalorimeterData * hCalBarrelExtension= PanUtil::getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::HADRONIC | dd4hep::DetType::BARREL),( dd4hep::DetType::AUXILIARY |  dd4hep::DetType::FORWARD ) );
-        //Get HCal Endcap extension by type, ignore plugs and rings 
+        //Get HCal Endcap extension by type, ignore plugs and rings
         const dd4hep::rec::LayeredCalorimeterData * hCalEndcapExtension= PanUtil::getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::HADRONIC | dd4hep::DetType::ENDCAP),( dd4hep::DetType::AUXILIARY |  dd4hep::DetType::FORWARD ) );
         if(hCalBarrelExtension){
             m_hCalBarrelOuterZ             =   hCalBarrelExtension->extent[3]/dd4hep::mm;
@@ -113,7 +113,7 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
                 "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ?
                 _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order")
                 : 0));
-            const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); 
+            const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout());
             m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1);
         }
         if(hCalEndcapExtension){
@@ -137,10 +137,10 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
             m_hCalEndCapLayerThickness = hCalEndCapLayerLayout.getThickness(hCalEndCapLayerLayout.getNLayers() - 1);
 
         }
-        //Get Muon Barrel extension by type, ignore plugs and rings 
+        //Get Muon Barrel extension by type, ignore plugs and rings
         const dd4hep::rec::LayeredCalorimeterData * muonBarrelExtension= PanUtil::getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::MUON | dd4hep::DetType::BARREL),( dd4hep::DetType::AUXILIARY |  dd4hep::DetType::FORWARD ) );
         //fg: muon endcap is not used :
-        //Get Muon Endcap extension by type, ignore plugs and rings 
+        //Get Muon Endcap extension by type, ignore plugs and rings
         // const dd4hep::rec::LayeredCalorimeterData * muonEndcapExtension= getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::MUON | dd4hep::DetType::ENDCAP), ( dd4hep::DetType::AUXILIARY ) );
         if(muonBarrelExtension){
             m_muonBarrelOuterZ             =   muonBarrelExtension->extent[3]/dd4hep::mm;
@@ -191,7 +191,7 @@ CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora
             "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ?
             _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order")
             : 0));
-        const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); 
+        const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout());
         m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1);
         m_hCalEndCapOuterR        = (_GEAR->getHcalEndcapParameters().getExtent()[1]);
         m_hCalEndCapOuterZ        = (_GEAR->getHcalEndcapParameters().getExtent()[3]);
@@ -219,7 +219,7 @@ CaloHitCreator::~CaloHitCreator()
 
 pandora::StatusCode CaloHitCreator::CreateCaloHits(const CollectionMaps& collectionMaps)
 {
-    
+
     PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateECalCaloHits (collectionMaps));
     PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalCaloHits (collectionMaps));
     PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateMuonCaloHits (collectionMaps));
@@ -268,7 +268,7 @@ pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& col
                 endcapLayers= &(PanUtil::getExtension( ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::ENDCAP), ( dd4hep::DetType::AUXILIARY  |  dd4hep::DetType::FORWARD ) )->layers);
             }
             else{
-                barrelLayerLayout = &(_GEAR->getEcalBarrelParameters().getLayerLayout()); 
+                barrelLayerLayout = &(_GEAR->getEcalBarrelParameters().getLayerLayout());
                 endcapLayerLayout = &(_GEAR->getEcalEndcapParameters().getLayerLayout());
             }
 
@@ -316,7 +316,7 @@ pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& col
                     caloHitParameters.m_hitType = pandora::ECAL;
                     caloHitParameters.m_isDigital = false;
                     caloHitParameters.m_layer = m_settings.m_use_dd4hep_decoder == false ? cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1 : m_decoder->get(pCaloHit->getCellID(), "layer");// from 0 to 29, 0 is preshower layer
-                    int Stave = 0 ; 
+                    int Stave = 0 ;
                     if (m_settings.m_use_dd4hep_decoder == false){
                         Stave = cellIdDecoder(pCaloHit)[ staveCoding];
                     }
@@ -327,7 +327,7 @@ pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& col
                     }
                     //std::cout<<"0Stave="<<Stave<<",0layer="<<caloHitParameters.m_layer.Get()<<std::endl;
                     if (Stave<0) throw "wrong Stave";
-                    if (m_settings.m_use_preshower==false && caloHitParameters.m_layer.Get()<1) continue;//don't use preshower layer 
+                    if (m_settings.m_use_preshower==false && caloHitParameters.m_layer.Get()<1) continue;//don't use preshower layer
                     //std::cout<<"Stave="<<Stave<<",layer="<<caloHitParameters.m_layer.Get()<<std::endl;
                     caloHitParameters.m_isInOuterSamplingLayer = false;
                     this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters);
@@ -343,7 +343,7 @@ pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& col
                     else
                     {
                         if(m_settings.m_use_dd4hep_geo) this->GetEndCapCaloHitProperties(pCaloHit, *endcapLayers, caloHitParameters, absorberCorrection);
-                        
+
                         else                            this->GetEndCapCaloHitProperties(pCaloHit, *endcapLayerLayout, caloHitParameters, absorberCorrection);
                         caloHitParameters.m_hadronicEnergy = eCalToHadGeVEndCap * pCaloHit->getEnergy();
                     }
@@ -444,26 +444,26 @@ pandora::StatusCode CaloHitCreator::CreateHCalCaloHits(const CollectionMaps& col
                     //std::cout<<"HCAL layer="<<caloHitParameters.m_layer.Get()<<std::endl;
                     caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers);
                     this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters);
-                    int Stave = 0 ; 
+                    int Stave = 0 ;
                     if (m_settings.m_use_dd4hep_decoder == false){
                         Stave = cellIdDecoder(pCaloHit)[ staveCoding];
                     }
                     else{
                         Stave = m_decoder->get(pCaloHit->getCellID(), "stave");
                         Stave = DD4hep2Lcio::CEPCv4::getHcalStave(Stave);
-                        //Stave = Stave ==0 ? Stave+7 : Stave-1 ;//correct, same with LCIO  
+                        // Stave = Stave ==0 ? Stave+7 : Stave-1 ;//correct, same with LCIO
                         /*
                                     1                     0
                                    ****                  ****
                                 2 *    * 0            1 *    * 7
                                  *      *              *      *
-                                3*      * 7  --->     2*      * 6    
+                                3*      * 7  --->     2*      * 6
                                  *      *              *      *
-                                4 *    * 6            3 *    * 5 
-                                   ****                  ****  
+                                4 *    * 6            3 *    * 5
+                                   ****                  ****
                                     5                     4
-                            
-                            
+
+
                         */
                     }
 
@@ -551,7 +551,7 @@ pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& col
             }
             else{
                 plugLayerLayout= &(_GEAR->getYokePlugParameters().getLayerLayout());
-                barrelLayerLayout = &(_GEAR->getYokeBarrelParameters().getLayerLayout()); 
+                barrelLayerLayout = &(_GEAR->getYokeBarrelParameters().getLayerLayout());
                 endcapLayerLayout = &(_GEAR->getYokeEndcapParameters().getLayerLayout());
             }
 
@@ -570,7 +570,7 @@ pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& col
                     //std::cout<<"Muon layer="<<caloHitParameters.m_layer.Get()<<std::endl;
                     caloHitParameters.m_isInOuterSamplingLayer = true;
                     this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters);
-                    int Stave = 0 ; 
+                    int Stave = 0 ;
                     if (m_settings.m_use_dd4hep_decoder == false){
                         Stave = cellIdDecoder(pCaloHit)[ staveCoding];
                         /*
@@ -670,7 +670,7 @@ pandora::StatusCode CaloHitCreator::CreateLCalCaloHits(const CollectionMaps& col
 
             auto tmpCaloHit0 = pCaloHitCollection.at(0);
 
-            const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout()); 
+            const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout());
 
             ID_UTIL::CellIDDecoder<decltype(tmpCaloHit0)> cellIdDecoder(m_encoder_str_LCal);
             const std::string layerCodingString(m_encoder_str_LCal);
@@ -896,7 +896,7 @@ void CaloHitCreator::GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *c
     for (unsigned int i = 0, iMax = layers.size(); i < iMax; ++i)
     {
         float absorberThickness((layers[i].inner_thickness - layers[i].sensitive_thickness/2.0 )/dd4hep::mm);
-        
+
         if (i>0)
             absorberThickness += (layers[i-1].outer_thickness - layers[i-1].sensitive_thickness/2.0)/dd4hep::mm;
 
@@ -996,7 +996,7 @@ void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *c
         nIntLengths += layers[physicalLayer-1].outer_nInteractionLengths;
         layerAbsorberThickness += (layers[physicalLayer-1].outer_thickness -layers[physicalLayer].sensitive_thickness/2.0)/dd4hep::mm;
     }
-    
+
     caloHitParameters.m_cellThickness = thickness;
     caloHitParameters.m_nCellRadiationLengths = nRadLengths;
     caloHitParameters.m_nCellInteractionLengths = nIntLengths;
@@ -1008,11 +1008,11 @@ void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *c
         throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
     }
     absorberCorrection = 1.;
-    float absorberThickness_0 = 0; 
+    float absorberThickness_0 = 0;
     for (unsigned int i = 0, iMax = layers.size(); i < iMax; ++i)
     {
         float absorberThickness((layers[i].inner_thickness - layers[i].sensitive_thickness/2.0 )/dd4hep::mm);
-        
+
         if (i>0)
             absorberThickness += (layers[i-1].outer_thickness - layers[i-1].sensitive_thickness/2.0)/dd4hep::mm;
 
@@ -1097,7 +1097,7 @@ int CaloHitCreator::GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCal
 
 float CaloHitCreator::GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const
 {
-    
+
     const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]};
     if (symmetryOrder <= 2)
         return std::sqrt((pCaloHitPosition[0] * pCaloHitPosition[0]) + (pCaloHitPosition[1] * pCaloHitPosition[1]));
diff --git a/Reconstruction/ParticleID/CMakeLists.txt b/Reconstruction/ParticleID/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4c03899bc8eef5dbc0dc61450f05e5823eb82d41
--- /dev/null
+++ b/Reconstruction/ParticleID/CMakeLists.txt
@@ -0,0 +1,30 @@
+# gaudi_add_header_only_library(ParticleIDLib)
+
+# Modules
+gaudi_add_module(ParticleID
+                 SOURCES src/TPCDndxAlg.cpp
+                         src/DCHDndxAlg.cpp
+			 src/TofRecAlg.cpp
+                 LINK SimplePIDSvc
+                      Gaudi::GaudiAlgLib
+                      Gaudi::GaudiKernel
+                      DataHelperLib
+                      DetSegmentation
+                      DetInterface
+                      ${GSL_LIBRARIES}
+                      ${GEAR_LIBRARIES}
+                      ${LCIO_LIBRARIES}
+		      EDM4CEPC::edm4cepc EDM4CEPC::edm4cepcDict
+                      EDM4HEP::edm4hep EDM4HEP::edm4hepDict
+                      k4FWCore::k4FWCore
+)
+
+target_include_directories(ParticleID PUBLIC
+  $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>/include
+  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+
+install(TARGETS ParticleID
+  EXPORT CEPCSWTargets
+  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
+  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
+  COMPONENT dev)
diff --git a/Reconstruction/ParticleID/src/DCHDndxAlg.cpp b/Reconstruction/ParticleID/src/DCHDndxAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed9cf4afb4da94c9ed45e30d139ea01bf799a3d6
--- /dev/null
+++ b/Reconstruction/ParticleID/src/DCHDndxAlg.cpp
@@ -0,0 +1,252 @@
+#include "DCHDndxAlg.h"
+#include "DataHelper/HelixClass.h"
+#include "DataHelper/Navigation.h"
+#include "DetInterface/IGeomSvc.h"
+#include "UTIL/ILDConf.h"
+
+#include "DD4hep/Detector.h"
+#include "edm4hep/Hypothesis.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/Quantity.h"
+#include "edm4hep/Vector3d.h"
+#include "lcio.h"
+
+#include <cmath>
+#include <fstream>
+
+using namespace edm4hep;
+
+DECLARE_COMPONENT(DCHDndxAlg)
+
+DCHDndxAlg::DCHDndxAlg(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) {
+    // Input
+    declareProperty("SDTRecTrackCollection", _trackCol, "handler of the input track collection");
+    declareProperty("SDTRecTrackCollectionParticleAssociation", _trkParAssCol, "handler of the input track particle association collection");
+
+    // Output
+    declareProperty("DndxTracks", _dndxCol, "handler of the collection of dN/dx tracks");
+}
+
+StatusCode DCHDndxAlg::initialize() {
+    info() << "Initilize DndxAlg ..." << endmsg;
+
+    if (m_method == "Simple") {
+        m_pid_svc = service("SimplePIDSvc");
+    }
+    else {
+        m_pid_svc = nullptr;
+    }
+
+    m_geom_svc = service("GeomSvc");
+
+    return GaudiAlgorithm::initialize();
+}
+
+StatusCode DCHDndxAlg::execute() {
+    info() << "Dndx reconstruction started" << endmsg;
+    // static std::ofstream check_file("log.txt");
+    // static int ievent = 0;
+    // check_file << "--------                 Event " << ievent++ << " --------" << std::endl;
+
+    const edm4hep::TrackCollection* trkcol = nullptr;
+    const edm4hep::MCRecoTrackParticleAssociationCollection* trkparasscol = nullptr;
+    try {
+        trkcol = _trackCol.get();
+        trkparasscol = _trkParAssCol.get();
+    }
+    catch(...) {
+        //
+    }
+
+    if (trkcol == nullptr || trkparasscol == nullptr) {
+        return StatusCode::SUCCESS;
+    }
+
+    RecDqdxCollection* outCol = _dndxCol.createAndPut();
+
+    // check_file << "before track loop" << std::endl;
+
+    for (std::size_t i = 0; i < trkcol->size(); i++) {
+        // check_file << "  Track " << i << std::endl;
+        Track trk(trkcol->at(i));
+        
+        /// MC truth information
+        int pdgid = -999;
+        double p_truth = -999.;
+        
+        float max_weight = -999.;
+        int max_weight_idx = -1;
+        int ass_idx = 0;
+        for (auto ass : *trkparasscol) {
+            if (ass.getRec() == trk) {
+                float weight = ass.getWeight();
+                if (weight > max_weight) {
+                    max_weight = weight;
+                    max_weight_idx = ass_idx;
+                }
+            }
+            ass_idx++;
+        }
+        if (max_weight_idx < 0) continue;
+        pdgid = trkparasscol->at(max_weight_idx).getSim().getPDG();
+        double px = trkparasscol->at(max_weight_idx).getSim().getMomentum()[0];
+        double py = trkparasscol->at(max_weight_idx).getSim().getMomentum()[1];
+        double pz = trkparasscol->at(max_weight_idx).getSim().getMomentum()[2];
+        p_truth = sqrt(px*px + py*py + pz*pz);
+
+        // check_file << "before track par" << std::endl;
+
+        /// Track parameters
+        podio::RelationRange<edm4hep::TrackerHit> hitcol = trk.getTrackerHits();
+        if (hitcol.size() == 0) return StatusCode::SUCCESS;
+
+        // check_file << "before get track state" << std::endl;
+        int ihit_first = -1;
+        int ihit_last = -1;
+        TrackState trk_par;
+        for (auto it = trk.trackStates_begin(); it != trk.trackStates_end(); it++) {
+            if (it->location == 0) {
+                trk_par = *it;
+                break;
+            }
+        }
+        if (trk_par.tanLambda > 0.1) {
+            getFirstAndLastHitsByZ(hitcol, ihit_first, ihit_last);
+        }
+        else {
+            // check_file << "before get first and last by r" << std::endl;
+            getFirstAndLastHitsByRadius(hitcol, ihit_first, ihit_last);
+        }
+        if (ihit_first < 0 || ihit_last < 0 || ihit_first == ihit_last) continue;
+
+        // check_file << "before conversion unit. ihit_first, ihit_last = " << ihit_first << ", " << ihit_last << std::endl;
+        
+        // convert the position from cm to mm
+        Vector3d first_hit_pos = Vector3d(hitcol[ihit_first].getPosition().x*10.0, hitcol[ihit_first].getPosition().y*10.0, hitcol[ihit_first].getPosition().z*10.0);
+        Vector3d last_hit_pos = Vector3d(hitcol[ihit_last].getPosition().x*10.0, hitcol[ihit_last].getPosition().y*10.0, hitcol[ihit_last].getPosition().z*10.0);
+        double len, p, cos;
+        m_pid_svc->getTrackPars(first_hit_pos, last_hit_pos, trk, 0, len, p, cos);
+
+        // check_file << "before dndx calc" << std::endl;
+
+        /// dN/dx reconstruction
+        if (m_method.value() == "Simple") { // Track level implementation
+            int particle_type = m_pid_svc->getParticleType(pdgid);
+            double bg = m_pid_svc->getBetaGamma(p_truth, particle_type);
+            double dndx_mean = m_pid_svc->getDndxMean(bg, cos);
+            double dndx_sigma = m_pid_svc->getDndxSigma(bg, cos, len);
+            double dndx_meas = m_pid_svc->getDndx(dndx_mean, dndx_sigma);
+            // std::cout << "pdgid: " << pdgid << " bg: " << bg << " dndx_mean: " << dndx_mean << " dndx_sigma: " << dndx_sigma << " dndx_meas: " << dndx_meas << std::endl;
+
+            Quantity q;
+            q.value = dndx_meas;
+            q.error = dndx_sigma;
+
+            //check_file << "before hypotheses loop" << std::endl;
+            std::array<Hypothesis, 5> hypotheses;
+            for (int pid = 0; pid < 5; pid++) {
+                bg = m_pid_svc->getBetaGamma(p_truth, pid);
+                dndx_mean = m_pid_svc->getDndxMean(bg, cos);
+                dndx_sigma = m_pid_svc->getDndxSigma(bg, cos, len);
+
+                Hypothesis h;
+                h.chi2 = m_pid_svc->getChi2(dndx_meas, dndx_mean, dndx_sigma);
+                h.expected = dndx_mean;
+                h.sigma = dndx_sigma;
+
+                hypotheses[pid] = h;
+            }
+            //check_file << "after hypotheses loop" << std::endl;
+
+            MutableRecDqdx dndx_track(q, particle_type, 0, hypotheses);
+            dndx_track.setTrack(trk);
+            outCol->push_back(dndx_track);
+        }
+        else if (m_method.value() == "Full") {
+            // Hit level implementation, loop over hits ...
+        }
+        else {
+            return StatusCode::FAILURE;
+        }
+    }
+
+
+    return StatusCode::SUCCESS;
+
+}
+
+StatusCode DCHDndxAlg::finalize() {
+
+    return StatusCode::SUCCESS;
+}
+
+void DCHDndxAlg::getFirstAndLastHitsByZ(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last) {
+    bool first_dc_hit = true;
+    double zmin, zmax;
+    for (size_t ihit = 0; ihit < hitcol.size(); ihit++) {
+        auto hit = hitcol[ihit];
+        double z = hit.getPosition()[2];
+        if (!isCDCHit(&hit)) {
+            continue;
+        }
+        if (first_dc_hit) {
+            zmin = z;
+            zmax = z;
+            first = ihit;
+            last = ihit;
+            first_dc_hit = false;
+        }
+        else {
+            if (z < zmin) {
+                zmin = z;
+                first = ihit;
+            }
+            if (z > zmax) {
+                zmax = z;
+                last = ihit;
+            }
+        }
+    }
+}
+
+void DCHDndxAlg::getFirstAndLastHitsByRadius(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last) {
+    bool first_dc_hit = true;
+    double rmin, rmax;
+    for (size_t ihit = 0; ihit < hitcol.size(); ihit++) {
+        auto hit = hitcol[ihit];
+        double x = hit.getPosition()[0];
+        double y = hit.getPosition()[1];
+        double r = sqrt(x*x + y*y);
+        if (!isCDCHit(&hit)) {
+            continue;
+        }
+        if (first_dc_hit) {
+            rmin = r;
+            rmax = r;
+            first = ihit;
+            last = ihit;
+            first_dc_hit = false;
+        }
+        else {
+            if (r < rmin) {
+                rmin = r;
+                first = ihit;
+            }
+            if (r > rmax) {
+                rmax = r;
+                last = ihit;
+            }
+        }
+    }
+}
+
+int DCHDndxAlg::getDetTypeID(unsigned long long cellID) const {
+    UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string);
+    encoder.setValue(cellID);
+    return encoder[lcio::ILDCellID0::subdet];
+}
+
+bool DCHDndxAlg::isCDCHit(edm4hep::TrackerHit* hit){
+    return m_geom_svc->lcdd()->constant<int>("DetID_DC")==
+        getDetTypeID(hit->getCellID());
+}
\ No newline at end of file
diff --git a/Reconstruction/ParticleID/src/DCHDndxAlg.h b/Reconstruction/ParticleID/src/DCHDndxAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..3601d75505082a2983f896ac4a2d8cf2d2a4affa
--- /dev/null
+++ b/Reconstruction/ParticleID/src/DCHDndxAlg.h
@@ -0,0 +1,50 @@
+#ifndef DCHDndxAlg_h
+#define DCHDndxAlg_h 1
+
+#include "k4FWCore/DataHandle.h"
+
+#include "edm4hep/TrackerHit.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/MCRecoTrackParticleAssociationCollection.h"
+#include "edm4hep/RecDqdx.h"
+#include "edm4hep/RecDqdxCollection.h"
+
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+#include "SimplePIDSvc/ISimplePIDSvc.h"
+#include "DetInterface/IGeomSvc.h"
+
+/**
+ * @class DCHDndxAlg
+ * @brief Algorithm to calculate dN/dx for DCH
+ * @author Guang Zhao (zhaog@ihep.ac.cn)
+*/
+
+class DCHDndxAlg : public GaudiAlgorithm {
+public:
+    DCHDndxAlg(const std::string& name, ISvcLocator* svcLoc);
+
+    virtual StatusCode initialize();
+    virtual StatusCode execute();
+    virtual StatusCode finalize();
+
+protected:
+    Gaudi::Property<std::string> m_method{this, "Method", "Simple"};
+
+    DataHandle<edm4hep::TrackCollection> _trackCol{"SDTRecTrackCollection", Gaudi::DataHandle::Reader, this};
+    //DataHandle<edm4hep::MCRecoTrackerAssociationCollection> _hitassCol{"DCHitAssociationCollection", Gaudi::DataHandle::Reader, this};
+    DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection> _trkParAssCol{"SDTRecTrackCollectionParticleAssociation", Gaudi::DataHandle::Reader, this};
+    DataHandle<edm4hep::RecDqdxCollection> _dndxCol{"DndxTracks", Gaudi::DataHandle::Writer, this};
+
+private:
+    SmartIF<ISimplePIDSvc> m_pid_svc;
+    SmartIF<IGeomSvc> m_geom_svc;
+    void getFirstAndLastHitsByZ(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last);
+    void getFirstAndLastHitsByRadius(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last);
+    int getDetTypeID(unsigned long long cellID) const;
+    bool isCDCHit(edm4hep::TrackerHit* hit);
+};
+
+#endif
diff --git a/Reconstruction/ParticleID/src/TPCDndxAlg.cpp b/Reconstruction/ParticleID/src/TPCDndxAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0af4dbc23467ae88ce287faae3cf1fb7b2e130cd
--- /dev/null
+++ b/Reconstruction/ParticleID/src/TPCDndxAlg.cpp
@@ -0,0 +1,192 @@
+#include "TPCDndxAlg.h"
+#include "DataHelper/HelixClass.h"
+#include "DataHelper/Navigation.h"
+
+#include "edm4hep/Hypothesis.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/Quantity.h"
+#include "edm4hep/Vector3d.h"
+#include "lcio.h"
+
+#include <cmath>
+
+using namespace edm4hep;
+
+DECLARE_COMPONENT(TPCDndxAlg)
+
+TPCDndxAlg::TPCDndxAlg(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) {
+    // Input
+    declareProperty("ClupatraTracks", _trackCol, "handler of the input track collection");
+    declareProperty("ClupatraTracksParticleAssociation", _trkParAssCol, "handler of the input track particle association collection");
+
+    // Output
+    declareProperty("DndxTracks", _dndxCol, "handler of the collection of dN/dx tracks");
+}
+
+StatusCode TPCDndxAlg::initialize() {
+    info() << "Initilize DndxAlg ..." << endmsg;
+
+    if (m_method == "Simple") {
+        m_pid_svc = service("SimplePIDSvc");
+    }
+    else {
+        m_pid_svc = nullptr;
+    }
+
+    return GaudiAlgorithm::initialize();
+}
+
+StatusCode TPCDndxAlg::execute() {
+    info() << "Dndx reconstruction started" << endmsg;
+
+    const edm4hep::TrackCollection* trkcol = nullptr;
+    const edm4hep::MCRecoTrackParticleAssociationCollection* trkparasscol = nullptr;
+    try {
+        trkcol = _trackCol.get();
+        trkparasscol = _trkParAssCol.get();
+    }
+    catch(...) {
+        //
+    }
+
+    if (trkcol == nullptr || trkparasscol == nullptr) {
+        return StatusCode::SUCCESS;
+    }
+
+    RecDqdxCollection* outCol = _dndxCol.createAndPut();
+
+    // Navigation nav;
+    // nav.Initialize();
+    for (std::size_t i = 0; i < trkcol->size(); i++) {
+        Track trk(trkcol->at(i));
+        
+        /// MC truth information
+        int pdgid = -999;
+        double p_truth = -999.;
+
+        float max_weight = -999.;
+        int max_weight_idx = -1;
+        int ass_idx = 0;
+        for (auto ass : *trkparasscol) {
+            if (ass.getRec() == trk) {
+                float weight = ass.getWeight();
+                if (weight > max_weight) {
+                    max_weight = weight;
+                    max_weight_idx = ass_idx;
+                }
+            }
+            ass_idx++;
+        }
+        if (max_weight_idx < 0) continue;
+        pdgid = trkparasscol->at(max_weight_idx).getSim().getPDG();
+        double px = trkparasscol->at(max_weight_idx).getSim().getMomentum()[0];
+        double py = trkparasscol->at(max_weight_idx).getSim().getMomentum()[1];
+        double pz = trkparasscol->at(max_weight_idx).getSim().getMomentum()[2];
+        p_truth = sqrt(px*px + py*py + pz*pz);
+
+        /// Track parameters
+        podio::RelationRange<edm4hep::TrackerHit> hitcol = trk.getTrackerHits();
+        int nhits = hitcol.size();
+        if (nhits == 0) return StatusCode::SUCCESS;
+
+        int ihit_first = -1;
+        int ihit_last = -1;
+        TrackState trk_par;
+        for (auto it = trk.trackStates_begin(); it != trk.trackStates_end(); it++) {
+            if (it->location == TrackState::AtFirstHit) {
+                trk_par = *it;
+                break;
+            }
+        }
+        if (trk_par.tanLambda > 0.1) {
+            ihit_first = 0;
+            ihit_last = nhits - 1;
+        }
+        else {
+            getFirstAndLastHitsByRadius(hitcol, ihit_first, ihit_last);
+        }
+        if (ihit_first < 0 || ihit_last < 0 || ihit_first == ihit_last) continue;
+    
+        const Vector3d& first_hit_pos = hitcol[ihit_first].getPosition();
+        const Vector3d& last_hit_pos = hitcol[ihit_last].getPosition();
+        double len, p, cos;
+        m_pid_svc->getTrackPars(first_hit_pos, last_hit_pos, trk, TrackState::AtFirstHit, len, p, cos);
+
+        /// dN/dx reconstruction
+        if (m_method.value() == "Simple") { // Track level implementation
+            int particle_type = m_pid_svc->getParticleType(pdgid);
+            double bg = m_pid_svc->getBetaGamma(p_truth, particle_type);
+            double dndx_mean = m_pid_svc->getDndxMean(bg, cos);
+            double dndx_sigma = m_pid_svc->getDndxSigma(bg, cos, len);
+            double dndx_meas = m_pid_svc->getDndx(dndx_mean, dndx_sigma);
+
+            Quantity q;
+            q.value = dndx_meas;
+            q.error = dndx_sigma;
+
+            std::array<Hypothesis, 5> hypotheses;
+            for (int pid = 0; pid < 5; pid++) {
+                bg = m_pid_svc->getBetaGamma(p_truth, pid);
+                dndx_mean = m_pid_svc->getDndxMean(bg, cos);
+                dndx_sigma = m_pid_svc->getDndxSigma(bg, cos, len);
+
+                Hypothesis h;
+                h.chi2 = m_pid_svc->getChi2(dndx_meas, dndx_mean, dndx_sigma);
+                h.expected = dndx_mean;
+                h.sigma = dndx_sigma;
+
+                hypotheses[pid] = h;
+            }
+
+            MutableRecDqdx dndx_track(q, particle_type, 0, hypotheses);
+            dndx_track.setTrack(trk);
+            outCol->push_back(dndx_track);
+        }
+        else if (m_method.value() == "Full") {
+            // Hit level implementation, loop over hits ...
+        }
+        else {
+            return StatusCode::FAILURE;
+        }
+    }
+
+
+    return StatusCode::SUCCESS;
+
+}
+
+StatusCode TPCDndxAlg::finalize() {
+
+    return StatusCode::SUCCESS;
+}
+
+void TPCDndxAlg::getFirstAndLastHitsByRadius(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last) {
+    bool first_hit = true;
+    double rmin, rmax;
+    for (size_t ihit = 0; ihit < hitcol.size(); ihit++) {
+        auto hit = hitcol[ihit];
+        double x = hit.getPosition()[0];
+        double y = hit.getPosition()[1];
+        double r = sqrt(x*x + y*y);
+        // if (!isCDCHit(&hit)) {
+        //     continue;
+        // }
+        if (first_hit) {
+            rmin = r;
+            rmax = r;
+            first = ihit;
+            last = ihit;
+            first_hit = false;
+        }
+        else {
+            if (r < rmin) {
+                rmin = r;
+                first = ihit;
+            }
+            if (r > rmax) {
+                rmax = r;
+                last = ihit;
+            }
+        }
+    }
+}
diff --git a/Reconstruction/ParticleID/src/TPCDndxAlg.h b/Reconstruction/ParticleID/src/TPCDndxAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8cd699ebea3e27a9168f4515377e192ed90b6d7
--- /dev/null
+++ b/Reconstruction/ParticleID/src/TPCDndxAlg.h
@@ -0,0 +1,44 @@
+#ifndef TPCDndxAlg_h
+#define TPCDndxAlg_h 1
+
+#include "k4FWCore/DataHandle.h"
+
+#include "edm4hep/TrackerHit.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/MCRecoTrackParticleAssociationCollection.h"
+#include "edm4hep/RecDqdx.h"
+#include "edm4hep/RecDqdxCollection.h"
+
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+#include "SimplePIDSvc/ISimplePIDSvc.h"
+
+/**
+ * @class TPCDndxAlg
+ * @brief Algorithm to calculate dN/dx for TPC
+ * @author Guang Zhao (zhaog@ihep.ac.cn)
+*/
+
+class TPCDndxAlg : public GaudiAlgorithm {
+public:
+    TPCDndxAlg(const std::string& name, ISvcLocator* svcLoc);
+
+    virtual StatusCode initialize();
+    virtual StatusCode execute();
+    virtual StatusCode finalize();
+
+protected:
+    Gaudi::Property<std::string> m_method{this, "Method", "Simple"};
+
+    DataHandle<edm4hep::TrackCollection> _trackCol{"ClupatraTracks", Gaudi::DataHandle::Reader, this};
+    DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection> _trkParAssCol{"ClupatraTracksParticleAssociation", Gaudi::DataHandle::Reader, this};
+    DataHandle<edm4hep::RecDqdxCollection> _dndxCol{"DndxTracks", Gaudi::DataHandle::Writer, this};
+
+private:
+    SmartIF<ISimplePIDSvc> m_pid_svc;
+    void getFirstAndLastHitsByRadius(const podio::RelationRange<edm4hep::TrackerHit>& hitcol, int& first, int& last);
+};
+
+#endif
diff --git a/Reconstruction/TofRecAlg/src/TofRecAlg.cpp b/Reconstruction/ParticleID/src/TofRecAlg.cpp
similarity index 92%
rename from Reconstruction/TofRecAlg/src/TofRecAlg.cpp
rename to Reconstruction/ParticleID/src/TofRecAlg.cpp
index 39ac4193ab0f5fd2c83a9197df214ef60f1de81a..db36ee1e3e09beab09749d81a04a7816dbc1d6fa 100644
--- a/Reconstruction/TofRecAlg/src/TofRecAlg.cpp
+++ b/Reconstruction/ParticleID/src/TofRecAlg.cpp
@@ -83,6 +83,7 @@ StatusCode TofRecAlg::initialize(){
 StatusCode TofRecAlg::execute(){
   
   const edm4hep::TrackCollection* trackCols = nullptr;
+  auto rectofCol = m_rectofCol.createAndPut();
   
   try {
     trackCols = _inTrackColHdl.get();
@@ -143,12 +144,15 @@ StatusCode TofRecAlg::execute(){
       }//end track hits
       if ( !hasSETHit && !hasFTDHit ) continue;
 
+      auto rectof = rectofCol->create();
+      std::array<float, 5> tmp_timeExp_list{ -99.9, -99.9, -99.9, -99.9, -99.9 };
+
       // smearing the measured time by gaussian 0.05 for intrinsic and 0.02 for bunchcrossing, giving the measured terr a constant
       m_ToFterr[m_nTracks] = std::sqrt(tof_resolution*tof_resolution + bunchcrossing*bunchcrossing);
       m_ToFt[m_nTracks] += normal_distribution_tof(generator_tof);
       m_ToFt[m_nTracks] += normal_distribution_bunch(generator_bunch);
 
-	    // found ToF hit, then to evaluate trajectory length
+      // found ToF hit, then to evaluate trajectory length
       for( std::vector<edm4hep::TrackState>::const_iterator it = track.trackStates_begin(); it != track.trackStates_end(); it++ ){
         
         edm4hep::TrackState trackState = *it;
@@ -211,6 +215,9 @@ StatusCode TofRecAlg::execute(){
         float totz1err    = (*trackStateMap[3])[m_nTracks][13];
         float tanL1       = (*trackStateMap[3])[m_nTracks][5];
         float tanL1err    = (*trackStateMap[3])[m_nTracks][14];
+	float positionx   = (*trackStateMap[3])[m_nTracks][7];
+	float positiony   = (*trackStateMap[3])[m_nTracks][8];
+	float positionz   = (*trackStateMap[3])[m_nTracks][9];
 
         float radius1     = 1./std::abs(omega1);
         float radius1err  = omega1err/(omega1*omega1);
@@ -228,7 +235,7 @@ StatusCode TofRecAlg::execute(){
 	float deltaphi = phi1 -phi0;
 	if ( omega0 * deltaphi > 0.0 ){
 	    deltaphi = 2. * M_PI - std::abs( deltaphi );
-	 }
+	}
 
         // calculate the length
         float _length             = std::sqrt( radius0*radius0 * (deltaphi)*(deltaphi) + (totz1-totz0)*(totz1-totz0) );//in mm
@@ -250,8 +257,8 @@ StatusCode TofRecAlg::execute(){
         //momenta to kg m/s
         float p_tmp = p_atIP * GeV2kgms;
         float perr_tmp = perr_atIP * GeV2kgms;
-
-        for (auto it = masses.begin(); it != masses.end(); ++it){//expected times and errors for e, mu, pi, k, proton
+        
+	for (auto it = masses.begin(); it != masses.end(); ++it){//expected times and errors for e, mu, pi, k, proton
             int idx = it->first;
             double assum = it->second;
             double m_tmp = assum * GeV2kg;
@@ -261,9 +268,15 @@ StatusCode TofRecAlg::execute(){
             double t_tmp = 10e5 * _length / v_tmp;
             double terr_tmp = 10e5 * std::sqrt( (_lengtherr/v_tmp)*(_lengtherr/v_tmp) + ( (_length*_length)/(v_tmp*v_tmp*v_tmp*v_tmp) )*verr_tmp*verr_tmp );
             m_exp_time[m_nTracks][idx]  	= t_tmp;
-            m_exp_timeerr[m_nTracks][idx] = terr_tmp;
+            m_exp_timeerr[m_nTracks][idx] 	= terr_tmp;
+	    tmp_timeExp_list[idx]		= (float) t_tmp;
             debug()<<"idx : "<< idx <<" assum: "<< assum <<" omega: "<<omega0<<" length: "<<_length<<" phi1: "<<phi1<<" phi0: "<<phi0<<" phi1-phi0: "<<deltaphi<<" exp_t: "<<t_tmp<<" obs_t: "<<m_ToFt[m_nTracks]<<endmsg;
         }
+	rectof.setTimeExp( tmp_timeExp_list );
+	rectof.setTime( m_ToFt[m_nTracks] );
+	rectof.setSigma( m_ToFterr[m_nTracks] );
+	rectof.setPosition( { positionx, positiony, positionz } );
+	rectof.setPathLength( { _length, _length, _length, _length, _length } );
 
         }else{
           m_length[m_nTracks] = -999;
@@ -277,6 +290,11 @@ StatusCode TofRecAlg::execute(){
             m_exp_time[m_nTracks][idx] = -999;
             m_exp_timeerr[m_nTracks][idx] = -999;
           }
+	  rectof.setTimeExp( tmp_timeExp_list );
+	  rectof.setTime( -999 );
+	  rectof.setSigma( -999 );
+	  rectof.setPosition( { -999, -999, -999 } );
+	  rectof.setPathLength( { -999, -999, -999, -999, -999 } );
       }
       m_nTracks++;
 
diff --git a/Reconstruction/TofRecAlg/src/TofRecAlg.h b/Reconstruction/ParticleID/src/TofRecAlg.h
similarity index 95%
rename from Reconstruction/TofRecAlg/src/TofRecAlg.h
rename to Reconstruction/ParticleID/src/TofRecAlg.h
index a9a5362a2988774840441ed8765333d52c0d0706..1ddd298f0be5415a1babc57deec3a51393513f76 100644
--- a/Reconstruction/TofRecAlg/src/TofRecAlg.h
+++ b/Reconstruction/ParticleID/src/TofRecAlg.h
@@ -10,6 +10,7 @@
 #include "edm4hep/TrackerHitCollection.h"
 #include <random>
 #include "GaudiKernel/NTuple.h"
+#include "edm4cepc/RecTofCollection.h"
 
 class TofRecAlg : public Algorithm {
  public:
@@ -24,6 +25,7 @@ class TofRecAlg : public Algorithm {
  private:
   DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
   DataHandle<edm4hep::TrackCollection> _inTrackColHdl{"CompleteTracks", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::RecTofCollection> m_rectofCol{"RecTofCollection", Gaudi::DataHandle::Writer, this};
 
   Gaudi::Property<double> m_field{this, "Field", 3.0};
 
@@ -105,4 +107,4 @@ class TofRecAlg : public Algorithm {
 
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/Reconstruction/RecAssociationMaker/CMakeLists.txt b/Reconstruction/RecAssociationMaker/CMakeLists.txt
index d854356b8be3c4ed9f5c0913c2e4836bdab14cb7..56187b36b9fdf96ae4373c7461b52e0c2356ee35 100644
--- a/Reconstruction/RecAssociationMaker/CMakeLists.txt
+++ b/Reconstruction/RecAssociationMaker/CMakeLists.txt
@@ -1,6 +1,7 @@
 # Modules
 gaudi_add_module(RecAssociationMaker
                  SOURCES src/TrackParticleRelationAlg.cpp
+                         src/TrueMuonTagAlg.cpp
 
                  LINK GearSvc
                       EventSeeder
diff --git a/Reconstruction/RecAssociationMaker/README_TrueMuTag.md b/Reconstruction/RecAssociationMaker/README_TrueMuTag.md
new file mode 100644
index 0000000000000000000000000000000000000000..e403f4189cb973197f352480c54195460ea307c8
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/README_TrueMuTag.md
@@ -0,0 +1,70 @@
+
+
+This is about the temporary `TrueMuonTagAlg`.
+
+The `TrueMuonTagAlg` is implemented in:
+
+`
+Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.h|cpp
+`
+
+refering to the `TrackParticleRelationAlg` implemented in the same folder.
+
+It first matches the `FullLDCTrack` with a `MCParticle`.
+If the `MCParticle` is a muon, according to a true efficiency `MuonTagEfficiency`,
+randomly flag it as having a muon Tag or not,
+separately for Barrel and Endcap.
+
+The flag is stored in the `edm4hep::MutableTrack::type()`,
+following the `lcio::ILDDetID::` numbers, which is defined in:
+[LCIO-02-20/src/cpp/src/UTIL/ILDConf.cc](https://github.com/iLCSoft/LCIO/blob/v02-20/src/cpp/src/UTIL/ILDConf.cc)
+
+
+An example configure is shown in `tracking_trueMuonTag.py`, e.g.:
+
+```
+from Configurables import TrueMuonTagAlg
+tmt = TrueMuonTagAlg("TrueMuonTag")
+tmt.MCParticleCollection = "MCParticle"
+tmt.TrackList = ["CompleteTracks"]
+tmt.MuonTagEfficiency = 0.95 # muon true tag efficiency, default is 1.0 (100%)
+tmt.MuonDetTanTheta = 1.2 # muon det barrel/endcap separation tan(theta)
+#tmt.OutputLevel = DEBUG
+```
+
+In this example, it adds the muon Tag in the `edm4hep::MutableTrack::type()` for each track in
+"CompleteTracks" collection (which is a `FullLDCTrack` collection)
+and output it to be "CompleteTracksWithMuonTag" in your output `lcio` root files.
+
+To use it in your analysis codes, one can do the following, either in your cpp codes in CEPCSW,
+or in your `ROOT` analysis codes.
+
+Example 1, for CEPCSW Algorithms:
+
+Add the following in your header file:
+```
+#include <UTIL/ILDConf.h>
+```
+
+Do the following in your cpp file, suppose `track` is the track you get from the
+"CompleteTracksWithMuonTag" collection:
+```
+bool hasMuonTag_MuonBarrel = ( ( track.type() >> lcio:ILDDetID:YOKE ) % 2 == 1 );
+bool hasMuonTag_MuonEndcap = ( ( track.type() >> lcio:ILDDetID:YOKE\_ENDCAP ) % 2 == 1 );
+```
+
+Example 2, for ROOT analysis .C macros, suppose `events` is the `TTree` in your output root
+file storing the events.
+
+```
+events.Draw("((CompleteTracksWithMuonTag.type>>27) % 2)>>hHasMuonTag_MuonBarrel");
+events.Draw("((CompleteTracksWithMuonTag.type>>31) % 2)>>hHasMuonTag_MuonEndcap");
+```
+
+This will draw one histogram for has muon tag in barrel or in endcap.
+in case a track has muon tag, it is one entry at 1 in this histogram.
+And the numbers 27 and 31 are the numbers defined for `lcio:ILDDetID:YOKE`
+and `lcio:ILDDetID:YOKE_ENDCAP` in `UTIL/ILDConf.h`, respectively.
+
+
+
diff --git a/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.cpp b/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ae934bf52788178b928400020be37f6cbb612ae
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.cpp
@@ -0,0 +1,183 @@
+#include "TrueMuonTagAlg.h"
+
+DECLARE_COMPONENT(TrueMuonTagAlg)
+
+TrueMuonTagAlg::TrueMuonTagAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc){
+  declareProperty("MCParticleCollection", m_inMCParticleColHdl, "Handle of the Input MCParticle collection");
+  declareProperty("MuonTagEfficiency", _m_muonTagEff, "Muon Tagging efficiency to be used to mimic the true muon tag, default is 1. (100%)");
+  declareProperty("MuonDetTanTheta", _m_muonDetTanTheta, "Muon barrel/endcap separate theta angle.");
+}
+
+StatusCode TrueMuonTagAlg::initialize() {
+  for(auto name : m_inTrackCollectionNames) {
+    m_inTrackColHdls.push_back(new DataHandle<edm4hep::TrackCollection> (name, Gaudi::DataHandle::Reader, this));
+    //m_outColHdls.push_back(new DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection> (name+"ParticleAssociation", Gaudi::DataHandle::Writer, this));
+    m_outTrackColHdls.push_back(new DataHandle<edm4hep::TrackCollection> (name+"WithMuonTag", Gaudi::DataHandle::Writer, this));
+  }
+  
+  for(unsigned i=0; i<m_inAssociationCollectionNames.size(); i++) {
+    m_inAssociationColHdls.push_back(new DataHandle<edm4hep::MCRecoTrackerAssociationCollection> (m_inAssociationCollectionNames[i], Gaudi::DataHandle::Reader, this));
+  }
+  
+  if(m_inAssociationColHdls.size()==0) {
+    warning() << "no Association Collection input" << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+  m_nEvt = 0;
+  return GaudiAlgorithm::initialize();
+}
+
+StatusCode TrueMuonTagAlg::execute() {
+  info() << "start Event " << m_nEvt << endmsg;
+  
+  // MCParticle
+  const edm4hep::MCParticleCollection* mcpCol = nullptr;
+  try {
+    mcpCol = m_inMCParticleColHdl.get();
+    for (auto mcp : *mcpCol) {
+      debug() << "id=" << mcp.id() << " pdgid=" << mcp.getPDG() << " charge=" << mcp.getCharge() << " genstat=" << mcp.getGeneratorStatus() << " simstat=" << mcp.getSimulatorStatus()
+	      << " p=" << mcp.getMomentum() << endmsg;
+      int nparents = mcp.parents_size();
+      int ndaughters = mcp.daughters_size();
+      for (int i=0; i<nparents; i++) {
+	debug() << "<<<<<<" << mcp.getParents(i).id() << endmsg;
+      }
+      for (int i=0; i<ndaughters; i++) {
+        debug() << "<<<<<<" << mcp.getDaughters(i).id() << endmsg;
+      }
+    }
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << m_inMCParticleColHdl.fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+  }
+  if(!mcpCol) {
+    warning() << "pass this event because MCParticle collection can not read" << endmsg; 
+    return StatusCode::SUCCESS;
+  }
+
+  // Prepare map from hit to MCParticle
+  std::map<edm4hep::TrackerHit, edm4hep::MCParticle> mapHitParticle;
+  debug() << "reading Association" << endmsg;
+  for (auto hdl : m_inAssociationColHdls) {
+    const edm4hep::MCRecoTrackerAssociationCollection* assCol = nullptr;
+    try {
+      assCol = hdl->get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << hdl->fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+      return StatusCode::FAILURE;
+    }
+    for (auto ass: *assCol) {
+      auto hit = ass.getRec();
+      auto particle = ass.getSim().getMCParticle();
+      mapHitParticle[hit] = particle;
+    }
+  }
+  
+  // Handle all input TrackCollection
+  for (unsigned icol=0; icol<m_inTrackColHdls.size(); icol++) {
+    auto hdl = m_inTrackColHdls[icol];
+
+    const edm4hep::TrackCollection* trkCol = nullptr;
+    try {
+      trkCol = hdl->get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << hdl->fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+    }
+
+    //auto outCol = m_outColHdls[icol]->createAndPut();
+    //if(!outCol) {
+    //  error() << "Collection " << m_outColHdls[icol]->fullKey() << " cannot be created" << endmsg;
+    //  return StatusCode::FAILURE;
+    //}
+   
+    auto outTrackCol = m_outTrackColHdls[icol]->createAndPut();
+    if(!outTrackCol) {
+      error() << "Collection " << m_outTrackColHdls[icol]->fullKey() << " cannot be created" << endmsg;
+      return StatusCode::FAILURE;
+    }
+ 
+    if(trkCol) {
+      std::map<edm4hep::MCParticle, std::vector<edm4hep::TrackerHit> > mapParticleHits;
+
+      for (auto track: *trkCol) {
+	std::map<edm4hep::MCParticle, int> mapParticleNHits;
+	
+	// Count hits related to MCParticle
+	int nhits = track.trackerHits_size();
+	for (int ihit=0; ihit<nhits; ihit++) {
+	  auto hit = track.getTrackerHits(ihit);
+	  auto itHP  = mapHitParticle.find(hit);
+	  if (itHP==mapHitParticle.end()) {
+	    warning() << "track " << track.id() << "'s hit " << hit.id() << "not in association list, will be ignored" << endmsg;
+	  }
+	  else {
+	    auto particle = itHP->second;
+	    if(!particle.isAvailable()) continue;
+	    debug() << "track " << track.id() << "'s hit " << hit.id() << " link to MCParticle " << particle.id() << endmsg;
+	    auto itPN = mapParticleNHits.find(particle);
+	    if (itPN!=mapParticleNHits.end()) itPN->second++;
+	    else                             mapParticleNHits[particle] = 1;
+
+	    if (msgLevel(MSG::DEBUG)) mapParticleHits[particle].push_back(hit);
+	  }
+	}
+	debug() << "Total " << mapParticleNHits.size() << " particles link to the track " << track.id() << endmsg;
+
+	// Save to collection
+	//for (std::map<edm4hep::MCParticle, int>::iterator it=mapParticleNHits.begin(); it!=mapParticleNHits.end(); it++) {
+	//  auto ass = outCol->create();
+	//  ass.setWeight(it->second);
+	//  ass.setRec(track);
+	//  ass.setSim(it->first);
+	//}
+
+        // tore to new track collection
+        edm4hep::MutableTrack new_track = track.clone();
+
+        // find the max nhits mcparticle 
+        auto max_nhits_iter = std::max_element(mapParticleNHits.begin(), mapParticleNHits.end(),
+                                     [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second;} );
+        // calculate the barrel/endcap theta
+        auto a_particle = max_nhits_iter->first;
+        auto p_pdg_id = a_particle.getPDG();
+        auto p_status = a_particle.getGeneratorStatus();
+        auto p_px = a_particle.getMomentum()[0];
+        auto p_py = a_particle.getMomentum()[1];
+        auto p_pz = a_particle.getMomentum()[2];
+        auto p_tantheta = sqrt(p_px*p_px+p_py*p_py)/fabs(p_pz);
+      
+       
+        if (abs(p_pdg_id)==13 && fRandom.Rndm()<_m_muonTagEff ) {
+          debug() << " particle PDG = " << p_pdg_id << "; status = " << p_status << endmsg;
+          if (p_tantheta>_m_muonDetTanTheta) new_track.setType( new_track.getType()| (1<<lcio::ILDDetID::YOKE) ) ;
+          else new_track.setType( new_track.getType()| (1<<lcio::ILDDetID::YOKE_ENDCAP) ) ;
+        }
+        outTrackCol->push_back(new_track);
+
+      }
+      
+      if (msgLevel(MSG::DEBUG)) {
+	for (std::map<edm4hep::MCParticle, std::vector<edm4hep::TrackerHit> >::iterator it=mapParticleHits.begin(); it!=mapParticleHits.end(); it++) {
+	  auto particle = it->first;
+	  auto hits     = it->second;
+	  debug() << "=== MCPaticle ===" << particle << endmsg;
+	  for (auto hit : hits) {
+	    debug() << hit << endmsg;
+	  }
+	}
+      }
+    }
+  }
+
+  m_nEvt++;
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TrueMuonTagAlg::finalize() {
+  
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.h b/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..e61faf1e04aa45a596e30ac635e9ae34a4071af5
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/src/TrueMuonTagAlg.h
@@ -0,0 +1,52 @@
+#ifndef TrueMuonTagAlg_h
+#define TrueMuonTagAlg_h 1
+
+#include "k4FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/MCRecoTrackParticleAssociationCollection.h"
+
+#include <UTIL/BitField64.h>
+#include <UTIL/ILDConf.h>
+
+#include "TRandom3.h"
+
+class TrueMuonTagAlg : public GaudiAlgorithm {
+ public:
+  // Constructor of this form must be provided
+  TrueMuonTagAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+  // Three mandatory member functions of any algorithm
+  StatusCode initialize() override;
+  StatusCode execute() override;
+  StatusCode finalize() override;
+
+ private:
+  // input MCParticle
+  DataHandle<edm4hep::MCParticleCollection>                              m_inMCParticleColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
+  // input Tracks to make relation
+  std::vector<DataHandle<edm4hep::TrackCollection>* >                    m_inTrackColHdls;
+  Gaudi::Property<std::vector<std::string> >                             m_inTrackCollectionNames{this, "TrackList", {"SiTracks"}};
+  // input TrackerAssociation to link TrackerHit and SimTrackerHit
+  std::vector<DataHandle<edm4hep::MCRecoTrackerAssociationCollection>* > m_inAssociationColHdls;
+  Gaudi::Property<std::vector<std::string> >                             m_inAssociationCollectionNames{this, "TrackerAssociationList", {"VXDTrackerHitAssociation",
+        "SITTrackerHitAssociation", "SETTrackerHitAssociation", "FTDTrackerHitAssociation"}};
+
+  // output TrackParticleAssociation
+  //std::vector<DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection>* > m_outColHdls;
+  std::vector<DataHandle<edm4hep::TrackCollection>* > m_outTrackColHdls;
+
+  // muon tag efficiency 
+  Gaudi::Property<double> _m_muonTagEff{this, "MuonTagEfficiency", 1.0};
+  // Muon barrel/endcap separate angle
+  Gaudi::Property<double> _m_muonDetTanTheta{this,"MuonDetTanTheta", 1.2};
+
+  int m_nEvt;
+
+  TRandom3 fRandom{1234};
+
+};
+#endif
diff --git a/Reconstruction/TofRecAlg/CMakeLists.txt b/Reconstruction/TofRecAlg/CMakeLists.txt
deleted file mode 100644
index 3f66caadd9150fd808898f895331554fdfc5cfe4..0000000000000000000000000000000000000000
--- a/Reconstruction/TofRecAlg/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-gaudi_add_module(TofRecAlg
-                 SOURCES src/TofRecAlg.cpp
-                 LINK DataHelperLib
-                      Gaudi::GaudiKernel
-                      EDM4HEP::edm4hep
-                      ${ROOT_LIBRARIES}
-                      ${CLHEP_LIBRARIES}
-		                  ${LCIO_LIBRARIES}
-		                  ${DD4hep_COMPONENT_LIBRARIES}
-                      DetInterface
-                      k4FWCore::k4FWCore
-)
-
-install(TARGETS TofRecAlg
-  EXPORT CEPCSWTargets
-  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
-  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
-  COMPONENT dev)
\ No newline at end of file
diff --git a/Service/CMakeLists.txt b/Service/CMakeLists.txt
index 24ff600bbc724865bb12782e5710849a7b1fd3c2..14c795387ec29c5eaa2ad469db497d2048ff8ee6 100644
--- a/Service/CMakeLists.txt
+++ b/Service/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(EventSeeder)
 add_subdirectory(GearSvc)
 add_subdirectory(TrackSystemSvc)
+add_subdirectory(SimplePIDSvc)
diff --git a/Service/SimplePIDSvc/CMakeLists.txt b/Service/SimplePIDSvc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6e8d14b98064b14577b89f18c7f0a9bd98e5e5d8
--- /dev/null
+++ b/Service/SimplePIDSvc/CMakeLists.txt
@@ -0,0 +1,24 @@
+
+gaudi_add_header_only_library(SimplePIDSvc)
+
+gaudi_add_module(SimplePIDSvcPlugins
+                 SOURCES src/SimplePIDSvc.cpp
+                 LINK SimplePIDSvc
+                      GearSvc
+                      Gaudi::GaudiKernel
+                      DataHelperLib
+                      ${DD4hep_COMPONENT_LIBRARIES}
+                      ${ROOT_LIBRARIES}
+                      ${GEAR_LIBRARIES}
+)
+
+#target_include_directories(SimplePIDSvc PUBLIC
+#  $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>/include
+#  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+
+install(TARGETS SimplePIDSvc SimplePIDSvcPlugins
+  EXPORT CEPCSWTargets
+  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
+  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
+  COMPONENT dev)
+
diff --git a/Service/SimplePIDSvc/include/SimplePIDSvc/ISimplePIDSvc.h b/Service/SimplePIDSvc/include/SimplePIDSvc/ISimplePIDSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a54322910026e389fd2786c8454ad50bb1a189d
--- /dev/null
+++ b/Service/SimplePIDSvc/include/SimplePIDSvc/ISimplePIDSvc.h
@@ -0,0 +1,33 @@
+#ifndef I_SimplePID_SVC_H
+#define I_SimplePID_SVC_H
+
+#include "GaudiKernel/IService.h"
+#include "edm4hep/Vector3d.h"
+#include "edm4hep/TrackerHit.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/Vector3d.h"
+
+/**
+ * @class ISimplePIDSvc
+ * @brief Interface for Simple PID
+ * @author Guang Zhao (zhaog@ihep.ac.cn)
+*/
+
+class ISimplePIDSvc: virtual public IService {
+public:
+    DeclareInterfaceID(ISimplePIDSvc, 0, 1); // major/minor version
+    
+    virtual ~ISimplePIDSvc() = default;
+
+    virtual double getDndx(double mean, double sigma) = 0;
+    virtual double getDndxMean(double bg, double cos) = 0;
+    virtual double getDndxSigma(double bg, double cos, double len) = 0;
+    virtual double getChi2(double dndx_meas, double dndx_exp, double dndx_sigma) = 0;
+    virtual void getTrackPars(const edm4hep::Vector3d& hit1, const edm4hep::Vector3d& hit2, const edm4hep::Track& trk, int location,
+                              double& len, double& p, double& cos) = 0;
+    virtual double getBetaGamma(double p, int pid_type) = 0; // e, mu, pi, K, p: 0, 1, 2, 3, 4
+    virtual int getParticleType(int pdgid) = 0;
+};
+
+
+#endif
diff --git a/Service/SimplePIDSvc/src/SimplePIDSvc.cpp b/Service/SimplePIDSvc/src/SimplePIDSvc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ccece5b49bd4d6f722dc8a700d5c23d6c040e91
--- /dev/null
+++ b/Service/SimplePIDSvc/src/SimplePIDSvc.cpp
@@ -0,0 +1,239 @@
+#include "SimplePIDSvc.h"
+#include "DataHelper/HelixClass.h"
+#include "GearSvc/IGearSvc.h"
+#include "gear/BField.h"
+#include "TFile.h"
+#include "TH2D.h"
+#include "TRandom.h"
+#include <iostream>
+#include <cmath>
+
+DECLARE_COMPONENT(SimplePIDSvc)
+
+using namespace edm4hep;
+
+SimplePIDSvc::SimplePIDSvc(const std::string& name, ISvcLocator* svc)
+    : base_class(name, svc)
+{
+    m_rootFile = nullptr;
+}
+
+SimplePIDSvc::~SimplePIDSvc()
+{
+    if (m_rootFile != nullptr) delete m_rootFile;
+}
+
+double SimplePIDSvc::getDndx(double mean, double sigma) {
+    return gRandom->Gaus(mean, sigma);
+}
+
+double SimplePIDSvc::getDndxMean(double bg, double cos)
+{
+    return interpolate(m_dndxMean, bg, cos);
+}
+
+double SimplePIDSvc::getDndxSigma(double bg, double cos, double len)
+{
+    return interpolate(m_dndxSigma, bg, cos)/sqrt(len*0.1); // len in mm, need to convert to cm
+}
+
+double SimplePIDSvc::getChi2(double dndx_meas, double dndx_exp, double dndx_sigma) {
+    double chi = (dndx_meas - dndx_exp)/dndx_sigma;
+    return chi*chi;
+}
+
+void SimplePIDSvc::getTrackPars(const edm4hep::Vector3d& first_hit_pos, const edm4hep::Vector3d& last_hit_pos, const edm4hep::Track& trk, int location,
+                                double& length, double& p, double& costheta) 
+{
+    TrackState trk_par;
+    for (auto it = trk.trackStates_begin(); it != trk.trackStates_end(); it++) {
+        if (it->location == location) {
+            trk_par = *it;
+            break;
+        }
+    }
+	auto _gear = service<IGearSvc>("GearSvc");
+	double bfield = _gear->getGearMgr()->getBField().at(gear::Vector3D(0.,0.0,0.)).z();
+    HelixClass hc = HelixClass();
+    hc.Initialize_Canonical(trk_par.phi, trk_par.D0, trk_par.Z0, trk_par.omega, trk_par.tanLambda, bfield);
+    double R = hc.getRadius();
+    double phi1 = atan2(first_hit_pos[1] - hc.getYC(), first_hit_pos[0] - hc.getXC());
+    double phi2 = atan2(last_hit_pos[1] - hc.getYC(), last_hit_pos[0] - hc.getXC());
+    double z1 = first_hit_pos[2];
+    double z2 = last_hit_pos[2];
+
+
+    // std::cout << "xc, yc = " << hc.getXC() << ", " << hc.getYC() << std::endl;
+    // std::cout << "r = " << R << std::endl;
+    // std::cout << "x1, y1 = " << first_hit_pos[0] << ", " << first_hit_pos[1] << std::endl;
+    // std::cout << "x2, y2 = " << last_hit_pos[0] << ", " << last_hit_pos[1] << std::endl;
+    // std::cout << "phi1, phi2 = " << phi1 << ", " << phi2 << std::endl;
+    // std::cout << "tanLambda = " << trk_par.tanLambda << std::endl;
+    // std::cout << "z1, z2 = " << z1 << ", " << z2 << std::endl;
+    // const float* p3 = hc.getMomentum();
+    // std::cout << "momentum = " << sqrt(p3[0]*p3[0] + p3[1]*p3[1] + p3[2]*p3[2]) << std::endl;
+    // std::cout << "charge = " << trk_par.omega << std::endl;
+
+    // if (fabs(z2 - z1) > fabs(2*M_PI*R/cos(atan(trk_par.tanLambda)))) { // length is larger than one cycle
+    if (fabs(trk_par.tanLambda) > 0.1) { // if the track is not vertical, use z
+        length = fabs((z1 - z2)/sin(atan(trk_par.tanLambda)));
+    }
+    else {
+        int outward_direction = int(fabs(z1) < fabs(z2));
+        int positive_charge = int(trk_par.omega > 0.);
+        if (outward_direction * positive_charge > 0) {
+            length = phi1 > phi2 ? (phi1 - phi2)*R/cos(atan(trk_par.tanLambda)) : (phi1 - phi2 + 2*M_PI)*R/cos(atan(trk_par.tanLambda));
+        }
+        else {
+            length = phi1 < phi2 ? (phi2 - phi1)*R/cos(atan(trk_par.tanLambda)) : (phi2 - phi1 + 2*M_PI)*R/cos(atan(trk_par.tanLambda));
+        }
+    }
+    // std::cout << "length (rphi): " << fabs((phi1 - phi2)*R/cos(atan(trk_par.tanLambda))) << std::endl;
+    // std::cout << "length (z): " << fabs((z1 - z2)/sin(atan(trk_par.tanLambda))) << std::endl << std::endl;
+    // std::cout << "length: " << length << std::endl;
+
+    double pt = hc.getPXY();
+    double pz = pt * hc.getTanLambda();
+    p = sqrt(pt*pt + pz*pz);
+    costheta = cos(M_PI/2 - atan(hc.getTanLambda()));
+}
+
+double SimplePIDSvc::getBetaGamma(double p, int pid_type) { // p: GeV/c
+    double mass;
+    switch (pid_type)
+    {
+    case 0:
+        mass = 0.511;
+        break;
+    case 1:
+        mass = 105.658;
+        break;
+    case 2:
+        mass = 139.570;
+        break;
+    case 3:
+        mass = 493.677;
+        break;
+    case 4:
+        mass = 938.272;
+        break;
+    
+    default:
+        mass = 105.658; // default is muon
+        break;
+    }
+    return p/mass*1000.;
+}
+
+int SimplePIDSvc::getParticleType(int pdgid) {
+    int type;
+    switch (abs(pdgid))
+    {
+    case 11:
+        type = 0;
+        break;
+    case 13:
+        type = 1;
+        break;
+    case 211:
+        type = 2;
+        break;
+    case 321:
+        type = 3;
+        break;
+    case 2212:
+        type = 4;
+        break;
+    
+    default:
+        type = -1;
+        break;
+    }
+    return type;
+}
+
+StatusCode SimplePIDSvc::initialize()
+{
+    m_rootFile = new TFile(m_parFile.value().c_str());
+    m_dndxMean = (TH2D*)m_rootFile->Get("dndx_mean");
+    m_dndxSigma = (TH2D*)m_rootFile->Get("dndx_sigma");
+    return StatusCode::SUCCESS;
+}
+
+StatusCode SimplePIDSvc::finalize()
+{
+    if (m_rootFile != nullptr) delete m_rootFile;
+    return StatusCode::SUCCESS;
+}
+
+double SimplePIDSvc::interpolate(TH2D* h, double x, double y) {
+    int nx = h->GetNbinsX();
+    int ny = h->GetNbinsY();
+    double xmax = h->GetXaxis()->GetBinCenter(nx);
+    double xmin = h->GetXaxis()->GetBinCenter(1);
+    double ymax = h->GetYaxis()->GetBinCenter(ny);
+    double ymin = h->GetYaxis()->GetBinCenter(1);
+    double dlogx = (log10(xmax) - log10(xmin)) * 0.01;
+    double dy = (ymax - ymin) * 0.01;
+
+    if (xmin <= x && x <= xmax && ymin <= y && y <= ymax) {
+        return h->Interpolate(x, y);
+    }
+
+    int xloc, yloc;
+    if (x > xmax) xloc = 1;
+    else if (x < xmin) xloc = -1;
+    else xloc = 0;
+    if (y > ymax) yloc = 1;
+    else if (y < ymin) yloc = -1;
+    else yloc = 0;
+
+    double x1, x2, y1, y2, z1, z2;
+    if (xloc == 1) {
+        x1 = pow(10, log10(xmax)-dlogx);
+        x2 = xmax;
+    }
+    else if (xloc == -1) {
+        x1 = xmin;
+        x2 = pow(10, log10(xmin) + dlogx);
+    }
+    if (yloc == 1) {
+        y1 = ymax - dy;
+        y2 = ymax;
+    }
+    else if (yloc == -1) {
+        y1 = ymin;
+        y2 = ymin + dy;
+    }
+
+    if (xloc != 0 && yloc == 0) {
+        z1 = h->Interpolate(x1, y);
+        z2 = h->Interpolate(x2, y);
+        return linear_interpolate(x1, x2, z1, z2, x);
+    }
+    else if (xloc == 0 && yloc != 0) {
+        z1 = h->Interpolate(x, y1);
+        z2 = h->Interpolate(x, y2);
+        return linear_interpolate(y1, y2, z1, z2, y);
+    }
+    else if (xloc != 0 && yloc != 0) {
+        double y_boundary = yloc > 0 ? ymax : ymin;
+        z1 = h->Interpolate(x1, y_boundary);
+        z2 = h->Interpolate(x2, y_boundary);
+        double z_tmp = linear_interpolate(x1, x2, z1, z2, x);
+
+        double x_boundary = xloc > 0 ? xmax : xmin;
+        z1 = h->Interpolate(x_boundary, y1);
+        z2 = h->Interpolate(x_boundary, y2);
+        double z_tmp2 = linear_interpolate(y1, y2, z1, z2, y);
+
+        return z_tmp + z_tmp2 - h->Interpolate(x_boundary, y_boundary);
+    }
+    else {
+        return 0.;
+    }
+}
+
+double SimplePIDSvc::linear_interpolate(double x1, double x2, double y1, double y2, double x) {
+    return (y2-y1)/(x2-x1)*(x-x1) + y1;
+}
diff --git a/Service/SimplePIDSvc/src/SimplePIDSvc.h b/Service/SimplePIDSvc/src/SimplePIDSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..661accb71f85a0c403d61b4021668a9ce73ff6c9
--- /dev/null
+++ b/Service/SimplePIDSvc/src/SimplePIDSvc.h
@@ -0,0 +1,46 @@
+#ifndef SIMPLEPID_SVC_H
+#define SIMPLEPID_SVC_H
+
+#include "SimplePIDSvc/ISimplePIDSvc.h"
+#include <GaudiKernel/Service.h>
+#include "DD4hep/Detector.h"
+#include "gear/GearMgr.h"
+#include "edm4hep/Vector3d.h"
+
+class TFile;
+class TH2D;
+
+/**
+ * @class SimplePIDSvc
+ * @brief Simple PID service
+ * @author Guang Zhao (zhaog@ihep.ac.cn)
+*/
+
+class SimplePIDSvc : public extends<Service, ISimplePIDSvc>
+{
+    public:
+        SimplePIDSvc(const std::string& name, ISvcLocator* svc);
+        virtual ~SimplePIDSvc();
+
+        double getDndx(double mean, double sigma) override;
+        double getDndxMean(double bg, double cos) override;
+        double getDndxSigma(double bg, double cos, double len) override;
+        double getChi2(double dndx_meas, double dndx_exp, double dndx_sigma) override;
+        void getTrackPars(const edm4hep::Vector3d& hit1, const edm4hep::Vector3d& hit2, const edm4hep::Track& trk, int location,
+                          double& len, double& p, double& cos) override;
+        double getBetaGamma(double p, int pid_type) override;
+        int getParticleType(int pdgid) override;
+
+        StatusCode initialize() override;
+        StatusCode finalize() override;
+
+    private:
+        Gaudi::Property<std::string> m_parFile{this, "ParFile", "dNdx_TPC.root"};
+        TFile* m_rootFile;
+        TH2D* m_dndxMean;
+        TH2D* m_dndxSigma;
+        double interpolate(TH2D* h, double bg, double cos);
+        double linear_interpolate(double x1, double x2, double y1, double y2, double x);
+};
+
+#endif
diff --git a/Utilities/DecoderHelper/CMakeLists.txt b/Utilities/DecoderHelper/CMakeLists.txt
index 3c3f4ca9ec0729ade291be0428a6cb5348a61814..4b82d87aa0107f1eab214dc1ae1a7ba9bfdd7847 100644
--- a/Utilities/DecoderHelper/CMakeLists.txt
+++ b/Utilities/DecoderHelper/CMakeLists.txt
@@ -1,5 +1,5 @@
 
-gaudi_add_library(DecoderHelperLib 
+gaudi_add_library(DecoderHelperLib
                   SOURCES src/DD4hep2Lcio.cc
 )
 
diff --git a/Utilities/DecoderHelper/include/DecoderHelper/DD4hep2Lcio.h b/Utilities/DecoderHelper/include/DecoderHelper/DD4hep2Lcio.h
index a5a2210df3e94839bff9f1988311a01195520844..1205bc3a4bab0882749b264caafc336208313916 100644
--- a/Utilities/DecoderHelper/include/DecoderHelper/DD4hep2Lcio.h
+++ b/Utilities/DecoderHelper/include/DecoderHelper/DD4hep2Lcio.h
@@ -5,10 +5,12 @@ namespace DD4hep2Lcio {
     namespace CEPCv4 {
         int getEcalLayer(int dd4hep_layer);
         int getEcalStave(int dd4hep_stave);
+        int getEcalBarrelStave(int dd4hep_stave);
+        int getEcalEndcapStave(int dd4hep_stave);
         int getHcalLayer(int dd4hep_layer);
         int getHcalStave(int dd4hep_stave);
         int getMuonLayer(int dd4hep_layer);
         int getMuonStave(int dd4hep_stave);
     }
 }
-#endif
+#endif
\ No newline at end of file
diff --git a/Utilities/DecoderHelper/src/DD4hep2Lcio.cc b/Utilities/DecoderHelper/src/DD4hep2Lcio.cc
index 30dba288134e03f2b89f5b8452f3c4e7dee24fe3..71999a83ab3d6fb6253e7a21bf2dbbc5f9e5ce13 100644
--- a/Utilities/DecoderHelper/src/DD4hep2Lcio.cc
+++ b/Utilities/DecoderHelper/src/DD4hep2Lcio.cc
@@ -7,6 +7,14 @@ int DD4hep2Lcio::CEPCv4::getEcalStave(int dd4hep_stave){
     int lcio_stave = dd4hep_stave <=2 ? dd4hep_stave+5 : dd4hep_stave-3 ;
     return lcio_stave ;
 }
+int DD4hep2Lcio::CEPCv4::getEcalBarrelStave(int dd4hep_stave){
+    int lcio_stave = dd4hep_stave <=2 ? dd4hep_stave+5 : dd4hep_stave-3 ;
+    return lcio_stave ;
+}
+int DD4hep2Lcio::CEPCv4::getEcalEndcapStave(int dd4hep_stave){
+    int lcio_stave = dd4hep_stave <=2 ? dd4hep_stave+1 : dd4hep_stave-3 ;
+    return lcio_stave ;
+}
 int DD4hep2Lcio::CEPCv4::getHcalLayer(int dd4hep_layer){
     return dd4hep_layer - 1 ;
 }
@@ -18,19 +26,19 @@ int DD4hep2Lcio::CEPCv4::getHcalStave(int dd4hep_stave){
                ****                  ****
             2 *    * 0            1 *    * 7
              *      *              *      *
-            3*      * 7  --->     2*      * 6    
+            3*      * 7  --->     2*      * 6
              *      *              *      *
-            4 *    * 6            3 *    * 5 
-               ****                  ****  
+            4 *    * 6            3 *    * 5
+               ****                  ****
                 5                     4
-        
-        
+
+
     */
-    return lcio_stave ; 
+    return lcio_stave ;
 }
 int DD4hep2Lcio::CEPCv4::getMuonLayer(int dd4hep_layer){
     return dd4hep_layer - 1 ;
 }
 int DD4hep2Lcio::CEPCv4::getMuonStave(int dd4hep_stave){
     return 12 - dd4hep_stave ;
-}
+}
\ No newline at end of file
diff --git a/build.sh b/build.sh
index 5c7393d169fd5b35240df699e7c1314b5cc783a3..85934189ecd1a6abd3fffec8ebe62aec3c00f45a 100755
--- a/build.sh
+++ b/build.sh
@@ -96,8 +96,8 @@ function run-install() {
 ##############################################################################
 
 # The current default platform
-lcg_platform=x86_64-centos7-gcc11-opt
-lcg_version=103.0.2
+lcg_platform=${CEPCSW_LCG_PLATFORM:-x86_64-centos7-gcc11-opt}
+lcg_version=${CEPCSW_LCG_VERSION:-103.0.2}
 
 bldtool=${CEPCSW_BLDTOOL} # make, ninja # set in env var
 
diff --git a/cmake/CEPCSWDependencies.cmake b/cmake/CEPCSWDependencies.cmake
index 90d8914ebf8dbf5a2e916aa515711a87c6683863..f14a91c508ee6a5027b3af9184050a8808a1baba 100644
--- a/cmake/CEPCSWDependencies.cmake
+++ b/cmake/CEPCSWDependencies.cmake
@@ -44,3 +44,12 @@ else()
   message("Try to use an internal installation of CKF BELLE")
   include("${CMAKE_CURRENT_LIST_DIR}/internal_ckf.cmake")
 endif()
+
+
+if (CEPCSW_USE_SYSTEM_EDM4CEPC)
+  message("Try to use an existing installation of EDM4CEPC")
+  find_package(EDM4CEPC)
+else()
+  message("Try to use an internal installation of EDM4CEPC")
+  include("${CMAKE_CURRENT_LIST_DIR}/internal_edm4cepc.cmake")
+endif()
diff --git a/cmake/CEPCSWOptions.cmake b/cmake/CEPCSWOptions.cmake
index 32e00142e62ddd467f0cb89b23b8cbecb69b2e25..a853022fe2e1b1c98683eb56177849d632074a1f 100644
--- a/cmake/CEPCSWOptions.cmake
+++ b/cmake/CEPCSWOptions.cmake
@@ -8,3 +8,6 @@ option(CEPCSW_USE_SYSTEM_CKF_BELLE
        "Use the existing installation of CKF BELLE. Otherwise the internal version will be used."
        FALSE)
 
+option(CEPCSW_USER_SYSTEM_EDM4CEPC
+       "Use the existing installation of EDM4CEPC. Otherwise the internal version will be used."
+       FALSE)
diff --git a/cmake/internal_edm4cepc.cmake b/cmake/internal_edm4cepc.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..65c5f1f6419b4319152d1711c4085faffe31c37f
--- /dev/null
+++ b/cmake/internal_edm4cepc.cmake
@@ -0,0 +1,10 @@
+
+include(FetchContent)
+
+FetchContent_Declare(
+  EDM4CEPC
+  GIT_REPOSITORY https://code.ihep.ac.cn/cepc/externals/EDM4cepc.git
+  GIT_TAG 8eb38894b7b055bf6fe99d4b156e97f7e9466a26
+  )
+
+FetchContent_MakeAvailable(EDM4CEPC)