diff --git a/Digitization/DigiSimple/CMakeLists.txt b/Digitization/DigiSimple/CMakeLists.txt
index dfebaaea1daebd39f3176e85452cf74166ba9623..ee035a9d704412ad0526eeceaaa65c675c2836b0 100644
--- a/Digitization/DigiSimple/CMakeLists.txt
+++ b/Digitization/DigiSimple/CMakeLists.txt
@@ -5,6 +5,8 @@ gaudi_add_module(SimpleDigi
                          src/voxel.cpp
                          src/CylinderDigiAlg.cpp
                          src/SiTrackerDigiAlg.cpp
+                         src/TPCPixelDigiAlg.cpp
+                         src/TPCPixelDigiTool.cpp
                          src/SmearDigiTool.cpp
                  LINK GearSvc
                       DigiTool
diff --git a/Digitization/DigiSimple/src/TPCPixelDigiAlg.cpp b/Digitization/DigiSimple/src/TPCPixelDigiAlg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f819fee2476a2025f03bcb0de2609279511d6bbf
--- /dev/null
+++ b/Digitization/DigiSimple/src/TPCPixelDigiAlg.cpp
@@ -0,0 +1,70 @@
+#include "TPCPixelDigiAlg.h"
+
+
+#include "edm4hep/Vector3f.h"
+
+#include "DD4hep/Detector.h"
+#include <DD4hep/Objects.h>
+#include "DD4hep/DD4hepUnits.h"
+#include "DDRec/Vector3D.h"
+#include "DDRec/ISurface.h"
+
+#include "GaudiKernel/INTupleSvc.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/IRndmGen.h"
+#include "GaudiKernel/IRndmGenSvc.h"
+#include "GaudiKernel/RndmGenerators.h"
+
+DECLARE_COMPONENT(TPCPixelDigiAlg)
+
+TPCPixelDigiAlg::TPCPixelDigiAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc) {
+  // Input collections
+  declareProperty("SimTrackHitCollection", m_inputColHdls, "Handle of the Input SimTrackerHit collection");
+
+
+  // Output collections
+  declareProperty("TPCTrackerHits", m_outputColHdls, "Handle of the output TrackerHit collection");
+  declareProperty("TPCTrackerHitAss", m_assColHdls, "Handle of the Association collection between SimTrackerHit and TrackerHit");
+}
+
+StatusCode TPCPixelDigiAlg::initialize() {
+  m_digiTool = ToolHandle<IDigiTool>(m_digiToolName.value());
+
+  info() << "DigiTool " << m_digiTool.typeAndName() << " found" << endmsg;
+
+  info() << "TPCPixelDigiAlg::initialized" << endmsg;
+  return GaudiAlgorithm::initialize();
+}
+
+
+StatusCode TPCPixelDigiAlg::execute(){
+  auto trkCol = m_outputColHdls.createAndPut();
+  auto assCol = m_assColHdls.createAndPut();
+
+  const edm4hep::SimTrackerHitCollection* simCol = nullptr;
+  try {
+    simCol = m_inputColHdls.get();
+  }
+  catch(GaudiException &e){
+    debug() << "Collection " << m_inputColHdls.fullKey() << " test is unavailable in event " << m_nEvt << endmsg;
+    return StatusCode::SUCCESS;
+  }
+  if (simCol->size() == 0) return StatusCode::SUCCESS;
+  debug() << m_inputColHdls.fullKey() << " has cluser "<< simCol->size() << endmsg;
+
+  m_digiTool->Call(simCol, trkCol, assCol);
+
+  debug() << "Created " << trkCol->size() << " hits, "<<simCol->size()<<" clusters"
+          << simCol->size() - trkCol->size() << " hits got dismissed for being out of boundary"
+          << endmsg;
+
+  m_nEvt++;
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TPCPixelDigiAlg::finalize(){
+  info() << "Processed " << m_nEvt << " events " << endmsg;
+  return GaudiAlgorithm::finalize();
+}
diff --git a/Digitization/DigiSimple/src/TPCPixelDigiAlg.h b/Digitization/DigiSimple/src/TPCPixelDigiAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..abfc71ec528b4e6d36e04ab34d3aaca0bfb58501
--- /dev/null
+++ b/Digitization/DigiSimple/src/TPCPixelDigiAlg.h
@@ -0,0 +1,38 @@
+#ifndef TPCPixelDigiAlg_H
+#define TPCPixelDigiAlg_H
+
+#include "k4FWCore/DataHandle.h"
+#include "GaudiKernel/NTuple.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/SimPrimaryIonizationClusterCollection.h"
+#include "edm4hep/SimPrimaryIonizationCluster.h"
+
+#include "DigiTool/IDigiTool.h"
+
+class TPCPixelDigiAlg : public GaudiAlgorithm{
+ public:
+  
+  TPCPixelDigiAlg(const std::string& name, ISvcLocator* svcLoc);
+ 
+  virtual StatusCode initialize();
+  virtual StatusCode execute();
+  virtual StatusCode finalize();
+ 
+protected:
+  // Input collections
+  // DataHandle<edm4hep::SimPrimaryIonizationClusterCollection>            m_inputColHdls{"SimPrimaryIonizationClusterCollection", Gaudi::DataHandle::Reader, this};
+  // DataHandle<edm4hep::SimPrimaryIonizationClusterCollection>            m_inputIonClusterCol{"SimPrimaryIonizationClusterCollection", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::SimTrackerHitCollection>            m_inputColHdls{"TPCCollection", Gaudi::DataHandle::Reader, this};
+  // Output collections
+  DataHandle<edm4hep::TrackerHitCollection>               m_outputColHdls{"TPCTrackerHits", Gaudi::DataHandle::Writer, this};
+  DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_assColHdls{"TPCTrackerHitsAss", Gaudi::DataHandle::Writer, this};
+
+  Gaudi::Property<std::string> m_digiToolName{this, "DigiTool", "TPCPixelDigiTool"};
+
+  ToolHandle<IDigiTool> m_digiTool;
+  int m_nEvt=0;
+};
+#endif
diff --git a/Digitization/DigiSimple/src/TPCPixelDigiTool.cpp b/Digitization/DigiSimple/src/TPCPixelDigiTool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9bb8d976a4197e90bd4f6166e984c14de24bd6e2
--- /dev/null
+++ b/Digitization/DigiSimple/src/TPCPixelDigiTool.cpp
@@ -0,0 +1,411 @@
+#include "TPCPixelDigiTool.h"
+#include "k4FWCore/DataHandle.h"
+#include "DataHelper/TrackerHitHelper.h"
+#include "DetIdentifier/CEPCConf.h"
+#include "DetInterface/IGeomSvc.h"
+#include "DataHelper/Circle.h"
+
+#include "edm4hep/Vector3f.h"
+
+#include "DD4hep/Detector.h"
+#include <DD4hep/Objects.h>
+#include "DD4hep/DD4hepUnits.h"
+#include "DDRec/ISurface.h"
+
+#include "GaudiKernel/INTupleSvc.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/IRndmGen.h"
+#include "GaudiKernel/RndmGenerators.h"
+#include <gear/GEAR.h>
+#include <gear/TPCParameters.h>
+
+#include "CLHEP/Vector/ThreeVector.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include <math.h>
+
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <map>
+#include <cmath>
+#include <algorithm>
+#include <array>
+
+// #include "DataHelper/Circle.h"
+#include "DataHelper/SimpleHelix.h"
+#include "DataHelper/LCCylinder.h"
+#include "EventSeeder/IEventSeeder.h"
+#include <stdexcept>
+#include "GearSvc/IGearSvc.h"
+#include <UTIL/BitField64.h>
+#include <edm4hep/MCParticle.h>
+#include "edm4hep/SimTrackerHit.h"
+
+#include "CLHEP/Vector/TwoVector.h"
+#include "UTIL/ILDConf.h"
+
+#define TRKHITNCOVMATRIX 6
+// using namespace lcio ;
+
+DECLARE_COMPONENT(TPCPixelDigiTool)
+
+StatusCode TPCPixelDigiTool::initialize()
+{
+
+  m_geosvc = service<IGeomSvc>("GeomSvc");
+  if (!m_geosvc)
+  {
+    error() << "Failed to get the GeomSvc" << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+
+  debug() << "Readout name: " << m_readoutName << endmsg;
+  m_decoder = m_geosvc->getDecoder(m_readoutName);
+  if (!m_decoder)
+  {
+    error() << "Failed to get the decoder. " << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+  _gear = service<IGearSvc>("GearSvc");
+  if (!_gear)
+  {
+    error() << "Failed to find GearSvc ..." << endmsg;
+    return StatusCode::FAILURE;
+  }
+  _GEAR = _gear->getGearMgr();
+  _f1 = new TF1("fp", "[0]*pow(1+[1],1+[1])*pow(x/[2],[1])*exp(-(1+[1])*x/[2])/TMath::Gamma(1+[1])", 0, 10000);
+  // _f1->SetParameters(3802, 0.487, 2092);
+  _f1->SetParameters(_polyParas[0], _polyParas[1], _polyParas[2]);
+  x_diffusion_p0=0.;
+  y_diffusion_p0=0.;
+  x_diffusion_p1=0.;
+  y_diffusion_p1=0.;
+  t_diffusion_p0 = 0.;
+  t_diffusion_p1 = 0.;
+
+  switch (_magnetic) {
+    case 2:
+        x_diffusion_p0 = 0.001992;
+        x_diffusion_p1 = 0.004387;
+        y_diffusion_p0 = 0.001877;
+        y_diffusion_p1 = 0.004398;
+		t_diffusion_p0 = 0.0002519;
+		t_diffusion_p1 = 0.00332;
+        tpcZRes = tpcTRes * 80; // drift speed 80um/us
+        break;
+
+    case 3:
+        x_diffusion_p0 = 0.001403;
+        x_diffusion_p1 = 0.003011;
+        y_diffusion_p0 = 0.001604;
+        y_diffusion_p1 = 0.003042;
+		t_diffusion_p0 = 5.41279e-05;
+		t_diffusion_p1 = 3.28842e-03;
+        tpcZRes = tpcTRes * 80; // drift speed 80um/us
+        break;
+
+    default:
+        x_diffusion_p0 = 0.0;
+        x_diffusion_p1 = 0.0;
+        y_diffusion_p0 = 0.0;
+        y_diffusion_p1 = 0.0;
+		t_diffusion_p0 = 5.41279e-05;
+		t_diffusion_p1 = 3.28842e-03;
+        tpcZRes = tpcTRes * 80; // drift speed 80um/us
+        break;
+}
+
+ 
+
+  info() << "initialized" << endmsg;
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TPCPixelDigiTool::Call(const edm4hep::SimTrackerHitCollection *simCol, edm4hep::TrackerHitCollection *hitCol,
+                                  edm4hep::MCRecoTrackerAssociationCollection *assCol)
+{
+
+  edm4hep::SimTrackerHit simhit;
+  StatusCode sc = Call(simhit, hitCol, assCol);
+  if (sc.isFailure())
+    return sc;
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TPCPixelDigiTool::Call(edm4hep::SimTrackerHit simhit, edm4hep::TrackerHitCollection *hitCol, edm4hep::MCRecoTrackerAssociationCollection *assCol)
+{
+  DataHandle<edm4hep::SimPrimaryIonizationClusterCollection> m_inputIonClusterCol{"SimPrimaryIonizationClusterCollection", Gaudi::DataHandle::Reader, this};
+  DataHandle<edm4hep::SimTrackerHitCollection> m_inputSimCol{m_readoutName, Gaudi::DataHandle::Reader, this};
+  UTIL::BitField64 *_cellid_encoder = new UTIL::BitField64(CEPCConf::DetEncoderString::getStringRepresentation());
+  float weight = 1.0;
+
+  // double bReso = _diffRPhi * _diffRPhi;
+  const gear::TPCParameters &gearTPC = _GEAR->getTPCParameters();
+  const gear::PadRowLayout2D &padLayout = gearTPC.getPadLayout();
+  // gear::Vector2D padCoord;
+  const edm4hep::SimTrackerHitCollection *simCol = nullptr;
+  try
+  {
+    simCol = m_inputSimCol.get();
+  }
+  catch (GaudiException &e)
+  {
+    debug() << "Collection " << m_inputSimCol.fullKey() << " is unavailable in event " << endmsg;
+    return StatusCode::SUCCESS;
+  }
+
+  const edm4hep::SimPrimaryIonizationClusterCollection *clusterCol = nullptr;
+  try
+  {
+    clusterCol = m_inputIonClusterCol.get();
+  }
+  catch (GaudiException &e)
+  {
+    debug() << "Collection " << m_inputIonClusterCol.fullKey() << " is unavailable in event " << endmsg;
+    return StatusCode::SUCCESS;
+  }
+  std::map<int, edm4hep::SimTrackerHit> simhitMap;                      // A map to save the sim tracker hit, key is TPC layer, value is 3D position of simhit
+  std::map<int, std::tuple<double, double, double>> digihitMap; // A map to save the XYZ resolutions and  Z position(key is pad index, values are z and rphi resolutions and Z position)
+  std::map<int, int> tpcPixelQ;                                         // A map to save number of electrons in same pixel (key is pixel index, value is number of eles)
+  std::map<int, int> tpcPixelFlag;                                      // A map to mark if a pixel already has a hit (key is pixel index), only used in merging case
+  std::map<int, std::vector<int>> tpcPixelQMap;
+  std::map<int, std::vector<std::tuple<float, float>>> TimeZMap;        // A map to save time and z direction infos
+  
+  for (auto sim : *simCol)
+  { // loop all sim tracker hits, save them in a map, key is TPC layer, value is 3D position of simhit
+    CLHEP::Hep3Vector SimPoint(sim.getPosition()[0], sim.getPosition()[1], sim.getPosition()[2]);
+    int simPadIndex = padLayout.getNearestPad(SimPoint.perp(), SimPoint.phi());
+    int iRowSimHit = padLayout.getRowNumber(simPadIndex);
+    simhitMap[iRowSimHit] = sim;
+  }
+
+  int nclu = 0;
+
+
+  int padIndex;
+  int iRowHit;
+  int poylaRandom;
+  double x_amp_diffusion;
+  double y_amp_diffusion;
+  CLHEP::Hep3Vector point;
+  CLHEP::Hep3Vector thisPoint;
+  gear::Vector2D padCoord;
+  edm4hep::Vector3d posAfterSmear;
+  edm4hep::Vector3d pos;
+
+  int nIonEle;
+  debug() << " Total clusters: " << clusterCol->size() << endmsg;
+  // for (int i=0; i < _nPads;++i){
+  // padCoord=padLayout.getPadCenter(int(i));
+  // std::cout<<" check padxy "<<padCoord[0] * cos(padCoord[1])<<" "<<padCoord[0] * sin(padCoord[1])<<std::endl;
+  // std::cout<<" check padrphi "<<padCoord[0] <<" "<<padCoord[1] <<std::endl;
+  // }
+  
+
+  for (edm4hep::SimPrimaryIonizationCluster cluster : *clusterCol)
+  { // Loop all clusters
+    // break;
+    debug() << " start cluster: " << nclu << " pos:" << cluster.getPosition() << " size: " << cluster.electronPosition_size() << endmsg;
+    nclu += 1;
+    nIonEle = 0;
+
+    for (std::size_t i = 0; i < cluster.electronPosition_size(); ++i)
+    { // loop all electrons in each clusters
+
+      pos = *(cluster.electronPosition_begin() + i);
+      float eleTime = *(cluster.electronTime_begin() + i) / 1000.;//time in us
+
+      if (_MaxIonEles > 0 && nIonEle > _MaxIonEles)
+      {
+        debug() << "Maximum eles achived, break the loop" << endmsg;
+        break;
+      }
+	  driftLength = gearTPC.getMaxDriftLength() - (fabs(pos.z));
+      tpcTRes = (t_diffusion_p0 +t_diffusion_p1 * sqrt(driftLength / 10.)); 
+
+      tpcXRes = x_diffusion_p0 + x_diffusion_p1 * sqrt(driftLength);
+      tpcYRes = y_diffusion_p0 + y_diffusion_p1 * sqrt(driftLength);
+      double randx = gRandom->Gaus(pos.x, tpcXRes);
+      double randy = gRandom->Gaus(pos.y, tpcYRes);
+      // double randz = gRandom->Gaus(pos.z, tpcZRes);
+      double randt = eleTime + gRandom->Gaus(driftLength / 80, tpcTRes); // unit in us
+      double randz = randt*80;
+      //   
+      point.set(randx, randy, randz);
+
+      if (fabs(point.z()) > gearTPC.getMaxDriftLength())
+        point.setZ((fabs(point.z()) / point.z()) * gearTPC.getMaxDriftLength());
+      debug() << "resolution, x: " << tpcXRes << " y: " << tpcYRes << " z: " << tpcZRes << endmsg;
+      debug() << "Max TPC length: " << gearTPC.getMaxDriftLength() << " posz: " << fabs(pos.z) << " driftLength: " << driftLength << endmsg;
+      debug() << "smear:" << pos.x << "," << pos.y << "," << pos.z << " -> " << point << endmsg;
+      poylaRandom = _f1->GetRandom();
+      // poylaRandom = 1;
+      debug() << "polyRandom: " << poylaRandom << endmsg;
+      for (int j = 0; j < poylaRandom; ++j) // Do amplication
+      {
+
+        x_amp_diffusion = gRandom->Gaus(point.x(), _ampDiffusion);
+        y_amp_diffusion = gRandom->Gaus(point.y(), _ampDiffusion);
+        thisPoint.set(x_amp_diffusion, y_amp_diffusion, point.z());
+
+        // following lines are the method to find the pixel center
+        padIndex = padLayout.getNearestPad(thisPoint.perp(), thisPoint.phi());
+        padCoord = padLayout.getPadCenter(int(padIndex));
+        posAfterSmear.x = padCoord[0] * cos(padCoord[1]);
+        posAfterSmear.y = padCoord[0] * sin(padCoord[1]);
+        posAfterSmear.z = point.z();
+
+        digihitMap[padIndex] = std::make_tuple(tpcXRes, tpcYRes, tpcZRes); 
+        if (tpcPixelQ.find(padIndex) != tpcPixelQ.end())
+        {
+          tpcPixelQ[padIndex] += 1;
+        }
+        else
+        {
+          tpcPixelQ[padIndex] = 1;
+        }
+        if (TimeZMap[padIndex].empty())
+        {
+          TimeZMap[padIndex].push_back(std::make_tuple(randt,point.z()));
+        }
+        else
+        {
+          if (!_saveAllTime)
+          {
+
+            if (randt > std::get<0>(TimeZMap[padIndex].back()) + _deadTime)
+            {
+              info() << "now the size of pad " << padIndex << " is " << TimeZMap[padIndex].size() << " Q is  " << tpcPixelQ[padIndex] << endmsg;
+              info() << "now time is: " << randt << " previous time is: " << std::get<0>(TimeZMap[padIndex].back()) << endmsg;
+
+              TimeZMap[padIndex].push_back(std::make_tuple(randt,point.z()));
+              tpcPixelQMap[padIndex].push_back(tpcPixelQ[padIndex]);
+              tpcPixelQ[padIndex]=0;
+            }
+          }
+          else
+          {
+            auto it = TimeZMap[padIndex].rbegin();
+            bool found = false;
+            for (; it != TimeZMap[padIndex].rend(); ++it)
+            {
+              float diff = std::abs(std::get<0>(*it) - randt);
+              if (diff < _minimumTime)
+              {
+                found = true;
+                break;
+              }
+            }
+
+            if (!found)
+            {
+              TimeZMap[padIndex].emplace_back(randt,point.z());
+              tpcPixelQMap[padIndex].push_back(tpcPixelQ[padIndex]);
+              tpcPixelQ[padIndex]=0;
+            }
+          }
+        }
+
+      }
+      nIonEle += 1;
+    }
+  }
+  debug() << "create " << digihitMap.size() << " hits in different pixels before merging" << endmsg;
+  for (auto digiHit = digihitMap.begin(); digiHit != digihitMap.end(); ++digiHit)
+    {
+      padIndex = digiHit->first;
+      std::vector<std::tuple<float, float>> TimeZVec = TimeZMap[padIndex];
+      tpcPixelQMap[padIndex].push_back(tpcPixelQ[padIndex]);
+      std::vector<int> QVec = tpcPixelQMap[padIndex];
+      
+      tpcXRes = std::get<0>(digiHit->second);
+      tpcYRes = std::get<1>(digiHit->second);
+      tpcZRes = std::get<2>(digiHit->second);
+      padCoord = padLayout.getPadCenter(int(digiHit->first));
+
+      double r = padCoord[0];
+      double phi = padCoord[1];
+      padIndex = digiHit->first;
+      iRowHit = padLayout.getRowNumber(padIndex);
+      debug() << "pad center: " << r * cos(phi) << " " << r * sin(phi) << endmsg;
+      debug() << "pad r: " << r << " phi: " << phi << " Q: " << tpcPixelQ[padIndex] << endmsg;
+      posAfterSmear.x = (r * cos(phi));
+      posAfterSmear.y = (r * sin(phi));
+      
+      for (size_t i = 0; i < TimeZVec.size(); ++i) {
+        posAfterSmear.z = std::get<1>(TimeZVec[i]);
+        auto it = simhitMap.find(iRowHit);
+        if (it != simhitMap.end() && !_skipAss)
+      {
+        
+        simhit = it->second;
+        auto outhit = hitCol->create();
+        auto ass = assCol->create();
+        outhit.setPosition(posAfterSmear);
+        (*_cellid_encoder)[lcio::ILDCellID0::subdet] = lcio::ILDDetID::TPC;
+        (*_cellid_encoder)[lcio::ILDCellID0::layer] = iRowHit;
+        (*_cellid_encoder)[lcio::ILDCellID0::module] = 0;
+
+        (*_cellid_encoder)[lcio::ILDCellID0::side] = lcio::ILDDetID::barrel;
+        outhit.setCellID(_cellid_encoder->lowWord());
+        std::array<float, TRKHITNCOVMATRIX> covMat = {float(tpcXRes * tpcXRes),
+                                                      float(tpcYRes * tpcXRes),
+                                                      float(tpcYRes * tpcYRes),
+                                                      float(tpcZRes * tpcXRes),
+                                                      float(tpcZRes * tpcYRes),
+                                                      float(tpcZRes * tpcZRes)};
+
+        outhit.setCovMatrix(covMat);
+        outhit.setEDep(tpcPixelQMap[padIndex][i]);
+        outhit.setTime(std::get<0>(TimeZVec[i]));
+        info() << "out hit, x: " << outhit.getPosition()[0] << " y: " << outhit.getPosition()[1] << " z: " << outhit.getPosition()[2] << " Q: " << outhit.getEDep() << " Time: "<< outhit.getTime() << endmsg;
+        ass.setSim(simhit);
+        ass.setRec(outhit);
+        ass.setWeight(weight);
+      }
+      else if (_skipAss)// do not match the TPCCollection and TPCTrackerHits, all the TPCTrackerHitsAss has been set to 0,0,0
+      {
+        debug() << " skip ass" << endmsg;
+        debug() << " SimTrackerHit " << simhit.getPosition()[0] << endmsg;
+
+        auto outhit = hitCol->create();
+        auto ass = assCol->create();
+        outhit.setPosition(posAfterSmear);
+        (*_cellid_encoder)[lcio::ILDCellID0::subdet] = lcio::ILDDetID::TPC;
+        (*_cellid_encoder)[lcio::ILDCellID0::layer] = iRowHit;
+        (*_cellid_encoder)[lcio::ILDCellID0::module] = 0;
+
+        (*_cellid_encoder)[lcio::ILDCellID0::side] = lcio::ILDDetID::barrel;
+        outhit.setCellID(_cellid_encoder->lowWord());
+        std::array<float, TRKHITNCOVMATRIX> covMat = {float(tpcXRes * tpcXRes),
+                                                      float(tpcYRes * tpcXRes),
+                                                      float(tpcYRes * tpcYRes),
+                                                      float(tpcZRes * tpcXRes),
+                                                      float(tpcZRes * tpcYRes),
+                                                      float(tpcZRes * tpcZRes)};
+
+        outhit.setCovMatrix(covMat);
+        outhit.setEDep(tpcPixelQMap[padIndex][i]);
+        outhit.setTime(std::get<0>(TimeZVec[i]));
+
+        ass.setSim(simhit);
+        ass.setRec(outhit);
+        ass.setWeight(weight);
+        info() << "out hit, x: " << outhit.getPosition()[0] << " y: " << outhit.getPosition()[1] << " z: " << outhit.getPosition()[2] << " Q: " << outhit.getEDep() << " Time: "<< outhit.getTime() << endmsg;
+      }
+      else
+      {
+        debug() << " no matches" << endmsg;
+      }
+      }
+    }
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TPCPixelDigiTool::finalize()
+{
+  StatusCode sc;
+  return sc;
+}
diff --git a/Digitization/DigiSimple/src/TPCPixelDigiTool.h b/Digitization/DigiSimple/src/TPCPixelDigiTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd43aa065200a97f18eee2ef7d0e1129dfba7961
--- /dev/null
+++ b/Digitization/DigiSimple/src/TPCPixelDigiTool.h
@@ -0,0 +1,76 @@
+#ifndef TPCPixelDigiTool_h
+#define TPCPixelDigiTool_h
+#include "CLHEP/Vector/TwoVector.h"
+#include "GaudiKernel/AlgTool.h"
+#include "GaudiKernel/IRndmGenSvc.h"
+#include "TF1.h"
+#include "DigiTool/IDigiTool.h"
+#include "DetInterface/IGeomSvc.h"
+#include "GearSvc/IGearSvc.h"
+#include "edm4hep/SimTrackerHitCollection.h"
+#include "edm4hep/TrackerHitCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/SimPrimaryIonizationClusterCollection.h"
+#include "edm4hep/SimPrimaryIonizationCluster.h"
+#include <gear/GEAR.h>
+#include "DDRec/DetectorData.h"
+#include "DDRec/SurfaceManager.h"
+#include "TRandom3.h"
+
+#include <vector>
+
+class TPCPixelDigiTool : public extends<AlgTool, IDigiTool> {
+ public:
+  using extends::extends;
+
+  virtual StatusCode Call(const edm4hep::SimTrackerHitCollection* simCol, edm4hep::TrackerHitCollection* hitCol,
+			  edm4hep::MCRecoTrackerAssociationCollection* assCol) override;
+  virtual StatusCode Call(edm4hep::SimTrackerHit simhit, edm4hep::TrackerHitCollection* hitCol,
+			  edm4hep::MCRecoTrackerAssociationCollection* assCol) override;
+
+  StatusCode initialize() override;
+  StatusCode finalize() override;
+  // double getPadPhi( CLHEP::Hep3Vector* thisPointRPhi, CLHEP::Hep3Vector* firstPointRPhi, CLHEP::Hep3Vector* middlePointRPhi, CLHEP::Hep3Vector* lastPointRPhi);
+  // double getPadTheta( CLHEP::Hep3Vector* firstPointRPhi, CLHEP::Hep3Vector* middlePointRPhi, CLHEP::Hep3Vector* lastPointRPhi );
+
+ private:
+
+  Gaudi::Property<std::string> m_detName{this, "DetName", "TPC"};
+  Gaudi::Property<std::string> m_readoutName{this, "Readout", "TPCCollection"};
+  
+
+  Gaudi::Property<int> _magnetic{this, "magnetic", 3};// Magnet field 3 Tesla
+  Gaudi::Property<double> _minimumTime{this, "minimumTime", 0.001};// if the time between two electrons less than this _minimumTime(us), then the two electrons will be treated as one 
+  Gaudi::Property<double> _deadTime{this, "deadTime", 300};// 
+  Gaudi::Property<int> _saveAllTime{this, "saveAllTime", 1};// 
+  Gaudi::Property<double> _ampDiffusion{this, "ampDiffusion", 0.0003}; // Amplification factor
+  Gaudi::Property<double> _MaxIonEles{this, "MaxIonEles",-1}; // Max allowed Inoized eles, negetive values mean no limits
+  Gaudi::Property<std::vector<double> > _polyParas{this, "polyParas", {3802., 0.487, 2092}};//amplification polynominal paramters
+  Gaudi::Property<double> _skipAss{this, "skipAss",1}; // Skip the mactching between digi hits and sim tracker hits
+
+
+
+
+  TF1 *_f1;
+  SmartIF<IRndmGenSvc> m_randSvc;
+  SmartIF<IGeomSvc> m_geosvc;
+  SmartIF<IGearSvc> _gear;
+  gear::GearMgr* _GEAR;
+  dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
+  const dd4hep::rec::SurfaceMap* m_surfaces;
+  double x_diffusion_p0;
+  double x_diffusion_p1;
+  double y_diffusion_p0; 
+  double y_diffusion_p1;
+  double t_diffusion_p0; 
+  double t_diffusion_p1;
+  double tpcXRes;
+  double tpcYRes;
+  double tpcZRes;
+  double tpcTRes;
+  double driftLength;
+  
+
+
+};
+#endif