From 18e0929e510d92b62b8b9519d97045d881aaa40a Mon Sep 17 00:00:00 2001
From: Zhang Yao <zhangyao@ihep.ac.cn>
Date: Tue, 1 Dec 2020 14:27:16 +0800
Subject: [PATCH] Add RecGenfitAlg with wire measurements

---
 Examples/options/tut_detsim_digi_fit_STD.py   | 210 +++++
 Reconstruction/RecGenfitAlg/CMakeLists.txt    |  39 +
 Reconstruction/RecGenfitAlg/README.md         |  12 +
 .../RecGenfitAlg/src/GenfitField.cpp          |  59 ++
 Reconstruction/RecGenfitAlg/src/GenfitField.h |  38 +
 .../RecGenfitAlg/src/GenfitFitter.cpp         | 614 +++++++++++++++
 .../RecGenfitAlg/src/GenfitFitter.h           | 200 +++++
 .../src/GenfitMaterialInterface.cpp           | 353 +++++++++
 .../src/GenfitMaterialInterface.h             |  74 ++
 Reconstruction/RecGenfitAlg/src/GenfitMsg.cpp |  19 +
 Reconstruction/RecGenfitAlg/src/GenfitMsg.h   |  26 +
 .../RecGenfitAlg/src/GenfitTrack.cpp          | 733 ++++++++++++++++++
 Reconstruction/RecGenfitAlg/src/GenfitTrack.h | 199 +++++
 .../RecGenfitAlg/src/RecGenfitAlgDC.cpp       | 416 ++++++++++
 .../RecGenfitAlg/src/RecGenfitAlgDC.h         | 179 +++++
 Reconstruction/Tracking/CMakeLists.txt        |  12 +-
 .../src/TruthTracker/TruthTrackerAlg.cpp      | 203 +++++
 .../src/TruthTracker/TruthTrackerAlg.h        |  79 ++
 Utilities/DataHelper/src/HelixClass.cc        |   2 +
 19 files changed, 3463 insertions(+), 4 deletions(-)
 create mode 100644 Examples/options/tut_detsim_digi_fit_STD.py
 create mode 100644 Reconstruction/RecGenfitAlg/CMakeLists.txt
 create mode 100644 Reconstruction/RecGenfitAlg/README.md
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitField.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitField.h
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitFitter.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitFitter.h
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.h
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitMsg.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitMsg.h
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitTrack.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/GenfitTrack.h
 create mode 100644 Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.cpp
 create mode 100644 Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.h
 create mode 100644 Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.cpp
 create mode 100644 Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.h

diff --git a/Examples/options/tut_detsim_digi_fit_STD.py b/Examples/options/tut_detsim_digi_fit_STD.py
new file mode 100644
index 00000000..9dd7f4bb
--- /dev/null
+++ b/Examples/options/tut_detsim_digi_fit_STD.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+
+import os
+print(os.environ["DD4HEP_LIBRARY_PATH"])
+import sys
+# sys.exit(0)
+
+from Gaudi.Configuration import *
+
+##############################################################################
+# Random Number Svc
+##############################################################################
+from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_
+
+# rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi
+rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_() # The default engine in Geant4
+rndmengine.SetSingleton = True
+rndmengine.Seeds = [42]
+
+# rndmgensvc = RndmGenSvc("RndmGenSvc")
+# rndmgensvc.Engine = rndmengine.name()
+
+
+##############################################################################
+# Event Data Svc
+##############################################################################
+from Configurables import k4DataSvc
+dsvc = k4DataSvc("EventDataSvc")
+
+
+##############################################################################
+# Geometry Svc
+##############################################################################
+
+# geometry_option = "CepC_v4-onlyTracker.xml"
+geometry_option = "det.xml"
+
+if not os.getenv("DETDRIFTCHAMBERROOT"):
+    print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." )
+    sys.exit(-1)
+
+geometry_path = os.path.join(os.getenv("DETDRIFTCHAMBERROOT"), "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
+
+##############################################################################
+# Physics 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 = ["pi+"]
+# gun.EnergyMins = [100.] # GeV
+# gun.EnergyMaxs = [100.] # GeV
+
+gun.Particles = ["e-"]
+
+# gun.PositionXs = [100.] # mm
+# gun.PositionYs = [100.] # mm
+# gun.PositionZs = [0.] # mm
+
+
+gun.EnergyMins = [10.] # GeV
+gun.EnergyMaxs = [10.] # GeV
+
+gun.ThetaMins = [90] # rad; 45deg
+gun.ThetaMaxs = [90] # rad; 45deg
+
+gun.PhiMins = [90] # rad; 0deg
+gun.PhiMaxs = [90] # rad; 360deg
+#gun.PhiMins = [0] # rad; 0deg
+#gun.PhiMaxs = [360] # rad; 360deg
+
+# stdheprdr = StdHepRdr("StdHepRdr")
+# stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep"
+
+# lciordr = SLCIORdr("SLCIORdr")
+# lciordr.Input = "/cefs/data/stdhep/lcio250/signal/Higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.slcio"
+
+# hepmcrdr = HepMCRdr("HepMCRdr")
+# hepmcrdr.Input = "example_UsingIterators.txt"
+
+genprinter = GenPrinter("GenPrinter")
+
+genalg = GenAlgo("GenAlgo")
+genalg.GenTools = ["GtGunTool"]
+# genalg.GenTools = ["StdHepRdr"]
+# genalg.GenTools = ["StdHepRdr", "GenPrinter"]
+# genalg.GenTools = ["SLCIORdr", "GenPrinter"]
+# genalg.GenTools = ["HepMCRdr", "GenPrinter"]
+
+##############################################################################
+# Detector Simulation
+##############################################################################
+from Configurables import DetSimSvc
+
+detsimsvc = DetSimSvc("DetSimSvc")
+
+# from Configurables import ExampleAnaElemTool
+# example_anatool = ExampleAnaElemTool("ExampleAnaElemTool")
+
+from Configurables import DetSimAlg
+
+detsimalg = DetSimAlg("DetSimAlg")
+
+if int(os.environ.get("VIS", 0)):
+    detsimalg.VisMacs = ["vis.mac"]
+
+detsimalg.RunCmds = [
+#    "/tracking/verbose 1",
+]
+detsimalg.AnaElems = [
+    # example_anatool.name()
+    # "ExampleAnaElemTool"
+    "Edm4hepWriterAnaElemTool"
+]
+detsimalg.RootDetElem = "WorldDetElemTool"
+
+from Configurables import AnExampleDetElemTool
+example_dettool = AnExampleDetElemTool("AnExampleDetElemTool")
+
+from Configurables import CalorimeterSensDetTool
+from Configurables import DriftChamberSensDetTool
+
+calo_sensdettool = CalorimeterSensDetTool("CalorimeterSensDetTool")
+driftchamber_sensdettool = DriftChamberSensDetTool("DriftChamberSensDetTool")
+
+# dedxoption = "DummyDedxSimTool"
+dedxoption = "BetheBlochEquationDedxSimTool"
+
+driftchamber_sensdettool.DedxSimTool = dedxoption
+
+from Configurables import DummyDedxSimTool
+from Configurables import BetheBlochEquationDedxSimTool
+
+if dedxoption == "DummyDedxSimTool":
+    dedx_simtool = DummyDedxSimTool("DummyDedxSimTool")
+elif dedxoption == "BetheBlochEquationDedxSimTool":
+    dedx_simtool = BetheBlochEquationDedxSimTool("BetheBlochEquationDedxSimTool")
+    dedx_simtool.material_Z = 2
+    dedx_simtool.material_A = 4
+    dedx_simtool.scale = 10
+    dedx_simtool.resolution = 0.0001
+
+##############################################################################
+from Configurables import DCHDigiAlg
+dCHDigiAlg = DCHDigiAlg("DCHDigiAlg")
+dCHDigiAlg.readout = "DriftChamberHitsCollection"
+dCHDigiAlg.drift_velocity = 40#um/ns
+dCHDigiAlg.mom_threshold = 0 #GeV
+dCHDigiAlg.SimDCHitCollection = "DriftChamberHitsCollection"
+dCHDigiAlg.DigiDCHitCollection = "DigiDCHitsCollection"
+dCHDigiAlg.AssociationCollection = "DCHAssociationCollectio"
+dCHDigiAlg.WriteAna  = True
+
+##############################################################################
+# POD I/O
+##############################################################################
+from Configurables import PodioOutput
+out = PodioOutput("outputalg")
+out.filename = "fit_DCH.root"
+out.outputCommands = ["keep *"]
+
+##############################################################################
+# TruthTrackerAlg
+##############################################################################
+from Configurables import TruthTrackerAlg
+truthTrackerAlg = TruthTrackerAlg("TruthTrackerAlg")
+truthTrackerAlg.DCHitAssociationCollection="DCHAssociationCollectio"
+truthTrackerAlg.debug = 1
+
+##############################################################################
+# GenfitAlg
+##############################################################################
+from Configurables import RecGenfitAlgDC
+recGenfitAlgDC = RecGenfitAlgDC("RecGenfitAlgDC")
+recGenfitAlgDC.debug = 11
+
+##############################################################################
+# NTupleSvc
+##############################################################################
+from Configurables import NTupleSvc
+ntsvc = NTupleSvc("NTupleSvc")
+ntsvc.Output = ["MyTuples DATAFILE='DCH_digi_ana.root' OPT='NEW' TYP='ROOT'",
+                "TruthTrackerAlg DATAFILE='result_truthTracker_STD.root' OPT='NEW' TYP='ROOT'",
+                "RecGenfitAlgDC DATAFILE='result_fit_SDT.root' OPT='NEW' TYP='ROOT'"]
+
+##############################################################################
+# ApplicationMgr
+##############################################################################
+
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [genalg, detsimalg, dCHDigiAlg, truthTrackerAlg,
+                          recGenfitAlgDC, out],
+                EvtSel = 'NONE',
+                EvtMax = 1,
+                ExtSvc = [rndmengine, dsvc, geosvc, ntsvc],
+                HistogramPersistency = "ROOT",
+                OutputLevel=DEBUG
+)
diff --git a/Reconstruction/RecGenfitAlg/CMakeLists.txt b/Reconstruction/RecGenfitAlg/CMakeLists.txt
new file mode 100644
index 00000000..920ae7b9
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/CMakeLists.txt
@@ -0,0 +1,39 @@
+gaudi_subdir(RecGenfitAlg v0r0)
+
+find_package(CLHEP REQUIRED;CONFIG)
+find_package(GSL REQUIRED )
+find_package(LCIO REQUIRED )
+find_package(podio REQUIRED )
+find_package(EDM4HEP REQUIRED)
+find_package(ROOT REQUIRED Geom)
+find_package(DD4hep COMPONENTS DDCore DDRec DDParsers REQUIRED)
+
+gaudi_depends_on_subdirs(
+    Detector/DetInterface
+    Detector/DetSegmentation
+    Utilities/DataHelper
+)
+
+set (GenFit_INCLUDE_DIRS $ENV{GENFIT_ROOT}/include)
+set (GenFit_LIB_DIRS $ENV{GENFIT_ROOT}/lib64)
+set (Eigen_INCLUDE_DIRS $ENV{Eigen_ROOT}/include/eigen3)
+
+set(RecGenfitAlg_srcs
+  src/RecGenfitAlgDC.cpp
+  src/GenfitTrack.cpp
+  src/GenfitField.cpp
+  src/GenfitFitter.cpp
+  src/GenfitMaterialInterface.cpp
+  src/GenfitMsg.cpp
+  )
+
+# Modules
+gaudi_add_module(RecGenfitAlg ${RecGenfitAlg_srcs}
+  INCLUDE_DIRS k4FWCore GaudiKernel GaudiAlgLib CLHEP ROOT gear
+  ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} ${GenFit_INCLUDE_DIRS}
+  ${Eigen_INCLUDE_DIRS}
+  LINK_LIBRARIES k4FWCore GaudiKernel GaudiAlgLib CLHEP ROOT DataHelperLib
+  DetSegmentation $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES}
+  ${GenFit_LIB_DIRS}/libgenfit2.so DD4hep ${DD4hep_COMPONENT_LIBRARIES}
+  -Wl,--no-as-needed EDM4HEP::edm4hep EDM4HEP::edm4hepDict -Wl,--as-needed
+  )
diff --git a/Reconstruction/RecGenfitAlg/README.md b/Reconstruction/RecGenfitAlg/README.md
new file mode 100644
index 00000000..3b08f667
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/README.md
@@ -0,0 +1,12 @@
+# RecGenfitAlg package
+
+This package is the track fitting algorithms to do track fitting with genfit.
+It's incudingg the interface to genfit fitter, track and measurement:
+* GenfitAlg: The algorithm for drift chamber fitting with genfit
+* GenfitFitter: fitter implementation
+* GenfitTrack: class for create and access of genfit Track and Measurement
+* GenfitField: implementation of genfit AbsField
+* GenfitGeoMaterialInterface: implementation of genfit AbsMaterialInterface
+* GenfitMsg: a class to get Gaudi message instance in Genfit classes.
+* HelixTrackModel: a class to get Gaudi message instance in Genfit classes.
+
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitField.cpp b/Reconstruction/RecGenfitAlg/src/GenfitField.cpp
new file mode 100644
index 00000000..de6df542
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitField.cpp
@@ -0,0 +1,59 @@
+#include "GenfitField.h"
+#include "GenfitMsg.h"
+
+//External
+#include "DD4hep/DD4hepUnits.h"
+
+//genfit
+#include "FieldManager.h"
+#include "ConstField.h"
+
+///-------------------------------------------------------------
+/// GenfitField constructor
+///-------------------------------------------------------------
+GenfitField::GenfitField(dd4hep::OverlayedField dd4hepField)
+:m_dd4hepField(dd4hepField)
+{
+    genfit::FieldManager::getInstance()->init(this);
+}
+
+
+///-------------------------------------------------------------
+/// GenfitField get field value by TVector3
+///-------------------------------------------------------------
+/// unit in genfit is cm and kGauss
+TVector3 GenfitField::get(const TVector3& pos) const
+{
+    double B[3]={1e9,1e9,1e9};
+    get(pos.X(),pos.Y(),pos.Z(),B[0],B[1],B[2]);
+    return TVector3(B[0],B[1],B[2]);
+}
+
+///-------------------------------------------------------------
+/// GenfitField get field value by double
+///-------------------------------------------------------------
+/// unit in genfit for position is cm and Bxyz is kGauss
+/// unit in DD4hepUnits kilogaus and cm? FIXME
+void
+GenfitField::get(const double& posX, const double& posY, const double& posZ,
+        double& Bx, double& By, double& Bz) const
+{
+    /// get field from dd4hepField
+    const dd4hep::Direction& field=m_dd4hepField.magneticField(
+            dd4hep::Position(posX/dd4hep::cm,posY/dd4hep::cm,posZ/dd4hep::cm));
+    //m_dd4hepField.magneticField(pos,B);
+
+    double factor = 1./dd4hep::kilogauss;
+    Bx=field.X()/dd4hep::kilogauss;
+    By=field.Y()/dd4hep::kilogauss;
+    Bz=field.Z()/dd4hep::kilogauss;
+
+//    std::cout<<"GenfitField "
+//      <<Form("xyz(%f,%f,%f)cm B(%f,%f,%f)kilogauss",posX,posY,posZ,Bx,By,Bz)
+//      <<std::endl;
+}
+
+double GenfitField::getBz(const TVector3& pos) const
+{
+    return get(pos).Z();
+}
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitField.h b/Reconstruction/RecGenfitAlg/src/GenfitField.h
new file mode 100644
index 00000000..406d0e6b
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitField.h
@@ -0,0 +1,38 @@
+///////////////////////////////////////////////////////////
+////   An implementation of genfit AbsBField - GenfitField
+//// Authors:
+////   Yao ZHANG (zhangyao@ihep.ac.cn)
+///////////////////////////////////////////////////////////
+
+#ifndef RECGENFITALG_GENFITFIELD_H
+#define RECGENFITALG_GENFITFIELD_H
+
+#include "AbsBField.h"
+#include "DD4hep/Fields.h"
+
+class TVector3;
+
+
+/// Calss for translating Field into genfit::AbsBField
+class GenfitField : public genfit::AbsBField{
+    public:
+        GenfitField(dd4hep::OverlayedField dd4hepField);
+        virtual ~GenfitField(){;}
+
+        //Get field value from TVector3
+        TVector3 get(const TVector3& pos) const override;
+
+        //Get field value from doubles
+        void get(const double& posX, const double& posY, const double& posZ,
+                double& Bx, double& By, double& Bz) const override;
+
+        //Get Bz, kilogauss
+        double getBz(const TVector3& pos) const;
+
+        //Get dd4hep field
+        const dd4hep::OverlayedField field() const {return m_dd4hepField;}
+
+    private:
+        dd4hep::OverlayedField m_dd4hepField;
+};
+#endif
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitFitter.cpp b/Reconstruction/RecGenfitAlg/src/GenfitFitter.cpp
new file mode 100644
index 00000000..2a7745b6
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitFitter.cpp
@@ -0,0 +1,614 @@
+#include "GenfitFitter.h"
+#include "GenfitTrack.h"
+#include "GenfitMsg.h"
+#include "GenfitField.h"
+#include "GenfitMaterialInterface.h"
+
+//Gaudi
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/ISvcLocator.h"
+
+//External
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/Detector.h"
+
+//genfit
+#include <Track.h>
+#include <Exception.h>
+#include <FieldManager.h>
+#include <TGeoMaterialInterface.h>
+#include <TGeoManager.h>
+#include <MaterialEffects.h>
+#include <MeasuredStateOnPlane.h>
+#include <KalmanFitter.h>
+#include <KalmanFitterRefTrack.h>
+#include <StateOnPlane.h>
+#include <DAF.h>
+#include <AbsKalmanFitter.h>
+#include <KalmanFitterInfo.h>
+
+//ROOT
+#include <TVector3.h>
+#include <TGeoManager.h>
+
+//STL
+#include <iostream>
+#include <string>
+
+
+GenfitFitter::~GenfitFitter(){
+    delete m_absKalman;
+}
+
+GenfitFitter::GenfitFitter(const char* type, const char* name):
+    m_absKalman(nullptr)
+    ,m_genfitField(nullptr)
+    ,m_geoMaterial(nullptr)
+    ,m_fitterType(type)
+    ,m_name(name)
+    ,m_minIterations(4)
+    ,m_maxIterations(10)
+    ,m_deltaPval(1e-3)
+    ,m_relChi2Change(0.2)
+    ,m_blowUpFactor(1e3)
+    ,m_resetOffDiagonals(true)
+    ,m_blowUpMaxVal(1.e6)
+    ,m_multipleMeasurementHandling(genfit::unweightedClosestToPredictionWire)
+    ,m_maxFailedHits(-1)
+    ,m_deltaWeight(1e-3)
+    ,m_annealingBetaStart(100)
+    ,m_annealingBetaStop(0.01)
+    ,m_annealingNSteps(0.01)
+    ,m_noEffects(false)
+    ,m_energyLossBetheBloch(true)
+    ,m_noiseBetheBloch(true)
+    ,m_noiseCoulomb(true)
+    ,m_energyLossBrems(false)
+    ,m_noiseBrems(false)
+    ,m_ignoreBoundariesBetweenEqualMaterials(true)
+    ,m_mscModelName("GEANE")
+    ,m_debug(0)
+    ,m_hist(0)
+{
+    /// Initialize genfit fitter
+    init();
+}
+
+void GenfitFitter::setField(const GenfitField* field)
+{
+    if(nullptr==m_genfitField) m_genfitField=field;
+}
+
+/// Set geometry for material, use geometry from IOADatabase
+void GenfitFitter::setGeoMaterial(const dd4hep::Detector* dd4hepGeo)
+{
+    if(nullptr==m_geoMaterial){
+        m_geoMaterial=GenfitMaterialInterface::getInstance(dd4hepGeo);
+    }
+}
+
+/// initialize genfit fitter
+int GenfitFitter::init(bool deleteOldFitter)
+{
+    if(deleteOldFitter && m_absKalman) delete m_absKalman;
+
+    GenfitMsg::get()<<MSG::DEBUG<<"Initialize GenfitFitter with "
+        <<m_fitterType<<endmsg;
+
+    if (m_fitterType=="DAFRef") {
+        m_absKalman = new genfit::DAF(true,getDeltaPval(),
+                getConvergenceDeltaWeight());
+    }
+    else if (m_fitterType=="DAF") {
+        m_absKalman = new genfit::DAF(false,getDeltaPval(),
+                getConvergenceDeltaWeight());
+    }
+    else if (m_fitterType=="KalmanFitter") {
+        m_absKalman = new genfit::KalmanFitter(getMaxIterations());
+    }
+    else if (m_fitterType=="KalmanFitterRefTrack") {
+        m_absKalman = new genfit::KalmanFitterRefTrack(getMaxIterations());
+    }
+    else {
+        m_absKalman = nullptr;
+        GenfitMsg::get()<< MSG::DEBUG<<"Fitter type is invalid:"
+            <<m_fitterType<<endmsg;
+        return -1;
+    }
+    GenfitMsg::get()<<MSG::DEBUG<<"Fitter type is "<<m_fitterType<<endmsg;
+std::cout<<__FILE__<<"   "<<__LINE__<<m_absKalman<<std::endl;
+    m_absKalman->setDebugLvl(m_debug);
+std::cout<<__FILE__<<"   "<<__LINE__<<std::endl;
+
+    return 0;
+}
+
+/// Fit a track from a candidate track
+int GenfitFitter::processTrackWithRep(GenfitTrack* track,int repID,bool resort)
+{
+    GenfitMsg::get()<<MSG::DEBUG<< "In ProcessTrackWithRep rep "<<repID<<endmsg;
+    if(getDebug()>2) print("");
+
+    if(getDebug()>0){
+        GenfitMsg::get()<<MSG::DEBUG<<"Print track seed "<<endmsg;
+        track->getTrack()->getStateSeed().Print();
+    }
+    /// Do the fitting
+    try{
+        m_absKalman->processTrackWithRep(track->getTrack(), track->getRep(repID),
+                resort);
+    }catch(genfit::Exception& e){
+        GenfitMsg::get()<<MSG::DEBUG<<"Genfit exception caught "<<endmsg;
+        e.what();
+        return false;
+    }
+    GenfitMsg::get()<<MSG::DEBUG<<"End of ProcessTrackWithRep"<<endmsg;
+    return true;
+} // End of ProcessTrackWithRep
+
+/// Fit a track from a candidate track
+int GenfitFitter::processTrack(GenfitTrack* track, bool resort)
+{
+    GenfitMsg::get()<<MSG::DEBUG<<"In ProcessTrack"<<endmsg;
+    if(getDebug()>2) print("");
+
+    /// Do the fitting
+    try{
+        m_absKalman->processTrack(track->getTrack(),resort);
+    }catch(genfit::Exception& e){
+        GenfitMsg::get()<<MSG::DEBUG<<"Genfit exception caught "<<endmsg;
+        e.what();
+        return false;
+    }
+    GenfitMsg::get()<<MSG::DEBUG<<"End of ProcessTrack"<<endmsg;
+    return true;
+} // End of ProcessTrack
+
+
+void GenfitFitter::setFitterType(const char* val)
+{
+    std::string oldFitterType=m_fitterType;
+    m_fitterType = val;
+    GenfitMsg::get()<<MSG::DEBUG<<"Fitter type is "<<m_fitterType<<endmsg;
+    init(oldFitterType==val);
+}
+
+/// Extrapolate track to the cloest point of approach(POCA) to the wire of hit,
+/// return StateOnPlane of this POCA
+/// inputs
+///  pos,mom ... position & momentum at starting point, unit= [mm]&[GeV/c]
+///              (converted to [cm]&[GeV/c] inside this function)
+///  hit ... destination
+/// outputs poca [mm] (converted from [cm] in this function) ,global
+double GenfitFitter::extrapolateToHit( TVector3& poca, TVector3& pocaDir,
+        TVector3& pocaOnWire, double& doca, const GenfitTrack* track,
+        TVector3 pos, TVector3 mom,
+        TVector3 end0,//one end of the hit wire
+        TVector3 end1,//the orhter end of the hit wire
+        int debug,
+        int repID,
+        bool stopAtBoundary,
+        bool calcJacobianNoise)
+{
+
+    return track->extrapolateToHit(poca,pocaDir,pocaOnWire,doca,pos,mom,end0,
+            end1,debug,repID,stopAtBoundary,calcJacobianNoise);
+}//end of ExtrapolateToHit
+
+
+/// Extrapolate the track to the cyliner at fixed raidus
+/// position & momentum as starting point
+/// position and momentum at global coordinate in dd4hepUnit
+/// return trackLength in dd4hepUnit
+    double
+GenfitFitter::extrapolateToCylinder(TVector3& pos, TVector3& mom,
+        GenfitTrack* track, double radius, const TVector3 linePoint,
+        const TVector3 lineDirection, int hitID, int repID,
+        bool stopAtBoundary, bool calcJacobianNoise)
+{
+    double trackLength(1e9*dd4hep::cm);
+    if(!track->getFitStatus(repID)->isFitted()) return trackLength;
+    try{
+        // get track rep
+        genfit::AbsTrackRep* rep = track->getRep(repID);
+        if(nullptr == rep) {
+            GenfitMsg::get()<<MSG::DEBUG<<"In ExtrapolateToCylinder rep is null"
+                <<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+
+        // get track point with fitter info
+        genfit::TrackPoint* tp =
+            track->getTrack()->getPointWithFitterInfo(hitID,rep);
+        if(nullptr == tp) {
+            GenfitMsg::get()<<MSG::DEBUG<<
+                "In ExtrapolateToCylinder TrackPoint is null"<<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+
+        // get fitted state on plane of this track point
+        genfit::KalmanFittedStateOnPlane* state =
+            static_cast<genfit::KalmanFitterInfo*>(
+                    tp->getFitterInfo(rep))->getBackwardUpdate();
+
+        if(nullptr == state){
+            GenfitMsg::get()<<MSG::DEBUG<<"In ExtrapolateToCylinder "
+                <<"no KalmanFittedStateOnPlane in backwardUpdate"<<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+        rep->setPosMom(*state, pos*(1/dd4hep::cm), mom*(1/dd4hep::GeV));
+
+        /// extrapolate
+        trackLength = rep->extrapolateToCylinder(*state,
+                radius/dd4hep::cm, linePoint*(1/dd4hep::cm), lineDirection,
+                stopAtBoundary, calcJacobianNoise);
+        // get pos&mom at extrapolated point on the cylinder
+        rep->getPosMom(*state,pos,mom);//FIXME exception exist
+        pos = pos*dd4hep::cm;
+        mom = mom*dd4hep::GeV;
+    } catch(genfit::Exception& e){
+        GenfitMsg::get() << MSG::ERROR
+            <<"Exception in GenfitFitter::extrapolateToCylinder "
+            << e.what()<<endmsg;
+        trackLength = 1e9*dd4hep::cm;
+    }
+    return trackLength*dd4hep::cm;
+}
+
+double GenfitFitter::extrapolateToPoint(TVector3& pos, TVector3& mom,
+        const GenfitTrack* track,
+        const TVector3& point,
+        int repID,// same with pidType
+        bool stopAtBoundary,
+        bool calcJacobianNoise) const
+{
+    double trackLength(1e9*dd4hep::cm);
+    if(!track->getFitStatus(repID)->isFitted()) return trackLength;
+    try{
+        // get track rep
+        genfit::AbsTrackRep* rep = track->getRep(repID);
+        if(nullptr == rep) {
+            GenfitMsg::get()<<MSG::DEBUG<<"In ExtrapolateToPoint rep "
+                <<repID<<" not exist!"<<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+
+        /// extrapolate to point
+        //genfit::StateOnPlane state(*(&(track->getTrack()->getFittedState(0,rep))));
+
+        // get track point with fitter info
+        genfit::TrackPoint* tp =
+            track->getTrack()->getPointWithFitterInfo(0,rep);
+        if(nullptr == tp) {
+            GenfitMsg::get()<<MSG::DEBUG<<
+                "In ExtrapolateToPoint TrackPoint is null"<<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+
+        // get fitted state on plane of this track point
+        genfit::KalmanFittedStateOnPlane* state =
+            static_cast<genfit::KalmanFitterInfo*>(
+                    tp->getFitterInfo(rep))->getBackwardUpdate();
+
+        if(nullptr == state) {
+            GenfitMsg::get()<<MSG::DEBUG<<
+                "In ExtrapolateToPoint KalmanFittedStateOnPlane is null"<<endmsg;
+            return trackLength*dd4hep::cm;
+        }
+        trackLength = rep->extrapolateToPoint(*state,
+                point*(1/dd4hep::cm),stopAtBoundary, calcJacobianNoise);
+        rep->getPosMom(*state,pos,mom);//FIXME exception exist
+        pos = pos*dd4hep::cm;
+        mom = mom*dd4hep::GeV;
+    } catch(genfit::Exception& e){
+        GenfitMsg::get() << MSG::ERROR
+            <<"Exception in GenfitFitter::extrapolateToPoint"
+            << e.what()<<endmsg;
+        trackLength = 1e9*dd4hep::cm;
+    }
+    return trackLength*dd4hep::cm;
+}//end of ExtrapolateToPoint
+
+GenfitFitter& GenfitFitter::operator=(
+        const GenfitFitter& r)
+{
+    m_fitterType          = r.m_fitterType;
+    m_minIterations       = r.m_minIterations;
+    m_maxIterations       = r.m_maxIterations;
+    m_deltaPval           = r.m_deltaPval;
+    m_relChi2Change       = r.m_relChi2Change;
+    m_blowUpFactor        = r.m_blowUpFactor;
+    m_resetOffDiagonals   = r.m_resetOffDiagonals;
+    m_blowUpMaxVal        = r.m_blowUpMaxVal;
+    m_multipleMeasurementHandling = r.m_multipleMeasurementHandling;
+    m_maxFailedHits       = r.m_maxFailedHits;
+    m_annealingNSteps     = r.m_annealingNSteps;
+    m_deltaWeight         = r.m_deltaWeight;
+    m_annealingBetaStart  = r.m_annealingBetaStart;
+    m_annealingBetaStop   = r.m_annealingBetaStop;
+    m_noEffects           = r.m_noEffects;
+    m_energyLossBetheBloch= r.m_energyLossBetheBloch;
+    m_noiseBetheBloch     = r.m_noiseBetheBloch;
+    m_noiseCoulomb        = r.m_noiseCoulomb;
+    m_energyLossBrems     = r.m_energyLossBrems;
+    m_noiseBrems          = r.m_noiseBrems;
+    m_ignoreBoundariesBetweenEqualMaterials
+        = r.m_ignoreBoundariesBetweenEqualMaterials;
+    m_mscModelName        = r.m_mscModelName;
+    m_debug               = r.m_debug;
+    m_hist                = r.m_hist;
+    return *this;
+}
+
+void GenfitFitter::print(const char* name)
+{
+
+    if(0==strlen(name)) name=m_name;
+    //TODO print all fitting parameters
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" GenfitFitter Global Parameters:"<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" Fitter type          = " << m_fitterType<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" Fitting Parameters:"<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" MinIteration         = " << m_minIterations<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" MaxIteration         = " << m_maxIterations<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_deltaPval           = " << m_deltaPval<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" Material Effect Parameters:"<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_noEffects           = " << m_noEffects<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_energyLossBetheBloch= " << m_energyLossBetheBloch<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_noiseBetheBloch     = " << m_noiseBetheBloch<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_noiseCoulomb        = " << m_noiseCoulomb<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_energyLossBrems     = " << m_energyLossBrems<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_noiseBrems          = " << m_noiseBrems<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_ignoreBoundariesBetweenEqualMaterials= "
+        << m_ignoreBoundariesBetweenEqualMaterials<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_mscModelName        = " << m_mscModelName<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_debug               = " << m_debug<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<name
+        <<" m_hist                 = " << m_hist<<endmsg;
+
+    if(m_fitterType=="DAF"||m_fitterType=="DAFRef"){
+        genfit::DAF* daf = getDAF();
+
+        if(nullptr != daf){
+            std::ostringstream sBetas;
+            std::vector<double> betas = daf->getBetas();
+            for (unsigned int i=0; i<betas.size(); ++i) {
+                sBetas<<betas.at(i)<<",";
+            }
+            GenfitMsg::get()<<MSG::DEBUG<<" print "<<betas.size()<<
+                " betas: %s "<<sBetas.str()<<endmsg;
+            GenfitMsg::get()<<MSG::DEBUG<<m_name
+                << " m_deltaWeight         = " << m_deltaWeight<<endmsg;
+            GenfitMsg::get()<<MSG::DEBUG<<" DAF maxIterations= "
+                << daf->getMaxIterations()<<endmsg;
+            GenfitMsg::get()<<MSG::DEBUG<<" DAF minIterations= "
+                << daf->getMinIterations()<<endmsg;
+            GenfitMsg::get()<<MSG::DEBUG<<" DAF deltaPval= "
+                << daf->getDeltaPval()<<endmsg;
+        }
+    }
+    genfit::KalmanFitterRefTrack* ref = getKalRef();
+    if(nullptr != ref){
+        std::ostringstream sBetas;
+        GenfitMsg::get()<<MSG::DEBUG<<" DAF maxIterations= "
+            << ref->getMaxIterations()<<endmsg;
+        GenfitMsg::get()<<MSG::DEBUG<<" DAF minIterations= "
+            << ref->getMinIterations()<<endmsg;
+        GenfitMsg::get()<<MSG::DEBUG<<" DAF deltaPval= "
+            << ref->getDeltaPval()<<endmsg;
+    }
+}
+
+///Setters of AbsKalmanFitter
+void GenfitFitter::setMinIterations(unsigned int val)
+{
+    m_absKalman->setMinIterations(val);
+    m_minIterations = val;
+}
+
+void GenfitFitter::setMaxIterations(unsigned int val)
+{
+    if(val<=4) {
+        GenfitMsg::get()<<MSG::ERROR<<"Could NOT set MaxIteration<=4!"<<endmsg;
+    }
+    m_absKalman->setMaxIterations(val);
+    m_maxIterations = val;
+}
+
+void GenfitFitter::setMaxIterationsBetas(double bStart,double bFinal,
+        unsigned int val)
+{
+    m_absKalman->setMaxIterations(val);
+    m_maxIterations = val;
+    if(val<=4) {
+        GenfitMsg::get()<<MSG::ERROR<<"Could NOT set MaxIteration<=4!"<<endmsg;
+    }
+    GenfitMsg::get()<<MSG::DEBUG<<"bStart "<<bStart<<" bFinal "<<bFinal
+        <<" MaxIteration "<<val<<endmsg;
+    // genfit version less than 2.2.0
+    genfit::DAF* daf = dynamic_cast<genfit::DAF*> (m_absKalman);
+    daf->setAnnealingScheme(bStart,bFinal,val);
+}
+
+void GenfitFitter::setDeltaPval(double val)
+{
+    m_absKalman->setDeltaPval(val);
+    m_deltaPval = val;
+}
+
+void GenfitFitter::setRelChi2Change(double val)
+{
+    m_absKalman->setRelChi2Change(val);
+    m_relChi2Change = val;
+}
+
+void GenfitFitter::setBlowUpFactor(double val)
+{
+    m_absKalman->setBlowUpFactor(val);
+    m_blowUpFactor = val;
+}
+
+void GenfitFitter::setResetOffDiagonals(bool val)
+{
+    m_absKalman->setResetOffDiagonals(val);
+    m_resetOffDiagonals = val;
+}
+
+void GenfitFitter::setBlowUpMaxVal(double val)
+{
+    m_absKalman->setBlowUpMaxVal(val);
+    m_blowUpMaxVal = val;
+}
+
+void GenfitFitter::setMultipleMeasurementHandling(
+        genfit::eMultipleMeasurementHandling val)
+{
+    m_absKalman->setMultipleMeasurementHandling(val);
+    m_multipleMeasurementHandling = val;
+}
+
+void GenfitFitter::setMaxFailedHits(int val)
+{
+    m_absKalman->setMaxFailedHits(val);
+    m_maxFailedHits = val;
+}
+
+///DAF setters
+void GenfitFitter::setConvergenceDeltaWeight(double val)
+{
+    genfit::DAF* daf = getDAF();
+    if(nullptr != daf) daf->setConvergenceDeltaWeight(val);
+    m_deltaWeight = val;
+}
+void GenfitFitter::setAnnealingScheme(
+        double bStart, double bFinal, unsigned int nSteps)
+{
+    genfit::DAF* daf = getDAF();
+    if(nullptr != daf) daf->setAnnealingScheme(bStart, bFinal, nSteps);
+    m_annealingBetaStart = bStart;
+    m_annealingBetaStop = bFinal;
+    m_annealingNSteps = nSteps;
+}
+
+//TODO chi2Cuts?
+///Material effects
+void GenfitFitter::setNoEffects(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setNoEffects();
+    m_noEffects = val;
+}
+
+void GenfitFitter::setEnergyLossBetheBloch(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setEnergyLossBetheBloch(val);
+    m_energyLossBetheBloch = val;
+}
+
+void GenfitFitter::setNoiseBetheBloch(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setNoiseBetheBloch(val);
+    m_noiseBetheBloch = val;
+}
+
+void GenfitFitter::setNoiseCoulomb(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setNoiseCoulomb(val);
+    m_noiseCoulomb = val;
+}
+
+void GenfitFitter::setEnergyLossBrems(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setEnergyLossBrems(val);
+    m_energyLossBrems = val;
+}
+
+void GenfitFitter::setNoiseBrems(bool val)
+{
+    genfit::MaterialEffects::getInstance()->setNoiseBrems(val);
+    m_noiseBrems = val;
+}
+
+void GenfitFitter::setIgnoreBoundariesBetweenEqualMaterials(bool val)
+{
+    genfit::MaterialEffects::getInstance()->
+        ignoreBoundariesBetweenEqualMaterials(val);
+    m_ignoreBoundariesBetweenEqualMaterials = val;
+}
+
+void GenfitFitter::setMscModelName(std::string val)
+{
+    genfit::MaterialEffects::getInstance()->setMscModel(val);
+    m_mscModelName = val;
+}
+
+void GenfitFitter::setMaterialDebugLvl(unsigned int val)
+{
+    genfit::MaterialEffects::getInstance()->setDebugLvl(val);
+}
+
+///Set GenfitFitter parameters
+void GenfitFitter::setDebug(unsigned int val)
+{
+    GenfitMsg::get()<<MSG::DEBUG<<"set fitter debugLvl "<<val<<endmsg;
+    m_absKalman->setDebugLvl(val);
+    if(nullptr!=getDAF()) getDAF()->setDebugLvl(val);
+    if(val>10) genfit::MaterialEffects::getInstance()->setDebugLvl(val);
+    m_debug = val;
+}
+
+void GenfitFitter::setHist(unsigned int val) {m_hist = val;}
+
+genfit::DAF* GenfitFitter::getDAF()
+{
+    genfit::DAF* daf = nullptr;
+    try{
+        daf = dynamic_cast<genfit::DAF*> (m_absKalman);
+    }catch(...){
+        GenfitMsg::get()<< MSG::ERROR
+            << "dynamic_cast m_rom AbsFitter to DAF m_ailed!"<<endmsg;
+        return nullptr;
+    }
+    return daf;
+}
+
+genfit::KalmanFitterRefTrack* GenfitFitter::getKalRef()
+{
+    genfit::KalmanFitterRefTrack* ref=nullptr;
+    try{
+        ref = dynamic_cast<genfit::KalmanFitterRefTrack*> (m_absKalman);
+    }catch(...){
+        GenfitMsg::get()<< MSG::ERROR
+            << "dynamic_cast m_rom AbsFitter to KalmanFitterRefTrack m_ailed!"
+            <<endmsg;
+    }
+    return ref;
+}
+
+void GenfitFitter::initHist(std::string name)
+{
+    GenfitMsg::get()<<MSG::DEBUG<<"GenfitFitter::initHist "<<name<<endmsg;
+    //getDAF()->initHist(name);
+}
+
+void GenfitFitter::writeHist()
+{
+    GenfitMsg::get()<<MSG::DEBUG<<"GenfitFitter::writeHist "<<endmsg;
+    //getDAF()->writeHist();
+}
+
+
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitFitter.h b/Reconstruction/RecGenfitAlg/src/GenfitFitter.h
new file mode 100644
index 00000000..9ca46644
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitFitter.h
@@ -0,0 +1,200 @@
+//////////////////////////////////////////////////////////////////
+///
+/// This is an interface of to call genfit fitter
+///
+/// In this file, including:
+///   a genfit fitter class
+///   Fitter type is fixed after creation
+///   Magnetic field and geometry for material effect are singletons in genfit.
+///   They will be set before fitting and before each time call track rep.
+///
+/// Authors:
+///   Yao ZHANG (zhangyao@ihep.ac.cn)
+///
+//////////////////////////////////////////////////////////////////
+
+#ifndef RECGENFITALG_GENFITFITTER_H
+#define RECGENFITALG_GENFITFITTER_H
+
+#include "AbsKalmanFitter.h"
+#include <string>
+
+class GenfitField;
+class GenfitMaterialInterface;
+class GenfitTrack;
+class TVector3;
+class TGeoManager;
+class ISvcLocator;
+namespace genfit{
+    class AbsKalmanFitter;
+    class KalmanFitterRefTrack;
+    class DAF;
+}
+namespace dd4hep{
+    class OverlayedField;
+    class Detector;
+}
+
+
+/// The GenfitTrack class
+class GenfitFitter{
+    public:
+        /// Type of fitters are :DAFRef,DAF,KalmanFitter,KalmanFitterRefTrack
+        GenfitFitter(const char* type="DAFRef",const char* name="GenfitFitter");
+        virtual ~GenfitFitter();
+
+        /// Magnetic field and geometry for material effect in genfit
+        /// please SET before use !!!!
+        void setField(const GenfitField* field);
+        /// please SET before use !!!!
+        void setGeoMaterial(const dd4hep::Detector* dd4hepGeo);
+
+        /// Main fitting function
+        int processTrack(GenfitTrack* track, bool resort=false);
+
+        /// fitting with rep
+        int processTrackWithRep(GenfitTrack* track,int repID=0,
+                bool resort=false);
+
+        /// Extrapolate the track to the CDC hit
+        /// Output: poca pos and dir and poca distance to the hit wire
+        /// Input: genfit track, pos and mom, two ends of a wire
+        ///        pos, and mom are position & momentum at starting point
+        double extrapolateToHit(TVector3& poca, TVector3& pocaDir,
+                TVector3& pocaOnWire, double& doca, const GenfitTrack* track,
+                TVector3 pos, TVector3 mom, TVector3 end0, TVector3 end1,
+                int debug=0, int repID=0, bool stopAtBoundary=false,
+                bool calcJacobianNoise=false);
+
+        /// Extrapolate the track to the cyliner at fixed raidus
+        /// Output: pos and mom at fixed radius
+        /// Input: genfitTrack, radius of cylinder at center of the origin,
+        ///        repID, stopAtBoundary and calcAverageState
+        double extrapolateToCylinder(TVector3& pos, TVector3& mom,
+                GenfitTrack* track, double radius, const TVector3 linePoint,
+                const TVector3 lineDirection, int hitID =0, int repID=0,
+                bool stopAtBoundary=false, bool calcJacobianNoise=false);
+
+        /// Extrapolate the track to the point
+        /// Output: pos and mom of POCA point to point
+        /// Input: genfitTrack,point,repID,stopAtBoundary and calcAverageState
+        /// repID same with pidType
+        double extrapolateToPoint(TVector3& pos, TVector3& mom,
+                const GenfitTrack* genfitTrack, const TVector3& point,
+                int repID=0, bool stopAtBoundary = false,
+                bool calcJacobianNoise = false) const;
+
+        /// setters of fitter properties
+        void setFitterType(const char* val);
+        void setMinIterations(unsigned int val);
+        void setMaxIterations(unsigned int val);
+        void setMaxIterationsBetas(double bStart,double bFinal,unsigned int val);
+        void setDeltaPval(double val);
+        void setRelChi2Change(double val);
+        void setBlowUpFactor(double val);
+        void setResetOffDiagonals(bool val);
+        void setBlowUpMaxVal(double val);
+        void setMultipleMeasurementHandling(
+                genfit::eMultipleMeasurementHandling val);
+        void setMaxFailedHits(int val);
+        void setConvergenceDeltaWeight(double val);
+        void setAnnealingScheme(double bStart,double bFinal,unsigned int nSteps);
+        //TODO chi2cut?
+        void setNoEffects(bool val);
+        void setEnergyLossBetheBloch(bool val);
+        void setNoiseBetheBloch(bool val);
+        void setNoiseCoulomb(bool val);
+        void setEnergyLossBrems(bool val);
+        void setNoiseBrems(bool val);
+        void setIgnoreBoundariesBetweenEqualMaterials(bool val);
+        void setMscModelName(std::string val);
+        void setMaterialDebugLvl(unsigned int val);
+        void setDebug(unsigned int val);
+        void setHist(unsigned int val);
+
+        /// getters of fitter properties
+        std::string getFitterType() const {return m_fitterType;}
+        unsigned int getMinIterations() const { return m_minIterations; }
+        unsigned int getMaxIterations() const { return m_maxIterations; }
+        double getDeltaPval() const { return m_deltaPval; }
+        double getRelChi2Change() const { return m_relChi2Change; }
+        double getBlowUpFactor() const { return m_blowUpFactor; }
+        double getBlowUpMaxVal() const { return m_blowUpMaxVal; }
+        bool getResetOffDiagonals() const { return m_resetOffDiagonals; }
+        genfit::eMultipleMeasurementHandling getMultipleMeasurementHandling()
+            const { return m_multipleMeasurementHandling; }
+        int getMaxFailedHits() const { return m_maxFailedHits; }
+        double getConvergenceDeltaWeight() const { return m_deltaWeight; }
+        float getAnnealingBetaStart() const {return m_annealingBetaStart;}
+        float getAnnealingBetaStop() const {return m_annealingBetaStop;}
+        bool getNoEffects(){return m_noEffects;}
+        bool getEnergyLossBetheBloch(){return m_energyLossBetheBloch;}
+        bool getNoiseBetheBloch(){return m_noiseBetheBloch;}
+        bool getNoiseCoulomb(){return m_noiseCoulomb;}
+        bool getEnergyLossBrems(){return m_energyLossBrems;}
+        bool getNoiseBrems(){return m_noiseBrems;}
+        bool getIgnoreBoundariesBetweenEqualMaterials()
+        {return m_ignoreBoundariesBetweenEqualMaterials;}
+        std::string getMscModelName(){return m_mscModelName;}
+        int  getDebug() const {return m_debug;}
+        int  getHist() const {return m_hist;}
+
+        /// Printer
+        void print(const char* name="");
+        void initHist(std::string name);
+        void writeHist();
+
+        const char* getName(void) const {return m_name;}
+
+    private:
+        GenfitFitter(const GenfitFitter&){};
+        GenfitFitter& operator=(const GenfitFitter&);
+
+        /// Initialze fitter and setting fitter parameter
+        int init(bool deleteOldFitter=false);
+
+        /// Get DAF fitter
+        genfit::DAF* getDAF();
+        /// Get KalmanFitterRefTrack
+        genfit::KalmanFitterRefTrack* getKalRef();
+
+        genfit::AbsKalmanFitter* m_absKalman;/// kalman fitter object
+
+        const GenfitField* m_genfitField;//pointer to genfit field
+        GenfitMaterialInterface* m_geoMaterial;//pointer to genfit geo
+
+        ///fitting method: DAFRef,DAF,KalmanFitter,KalmanFitterRefTrack
+        std::string m_fitterType;
+
+        const char* m_name;
+
+        /// control parameters of fitter
+        unsigned int m_minIterations;     /// minimum number of iterations
+        unsigned int m_maxIterations;     /// maximum number of iterations
+        double       m_deltaPval;         /// delta pVal that converged
+        double       m_relChi2Change;     ///
+        double       m_blowUpFactor;      ///
+        bool         m_resetOffDiagonals; ///
+        double       m_blowUpMaxVal;      ///
+        genfit::eMultipleMeasurementHandling m_multipleMeasurementHandling;///
+        int          m_maxFailedHits;     ///
+        double       m_deltaWeight;       /// delta weight that converged
+        double       m_annealingBetaStart;/// start beta for annealing
+        double       m_annealingBetaStop; /// stop beta for annealing
+        unsigned int m_annealingNSteps;   /// n steps
+
+        /// control parAmeters of material effects
+        bool         m_noEffects;
+        bool         m_energyLossBetheBloch;
+        bool         m_noiseBetheBloch;
+        bool         m_noiseCoulomb;
+        bool         m_energyLossBrems;
+        bool         m_noiseBrems;
+        bool         m_ignoreBoundariesBetweenEqualMaterials;
+        std::string  m_mscModelName;
+
+        int          m_debug;             /// debug
+        int          m_hist;             /// hist
+};
+
+#endif
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.cpp b/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.cpp
new file mode 100644
index 00000000..73a59316
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.cpp
@@ -0,0 +1,353 @@
+///
+///   Authors: ZHANG Yao (zhangyao@ihep.ac.cn)
+///
+
+#include "GenfitMaterialInterface.h"
+//Gaudi
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/SmartIF.h"
+#include "GaudiKernel/ISvcLocator.h"
+//CEPCSW
+#include "DetInterface/IGeomSvc.h"
+//Externals
+#include "DD4hep/Detector.h"
+//#include "DD4hep/DD4hepUnits.h"
+//genfit
+#include "Exception.h"
+//ROOT
+#include "TGeoManager.h"
+#include "TGeoNode.h"
+#include "TGeoMedium.h"
+#include "TGeoMaterial.h"
+#include "TGeoManager.h"
+#include "MaterialEffects.h"
+#include "Material.h"
+//STL
+#include <assert.h>
+#include <math.h>
+
+GenfitMaterialInterface* GenfitMaterialInterface::m_instance = nullptr;
+
+//#define DEBUG_GENFITGEO 1
+
+double MeanExcEnergy_get(int Z);
+double MeanExcEnergy_get(TGeoMaterial*);
+
+GenfitMaterialInterface::GenfitMaterialInterface(
+        const dd4hep::Detector* dd4hepGeo)
+{
+    assert(nullptr!=dd4hepGeo);
+    m_geoManager=&(dd4hepGeo->manager());
+    assert(nullptr!=m_geoManager);
+}
+
+GenfitMaterialInterface* GenfitMaterialInterface::getInstance(
+        const dd4hep::Detector* dd4hepGeo)
+{
+    if(nullptr == m_instance){
+        m_instance = new GenfitMaterialInterface(dd4hepGeo);
+    }
+    genfit::MaterialEffects::getInstance()->init(m_instance);
+    return m_instance;
+}
+
+void GenfitMaterialInterface::destruct(){
+    delete m_instance;
+}
+
+TGeoManager* GenfitMaterialInterface::getGeoManager()
+{
+    return m_geoManager;
+}
+
+    bool
+GenfitMaterialInterface::initTrack(double posX, double posY,
+        double posZ, double dirX, double dirY, double dirZ)
+{
+    //debugLvl_ = 1;
+#ifdef DEBUG_GENFITGEO
+    std::cout << "GenfitMaterialInterface::initTrack. \n";
+    std::cout << "Pos    "; TVector3(posX, posY, posZ).Print();
+    std::cout << "Dir    "; TVector3(dirX, dirY, dirZ).Print();
+#endif
+
+    // Move to the new point.
+    bool result = !isSameLocation(posX, posY, posZ, kTRUE);
+
+    // Set the intended direction.
+    setCurrentDirection(dirX, dirY, dirZ);
+
+    if (debugLvl_ > 0) {
+        std::cout << "      GenfitMaterialInterface::initTrack at \n";
+        std::cout << "      position:  "; TVector3(posX, posY, posZ).Print();
+        std::cout << "      direction: "; TVector3(dirX, dirY, dirZ).Print();
+    }
+
+    return result;
+}
+
+
+genfit::Material GenfitMaterialInterface::getMaterialParameters()
+{
+    TGeoMaterial* mat =
+        getGeoManager()->GetCurrentVolume()->GetMedium()->GetMaterial();
+    //Scalar density;  /// Density in g / cm^3
+    //Scalar Z;  /// Atomic number
+    //Scalar A;  /// Mass number in g / mol
+    //Scalar radiationLength;  /// Radiation Length in cm
+    //Scalar mEE;  /// Mean excitaiton energy in eV
+    //Material from CEPCSW is NOT follow the dd4hep?FIXME
+
+    //std::cout<<__FILE__<<" "<<__LINE__<<" yzhang debug material "<<std::endl;
+    //mat->Print();
+    return genfit::Material(mat->GetDensity(), mat->GetZ(), mat->GetA(),
+            mat->GetRadLen(), MeanExcEnergy_get(mat));
+}
+
+    double
+GenfitMaterialInterface::findNextBoundary(const genfit::RKTrackRep* rep,
+        const genfit::M1x7& stateOrig,
+        double sMax, // signed
+        bool varField)
+{
+    //debugLvl_ = 1;
+    // cm, distance limit beneath which straight-line steps are taken.
+    const double delta(1.E-2);
+    const double epsilon(1.E-1); // cm, allowed upper bound on arch
+    // deviation from straight line
+
+    genfit::M1x3 SA;
+    genfit::M1x7 state7, oldState7;
+    oldState7 = stateOrig;
+
+    int stepSign(sMax < 0 ? -1 : 1);
+
+    double s = 0;  // trajectory length to boundary
+
+    const unsigned maxIt = 300;
+    unsigned it = 0;
+
+    // Initialize the geometry to the current location (set by caller).
+    findNextBoundary(fabs(sMax) - s);
+    double safety = getSafeDistance(); // >= 0
+    double slDist = getStep();
+
+    // this should not happen, but it happens sometimes.
+    // The reason are probably overlaps in the geometry.
+    // Without this "hack" many small steps with size of minStep will be made,
+    // until eventually the maximum number of iterations are exceeded
+    // and the extrapolation fails
+    if (slDist < safety) 
+        slDist = safety;
+    double step = slDist;
+
+    if (debugLvl_ > 0)
+        std::cout << "   safety = " << safety << "; step, slDist = " << step << "\n";
+
+    while (1) {
+        if (++it > maxIt){
+            genfit::Exception exc("GenfitMaterialInterface::findNextBoundary ==> maximum number of iterations exceeded",__LINE__,__FILE__);
+            exc.setFatal();
+            throw exc;
+        }
+
+        // No boundary in sight?
+        if (s + safety > fabs(sMax)) {
+            if (debugLvl_ > 0)
+                std::cout << "   next boundary is further away than sMax \n";
+            return stepSign*(s + safety); //sMax;
+        }
+
+        // Are we at the boundary?
+        if (slDist < delta) {
+            if (debugLvl_ > 0)
+                std::cout << "   very close to the boundary -> return"
+                    << " stepSign*(s + slDist) = "
+                    << stepSign << "*(" << s + slDist << ")\n";
+            return stepSign*(s + slDist);
+        }
+
+        // We have to find whether there's any boundary on our path.
+
+        // Follow curved arch, then see if we may have missed a boundary.
+        // Always propagate complete way from original start to avoid
+        // inconsistent extrapolations.
+        state7 = stateOrig;
+        rep->RKPropagate(state7, nullptr, SA, stepSign*(s + step), varField);
+
+        // Straight line distance² between extrapolation finish and
+        // the end of the previously determined safe segment.
+        double dist2 = (pow(state7[0] - oldState7[0], 2)
+                + pow(state7[1] - oldState7[1], 2)
+                + pow(state7[2] - oldState7[2], 2));
+        // Maximal lateral deviation².
+        double maxDeviation2 = 0.25*(step*step - dist2);
+
+        if (step > safety
+                && maxDeviation2 > epsilon*epsilon) {
+            // Need to take a shorter step to reliably estimate material,
+            // but only if we didn't move by safety.  In order to avoid
+            // issues with roundoff we check 'step > safety' instead of
+            // 'step != safety'.  If we moved by safety, there couldn't have
+            // been a boundary that we missed along the path, but we could
+            // be on the boundary.
+
+            // Take a shorter step, but never shorter than safety.
+            step = std::max(step / 2, safety);
+        } else {
+            getGeoManager()->PushPoint();
+            bool volChanged = initTrack(state7[0], state7[1], state7[2],
+                    stepSign*state7[3], stepSign*state7[4],
+                    stepSign*state7[5]);
+
+            if (volChanged) {
+                if (debugLvl_ > 0)
+                    std::cout << "   volChanged\n";
+                // Move back to start.
+                getGeoManager()->PopPoint();
+
+                // Extrapolation may not take the exact step length we asked
+                // for, so it can happen that a requested step < safety takes
+                // us across the boundary.  This is then the best estimate we
+                // can get of the distance to the boundary with the stepper.
+                if (step <= safety) {
+                    if (debugLvl_ > 0)
+                        std::cout <<
+                            "   step <= safety, return stepSign*(s + step) = "
+                            << stepSign*(s + step) << "\n";
+                    return stepSign*(s + step);
+                }
+
+                // Volume changed during the extrapolation.  Take a shorter
+                // step, but never shorter than safety.
+                step = std::max(step / 2, safety);
+            } else {
+                // we're in the new place, the step was safe, advance
+                s += step;
+
+                oldState7 = state7;
+                getGeoManager()->PopDummy();  // Pop stack, but stay in place.
+
+                findNextBoundary(fabs(sMax) - s);
+                safety = getSafeDistance();
+                slDist = getStep();
+
+                // this should not happen, but it happens sometimes.
+                // The reason are probably overlaps in the geometry.
+                // Without this "hack" many small steps with size of minStep will be made,
+                // until eventually the maximum number of iterations are exceeded and the extrapolation fails
+                if (slDist < safety)
+                    slDist = safety;
+                step = slDist;
+                if (debugLvl_ > 0){
+                    std::cout << "   safety = " << safety 
+                        << "; step, slDist = " << step << "\n";
+                }
+            }
+        }
+    }
+}
+
+
+/*
+   Reference for elemental mean excitation energies at:
+http://physics.nist.gov/PhysRefData/XrayMassCoef/tab1.html
+
+Code ported from GEANT 3
+*/
+
+const int MeanExcEnergy_NELEMENTS = 93; // 0 = vacuum, 1 = hydrogen, 92 = uranium
+const double MeanExcEnergy_vals[MeanExcEnergy_NELEMENTS] = {
+    1.e15, 19.2, 41.8, 40.0, 63.7, 76.0, 78., 82.0,
+    95.0, 115.0, 137.0, 149.0, 156.0, 166.0, 173.0, 173.0,
+    180.0, 174.0, 188.0, 190.0, 191.0, 216.0, 233.0, 245.0,
+    257.0, 272.0, 286.0, 297.0, 311.0, 322.0, 330.0, 334.0,
+    350.0, 347.0, 348.0, 343.0, 352.0, 363.0, 366.0, 379.0,
+    393.0, 417.0, 424.0, 428.0, 441.0, 449.0, 470.0, 470.0,
+    469.0, 488.0, 488.0, 487.0, 485.0, 491.0, 482.0, 488.0,
+    491.0, 501.0, 523.0, 535.0, 546.0, 560.0, 574.0, 580.0,
+    591.0, 614.0, 628.0, 650.0, 658.0, 674.0, 684.0, 694.0,
+    705.0, 718.0, 727.0, 736.0, 746.0, 757.0, 790.0, 790.0,
+    800.0, 810.0, 823.0, 823.0, 830.0, 825.0, 794.0, 827.0,
+    826.0, 841.0, 847.0, 878.0, 890.0, };
+// Logarithms of the previous table, used to calculate mixtures.
+const double MeanExcEnergy_logs[MeanExcEnergy_NELEMENTS] = {
+    34.5388, 2.95491, 3.7329, 3.68888, 4.15418, 4.33073, 4.35671, 4.40672, 
+    4.55388, 4.74493, 4.91998, 5.00395, 5.04986, 5.11199, 5.15329, 5.15329, 
+    5.19296, 5.15906, 5.23644, 5.24702, 5.25227, 5.37528, 5.45104, 5.50126, 
+    5.54908, 5.6058, 5.65599, 5.69373, 5.73979, 5.77455, 5.79909, 5.81114, 
+    5.85793, 5.84932, 5.8522, 5.83773, 5.86363, 5.8944, 5.90263, 5.93754, 
+    5.97381, 6.03309, 6.04973, 6.05912, 6.08904, 6.10702, 6.15273, 6.15273, 
+    6.1506, 6.19032, 6.19032, 6.18826, 6.18415, 6.19644, 6.17794, 6.19032, 
+    6.19644, 6.21661, 6.25958, 6.28227, 6.30262, 6.32794, 6.35263, 6.36303, 
+    6.38182, 6.41999, 6.44254, 6.47697, 6.4892, 6.51323, 6.52796, 6.54247, 
+    6.5582, 6.57647, 6.58893, 6.60123, 6.61473, 6.62936, 6.67203, 6.67203, 
+    6.68461, 6.69703, 6.71296, 6.71296, 6.72143, 6.71538, 6.67708, 6.7178, 
+    6.71659, 6.73459, 6.7417, 6.77765, 6.79122, };
+
+
+double
+MeanExcEnergy_get(int Z, bool logs = false) {
+    assert(Z >= 0 && Z < MeanExcEnergy_NELEMENTS);
+    if (logs)
+        return MeanExcEnergy_logs[Z];
+    else
+        return MeanExcEnergy_vals[Z];
+}
+
+
+double
+MeanExcEnergy_get(TGeoMaterial* mat) {
+    if (mat->IsMixture()) {
+        // The mean excitation energy is calculated as the geometric mean
+        // of the mEEs of the components, weighted for abundance.
+        double logMEE = 0.;
+        double denom  = 0.;
+        TGeoMixture* mix = (TGeoMixture*)mat;
+        for (int i = 0; i < mix->GetNelements(); ++i) {
+            int index = int(mix->GetZmixt()[i]);
+            double weight = mix->GetWmixt()[i] * mix->GetZmixt()[i] / mix->GetAmixt()[i];
+            logMEE += weight * MeanExcEnergy_get(index, true);
+            denom  += weight;
+        }
+        logMEE /= denom;
+        return exp(logMEE);
+    }
+
+    // not a mixture
+    int index = int(mat->GetZ());
+    return MeanExcEnergy_get(index, false);
+}
+
+double GenfitMaterialInterface::getSafeDistance()
+{
+    return getGeoManager()->GetSafeDistance();
+}
+
+double GenfitMaterialInterface::getStep()
+{
+    return getGeoManager()->GetSafeDistance();
+}
+
+TGeoNode* GenfitMaterialInterface::findNextBoundary(double stepmax,
+        const char* path,bool frombdr)
+{
+    return getGeoManager()->FindNextBoundary(stepmax,path,frombdr);
+}
+
+bool GenfitMaterialInterface::isSameLocation(double posX, double posY,
+        double posZ, bool change)
+{
+    //std::cout<<" MatInt  "<<__LINE__<<" posXYZ*dd4hep::cm "<<posX*dd4hep::cm
+    //<<" posY "<<posY*dd4hep::cm<<" posZ "<<posZ*dd4hep::cm<<std::endl;
+    return getGeoManager()->IsSameLocation(posX,posY,
+            posZ,change);
+}
+
+void GenfitMaterialInterface::setCurrentDirection(double nx, double ny,
+        double nz)
+{
+    return getGeoManager()->SetCurrentDirection(nx, ny, nz);
+
+}
+
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.h b/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.h
new file mode 100644
index 00000000..83da9fc1
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitMaterialInterface.h
@@ -0,0 +1,74 @@
+/////////////////////////////////////////////////////////////////////////
+//  An implementation of genfit AbsMaterialInterface
+//
+//  Author:
+//   Yao ZHANG (zhangyao@ihep.ac.cn)
+//
+//
+/////////////////////////////////////////////////////////////////////////
+
+#ifndef RECGENFITALG_GENFITMATERIALINTERFACE_H
+#define RECGENFITALG_GENFITMATERIALINTERFACE_H
+
+#include "AbsMaterialInterface.h"
+
+class RKTrackRep;
+class TGeoManager;
+class TGeoNode;
+namespace dd4hep{
+    class Detector;
+}
+
+/**
+ * @brief MaterialInterface implementation for use with ROOT's TGeoManager.
+ */
+class GenfitMaterialInterface : public genfit::AbsMaterialInterface{
+    public:
+        GenfitMaterialInterface(const dd4hep::Detector* dd4hepGeo);
+        virtual ~GenfitMaterialInterface(){};
+        static GenfitMaterialInterface* getInstance(
+                const dd4hep::Detector* dd4hepGeo);
+        void destruct();
+
+        //Set Detector pointer of dd4hep
+        void setDetector(dd4hep::Detector*);
+
+        /** @brief Initialize the navigator at given position and with given
+          direction.  Returns true if the volume changed.
+          */
+        bool initTrack(double posX, double posY, double posZ,
+                double dirX, double dirY, double dirZ) override;
+
+        genfit::Material getMaterialParameters() override;
+
+
+        /** @brief Make a step (following the curvature) until step length
+         * sMax or the next boundary is reached.  After making a step to a
+         * boundary, the position has to be beyond the boundary, i.e. the
+         * current material has to be that beyond the boundary.  The actual
+         * step made is returned.
+         */
+        double findNextBoundary(const genfit::RKTrackRep* rep,
+                const genfit::M1x7& state7,
+                double sMax,
+                bool varField = true) override;
+
+        // ClassDef(GenfitMaterialInterface, 1);
+
+    private:
+        static GenfitMaterialInterface* m_instance;
+        TGeoManager* getGeoManager();
+        TGeoManager* m_geoManager;
+        double getSafeDistance();
+        double getStep();
+        TGeoNode* findNextBoundary(double stepmax, const char* path="",
+                bool frombdr=false);
+        bool isSameLocation(double posX, double posY, double posZ,
+                bool change=false);
+        void setCurrentDirection(double nx, double ny, double nz);
+
+};
+
+/** @} */
+
+#endif // GenfitMaterialInterface
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitMsg.cpp b/Reconstruction/RecGenfitAlg/src/GenfitMsg.cpp
new file mode 100644
index 00000000..6799d68e
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitMsg.cpp
@@ -0,0 +1,19 @@
+#include "GenfitMsg.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/IMessageSvc.h"
+
+MsgStream* GenfitMsg::m_log = nullptr;
+
+MsgStream GenfitMsg::get(){
+  if(nullptr == m_log){
+    SmartIF<IMessageSvc> msgSvc(
+        Gaudi::svcLocator()->service<IMessageSvc>("MessageSvc"));
+    m_log = new MsgStream(msgSvc, "GenfitMsg");
+    (*m_log) << MSG::DEBUG << "initialize GenfitMsg" << endmsg;
+  }
+  return (*m_log);
+}
+
+GenfitMsg::~GenfitMsg(){
+  delete m_log;
+}
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitMsg.h b/Reconstruction/RecGenfitAlg/src/GenfitMsg.h
new file mode 100644
index 00000000..43808b42
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitMsg.h
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////
+///
+/// This is a class for genfit interfaces classes to access Gaudi log
+///   system
+///
+/// Authors:
+///   Yao ZHANG(zhangyao@ihep.ac.cn)
+///
+//////////////////////////////////////////////////////////////////////
+#ifndef RECGENFITALG_GENFITMSG_H
+#define RECGENFITALG_GENFITMSG_H
+
+#include "GaudiKernel/MsgStream.h"
+
+class GenfitMsg {
+  public:
+    static MsgStream get();
+  private:
+    GenfitMsg(){};
+    virtual ~GenfitMsg();
+    static MsgStream* m_log;
+
+};
+
+#endif
+
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitTrack.cpp b/Reconstruction/RecGenfitAlg/src/GenfitTrack.cpp
new file mode 100644
index 00000000..a73f6108
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitTrack.cpp
@@ -0,0 +1,733 @@
+#include "GenfitTrack.h"
+#include "GenfitMsg.h"
+#include "GenfitField.h"
+
+//CEPCSW
+#include "DataHelper/HelixClass.h"
+
+//Externals
+#include "DD4hep/DD4hepUnits.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/ReconstructedParticle.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/Vector3d.h"
+#include "DetSegmentation/GridDriftChamber.h"
+
+//genfit
+#include "Track.h"
+#include "MeasuredStateOnPlane.h"
+#include "RKTrackRep.h"
+#include "TrackPoint.h"
+#include "StateOnPlane.h"
+#include "KalmanFitterInfo.h"
+#include "KalmanFittedStateOnPlane.h"
+#include "AbsTrackRep.h"
+#include "FitStatus.h"
+#include "SpacepointMeasurement.h"
+#include "WireMeasurementNew.h"
+
+//ROOT
+#include "TRandom.h"
+#include "TVector3.h"
+#include "TLorentzVector.h"
+#include "TMatrixDSym.h"
+
+const int GenfitTrack::s_PDG[2][5]
+={{-11,-13,211,321,2212},{11,13,-211,-321,-2212}};
+
+    bool
+sortDCHit(edm4hep::SimTrackerHit hit1,edm4hep::SimTrackerHit hit2)
+{
+    return (hit1.getTime()<hit2.getTime());
+}
+
+    GenfitTrack::GenfitTrack(const GenfitField* genfitField, const dd4hep::DDSegmentation::GridDriftChamber* seg, const char* name)
+:m_genfitField(genfitField),m_gridDriftChamber(seg),m_name(name), m_track(nullptr) ,m_reps() ,m_debug(0)
+{
+
+}
+
+GenfitTrack::~GenfitTrack()
+{
+    ///Note: track reps and points will be deleted in the destructor of track
+    ///implemented in genfit::Track::Clear()
+    delete m_track;
+}
+
+/// create a Genfit track from track state, without trackRep
+/// Initialize track with seed states
+/// NO unit conversion here
+bool GenfitTrack::createGenfitTrack(int pdgType,int charge,
+        TLorentzVector posInit, TVector3 momInit, TMatrixDSym covMInit)
+{
+    TVectorD seedState(6);
+    TMatrixDSym seedCov(6);
+
+    //for(int i = 0; i < 6; ++i) {
+    //  for(int j = 0; j < 6; ++j) {
+    //    seedCov(i,j)=covMInit(i,j);
+    //  }
+    //}
+    //yzhang FIXME
+    //seed position
+    for(int i = 0; i < 3; ++i) {
+        seedState(i)=posInit[i];
+        //yzhang TODO from covMInit to seedCov
+        double resolution = 0.1;//*dd4hep::mm/dd4hep::cm;
+        seedCov(i,i)=resolution*resolution;
+        if(i==2) seedCov(i,i)=0.5*0.5;
+    }
+    //seed momentum
+    for(int i = 3; i < 6; ++i){
+        //seedState(i)=momInit[i-3]*(dd4hep::GeV);
+        seedState(i)=momInit[i-3];
+        //yzhang TODO from covMInit to seedCov
+        seedCov(i,i)=0.01;//pow(resolution / sqrt(3),2);
+    }
+
+    if(nullptr==m_track) m_track=new genfit::Track();
+    m_track->setStateSeed(seedState);
+    m_track->setCovSeed(seedCov);
+
+    /// new a track representation and add to the track
+    int chargeId=0;
+    charge<0 ? chargeId=0 : chargeId=1;
+
+    GenfitMsg::get()<<MSG::DEBUG<<m_name<<" CreateGenfitTrack seed pos("
+        <<seedState[0]<<" " <<seedState[1]<<" " <<seedState[2]<<")cm ("
+        <<seedState[3]<<" " <<seedState[4]<<" " <<seedState[5]<<")GeV pdg "
+        <<s_PDG[chargeId][pdgType]<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<"seedCov "<<endmsg;
+
+    addTrackRep(s_PDG[chargeId][pdgType]);
+
+    if(m_debug>0) seedCov.Print();
+    return true;
+}
+
+///Create a Genfit track with MCParticle, unit conversion here
+bool GenfitTrack::createGenfitTrackFromMCParticle(int pidType,
+        const edm4hep::MCParticle& mcParticle, double eventStartTime)
+{
+    ///get track parameters from McParticle
+    edm4hep::Vector3d mcPocaPos = mcParticle.getVertex();//mm
+    edm4hep::Vector3f mcPocaMom = mcParticle.getMomentum();//GeV
+    GenfitMsg::get()<<MSG::DEBUG<<"seedPos poca "<< mcPocaPos.x
+        <<" "<<mcPocaPos.y<<" "<<mcPocaPos.z<<" mm "<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<"seedMom poca "<< mcPocaMom.x
+        <<" "<<mcPocaMom.y<<" "<<mcPocaMom.z<<" GeV "<<endmsg;
+
+    ///Pivot to first layer to avoid correction of beam pipe
+    edm4hep::Vector3d firstLayerPos(1e9,1e9,1e9);
+    edm4hep::Vector3f firstLayerMom(1e9,1e9,1e9);
+    pivotToFirstLayer(mcPocaPos,mcPocaMom,firstLayerPos,firstLayerMom);
+
+    //TODO convert unit
+    ///Get seed position and momentum
+    TLorentzVector seedPos(firstLayerPos.x,firstLayerPos.y,firstLayerPos.z,
+            eventStartTime);
+    TVector3 seedMom(firstLayerMom.x,firstLayerMom.y,firstLayerMom.z);
+    GenfitMsg::get()<<MSG::DEBUG<<"seedPos "<< firstLayerPos.x
+        <<" "<<firstLayerPos.y<<" "<<firstLayerPos.z<<endmsg;
+    GenfitMsg::get()<<MSG::DEBUG<<"seedMom "<< firstLayerMom.x
+        <<" "<<firstLayerMom.y<<" "<<firstLayerMom.z<<endmsg;
+
+    ///Get error matrix of seed track
+    TMatrixDSym covM(5);//FIXME, TODO
+
+    ///Create a genfit track with seed
+    GenfitMsg::get()<<MSG::DEBUG<<"createGenfitTrack " ;
+    if(!GenfitTrack::createGenfitTrack(pidType,mcParticle.getCharge(),
+                seedPos,seedMom,covM)){
+        GenfitMsg::get()<<MSG::ERROR<<"GenfitTrack"
+            <<" Error in createGenfitTrack" <<endmsg;
+        return false;
+    }else{
+        GenfitMsg::get()<<MSG::DEBUG<<"GenfitTrack "
+            <<"createGenfitTrackFromMCParticle track created" <<endmsg;
+    }
+    return true;
+}//end of createGenfitTrackFromMCParticle
+
+///Create a Genfit track with MCParticle, unit conversion here
+bool GenfitTrack::createGenfitTrackFromEDM4HepTrack(int pidType,
+        const edm4hep::Track& track, double eventStartTime)
+{
+    std::cout<<__FILE__<<"   "<<__LINE__<<" bz kilogauss "<<m_genfitField->getBz({0.,0.,0.})/dd4hep::kilogauss<<std::endl;
+    std::cout<<__FILE__<<"   "<<__LINE__<<" bz tesla "<<m_genfitField->getBz({0.,0.,0.})/dd4hep::tesla<<std::endl;
+    std::cout<<__FILE__<<"   "<<__LINE__<<" bz "<<m_genfitField->getBz({0.,0.,0.})<< dd4hep::kilogauss <<" "<<dd4hep::tesla<<std::endl;
+    //TODO
+    //pivotToFirstLayer(mcPocaPos,mcPocaMom,firstLayerPos,firstLayerMom);
+    //Get track parameters
+    edm4hep::TrackState trackStat=track.getTrackStates(0);//FIXME?
+    HelixClass helixClass;
+    helixClass.Initialize_Canonical(trackStat.phi,trackStat.D0,
+            trackStat.Z0,trackStat.omega,trackStat.tanLambda,
+            m_genfitField->getBz({0.,0.,0.})*dd4hep::kilogauss/dd4hep::tesla);
+    TLorentzVector posInit(helixClass.getReferencePoint()[0],
+            helixClass.getReferencePoint()[1],
+            helixClass.getReferencePoint()[2],eventStartTime);
+    posInit.SetX(posInit.X()*dd4hep::mm);
+    posInit.SetY(posInit.Y()*dd4hep::mm);
+    posInit.SetZ(posInit.Z()*dd4hep::mm);
+    TVector3 momInit(helixClass.getMomentum()[0],
+            helixClass.getMomentum()[1],helixClass.getMomentum()[2]);
+    momInit.SetX(momInit.x()*dd4hep::GeV);
+    momInit.SetY(momInit.y()*dd4hep::GeV);
+    momInit.SetZ(momInit.z()*dd4hep::GeV);
+    TMatrixDSym covMInit;
+    if(!createGenfitTrack(pidType,
+                int(trackStat.omega/fabs(trackStat.omega)),//charge,FIXME?
+                posInit,momInit,covMInit)){
+        return false;
+    }
+    return true;
+}
+
+/// Add a 3d SpacepointMeasurement with MC truth position smeared by sigma
+bool GenfitTrack::addSpacePointMeasurementOnTrack(const TVectorD& pos,
+        bool smear, double resolution, int detID, int hitID)
+{
+
+    /// Convert from CEPCSW unit to genfit unit, cm
+    TVectorD pos_t(3);
+    pos_t(0) = pos(0)*dd4hep::mm;
+    pos_t(1) = pos(1)*dd4hep::mm;
+    pos_t(2) = pos(2)*dd4hep::mm;
+    /// smear hit position with same weight
+    TVectorD pos_smeared(pos_t);
+    if (smear) {
+        for (int ii=0;ii<3;ii++){
+            pos_smeared[ii] += gRandom->Gaus(0, resolution/TMath::Sqrt(3.));
+        }
+    }
+
+    /// New a SpacepointMeasurement
+    TMatrixDSym hitCov(3);
+    hitCov(0,0) = resolution*resolution;
+    hitCov(1,1) = resolution*resolution;
+    hitCov(2,2) = resolution*resolution;
+
+    GenfitMsg::get()<< MSG::DEBUG<<m_name<<" addSpacePointMeasurementOnTrack "
+        <<hitID<<" " <<pos_t[0]<<" "<<pos_t[1]<<" "<<pos_t[2]<<"cm smeared "
+        <<pos_smeared[0]<<" "<<pos_smeared[1]<<" "<<pos_smeared[2]
+        <<" res "<<resolution<<" cm"<<endmsg;
+
+    genfit::SpacepointMeasurement* sMeas =
+        new genfit::SpacepointMeasurement(pos_smeared,hitCov,detID,hitID,nullptr);
+    genfit::TrackPoint* trackPoint = new genfit::TrackPoint(sMeas,m_track);
+    m_track->insertPoint(trackPoint);
+
+    return true;
+}
+
+
+/// Add a WireMeasurement, no Unit conversion here
+void GenfitTrack::addWireMeasurement(double driftDistance,
+        double driftDistanceError, const TVector3& endPoint1,
+        const TVector3& endPoint2, int lrAmbig, int detID, int hitID)
+{
+    try{
+        /// New a WireMeasurement
+        genfit::WireMeasurementNew* wireMeas = new genfit::WireMeasurementNew(
+                driftDistance, driftDistanceError, endPoint1, endPoint2, detID,
+                hitID, nullptr);
+        wireMeas->setMaxDistance(0.5);//0.5 cm FIXME
+        wireMeas->setLeftRightResolution(lrAmbig);
+
+        GenfitMsg::get()<<MSG::DEBUG<<m_name<<" Add wire measurement(cm) "<<hitID
+            <<" ep1("<<endPoint1[0]<<" "<<endPoint1[1]<<" "<<endPoint1[2]
+            <<") ep2("<<endPoint2[0]<<" "<<endPoint2[1]<<" "<<endPoint2[2]
+            <<") drift "<<driftDistance<<" driftErr "<<driftDistanceError
+            <<" lr "<<lrAmbig<<" detId "<<detID << " hitId "<< hitID
+            <<endmsg;
+
+        ///New a TrackPoint,create connection between meas. and trackPoint
+        genfit::TrackPoint* trackPoint=new genfit::TrackPoint(wireMeas,m_track);
+        wireMeas->setTrackPoint(trackPoint);
+
+        m_track->insertPoint(trackPoint);
+
+    }catch(genfit::Exception e){
+        GenfitMsg::get()<<MSG::DEBUG<<m_name
+            <<"Add wire measurement exception"<<endmsg;
+        e.what();
+    }
+}//end of addWireMeasurementOnTrack
+
+//Add wire measurement on wire, unit conversion here
+bool GenfitTrack::addWireMeasurementOnTrack(edm4hep::Track& track,double sigma)
+{
+    for(int iHit=0;iHit<track.trackerHits_size();iHit++){
+        edm4hep::ConstTrackerHit hit=track.getTrackerHits(iHit);
+
+        double driftVelocity=40;//FIXME, TODO, um/ns
+        double driftDistance=hit.getTime()*driftVelocity*dd4hep::um;
+        TVector3 endPointStart(0,0,0);
+        TVector3 endPointEnd(0,0,0);
+        m_gridDriftChamber->cellposition(hit.getCellID(),endPointStart,
+                endPointEnd);
+        int lrAmbig=0;
+        std::cout<<__FILE__<<" time  "<<hit.getTime()<<" driftVelocity "
+            <<driftVelocity<<std::endl;
+        std::cout<<__FILE__<<" wire pos " <<endPointStart.X()<<" "
+            <<endPointStart.Y()<<" " <<endPointStart.Z()<<" "
+            <<endPointEnd.X()<<" " <<endPointEnd.Y()<<" "
+            <<endPointEnd.Z()<<" " <<std::endl;
+        endPointStart.SetX(endPointStart.x()*dd4hep::cm);
+        endPointStart.SetY(endPointStart.y()*dd4hep::cm);
+        endPointStart.SetZ(endPointStart.z()*dd4hep::cm);
+        endPointEnd.SetX(endPointEnd.x()*dd4hep::cm);
+        endPointEnd.SetY(endPointEnd.y()*dd4hep::cm);
+        endPointEnd.SetZ(endPointEnd.z()*dd4hep::cm);
+        addWireMeasurement(driftDistance,sigma*dd4hep::cm,endPointStart,
+                endPointEnd,lrAmbig,hit.getCellID(),iHit);
+    }
+    return true;
+}//end of addWireMeasurementOnTrack of Track
+
+/// Get MOP
+bool GenfitTrack::getMOP(int hitID,
+        genfit::MeasuredStateOnPlane& mop, genfit::AbsTrackRep* trackRep) const
+{
+    if(nullptr == trackRep) trackRep = getRep();
+    try{
+        mop = m_track->getFittedState(hitID,trackRep);
+    }catch(genfit::Exception e){
+        e.what();
+        return false;
+    }
+    return true;
+}
+
+/// New and add a track representation to track
+genfit::RKTrackRep* GenfitTrack::addTrackRep(int pdg)
+{
+    /// create a new track representation
+    genfit::RKTrackRep* rep = new genfit::RKTrackRep(pdg);
+    m_reps.push_back(rep);
+    m_track->addTrackRep(rep);
+    //try{
+    //  genfit::MeasuredStateOnPlane stateInit(rep);
+    //  rep->setPosMomCov(stateInit, pos, mom, covM);
+    //}catch(genfit::Exception e){
+    //  GenfitMsg::get() << MSG::DEBUG<<m_name<<" Exception in set track status"
+    //  <<endmsg     ;
+    //  std::cout<<e.what()<<std::endl;
+    //  return false;
+    //}
+    return rep;
+}
+
+/// Get the position from genfit::Track::getStateSeed
+const TLorentzVector GenfitTrack::getSeedStatePos()const
+{
+    TVectorD seedStat(6);
+    seedStat = m_track->getStateSeed();
+    TVector3 p(seedStat[0],seedStat[1],seedStat[2]);
+    p = p*dd4hep::cm;
+    TLorentzVector pos(p[0],p[1],p[2],9999);//FIXME
+    return pos;
+}
+
+/// Get the momentum from genfit::Track::getStateSeed
+const TVector3 GenfitTrack::getSeedStateMom() const
+{
+    TVectorD seedStat(6); seedStat = m_track->getStateSeed();
+    TVector3 mom(seedStat[3],seedStat[4],seedStat[5]);
+    return mom*dd4hep::GeV;
+}
+
+/// Get the seed states of momentum and position
+void GenfitTrack::getSeedStateMom(TLorentzVector& pos, TVector3& mom) const
+{
+    TVectorD seedStat(6); seedStat = m_track->getStateSeed();
+    mom = TVector3(seedStat[3],seedStat[4],seedStat[5])*dd4hep::GeV;
+    seedStat = m_track->getStateSeed();
+    TVector3 p = TVector3(seedStat[0],seedStat[1],seedStat[2])*dd4hep::cm;
+    pos.SetXYZT(p[0],p[1],p[2],9999);//FIXME time
+}
+
+unsigned int GenfitTrack::getNumPoints() const
+{
+    return m_track->getNumPoints();
+}
+
+/// Test the fit result FIXME
+bool GenfitTrack::fitSuccess(int repID) const
+{
+
+    genfit::FitStatus* fitStatus = m_track->getFitStatus(getRep(repID));
+
+    /// Test fitting converged
+    if (!fitStatus->isFitted()||!fitStatus->isFitConverged()
+            ||fitStatus->isFitConvergedFully()) {
+        GenfitMsg::get() << MSG::DEBUG<<m_name<< "Fitting is failed... isFitted"
+            <<fitStatus->isFitted()<<" , isFitConverged "
+            <<fitStatus->isFitConverged()<<", isFitConvergedFully "
+            <<fitStatus->isFitConvergedFully()<<endmsg;
+        return false;
+    }
+
+    double chi2 = fitStatus->getChi2();
+    double ndf  = fitStatus->getNdf();
+    GenfitMsg::get() << MSG::INFO << "Fit result: chi2 "<<chi2 <<" ndf "<<ndf
+        << " chi2/ndf = " << chi2/ndf<<endmsg;
+
+    /// Test fitting chi2
+    if (chi2<= 0) {
+        GenfitMsg::get() << MSG::DEBUG<<m_name<< "Fit chi2<0 (chi2,ndf) = (" <<
+            chi2 << "," << ndf  << ")"<<endmsg;
+        return false;
+    }
+    return true;
+}
+
+void GenfitTrack::setDebug(int debug)
+{
+    m_debug = debug;
+    for(unsigned int i=0;i<m_reps.size();i++){ m_reps[i]->setDebugLvl(debug); }
+}
+
+void GenfitTrack::printSeed() const
+{
+    TLorentzVector pos = getSeedStatePos();
+    TVector3 mom = getSeedStateMom();
+    print(pos,mom);
+    GenfitMsg::get()<<MSG::DEBUG<<m_name<<" NumPoints "<<getNumPoints()<<endmsg;
+}
+
+void GenfitTrack::printFitted(int repID) const
+{
+    TLorentzVector fittedPos;
+    TVector3 fittedMom;
+    TMatrixDSym cov;
+
+    GenfitMsg::get()<<MSG::DEBUG<<m_name<< "printFitted nHit="
+        <<m_track->getNumPoints()<<endmsg;
+    for(unsigned int iHit=0; iHit<m_track->getNumPoints(); iHit++){
+        if (getPosMomCovMOP((int) iHit, fittedPos, fittedMom, cov, repID)){
+            //print(fittedPos,fittedMom,to_string(iHit).c_str());//TODO
+        }else{
+            GenfitMsg::get()<<MSG::DEBUG<<m_name<<"Hit "<<iHit
+                <<" have no fitter info"<<endmsg;
+        }
+    }
+}
+
+/// Print track information
+void GenfitTrack::print( TLorentzVector pos, TVector3 mom,
+        const char* comment) const
+{
+    TVector3 pglo = pos.Vect();
+    TVector3 mglo = mom;
+
+    // TODO
+    GenfitMsg::get()<<MSG::DEBUG<<m_name<<" "<<comment<<endmsg;
+
+    if(m_debug>1){
+        for(unsigned int i=0;i<m_reps.size();i++){ m_reps[i]->Print(); }
+    }
+    //for(unsigned int i=0; i<m_track->getNumPoints(); i++){
+    //  m_track->getPoint(i)->print();
+    //}
+}
+
+/// Get position, momentum, cov on plane of hitID-th hit
+bool GenfitTrack::getPosMomCovMOP(int hitID, TLorentzVector& pos,
+        TVector3& mom, TMatrixDSym& cov, int repID) const
+{
+    TVector3 p;
+    genfit::MeasuredStateOnPlane mop;
+    if(!getMOP(hitID,mop,getRep(repID))) return false;
+    mop.getPosMomCov(p,mom,cov);
+    pos.SetVect(p*dd4hep::cm);
+    pos.SetT(9999);//FIXME
+    mom = mom*(dd4hep::GeV);
+    //FIXME
+    //TrackingUtils::CovConvertUnit(cov, dd4hep::cm, dd4hep::GeV);
+    return true;
+}
+
+int GenfitTrack::getNumPointsWithFittedInfo(int repID) const
+{
+    int nHitWithFittedInfo = 0;
+    int nHit = m_track->getNumPointsWithMeasurement();
+    for(int i=0; i<nHit; i++){
+        if(nullptr != m_track->getPointWithFitterInfo(i,getRep(repID))){
+            nHitWithFittedInfo++;
+        }
+    }
+    return nHitWithFittedInfo;
+}
+
+int GenfitTrack::getFittedState(TLorentzVector& pos, TVector3& mom,
+        TMatrixDSym& cov, int repID, bool biased) const
+{
+    //check number of hit with fitter info
+    if(getNumPointsWithFittedInfo(repID)<=2) return 1;
+
+    //get track rep
+    genfit::AbsTrackRep* rep = getRep(repID);
+    if(nullptr == rep) return 2;
+
+    //get first or last measured state on plane
+    genfit::MeasuredStateOnPlane mop;
+    try{
+        mop = m_track->getFittedState(biased);
+    }catch(genfit::Exception e){
+        std::cout<<" getNumPointsWithFittedInfo "
+            <<getNumPointsWithFittedInfo(repID)
+            <<" no TrackPoint with fitted info "<<std::endl;
+        GenfitMsg::get()<<MSG::DEBUG<<m_name
+            <<"Exception in getFittedState"<<endmsg;
+        std::cout<<e.what()<<std::endl;
+        return 3;
+    }
+
+    //get state
+    TVector3 p;
+    mop.getPosMomCov(p,mom,cov);
+    pos.SetVect(p*dd4hep::cm);
+    pos.SetT(9999);//FIXME
+    mom = mom*(dd4hep::GeV);
+
+    return 0;//success
+}
+
+// Get point with fitter info
+int GenfitTrack::getDetIDWithFitterInfo(int hitID, int idRaw) const
+{
+    return m_track->getPointWithFitterInfo(hitID)->
+        getRawMeasurement(idRaw)->getDetId();
+}
+
+int GenfitTrack::getPDG(int id) const
+{
+    return m_reps[id]->getPDG();
+}
+
+int GenfitTrack::getPDGCharge(int id) const
+{
+    return m_reps[id]->getPDGCharge();
+}
+
+const genfit::FitStatus*
+GenfitTrack::getFitStatus(int repID) const
+{
+    return m_track->getFitStatus(getRep(repID));
+}
+
+/// Extrapolate track to the cloest point of approach(POCA) to the wire of hit,
+/// return StateOnPlane of this POCA
+/// inputs
+///  pos,mom ... position & momentum at starting point, unit= [mm]&[GeV/c]
+///              (converted to [cm]&[GeV/c] inside this function)
+///  hit ... destination
+/// outputs poca [mm] (converted from [cm] in this function) ,global
+double GenfitTrack::extrapolateToHit( TVector3& poca, TVector3& pocaDir,
+        TVector3& pocaOnWire, double& doca, TVector3 pos, TVector3 mom,
+        TVector3 end0,//one end of the hit wire
+        TVector3 end1,//the orhter end of the hit wire
+        int debug,
+        int repID,
+        bool stopAtBoundary,
+        bool calcJacobianNoise)const
+{
+
+    //genfit::MeasuredStateOnPlane state = getMOP(iPoint); // better?
+    //genfit::MeasuredStateOnPlane state = getMOP(0);      // better?
+    //To do the extrapolation without IHitSelection,above 2 lines are not used.
+    pos = pos*dd4hep::cm;//FIXME
+    mom = mom*dd4hep::GeV;
+
+    //std::cout<<__LINE__<<" extrapolate to Hit pos and mom"<<std::endl;
+    //pos.Print();
+    //mom.Print();
+
+    genfit::AbsTrackRep* rep = new genfit::RKTrackRep(getRep(repID)->getPDG());
+    rep->setDebugLvl(debug);
+    genfit::MeasuredStateOnPlane state(rep);
+    rep->setPosMom(state, pos, mom);
+
+
+    //genfit::MeasuredStateOnPlane state(m_track->getRep(repID));
+    //m_track->getRep(repID)->setPosMom(state, pos, mom);
+
+    //m_track->PrintSeed();
+    double extrapoLen(0);
+    //std::cout<<" wire1 "<<std::endl;
+    //end0.Print();
+    //std::cout<<" wire0 "<<std::endl;
+    //end1.Print();
+    //std::cout<<" state "<<std::endl;
+    //state.Print();
+
+
+    // forth
+    try {
+        //genfit::RKTrackRep* rkRep =
+        //  dynamic_cast<genfit::RKTrackRep*> (m_track->getRep(repID));
+        //extrapoLen = rkRep->extrapolateToLine(state, end0, end1, poca,
+        //    pocaDir, pocaOnWire, stopAtBoundary, calcJacobianNoise);
+        extrapoLen = rep->extrapolateToLine(state, end0, end1, poca,
+                pocaDir, pocaOnWire, stopAtBoundary, calcJacobianNoise);
+    } catch (genfit::Exception& e) {
+        GenfitMsg::get() << MSG::ERROR
+            <<"Exception in GenfigFitter::ExtrapolateToHit"<<e.what()<<endmsg;
+        return extrapoLen;
+    }
+
+    //poca = poca*(dd4hep::cm);
+    //pocaOnWire = pocaOnWire*(dd4hep::cm);
+    pocaOnWire = pocaOnWire;
+    doca = (pocaOnWire-poca).Mag();
+    //TODO: debug pocaOnWire
+    GenfitMsg::get() << MSG::DEBUG << " poca "<<poca.x()<<","<<poca.y()
+        <<" "<<poca.z()<<" doca "<<doca<<endmsg;
+    GenfitMsg::get() << MSG::DEBUG << " pocaOnWire "<<pocaOnWire.x()
+        <<","<<pocaOnWire.y()<<" "<<pocaOnWire.z()<<" doca "<<doca<<endmsg;
+
+    return extrapoLen*(dd4hep::cm);
+}//end of ExtrapolateToHit
+
+
+///Add space point measurement to track
+int GenfitTrack::addSpacePointMeasurementOnTrack(
+        const edm4hep::MCParticle& mcParticle,
+        const edm4hep::SimTrackerHitCollection*& simDCHitCol,
+        bool smear, double resolution) {
+    //Sort sim DC hit by time
+    std::vector<edm4hep::SimTrackerHit> sortedSimDCHitCol;
+    for(auto simDCHit: *simDCHitCol) sortedSimDCHitCol.push_back(simDCHit);
+    std::sort(sortedSimDCHitCol.begin(),sortedSimDCHitCol.end(),sortDCHit);
+
+    int hitID=0;
+    for(auto simDCHit: sortedSimDCHitCol){
+        int rand=gRandom->Integer(sortedSimDCHitCol.size());
+        if(rand>200){ continue; }
+        edm4hep::Vector3d pos=simDCHit.getPosition();
+        TVectorD p(3);
+        p[0]=pos.x*dd4hep::mm;
+        p[1]=pos.y*dd4hep::mm;
+        p[2]=pos.z*dd4hep::mm;
+        unsigned long long detID = simDCHit.getCellID();
+        if(addSpacePointMeasurementOnTrack(p,smear,resolution,detID,hitID)){
+            hitID++;
+        }else{
+            GenfitMsg::get()<<MSG::ERROR<<"addSpacePointMeasurementOnTrack "
+                <<detID<<" faieled" <<endmsg;
+        }
+    }
+    GenfitMsg::get()<<MSG::DEBUG<<"GenfitTrack nHitAdded "<<hitID<<endmsg;
+    return hitID;
+}
+
+bool GenfitTrack::storeTrack(edm4hep::ReconstructedParticle& recParticle,
+        int pidType, int ndfCut, double chi2Cut)
+{
+
+    /// Get fit status
+    const genfit::FitStatus* fitState = m_track->getFitStatus();
+    double chi2 = fitState->getChi2();
+    double ndf = fitState->getNdf();
+    double charge = fitState->getCharge();
+    int isFitted = fitState->isFitted();
+    int isConverged = fitState->isFitConverged();
+    int isConvergedFully = fitState->isFitConvergedFully();
+    TMatrixDSym fittedCov;
+    TLorentzVector fittedPos;
+    TVector3 fittedMom;
+    int fittedState=getFittedState(fittedPos,fittedMom,fittedCov);
+    GenfitMsg::get()<<MSG::DEBUG<<"fit result: get status OK? pidType "
+        <<pidType<<" fittedState==0 " <<(0==fittedState)<<" isFitted "<<isFitted
+        <<" isConverged "<<isConverged<<" ndf "<<ndf<<endmsg;
+    if((0!=fittedState) || (!isFitted) || !isConvergedFully || (ndf<ndfCut)){
+        GenfitMsg::get()<<MSG::DEBUG<<" fitting failed"<<endmsg;
+    }else{
+        GenfitMsg::get()<<MSG::DEBUG<<"fit result: Pos("<<
+            fittedPos.X()<<" "<<
+            fittedPos.Y()<<" "<<
+            fittedPos.Z()<<") mom("<<
+            fittedMom.X()<<" "<<
+            fittedMom.Y()<<" "<<
+            fittedMom.Z()<<") p_tot "<<
+            fittedMom.Mag()<<" pt "<<
+            fittedMom.Perp()<<
+            " chi2 "<<chi2<<
+            " ndf "<<ndf
+            <<endmsg;
+    }
+    float pos[3]={fittedPos.X(),fittedPos.Y(),fittedPos.Z()};
+    float mom[3]={fittedMom.X(),fittedMom.Y(),fittedMom.Z()};
+    HelixClass helix;
+    helix.Initialize_VP(pos,mom,charge,m_genfitField->getBz(fittedPos.Vect()));
+
+
+    /////track status at POCA to origin
+    //TVector3 origin(pivot);
+    //TVector3 pocaToOrigin_pos(1e9*dd4hep::cm,1e9*dd4hep::cm,1e9*dd4hep::cm);
+    //TVector3 pocaToOrigin_mom(1e9*dd4hep::GeV,1e9*dd4hep::GeV,1e9*dd4hep::GeV);
+
+    //if(ExtrapolateToPoint(pocaToOrigin_pos,pocaToOrigin_mom,
+    //            m_track,origin) > 1e6*dd4hep::cm){
+    //    log<<"extrapolate to origin failed";
+    //    return false;
+    //}
+
+
+    //new TrackState
+    edm4hep::TrackState* trackState = new edm4hep::TrackState();
+    trackState->location=0;//edm4hep::AtIP;
+    trackState->D0=helix.getD0();
+    trackState->phi=helix.getPhi0();
+    trackState->omega=helix.getOmega();
+    trackState->Z0=helix.getZ0();
+    trackState->tanLambda=helix.getTanLambda();
+    trackState->referencePoint=helix.getReferencePoint();
+
+    //    std::array<float,15> covMatrix;
+    //    int k=0;
+    //    for(int i=0;i<5;i++){
+    //        for(int j=0;j<5;j++){
+    //            if(i<=j) covMatrix[k]=;//FIXME
+    //        }
+    //    }
+    //    trackState.covMatrix=
+
+    //new Track
+    edm4hep::Track* track = new edm4hep::Track();
+    //track->setType();
+    track->setChi2(fitState->getChi2());
+    track->setNdf(fitState->getNdf());
+    //track->setDEdx();
+    //track->setRadiusOfInnermostHit();//FIXME
+    //track->addToTrackerHits();
+
+    //new ReconstructedParticle
+    //recParticle->setType();
+    //dcRecParticle->setEnergy();
+
+    edm4hep::Vector3f momVec3(helix.getMomentum()[0],
+            helix.getMomentum()[1],helix.getMomentum()[2]);
+    recParticle.setMomentum(momVec3);
+    //recParticle->setReferencePoint(referencePoint);
+    recParticle.setCharge(helix.getCharge());
+    //    recParticle->setMass();
+    //    recParticle->setCovMatrix();
+    //    rcRecParticle->setStartVertex();
+    //recParticle->addToTracks(track);
+
+    return true;
+}
+
+void GenfitTrack::pivotToFirstLayer(edm4hep::Vector3d& pos,
+        edm4hep::Vector3f& mom, edm4hep::Vector3d& firstPos,
+        edm4hep::Vector3f& firstMom)
+{
+    //FIXME, TODO
+    firstPos=pos;
+    firstMom=mom;
+}
+
diff --git a/Reconstruction/RecGenfitAlg/src/GenfitTrack.h b/Reconstruction/RecGenfitAlg/src/GenfitTrack.h
new file mode 100644
index 00000000..6e2823e4
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/GenfitTrack.h
@@ -0,0 +1,199 @@
+//////////////////////////////////////////////////////////////////
+///
+/// This is an interface of to call genfit
+/// A genfit track can be created, fitted and extrapolated
+/// Track with only track representation(s)
+///
+/// In this file, including:
+///   a genfit track class
+///
+///   Units are following DD4hepUnits
+///
+/// Authors:
+///   Zhang Yao (zhangyao@ihep.ac.cn)
+///   Y.Fujii (yfujii@ihep.ac.cn)
+///   Yohei Nakatsugawa (yohei@ihep.ac.cn)
+///
+//////////////////////////////////////////////////////////////////
+
+#ifndef RECGENFITALG_GENFITTRACK_H
+#define RECGENFITALG_GENFITTRACK_H
+
+#include "GenfitFitter.h"
+
+//ROOT
+#include "TVectorD.h"
+#include "TMatrixDSym.h"
+
+//STL
+#include <vector>
+
+class TLorentzVector;
+
+namespace genfit{
+    class Track;
+    class FitStatus;
+    class AbsTrackRep;
+    class RKTrackRep;
+    class KalmanFittedStateOnPlane;
+}
+namespace edm4hep{
+    class MCParticle;
+    class SimTrackerHitCollection;
+    class ReconstructedParticle;
+    class Track;
+    class Vector3d;
+    class Vector3f;
+}
+namespace dd4hep {
+    namespace DDSegmentation{
+        class GridDriftChamber;
+    }
+}
+
+class GenfitTrack {
+    friend int GenfitFitter::processTrack(
+            GenfitTrack* track, bool resort=false);
+
+    friend int GenfitFitter::processTrackWithRep(
+            GenfitTrack* track, int repID=0, bool resort=false);
+
+    friend double GenfitFitter::extrapolateToHit(TVector3& poca,
+            TVector3& pocaDir,
+            TVector3& pocaOnWire, double& doca, const GenfitTrack* track,
+            TVector3 pos, TVector3 mom, TVector3 end0, TVector3 end1, int debug,
+            int repID=0, bool stopAtBoundary=false, bool calcJacobianNoise=false);
+
+    friend double GenfitFitter::extrapolateToCylinder(TVector3& pos,
+            TVector3& mom,
+            GenfitTrack* track, double radius, const TVector3 linePoint,
+            const TVector3 lineDirection, int hitID =0, int repID=0,
+            bool stopAtBoundary=false, bool calcJacobianNoise=false);
+
+    friend double GenfitFitter::extrapolateToPoint(TVector3& pos, TVector3& mom,
+            const GenfitTrack* genfitTrack, const TVector3& point, int repID=0,
+            bool stopAtBoundary = false, bool calcJacobianNoise = false) const;
+
+    public:
+    GenfitTrack(const GenfitField* field,
+            const dd4hep::DDSegmentation::GridDriftChamber* seg,
+            const char* name="GenfitTrack");
+    virtual ~GenfitTrack();
+
+    /// Add a Genfit track
+    virtual bool createGenfitTrack(int pdgType,int charge,TLorentzVector pos, TVector3 mom,
+            TMatrixDSym covM);
+    //virtual bool createGenfitTrack(TLorentzVector posInit,TVector3 momInit,
+            //TMatrixDSym covMInit);
+
+    ///Create genfit track from MCParticle
+    bool createGenfitTrackFromMCParticle(int pidTyep,const edm4hep::MCParticle&
+            mcParticle, double eventStartTime=0.);
+    bool createGenfitTrackFromEDM4HepTrack(int pidType,const edm4hep::Track& track,
+            double eventStartTime);
+
+    //  /// Prepare a hit list, return number of hits on track
+    //  int PrepareHits();//TODO
+
+    /// Add a space point measurement, return number of hits on track
+    virtual bool addSpacePointMeasurementOnTrack(const TVectorD&, bool, double,
+            int detID=-1, int hitID=-1);
+
+    /// Add a WireMeasurement with MC truth position smeared by sigma
+    virtual void addWireMeasurement(double driftDistance,
+            double driftDistanceError, const TVector3& endPoint1,
+            const TVector3& endPoint2, int lrAmbig, int detID, int hitID);
+
+    /// Add a WireMeasurement with DC digi
+    virtual bool addWireMeasurementOnTrack(edm4hep::Track& track, double sigma);
+
+    ///Add space point from truth to track
+    int addSpacePointMeasurementOnTrack(const edm4hep::MCParticle& mcParticle,
+            const edm4hep::SimTrackerHitCollection*& simDCHitCol,bool smear=true,
+            double resolution=0.01);
+
+    ///Store track to ReconstructedParticle
+    bool storeTrack(edm4hep::ReconstructedParticle& dcRecParticle,int pidType,
+            int ndfCut, double chi2Cut);
+
+    ///A tool to convert track to the first layer of DC
+    void pivotToFirstLayer(edm4hep::Vector3d& pos,edm4hep::Vector3f& mom,
+            edm4hep::Vector3d& firstPos, edm4hep::Vector3f& firstMom);
+
+    /// Copy a track to event
+    //void CopyATrack()const;
+
+    ///Extrapolate to Hit
+    double extrapolateToHit( TVector3& poca, TVector3& pocaDir,
+            TVector3& pocaOnWire, double& doca, TVector3 pos, TVector3 mom,
+            TVector3 end0,//one end of the hit wire
+            TVector3 end1,//the orhter end of the hit wire
+            int debug,
+            int repID,
+            bool stopAtBoundary,
+            bool calcJacobianNoise) const;
+
+    bool getPosMomCovMOP(int hitID, TLorentzVector& pos, TVector3& mom,
+            TMatrixDSym& cov, int repID=0) const;
+
+    /// get the seed position and momentum from track
+    const TLorentzVector getSeedStatePos() const;
+    const TVector3 getSeedStateMom() const;
+    void getSeedStateMom(TLorentzVector& pos, TVector3& mom) const;
+    unsigned int getNumPoints() const;
+
+    /// get the fitted track status
+    const genfit::FitStatus* getFitStatus(int repID=0) const;
+    int getFittedState(TLorentzVector& pos, TVector3& mom, TMatrixDSym& cov,
+            int repID=0, bool biased=true) const;
+    int getNumPointsWithFittedInfo(int repID=0) const;
+    bool getFirstPointWithFittedInfo(int repID=0) const;
+    bool fitSuccess(int repID) const;
+
+    /// get the wire infomation
+    int getDetIDWithFitterInfo(int hitID, int idRaw=0) const;
+
+    int getPDG(int id=0) const;
+    int getPDGCharge(int id=0) const;
+
+    /// print genfit track
+    void printSeed() const;//print seed
+    void printFitted(int repID=0) const;//print seed
+    void print(TLorentzVector pos, TVector3 mom, const char* comment="") const;
+
+    /// set and get debug level
+    void setDebug(int debug);
+    int getDebug(void) const { return m_debug;}
+
+    /// get name of this object
+    const char* getName() const {return m_name;}
+    genfit::Track* getTrack() const{return m_track;}
+
+    /// Add a track representation
+    genfit::RKTrackRep* addTrackRep(int pdg);
+
+    protected:
+    //genfit::Track* getTrack() {return m_track;}
+
+    private:
+
+    const char* m_name;
+
+    ///Note! private functions are using genfit unit, cm and MeV
+
+    genfit::AbsTrackRep* getRep(int id=0) const {return m_reps[id];}
+    bool getMOP(int hitID, genfit::MeasuredStateOnPlane& mop,
+            genfit::AbsTrackRep* trackRep=nullptr) const;
+
+    genfit::Track* m_track;/// track
+    std::vector<genfit::AbsTrackRep*> m_reps;/// track repesentations
+    int m_debug;/// debug level
+
+    const GenfitField* m_genfitField;//pointer to genfit field
+    const dd4hep::DDSegmentation::GridDriftChamber* m_gridDriftChamber;
+
+    static const int s_PDG[2][5];
+
+};
+
+#endif
diff --git a/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.cpp b/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.cpp
new file mode 100644
index 00000000..99d7d3a5
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.cpp
@@ -0,0 +1,416 @@
+#include "RecGenfitAlgDC.h"
+#include "GenfitTrack.h"
+#include "GenfitFitter.h"
+#include "GenfitField.h"
+
+//genfit
+#include "EventDisplay.h"
+
+//cepcsw
+#include "DetInterface/IGeomSvc.h"
+#include "DataHelper/HelixClass.h"
+#include "DetSegmentation/GridDriftChamber.h"
+
+//externals
+#include "edm4hep/EventHeaderCollection.h"
+#include "edm4hep/MCParticle.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/ReconstructedParticle.h"
+#include "edm4hep/ReconstructedParticleCollection.h"
+#include "edm4hep/Track.h"
+#include "edm4hep/TrackCollection.h"
+#include "DD4hep/DD4hepUnits.h"
+#include "DD4hep/Detector.h"
+#include "UTIL/BitField64.h"
+#include "DDSegmentation/Segmentation.h"
+#include "TRandom.h"
+#include "TLorentzVector.h"
+
+//stl
+#include "time.h"
+
+
+DECLARE_COMPONENT( RecGenfitAlgDC )
+
+///////////////////////////////////////////////////////////////////////////
+
+RecGenfitAlgDC::RecGenfitAlgDC(const std::string& name, ISvcLocator* pSvcLocator) :
+    GaudiAlgorithm(name, pSvcLocator),m_nPDG(5),m_dd4hep(nullptr),m_gridDriftChamber(nullptr),m_decoder(nullptr)
+{
+    declareProperty("inputType", m_inputType=0);//0:MC particle and hits
+    declareProperty("debug", m_debug=0);
+    //DAF,DAFRef,KalmanFitter,KalmanFitterRefTrack
+    declareProperty("fitterType",m_fitterType="DAFRef");
+    declareProperty("correctBremsstrahlung", m_correctBremsstrahlung=false);
+    declareProperty("noMaterialEffects", m_noMaterialEffects=false);
+    declareProperty("maxIteration", m_maxIteration=20);
+    declareProperty("resortHits", m_resortHits=true);
+    declareProperty("ndfCut", m_ndfCut=1);
+    declareProperty("chi2Cut", m_chi2Cut=1000);
+    declareProperty("bStart", m_bStart=100);
+    declareProperty("bFinal", m_bFinal=0.01);
+    //mdc corner cuts, negtive for no cut
+    declareProperty("dcCornerCuts", m_dcCornerCuts=-999);
+    //-1,chargedGeantino;0,1,2,3,4:e,mu,pi,K,proton
+    declareProperty("debugPid", m_debugPid=-99);
+    declareProperty("useTruthSeed", m_useTruthSeed=false);
+    declareProperty("useRecLRAmbig", m_useRecLRAmbig=true);
+    declareProperty("genfitHistRootName", m_genfitHistRootName="");
+    declareProperty("useTruthHit", m_useTruthHit=false);
+    declareProperty("showDisplay", m_showDisplay=false);
+    declareProperty("initCovResPos", m_initCovResPos=1);
+    declareProperty("initCovResMom", m_initCovResMom=0.1);
+
+    //declareProperty("EventHeaderCol", _headerCol);
+    declareProperty("MCParticle", m_mcParticleCol,
+            "Handle of the input MCParticle collection");
+    declareProperty("DriftChamberHitsCollection", m_simDCHitCol,
+            "Handle of the input SimHit collection");
+    declareProperty("DigiDCHitCollection", m_digiDCHitsCol,
+            "Handle of digi DCHit collection");
+    declareProperty("DCTrackCollection", m_dcTrackCol,
+            "Handle of DC track collection");
+    //declareProperty("DCHitAssociationCollection", _dcHitAssociationCol,
+    //    "Handle of association collection");
+    declareProperty("DCRecParticleCollection", m_dcRecParticleCol,
+            "Handle of drift chamber reconstructed particle collection");
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode RecGenfitAlgDC::initialize()
+{
+    MsgStream log(msgSvc(), name());
+    info()<<" RecGenfitAlgDC initialize()"<<endmsg;
+
+    ///Get GeomSvc
+    m_geomSvc=Gaudi::svcLocator()->service("GeomSvc");
+    if (nullptr==m_geomSvc) {
+        std::cout<<"Failed to find GeomSvc"<<std::endl;
+        return StatusCode::FAILURE;
+    }
+    ///Get Detector
+    m_dd4hep = m_geomSvc->lcdd();
+    ///Get Field
+    m_dd4hepField=m_geomSvc->lcdd()->field();
+
+    /// New a genfit fitter
+    m_genfitFitter=new GenfitFitter(m_fitterType.c_str());
+    m_genfitField=new GenfitField(m_dd4hepField);
+    m_genfitFitter->setField(m_genfitField);
+    m_genfitFitter->setGeoMaterial(m_geomSvc->lcdd());
+    m_genfitFitter->setEnergyLossBrems(m_correctBremsstrahlung);
+    m_genfitFitter->setNoiseBrems(m_correctBremsstrahlung);
+    if(m_debug>10) m_genfitFitter->setDebug(m_debug-10);
+    if(m_noMaterialEffects) m_genfitFitter->setNoEffects(true);
+    if(-1==m_debugPid) m_genfitFitter->setNoEffects(true);
+    if(-1==m_debugPid) m_debugPid=0;//charged geantino with electron pid
+    if(m_fitterType=="DAF"||m_fitterType=="DafRef"){
+        m_genfitFitter->setMaxIterationsBetas(m_bStart,m_bFinal,m_maxIteration);
+    } else {
+        m_genfitFitter->setMaxIterations(m_maxIteration);
+    }
+    //print genfit parameters
+    if(m_debug) m_genfitFitter->print();
+    if(""!=m_genfitHistRootName) m_genfitFitter->initHist(m_genfitHistRootName);
+
+    //initialize member vairables
+    for(int i=0;i<5;i++) m_fitSuccess[i]=0;
+    m_nDCTrack=0;
+    ///Get Readout
+    dd4hep::Readout readout=m_dd4hep->readout(m_readout_name);
+std::cout<<__FILE__<<"   "<<__LINE__<<std::endl;
+    ///Get Segmentation
+    m_gridDriftChamber=dynamic_cast<dd4hep::DDSegmentation::GridDriftChamber*>
+        (readout.segmentation().segmentation());
+std::cout<<__FILE__<<"   "<<__LINE__<<std::endl;
+    if(nullptr==m_gridDriftChamber){
+        error() << "Failed to get the GridDriftChamber" << endmsg;
+        return StatusCode::FAILURE;
+    }
+std::cout<<__FILE__<<"   "<<__LINE__<<std::endl;
+    ///Get Decoder
+    m_decoder = m_geomSvc->getDecoder(m_readout_name);
+    if (nullptr==m_decoder) {
+        error() << "Failed to get the decoder" << endmsg;
+        return StatusCode::FAILURE;
+    }
+std::cout<<__FILE__<<"   "<<__LINE__<<std::endl;
+
+
+    ///book tuple
+    NTuplePtr nt(ntupleSvc(), "RecGenfitAlgDC/genfit");
+    if(nt){
+        m_tuple=nt;
+    }else{
+        m_tuple=ntupleSvc()->book("RecGenfitAlgDC/genfit",
+                CLID_ColumnWiseTuple,"RecGenfitAlgDC");
+        if(m_tuple){
+            StatusCode sc;
+            sc=m_tuple->addItem("run",m_run);
+            sc=m_tuple->addItem("evt",m_evt);
+            sc=m_tuple->addItem("tkId",m_tkId);
+            sc=m_tuple->addItem("mcIndex",m_mcIndex,0,100);//max. 100 particles
+            sc=m_tuple->addItem("truthPocaMc",m_mcIndex,m_pocaPosMc,3);
+            sc=m_tuple->addItem("pocaPosMc",m_mcIndex,m_pocaPosMc,3);
+            sc=m_tuple->addItem("pocaMomMc",m_mcIndex,m_pocaMomMc,3);
+            sc=m_tuple->addItem("pocaMomMcP",m_mcIndex,m_pocaMomMcP);
+            sc=m_tuple->addItem("pocaMomMcPt",m_mcIndex,m_pocaMomMcPt);
+            sc=m_tuple->addItem("pocaPosMdc",3,m_pocaPosMdc);
+            sc=m_tuple->addItem("pocaMomMdc",3,m_pocaMomMdc);
+            sc=m_tuple->addItem("index",m_pidIndex, 0, 5);
+            sc=m_tuple->addItem("firstPosKalP",5,3,m_firstPosKal);
+            sc=m_tuple->addItem("firstMomKalP",5,m_firstMomKalP);
+            sc=m_tuple->addItem("firstMomKalPt",5,m_firstMomKalPt);
+            sc=m_tuple->addItem("pocaPosKal",5,3,m_pocaPosKal);
+            sc=m_tuple->addItem("pocaMomKal",5,3,m_pocaMomKal);
+            sc=m_tuple->addItem("pocaMomKalP",5,m_pocaMomKalP);
+            sc=m_tuple->addItem("pocaMomKalPt",5,m_pocaMomKalPt);
+            sc=m_tuple->addItem("nDofKal",m_pidIndex,m_nDofKal);
+            sc=m_tuple->addItem("chi2Kal",m_pidIndex,m_chi2Kal);
+            sc=m_tuple->addItem("convergeKal",m_pidIndex,m_convergeKal);
+            sc=m_tuple->addItem("isFittedKal",m_pidIndex,m_isFittedKal);
+            sc=m_tuple->addItem("nHitFailedKal",m_pidIndex,m_nHitFailedKal);
+            sc=m_tuple->addItem("nHitFitted",m_pidIndex,m_nHitFitted);
+            sc=m_tuple->addItem("nDigi",m_nDigi);
+            sc=m_tuple->addItem("nHitMc",m_nHitMc);
+            sc=m_tuple->addItem("nHitKalInput",m_nHitKalInput);
+            sc=m_tuple->addItem("nClusterCgem",m_nClusterCgem);
+            sc=m_tuple->addItem("nHitMdc",m_nHitMdc,0,6796);
+            sc=m_tuple->addItem("mdcHitDriftT",m_nHitMdc,m_mdcHitDriftT);
+            sc=m_tuple->addItem("mdcHitDriftDl",m_nHitMdc,m_mdcHitDriftDl);
+            sc=m_tuple->addItem("mdcHitDriftDr",m_nHitMdc,m_mdcHitDriftDr);
+            sc=m_tuple->addItem("mdcHitLr",m_nHitMdc,m_mdcHitLr);
+            sc=m_tuple->addItem("mdcHitLayer",m_nHitMdc,m_mdcHitLayer);
+            sc=m_tuple->addItem("mdcHitWire",m_nHitMdc,m_mdcHitWire);
+            sc=m_tuple->addItem("mdcHitExpDoca",m_nHitMdc,m_mdcHitExpDoca);
+            sc=m_tuple->addItem("mdcHitExpMcDoca",m_nHitMdc,m_mdcHitExpMcDoca);
+            sc=m_tuple->addItem("mdcHitErr",m_nHitMdc,m_mdcHitErr);
+            sc=m_tuple->addItem("time",m_pidIndex,m_time);
+            sc=m_tuple->addItem("mdcHitMcTkId",m_nHitMdc,m_mdcHitMcTkId);
+            sc=m_tuple->addItem("mdcHitMcLr",m_nHitMdc,m_mdcHitMcLr);
+            sc=m_tuple->addItem("mdcHitMcDrift",m_nHitMdc,m_mdcHitMcDrift);
+            sc=m_tuple->addItem("mdcHitMcX",m_nHitMdc,m_mdcHitMcX);
+            sc=m_tuple->addItem("mdcHitMcY",m_nHitMdc,m_mdcHitMcY);
+            sc=m_tuple->addItem("mdcHitMcZ",m_nHitMdc,m_mdcHitMcZ);
+            sc=m_tuple->addItem("mcPocaX",m_nHitMdc,m_mdcHitExpMcPocaX);
+            sc=m_tuple->addItem("mcPocaY",m_nHitMdc,m_mdcHitExpMcPocaY);
+            sc=m_tuple->addItem("mcPocaZ",m_nHitMdc,m_mdcHitExpMcPocaZ);
+            sc=m_tuple->addItem("mcPocaWireX",m_nHitMdc,m_mdcHitExpMcPocaWireX);
+            sc=m_tuple->addItem("mcPocaWireY",m_nHitMdc,m_mdcHitExpMcPocaWireY);
+            sc=m_tuple->addItem("mcPocaWireZ",m_nHitMdc,m_mdcHitExpMcPocaWireZ);
+            log << MSG::DEBUG<< "Book tuple RecGenfitAlgDC/genfit" << endmsg;
+        }else{
+            log << MSG::ERROR << "Cannot book tuple RecGenfitAlgDC/genfit" << endmsg;
+        }
+    }//end of book tuple
+
+    //init genfit event display
+    //if(m_showDisplay) m_genfitDisplay = genfit::EventDisplay::getInstance();
+
+
+    return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode RecGenfitAlgDC::execute()
+{
+
+    m_timer=clock();
+    m_firstPid=true;
+    info()<<" RecGenfitAlgDC in execute()"<<endmsg;
+    StatusCode sc;
+
+    /////retrieve EventHeader
+    //auto header = _headerCol.get()->at(0);
+    //int evtNo = header.getEventNumber();
+    //int runNo = header.getRunNumber();
+
+    //std::cout<<"run "<<header.getEventNumber()
+    //  <<" "<<header.getRunNumber()<<std::endl;
+
+    fitMC();
+
+    //if(m_genfitDisplay) while(1){
+    //    std::cout<<"Press any key to finish..."<<std::endl;
+    //    //system ("pause");
+    //}
+
+    if(m_tuple) m_tuple->write();
+
+    return StatusCode::SUCCESS;
+}
+
+StatusCode RecGenfitAlgDC::fitMC()
+{
+    MsgStream log(msgSvc(), name());
+
+    /////retrieve DC hits and MC particle(s)
+    //const edm4hep::SimTrackerHitCollection* simDCHitCol=nullptr;
+    //simDCHitCol=m_simDCHitCol.get();
+    //if(nullptr==simDCHitCol) {
+    //    log<<MSG::DEBUG<<"DriftChamberHitsCollection not found"<<endmsg;
+    //    return StatusCode::SUCCESS;
+    //}
+    //const edm4hep::MCParticleCollection* mcParticleCol = nullptr;
+    //mcParticleCol=m_mcParticleCol.get();
+    //if(!mcParticleCol) {
+    //    log<<MSG::DEBUG<<"MCParticleCollection not found"<<endmsg;
+    //    return StatusCode::SUCCESS;
+    //}
+    ///retrieve Track and TrackHits
+    const edm4hep::TrackCollection* dcTrackCol=nullptr;
+    dcTrackCol=m_dcTrackCol.get();
+    if(nullptr==dcTrackCol) {
+        log<<MSG::DEBUG<<"TrackCollection not found"<<endmsg;
+        return StatusCode::SUCCESS;
+    }
+    const edm4hep::TrackerHitCollection* didiDCHitsCol=nullptr;
+    didiDCHitsCol=m_digiDCHitsCol.get();
+    if(nullptr==didiDCHitsCol) {
+        log<<MSG::DEBUG<<"DigiDCHitsCollection not found"<<endmsg;
+        return StatusCode::SUCCESS;
+    }
+    edm4hep::ReconstructedParticleCollection* dcRecParticleCol=
+        m_dcRecParticleCol.createAndPut();
+    ///----------------------------------------------------
+    ///Loop over Track and do fitting for each track
+    ///----------------------------------------------------
+    log<<MSG::DEBUG<<"DCTrackCol size="<<dcTrackCol->size()<<endmsg;
+    for(auto dcTrack: *dcTrackCol){
+        ///Loop over 5 particle hypothesis(0-4): e,mu,pi,K,p
+        ///, -1 for chargedgeantino
+        for(unsigned int pidType=0;pidType<m_nPDG-1;pidType++){
+            if((m_debugPid>=0) && (m_debugPid!=pidType)) continue;
+            ///-----------------------------------
+            ///Create a GenFit track
+            ///-----------------------------------
+            GenfitTrack* genfitTrack=new GenfitTrack(m_genfitField,
+                    m_gridDriftChamber);
+            genfitTrack->setDebug(m_debug);
+            double eventStartTime=0;
+            if(!genfitTrack->createGenfitTrackFromEDM4HepTrack(pidType,dcTrack,
+                        eventStartTime)){
+                log<<MSG::DEBUG<<"createGenfitTrack failed!"<<endmsg;
+                return StatusCode::SUCCESS;
+            }
+            double sigma=0.02;//cm
+            if(0==genfitTrack->addWireMeasurementOnTrack(dcTrack,sigma)){
+                log<<MSG::DEBUG<<"addWireMeasurementOnTrack failed!"<<endmsg;
+                return StatusCode::SUCCESS;
+            }
+            if(m_debug) genfitTrack->printSeed();
+
+            ///-----------------------------------
+            ///call genfit fitting procedure
+            ///-----------------------------------
+            m_genfitFitter->processTrack(genfitTrack,m_resortHits);
+            m_genfitFitter->setDebug(m_debug);
+
+            ///-----------------------------------
+            ///Store track
+            ///-----------------------------------
+            auto dcRecParticle=dcRecParticleCol->create();
+            genfitTrack->storeTrack(dcRecParticle,pidType,m_ndfCut,
+                    m_chi2Cut);
+
+            if(m_tuple) debugTrack(pidType,genfitTrack);
+            if(m_showDisplay) {
+                //m_genfitDisplay->addEvent(genfitTrack->getTrack());
+                //m_genfitDisplay->open();
+            }else{
+                delete genfitTrack;
+            }
+        }//end loop over particle type
+    }//end loop over a track
+
+    if(m_tuple) debugEvent();
+
+    return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode RecGenfitAlgDC::finalize()
+{
+    MsgStream log(msgSvc(), name());
+    log << MSG::INFO << " RecGenfitAlgDC in finalize()" << endmsg;
+
+    m_genfitFitter->writeHist();
+    delete m_genfitFitter;
+    std::cout<<"RecGenfitAlgDC nRecTrack="<<m_nDCTrack<<" success e "
+        <<m_fitSuccess[0]<<" mu "<<m_fitSuccess[1]<<" pi "<<m_fitSuccess[2]
+        <<" K "<<m_fitSuccess[3]<<" p "<<m_fitSuccess[4]<<std::endl;
+    if(m_nDCTrack>0){
+        std::cout<<"RecGenfitAlgDC Success rate = "<<std::endl;
+        for (int i=0;i<5;i++){
+            std::cout<<Form("%d %2.2f",i,((float) m_fitSuccess[i])/m_nDCTrack)
+                <<std::endl;
+        }
+    }
+    return StatusCode::SUCCESS;
+}
+
+void RecGenfitAlgDC::debugTrack(int pidType,const GenfitTrack* genfitTrack)
+{
+    /// Get fit status
+    const genfit::FitStatus* fitState = genfitTrack->getFitStatus();
+    double chi2 = fitState->getChi2();
+    double ndf = fitState->getNdf();
+    double charge = fitState->getCharge();
+    int isFitted = fitState->isFitted();
+    int isConverged = fitState->isFitConverged();
+    int isConvergedFully = fitState->isFitConvergedFully();
+
+    ///get fitted state of track
+    TMatrixDSym fittedCov;
+    TLorentzVector fittedPos;
+    TVector3 fittedMom;
+    int fittedState=genfitTrack->getFittedState(fittedPos,fittedMom,fittedCov);
+    HelixClass helix;//mm and GeV
+    float pos[3]={fittedPos.X()/dd4hep::mm,fittedPos.Y()/dd4hep::mm,fittedPos.Z()/dd4hep::mm};
+    float mom[3]={fittedMom.X(),fittedMom.Y(),fittedMom.Z()};
+    helix.Initialize_VP(pos,mom,charge,m_genfitField->getBz(fittedPos.Vect()));
+    m_pocaMomKalP[pidType]=fittedMom.Mag();
+
+}
+
+void RecGenfitAlgDC::debugEvent()
+{
+    const edm4hep::MCParticleCollection* mcParticleCol = nullptr;
+    const edm4hep::SimTrackerHitCollection* simDCHitCol=nullptr;
+
+    mcParticleCol=m_mcParticleCol.get();
+    simDCHitCol=m_simDCHitCol.get();
+    m_nHitMdc=simDCHitCol->size();
+    int iMcParticle=0;
+    int iHit=0;
+    for(auto mcParticle : *mcParticleCol){
+        for(auto simDCHit: *simDCHitCol){
+            edm4hep::Vector3d pos=simDCHit.position();
+            TVectorD p(3);
+            p[0]=pos.x;//no unit conversion here
+            p[1]=pos.y;
+            p[2]=pos.z;
+            m_mdcHitMcX[iHit]=pos.x;
+            m_mdcHitMcY[iHit]=pos.y;
+            m_mdcHitMcZ[iHit]=pos.z;
+            iHit++;
+        }
+        edm4hep::Vector3f mcPocaMom = mcParticle.getMomentum();//GeV
+        float px=mcPocaMom.x;
+        float py=mcPocaMom.y;
+        float pz=mcPocaMom.z;
+        std::cout<<__FILE__<<"   "<<px<<" "<<py<<" "<<pz<<std::endl;
+        m_pocaMomMcP[iMcParticle]=sqrt(px*px+py*py+pz*pz);
+        iMcParticle++;
+    }
+    m_mcIndex=iHit;
+
+    if(m_tuple) m_tuple->write();
+}
diff --git a/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.h b/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.h
new file mode 100644
index 00000000..8b2754f7
--- /dev/null
+++ b/Reconstruction/RecGenfitAlg/src/RecGenfitAlgDC.h
@@ -0,0 +1,179 @@
+//////////////////////////////////////////////////////////////////////
+///
+/// This is an algorithm for track fitting for CEPC track with genfit.
+///
+/// In this file, including:
+///   An algorithm for track fitting with genfit with 5 pid hypothesis
+///
+///   Units are following DD4hepUnits
+///
+/// Authors:
+///   Yao ZHANG(zhangyao@ihep.ac.cn)
+///
+/////////////////////////////////////////////////////////////////////
+
+#ifndef RECGENFITALG_RECGENFITALGDC_H
+#define RECGENFITALG_RECGENFITALGDC_H
+
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "GaudiKernel/NTuple.h"
+#include "k4FWCore/DataHandle.h"
+#include "DD4hep/Fields.h"
+#include <string>
+
+class GenfitFitter;
+class GenfitField;
+class GenfitTrack;
+class IGeomSvc;
+class time;
+namespace genfit{
+    class EventDisplay;
+}
+namespace dd4hep {
+    class Detector;
+    //class rec::CellIDPositionConverter;
+    namespace DDSegmentation{
+        class GridDriftChamber;
+        class BitFieldCoder;
+    }
+}
+namespace edm4hep{
+    class EventHeaderCollection;
+    class MCParticleCollection;
+    class SimTrackerHitCollection;
+    class TrackCollection;
+    class TrackerHitCollection;
+    class MCRecoTrackerAssociationCollection;
+    class ReconstructedParticle;
+    class ReconstructedParticleCollection;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+class RecGenfitAlgDC:public GaudiAlgorithm {
+    public:
+        RecGenfitAlgDC (const std::string& name, ISvcLocator* pSvcLocator);
+        StatusCode initialize() override;
+        StatusCode execute() override;
+        StatusCode finalize() override;
+
+    private:
+        GenfitFitter* m_genfitFitter;//The pointer to a GenfitFitter
+        const GenfitField* m_genfitField;//The pointer to a GenfitField
+
+        StatusCode fitMC();
+        void debugTrack(int pidType,const GenfitTrack* genfitTrack);
+        void debugEvent();
+        //void debugDoca(RecMdcTrack* recMdcTrack,const GenfitTrack* genfitTrack);
+        //void debugTruthHit();
+
+        DataHandle<edm4hep::EventHeaderCollection> _headerCol{
+            "EventHeaderCol", Gaudi::DataHandle::Reader, this};
+        //Drift chamber rec hit and trac
+        DataHandle<edm4hep::TrackerHitCollection> m_digiDCHitsCol{
+            "DigiDCHitsCollection", Gaudi::DataHandle::Reader, this};
+        DataHandle<edm4hep::TrackCollection> m_dcTrackCol{
+            "DCTrackCollection", Gaudi::DataHandle::Reader, this};
+        //Mc truth
+        DataHandle<edm4hep::MCParticleCollection> m_mcParticleCol{
+            "MCParticle", Gaudi::DataHandle::Reader, this};
+        DataHandle<edm4hep::SimTrackerHitCollection> m_simDCHitCol{
+            "DriftChamberHitsCollection" , Gaudi::DataHandle::Reader, this};
+        //output hits and particles
+        DataHandle<edm4hep::TrackerHitCollection> m_dcFitRecHitCol{
+            "DCFitRecHitsCollection", Gaudi::DataHandle::Writer, this};
+        DataHandle<edm4hep::ReconstructedParticleCollection> m_dcRecParticleCol{
+            "DCRecParticleCollection", Gaudi::DataHandle::Writer, this};
+
+        const unsigned int m_nPDG;//5:e,mu,pi,K,proton
+        SmartIF<IGeomSvc> m_geomSvc;
+        dd4hep::OverlayedField m_dd4hepField;
+        dd4hep::Detector* m_dd4hep;
+        dd4hep::DDSegmentation::GridDriftChamber* m_gridDriftChamber;
+        dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
+        Gaudi::Property<std::string> m_readout_name{this, "readout",
+            "DriftChamberHitsCollection"};
+        int m_inputType;
+        int m_debug;
+        std::string m_fitterType;//default DAFRef, DAFRef, DAF
+        bool m_correctBremsstrahlung;//defalut do not correct bremsstrahlung
+        bool m_noMaterialEffects;//defalut false, correct material effects
+        int m_maxIteration;//default 20
+        bool m_resortHits;//default true
+        double m_bStart;
+        double m_bFinal;
+        double m_dcCornerCuts;
+        int m_ndfCut;//default true
+        double m_chi2Cut;//default 1000
+        int m_fitSuccess[5];
+        int m_nDCTrack;
+        int m_debugPid;
+        bool m_useTruthSeed;
+        bool m_useRecLRAmbig;
+
+        std::string m_genfitHistRootName;
+        bool m_firstPid;
+        bool m_useTruthHit;
+        bool m_showDisplay;
+        double m_initCovResPos;
+        double m_initCovResMom;
+        genfit::EventDisplay* m_genfitDisplay;
+        clock_t m_timer;
+
+        /// tuples
+        NTuple::Tuple*  m_tuple;
+        NTuple::Item<int> m_run;
+        NTuple::Item<int> m_evt;
+        NTuple::Item<int> m_tkId;
+        NTuple::Item<int> m_mcIndex;//number of navigated mcParicle
+        NTuple::Matrix<double> m_pocaPosMc;//2 dim matched particle and 3 pos.
+        NTuple::Matrix<double> m_pocaMomMc;//2 dim matched particle and 3 mom.
+        NTuple::Array<double> m_pocaMomMcP;//2 dim matched particle and p
+        NTuple::Array<double> m_pocaMomMcPt;//2 dim matched particle and pt
+        NTuple::Array<double> m_pocaPosMdc;//pos 0:x,1:y,2:z
+        NTuple::Array<double> m_pocaMomMdc;//mom. 0:px,1:py,2:pz
+        NTuple::Item<int> m_pidIndex;
+        NTuple::Matrix<double> m_firstPosKal;//5 hyposis and pos. at first
+        NTuple::Array<double> m_firstMomKalP;//5 hyposis and mom. at first
+        NTuple::Array<double> m_firstMomKalPt;//5 hyposis and mom. at first
+        NTuple::Matrix<double> m_pocaPosKal;//5 hyposis and 3 mom.
+        NTuple::Matrix<double> m_pocaMomKal;//5 hyposis and 3 mom.
+        NTuple::Array<double> m_pocaMomKalP;//5 hyposis and p
+        NTuple::Array<double> m_pocaMomKalPt;//5 hyposis and pt
+        NTuple::Array<int> m_nDofKal;
+        NTuple::Array<double> m_chi2Kal;
+        NTuple::Array<bool> m_convergeKal;
+        NTuple::Array<bool> m_isFittedKal;
+        NTuple::Item<int> m_nDigi;
+        NTuple::Item<int> m_nHitMc;
+        NTuple::Item<int> m_nHitMdc;
+        NTuple::Item<int> m_nClusterCgem;
+        NTuple::Item<int> m_nHitKalInput;
+        NTuple::Array<double> m_mdcHitDriftT;
+        NTuple::Array<double> m_mdcHitDriftDl;
+        NTuple::Array<double> m_mdcHitDriftDr;
+        NTuple::Array<int> m_mdcHitLr;
+        NTuple::Array<int> m_mdcHitLayer;
+        NTuple::Array<int> m_mdcHitWire;
+        NTuple::Array<double> m_mdcHitExpDoca;
+        NTuple::Array<double> m_mdcHitExpMcDoca;
+        NTuple::Array<double> m_mdcHitErr;
+        NTuple::Array<int> m_nHitFailedKal;
+        NTuple::Array<int> m_nHitFitted;
+        NTuple::Array<double> m_time;
+        //truth
+        NTuple::Array<int> m_mdcHitMcLr;
+        NTuple::Array<int> m_mdcHitMcTkId;
+        NTuple::Array<double> m_mdcHitMcDrift;
+        NTuple::Array<double> m_mdcHitMcX;
+        NTuple::Array<double> m_mdcHitMcY;
+        NTuple::Array<double> m_mdcHitMcZ;
+        NTuple::Array<double> m_mdcHitExpMcPocaX;
+        NTuple::Array<double> m_mdcHitExpMcPocaY;
+        NTuple::Array<double> m_mdcHitExpMcPocaZ;
+        NTuple::Array<double> m_mdcHitExpMcPocaWireX;
+        NTuple::Array<double> m_mdcHitExpMcPocaWireY;
+        NTuple::Array<double> m_mdcHitExpMcPocaWireZ;
+
+};
+#endif
diff --git a/Reconstruction/Tracking/CMakeLists.txt b/Reconstruction/Tracking/CMakeLists.txt
index 44b8702a..0a4452cc 100644
--- a/Reconstruction/Tracking/CMakeLists.txt
+++ b/Reconstruction/Tracking/CMakeLists.txt
@@ -1,9 +1,9 @@
 gaudi_subdir(Tracking v0r0)
 
 find_package(GEAR REQUIRED)
-find_package(GSL REQUIRED ) 
-find_package(LCIO REQUIRED ) 
-find_package(EDM4HEP REQUIRED ) 
+find_package(GSL REQUIRED )
+find_package(LCIO REQUIRED )
+find_package(EDM4HEP REQUIRED )
 find_package(DD4hep COMPONENTS DDCore DDRec REQUIRED)
 
 
@@ -11,17 +11,21 @@ gaudi_depends_on_subdirs(
     Service/GearSvc
     Service/EventSeeder
     Service/TrackSystemSvc
+    Detector/DetSegmentation
 )
 
 set(Tracking_srcs
     src/Clupatra/*.cpp
     src/FullLDCTracking/*.cpp
+    src/TruthTracker/*.cpp
 )
 
 # Modules
 gaudi_add_module(Tracking ${Tracking_srcs}
     INCLUDE_DIRS GaudiKernel gear ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS}
-    LINK_LIBRARIES GaudiAlgLib GaudiKernel ${GEAR_LIBRARIES} ${GSL_LIBRARIES} ${LCIO_LIBRARIES} TrackSystemSvcLib
+    LINK_LIBRARIES GaudiAlgLib GaudiKernel ${GEAR_LIBRARIES} ${GSL_LIBRARIES}
+    ${LCIO_LIBRARIES} TrackSystemSvcLib
+    DetSegmentation
       -Wl,--no-as-needed
      EDM4HEP::edm4hep EDM4HEP::edm4hepDict
      -Wl,--as-needed
diff --git a/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.cpp b/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.cpp
new file mode 100644
index 00000000..b6da32ed
--- /dev/null
+++ b/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.cpp
@@ -0,0 +1,203 @@
+#include "TruthTrackerAlg.h"
+#include "DataHelper/HelixClass.h"
+#include "edm4hep/EventHeaderCollection.h"
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/MCRecoParticleAssociationCollection.h"
+#include "edm4hep/ReconstructedParticleCollection.h"
+#include "DDSegmentation/Segmentation.h"
+#include "DetSegmentation/GridDriftChamber.h"
+#include "DetInterface/IGeomSvc.h"
+//#include "edm4hep/SimCalorimeterHitCollection.h"
+//#include "edm4hep/CaloHitContributionCollection.h"
+
+#include "DD4hep/Detector.h"
+#include "DD4hep/IDDescriptor.h"
+#include "DD4hep/Plugins.h"
+#include "DD4hep/DD4hepUnits.h"
+
+DECLARE_COMPONENT(TruthTrackerAlg)
+
+TruthTrackerAlg::TruthTrackerAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc), m_dd4hep(nullptr), m_gridDriftChamber(nullptr),m_decoder(nullptr)
+{
+    declareProperty("MCParticle", m_mcParticleCol,
+            "Handle of the input MCParticle collection");
+    declareProperty("DigiDCHitCollection", m_digiDCHitsCol,
+            "Handle of digi DCHit collection");
+    declareProperty("DCHitAssociationCollection", m_dcHitAssociationCol,
+        "Handle of association collection");
+    declareProperty("DCTrackCollection", m_dcTrackCol,
+        "Handle of association collection");
+    declareProperty("DCRecParticleCollection", m_dcRecParticleCol,
+            "Handle of drift chamber reconstructed particle collection");
+    declareProperty("DCRecParticleAssociationCollection", m_dcRecParticleAssociationCol,
+            "Handle of drift chamber reconstructed particle collection");
+    declareProperty("debug", m_debug=false);
+}
+
+StatusCode TruthTrackerAlg::initialize()
+{
+    ///Get geometry
+    m_geomSvc=service<IGeomSvc>("GeomSvc");
+    if (!m_geomSvc) {
+        error() << "Failed to get GeomSvc." << endmsg;
+        return StatusCode::FAILURE;
+    }
+    ///Get Detector
+    m_dd4hep=m_geomSvc->lcdd();
+    if (nullptr==m_dd4hep) {
+        error() << "Failed to get dd4hep::Detector." << endmsg;
+        return StatusCode::FAILURE;
+    }
+    //Get Field
+    m_dd4hepField=m_geomSvc->lcdd()->field();
+    ///Get Readout
+    dd4hep::Readout readout=m_dd4hep->readout(m_readout_name);
+    ///Get Segmentation
+    m_gridDriftChamber=dynamic_cast<dd4hep::DDSegmentation::GridDriftChamber*>
+        (readout.segmentation().segmentation());
+    if(nullptr==m_gridDriftChamber){
+        error() << "Failed to get the GridDriftChamber" << endmsg;
+        return StatusCode::FAILURE;
+    }
+    ///Get Decoder
+    m_decoder = m_geomSvc->getDecoder(m_readout_name);
+    if (nullptr==m_decoder) {
+        error() << "Failed to get the decoder" << endmsg;
+        return StatusCode::FAILURE;
+    }
+
+    //  Book N-tuple 1
+    NTuplePtr nt1(ntupleSvc(), "TruthTrackerAlg/1");
+    if ( nt1 ) {
+        m_tuple_id = nt1;
+    } else {
+        m_tuple_id = ntupleSvc()->book( "TruthTrackerAlg/1", CLID_RowWiseTuple, "Row-wise N-Tuple example" );
+        if ( m_tuple_id ) {
+            m_tuple_id->addItem( "system", m_id_system ).ignore();
+            m_tuple_id->addItem( "module", m_id_module ).ignore();
+            m_tuple_id->addItem( "stave", m_id_stave ).ignore();
+            m_tuple_id->addItem( "tower", m_id_tower ).ignore();
+            m_tuple_id->addItem( "layer", m_id_layer ).ignore();
+            m_tuple_id->addItem( "wafer", m_id_wafer ).ignore();
+            m_tuple_id->addItem( "cellX", m_id_cellX ).ignore();
+            m_tuple_id->addItem( "cellY", m_id_cellY ).ignore();
+
+        } else { // did not manage to book the N tuple....
+            error() << "    Cannot book N-tuple:" << long( m_tuple_id ) << endmsg;
+            return StatusCode::FAILURE;
+        }
+    }
+
+
+    return GaudiAlgorithm::initialize();
+}
+
+StatusCode TruthTrackerAlg::execute()
+{
+    ///Retrieve MC particle(s)
+    const edm4hep::MCParticleCollection* mcParticleCol=nullptr;
+    mcParticleCol=m_mcParticleCol.get();
+    if(nullptr==mcParticleCol){
+        debug()<<"MCParticleCollection not found"<<endmsg;
+        return StatusCode::SUCCESS;
+    }
+    ///Retrieve DC digi
+    const edm4hep::TrackerHitCollection* digiDCHitsCol=nullptr;
+    digiDCHitsCol=m_digiDCHitsCol.get();//FIXME DEBUG
+    if(nullptr==digiDCHitsCol){
+        debug()<<"TrackerHitCollection not found"<<endmsg;
+        //return StatusCode::SUCCESS;
+    }
+
+    ///Output Track collection
+    edm4hep::TrackCollection* dcTrackCol=m_dcTrackCol.createAndPut();
+    ////TODO
+    /////Output MCRecoTrackerAssociationCollection collection
+    //const edm4hep::MCRecoTrackerAssociationCollection*
+    //    mcRecoTrackerAssociationCol=nullptr;
+    //if(nullptr==mcRecoTrackerAssociationCol){
+    //    log<<MSG::DEBUG<<"MCRecoTrackerAssociationCollection not found"
+    //        <<endmsg;
+    //    return StatusCode::SUCCESS;
+    //}
+    //mcRecoTrackerAssociationCol=m_mcRecoParticleAssociation.get();
+
+    ///Convert MCParticle to Track and ReconstructedParticle
+    if(m_debug){
+        debug()<<"MCParticleCol size="<<mcParticleCol->size()<<endmsg;
+    }
+    for(auto mcParticle : *mcParticleCol){
+        //if(fabs(mcParticle.getCharge()<1e-6) continue;//Skip neutral particles
+        edm4hep::Vector3d posV= mcParticle.getVertex();
+        edm4hep::Vector3f momV= mcParticle.getMomentum();//GeV
+        float pos[3]={posV.x, posV.y, posV.z};
+        float mom[3]={momV.x, momV.y, momV.z};
+        //FIXME
+        //pivotToFirstLayer(mcPocaPos,mcPocaMom,firstLayerPos,firstLayerMom);
+        double B[3]={1e9,1e9,1e9};
+        m_dd4hepField.magneticField({0.,0.,0.},B);
+        if(m_debug)std::cout<<" PDG "<<mcParticle.getPDG()<<" charge "
+            << mcParticle.getCharge()
+            <<" pos "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]
+            <<" mom "<<mom[0]<<" "<<mom[1]<<" "<<mom[2]
+            <<" Bxyz "<<B[0]/dd4hep::tesla<<" "<<B[1]/dd4hep::tesla
+            <<" "<<B[2]/dd4hep::tesla<<" tesla"<<std::endl;
+
+        HelixClass helix;
+        helix.Initialize_VP(pos,mom,(int) mcParticle.getCharge(),B[2]/dd4hep::tesla);
+        edm4hep::TrackState trackState;
+        trackState.D0=helix.getD0();
+        trackState.phi=helix.getPhi0();
+        trackState.omega=helix.getOmega();
+        trackState.Z0=helix.getZ0();
+        trackState.tanLambda=helix.getTanLambda();
+        trackState.referencePoint=helix.getReferencePoint();
+        std::array<float,15> covMatrix;
+        for(int i=0;i<15;i++){covMatrix[i]=999.;}//FIXME
+        trackState.covMatrix=covMatrix;
+
+        if(m_debug){
+            std::cout<<" helix  d0 "<<trackState.D0<<
+                " phi "<<trackState.phi<<
+                " omega "<<trackState.omega<<
+                " z0 "<<trackState.Z0<<
+                " tanLambda "<<trackState.tanLambda<<
+                " referencePoint "<<trackState.referencePoint<< std::endl;
+        }
+        //new Track
+        edm4hep::Track track = dcTrackCol->create();
+        track.addToTrackStates(trackState);
+        if(nullptr!=digiDCHitsCol) {
+            //track.setType();//TODO
+            //track.setChi2(trackState->getChi2());
+            track.setNdf(digiDCHitsCol->size()-5);
+            //track.setDEdx();//TODO
+            //track.setRadiusOfInnermostHit();//TODO
+            for(int i=0; i<digiDCHitsCol->size(); i++ ){
+                edm4hep::TrackerHit digiDC=digiDCHitsCol->at(i);
+                //if(Sim->MCParti!=current) continue;//TODO
+                track.addToTrackerHits(digiDC);
+            }
+        }
+        //TODO
+        //new ReconstructedParticle
+        //recParticle->setType();
+        //dcRecParticle->setEnergy();
+        //edm4hep::Vector3f momVec3(helix.getMomentum()[0],
+        //        helix.getMomentum()[1],helix.getMomentum()[2]);
+        //recParticle->setMomentum(momVec3);
+    }
+
+    if(m_debug) std::cout<<"Output DCTrack size="<<dcTrackCol->size()<<std::endl;
+    return StatusCode::SUCCESS;
+}
+
+StatusCode TruthTrackerAlg::finalize()
+{
+    return GaudiAlgorithm::finalize();
+}
diff --git a/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.h b/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.h
new file mode 100644
index 00000000..f8f31c13
--- /dev/null
+++ b/Reconstruction/Tracking/src/TruthTracker/TruthTrackerAlg.h
@@ -0,0 +1,79 @@
+#ifndef TruthTrackerAlg_h
+#define TruthTrackerAlg_h
+
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "k4FWCore/DataHandle.h"
+#include "GaudiKernel/NTuple.h"
+#include "DD4hep/Fields.h"
+
+class IGeomSvc;
+namespace dd4hep {
+    class Detector;
+    //class rec::CellIDPositionConverter;
+    namespace DDSegmentation{
+        class GridDriftChamber;
+        class BitFieldCoder;
+    }
+}
+namespace edm4hep {
+    class MCParticleCollection;
+    class TrackerHitCollection;
+    class TrackCollection;
+    class MCRecoTrackerAssociationCollection;
+    class ReconstructedParticleCollection;
+    class MCRecoParticleAssociationCollection;
+}
+
+class TruthTrackerAlg: public GaudiAlgorithm
+{
+    public:
+        TruthTrackerAlg(const std::string& name, ISvcLocator* svcLoc);
+
+        virtual StatusCode initialize();
+        virtual StatusCode execute();
+        virtual StatusCode finalize();
+
+    private:
+        SmartIF<IGeomSvc> m_geomSvc;
+        dd4hep::Detector* m_dd4hep;
+        dd4hep::OverlayedField m_dd4hepField;
+        //dd4hep::rec::CellIDPositionConverter* m_cellIDConverter;
+        dd4hep::DDSegmentation::GridDriftChamber* m_gridDriftChamber;
+        dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
+
+        //reader
+        DataHandle<edm4hep::MCParticleCollection> m_mcParticleCol{
+            "MCParticle", Gaudi::DataHandle::Reader, this};
+        DataHandle<edm4hep::TrackerHitCollection> m_digiDCHitsCol{
+            "DigiDCHitsCollection", Gaudi::DataHandle::Reader, this};
+        DataHandle<edm4hep::MCRecoTrackerAssociationCollection>
+            m_dcHitAssociationCol{ "DCHitAssociationCollection",
+                Gaudi::DataHandle::Reader, this};
+        //writer
+        DataHandle<edm4hep::TrackCollection> m_dcTrackCol{"DCTrackCollection",
+            Gaudi::DataHandle::Writer, this};
+        DataHandle<edm4hep::ReconstructedParticleCollection> m_dcRecParticleCol{
+            "DCRecParticleCollection", Gaudi::DataHandle::Writer, this};
+        DataHandle<edm4hep::MCRecoParticleAssociationCollection>
+            m_dcRecParticleAssociationCol{"DCRecMCRecoParticleAssociationCollection",
+                Gaudi::DataHandle::Writer, this};
+
+        //readout for getting segmentation
+        Gaudi::Property<std::string> m_readout_name{this, "readout",
+            "DriftChamberHitsCollection"};
+
+        int m_debug;
+        //strore all the id for later analysis
+        NTuple::Tuple* m_tuple_id = nullptr;
+
+        NTuple::Item<int> m_id_system;
+        NTuple::Item<int> m_id_module;
+        NTuple::Item<int> m_id_stave;
+        NTuple::Item<int> m_id_tower;
+        NTuple::Item<int> m_id_layer;
+        NTuple::Item<int> m_id_wafer;
+        NTuple::Item<int> m_id_cellX;
+        NTuple::Item<int> m_id_cellY;
+};
+
+#endif
diff --git a/Utilities/DataHelper/src/HelixClass.cc b/Utilities/DataHelper/src/HelixClass.cc
index 591acc51..8075c062 100644
--- a/Utilities/DataHelper/src/HelixClass.cc
+++ b/Utilities/DataHelper/src/HelixClass.cc
@@ -49,6 +49,8 @@ void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) {
     else {
       d0 = double(q)*radius + double(sqrt(xCentre*xCentre+yCentre*yCentre));
     }
+    std::cout<<__FILE__<<"   "<<__LINE__<<" d0 "<<d0<<" r "<<radius<<" q "<<q<<" xCentre "<<xCentre<<" yCentre "<<yCentre<<std::endl;
+    std::cout<<__FILE__<<"   "<<__LINE__<<" pxy "<<_pxy<<" FCT "<<_FCT<<" B "<<B<<std::endl;
 
     _d0 = float(d0);
 
-- 
GitLab