diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/CMakeLists.txt b/Tracker/TrackerDigitization/FaserSCT_Digitization/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d0965e8dc9ed2520312a1eab0fc8b8cb0ead9e8a
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/CMakeLists.txt
@@ -0,0 +1,55 @@
+################################################################################
+# Package: FaserSCT_Digitization
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserSCT_Digitization )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          #Commission/CommissionEvent
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          Control/PileUpTools
+                          DetectorDescription/Identifier
+                          Event/xAOD/xAODEventInfo
+                          GaudiKernel
+                          InnerDetector/InDetConditions/InDetCondTools
+                          Tracker/TrackerDigitization/FaserSiDigitization
+                          InnerDetector/InDetRawEvent/InDetRawData
+                          Tracker/TrackerSimEvent
+                          Simulation/HitManagement
+                          PRIVATE
+                          Control/StoreGate
+                          Generators/GeneratorObjects
+                          #InnerDetector/InDetConditions/InDetConditionsSummaryService
+                          #InnerDetector/InDetConditions/SCT_ConditionsTools
+                          InnerDetector/InDetConditions/SiPropertiesTool
+                          Tracker/TrackerDetDescr/TrackerIdentifier
+                          Tracker/TrackerDetDescr/TrackerReadoutGeometry
+                          #InnerDetector/InDetDetDescr/SCT_ModuleDistortions
+                          InnerDetector/InDetRawEvent/InDetSimData )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( CLHEP )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+
+# Component(s) in the package:
+atlas_add_component( FaserSCT_Digitization
+                     src/*.cxx
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CLHEP_LIBRARIES} AthenaBaseComps AthenaKernel PileUpToolsLib Identifier xAODEventInfo GaudiKernel FaserSiDigitization InDetRawData TrackerSimEvent HitManagement GeneratorObjects SiPropertiesToolLib TrackerIdentifier TrackerReadoutGeometry InDetSimData )
+#                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CLHEP_LIBRARIES} CommissionEvent AthenaBaseComps AthenaKernel PileUpToolsLib Identifier xAODEventInfo GaudiKernel SiDigitization InDetRawData InDetSimEvent HitManagement GeneratorObjects SiPropertiesToolLib InDetIdentifier InDetReadoutGeometry InDetSimData )
+
+#atlas_add_test( SCT_DigitizationMT_test
+#                SCRIPT Digi_tf.py --inputHITSFile /cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/DigitizationTests/HITS.04919495._001041.pool.root.1 --conditionsTag default:OFLCOND-RUN12-SDR-25 --digiSeedOffset1 170 --digiSeedOffset2 170 --geometryVersion ATLAS-R2-2015-03-01-00 --DataRunNumber 222525 --outputRDOFile mc15_2015_ttbar.RDO.pool.root --preInclude HITtoRDO:SimulationJobOptions/preInclude.SCTOnlyConfig.py,Digitization/ForceUseOfAlgorithms.py --postInclude Digitization/FixDataDependenciesForMT.py --skipEvents 0  --maxEvents 100 --athenaopts=--threads=10
+#                PROPERTIES TIMEOUT 1200
+#                ENVIRONMENT THREADS=10 )
+
+# Install files from the package:
+atlas_install_headers( FaserSCT_Digitization )
+atlas_install_python_modules( python/*.py )
+atlas_install_joboptions( share/*.py )
+
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ATLAS_CHECK_THREAD_SAFETY b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..c5030c6d4ab80ea56f53ce2ea52e49acec23ed91
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+Tracker/TrackerDigitization/FaserSCT_Digitization
\ No newline at end of file
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_Amp.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_Amp.h
new file mode 100644
index 0000000000000000000000000000000000000000..267840df70550cf4cc63de8a9f5d3de8a9c86fa2
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_Amp.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISCT_Amp.h
+ * Header file for abstract base class ISCT_Amp
+ * (c) ATLAS Detector software
+ * Interface for the SiChargedDiode processor classes
+ * 23/08/2007 Kondo.Gnanvo@cern.ch, and others   
+ */
+
+#ifndef FASERSIDIGITIZATION_ISCT_AMP_H
+#define FASERSIDIGITIZATION_ISCT_AMP_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "TrackerSimEvent/SiTotalCharge.h"
+
+#include <vector>
+
+static const InterfaceID IID_ISCT_Amp("ISCT_Amp", 1, 0);
+
+class ISCT_Amp : virtual public IAlgTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+  typedef SiTotalCharge::list_t list_t;
+
+  //Retrieve interface ID
+  static const InterfaceID& interfaceID() { return IID_ISCT_Amp; }
+
+  // Destructor:
+  virtual ~ISCT_Amp() {}
+
+  ///////////////////////////////////////////////////////////////////
+  // Pure virtual methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // process the collection of charged diodes
+  /** main purpose: CR-RC^3 response to a list of charges with times */
+  virtual float response(const list_t& Charges, const float timeOverThreshold) const =0;
+  virtual void response(const list_t& Charges, const float timeOverThreshold, std::vector<float>& resp) const =0;
+
+  /** Neighbour strip cross talk response strip to a list of charges with times */
+  virtual float crosstalk(const list_t& Charges, const float timeOverThreshold) const =0;
+  virtual void crosstalk(const list_t& Charges, const float timeOverThreshold, std::vector<float> &resp) const =0;
+};
+
+#endif // FASERSIDIGITIZATION_ISCT_AMP_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_FrontEnd.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_FrontEnd.h
new file mode 100644
index 0000000000000000000000000000000000000000..35a40ddbfa4f78825dae788954202f868c527732
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_FrontEnd.h
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISCT_FrontEnd.h
+ * Header file for interface class for SCT_FrontEnd
+ * (c) ATLAS Detector software
+ */
+
+#ifndef FASERSCT_DIGITIZATION_ISCT_FRONTEND_H
+#define FASERSCT_DIGITIZATION_ISCT_FRONTEND_H
+
+//Inheritance
+#include "FaserSiDigitization/ISiChargedDiodesProcessorTool.h"
+#include "FaserSiDigitization/SiChargedDiode.h"
+
+//methods
+#include "Identifier/Identifier.h"
+class SiChargedDiodeCollection;
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+static const InterfaceID IID_ISCT_FrontEnd("ISCT_FrontEnd", 1, 0);
+
+class ISCT_FrontEnd : virtual public ISiChargedDiodesProcessorTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+  //** Retrieve interface ID */
+  static const InterfaceID& interfaceID() { return IID_ISCT_FrontEnd; }
+
+  //** Destructor: */
+  virtual ~ISCT_FrontEnd() {}
+
+};
+
+#endif // FASERSCT_DIGITIZATION_ISCT_FRONTEND_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_RandomDisabledCellGenerator.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_RandomDisabledCellGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3c69bc251a9402ca1bb6e3a02cbd2c65c45a250
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_RandomDisabledCellGenerator.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISCT_RandomDisabledCellGenerator.h
+ * Header file for interface class for SCT_RandomDisabledCellGenerator
+ * (c) ATLAS Detector software
+ */
+
+#ifndef FASERSCT_DIGITIZATION_ISCT_RANDOMDISABLEDCELLGENERATOR_H
+#define FASERSCT_DIGITIZATION_ISCT_RANDOMDISABLEDCELLGENERATOR_H
+
+//Inheritance
+#include "FaserSiDigitization/ISiChargedDiodesProcessorTool.h"
+
+//methods
+class SiChargedDiodeCollection;
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+static const InterfaceID IID_ISCT_RandomDisabledCellGenerator("ISCT_RandomDisabledCellGenerator",1,0);
+
+class ISCT_RandomDisabledCellGenerator : virtual public ISiChargedDiodesProcessorTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+  //Retrieve interface ID
+  static const InterfaceID& interfaceID() { return IID_ISCT_RandomDisabledCellGenerator; }
+
+  // Destructor:
+  virtual ~ISCT_RandomDisabledCellGenerator() {}
+
+};
+
+#endif // FASERSCT_DIGITIZATION_ISCT_RANDOMDISABLEDCELLGENERATOR_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_SurfaceChargesGenerator.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_SurfaceChargesGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9188844d716ab40eab7ff8fe924a240a0dee6a64
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/FaserSCT_Digitization/ISCT_SurfaceChargesGenerator.h
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISCT_SurfaceChargesGenerator.h
+ * Header file for abstract base class ISCT_SurfaceChargesGenerator
+ * (c) ATLAS Detector software
+ * Interface for the Sct_SurfaceCharge generator classes
+ * Version  23/08/2007 Kondo Gnanvo
+ */
+
+#ifndef FASERSCT_DIGITIZATION_ISCT_SURFACECHARGESGENERATOR_H
+#define FASERSCT_DIGITIZATION_ISCT_SURFACECHARGESGENERATOR_H
+
+// Input/output classes
+#include <list>
+#include "FaserSiDigitization/SiSurfaceCharge.h"
+#include "HitManagement/TimedHitPtr.h"
+
+#include "GaudiKernel/IAlgTool.h"
+
+class FaserSiHit;
+
+namespace TrackerDD {
+  class SiDetectorElement;
+}
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+class ISiSurfaceChargesInserter
+{
+ public:
+  virtual ~ISiSurfaceChargesInserter() {}
+  virtual void operator() (const SiSurfaceCharge& scharge) const = 0;
+};
+
+static const InterfaceID IID_ISCT_SurfaceChargesGenerator("ISCT_SurfaceChargesGenerator",1,0);
+
+class ISCT_SurfaceChargesGenerator : virtual public IAlgTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+  //Retrieve interface ID
+  static const InterfaceID& interfaceID() { return IID_ISCT_SurfaceChargesGenerator; }
+
+  // Destructor:
+  virtual ~ISCT_SurfaceChargesGenerator() {}
+
+  virtual void process(const TrackerDD::SiDetectorElement* ele,
+                       const TimedHitPtr<FaserSiHit>& phit,
+                       const ISiSurfaceChargesInserter& inserter, CLHEP::HepRandomEngine * rndmEngine) const =0;
+  virtual void setFixedTime(float fixedTime) =0;
+};
+
+#endif // FASERSCT_DIGITIZATION_ISCT_SURFACECHARGESGENERATOR_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfig.py b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..42b92ef195088b1390cbae4fd21e455f02d1151b
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfig.py
@@ -0,0 +1,297 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon import CfgMgr
+# The earliest bunch crossing time for which interactions will be sent
+# to the SCT Digitization code.
+def SCT_FirstXing():
+    return -50
+# The latest bunch crossing time for which interactions will be sent
+# to the SCT Digitization code.
+def SCT_LastXing():
+    return 25
+
+
+
+######################################################################################
+def getSCT_RandomDisabledCellGenerator(name="SCT_RandomDisabledCellGenerator", **kwargs):
+    kwargs.setdefault("TotalBadChannels", 0.01)
+    from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_RandomDisabledCellGenerator
+    return SCT_RandomDisabledCellGenerator(name, **kwargs)
+
+
+######################################################################################
+def getSCT_Amp(name="SCT_Amp", **kwargs):
+    kwargs.setdefault("CrossFactor2sides", 0.1)
+    kwargs.setdefault("CrossFactorBack", 0.07)
+    kwargs.setdefault("PeakTime", 21)
+    kwargs.setdefault("deltaT", 1.0)
+    kwargs.setdefault("Tmin", -25.0)
+    kwargs.setdefault("Tmax", 150.0)
+    from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_Amp
+    return SCT_Amp(name, **kwargs)
+
+
+######################################################################################
+def getSCT_SurfaceChargesGenerator(name="SCT_SurfaceChargesGenerator", **kwargs):
+    ## Set up services used by SCT_SurfaceChargesGenerator
+    # Set up SCT_DCSConditiosnTool
+    from SCT_ConditionsTools.SCT_DCSConditionsToolSetup import SCT_DCSConditionsToolSetup
+    sct_DCSConditionsToolSetup = SCT_DCSConditionsToolSetup()
+    sct_DCSConditionsToolSetup.setup()
+    # Set up SCT_SiliconConditionsTool
+    from SCT_ConditionsTools.SCT_SiliconConditionsToolSetup import SCT_SiliconConditionsToolSetup
+    sct_SiliconConditionsToolSetup = SCT_SiliconConditionsToolSetup()
+    sct_SiliconConditionsToolSetup.setDcsTool(sct_DCSConditionsToolSetup.getTool())
+    sct_SiliconConditionsToolSetup.setup()
+    # Set up SCT_SiPropertiesTool
+    from SiPropertiesTool.SCT_SiPropertiesToolSetup import SCT_SiPropertiesToolSetup
+    sct_SiPropertiesToolSetup = SCT_SiPropertiesToolSetup()
+    sct_SiPropertiesToolSetup.setSiliconTool(sct_SiliconConditionsToolSetup.getTool())
+    sct_SiPropertiesToolSetup.setup()
+    ## Charge trapping tool - used by SCT_SurfaceChargesGenerator
+    from AthenaCommon.AppMgr import ToolSvc
+    ## SiLorentzAngleTool for SCT_SurfaceChargesGenerator
+    from SiLorentzAngleTool.SCTLorentzAngleToolSetup import SCTLorentzAngleToolSetup
+    sctLorentzAngleToolSetup = SCTLorentzAngleToolSetup()
+
+    kwargs.setdefault("FixedTime", -999)
+    kwargs.setdefault("SubtractTime", -999)
+    kwargs.setdefault("SurfaceDriftTime", 10)
+    kwargs.setdefault("NumberOfCharges", 1)
+    kwargs.setdefault("SmallStepLength", 5)
+    kwargs.setdefault("DepletionVoltage", 70)
+    kwargs.setdefault("BiasVoltage", 150)
+    kwargs.setdefault("SiPropertiesTool", sct_SiPropertiesToolSetup.getTool())
+    kwargs.setdefault("LorentzAngleTool", sctLorentzAngleToolSetup.SCTLorentzAngleTool)
+    from AthenaCommon.GlobalFlags import globalflags
+    kwargs.setdefault("isOverlay", globalflags.isOverlay())
+
+    # kwargs.setdefault("doTrapping", True) # ATL-INDET-INT-2016-019
+
+    from Digitization.DigitizationFlags import digitizationFlags
+    if 'doDetailedSurfChargesGen' in digitizationFlags.experimentalDigi():
+        kwargs.setdefault("ChargeDriftModel", 1)
+        kwargs.setdefault("EFieldModel", 2)
+        kwargs.setdefault("MagneticField", -2.0)
+        kwargs.setdefault("SensorTemperature", 273.15)
+        kwargs.setdefault("TransportTimeStep", 0.25)
+        kwargs.setdefault("TransportTimeMax", 25.0)
+        from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_DetailedSurfaceChargesGenerator
+        return SCT_DetailedSurfaceChargesGenerator(name, **kwargs)
+    else:
+        from SCT_ConditionsTools.SCT_ConditionsToolsConf import SCT_RadDamageSummaryTool
+        kwargs.setdefault("RadDamageSummaryTool", SCT_RadDamageSummaryTool(name = "InDetSCT_RadDamageSummaryTool"))
+        from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_SurfaceChargesGenerator
+        return SCT_SurfaceChargesGenerator(name, **kwargs)
+
+######################################################################################
+def getSCT_FrontEnd(name="SCT_FrontEnd", **kwargs):
+    from Digitization.DigitizationFlags import digitizationFlags
+    #Setup noise treament in SCT_FrontEnd
+    # To set the mean noise values for the different module types
+    # Default values set at 0 degrees, plus/minus ~5 enc per plus/minus degree
+    kwargs.setdefault("NoiseBarrel", 1500.0)
+    kwargs.setdefault("NoiseBarrel3", 1541.0)
+    kwargs.setdefault("NoiseInners", 1090.0)
+    kwargs.setdefault("NoiseMiddles", 1557.0)
+    kwargs.setdefault("NoiseShortMiddles", 940.0)
+    kwargs.setdefault("NoiseOuters", 1618.0)
+    kwargs.setdefault("NOBarrel", 1.5e-5)
+    kwargs.setdefault("NOBarrel3", 2.1e-5)
+    kwargs.setdefault("NOInners", 5.0e-9)
+    kwargs.setdefault("NOMiddles", 2.7e-5)
+    kwargs.setdefault("NOShortMiddles", 2.0e-9)
+    kwargs.setdefault("NOOuters", 3.5e-5)
+    # If noise is turned off:
+    if not digitizationFlags.doInDetNoise.get_Value():
+        ###kwargs.setdefault("OnlyHitElements", True)
+        print('SCT_Digitization:::: Turned off Noise in SCT_FrontEnd')
+        kwargs.setdefault("NoiseOn", False)
+        kwargs.setdefault("AnalogueNoiseOn", False)
+    else:
+        kwargs.setdefault("NoiseOn", True)
+        kwargs.setdefault("AnalogueNoiseOn", True)
+    # In overlay MC, only analogue noise is on. Noise hits are not added.
+    from AthenaCommon.GlobalFlags import globalflags
+    if globalflags.isOverlay() and globalflags.DataSource == 'geant4':
+        kwargs["NoiseOn"] = False
+        kwargs["AnalogueNoiseOn"] = True
+    # Use Calibration data from Conditions DB, still for testing purposes only
+    kwargs.setdefault("UseCalibData", True)
+
+    # Setup the ReadCalibChip folders and Svc
+    from SCT_ConditionsTools.SCT_ReadCalibChipDataToolSetup import SCT_ReadCalibChipDataToolSetup
+    sct_ReadCalibChipDataToolSetup = SCT_ReadCalibChipDataToolSetup()
+    sct_ReadCalibChipDataToolSetup.setup()
+    kwargs.setdefault("SCT_ReadCalibChipDataTool", sct_ReadCalibChipDataToolSetup.getTool())
+    # DataCompressionMode: 1 is level mode x1x (default), 2 is edge mode 01x, 3 is expanded any hit xxx
+    from AthenaCommon.BeamFlags import jobproperties
+    if digitizationFlags.PileUpPremixing:
+        kwargs.setdefault("DataCompressionMode", 3)
+    elif globalflags.isOverlay() and globalflags.DataSource == 'geant4':
+        kwargs.setdefault("DataCompressionMode", 2)
+    elif (jobproperties.Beam.bunchSpacing() <= 50):
+        kwargs.setdefault("DataCompressionMode", 1) 
+    else: 
+        kwargs.setdefault("DataCompressionMode", 3) 
+    # DataReadOutMode: 0 is condensed mode and 1 is expanded mode
+    if globalflags.isOverlay() and globalflags.DataSource == 'geant4':
+        kwargs.setdefault("DataReadOutMode", 0)
+    else:
+        kwargs.setdefault("DataReadOutMode", 1)
+    from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_FrontEnd
+    return SCT_FrontEnd(name, **kwargs)
+
+######################################################################################
+def getPileupSCT_FrontEnd(name="PileupSCT_FrontEnd", **kwargs):
+
+    kwargs.setdefault("NoiseBarrel", 0.0)
+    kwargs.setdefault("NoiseBarrel3", 0.0)
+    kwargs.setdefault("NoiseInners", 0.0)
+    kwargs.setdefault("NoiseMiddles", 0.0)
+    kwargs.setdefault("NoiseShortMiddles", 0.0)
+    kwargs.setdefault("NoiseOuters", 0.0)
+    kwargs.setdefault("NOBarrel", 0.0)
+    kwargs.setdefault("NOBarrel3", 0.0)
+    kwargs.setdefault("NOInners", 0.0)
+    kwargs.setdefault("NOMiddles", 0.0)
+    kwargs.setdefault("NOShortMiddles", 0.0)
+    kwargs.setdefault("NOOuters", 0.0)
+    kwargs.setdefault("NoiseOn", False)
+
+    return getSCT_FrontEnd(name, **kwargs)
+
+######################################################################################
+
+
+def commonSCT_DigitizationConfig(name,**kwargs):
+
+    from Digitization.DigitizationFlags import digitizationFlags
+    # If noise is turned off:
+    if not digitizationFlags.doInDetNoise.get_Value():
+        kwargs.setdefault("OnlyHitElements", True)
+
+    kwargs.setdefault("InputObjectName", "SCT_Hits")
+    kwargs.setdefault("EnableHits", True)
+    kwargs.setdefault("BarrelOnly", False)
+
+    # Use of random disabled cells
+    #kwargs.setdefault("RandomDisabledCells", True)
+
+    # Set FixedTime for cosmics for use in SurfaceChargesGenerator
+    from AthenaCommon.BeamFlags import jobproperties
+    if jobproperties.Beam.beamType == "cosmics" :
+        kwargs.setdefault("CosmicsRun", True)
+        kwargs.setdefault("FixedTime", 10)
+
+    # write out SCT1_RawData
+    #kwargs.setdefault("WriteSCT1_RawData", False)
+
+    if digitizationFlags.doXingByXingPileUp():
+        kwargs.setdefault("FirstXing", SCT_FirstXing())
+        kwargs.setdefault("LastXing",  SCT_LastXing() )
+
+    from AthenaCommon import CfgMgr
+    return CfgMgr.SCT_DigitizationTool(name,**kwargs)
+#    else:
+#        from AthenaCommon import CfgMgr
+#        return CfgMgr.SCT_Digitization(name, **kwargs)
+
+######################################################################################
+
+def SCT_DigitizationTool(name="SCT_DigitizationTool", **kwargs):
+    from Digitization.DigitizationFlags import digitizationFlags
+    if digitizationFlags.PileUpPremixing and 'OverlayMT' in digitizationFlags.experimentalDigi():
+        from OverlayCommonAlgs.OverlayFlags import overlayFlags
+        kwargs.setdefault("OutputObjectName", overlayFlags.bkgPrefix() + "SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", overlayFlags.bkgPrefix() + "SCT_SDO_Map")
+    else:
+        kwargs.setdefault("OutputObjectName", "SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", "SCT_SDO_Map")
+
+    kwargs.setdefault("HardScatterSplittingMode", 0)
+    return commonSCT_DigitizationConfig(name,**kwargs)
+
+######################################################################################
+
+def SCT_GeantinoTruthDigitizationTool(name="SCT_GeantinoTruthDigitizationTool", **kwargs):
+    kwargs.setdefault("ParticleBarcodeVeto", 0)
+    return SCT_DigitizationTool(name,**kwargs)
+
+######################################################################################
+
+def SCT_DigitizationToolHS(name="SCT_DigitizationToolHS",**kwargs):
+    kwargs.setdefault("OutputObjectName", "SCT_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_SDO_Map")
+    kwargs.setdefault("HardScatterSplittingMode", 1)
+    return commonSCT_DigitizationConfig(name,**kwargs)
+
+######################################################################################
+
+def SCT_DigitizationToolPU(name="SCT_DigitizationToolPU",**kwargs):
+    kwargs.setdefault("OutputObjectName", "SCT_PU_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_PU_SDO_Map")
+    kwargs.setdefault("HardScatterSplittingMode", 2)
+    return commonSCT_DigitizationConfig(name,**kwargs)
+
+######################################################################################
+
+def SCT_DigitizationToolSplitNoMergePU(name="SCT_DigitizationToolSplitNoMergePU",**kwargs):
+
+    kwargs.setdefault("InputObjectName", "PileupSCT_Hits")
+    kwargs.setdefault("HardScatterSplittingMode", 0)
+    kwargs.setdefault("OutputObjectName", "SCT_PU_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_PU_SDO_Map")
+    kwargs.setdefault("OnlyHitElements", True)
+    kwargs.setdefault("FrontEnd", "PileupSCT_FrontEnd")
+
+    return commonSCT_DigitizationConfig(name,**kwargs)
+
+######################################################################################
+
+def SCT_OverlayDigitizationTool(name="SCT_OverlayDigitizationTool",**kwargs):
+    from OverlayCommonAlgs.OverlayFlags import overlayFlags
+    if overlayFlags.isOverlayMT():
+        kwargs.setdefault("OnlyUseContainerName", False)
+        kwargs.setdefault("OutputObjectName", overlayFlags.sigPrefix() + "SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", overlayFlags.sigPrefix() + "SCT_SDO_Map")
+    else:
+        kwargs.setdefault("OutputObjectName", overlayFlags.evtStore() + "+SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", overlayFlags.evtStore() + "+SCT_SDO_Map")
+    kwargs.setdefault("HardScatterSplittingMode", 0)
+    return commonSCT_DigitizationConfig(name,**kwargs)
+
+######################################################################################
+
+def getSiliconRange(name="SiliconRange" , **kwargs):
+    #this is the time of the xing in ns
+    kwargs.setdefault('FirstXing', SCT_FirstXing() )
+    kwargs.setdefault('LastXing',  SCT_LastXing()  )
+    kwargs.setdefault('CacheRefreshFrequency', 1.0 ) #default 0 no dataproxy reset
+    kwargs.setdefault('ItemList', ["SiHitCollection#SCT_Hits"] )
+    return CfgMgr.PileUpXingFolder(name, **kwargs)
+
+######################################################################################
+
+def SCT_DigitizationHS(name="SCT_DigitizationHS",**kwargs):
+    kwargs.setdefault("DigitizationTool", "SCT_DigitizationToolHS")
+    from FaserSCT_Digitization.FaserSCT_DigitizationConf import SCT_Digitization
+    return SCT_Digitization(name,**kwargs)
+
+######################################################################################
+
+def SCT_DigitizationPU(name="SCT_DigitizationPU",**kwargs):
+    kwargs.setdefault("DigitizationTool", "SCT_DigitizationToolPU")
+    return CfgMgr.SCT_Digitization(name,**kwargs)
+
+######################################################################################
+
+def SCT_OverlayDigitization(name="SCT_OverlayDigitization",**kwargs):
+    kwargs.setdefault("DigitizationTool", "SCT_OverlayDigitizationTool")
+    # Multi-threading settinggs
+    from AthenaCommon.ConcurrencyFlags import jobproperties as concurrencyProps
+    is_hive = (concurrencyProps.ConcurrencyFlags.NumThreads() > 0)
+    if is_hive:
+        kwargs.setdefault('Cardinality', concurrencyProps.ConcurrencyFlags.NumThreads())
+
+    return CfgMgr.SCT_Digitization(name,**kwargs)
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigDb.py b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigDb.py
new file mode 100644
index 0000000000000000000000000000000000000000..11d8480f3c69a0e2c8e0b93a1844e522b24443e1
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigDb.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.CfgGetter import addTool,addService,addAlgorithm
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationTool"          , "SCT_DigitizationTool")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_GeantinoTruthDigitizationTool"          , "SCT_GeantinoTruthDigitizationTool")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationToolHS"        , "SCT_DigitizationToolHS")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationToolPU"        , "SCT_DigitizationToolPU")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationToolSplitNoMergePU", "SCT_DigitizationToolSplitNoMergePU")
+addAlgorithm("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationHS"       , "SCT_DigitizationHS")
+addAlgorithm("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_DigitizationPU"       , "SCT_DigitizationPU")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getSiliconRange"               , "SiliconRange" )
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getSCT_RandomDisabledCellGenerator", "SCT_RandomDisabledCellGenerator")
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getSCT_Amp", "SCT_Amp" )
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getSCT_FrontEnd"               , "SCT_FrontEnd" )
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getPileupSCT_FrontEnd"         , "PileupSCT_FrontEnd" )
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.getSCT_SurfaceChargesGenerator", "SCT_SurfaceChargesGenerator" )
+addTool("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_OverlayDigitizationTool", "SCT_OverlayDigitizationTool")
+addAlgorithm("FaserSCT_Digitization.FaserSCT_DigitizationConfig.SCT_OverlayDigitization", "SCT_OverlayDigitization")
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigNew.py b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigNew.py
new file mode 100644
index 0000000000000000000000000000000000000000..92b74cad966602cd7e9b9046cba428534805f7fd
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/python/FaserSCT_DigitizationConfigNew.py
@@ -0,0 +1,305 @@
+"""Define methods to construct configured SCT Digitization tools and algorithms
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from AthenaCommon.Logging import logging
+from FaserSCT_Digitization.FaserSCT_DigitizationConf import (
+    SCT_RandomDisabledCellGenerator,
+    SCT_Amp,
+    SCT_SurfaceChargesGenerator,
+    SCT_FrontEnd,
+    SCT_DigitizationTool,
+    SCT_Digitization,
+)
+PileUpXingFolder=CompFactory.PileUpXingFolder
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+#SCT_RadDamageSummaryTool=CompFactory.SCT_RadDamageSummaryTool
+from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg
+from SCT_ConditionsTools.SCT_DCSConditionsConfig import SCT_DCSConditionsCfg
+from SCT_ConditionsTools.SCT_SiliconConditionsConfig import SCT_SiliconConditionsToolCfg, SCT_SiliconConditionsCfg
+from SCT_ConditionsTools.SCT_ReadCalibChipDataConfig import SCT_ReadCalibChipDataCfg
+from SiPropertiesTool.SCT_SiPropertiesConfig import SCT_SiPropertiesCfg
+from SiLorentzAngleTool.SCT_LorentzAngleConfig import SCT_LorentzAngleCfg
+from Digitization.TruthDigitizationOutputConfig import TruthDigitizationOutputCfg
+from Digitization.PileUpToolsConfig import PileUpToolsCfg
+
+
+# The earliest and last bunch crossing times for which interactions will be sent
+# to the SCT Digitization code
+def SCT_FirstXing():
+    return -50
+
+
+def SCT_LastXing():
+    return 25
+
+
+def SCT_DigitizationCommonCfg(flags, name="SCT_DigitizationToolCommon", **kwargs):
+    """Return ComponentAccumulator with common SCT digitization tool config"""
+    acc = FaserSCT_GeometryCfg(flags)
+    if not flags.Digitization.DoInnerDetectorNoise:
+        kwargs.setdefault("OnlyHitElements", True)
+    kwargs.setdefault("InputObjectName", "SCT_Hits")
+    kwargs.setdefault("EnableHits", True)
+    #kwargs.setdefault("BarrelOnly", False)
+    # Set FixedTime for cosmics for use in SurfaceChargesGenerator
+    if flags.Beam.Type == "cosmics":
+        kwargs.setdefault("CosmicsRun", True)
+        kwargs.setdefault("FixedTime", 10)
+    if flags.Digitization.DoXingByXingPileUp:
+        kwargs.setdefault("FirstXing", SCT_FirstXing())
+        kwargs.setdefault("LastXing", SCT_LastXing() )
+    tool = SCT_DigitizationTool(name, **kwargs)
+    # attach ToolHandles
+    tool.FrontEnd = acc.popToolsAndMerge(SCT_FrontEndCfg(flags))
+    tool.SurfaceChargesGenerator = acc.popToolsAndMerge(SCT_SurfaceChargesGeneratorCfg(flags))
+    tool.RandomDisabledCellGenerator = SCT_RandomDisabledCellGeneratorCfg(flags)
+    acc.setPrivateTools(tool)
+    return acc
+
+
+def SCT_DigitizationToolCfg(flags, name="SCT_DigitizationTool", **kwargs):
+    """Return ComponentAccumulator with configured SCT digitization tool"""
+    if flags.Digitization.PileUpPremixing:
+        kwargs.setdefault("OutputObjectName", flags.Overlay.BkgPrefix + "SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", flags.Overlay.BkgPrefix + "SCT_SDO_Map")
+    else:
+        kwargs.setdefault("OutputObjectName", "SCT_RDOs")
+        kwargs.setdefault("OutputSDOName", "SCT_SDO_Map")
+    #kwargs.setdefault("HardScatterSplittingMode", 0)
+    return SCT_DigitizationCommonCfg(flags, name, **kwargs)
+
+
+def SCT_DigitizationHSToolCfg(flags, name="SCT_DigitizationHSTool", **kwargs):
+    """Return ComponentAccumulator with hard scatter configured SCT digitization tool"""
+    kwargs.setdefault("OutputObjectName", "SCT_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_SDO_Map")
+    #kwargs.setdefault("HardScatterSplittingMode", 1)
+    return SCT_DigitizationCommonCfg(flags, name, **kwargs)
+
+
+def SCT_DigitizationPUToolCfg(flags, name="SCT_DigitizationPUTool",**kwargs):
+    """Return ComponentAccumulator with pileup configured SCT digitization tool"""
+    kwargs.setdefault("OutputObjectName", "SCT_PU_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_PU_SDO_Map")
+    #kwargs.setdefault("HardScatterSplittingMode", 2)
+    return SCT_DigitizationCommonCfg(flags, name, **kwargs)
+
+
+def SCT_OverlayDigitizationToolCfg(flags, name="SCT_OverlayDigitizationTool",**kwargs):
+    """Return ComponentAccumulator with overlay configured SCT digitization tool"""
+    acc = ComponentAccumulator()
+    kwargs.setdefault("OnlyUseContainerName", False)
+    kwargs.setdefault("OutputObjectName", "StoreGateSvc+" + flags.Overlay.SigPrefix + "SCT_RDOs")
+    kwargs.setdefault("OutputSDOName", "StoreGateSvc+" + flags.Overlay.SigPrefix + "SCT_SDO_Map")
+    #kwargs.setdefault("HardScatterSplittingMode", 0)
+    tool = acc.popToolsAndMerge(SCT_DigitizationCommonCfg(flags, name, **kwargs))
+    acc.setPrivateTools(tool)
+    return acc
+
+
+def SCT_DigitizationToolSplitNoMergePUCfg(flags, name="SCT_DigitizationToolSplitNoMergePU",**kwargs):
+    """Return ComponentAccumulator with merged pileup configured SCT digitization tool"""
+    kwargs.setdefault("InputObjectName", "PileupSCT_Hits")
+    #kwargs.setdefault("HardScatterSplittingMode", 0)
+    kwargs.setdefault("OutputObjectName", "SCT_PU_RDOs")
+    kwargs.setdefault("OutputSDOName", "SCT_PU_SDO_Map")
+    kwargs.setdefault("OnlyHitElements", True)
+    kwargs.setdefault("FrontEnd", "PileupSCT_FrontEnd")
+    return SCT_DigitizationCommonCfg(flags, name, **kwargs)
+
+
+def SCT_DigitizationToolGeantinoTruthCfg(flags, name="SCT_GeantinoTruthDigitizationTool", **kwargs):
+    """Return Geantino truth configured digitization tool"""
+    kwargs.setdefault("ParticleBarcodeVeto", 0)
+    return SCT_DigitizationToolCfg(flags, name, **kwargs)
+
+
+def SCT_RandomDisabledCellGeneratorCfg(flags, name="SCT_RandomDisabledCellGenerator", **kwargs):
+    """Return configured random cell disabling tool"""
+    kwargs.setdefault("TotalBadChannels", 0.01)
+    return SCT_RandomDisabledCellGenerator(name, **kwargs)
+
+
+def SCT_AmpCfg(flags, name="SCT_Amp", **kwargs):
+    """Return configured amplifier and shaper tool"""
+    kwargs.setdefault("CrossFactor2sides", 0.1)
+    kwargs.setdefault("CrossFactorBack", 0.07)
+    kwargs.setdefault("PeakTime", 21)
+    kwargs.setdefault("deltaT", 1.0)
+    kwargs.setdefault("Tmin", -25.0)
+    kwargs.setdefault("Tmax", 150.0)
+    return SCT_Amp(name, **kwargs)
+
+
+def SCT_SurfaceChargesGeneratorCfg(flags, name="SCT_SurfaceChargesGenerator", **kwargs):
+    """Return ComponentAccumulator with configured surface charges tool"""
+    acc = ComponentAccumulator()
+    kwargs.setdefault("FixedTime", -999)
+    kwargs.setdefault("SubtractTime", -999)
+    kwargs.setdefault("SurfaceDriftTime", 10)
+    kwargs.setdefault("NumberOfCharges", 1)
+    kwargs.setdefault("SmallStepLength", 5)
+    kwargs.setdefault("DepletionVoltage", 70)
+    kwargs.setdefault("BiasVoltage", 150)
+    kwargs.setdefault("isOverlay", flags.Detector.Overlay)
+    # kwargs.setdefault("doTrapping", True) # ATL-INDET-INT-2016-019
+    # experimental SCT_DetailedSurfaceChargesGenerator config dropped here
+    tool = SCT_SurfaceChargesGenerator(name, **kwargs)
+    #tool.RadDamageSummaryTool = SCT_RadDamageSummaryTool()
+    DCSCondTool = acc.popToolsAndMerge(SCT_DCSConditionsCfg(flags))
+    SiliCondTool = SCT_SiliconConditionsToolCfg(flags)
+    SiliCondAcc = SCT_SiliconConditionsCfg(flags, DCSConditionsTool=DCSCondTool)
+    SiliPropsAcc = SCT_SiPropertiesCfg(flags, SiConditionsTool=SiliCondTool)
+    acc.merge(SiliCondAcc)
+    #tool.SiConditionsTool = SiliCondTool
+    tool.SiPropertiesTool = acc.popToolsAndMerge(SiliPropsAcc)
+    tool.LorentzAngleTool = acc.popToolsAndMerge(SCT_LorentzAngleCfg(flags))
+    acc.setPrivateTools(tool)
+    return acc
+
+
+def SCT_FrontEndCfg(flags, name="SCT_FrontEnd", **kwargs):
+    """Return ComponentAccumulator with configured front-end electronics tool"""
+    # Setup noise treament in SCT_FrontEnd
+    # To set the mean noise values for the different module types
+    # Default values set at 0 degrees, plus/minus ~5 enc per plus/minus degree
+    kwargs.setdefault("NoiseBarrel", 1500.0)
+    kwargs.setdefault("NoiseBarrel3", 1541.0)
+    kwargs.setdefault("NoiseInners", 1090.0)
+    kwargs.setdefault("NoiseMiddles", 1557.0)
+    kwargs.setdefault("NoiseShortMiddles", 940.0)
+    kwargs.setdefault("NoiseOuters", 1618.0)
+    kwargs.setdefault("NOBarrel", 1.5e-5)
+    kwargs.setdefault("NOBarrel3", 2.1e-5)
+    kwargs.setdefault("NOInners", 5.0e-9)
+    kwargs.setdefault("NOMiddles", 2.7e-5)
+    kwargs.setdefault("NOShortMiddles", 2.0e-9)
+    kwargs.setdefault("NOOuters", 3.5e-5)
+    if not flags.Digitization.DoInnerDetectorNoise:
+        log = logging.getLogger("SCT_FrontEndCfg")
+        log.info("SCT_Digitization:::: Turned off Noise in SCT_FrontEnd")
+        kwargs.setdefault("NoiseOn", False)
+        kwargs.setdefault("AnalogueNoiseOn", False)
+    else:
+        kwargs.setdefault("NoiseOn", True)
+        kwargs.setdefault("AnalogueNoiseOn", True)
+    # In overlay MC, only analogue noise is on. Noise hits are not added.
+    if flags.Detector.Overlay and flags.Input.isMC:
+        kwargs["NoiseOn"] = False
+        kwargs["AnalogueNoiseOn"] = True
+    # Use Calibration data from Conditions DB, still for testing purposes only
+    kwargs.setdefault("UseCalibData", True)
+    # Setup the ReadCalibChip folders and Svc
+    acc = SCT_ReadCalibChipDataCfg(flags)
+    garbage = acc.popPrivateTools()
+    #kwargs.setdefault("SCT_ReadCalibChipDataTool", acc.popPrivateTools())
+    # DataCompressionMode: 1 is level mode x1x (default), 2 is edge mode 01x, 3 is expanded any hit xxx
+    if flags.Digitization.PileUpPremixing:
+        kwargs.setdefault("DataCompressionMode", 3)
+    elif flags.Detector.Overlay and flags.Input.isMC:
+        kwargs.setdefault("DataCompressionMode", 2)
+    elif flags.Beam.BunchSpacing <= 50:
+        kwargs.setdefault("DataCompressionMode", 1)
+    else:
+        kwargs.setdefault("DataCompressionMode", 3)
+    # DataReadOutMode: 0 is condensed mode and 1 is expanded mode
+    if flags.Detector.Overlay and flags.Input.isMC:
+        kwargs.setdefault("DataReadOutMode", 0)
+    else:
+        kwargs.setdefault("DataReadOutMode", 1)
+    acc.setPrivateTools(SCT_FrontEnd(name, **kwargs))
+    return acc
+
+
+def SCT_FrontEndPileupCfg(flags, name="PileupSCT_FrontEnd", **kwargs):
+    """Return ComponentAccumulator with pileup-configured front-end electronics tool"""
+    kwargs.setdefault("NoiseBarrel", 0.0)
+    kwargs.setdefault("NoiseBarrel3", 0.0)
+    kwargs.setdefault("NoiseInners", 0.0)
+    kwargs.setdefault("NoiseMiddles", 0.0)
+    kwargs.setdefault("NoiseShortMiddles", 0.0)
+    kwargs.setdefault("NoiseOuters", 0.0)
+    kwargs.setdefault("NOBarrel", 0.0)
+    kwargs.setdefault("NOBarrel3", 0.0)
+    kwargs.setdefault("NOInners", 0.0)
+    kwargs.setdefault("NOMiddles", 0.0)
+    kwargs.setdefault("NOShortMiddles", 0.0)
+    kwargs.setdefault("NOOuters", 0.0)
+    kwargs.setdefault("NoiseOn", False)
+    return SCT_FrontEndCfg(flags, name, **kwargs)
+
+def SCT_RangeCfg(flags, name="SiliconRange", **kwargs):
+    """Return an SCT configured PileUpXingFolder tool"""
+    kwargs.setdefault("FirstXing", SCT_FirstXing())
+    kwargs.setdefault("LastXing", SCT_LastXing())
+    kwargs.setdefault("CacheRefreshFrequency", 1.0) # default 0 no dataproxy reset
+    kwargs.setdefault("ItemList", ["FaserSiHitCollection#SCT_Hits"] )
+    return PileUpXingFolder(name, **kwargs)
+
+
+def SCT_OutputCfg(flags):
+    """Return ComponentAccumulator with Output for SCT. Not standalone."""
+    acc = ComponentAccumulator()
+    ItemList = ["SCT_RDO_Container#*"]
+    if flags.Digitization.TruthOutput:
+        ItemList += ["InDetSimDataCollection#*"]
+        acc.merge(TruthDigitizationOutputCfg(flags))
+    acc.merge(OutputStreamCfg(flags, "RDO", ItemList))
+    return acc
+
+
+def SCT_DigitizationBasicCfg(flags, **kwargs):
+    """Return ComponentAccumulator for SCT digitization"""
+    acc = ComponentAccumulator()
+    if "PileUpTools" not in kwargs:
+        PileUpTools = acc.popToolsAndMerge(SCT_DigitizationToolCfg(flags))
+        kwargs["PileUpTools"] = PileUpTools
+    acc.merge(PileUpToolsCfg(flags, **kwargs))
+    return acc
+
+
+def SCT_OverlayDigitizationBasicCfg(flags, **kwargs):
+    """Return ComponentAccumulator with SCT Overlay digitization"""
+    acc = ComponentAccumulator()
+    if "DigitizationTool" not in kwargs:
+        tool = acc.popToolsAndMerge(SCT_OverlayDigitizationToolCfg(flags))
+        kwargs["DigitizationTool"] = tool
+    acc.addEventAlgo(SCT_Digitization(**kwargs))
+    return acc
+
+
+# with output defaults
+def SCT_DigitizationCfg(flags, **kwargs):
+    """Return ComponentAccumulator for SCT digitization and Output"""
+    acc = SCT_DigitizationBasicCfg(flags, **kwargs)
+    acc.merge(SCT_OutputCfg(flags))
+    return acc
+
+
+def SCT_OverlayDigitizationCfg(flags, **kwargs):
+    """Return ComponentAccumulator with SCT Overlay digitization and Output"""
+    acc = SCT_OverlayDigitizationBasicCfg(flags, **kwargs)
+    acc.merge(SCT_OutputCfg(flags))
+    return acc
+
+
+# additional specialisations
+def SCT_DigitizationHSCfg(flags, name="SCT_DigitizationHS", **kwargs):
+    """Return ComponentAccumulator for Hard-Scatter-only SCT digitization and Output"""
+    acc = SCT_DigitizationHSToolCfg(flags)
+    kwargs["PileUpTools"] = acc.popPrivateTools()
+    acc = SCT_DigitizationBasicCfg(flags, name=name, **kwargs)
+    acc.merge(SCT_OutputCfg(flags))
+    return acc
+
+
+def SCT_DigitizationPUCfg(flags, name="SCT_DigitizationPU", **kwargs):
+    """Return ComponentAccumulator with Pile-up-only SCT digitization and Output"""
+    acc = SCT_DigitizationPUToolCfg(flags)
+    kwargs["PileUpTools"] = acc.popPrivateTools()
+    acc = SCT_DigitizationBasicCfg(flags, name=name, **kwargs)
+    acc.merge(SCT_OutputCfg(flags))
+    return acc
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..22352b26451489fee9f36c56a1a5c756397942ec
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.cxx
@@ -0,0 +1,143 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_Amp.h"
+
+// CLHEP
+#include "CLHEP/Units/SystemOfUnits.h"
+
+//STD includes
+#include <cmath>
+#include <fstream>
+
+//#define SCT_DIG_DEBUG
+
+// constructor
+SCT_Amp::SCT_Amp(const std::string& type, const std::string& name, const IInterface* parent) 
+  : base_class(type, name, parent)
+{
+}
+
+//----------------------------------------------------------------------
+// Initialize
+//----------------------------------------------------------------------
+StatusCode SCT_Amp::initialize() {
+  
+  StatusCode sc{AthAlgTool::initialize()};
+  if (sc.isFailure()) {
+    ATH_MSG_FATAL("SCT_Amp::initialize() failed");
+    return sc;
+  }
+  ATH_MSG_DEBUG("SCT_Amp::initialize()");
+
+  /** CHLEP Units */
+  m_PeakTime.setValue(m_PeakTime.value() * CLHEP::ns);
+  m_dt.setValue(m_dt.value() * CLHEP::ns);
+  m_tmin.setValue(m_tmin.value() * CLHEP::ns);
+  m_tmax.setValue(m_tmax.value() * CLHEP::ns);
+
+  m_NormConstCentral = (exp(3.0)/27.0)*(1.0-m_CrossFactor2sides)*(1.0-m_CrossFactorBack);
+  m_NormConstNeigh = exp(3.0-sqrt(3.0))/(6*(2.0*sqrt(3.0)-3.0));
+  m_NormConstNeigh *= (m_CrossFactor2sides/2.0)*(1.0-m_CrossFactorBack);
+
+#ifdef SCT_DIG_DEBUG
+  ATH_MSG_INFO("\tAmp created, PeakTime = " << m_PeakTime);
+  ATH_MSG_INFO("\tResponse will be CR-RC^3 with tp = " << m_PeakTime/3.0);
+  ATH_MSG_INFO("\tCoupling to both neighbours = " << m_CrossFactor2sides);
+  ATH_MSG_INFO("\tCoupling to backplane = " << m_CrossFactorBack);
+  ATH_MSG_INFO("\tNormalization for central " << m_NormConstCentral);
+  ATH_MSG_INFO("\tNormalization for neighbour " << m_NormConstNeigh);
+#endif
+
+  return sc;
+}
+
+//----------------------------------------------------------------------
+// Finalize 
+//----------------------------------------------------------------------
+StatusCode SCT_Amp::finalize() {
+  StatusCode sc{AthAlgTool::finalize()};
+  if (sc.isFailure()) {
+    ATH_MSG_FATAL("SCT_Amp::finalize() failed");
+    return sc;
+  }
+  ATH_MSG_DEBUG("SCT_Amp::finalize()");
+  return sc;
+}
+
+//----------------------------------------------------------------------
+// Electronique response is now CR-RC^3 of the charge diode
+//----------------------------------------------------------------------
+float SCT_Amp::response(const list_t& Charges, const float timeOfThreshold) const {
+  float resp{0.0};
+  float tp{static_cast<float>(m_PeakTime/3.0)}; // for CR-RC^3
+  for (const SiCharge& charge: Charges) {
+    float ch{static_cast<float>(charge.charge())};
+    float tC{static_cast<float>(timeOfThreshold - charge.time())};
+    if (tC > 0.0) {
+      tC/=tp; //to avoid doing it four times
+      resp += ch*tC*tC*tC*exp(-tC); //faster than pow
+    }
+  }
+  return resp*m_NormConstCentral;
+}
+
+void SCT_Amp::response(const list_t& Charges, const float timeOfThreshold, std::vector<float>& response) const {
+  short bin_max{static_cast<short>(response.size())};
+  std::fill(response.begin(), response.end(), 0.0);
+  float tp{static_cast<float>(m_PeakTime/3.0)}; // for CR-RC^3
+  for (const SiCharge& charge: Charges) {
+    float ch{static_cast<float>(charge.charge())};
+    float ch_time{static_cast<float>(charge.time())};
+    short bin_end{static_cast<short>(bin_max-1)};
+    for (short bin{-1}; bin<bin_end; ++bin) {
+      float bin_timeOfThreshold{timeOfThreshold + bin*25};//25, fix me
+      float tC{bin_timeOfThreshold - ch_time};
+      if (tC > 0.0) {
+        tC/=tp; //to avoid doing it four times
+        response[bin+1] += ch*tC*tC*tC*exp(-tC); //faster than pow
+      }
+    }
+  }
+  for (short bin{0}; bin<bin_max; ++bin) response[bin] = response[bin]*m_NormConstCentral;
+  return;
+}
+
+//----------------------------------------------------------------------
+// differenciated and scaled pulse on the neighbour strip! 
+//----------------------------------------------------------------------
+float SCT_Amp::crosstalk(const list_t& Charges, const float timeOfThreshold) const {
+  float resp{0};
+  float tp{static_cast<float>(m_PeakTime/3.0)}; // for CR-RC^3
+  for (const SiCharge& charge: Charges) {
+    float ch{static_cast<float>(charge.charge())};
+    float tC{static_cast<float>(timeOfThreshold - charge.time())};
+    if (tC > 0.0) {
+      tC/=tp; //to avoid doing it four times
+      resp += ch*tC*tC*exp(-tC)*(3.0-tC); //faster than pow
+    }
+  }
+  return resp*m_NormConstNeigh;
+}
+
+void SCT_Amp::crosstalk(const list_t& Charges, const float timeOfThreshold, std::vector<float>& response) const {
+  short bin_max{static_cast<short>(response.size())};
+  std::fill(response.begin(), response.end(), 0.0);
+  float tp{static_cast<float>(m_PeakTime/3.0)}; // for CR-RC^3
+  for (const SiCharge& charge: Charges) {
+    float ch{static_cast<float>(charge.charge())};
+    float ch_time{static_cast<float>(charge.time())};
+    short bin_end{static_cast<short>(bin_max-1)};
+    for (short bin{-1}; bin<bin_end; ++bin) {
+      float bin_timeOfThreshold{timeOfThreshold + bin*25}; // 25, fix me
+      float tC{bin_timeOfThreshold - ch_time};
+      if (tC > 0.0) {
+        tC/=tp; //to avoid doing it four times
+        response[bin+1] += ch*tC*tC*exp(-tC)*(3.0-tC); //faster than pow
+      }
+    }
+  }
+  for (short bin{0}; bin<bin_max; ++bin) response[bin] = response[bin]*m_NormConstNeigh;
+  return;
+}
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.h
new file mode 100644
index 0000000000000000000000000000000000000000..d066e194758804bcce453f97b8b11522831b9aa6
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Amp.h
@@ -0,0 +1,69 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ *  Header file for SCT_Amp Class  
+ *  @brief A class to model an SCT amplifier and shaper. Gives a CRRC response to a 
+ *  list of charges with times. Also calculates average input and output for 
+ *  diagnostic purposes. Questions/comments to Szymon.Gadomski@cern.ch
+ *  Name changed from SCTpreamp (misleading) on 09.05.01. 
+ *  @author Szymon.Gadomski@cern.ch, Awatif.Belymam@cern.ch, Davide.Costanzo@cern.ch,
+ *  tgcornel@nikhef.nl, Grant.Gorfine@cern.ch, Paul.Bell@cern.ch, Jorgen.Dalmau@cern.ch, 
+ * 23/08/2007 - Kondo.Gnanvo@cern.ch 
+ *            - Conversion of the SCT_Amp code AlgTool 
+ */
+
+#ifndef FASERSCT_DIGITIZATION_SCTAMP_H
+#define FASERSCT_DIGITIZATION_SCTAMP_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FaserSCT_Digitization/ISCT_Amp.h"
+
+#include "TrackerSimEvent/SiCharge.h"
+
+class SCT_Amp : public extends<AthAlgTool, ISCT_Amp> {
+ public:
+
+  /**  constructor */
+  SCT_Amp(const std::string& type, const std::string& name, const IInterface* parent);
+  /** Destructor */
+  virtual ~SCT_Amp() = default;
+  /** AlgTool initialize */
+  virtual StatusCode initialize() override;
+  /** AlgTool finalize */
+  virtual StatusCode finalize() override;
+   
+  /** main purpose: CR-RC^3 response to a list of charges with times */
+  virtual float response(const list_t& Charges, const float timeOverThreshold) const override;
+  virtual void response(const list_t& Charges, const float timeOverThreshold, std::vector<float>& resp) const override;
+
+  /** Neighbour strip cross talk response strip to a list of charges with times */
+  virtual float crosstalk(const list_t& Charges, const float timeOverThreshold) const override;
+  virtual void crosstalk(const list_t& Charges, const float timeOverThreshold, std::vector<float>& resp) const override;
+
+private:
+
+  /** signal peak time */   
+  FloatProperty m_PeakTime{this, "PeakTime", 21., "Front End Electronics peaking time"};
+
+  /** Cross factor 2 side */
+  FloatProperty m_CrossFactor2sides{this, "CrossFactor2sides", 0.1, "Loss of charge to neighbour strip constant"};
+
+  /** cross factor */
+  FloatProperty m_CrossFactorBack{this, "CrossFactorBack", 0.07, "Loss of charge to back plane constant"};
+
+  FloatProperty m_tmin{this, "Tmin", -25.0};
+  FloatProperty m_tmax{this, "Tmax", 150.0};
+  FloatProperty m_dt{this, "deltaT", 1.0};
+
+  /** Normalisation factor for the signal response */
+  float m_NormConstCentral{0.};
+
+  /** Normalisation factor for the neighbour strip signal response */
+  float m_NormConstNeigh{0.};
+};
+
+#endif // FASERSCT_DIGITIZATION_SCTAMP_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f30bbd62b14fd201ca98a739de49894bafe9c6bc
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.cxx
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_Digitization.h"
+#include "PileUpTools/IPileUpTool.h"
+
+//----------------------------------------------------------------------
+// Constructor with parameters:
+//----------------------------------------------------------------------
+SCT_Digitization::SCT_Digitization(const std::string& name, ISvcLocator* pSvcLocator) :
+  AthAlgorithm(name, pSvcLocator)
+{
+}
+
+//----------------------------------------------------------------------
+// Initialize method:
+//----------------------------------------------------------------------
+StatusCode SCT_Digitization::initialize() {
+  ATH_MSG_DEBUG("SCT_Digitization::initialize()");
+  return StatusCode::SUCCESS ;
+}
+
+//----------------------------------------------------------------------
+// Execute method:
+//----------------------------------------------------------------------
+
+StatusCode SCT_Digitization::execute() {
+  ATH_MSG_DEBUG("execute()");
+  return m_sctDigitizationTool->processAllSubEvents();
+}
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f32cdf0734f555ef6e64b1b476c07218201a534
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_Digitization.h
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/** @file SCT_Digitization.h  Header file for SCT_Digitization class.
+ *  @author Szymon.Gadomski@cern.ch, Awatif.Belymam@cern.ch, Davide.Costanzo@cern.ch,
+ *          tgcornel@nikhef.nl, Grant.Gorfine@cern.ch, Paul.Bell@cern.ch,
+ *          Jorgen.Dalmau@cern.ch, Kondo.Gnanvo@cern.ch, and others
+ * Version 23/08/2007 Kondo.Gnanvo@cern.ch
+ *          Conversion of the processors into AlgTool
+ */
+
+// Multiple inclusion protection
+#ifndef FASERSCT_DIGITIZATION_SCT_DIGITIZATION_H
+#define FASERSCT_DIGITIZATION_SCT_DIGITIZATION_H
+
+// Base class
+#include "AthenaBaseComps/AthAlgorithm.h"
+// Gaudi
+#include "GaudiKernel/ToolHandle.h"
+
+class IPileUpTool;
+
+/** Top algorithm class for SCT digitization */
+class SCT_Digitization : public AthAlgorithm {
+
+ public:
+
+  /** Constructor with parameters */
+  SCT_Digitization(const std::string& name, ISvcLocator* pSvcLocator);
+
+  /** Destructor */
+  virtual ~SCT_Digitization() = default;
+
+  /** Basic algorithm methods */
+  virtual StatusCode initialize() override final;
+  virtual StatusCode execute() override final;
+  virtual bool isClonable() const override final { return true; }
+
+ private:
+
+  ToolHandle<IPileUpTool> m_sctDigitizationTool{this, "DigitizationTool", "SCT_DigitizationTool", "SCT_DigitizationTool name"};
+
+};
+
+#endif // FASERSCT_DIGITIZATION_SCT_DIGITIZATION_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..981e3e97d98de8da7c12d9c5f15c91406255d8ee
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.cxx
@@ -0,0 +1,795 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_DigitizationTool.h"
+
+// Mother Package includes
+#include "FaserSiDigitization/SiHelper.h"
+#include "FaserSiDigitization/SiChargedDiodeCollection.h"
+
+// EDM includes
+#include "InDetRawData/SCT1_RawData.h"
+#include "InDetRawData/SCT3_RawData.h"
+
+// Hit class includes
+#include "TrackerSimEvent/FaserSiHit.h"
+#include "Identifier/Identifier.h"
+
+// Det Descr includes
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerReadoutGeometry/SCT_ModuleSideDesign.h"
+
+// Data Handle
+#include "StoreGate/ReadCondHandle.h"
+#include "StoreGate/ReadHandle.h"
+
+// Random Number Generation
+#include "AthenaKernel/RNGWrapper.h"
+#include "CLHEP/Random/RandomEngine.h"
+
+// C++ Standard Library
+#include <memory>
+#include <sstream>
+
+// Barcodes at the HepMC level are int
+
+using TrackerDD::SiCellId;
+
+SCT_DigitizationTool::SCT_DigitizationTool(const std::string& type,
+                                           const std::string& name,
+                                           const IInterface* parent) :
+  base_class(type, name, parent) {
+  m_WriteSCT1_RawData.declareUpdateHandler(&SCT_DigitizationTool::SetupRdoOutputType, this);
+}
+
+SCT_DigitizationTool::~SCT_DigitizationTool() {
+  delete m_thpcsi;
+  for (FaserSiHitCollection* hit: m_hitCollPtrs) {
+    hit->Clear();
+    delete hit;
+  }
+  m_hitCollPtrs.clear();
+}
+
+// ----------------------------------------------------------------------
+// Initialize method:
+// ----------------------------------------------------------------------
+StatusCode SCT_DigitizationTool::initialize() {
+  ATH_MSG_DEBUG("SCT_DigitizationTool::initialize()");
+
+  // +++ Init the services
+  ATH_CHECK(initServices());
+
+  // +++ Get the Surface Charges Generator tool
+  ATH_CHECK(initSurfaceChargesGeneratorTool());
+
+  // +++ Get the Front End tool
+  ATH_CHECK(initFrontEndTool());
+
+  // +++ Initialise for disabled cells from the random disabled cells tool
+  // +++ Default off, since disabled cells taken form configuration in
+  // reconstruction stage
+  if (m_randomDisabledCells) {
+    ATH_CHECK(initDisabledCells());
+    ATH_MSG_INFO("Use of Random disabled cells");
+  } else {
+    m_sct_RandomDisabledCellGenerator.disable();
+  }
+
+  // check the input object name
+  if (m_hitsContainerKey.key().empty()) {
+    ATH_MSG_FATAL("Property InputObjectName not set !");
+    return StatusCode::FAILURE;
+  }
+  if(m_onlyUseContainerName) m_inputObjectName = m_hitsContainerKey.key();
+  ATH_MSG_DEBUG("Input objects in container : '" << m_inputObjectName << "'");
+
+  // Initialize ReadHandleKey
+  ATH_CHECK(m_hitsContainerKey.initialize(!m_onlyUseContainerName));
+
+  // +++ Initialize WriteHandleKey
+  ATH_CHECK(m_rdoContainerKey.initialize());
+  ATH_CHECK(m_simDataCollMapKey.initialize());
+
+  // Initialize ReadCondHandleKey
+  ATH_CHECK(m_SCTDetEleCollKey.initialize());
+
+  ATH_MSG_DEBUG("SiDigitizationTool::initialize() complete");
+
+  return StatusCode::SUCCESS;
+}
+
+namespace {
+  class SiDigitizationSurfaceChargeInserter
+    : public ISiSurfaceChargesInserter
+  {
+  public:
+    SiDigitizationSurfaceChargeInserter(const TrackerDD::SiDetectorElement* sielement,
+                                        SiChargedDiodeCollection* chargedDiodes)
+      : m_sielement(sielement),
+        m_chargedDiodes(chargedDiodes) {
+    }
+
+    void operator () (const SiSurfaceCharge& scharge) const;
+  private:
+    const TrackerDD::SiDetectorElement* m_sielement;
+    SiChargedDiodeCollection* m_chargedDiodes;
+  };
+
+
+  void SiDigitizationSurfaceChargeInserter::operator ()
+    (const SiSurfaceCharge& scharge) const {
+    // get the diode in which this charge is
+    SiCellId diode{m_sielement->cellIdOfPosition(scharge.position())};
+
+    if (diode.isValid()) {
+      // add this charge to the collection (or merge in existing charged diode)
+      m_chargedDiodes->add(diode, scharge.charge());
+    }
+  }
+} // anonymous namespace
+
+// ----------------------------------------------------------------------
+// Initialise the surface charge generator Tool
+// ----------------------------------------------------------------------
+StatusCode SCT_DigitizationTool::initSurfaceChargesGeneratorTool() {
+  ATH_CHECK(m_sct_SurfaceChargesGenerator.retrieve());
+
+  if (m_cosmicsRun and m_tfix > -998) {
+    m_sct_SurfaceChargesGenerator->setFixedTime(m_tfix);
+    ATH_MSG_INFO("Use of FixedTime = " << m_tfix << " in cosmics");
+  }
+
+  ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_SurfaceChargesGenerator);
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// Initialise the Front End electronics Tool
+// ----------------------------------------------------------------------
+StatusCode SCT_DigitizationTool::initFrontEndTool() {
+  ATH_CHECK(m_sct_FrontEnd.retrieve());
+
+  storeTool(&(*m_sct_FrontEnd));
+
+  ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_FrontEnd);
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// Initialize the different services
+// ----------------------------------------------------------------------
+StatusCode SCT_DigitizationTool::initServices() {
+  // Get SCT ID helper for hash function and Store them using methods from the
+  // SiDigitization.
+  ATH_CHECK(detStore()->retrieve(m_detID, "FaserSCT_ID"));
+
+  ATH_CHECK(m_mergeSvc.retrieve());
+  ATH_CHECK(m_rndmSvc.retrieve());
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// Initialize the disabled cells for cosmics or CTB cases
+// ----------------------------------------------------------------------
+StatusCode SCT_DigitizationTool::initDisabledCells() {
+  // +++ Retrieve the SCT_RandomDisabledCellGenerator
+  ATH_CHECK(m_sct_RandomDisabledCellGenerator.retrieve());
+
+  storeTool(&(*m_sct_RandomDisabledCellGenerator));
+
+  ATH_MSG_INFO("Retrieved the SCT_RandomDisabledCellGenerator tool:" << m_sct_RandomDisabledCellGenerator);
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_DigitizationTool::processAllSubEvents() {
+  if (prepareEvent(0).isFailure()) {
+    return StatusCode::FAILURE;
+  }
+  // Set the RNG to use for this event.
+  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
+  rngWrapper->setSeed( name(), Gaudi::Hive::currentContext() );
+  CLHEP::HepRandomEngine *rndmEngine = *rngWrapper;
+
+  ATH_MSG_VERBOSE("Begin digitizeAllHits");
+  if (m_enableHits and (not getNextEvent().isFailure())) {
+    digitizeAllHits(&m_rdoContainer, &m_simDataCollMap, &m_processedElements, m_thpcsi, rndmEngine);
+  } else {
+    ATH_MSG_DEBUG("no hits found in event!");
+  }
+  ATH_MSG_DEBUG("Digitized Elements with Hits");
+
+  // loop over elements without hits
+  if (not m_onlyHitElements) {
+    digitizeNonHits(&m_rdoContainer, &m_simDataCollMap, &m_processedElements, rndmEngine);
+    ATH_MSG_DEBUG("Digitized Elements without Hits");
+  }
+
+  delete m_thpcsi;
+  m_thpcsi = nullptr;
+
+  ATH_MSG_VERBOSE("Digitize success!");
+  return StatusCode::SUCCESS;
+}
+
+// ======================================================================
+// prepareEvent
+// ======================================================================
+StatusCode SCT_DigitizationTool::prepareEvent(unsigned int /*index*/) {
+  ATH_MSG_VERBOSE("SCT_DigitizationTool::prepareEvent()");
+  // Create the IdentifiableContainer to contain the digit collections Create
+  // a new RDO container
+  m_rdoContainer = SG::makeHandle(m_rdoContainerKey);
+  ATH_CHECK(m_rdoContainer.record(std::make_unique<SCT_RDO_Container>(m_detID->wafer_hash_max())));
+
+  // Create a map for the SDO and register it into StoreGate
+  m_simDataCollMap = SG::makeHandle(m_simDataCollMapKey);
+  ATH_CHECK(m_simDataCollMap.record(std::make_unique<InDetSimDataCollection>()));
+
+  m_processedElements.clear();
+  m_processedElements.resize(m_detID->wafer_hash_max(), false);
+
+  m_thpcsi = new TimedHitCollection<FaserSiHit>();
+//   m_HardScatterSplittingSkipper = false;
+  return StatusCode::SUCCESS;
+}
+
+// =========================================================================
+// mergeEvent
+// =========================================================================
+StatusCode SCT_DigitizationTool::mergeEvent() {
+  ATH_MSG_VERBOSE("SCT_DigitizationTool::mergeEvent()");
+
+  // Set the RNG to use for this event.
+  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
+  rngWrapper->setSeed( name(), Gaudi::Hive::currentContext() );
+  CLHEP::HepRandomEngine *rndmEngine = *rngWrapper;
+
+  if (m_enableHits) {
+    digitizeAllHits(&m_rdoContainer, &m_simDataCollMap, &m_processedElements, m_thpcsi, rndmEngine);
+  }
+
+  if (not m_onlyHitElements) {
+    digitizeNonHits(&m_rdoContainer, &m_simDataCollMap, &m_processedElements, rndmEngine);
+  }
+
+  for (FaserSiHitCollection* hit: m_hitCollPtrs) {
+    hit->Clear();
+    delete hit;
+  }
+  m_hitCollPtrs.clear();
+
+  delete m_thpcsi;
+  m_thpcsi = nullptr;
+
+  ATH_MSG_DEBUG("Digitize success!");
+  return StatusCode::SUCCESS;
+}
+
+void SCT_DigitizationTool::digitizeAllHits(SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, std::vector<bool>* processedElements, TimedHitCollection<FaserSiHit>* thpcsi, CLHEP::HepRandomEngine * rndmEngine) const {
+  /////////////////////////////////////////////////
+  //
+  // In order to process all element rather than just those with hits we
+  // create a vector to keep track of which elements have been processed.
+  // NB. an element is an sct module
+  //
+  /////////////////////////////////////////////////
+  ATH_MSG_DEBUG("Digitizing hits");
+  int hitcount{0}; // First, elements with hits.
+
+  SiChargedDiodeCollection chargedDiodes;
+
+  while (digitizeElement(&chargedDiodes, thpcsi, rndmEngine)) {
+    ATH_MSG_DEBUG("Hit collection ID=" << m_detID->show_to_string(chargedDiodes.identify()));
+
+    hitcount++;  // Hitcount will be a number in the hit collection minus
+    // number of hits in missing mods
+
+    ATH_MSG_DEBUG("in digitize elements with hits: station - layer - eta - phi  "
+                  << m_detID->station(chargedDiodes.identify()) << " - "
+                  << m_detID->layer(chargedDiodes.identify()) << " - "
+                  << m_detID->eta_module(chargedDiodes.identify()) << " - "
+                  << m_detID->phi_module(chargedDiodes.identify()) << " - "
+                  << " processing hit number " << hitcount);
+
+    // Have a flag to check if the module is present or not
+    // Generally assume it is:
+
+    IdentifierHash idHash{chargedDiodes.identifyHash()};
+
+    assert(idHash < processedElements->size());
+    (*processedElements)[idHash] = true;
+
+    // create and store RDO and SDO
+
+    if (not chargedDiodes.empty()) {
+      StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
+      if (sc.isSuccess()) { // error msg is given inside
+        // createAndStoreRDO()
+        addSDO(&chargedDiodes, simDataCollMap);
+      }
+    }
+
+    chargedDiodes.clear();
+  }
+  ATH_MSG_DEBUG("hits processed");
+  return;
+}
+
+// digitize elements without hits
+void SCT_DigitizationTool::digitizeNonHits(SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, const std::vector<bool>* processedElements, CLHEP::HepRandomEngine * rndmEngine) const {
+  // Get SCT_DetectorElementCollection
+  SG::ReadCondHandle<TrackerDD::SiDetectorElementCollection> sctDetEle(m_SCTDetEleCollKey);
+  const TrackerDD::SiDetectorElementCollection* elements{sctDetEle.retrieve()};
+  if (elements==nullptr) {
+    ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
+    return;
+  }
+
+  ATH_MSG_DEBUG("processing elements without hits");
+  SiChargedDiodeCollection chargedDiodes;
+
+  for (unsigned int i{0}; i < processedElements->size(); i++) {
+    if (not (*processedElements)[i]) {
+      IdentifierHash idHash{i};
+      if (not idHash.is_valid()) {
+        ATH_MSG_ERROR("SCT Detector element id hash is invalid = " << i);
+      }
+
+      const TrackerDD::SiDetectorElement* element{elements->getDetectorElement(idHash)};
+      if (element) {
+        ATH_MSG_DEBUG("In digitize of untouched elements: layer - phi - eta  "
+                      << m_detID->layer(element->identify()) << " - "
+                      << m_detID->phi_module(element->identify()) << " - "
+                      << m_detID->eta_module(element->identify()) << " - "
+                      << "size: " << processedElements->size());
+
+        chargedDiodes.setDetectorElement(element);
+        ATH_MSG_DEBUG("calling applyProcessorTools() for NON hits");
+        applyProcessorTools(&chargedDiodes, rndmEngine);
+
+        // Create and store RDO and SDO
+        // Don't create empty ones.
+        if (not chargedDiodes.empty()) {
+          StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
+          if (sc.isSuccess()) {// error msg is given inside
+            // createAndStoreRDO()
+            addSDO(&chargedDiodes, simDataCollMap);
+          }
+        }
+
+        chargedDiodes.clear();
+      }
+    }
+  }
+
+  return;
+}
+
+bool SCT_DigitizationTool::digitizeElement(SiChargedDiodeCollection* chargedDiodes, TimedHitCollection<FaserSiHit>*& thpcsi, CLHEP::HepRandomEngine * rndmEngine) const {
+  if (nullptr == thpcsi) {
+    ATH_MSG_ERROR("thpcsi should not be nullptr!");
+
+    return false;
+  }
+
+  // get the iterator pairs for this DetEl
+
+  TimedHitCollection<FaserSiHit>::const_iterator i, e;
+  if (thpcsi->nextDetectorElement(i, e) == false) { // no more hits
+    return false;
+  }
+
+  // create the identifier for the collection:
+  ATH_MSG_DEBUG("create ID for the hit collection");
+  const TimedHitPtr<FaserSiHit>& firstHit{*i};
+  int barrel{firstHit->getStation()};
+  Identifier id{m_detID->wafer_id(barrel,
+                                  firstHit->getPlane(),
+                                  firstHit->getRow(),
+                                  firstHit->getModule(),
+                                  firstHit->getSensor())};
+  IdentifierHash waferHash{m_detID->wafer_hash(id)};
+
+  // Get SCT_DetectorElementCollection
+  SG::ReadCondHandle<TrackerDD::SiDetectorElementCollection> sctDetEle(m_SCTDetEleCollKey);
+  const TrackerDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
+  if (elements==nullptr) {
+    ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
+    return false;
+  }
+
+  // get the det element from the manager
+  const TrackerDD::SiDetectorElement* sielement{elements->getDetectorElement(waferHash)};
+
+  if (sielement == nullptr) {
+    ATH_MSG_DEBUG("Station=" << barrel << " layer=" << firstHit->getPlane() << " Row=" << firstHit->getRow() << " Module=" << firstHit->getModule() << " Side=" << firstHit->getSensor());
+    ATH_MSG_ERROR("detector manager could not find element with id = " << id);
+    return false;
+  }
+  // create the charged diodes collection
+  chargedDiodes->setDetectorElement(sielement);
+
+  // Loop over the hits and created charged diodes:
+  while (i != e) {
+    TimedHitPtr<FaserSiHit> phit{*i++};
+
+    // skip hits which are more than 10us away
+    if (fabs(phit->meanTime()) < 10000. * CLHEP::ns) {
+      ATH_MSG_DEBUG("HASH = " << m_detID->wafer_hash(m_detID->wafer_id(phit->getStation(),
+                                                                       phit->getPlane(),
+                                                                       phit->getRow(),
+                                                                       phit->getModule(),
+                                                                       phit->getSensor())));
+      ATH_MSG_DEBUG("calling process() for all methods");
+      m_sct_SurfaceChargesGenerator->process(sielement, phit, SiDigitizationSurfaceChargeInserter(sielement, chargedDiodes), rndmEngine);
+      ATH_MSG_DEBUG("charges filled!");
+    }
+  }
+  applyProcessorTools(chargedDiodes, rndmEngine); // !< Use of the new AlgTool surface
+  // charges generator class
+  return true;
+}
+
+// -----------------------------------------------------------------------------
+// Applies processors to the current detector element for the current element:
+// -----------------------------------------------------------------------------
+void SCT_DigitizationTool::applyProcessorTools(SiChargedDiodeCollection* chargedDiodes, CLHEP::HepRandomEngine * rndmEngine) const {
+  ATH_MSG_DEBUG("applyProcessorTools()");
+  int processorNumber{0};
+
+  for (ISiChargedDiodesProcessorTool* proc: m_diodeCollectionTools) {
+    proc->process(*chargedDiodes, rndmEngine);
+
+    processorNumber++;
+    ATH_MSG_DEBUG("Applied processor # " << processorNumber);
+  }
+}
+
+StatusCode SCT_DigitizationTool::processBunchXing(int bunchXing,
+                                                  SubEventIterator bSubEvents,
+                                                  SubEventIterator eSubEvents) {
+    ATH_MSG_VERBOSE("SCT_DigitizationTool::processBunchXing() " << bunchXing);
+
+    typedef PileUpMergeSvc::TimedList<FaserSiHitCollection>::type TimedHitCollList;
+    TimedHitCollList hitCollList;
+
+    if ((not (m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName, hitCollList, bunchXing,
+                                                bSubEvents, eSubEvents).isSuccess())) and
+        hitCollList.size() == 0) {
+      ATH_MSG_ERROR("Could not fill TimedHitCollList");
+      return StatusCode::FAILURE;
+    } else {
+      ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " <<
+		      m_inputObjectName << " found");
+    }
+
+    TimedHitCollList::iterator endColl{hitCollList.end()};
+    for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; iColl++) {
+      FaserSiHitCollection *hitCollPtr{new FaserSiHitCollection(*iColl->second)};
+      PileUpTimeEventIndex timeIndex{iColl->first};
+      ATH_MSG_DEBUG("SiHitCollection found with " << hitCollPtr->size() <<
+                    " hits");
+      ATH_MSG_VERBOSE("time index info. time: " << timeIndex.time()
+		      << " index: " << timeIndex.index()
+		      << " type: " << timeIndex.type());
+      m_thpcsi->insert(timeIndex, hitCollPtr);
+      m_hitCollPtrs.push_back(hitCollPtr);
+    }
+
+    return StatusCode::SUCCESS;
+
+}
+
+// =========================================================================
+// property handlers
+// =========================================================================
+void SCT_DigitizationTool::SetupRdoOutputType(Property &) {
+}
+
+// Does nothing, but required by Gaudi
+
+// ----------------------------------------------------------------------
+// Digitisation of non hit elements
+// ----------------------------------------------------------------------
+
+class DigitizeNonHitElementsDebugPrinter
+{
+public:
+  DigitizeNonHitElementsDebugPrinter(const FaserSCT_ID* detID) :
+    m_detID{detID}, m_msgNo{-1} {
+    }
+
+  std::string msg(const TrackerDD::SiDetectorElement* element) {
+    std::ostringstream ost;
+
+    ost << "Digitized unprocessed elements: layer - phi - eta - side  "
+        << m_detID->layer(element->identify()) << " - "
+        << m_detID->phi_module(element->identify()) << " - "
+        << m_detID->eta_module(element->identify()) << " - "
+        << m_detID->side(element->identify()) << " - "
+        << " unprocessed hit number: " << ++m_msgNo << '\n';
+
+    return ost.str();
+  }
+
+private:
+  const FaserSCT_ID* m_detID;
+  int m_msgNo;
+};
+
+// ----------------------------------------------------------------------//
+// createAndStoreRDO                                                     //
+// ----------------------------------------------------------------------//
+StatusCode SCT_DigitizationTool::createAndStoreRDO(SiChargedDiodeCollection* chDiodeCollection, SG::WriteHandle<SCT_RDO_Container>* rdoContainer) const {
+
+  // Create the RDO collection
+  SCT_RDO_Collection* RDOColl{createRDO(chDiodeCollection)};
+
+  // Add it to storegate
+  if ((*rdoContainer)->addCollection(RDOColl, RDOColl->identifyHash()).isFailure()) {
+      ATH_MSG_FATAL("SCT RDO collection could not be added to container!");
+      delete RDOColl;
+      RDOColl = nullptr;
+      return StatusCode::FAILURE;
+  }
+  return StatusCode::SUCCESS;
+} // SCT_Digitization::createAndStoreRDO()
+
+// ----------------------------------------------------------------------
+// createRDO
+// ----------------------------------------------------------------------
+SCT_RDO_Collection* SCT_DigitizationTool::createRDO(SiChargedDiodeCollection* collection) const {
+
+  // create a new SCT RDO collection
+  SCT_RDO_Collection* p_rdocoll{nullptr};
+
+  // need the DE identifier
+  const Identifier id_de{collection->identify()};
+  IdentifierHash idHash_de{collection->identifyHash()};
+  try {
+    p_rdocoll = new SCT_RDO_Collection(idHash_de);
+  } catch (const std::bad_alloc&) {
+    ATH_MSG_FATAL("Could not create a new SCT_RDORawDataCollection !");
+  }
+  p_rdocoll->setIdentifier(id_de);
+
+  SiChargedDiodeIterator i_chargedDiode{collection->begin()};
+  SiChargedDiodeIterator i_chargedDiode_end{collection->end()};
+  // Choice of producing SCT1_RawData or SCT3_RawData
+  if (m_WriteSCT1_RawData.value()) {
+    for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+      unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
+
+      if (!flagmask) { // now check it wasn't masked:
+        // create new SCT RDO, using method 1 for mask:
+        // GroupSize=1: need readout id, make use of
+        // SiTrackerDetDescr
+        TrackerDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
+        int strip{roCell.strip()};
+        if (strip > 0xffff) { // In upgrade layouts strip can be bigger
+          // than 4000
+          ATH_MSG_FATAL("Strip number too big for SCT1 raw data format.");
+        }
+        const Identifier id_readout{m_detID->strip_id(collection->identify(), strip)};
+
+        // build word, masks taken from SiTrackerEvent/SCTRawData.cxx
+        const unsigned int strip_rdo{static_cast<unsigned int>((strip & 0xFFFF) << 16)};
+
+        // user can define what GroupSize is, here 1: TC. Incorrect,
+        // GroupSize >= 1
+        int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
+        unsigned int size_rdo{static_cast<unsigned int>(size & 0xFFFF)};
+
+        // TC. Need to check if there are disabled strips in the cluster
+        int cluscounter{0};
+        if (size > 1) {
+          SiChargedDiodeIterator it2{i_chargedDiode};
+          ++it2;
+          for (; it2 != i_chargedDiode_end; ++it2) {
+            ++cluscounter;
+            if (cluscounter >= size) {
+              break;
+            }
+            if (it2->second.flag() & 0xDE) {
+              int tmp{cluscounter};
+              while ((it2 != i_chargedDiode_end) and (cluscounter < size - 1) and (it2->second.flag() & 0xDE)) {
+                it2++;
+                cluscounter++;
+              }
+              if ((it2 != collection->end()) and !(it2->second.flag() & 0xDE)) {
+                SiHelper::ClusterUsed(it2->second, false);
+                SiHelper::SetStripNum(it2->second, size - cluscounter, &msg());
+              }
+              // groupSize=tmp;
+              size_rdo = tmp & 0xFFFF;
+              break;
+            }
+          }
+        }
+        unsigned int SCT_Word{strip_rdo | size_rdo};
+        SCT1_RawData* p_rdo{new SCT1_RawData(id_readout, SCT_Word)};
+        if (p_rdo) {
+          p_rdocoll->push_back(p_rdo);
+        }
+      }
+    }
+  } else {
+    // Under the current scheme time bin and ERRORS are hard-coded to
+    // default values.
+    int ERRORS{0};
+    static std::vector<int> dummyvector;
+    for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+      unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
+
+      if (!flagmask) { // Check it wasn't masked
+        int tbin{SiHelper::GetTimeBin((*i_chargedDiode).second)};
+        // create new SCT RDO
+        TrackerDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
+        int strip{roCell.strip()};
+        Identifier id_readout;
+        id_readout = m_detID->strip_id(collection->identify(), strip);
+                
+        // build word (compatible with
+        // SCT_RawDataByteStreamCnv/src/SCT_RodDecoder.cxx)
+        int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
+        int groupSize{size};
+
+        // TC. Need to check if there are disabled strips in the cluster
+        int cluscounter{0};
+        if (size > 1) {
+          SiChargedDiode* diode{i_chargedDiode->second.nextInCluster()};
+          while (diode) {//check if there is a further strip in the cluster
+            ++cluscounter;
+            if (cluscounter >= size) {
+              ATH_MSG_WARNING("Cluster size reached while neighbouring strips still defined.");
+              break;
+            }
+            if (diode->flag() & 0xDE) {//see if it is disabled/below threshold/disconnected/etc (0xDE corresponds to BT_SET | DISABLED_SET | BADTOT_SET | DISCONNECTED_SET | MASKOFF_SET)
+              int tmp{cluscounter};
+              while ((cluscounter < size - 1) and (diode->flag() & 0xDE)) { //check its not the end and still disabled
+                diode = diode->nextInCluster();
+                cluscounter++;
+              }
+              if (diode and !(diode->flag() & 0xDE)) {
+                SiHelper::ClusterUsed(*diode, false);
+                SiHelper::SetStripNum(*diode, size - cluscounter, &msg());
+              }
+              groupSize = tmp;
+              break;
+            }
+            diode = diode->nextInCluster();
+          }
+        }
+
+        int stripIn11bits{strip & 0x7ff};
+        if (stripIn11bits != strip) {
+          ATH_MSG_DEBUG("Strip number " << strip << " doesn't fit into 11 bits - will be truncated");
+        }
+                
+        unsigned int SCT_Word{static_cast<unsigned int>(groupSize | (stripIn11bits << 11) | (tbin << 22) | (ERRORS << 25))};
+        SCT3_RawData *p_rdo{new SCT3_RawData(id_readout, SCT_Word, &dummyvector)};
+        if (p_rdo) {
+          p_rdocoll->push_back(p_rdo);
+        }
+      }
+    }
+  }
+  return p_rdocoll;
+} // SCT_Digitization::createRDO()
+
+// ------------------------------------------------------------
+// Get next event and extract collection of hit collections:
+// ------------------------------------------------------------
+StatusCode SCT_DigitizationTool::getNextEvent() {
+  ATH_MSG_DEBUG("SCT_DigitizationTool::getNextEvent()");
+  //  get the container(s)
+  typedef PileUpMergeSvc::TimedList<FaserSiHitCollection>::type TimedHitCollList;
+  // this is a list<pair<time_t, DataLink<SiHitCollection> >
+
+  // In case of single hits container just load the collection using read handles
+  if (!m_onlyUseContainerName) {
+    SG::ReadHandle<FaserSiHitCollection> hitCollection(m_hitsContainerKey);
+    if (!hitCollection.isValid()) {
+      ATH_MSG_ERROR("Could not get SCT SiHitCollection container " << hitCollection.name() << " from store " << hitCollection.store());
+      return StatusCode::FAILURE;
+    }
+
+    // create a new hits collection
+    m_thpcsi = new TimedHitCollection<FaserSiHit>{1};
+    m_thpcsi->insert(0, hitCollection.cptr());
+    ATH_MSG_DEBUG("SiHitCollection found with " << hitCollection->size() << " hits");
+
+    return StatusCode::SUCCESS;
+  }
+
+  TimedHitCollList hitCollList;
+  unsigned int numberOfSiHits{0};
+  if (not (m_mergeSvc->retrieveSubEvtsData(m_inputObjectName, hitCollList, numberOfSiHits).isSuccess()) and hitCollList.size() == 0) {
+    ATH_MSG_ERROR("Could not fill TimedHitCollList");
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_DEBUG(hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found");
+  }
+  // create a new hits collection
+  m_thpcsi = new TimedHitCollection<FaserSiHit>{numberOfSiHits};
+  // now merge all collections into one
+  TimedHitCollList::iterator endColl{hitCollList.end()};
+  for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; ++iColl) {
+    const FaserSiHitCollection* p_collection{iColl->second};
+    m_thpcsi->insert(iColl->first, p_collection);
+    ATH_MSG_DEBUG("SiTrackerHitCollection found with " << p_collection->size() << " hits"); // loop on the hit collections
+  }
+  return StatusCode::SUCCESS;
+}
+
+// -----------------------------------------------------------------------------------------------
+// Convert a SiTotalCharge to a InDetSimData, and store it.
+// -----------------------------------------------------------------------------------------------
+void SCT_DigitizationTool::addSDO(SiChargedDiodeCollection* collection, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap) const {
+  typedef SiTotalCharge::list_t list_t;
+  std::vector<InDetSimData::Deposit> deposits;
+  deposits.reserve(5); // no idea what a reasonable number for this would be
+  // with pileup
+  // loop over the charged diodes
+  SiChargedDiodeIterator EndOfDiodeCollection{collection->end()};
+  for (SiChargedDiodeIterator i_chargedDiode{collection->begin()}; i_chargedDiode != EndOfDiodeCollection; ++i_chargedDiode) {
+    deposits.clear();
+    const list_t& charges{(*i_chargedDiode).second.totalCharge().chargeComposition()};
+
+    bool real_particle_hit{false};
+    // loop over the list
+    list_t::const_iterator EndOfChargeList{charges.end()};
+    for (list_t::const_iterator i_ListOfCharges{charges.begin()}; i_ListOfCharges != EndOfChargeList; ++i_ListOfCharges) {
+      const HepMcParticleLink& trkLink{i_ListOfCharges->particleLink()};
+      const int barcode{trkLink.barcode()};
+      if ((barcode == 0) or (barcode == m_vetoThisBarcode)) {
+        continue;
+      }
+      if (not real_particle_hit) {
+        // Types of SiCharges expected from SCT
+        // Noise:                        barcode==0 and
+        // processType()==SiCharge::noise
+        // Delta Rays:                   barcode==0 and
+        // processType()==SiCharge::track
+        // Pile Up Tracks With No Truth: barcode!=0 and
+        // processType()==SiCharge::cut_track
+        // Tracks With Truth:            barcode!=0 and
+        // processType()==SiCharge::track
+        if (barcode != 0 and i_ListOfCharges->processType() == SiCharge::track) {
+          real_particle_hit = true;
+        }
+      }
+      // check if this track number has been already used.
+      std::vector<InDetSimData::Deposit>::reverse_iterator theDeposit{deposits.rend()};  // dummy value
+      std::vector<InDetSimData::Deposit>::reverse_iterator depositsR_end{deposits.rend()};
+      std::vector<InDetSimData::Deposit>::reverse_iterator i_Deposit{deposits.rbegin()};
+      for (; i_Deposit != depositsR_end; ++i_Deposit) {
+        if ((*i_Deposit).first == trkLink) {
+          theDeposit = i_Deposit;
+          break;
+        }
+      }
+
+      // if the charge has already hit the Diode add it to the deposit
+      if (theDeposit != depositsR_end) {
+        (*theDeposit).second += i_ListOfCharges->charge();
+      } else { // create a new deposit
+        InDetSimData::Deposit deposit(trkLink, i_ListOfCharges->charge());
+        deposits.push_back(deposit);
+      }
+    }
+
+    // add the simdata object to the map:
+    if (real_particle_hit or m_createNoiseSDO) {
+      TrackerDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
+      int strip{roCell.strip()};
+      Identifier id_readout;
+      id_readout = m_detID->strip_id(collection->identify(),strip);
+      (*simDataCollMap)->insert(std::make_pair(id_readout, InDetSimData(deposits, (*i_chargedDiode).second.flag())));
+    }
+  }
+}
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..f34d0619d4bb0538d63e4ded88df576d5b175f44
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_DigitizationTool.h
@@ -0,0 +1,156 @@
+/* -*- C++ -*- */
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERSCT_DIGITZATION_SCT_DIGITZATIONTOOL_H
+#define FASERSCT_DIGITZATION_SCT_DIGITZATIONTOOL_H
+/** @file SCT_DigitizationTool.h
+ * @brief Digitize the SCT using an implementation of IPileUpTool
+ * $Id: SCT_DigitizationTool.h,v 1.0 2009-09-22 18:34:42 jchapman Exp $
+ * @author John Chapman - ATLAS Collaboration
+ */
+
+//Base class header
+#include "PileUpTools/PileUpToolBase.h"
+
+// Athena headers
+#include "AthenaKernel/IAthRNGSvc.h"
+#include "HitManagement/TimedHitCollection.h"
+#include "InDetRawData/SCT_RDO_Container.h"
+#include "TrackerReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetSimData/InDetSimDataCollection.h"
+#include "TrackerSimEvent/FaserSiHitCollection.h"
+#include "PileUpTools/PileUpMergeSvc.h"
+#include "FaserSCT_Digitization/ISCT_FrontEnd.h"
+#include "FaserSCT_Digitization/ISCT_RandomDisabledCellGenerator.h"
+#include "FaserSCT_Digitization/ISCT_SurfaceChargesGenerator.h"
+#include "StoreGate/ReadCondHandleKey.h"
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/WriteHandleKey.h"
+
+// Gaudi headers
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+
+// STL headers
+#include <limits>
+#include <string>
+
+// Forward declarations
+class ISiChargedDiodesProcessorTool;
+class FaserSCT_ID;
+class SiChargedDiodeCollection;
+
+namespace CLHEP
+{
+  class HepRandomEngine;
+}
+
+class SCT_DigitizationTool : public extends<PileUpToolBase, IPileUpTool>
+{
+public:
+  static const InterfaceID& interfaceID();
+  SCT_DigitizationTool(const std::string& type,
+                       const std::string& name,
+                       const IInterface* parent);
+  virtual ~SCT_DigitizationTool();
+  /**
+     @brief Called before processing physics events
+  */
+  virtual StatusCode prepareEvent(unsigned int) override final;
+  virtual StatusCode processBunchXing(int bunchXing,
+                                      SubEventIterator bSubEvents,
+                                      SubEventIterator eSubEvents) override final;
+  virtual StatusCode mergeEvent() override final;
+
+  virtual StatusCode initialize() override final;
+  virtual StatusCode processAllSubEvents() override final;
+
+protected:
+
+  bool digitizeElement(SiChargedDiodeCollection* chargedDiodes, TimedHitCollection<FaserSiHit>*& thpcsi, CLHEP::HepRandomEngine * rndmEngine) const ; //!
+  void applyProcessorTools(SiChargedDiodeCollection* chargedDiodes, CLHEP::HepRandomEngine * rndmEngine) const; //!
+  void addSDO(SiChargedDiodeCollection* collection, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap) const;
+
+  void storeTool(ISiChargedDiodesProcessorTool* p_processor) {m_diodeCollectionTools.push_back(p_processor);}
+
+private:
+
+  /**
+     @brief initialize the required services
+  */
+  StatusCode initServices();
+  /**
+     @brief Initialize the SCT_FrontEnd AlgTool
+  */
+  StatusCode initFrontEndTool();
+  /**
+     @brief Initialize the SCT_RandomDisabledCellGenerator AlgTool
+  */
+  StatusCode initDisabledCells();
+  /**
+     @brief Initialize the SCT_SurfaceChargesGenerator AlgTool
+  */
+  StatusCode initSurfaceChargesGeneratorTool();
+
+  /** RDO and SDO methods*/
+  /**
+     @brief Create RDOs from the SiChargedDiodeCollection for the current wafer and save to StoreGate
+     @param chDiodeCollection       list of the SiChargedDiodes on the current wafer
+  */
+  StatusCode createAndStoreRDO(SiChargedDiodeCollection* chDiodeCollection, SG::WriteHandle<SCT_RDO_Container>* rdoContainer) const;
+  /**
+     @brief Create RDOs from the SiChargedDiodeCollection for the current wafer
+     @param chDiodeCollection       list of the SiChargedDiodes on the current wafer
+  */
+  SCT_RDO_Collection* createRDO(SiChargedDiodeCollection* collection) const;
+
+  StatusCode getNextEvent();
+  void       digitizeAllHits(SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, std::vector<bool>* processedElements, TimedHitCollection<FaserSiHit>* thpcsi, CLHEP::HepRandomEngine * rndmEngine) const; //!< digitize all hits
+  void       digitizeNonHits(SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, const std::vector<bool>* processedElements, CLHEP::HepRandomEngine * rndmEngine) const;     //!< digitize SCT without hits
+
+  /**
+     @brief Called when m_WriteSCT1_RawData is altered. Does nothing, but required by Gaudi.
+  */
+  void SetupRdoOutputType(Property&);
+
+  FloatProperty m_tfix{this, "FixedTime", -999., "Fixed time for Cosmics run selection"};
+  BooleanProperty m_enableHits{this, "EnableHits", true, "Enable hits"};
+  BooleanProperty m_onlyHitElements{this, "OnlyHitElements", false, "Process only elements with hits"};
+  BooleanProperty m_cosmicsRun{this, "CosmicsRun", false, "Cosmics run selection"};
+  BooleanProperty m_randomDisabledCells{this, "RandomDisabledCells", false, "Use Random disabled cells, default no"};
+  BooleanProperty m_createNoiseSDO{this, "CreateNoiseSDO", false, "Create SDOs for strips with only noise hits (huge increase in SDO collection size"};
+  BooleanProperty m_WriteSCT1_RawData{this, "WriteSCT1_RawData", false, "Write out SCT1_RawData rather than SCT3_RawData"};
+
+  BooleanProperty m_onlyUseContainerName{this, "OnlyUseContainerName", true, "Don't use the ReadHandleKey directly. Just extract the container name from it."};
+  SG::ReadHandleKey<FaserSiHitCollection> m_hitsContainerKey{this, "InputObjectName", "SCT_Hits", "Input HITS collection name"};
+  std::string m_inputObjectName{""};
+
+  SG::WriteHandleKey<SCT_RDO_Container> m_rdoContainerKey{this, "OutputObjectName", "SCT_RDOs", "Output Object name"};
+  SG::WriteHandle<SCT_RDO_Container> m_rdoContainer; //!< RDO container handle
+  SG::WriteHandleKey<InDetSimDataCollection> m_simDataCollMapKey{this, "OutputSDOName", "SCT_SDO_Map", "Output SDO container name"};
+  SG::WriteHandle<InDetSimDataCollection>            m_simDataCollMap; //!< SDO Map handle
+  SG::ReadCondHandleKey<TrackerDD::SiDetectorElementCollection> m_SCTDetEleCollKey{this, "SCTDetEleCollKey", "SCT_DetectorElementCollection", "Key of SiDetectorElementCollection for SCT"};
+
+  ToolHandle<ISCT_FrontEnd> m_sct_FrontEnd{this, "FrontEnd", "SCT_FrontEnd", "Handle the Front End Electronic tool"};
+  ToolHandle<ISCT_SurfaceChargesGenerator> m_sct_SurfaceChargesGenerator{this, "SurfaceChargesGenerator", "SCT_SurfaceChargesGenerator", "Choice of using a more detailed charge drift model"};
+  ToolHandle<ISCT_RandomDisabledCellGenerator> m_sct_RandomDisabledCellGenerator{this, "RandomDisabledCellGenerator", "SCT_RandomDisabledCellGenerator", ""};
+  ServiceHandle<IAthRNGSvc> m_rndmSvc{this, "RndmSvc", "AthRNGSvc", ""};  //!< Random number service
+  ServiceHandle <PileUpMergeSvc> m_mergeSvc{this, "MergeSvc", "PileUpMergeSvc", "Merge service used in Pixel & SCT digitization"}; //!
+
+  const FaserSCT_ID* m_detID{nullptr}; //!< Handle to the ID helper
+  TimedHitCollection<FaserSiHit>* m_thpcsi{nullptr};
+  std::list<ISiChargedDiodesProcessorTool*> m_diodeCollectionTools;
+  std::vector<bool> m_processedElements; //!< vector of processed elements - set by digitizeHits() */
+  std::vector<FaserSiHitCollection*> m_hitCollPtrs;
+};
+
+static const InterfaceID IID_ISCT_DigitizationTool("SCT_DigitizationTool", 1, 0);
+inline const InterfaceID& SCT_DigitizationTool::interfaceID() {
+  return IID_ISCT_DigitizationTool;
+}
+
+#endif // FASERSCT_DIGITZATION_SCT_DIGITZATIONTOOL_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..50d06c46c2dceb839ae362a89b6eea8c92320a38
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.cxx
@@ -0,0 +1,1044 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_FrontEnd.h"
+
+// Random number
+#include "CLHEP/Random/RandFlat.h"
+#include "CLHEP/Random/RandGaussZiggurat.h"  // for RandGaussZiggurat
+#include "CLHEP/Random/RandPoisson.h"
+#include "CLHEP/Random/RandomEngine.h"
+
+#include "FaserSiDigitization/SiHelper.h"
+#include "FaserSCT_Digitization/ISCT_Amp.h"
+
+#include "TrackerIdentifier/FaserSCT_ID.h"
+
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+#include "TrackerReadoutGeometry/SCT_ModuleSideDesign.h"
+
+// C++ Standard Library
+#include <algorithm>
+#include <iostream>
+
+// #define SCT_DIG_DEBUG
+
+using namespace std;
+using namespace TrackerDD;
+
+// constructor
+SCT_FrontEnd::SCT_FrontEnd(const std::string& type, const std::string& name, const IInterface* parent)
+  : base_class(type, name, parent) {
+}
+
+// ----------------------------------------------------------------------
+// Initialize
+// ----------------------------------------------------------------------
+StatusCode SCT_FrontEnd::initialize() {
+  if (m_NoiseOn and (not m_analogueNoiseOn)) {
+    ATH_MSG_FATAL("AnalogueNoiseOn/m_analogueNoiseOn should be true if NoiseOn/m_NoiseOn is true.");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_MSG_DEBUG("SCT_FrontEnd::initialize()");
+  // Get SCT helper
+  ATH_CHECK(detStore()->retrieve(m_sct_id, "FaserSCT_ID"));
+  // Get SCT detector manager
+  ATH_CHECK(detStore()->retrieve(m_SCTdetMgr, "SCT"));
+  // Get the amplifier tool
+  ATH_CHECK(m_sct_amplifier.retrieve());
+  ATH_MSG_DEBUG("SCT Amplifier tool located ");
+
+  // Get the SCT_ReadCaliDataSvc
+  if (m_useCalibData) {
+    // ATH_CHECK(m_ReadCalibChipDataTool.retrieve());
+    // ATH_MSG_DEBUG("CalibChipData Service located ");
+    ATH_MSG_FATAL("Use of calibration data not supported.");
+  } else {
+    // m_ReadCalibChipDataTool.disable();
+  }
+
+  // Get the maximum number of strips of any module
+  m_strip_max = m_SCTdetMgr->numerology().maxNumStrips();
+
+  constexpr float fC = 6242.2;
+  m_Threshold = m_Threshold * fC;
+
+#ifdef SCT_DIG_DEBUG
+  ATH_MSG_INFO("\tNoise factors:");
+  ATH_MSG_INFO("\tBarrel = " << m_NoiseBarrel << " Outer Barrel = " << m_NoiseBarrel3 <<
+               " EC, inners = " << m_NoiseInners << " EC, middles = " << m_NoiseMiddles <<
+               " EC, short middles = " << m_NoiseShortMiddles << " EC, outers = " << m_NoiseOuters);
+  ATH_MSG_INFO("\tThreshold=" << m_Threshold << " fC, time of Threshold=" << m_timeOfThreshold);
+#endif
+
+  ATH_MSG_INFO("m_Threshold             (Threshold)           = " << m_Threshold);
+  ATH_MSG_INFO("m_timeOfThreshold       (TimeOfThreshold)     = " << m_timeOfThreshold);
+  ATH_MSG_INFO("m_data_compression_mode (DataCompressionMode) = " << m_data_compression_mode);
+  ATH_MSG_INFO("m_data_readout_mode     (DataReadOutMode)     = " <<  m_data_readout_mode);
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_FrontEnd::finalize() {
+#ifdef SCT_DIG_DEBUG
+  ATH_MSG_INFO("SCT_FrontEnd::finalize()");
+#endif
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// Init the class variable  vectors
+// ----------------------------------------------------------------------
+StatusCode SCT_FrontEnd::initVectors(int strips, SCT_FrontEndData& data) const {
+  data.m_Offset.assign(strips, 0.0);
+  data.m_GainFactor.assign(strips, 0.0);
+  data.m_NoiseFactor.assign(strips, 0.0);
+
+  if (m_data_compression_mode == 1 and m_data_readout_mode == 0) {
+    data.m_Analogue[0].reserve(1);
+    data.m_Analogue[1].reserve(strips);
+  } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) {
+    data.m_Analogue[0].reserve(strips);
+    data.m_Analogue[1].reserve(strips);
+  } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) {
+    data.m_Analogue[0].reserve(strips);
+    data.m_Analogue[1].reserve(strips);
+    data.m_Analogue[2].reserve(strips);
+  } else {
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// prepare gain and offset for the strips for a given module
+// ----------------------------------------------------------------------
+StatusCode SCT_FrontEnd::prepareGainAndOffset(SiChargedDiodeCollection& collection, /*const Identifier& moduleId,*/ CLHEP::HepRandomEngine * rndmEngine, SCT_FrontEndData& data) const {
+  // now we need to generate gain and offset channel by channel: some algebra
+  // for generation of partially correlated random numbers
+  float W = m_OGcorr * m_GainRMS * m_Ospread / (m_GainRMS * m_GainRMS - m_Ospread * m_Ospread);
+  float A = 4 * W * W + 1.0;
+  float x1 = (A - sqrt(A)) / (2.0 * A);
+  float sinfi = sqrt(x1);
+  float cosfi = sqrt(1.0 - x1);
+
+  sinfi = sinfi * m_OGcorr / fabs(m_OGcorr);
+  float S = m_GainRMS * m_GainRMS + m_Ospread * m_Ospread;
+  float D = (m_GainRMS * m_GainRMS - m_Ospread * m_Ospread) / (cosfi * cosfi - sinfi * sinfi);
+  float S1 = sqrt((S + D) * 0.5);
+  float S2 = sqrt((S - D) * 0.5);
+  float Noise = 0;
+  int mode = 1;
+
+  // To set noise values for different module types, barrel, EC, inners, middles, short middles, and outers
+  if (m_analogueNoiseOn) {
+    // if (m_sct_id->barrel_ec(moduleId) == 0) { // barrel_ec=0 corresponds to barrel
+    //   if (m_sct_id->layer_disk(moduleId) == 3) { // outer barrel layer 10 degrees warmer
+        Noise = m_NoiseBarrel3;
+    //   } else {
+    //     Noise = m_NoiseBarrel;
+    //   }
+    // } else {
+    //   int moduleType = m_sct_id->eta_module(moduleId);
+    //   switch (moduleType) { // eta = 0, 1, or 2 corresponds to outers, middles and inners?! (at least in the offline world)
+    //   case 0: {
+    //     Noise = m_NoiseOuters;
+    //     break;
+    //   }
+    //   case 1: {
+    //     if (m_sct_id->layer_disk(moduleId) == 7) {
+    //       Noise = m_NoiseShortMiddles;
+    //     } else {
+    //       Noise = m_NoiseMiddles;
+    //     }
+    //     break;
+    //   }
+    //   case 2: {
+    //     Noise = m_NoiseInners;
+    //     break;
+    //   }
+    //   default: {
+    //     Noise = m_NoiseBarrel;
+    //     ATH_MSG_ERROR("moduleType(eta): " << moduleType << " unknown, using barrel");
+    //   }
+    //   }// end of switch structure
+    // }
+  }
+
+  // Loop over collection and setup gain/offset/noise for the hit and neighbouring strips
+  SiChargedDiodeIterator i_chargedDiode = collection.begin();
+  SiChargedDiodeIterator i_chargedDiode_end = collection.end();
+
+  for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+    SiChargedDiode diode = (*i_chargedDiode).second;
+    // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
+    unsigned int flagmask = diode.flag() & 0xFE;
+    // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
+    if (!flagmask) { // If the diode is OK (not flagged)
+      const SiReadoutCellId roCell = diode.getReadoutCell();
+      if (roCell.isValid()) {
+        int strip = roCell.strip();
+        int i = std::max(strip - 1, 0);
+        int i_end = std::min(strip + 2, m_strip_max.load());
+
+        // loop over strips
+        for (; i < i_end; i++) {
+          // Need to check if strip is already setup
+          if (data.m_Analogue[1][i] <= 0.0) {
+            float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S1);
+            float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S2);
+
+            data.m_GainFactor[i] = 1.0 + (cosfi * g + sinfi * o);
+            data.m_Offset[i] = (cosfi * o - sinfi * g);
+            data.m_NoiseFactor[i] = Noise * mode;
+
+            // Fill the noise and offset values into the Analogue
+            if (m_data_compression_mode == 1 and m_data_readout_mode == 0) { // level mode x1x
+              data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+            } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) { // edge mode 01x
+              data.m_Analogue[0][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+              data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+            } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) { // any hit mode xxx or expanded read out mode
+              data.m_Analogue[0][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+              data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+              data.m_Analogue[2][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// prepare gain and offset for the strips for a given module using
+// Cond Db data to get the chip calibration data
+// ----------------------------------------------------------------------
+// StatusCode SCT_FrontEnd::prepareGainAndOffset(SiChargedDiodeCollection& collection, int side, const Identifier& moduleId, CLHEP::HepRandomEngine * rndmEngine, SCT_FrontEndData& data) const {
+//   // Get chip data from calib DB
+//   std::vector<float> gainByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "GainByChip");
+//   std::vector<float> gainRMSByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "GainRMSByChip");
+//   std::vector<float> offsetByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "OffsetByChip");
+//   std::vector<float> offsetRMSByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "OffsetRMSByChip");
+//   std::vector<float> noiseByChipVect(6, 0.0);
+
+//   if (m_analogueNoiseOn) { // Check if noise should be on or off
+//     noiseByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "NoiseByChip");
+//   }
+
+//   // Need to check if empty, most should have data, but a few old DEAD modules don't
+//   if (gainByChipVect.empty() or noiseByChipVect.empty()) {
+//     ATH_MSG_DEBUG("No calibration data in cond DB for module " << moduleId << " using JO values");
+//     if (StatusCode::SUCCESS != prepareGainAndOffset(collection, moduleId, rndmEngine, data)) {
+//       return StatusCode::FAILURE;
+//     } else {
+//       return StatusCode::SUCCESS;
+//     }
+//   }
+
+//   // Don't really need to set up values for each chip...
+//   float gainMeanValue = meanValue(gainByChipVect);
+//   if (gainMeanValue < 0.0) {
+//     ATH_MSG_DEBUG("All chip gain values are 0 for module " << moduleId << " using JO values");
+//     if (StatusCode::SUCCESS != prepareGainAndOffset(collection, moduleId, rndmEngine, data)) {
+//       return StatusCode::FAILURE;
+//     } else {
+//       return StatusCode::SUCCESS;
+//     }
+//   }
+
+//   std::vector<float> gain(6, 0.0);
+//   std::vector<float> offset(6, 0.0);
+//   std::vector<float> S1(6, 0.0);
+//   std::vector<float> S2(6, 0.0);
+//   std::vector<float> sinfi(6, 0.0);
+//   std::vector<float> cosfi(6, 0.0);
+//   float gainRMS = 0.0;
+//   float offsetRMS = 0.0;
+
+//   for (int i = 0; i < 6; ++i) {
+//     // Some very few chips have 0 values, dead/bypassed/etc, so check and use some fixed values instead
+//     if (gainByChipVect[i] > 0.1) {
+//       gain[i] = gainByChipVect[i] / gainMeanValue;
+//       offset[i] = offsetByChipVect[i] / m_Threshold;
+//       gainRMS = gainRMSByChipVect[i] / gainMeanValue;
+//       offsetRMS = offsetRMSByChipVect[i] / m_Threshold;
+//     } else {
+//       gain[i] = 55.0 / gainMeanValue;
+//       offset[i] = 42.0 / m_Threshold;
+//       gainRMS = 1.3 / gainMeanValue;
+//       offsetRMS = 2.0 / m_Threshold;
+//     }
+
+//     float W = m_OGcorr * gainRMS * offsetRMS / (gainRMS * gainRMS - offsetRMS * offsetRMS);
+//     float A = 4 * W * W + 1.0;
+//     float x1 = (A - sqrt(A)) / (2.0 * A);
+//     sinfi[i] = sqrt(x1);
+//     cosfi[i] = sqrt(1.0 - x1);
+//     sinfi[i] = sinfi[i] * m_OGcorr / fabs(m_OGcorr);
+//     float S = gainRMS * gainRMS + offsetRMS * offsetRMS;
+//     float D = (gainRMS * gainRMS - offsetRMS * offsetRMS) / (cosfi[i] * cosfi[i] - sinfi[i] * sinfi[i]);
+//     S1[i] = sqrt((S + D) / 2.0);
+//     S2[i] = sqrt((S - D) / 2.0);
+//   }
+
+//   // Loop over collection and setup gain/offset/noise for the hit and neighbouring strips
+//   SiChargedDiodeIterator i_chargedDiode = collection.begin();
+//   SiChargedDiodeIterator i_chargedDiode_end = collection.end();
+
+//   for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+//     SiChargedDiode diode = (*i_chargedDiode).second;
+//     // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
+//     unsigned int flagmask = diode.flag() & 0xFE;
+//     // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
+//     if (!flagmask) { // If the diode is OK (not flagged)
+//       const SiReadoutCellId roCell = diode.getReadoutCell();
+
+//       if (roCell.isValid()) {
+//         int strip = roCell.strip();
+//         int i = std::max(strip - 1, 0);
+//         int i_end = std::min(strip + 2, m_strip_max.load());
+
+//         // loop over strips
+//         for (; i < i_end; i++) {
+//           // Need to check if strip is already setup
+//           if (data.m_Analogue[1][i] <= 0.0) {
+//             // Values depends on which chip the strip is on (complex when strip is on chip edge)
+//             int chip = i / 128;
+//             float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S1[chip]);
+//             float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S2[chip]);
+
+//             data.m_GainFactor[i] = gain[chip] + (cosfi[chip] * g + sinfi[chip] * o);
+//             data.m_Offset[i] = offset[chip]   + (cosfi[chip] * o - sinfi[chip] * g);
+//             data.m_NoiseFactor[i] = noiseByChipVect[chip];
+
+//             // Fill the noise and offset values into the Analogue
+//             if (m_data_compression_mode == 1 and m_data_readout_mode == 0) { // level mode x1x
+//               data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//             } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) { // edge mode 01x
+//               data.m_Analogue[0][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//               data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//             } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) { // any hit mode xxx or expanded read out mode
+//               data.m_Analogue[0][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//               data.m_Analogue[1][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//               data.m_Analogue[2][i] = data.m_Offset[i] + data.m_NoiseFactor[i] * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
+//             }
+//           }
+//         }
+//       }
+//     }
+//   }
+
+//   return StatusCode::SUCCESS;
+// }
+
+// ----------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------
+StatusCode SCT_FrontEnd::randomNoise(SiChargedDiodeCollection& collection, /*const Identifier& moduleId,*/ CLHEP::HepRandomEngine * rndmEngine, SCT_FrontEndData& data) const {
+  // Add random noise
+
+  double occupancy = 0.0;
+  double NoiseOccupancy = 0.0;
+  float Noise = 0.0;
+  int nNoisyStrips = 0;
+  double mode = 1.;
+
+  const bool noise_expanded_mode = (m_data_compression_mode == 3 and m_data_readout_mode == 1);
+
+  // Will give 3 times as much noise occupancy if running in any hit expanded mode
+  if (noise_expanded_mode) {
+    mode = 3.;
+  }
+
+  // Sets fixed noise occupancy values for different module types, barrel, EC,
+  // inners, middles
+  // short middles, and outers
+//   if (m_sct_id->barrel_ec(moduleId) == 0) { // barrel_ec=0 corresponds to barrel
+//     if (m_sct_id->layer_disk(moduleId) == 3) { // outer barrel layer 10 degrees warmer
+      NoiseOccupancy = m_NOBarrel3;
+      Noise = m_NoiseBarrel3;
+//     } else {
+//       NoiseOccupancy = m_NOBarrel;
+//       Noise = m_NoiseBarrel;
+//     }
+//   } else {
+//     int moduleType = m_sct_id->eta_module(moduleId);
+//     switch (moduleType) { // eta = 0, 1, or 2 corresponds to outers, middles and inners?! (at least in the offline world)
+//     case 0: {
+//       NoiseOccupancy = m_NOOuters;
+//       Noise = m_NoiseOuters;
+//       break;
+//     }
+//     case 1: {
+//       if (m_sct_id->layer_disk(moduleId) == 7) {
+//         NoiseOccupancy = m_NOShortMiddles;
+//         Noise = m_NoiseShortMiddles;
+//       } else {
+//         NoiseOccupancy = m_NOMiddles;
+//         Noise = m_NoiseMiddles;
+//       }
+//       break;
+//     }
+//     case 2: {
+//       NoiseOccupancy = m_NOInners;
+//       Noise = m_NoiseInners;
+//       break;
+//     }
+//     default: {
+//       NoiseOccupancy = m_NOBarrel;
+//       Noise = m_NoiseBarrel;
+//       ATH_MSG_ERROR("moduleType(eta): " << moduleType << " unknown, using barrel");
+//     }
+//     }// end of switch structure
+//   }
+
+  // Calculate the number of "free strips"
+  int nEmptyStrips = 0;
+  std::vector<int> emptyStrips;
+  emptyStrips.reserve(m_strip_max);
+  for (int i = 0; i < m_strip_max; i++) {
+    if (data.m_StripHitsOnWafer[i] == 0) {
+      emptyStrips.push_back(i);
+      ++nEmptyStrips;
+    }
+  }
+
+  if (nEmptyStrips != 0) {
+    // Should randomize the fixed NO values, so we get some differences per
+    // wafer
+    occupancy = CLHEP::RandGaussZiggurat::shoot(rndmEngine, NoiseOccupancy, NoiseOccupancy * 0.1);
+
+    // Modify the occupancy if threshold is not 1.0 fC
+    if (m_Threshold > 6242.3 or m_Threshold < 6242.1) {
+      const float fC = 6242.2;
+      occupancy = occupancy * exp(-(0.5 / (Noise * Noise) * (m_Threshold * m_Threshold - fC * fC)));
+    }
+    nNoisyStrips = CLHEP::RandPoisson::shoot(rndmEngine, m_strip_max * occupancy * mode);
+
+    // Check and adapt the number of noisy strips to the number of free strips
+    if (nEmptyStrips < nNoisyStrips) {
+      nNoisyStrips = nEmptyStrips;
+    }
+
+    // Find random strips to get noise hits
+    for (int i = 0; i < nNoisyStrips; i++) {
+      int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStrips - i); // strip == 10, 12 free strips
+      // have vector [10000100100200211001] 20 strips
+      int strip = emptyStrips.at(index);
+      emptyStrips.erase(emptyStrips.begin()+index); // Erase it not to use it again
+      if (data.m_StripHitsOnWafer[strip]!=0) {
+        ATH_MSG_ERROR(index << "-th empty strip, strip " << strip << " should be empty but is not empty! Something is wrong!");
+      }
+      data.m_StripHitsOnWafer[strip] = 3; // !< Random Noise hit
+      // Add tbin info to noise diode
+      if (noise_expanded_mode) { // !< if any hit mode, any time bin otherwise fixed tbin=2
+        int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
+        // !< random number 0, 1 or 2
+        if (noise_tbin == 0) {
+          noise_tbin = 4; // !< now 1,2 or 4
+        }
+        if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, noise_tbin)) {
+          ATH_MSG_ERROR("Can't add noise hit diode to collection");
+        }
+      } else {
+        if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
+          ATH_MSG_ERROR("Can't add noise hit diode to collection");
+        }
+      }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------
+// StatusCode SCT_FrontEnd::randomNoise(SiChargedDiodeCollection& collection, const Identifier& moduleId, int side, CLHEP::HepRandomEngine * rndmEngine, SCT_FrontEndData& data) const {
+//   const int n_chips = 6;
+//   const int chipStripmax = m_strip_max / n_chips;
+//   std::vector<float> NOByChipVect(n_chips, 0.0);
+//   std::vector<float> ENCByChipVect(n_chips, 0.0);
+//   std::vector<int> nNoisyStrips(n_chips, 0);
+//   double mode = 1.;
+
+//   const bool noise_expanded_mode = (m_data_compression_mode == 3 and m_data_readout_mode == 1);
+
+//   // Will give 3 times as much noise occupancy if running in any hit expanded mode
+//   if (noise_expanded_mode) {
+//     mode = 3.;
+//   }
+
+//   // Get chip data from calib DB
+//   NOByChipVect = m_ReadCalibChipDataTool->getNoiseOccupancyData(moduleId, side, "OccupancyByChip");
+//   ENCByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "NoiseByChip");
+
+//   // Need to check if empty, most should have data, but a few old DEAD modules don't, and 9C...
+//   if (NOByChipVect.empty()) {
+//     ATH_MSG_DEBUG("No calibration data in cond DB for module " << moduleId << " using JO values");
+//     if (StatusCode::SUCCESS != randomNoise(collection, moduleId, rndmEngine, data)) {
+//       return StatusCode::FAILURE;
+//     } else {
+//       return StatusCode::SUCCESS;
+//     }
+//   } else {
+//     for (int i = 0; i < n_chips; i++) {
+//       // A 0 value can mean two things now, chip out of config for long time and no value was uploaded
+//       // or its short middles and inners and the value is for all purposes 0! so ok.
+
+//       // Modify the occupancy if threshold is not 1.0 fC
+//       if (m_Threshold > 6242.3 or m_Threshold < 6242.1) {
+//         constexpr float fC = 6242.2;
+//         NOByChipVect[i] = NOByChipVect[i] * exp(-(0.5 / (ENCByChipVect[i]*ENCByChipVect[i]) * (m_Threshold*m_Threshold - fC*fC)));
+//       }
+
+//       nNoisyStrips[i] = CLHEP::RandPoisson::shoot(rndmEngine, chipStripmax * NOByChipVect[i] * mode);
+//     }
+//   }
+
+//   // Loop over the chips on the wafer
+//   for (int chip_index = 0; chip_index < n_chips; ++chip_index) {
+//     int chip_strip_offset = chipStripmax * chip_index; // First strip number on chip
+
+//     // Calculate the number of "free strips" on this chip
+//     int nEmptyStripsOnChip = 0;
+//     std::vector<int> emptyStripsOnChip;
+//     emptyStripsOnChip.reserve(chipStripmax);
+//     for (int i = 0; i < chipStripmax; i++) {
+//       if (data.m_StripHitsOnWafer[i + chip_strip_offset] == 0) {
+//         emptyStripsOnChip.push_back(i);
+//         ++nEmptyStripsOnChip;
+//       }
+//     }
+
+//     // if no empty strips on chip do nothing
+//     if (nEmptyStripsOnChip != 0) {
+//       // Check and adapt the number of noisy strips to the number of free strips
+//       if (nEmptyStripsOnChip < nNoisyStrips[chip_index]) {
+//         nNoisyStrips[chip_index] = nEmptyStripsOnChip;
+//       }
+
+//       // Find random strips to get noise hits
+//       for (int i = 0; i < nNoisyStrips[chip_index]; i++) {
+//         int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStripsOnChip - i);
+//         int strip_on_chip = emptyStripsOnChip.at(index);
+//         emptyStripsOnChip.erase(emptyStripsOnChip.begin()+index); // Erase it not to use it again
+//         int strip = strip_on_chip + chip_strip_offset;
+//         if (data.m_StripHitsOnWafer[strip]!=0) {
+//           ATH_MSG_ERROR(index << "-th empty strip, strip " << strip << " should be empty but is not empty! Something is wrong!");
+//         }
+//         data.m_StripHitsOnWafer[strip] = 3; // !< Random Noise hit
+//         // Add tbin info to noise diode
+//         if (noise_expanded_mode) { // !< if any hit mode, any time bin
+//           // !< otherwise fixed tbin=2
+//           int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
+//           // !< random number 0, 1 or 2
+//           if (noise_tbin == 0) {
+//             noise_tbin = 4; // !< now 1, 2 or 4
+//           }
+//           if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, noise_tbin)) {
+//             ATH_MSG_ERROR("Can't add noise hit diode to collection");
+//           }
+//         } else {
+//           if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
+//             ATH_MSG_ERROR("Can't add noise hit diode to collection");
+//           }
+//         }
+//       }
+//     }
+//   }
+
+//   return StatusCode::SUCCESS;
+// }
+
+// ----------------------------------------------------------------------
+// process the collection of pre digits this will need to go through
+// all single-strip pre-digits calculate the amplifier response add noise
+// (this could be moved elsewhere later) apply threshold do clustering
+// ----------------------------------------------------------------------
+void SCT_FrontEnd::process(SiChargedDiodeCollection& collection, CLHEP::HepRandomEngine * rndmEngine) const {
+  // get SCT module side design and check it
+  const SCT_ModuleSideDesign *p_design = dynamic_cast<const SCT_ModuleSideDesign*>(&(collection.design()));
+
+  if (p_design==nullptr) {
+    return;
+  }
+
+  SCT_FrontEndData data;
+
+  // Check number of strips in design and from manager(max number of strips on any module)
+  // The design value should always be equal or lower than the manager one
+  // However, no resising is now done in case of a lower value
+  const int strip_max = p_design->cells();
+  // Init vectors
+  if (StatusCode::SUCCESS != initVectors(strip_max, data)) {
+    ATH_MSG_ERROR("Can't resize class variable vectors");
+    return;
+  }
+
+  // Contains strip hit info, reset to 0 for each wafer processed
+  data.m_StripHitsOnWafer.assign(m_strip_max, 0);
+
+  // Containes the charge for each bin on each hit strip
+  if (m_data_compression_mode == 1 and m_data_readout_mode == 0) {
+    for (int i = 0; i < m_strip_max; ++i) {
+      data.m_Analogue[1][i] = 0.0;
+    }
+  } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) {
+    for (int i = 0; i < m_strip_max; ++i) {
+      data.m_Analogue[0][i] = 0.0;
+      data.m_Analogue[1][i] = 0.0;
+    }
+  } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) {
+    for (int i = 0; i < m_strip_max; ++i) {
+      data.m_Analogue[0][i] = 0.0;
+      data.m_Analogue[1][i] = 0.0;
+      data.m_Analogue[2][i] = 0.0;
+    }
+  }
+
+  // Get wafer, moduleId and side
+//   Identifier waferId = collection.identify();
+//   Identifier moduleId = m_sct_id->module_id(waferId);
+//   const int side = m_sct_id->side(waferId);
+
+  // Check if collection empty
+  if (not collection.empty()) {
+    // Setup gain/offset/noise to the hit and neighbouring strips
+    if (m_useCalibData) { // Use calib cond DB data
+        ATH_MSG_FATAL("Use of calibration data not supported.");
+    //   if (StatusCode::SUCCESS != prepareGainAndOffset(collection, side, moduleId, rndmEngine, data)) {
+    //     ATH_MSG_ERROR("\tCan't prepare Gain and Offset");
+    //   }
+    } else { // Use JO values
+      if (StatusCode::SUCCESS != prepareGainAndOffset(collection, /*moduleId,*/ rndmEngine, data)) {
+        ATH_MSG_ERROR("\tCan't prepare Gain and Offset");
+      }
+    }
+
+    if (StatusCode::SUCCESS != doSignalChargeForHits(collection, data)) {
+      ATH_MSG_ERROR("\tCan't doSignalChargeForHits");
+    }
+
+    if (StatusCode::SUCCESS != doThresholdCheckForRealHits(collection, data)) {
+      ATH_MSG_ERROR("\tCan't doThresholdCheckForRealHits");
+    }
+
+    if (StatusCode::SUCCESS != doThresholdCheckForCrosstalkHits(collection, data)) {
+      ATH_MSG_ERROR("\tCan't doThresholdCheckForCrosstalkHits");
+    }
+  }
+
+  if (m_NoiseOn) {
+    if (m_useCalibData) { // Check if using DB or not
+        ATH_MSG_FATAL("Use of calibration data not supported.");
+    //   if (StatusCode::SUCCESS != randomNoise(collection, moduleId, side, rndmEngine, data)) {
+    //     ATH_MSG_ERROR("\tCan't do random noise on wafer?!");
+    //   }
+    } else { // Use JO fixed values
+      if (StatusCode::SUCCESS != randomNoise(collection, /*moduleId,*/ rndmEngine, data)) {
+        ATH_MSG_ERROR("\tCan't do random noise on wafer?!");
+      }
+    }
+  }
+
+  // Check for strips above threshold and do clustering
+  if (StatusCode::SUCCESS != doClustering(collection, data)) {
+    ATH_MSG_ERROR("\tCan't cluster the hits?!");
+  }
+}
+
+StatusCode SCT_FrontEnd::doSignalChargeForHits(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const {
+  typedef SiTotalCharge::list_t list_t;
+
+  // *****************************************************************************
+  // Loop over the diodes (strips ) and for each of them define the total signal
+  // *****************************************************************************
+
+  // set up number of needed bins depending on the compression mode
+  short bin_max = 0;
+  if (m_data_readout_mode == 0) {
+    bin_max = m_data_compression_mode;
+  } else {
+    bin_max = 3;
+  }
+
+  std::vector<float> response(bin_max);
+
+  SiChargedDiodeIterator i_chargedDiode = collection.begin();
+  SiChargedDiodeIterator i_chargedDiode_end = collection.end();
+  for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+    SiChargedDiode diode = (*i_chargedDiode).second;
+    // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
+    unsigned int flagmask = diode.flag() & 0xFE;
+    // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
+    if (!flagmask) { // If the diode is OK (not flagged)
+      const SiReadoutCellId roCell = diode.getReadoutCell();
+
+      if (roCell.isValid()) {
+        int strip = roCell.strip();
+
+        const list_t &ChargesOnStrip = diode.totalCharge().chargeComposition();
+
+        if (m_data_compression_mode == 1 and m_data_readout_mode == 0) { // level mode x1x
+          // Amplifier response
+          data.m_Analogue[1][strip] += data.m_GainFactor[strip] * m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold);
+
+          // Add Crosstalk signal for neighboring strip
+          response[0] = m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold);
+          if (strip + 1 < m_strip_max) {
+            data.m_Analogue[1][strip + 1] += data.m_GainFactor[strip + 1] * response[0];
+          }
+          if (strip > 0) {
+            data.m_Analogue[1][strip - 1] += data.m_GainFactor[strip - 1] * response[0];
+          }
+        } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) { // edge mode 01x
+          // Amplifier response
+          m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
+          for (short bin = 0; bin < bin_max; ++bin) {
+            data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
+          }
+          // Add Crosstalk signal for neighboring strip
+          m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
+          for (short bin = 0; bin < bin_max; ++bin) {
+            if (strip + 1 < m_strip_max) {
+              data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
+            }
+            if (strip > 0) {
+              data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
+            }
+          }
+        } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) { // any hit mode xxx or expanded read out mode
+          // Amplifier response
+          m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
+          for (short bin = 0; bin < bin_max; ++bin) {
+            data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
+          }
+          // Add Crosstalk signal for neighboring strip
+          m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
+          for (short bin = 0; bin < bin_max; ++bin) {
+            if (strip + 1 < m_strip_max) {
+              data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
+            }
+            if (strip > 0) {
+              data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
+            }
+          }
+        }
+      } else { // if roCell not valid
+        ATH_MSG_WARNING("\t Cannot get the cell ");
+      }
+    } else {// If diode is disconnected/disabled skip it
+      ATH_MSG_WARNING("\tDisabled or disconnected diode (strip)");
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_FrontEnd::doThresholdCheckForRealHits(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const {
+  // **********************************************************************************
+  // Flag strips below threshold and flag the threshold check into data.m_StripHitsOnWafer
+  // **********************************************************************************
+
+  SiChargedDiodeIterator i_chargedDiode = collection.begin();
+  SiChargedDiodeIterator i_chargedDiode_end = collection.end();
+
+  for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
+    SiChargedDiode& diode = (*i_chargedDiode).second;
+    SiReadoutCellId roCell = diode.getReadoutCell();
+    if (roCell.isValid()) {
+      int strip = roCell.strip();
+      if (strip > -1 and strip < m_strip_max) {
+        if (m_data_compression_mode == 1 and m_data_readout_mode == 0) { // level mode x1x
+          if (data.m_Analogue[1][strip] < m_Threshold) {
+            SiHelper::belowThreshold(diode, true);   // Below strip diode signal threshold
+            data.m_StripHitsOnWafer[strip] = -1;
+          } else if (((0x10 & diode.flag()) == 0x10) or ((0x4 & diode.flag()) == 0x4)) {
+            // previously a crazy strip number could have screwed things up here.
+            data.m_StripHitsOnWafer[strip] = -1;
+          } else {
+            data.m_StripHitsOnWafer[strip] = 1;
+            SiHelper::SetTimeBin(diode, 2, &msg()); // set timebin info
+          }
+        } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) { // edge mode 01x
+          if ((data.m_Analogue[0][strip] >= m_Threshold or data.m_Analogue[1][strip] < m_Threshold)) {
+            SiHelper::belowThreshold(diode, true);   // Below strip diode signal threshold
+            data.m_StripHitsOnWafer[strip] = -1;
+          } else if (((0x10 & diode.flag()) == 0x10) or ((0x4 & diode.flag()) == 0x4)) {
+            // previously a crazy strip number could have screwed things up here.
+            data.m_StripHitsOnWafer[strip] = -1;
+          } else {
+            data.m_StripHitsOnWafer[strip] = 1;
+            SiHelper::SetTimeBin(diode, 2, &msg()); // set timebin info
+          }
+        } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) { // Check hit pattern
+          int have_hit_bin = 0;
+          if (data.m_Analogue[0][strip] >= m_Threshold) {
+            have_hit_bin = 4;
+          }
+          if (data.m_Analogue[1][strip] >= m_Threshold) {
+            have_hit_bin += 2;
+          }
+          if (data.m_Analogue[2][strip] >= m_Threshold) {
+            have_hit_bin += 1;
+          }
+          if (((0x10 & diode.flag()) == 0x10) || ((0x4 & diode.flag()) == 0x4)) {
+            // previously a crazy strip number could have screwed things up here.
+            data.m_StripHitsOnWafer[strip] = -1;
+          } else if (m_data_compression_mode == 1) { // !< level and expanded mode
+            if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
+              data.m_StripHitsOnWafer[strip] = 1;
+              SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
+            } else {
+              SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
+              data.m_StripHitsOnWafer[strip] = -1;
+            }
+          } else if (m_data_compression_mode == 2) { // !< edge and expanded mode
+            if (have_hit_bin == 2 or have_hit_bin == 3) {
+              data.m_StripHitsOnWafer[strip] = 1;
+              SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
+            } else {
+              SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
+              data.m_StripHitsOnWafer[strip] = -1;
+            }
+          } else if (m_data_compression_mode == 3) { // !< any hit mode
+            if (have_hit_bin == 0) {
+              SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
+              data.m_StripHitsOnWafer[strip] = -1;
+            } else {
+              data.m_StripHitsOnWafer[strip] = 1;
+              if (m_data_readout_mode == 1) { // !< check for exp mode or not
+                SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
+              } else {
+                SiHelper::SetTimeBin(diode, 2, &msg());
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------
+StatusCode SCT_FrontEnd::doThresholdCheckForCrosstalkHits(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const {
+  // Check for noise+crosstalk strips above threshold
+  // data.m_StripHitsOnWafer: real hits above threshold == 1 or below/disconnected
+  // == -1
+  // =0 for free strips or strips with charge to be checked (data.m_Analogue[1]!=0)
+  // Set 2 for crosstalk noise hits and -2 for below ones
+
+  for (int strip = 0; strip < m_strip_max; strip++) {
+    // Find strips with data.m_StripHitsOnWafer[strip] == 0
+    if (data.m_StripHitsOnWafer[strip] != 0) { // real hits already checked
+      continue;
+    }
+    if (data.m_Analogue[1][strip] > 0) { // Better way of doing this?!
+                                    // set data.m_StripHitsOnWafer to x in prepareGainAndOffset
+      if (m_data_compression_mode == 1 and m_data_readout_mode == 0) { // level mode x1x
+        if (data.m_Analogue[1][strip] < m_Threshold) {
+          data.m_StripHitsOnWafer[strip] = -2; // Below threshold
+        } else {
+          data.m_StripHitsOnWafer[strip] = 2; // Crosstalk+Noise hit
+          if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
+            ATH_MSG_ERROR("Can't add noise hit diode to collection");
+          }
+        }
+      } else if (m_data_compression_mode == 2 and m_data_readout_mode == 0) { // edge mode 01x
+        if ((data.m_Analogue[0][strip] >= m_Threshold or data.m_Analogue[1][strip] < m_Threshold)) {
+          data.m_StripHitsOnWafer[strip] = -2; // Below threshold
+        } else {
+          data.m_StripHitsOnWafer[strip] = 2; // Crosstalk+Noise hit
+          if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
+            ATH_MSG_ERROR("Can't add noise hit diode to collection");
+          }
+        }
+      } else if (m_data_compression_mode == 3 or m_data_readout_mode == 1) {
+        int have_hit_bin = 0;
+        if (data.m_Analogue[0][strip] >= m_Threshold) {
+          have_hit_bin = 4;
+        }
+        if (data.m_Analogue[1][strip] >= m_Threshold) {
+          have_hit_bin += 2;
+        }
+        if (data.m_Analogue[2][strip] >= m_Threshold) {
+          have_hit_bin += 1;
+        }
+        if (m_data_compression_mode == 1) { // !< level and expanded mode
+          if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
+            data.m_StripHitsOnWafer[strip] = 2; // Crosstalk+Noise hit
+            if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
+              ATH_MSG_ERROR("Can't add noise hit diode to collection");
+            }
+          } else {
+            data.m_StripHitsOnWafer[strip] = -2; // Below threshold
+          }
+        } else if (m_data_compression_mode == 2) { // !< edge and expanded mode
+          if (have_hit_bin == 2 or have_hit_bin == 3) {
+            data.m_StripHitsOnWafer[strip] = 2; // Noise hit
+            if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
+              ATH_MSG_ERROR("Can't add noise hit diode to collection");
+            }
+          } else {
+            data.m_StripHitsOnWafer[strip] = -2; // Below threshold
+          }
+        } else if (m_data_compression_mode == 3) { // !< any hit mode
+          if (have_hit_bin == 0) {
+            data.m_StripHitsOnWafer[strip] = -2; // Below threshold
+          } else {
+            data.m_StripHitsOnWafer[strip] = 2; // !< Crosstalk+Noise hit
+            if (m_data_readout_mode == 1) { // !< check for exp mode or not
+              if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
+                ATH_MSG_ERROR("Can't add noise hit diode to collection");
+              }
+            } else {
+              if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
+                ATH_MSG_ERROR("Can't add noise hit diode to collection");
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_FrontEnd::doClustering(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const {
+  // ********************************
+  // now do clustering
+  // ********************************
+  int strip = 0;
+  int clusterSize = 0;
+
+  const SCT_ModuleSideDesign& sctDesign = dynamic_cast<const SCT_ModuleSideDesign&>(collection.design());
+
+  Identifier hitStrip;
+
+  if (m_data_readout_mode == 0) {
+    do {
+      if (data.m_StripHitsOnWafer[strip] > 0) {
+        // ====== First step: Get the cluster size
+        // ===================================================
+        int clusterFirstStrip = strip;
+
+        // Find end of cluster. In multi-row sensors, cluster cannot span rows.
+        int row = sctDesign.row(strip);
+        if (row < 0) {
+          row = 0;
+        }
+
+        int lastStrip1DInRow = 0;
+        for (int i = 0; i < row + 1; ++i) {
+          lastStrip1DInRow += sctDesign.diodesInRow(i);
+        }
+
+        while (strip < lastStrip1DInRow-1 and data.m_StripHitsOnWafer[strip +1] > 0) {
+          ++strip; // !< Find first strip hit and add up the following strips
+        }
+        int clusterLastStrip = strip;
+
+        clusterSize = (clusterLastStrip - clusterFirstStrip) + 1;
+        hitStrip = m_sct_id->strip_id(collection.identify(), clusterFirstStrip);
+        SiChargedDiode& HitDiode = *(collection.find(hitStrip));
+        SiHelper::SetStripNum(HitDiode, clusterSize, &msg());
+                                                                                      
+        SiChargedDiode *PreviousHitDiode = &HitDiode;
+        for (int i = clusterFirstStrip+1; i <= clusterLastStrip; ++i) {
+          hitStrip = m_sct_id->strip_id(collection.identify(), i);
+          SiChargedDiode& HitDiode2 = *(collection.find(hitStrip));
+          SiHelper::ClusterUsed(HitDiode2, true);
+          PreviousHitDiode->setNextInCluster(&HitDiode2);
+          PreviousHitDiode = &HitDiode2;
+        }
+      }
+      ++strip; // !< This is the starting point of the next cluster within this collection
+    } while (strip < m_strip_max);
+  } else {
+    // Expanded read out mode, basically one RDO/strip per cluster
+    // But if consecutively fired strips have the same time bin, those are converted into one cluster.
+    do {
+      clusterSize = 1;
+      if (data.m_StripHitsOnWafer[strip] > 0) {
+        hitStrip = m_sct_id->strip_id(collection.identify(), strip);
+        SiChargedDiode& hitDiode = *(collection.find(hitStrip));
+        int timeBin = SiHelper::GetTimeBin(hitDiode);
+        SiChargedDiode* previousHitDiode = &hitDiode;
+        // Check if consecutively fired strips have the same time bin
+        for (int newStrip=strip+1; newStrip<m_strip_max; newStrip++) {
+          if (not (data.m_StripHitsOnWafer[newStrip]>0)) break;
+          Identifier newHitStrip = m_sct_id->strip_id(collection.identify(), newStrip);
+          SiChargedDiode& newHitDiode = *(collection.find(newHitStrip));
+          if (timeBin!=SiHelper::GetTimeBin(newHitDiode)) break;
+          SiHelper::ClusterUsed(newHitDiode, true);
+          previousHitDiode->setNextInCluster(&newHitDiode);
+          previousHitDiode = &newHitDiode;
+          clusterSize++;
+        }
+        SiHelper::SetStripNum(hitDiode, clusterSize, &msg());
+
+#ifdef SCT_DIG_DEBUG
+        ATH_MSG_DEBUG("RDO Strip = " << strip << ", tbin = " <<
+                      SiHelper::GetTimeBin(hitDiode) <<
+                      ", HitInfo(1=real, 2=crosstalk, 3=noise): " <<
+                      data.m_StripHitsOnWafer[strip]);
+#endif
+      }
+      strip += clusterSize; // If more than one strip fires, those following strips are skipped.
+    } while (strip < m_strip_max);
+  }
+
+  // clusters below threshold, only from pre-digits that existed before no
+  // pure noise clusters below threshold will be made
+  // D. Costanzo. I don't see why we should cluster the strips below
+  // threshold. I'll pass on the info of strips below threshold
+  // to the SDOs. I'll leave the SCT experts the joy to change this if they
+  // don't like what I did or if this requires too much memory/disk
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_FrontEnd::addNoiseDiode(SiChargedDiodeCollection& collection, int strip, int tbin) const {
+  const SiCellId ndiode(strip); // !< create a new diode
+  const SiCharge noiseCharge(2 * m_Threshold, 0, SiCharge::noise); // !< add some noise to it
+  collection.add(ndiode, noiseCharge); // !< add it to the collection
+
+  // Get the strip back to check
+  const Identifier idstrip = m_sct_id->strip_id(collection.identify(), strip);
+  SiChargedDiode *NoiseDiode = (collection.find(idstrip));
+  if (NoiseDiode == nullptr) {
+    return StatusCode::FAILURE;
+  }
+  SiHelper::SetTimeBin(*NoiseDiode, tbin, &msg()); // set timebin info
+
+  return StatusCode::SUCCESS;
+}
+
+float SCT_FrontEnd::meanValue(std::vector<float>& calibDataVect) const {
+  float mean_value = 0.0;
+  int nData = 0;
+  const unsigned int vec_size = calibDataVect.size();
+
+  for (unsigned int i = 0; i < vec_size; ++i) {
+    if (calibDataVect[i] > 0.1) {
+      mean_value += calibDataVect[i];
+      ++nData;
+    }
+  }
+
+  if (nData == 0) {
+    return -1;
+  } else {
+    return mean_value / nData;
+  }
+}
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.h
new file mode 100644
index 0000000000000000000000000000000000000000..03f34b2c9c1681ff32f919bde33c80f6ef7a1b0f
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_FrontEnd.h
@@ -0,0 +1,140 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * Header file for SCT_FrontEnd Class 
+ * @brief simulation of the SCT front-end electronics
+ * working as a SiPreDigitsProcessor
+ * models response of ABCD chip amplifiers to 
+ * collected charges, also does cross-talk, offset
+ * variation and gain variation, in a correlated way
+ * Version 1.0 04.05.2001 Szymon Gadomski
+ * 1.1 07.06.2001 pass amplifier and design as pointers
+ * 1.2, 15/06/2001, compiles with framework and tested
+ * 31.07.2001 changes, constructor now without design
+ * design is only known to process method (from the collection)
+ * 10.08.2001 dedided not to use AlwaysSame flag
+ * Implementation for using it may be provided later
+ * @author Szymon.Gadomski@cern.ch, Awatif.Belymam@cern.ch, Davide.Costanzo@cern.ch,
+ * tgcornel@nikhef.nl, Grant.Gorfine@cern.ch, Paul.Bell@cern.ch, Jorgen.Dalmau@cern.ch,
+ * 23/08/2007 - Kondo.Gnanvo@cern.ch
+ *            - Conversion of the SCT_Front code Al gTool 
+ */
+
+#ifndef FASERSCT_DIGITIZATION_SCT_FRONTEND_H
+#define FASERSCT_DIGITIZATION_SCT_FRONTEND_H
+
+// Inheritance
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FaserSCT_Digitization/ISCT_FrontEnd.h"
+
+// Athena
+#include "FaserSiDigitization/SiChargedDiodeCollection.h"
+// #include "SCT_ConditionsTools/ISCT_ReadCalibChipDataTool.h"
+
+// Gaudi
+#include "GaudiKernel/ToolHandle.h"
+
+// STL
+#include <atomic>
+#include <mutex>
+#include <vector>
+
+class ISCT_Amp;
+class FaserSCT_ID;
+
+namespace TrackerDD {
+  class SCT_DetectorManager;
+}
+
+namespace CLHEP {
+  class HepRandomEngine;
+}
+/**
+ * @brief simulation of the SCT front-end electronics
+ * working as a SiPreDigitsProcessor
+ * models response of ABCD chip amplifiers to 
+ * collected charges, also does cross-talk, offset
+ * variation and gain variation, in a correlated way
+ */
+
+struct SCT_FrontEndData {
+  std::vector<float> m_Offset; //!< generate offset per channel
+  std::vector<float> m_GainFactor; //!< generate gain per channel  (added to the gain per chip from calib data)
+  std::vector<float> m_NoiseFactor; //!< Kondo: 31/08/07 noise per channel (actually noise per chip from calib data)
+  std::vector<double> m_Analogue[3];  //!< To hold the noise and amplifier response
+  std::vector<int> m_StripHitsOnWafer; //!< Info about which strips are above threshold
+};
+
+class  SCT_FrontEnd : public extends<AthAlgTool, ISCT_FrontEnd> {
+
+ public:
+
+  /**  constructor */
+  SCT_FrontEnd(const std::string& type, const std::string& name, const IInterface* parent);
+  /** Destructor */
+  virtual ~SCT_FrontEnd() = default;
+  //PJ not needed after merging?!
+  /** AlgTool InterfaceID */
+  //static const InterfaceID& interfaceID();
+  
+  /** AlgTool initialize */
+  virtual StatusCode initialize() override;
+  /** AlgTool finalize */
+  virtual StatusCode finalize() override;
+
+  /**
+   * process the collection of pre digits: needed to go through all single-strip pre-digits to calculate
+   * the amplifier response add noise (this could be moved elsewhere later) apply threshold do clustering
+   */
+  virtual void process(SiChargedDiodeCollection& collection, CLHEP::HepRandomEngine* rndmEngine) const override;
+  StatusCode doSignalChargeForHits(SiChargedDiodeCollection& collectione, SCT_FrontEndData& data) const;
+  StatusCode doThresholdCheckForRealHits(SiChargedDiodeCollection& collectione, SCT_FrontEndData& data) const;
+  StatusCode doThresholdCheckForCrosstalkHits(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const;
+  StatusCode doClustering(SiChargedDiodeCollection& collection, SCT_FrontEndData& data) const;
+  StatusCode prepareGainAndOffset(SiChargedDiodeCollection& collection, /*const Identifier& moduleId,*/ CLHEP::HepRandomEngine* rndmEngine, SCT_FrontEndData& data) const;
+//   StatusCode prepareGainAndOffset(SiChargedDiodeCollection& collection, int side, const Identifier& moduleId, CLHEP::HepRandomEngine* rndmEngine, SCT_FrontEndData& data) const;
+  StatusCode randomNoise(SiChargedDiodeCollection& collection, /*const Identifier& moduleId,*/ CLHEP::HepRandomEngine* rndmEngine, SCT_FrontEndData& data) const;
+//   StatusCode randomNoise(SiChargedDiodeCollection& collection, const Identifier& moduleId, int side, CLHEP::HepRandomEngine* rndmEngine, SCT_FrontEndData& data) const;
+  StatusCode addNoiseDiode(SiChargedDiodeCollection& collection, int strip, int tbin) const;
+  float meanValue(std::vector<float>& calibDataVect) const;
+  StatusCode initVectors(int strips, SCT_FrontEndData& data) const;
+
+ private:
+
+  FloatProperty m_NoiseBarrel{this, "NoiseBarrel", 1500.0, "Noise factor, Barrel  (in the case of no use of calibration data)"};
+  FloatProperty m_NoiseBarrel3{this, "NoiseBarrel3", 1541.0, "Noise factor, Barrel3  (in the case of no use of calibration data)"};
+  FloatProperty m_NoiseInners{this, "NoiseInners", 1090.0, "Noise factor, EC Inners  (in the case of no use of calibration data)"};
+  FloatProperty m_NoiseMiddles{this, "NoiseMiddles", 1557.0, "Noise factor, EC Middles (in the case of no use of calibration data)"};
+  FloatProperty m_NoiseShortMiddles{this, "NoiseShortMiddles", 940.0, "Noise factor, EC Short Middles (in the case of no use of calibration data)"};
+  FloatProperty m_NoiseOuters{this, "NoiseOuters", 1618.0, "Noise factor, Ec Outers  (in the case of no use of calibration data)"};
+  DoubleProperty m_NOBarrel{this, "NOBarrel", 1.5e-5, "Noise factor, Barrel  (in the case of no use of calibration data)"};
+  DoubleProperty m_NOBarrel3{this, "NOBarrel3", 2.1e-5, "Noise factor, Barrel3  (in the case of no use of calibration data)"};
+  DoubleProperty m_NOInners{this, "NOInners", 5.0e-9, "Noise Occupancy, EC Inners  (in the case of no use of calibration data)"};
+  DoubleProperty m_NOMiddles{this, "NOMiddles", 2.7e-5, "Noise Occupancy, EC Middles (in the case of no use of calibration data)"};
+  DoubleProperty m_NOShortMiddles{this, "NOShortMiddles", 2.0e-9, "Noise Occupancy, EC Short Middles (in the case of no use of calibration data)"};
+  DoubleProperty m_NOOuters{this, "NOOuters", 3.5e-5, "Noise Occupancy, Ec Outers  (in the case of no use of calibration data)"};
+  BooleanProperty m_NoiseOn{this, "NoiseOn", true, "To know if noise is on or off when using calibration data"};
+  BooleanProperty m_analogueNoiseOn{this, "AnalogueNoiseOn", true, "To know if analogue noise is on or off"};
+  FloatProperty m_GainRMS{this, "GainRMS", 0.031, "Gain spread parameter within the strips for a given Chip gain"};
+  FloatProperty m_Ospread{this, "Ospread", 0.0001, "offset spread within the strips for a given Chip offset"};
+  FloatProperty m_OGcorr{this, "OffsetGainCorrelation", 0.00001, "Gain/offset correlation for the strips"};
+  FloatProperty m_Threshold{this, "Threshold", 1.0, "Threshold"};
+  FloatProperty m_timeOfThreshold{this, "TimeOfThreshold", 30.0, "Threshold time"};
+  ShortProperty m_data_compression_mode{this, "DataCompressionMode", 1, "Front End Data Compression Mode"};
+  ShortProperty m_data_readout_mode{this, "DataReadOutMode", 0, "Front End Data Read out mode Mode"};
+  BooleanProperty m_useCalibData{this, "UseCalibData", false, "Flag to set the use of calibration data for noise, Gain,offset etc."}; // was true in ATLAS
+
+  ToolHandle<ISCT_Amp> m_sct_amplifier{this, "SCT_Amp", "SCT_Amp", "Handle the Amplifier tool"}; //!< Handle the Amplifier tool
+//   ToolHandle<ISCT_ReadCalibChipDataTool> m_ReadCalibChipDataTool{this, "SCT_ReadCalibChipDataTool", "SCT_ReadCalibChipDataTool", "Tool to retrieve chip calibration information"}; //!< Handle to the Calibration ConditionsTool
+
+  const TrackerDD::SCT_DetectorManager* m_SCTdetMgr{nullptr}; //!< Handle to SCT detector manager
+  const FaserSCT_ID* m_sct_id{nullptr}; //!< Handle to SCT ID helper
+
+  mutable std::atomic_int m_strip_max{768}; //!< For SLHC studies
+};
+
+#endif //SCT_FRONTEND_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b170bd10f5c166e02e8258d5138f0fdd7fc23cac
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.cxx
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_RandomDisabledCellGenerator.h"
+
+#include "FaserSiDigitization/SiChargedDiodeCollection.h"
+
+#include "FaserSiDigitization/SiHelper.h"
+
+#include "CLHEP/Random/RandomEngine.h"
+#include "CLHEP/Random/RandFlat.h"
+
+// constructor
+SCT_RandomDisabledCellGenerator::SCT_RandomDisabledCellGenerator(const std::string& type, const std::string& name, const IInterface* parent)
+  : base_class(type, name, parent)
+{
+}
+
+StatusCode SCT_RandomDisabledCellGenerator::initialize() {
+  ATH_MSG_DEBUG("SCT_RandomDisabledCellGenerator::initialize()");
+  ATH_MSG_INFO("\tCreating missing bond generator with "<<m_disableProbability<<" probability");
+  return StatusCode::SUCCESS;
+}
+
+StatusCode SCT_RandomDisabledCellGenerator::finalize() {
+  ATH_MSG_INFO("SCT_RandomDisabledCellGenerator::finalize()");
+  return StatusCode::SUCCESS;
+}
+
+// process the collection 
+void SCT_RandomDisabledCellGenerator::process(SiChargedDiodeCollection& collection, CLHEP::HepRandomEngine * rndmEngine) const {
+  // disabling is applied to all cells even unconnected or below threshold ones to be able to use these cells as well
+  // loop on all charged diodes
+  for (std::pair<const TrackerDD::SiCellId, SiChargedDiode>& chargedDiode: collection) {
+    if (CLHEP::RandFlat::shoot(rndmEngine)<m_disableProbability) {
+      SiHelper::disconnected(chargedDiode.second, true, false);
+    }
+  }
+}
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ea27123d73228fb6fd62fb6960ed8daa24472be
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_RandomDisabledCellGenerator.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_RandomDisabledCellGenerator.h
+//   Header file for class SCT_RandomDisabledCellGenerator 
+///////////////////////////////////////////////////////////////////
+// Class to randomly disable cells for SCT
+///////////////////////////////////////////////////////////////////
+// Version 1.0 25/07/2007 Kondo Gnanvo
+//   - Randomly select a cell and modify its flag by using the pointer to 
+//     a SiHelper function.
+//   - Inherits from ISiChargedDiodeProcessor, as SiPreDiodeProcessor
+//     has been discontinued
+// This can be used for disabling, disconnecting, and flagging bad_tot
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERSCT_DIGITIZATION_SCT_RANDOMDISABLEDCELLGENERATOR_H
+#define FASERSCT_DIGITIZATION_SCT_RANDOMDISABLEDCELLGENERATOR_H
+
+//Inheritance
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FaserSCT_Digitization/ISCT_RandomDisabledCellGenerator.h"
+
+class SiChargedDiode;
+class SiChargedDiodeCollection;
+
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+class SCT_RandomDisabledCellGenerator : public extends<AthAlgTool, ISCT_RandomDisabledCellGenerator> {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+
+ public:
+
+  /**  constructor */
+  SCT_RandomDisabledCellGenerator(const std::string& type, const std::string& name, const IInterface* parent) ;
+
+  /** Destructor */
+  virtual ~SCT_RandomDisabledCellGenerator() = default;
+
+  /** AlgTool initialize */
+  virtual StatusCode initialize() override;
+  /** AlgTool finalize */
+  virtual StatusCode finalize() override;
+
+  virtual void process(SiChargedDiodeCollection& collection, CLHEP::HepRandomEngine * rndmEngine) const override;
+
+ private:
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+ private:
+
+  FloatProperty m_disableProbability{this, "TotalBadChannels", 0.01, "probability that a cell is disabled"};
+
+};
+
+#endif //FASERSCT_DIGITIZATION_SCT_RANDOMDISABLEDCELLGENERATOR_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b05cd7b4468a07ce90afc0346eeb6f07ed77d442
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.cxx
@@ -0,0 +1,578 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SCT_SurfaceChargesGenerator.h"
+
+// DD
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerReadoutGeometry/SCT_ModuleSideDesign.h"
+
+// Athena
+#include "GeneratorObjects/HepMcParticleLink.h"
+#include "TrackerSimEvent/FaserSiHit.h" // for SiHit, SiHit::::xDep, etc
+#include "HitManagement/TimedHitPtr.h" // for TimedHitPtr
+
+// ROOT
+#include "TH1.h" // for TH1F
+#include "TH2.h" // for TH2F
+#include "TProfile.h" // for TProfile
+
+// CLHEP
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Random/RandomEngine.h"
+#include "CLHEP/Random/RandGaussZiggurat.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+// STL
+#include <cmath>
+
+using TrackerDD::SiDetectorElement;
+using TrackerDD::SCT_ModuleSideDesign;
+using TrackerDD::SiLocalPosition;
+
+using namespace std;
+
+// constructor
+SCT_SurfaceChargesGenerator::SCT_SurfaceChargesGenerator(const std::string& type,
+                                                         const std::string& name,
+                                                         const IInterface* parent)
+  : base_class(type, name, parent) {
+}
+
+// ----------------------------------------------------------------------
+// Initialize
+// ----------------------------------------------------------------------
+StatusCode SCT_SurfaceChargesGenerator::initialize() {
+  ATH_MSG_DEBUG("SCT_SurfaceChargesGenerator::initialize()");
+
+  // Get ISiPropertiesTool
+  ATH_CHECK(m_siPropertiesTool.retrieve());
+
+  // Get ISiliconConditionsSvc
+//   ATH_CHECK(m_siConditionsTool.retrieve());
+
+  if (m_doTrapping) {
+    // -- Get Radiation Damage Tool
+    ATH_MSG_FATAL("Radiation damage tool not supported.");
+//     ATH_CHECK(m_radDamageTool.retrieve());
+//   } else {
+//     m_radDamageTool.disable();
+  }
+
+//   if (m_doHistoTrap) {
+//     // -- Get Histogram Service
+//     ATH_CHECK(m_thistSvc.retrieve());
+
+//     m_h_efieldz = new TProfile("efieldz", "", 50, 0., 0.4);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/efieldz", m_h_efieldz));
+
+//     m_h_efield = new TH1F("efield", "", 100, 200., 800.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/efield", m_h_efield));
+
+//     m_h_spess = new TH1F("spess", "", 50, 0., 0.4);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/spess", m_h_spess));
+
+//     m_h_depD = new TH1F("depD", "", 50, -0.3, 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/depD", m_h_depD));
+
+//     m_h_drift_electrode = new TH2F("drift_electrode", "", 50, 0., 20., 50, 0., 20.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/drift_electrode", m_h_drift_electrode));
+
+//     m_h_drift_time = new TH1F("drift_time", "", 100, 0., 20.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/drift_time", m_h_drift_time));
+
+//     m_h_t_electrode = new TH1F("t_electrode", "", 100, 0., 20.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/t_electrode", m_h_t_electrode));
+
+//     m_h_ztrap = new TH1F("ztrap", "", 100, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/ztrap", m_h_ztrap));
+
+//     // More histograms to check what's going on
+//     m_h_zhit = new TH1F("zhit", "", 50, -0.2, 0.2);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/zhit", m_h_zhit));
+
+//     m_h_ztrap_tot = new TH1F("ztrap_tot", "", 100, 0., 0.5);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/ztrap_tot", m_h_ztrap_tot));
+
+//     m_h_no_ztrap = new TH1F("no_ztrap", "", 100, 0., 0.5);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/no_ztrap", m_h_no_ztrap));
+
+//     m_h_trap_drift_t = new TH1F("trap_drift_t", "", 100, 0., 20.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/trap_drift_t", m_h_trap_drift_t));
+
+//     m_h_notrap_drift_t = new TH1F("notrap_drift_t", "", 100, 0., 20.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/notrap_drift_t", m_h_notrap_drift_t));
+
+//     m_h_mob_Char = new TProfile("mob_Char", "", 200, 100., 1000.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/mob_Char", m_h_mob_Char));
+
+//     m_h_vel = new TProfile("vel", "", 100, 100., 1000.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/vel", m_h_vel));
+
+//     m_h_drift1 = new TProfile("drift1", "", 50, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/drift1", m_h_drift1));
+
+//     m_h_gen = new TProfile("gen", "", 50, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/gen", m_h_gen));
+
+//     m_h_gen1 = new TProfile("gen1", "", 50, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/gen1", m_h_gen1));
+
+//     m_h_gen2 = new TProfile("gen2", "", 50, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/gen2", m_h_gen2));
+
+//     m_h_velocity_trap = new TProfile("velocity_trap", "", 50, 0., 1000.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/velocity_trap", m_h_velocity_trap));
+
+//     m_h_mobility_trap = new TProfile("mobility_trap", "", 50, 100., 1000.);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/mobility_trap", m_h_mobility_trap));
+
+//     m_h_trap_pos = new TH1F("trap_pos", "", 100, 0., 0.3);
+//     ATH_CHECK(m_thistSvc->regHist("/file1/trap_pos", m_h_trap_pos));
+//   }
+  ///////////////////////////////////////////////////
+
+  m_smallStepLength.setValue(m_smallStepLength.value() * CLHEP::micrometer);
+  m_tSurfaceDrift.setValue(m_tSurfaceDrift.value() * CLHEP::ns);
+
+  // Surface drift time calculation Stuff
+  m_tHalfwayDrift = m_tSurfaceDrift * 0.5;
+  m_distHalfInterStrip = m_distInterStrip * 0.5;
+  if ((m_tSurfaceDrift > m_tHalfwayDrift) and (m_tHalfwayDrift >= 0.0) and
+      (m_distHalfInterStrip > 0.0) and (m_distHalfInterStrip < m_distInterStrip)) {
+    m_SurfaceDriftFlag = true;
+  } else {
+    ATH_MSG_INFO("\tsurface drift still not on, wrong params");
+  }
+
+  // Make sure these two flags are not set simultaneously
+  if (m_tfix>-998. and m_tsubtract>-998.) {
+    ATH_MSG_FATAL("\tCannot set both FixedTime and SubtractTime options!");
+    ATH_MSG_INFO("\tMake sure the two flags are not set simultaneously in jo");
+    return StatusCode::FAILURE;
+  }
+
+  if (m_doDistortions) {
+      ATH_MSG_FATAL("Distortions not supported.");
+//     ATH_CHECK(m_distortionsTool.retrieve());
+//   } else {
+//     m_distortionsTool.disable();
+  }
+
+  ATH_CHECK(m_lorentzAngleTool.retrieve());
+
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// finalize
+// ----------------------------------------------------------------------
+StatusCode SCT_SurfaceChargesGenerator::finalize() {
+  ATH_MSG_DEBUG("SCT_SurfaceChargesGenerator::finalize()");
+  return StatusCode::SUCCESS;
+}
+
+// ----------------------------------------------------------------------
+// perpandicular Drift time calculation
+// ----------------------------------------------------------------------
+float SCT_SurfaceChargesGenerator::driftTime(float zhit, const SiDetectorElement* element) const {
+  if (element==nullptr) {
+    ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process element is nullptr");
+    return -2.0;
+  }
+  const SCT_ModuleSideDesign* design{dynamic_cast<const SCT_ModuleSideDesign*>(&(element->design()))};
+  if (design==nullptr) {
+    ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process can not get " << design);
+    return -2.0;
+  }
+  const double thickness{design->thickness()};
+  const IdentifierHash hashId{element->identifyHash()};
+
+  if ((zhit < 0.0) or (zhit > thickness)) {
+    ATH_MSG_DEBUG("driftTime: hit coordinate zhit=" << zhit / CLHEP::micrometer << " out of range");
+    return -2.0;
+  }
+
+  float depletionVoltage{0.};
+  float biasVoltage{0.};
+  if (m_useSiCondDB) {
+      ATH_MSG_FATAL("Conditions DB voltages not supported.");
+    // depletionVoltage = m_siConditionsTool->depletionVoltage(hashId) * CLHEP::volt;
+    // biasVoltage = m_siConditionsTool->biasVoltage(hashId) * CLHEP::volt;
+  } else {
+    depletionVoltage = m_vdepl * CLHEP::volt;
+    biasVoltage = m_vbias * CLHEP::volt;
+  }
+
+  const float denominator{static_cast<float>(depletionVoltage + biasVoltage - (2.0 * zhit * depletionVoltage / thickness))};
+  if (denominator <= 0.0) {
+    if (biasVoltage >= depletionVoltage) { // Should not happen
+      if(not m_isOverlay) {
+        ATH_MSG_ERROR("driftTime: negative argument X for log(X) " << zhit);
+      }
+      return -1.0;
+    } else { 
+      // (m_biasVoltage<m_depletionVoltage) can happen with underdepleted sensors, lose charges in that volume
+      return -10.0;
+    }
+  }
+
+  float t_drift{log((depletionVoltage + biasVoltage) / denominator)};
+  t_drift *= thickness * thickness / (2.0 * m_siPropertiesTool->getSiProperties(hashId).holeDriftMobility() * depletionVoltage);
+  return t_drift;
+}
+
+// ----------------------------------------------------------------------
+// Sigma diffusion calculation
+// ----------------------------------------------------------------------
+float SCT_SurfaceChargesGenerator::diffusionSigma(float zhit, const SiDetectorElement* element) const {
+  if (element==nullptr) {
+    ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::diffusionSigma element is nullptr");
+    return 0.0;
+  }
+  const IdentifierHash hashId{element->identifyHash()};
+  const float t{driftTime(zhit, element)}; // in ns
+
+  if (t > 0.0) {
+    const float sigma{static_cast<float>(sqrt(2. * m_siPropertiesTool->getSiProperties(hashId).holeDiffusionConstant() * t))}; // in mm
+    return sigma;
+  } else {
+    return 0.0;
+  }
+}
+
+// ----------------------------------------------------------------------
+// Maximum drift time
+// ----------------------------------------------------------------------
+float SCT_SurfaceChargesGenerator::maxDriftTime(const SiDetectorElement* element) const {
+  if (element) {
+    const float sensorThickness{static_cast<float>(element->thickness())};
+    return driftTime(sensorThickness, element);
+  } else {
+    ATH_MSG_INFO("Error: SiDetectorElement not set!");
+    return 0.;
+  }
+}
+
+// ----------------------------------------------------------------------
+// Maximum Sigma difusion
+// ----------------------------------------------------------------------
+float SCT_SurfaceChargesGenerator::maxDiffusionSigma(const SiDetectorElement* element) const {
+  if (element) {
+    const float sensorThickness{static_cast<float>(element->thickness())};
+    return diffusionSigma(sensorThickness, element);
+  } else {
+    ATH_MSG_INFO("Error: SiDetectorElement not set!");
+    return 0.;
+  }
+}
+
+// ----------------------------------------------------------------------
+// Calculating the surface drift time but I should confess that
+// I haven't found out yet where the calculation come from
+// ----------------------------------------------------------------------
+float SCT_SurfaceChargesGenerator::surfaceDriftTime(float ysurf) const {
+  if (m_SurfaceDriftFlag) {
+    if ((ysurf >= 0.0) and (ysurf <= m_distInterStrip)) {
+      float t_surfaceDrift{0.};
+      if (ysurf < m_distHalfInterStrip) {
+        const float y{ysurf / m_distHalfInterStrip};
+        t_surfaceDrift= m_tHalfwayDrift * y * y;
+      } else {
+        const float y{(m_distInterStrip - ysurf) / (m_distInterStrip - m_distHalfInterStrip)};
+        t_surfaceDrift = m_tSurfaceDrift + (m_tHalfwayDrift - m_tSurfaceDrift) * y * y;
+      }
+      return t_surfaceDrift;
+    } else {
+      ATH_MSG_INFO(" ysurf out of range " << ysurf);
+      return -1.0;
+    }
+  } else {
+    return 0.0;
+  }
+}
+
+// -------------------------------------------------------------------------------------------
+// create a list of surface charges from a hit - called from SCT_Digitization
+// AthAlgorithm
+// -------------------------------------------------------------------------------------------
+void SCT_SurfaceChargesGenerator::process(const SiDetectorElement* element,
+                                          const TimedHitPtr<FaserSiHit>& phit,
+                                          const ISiSurfaceChargesInserter& inserter, CLHEP::HepRandomEngine * rndmEngine) const {
+  ATH_MSG_VERBOSE("SCT_SurfaceChargesGenerator::process starts");
+  processSiHit(element, *phit, inserter, phit.eventTime(), phit.eventId(), rndmEngine);
+  return;
+}
+
+// -------------------------------------------------------------------------------------------
+// create a list of surface charges from a hit - called from both AthAlgorithm
+// and PileUpTool
+// -------------------------------------------------------------------------------------------
+void SCT_SurfaceChargesGenerator::processSiHit(const SiDetectorElement* element,
+                                               const FaserSiHit& phit,
+                                               const ISiSurfaceChargesInserter& inserter,
+                                               float p_eventTime,
+                                               unsigned short p_eventId, CLHEP::HepRandomEngine * rndmEngine) const {
+  const SCT_ModuleSideDesign* design{dynamic_cast<const SCT_ModuleSideDesign*>(&(element->design()))};
+  if (design==nullptr) {
+    ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::process can not get " << design);
+    return;
+  }
+
+  const double thickness{design->thickness()};
+  const IdentifierHash hashId{element->identifyHash()};
+  const double tanLorentz{m_lorentzAngleTool->getTanLorentzAngle(hashId)};
+
+  // ---**************************************
+  //  Time of Flight Calculation - separate method?
+  // ---**************************************
+  // --- Original calculation of Time of Flight of the particle Time needed by the particle to reach the sensor
+  float timeOfFlight{p_eventTime + hitTime(phit)};
+
+  // Kondo 19/09/2007: Use the coordinate of the center of the module to calculate the time of flight
+  timeOfFlight -= (element->center().mag()) / CLHEP::c_light;
+  // !< extract the distance to the origin of the module to Time of flight
+
+  // !< timing set from jo to adjust (subtract) the timing
+  if (m_tsubtract > -998.) {
+    timeOfFlight -= m_tsubtract;
+  }
+  // ---**************************************
+
+  const CLHEP::Hep3Vector pos{phit.localStartPosition()};
+  const float xEta{static_cast<float>(pos[FaserSiHit::xEta])};
+  const float xPhi{static_cast<float>(pos[FaserSiHit::xPhi])};
+  const float xDep{static_cast<float>(pos[FaserSiHit::xDep])};
+
+  const CLHEP::Hep3Vector endPos{phit.localEndPosition()};
+  const float cEta{static_cast<float>(endPos[FaserSiHit::xEta]) - xEta};
+  const float cPhi{static_cast<float>(endPos[FaserSiHit::xPhi]) - xPhi};
+  const float cDep{static_cast<float>(endPos[FaserSiHit::xDep]) - xDep};
+
+  const float LargeStep{sqrt(cEta*cEta + cPhi*cPhi + cDep*cDep)};
+  const int numberOfSteps{static_cast<int>(LargeStep / m_smallStepLength) + 1};
+  const float steps{static_cast<float>(m_numberOfCharges * numberOfSteps)};
+  const float e1{static_cast<float>(phit.energyLoss() / steps)};
+  const float q1{static_cast<float>(e1 * m_siPropertiesTool->getSiProperties(hashId).electronHolePairsPerEnergy())};
+
+  // in the following, to test the code, we will use the original coordinate
+  // system of the SCTtest3SurfaceChargesGenerator x is eta y is phi z is depth
+  float xhit{xEta};
+  float yhit{xPhi};
+  float zhit{xDep};
+
+  if (m_doDistortions) {
+      ATH_MSG_FATAL("Distortions not supported.");
+    // if (element->isBarrel()) {// Only apply disortions to barrel modules
+    //   Amg::Vector2D BOW;
+    //   BOW[0] = m_distortionsTool->correctSimulation(hashId, xhit, yhit, cEta, cPhi, cDep)[0];
+    //   BOW[1] = m_distortionsTool->correctSimulation(hashId, xhit, yhit, cEta, cPhi, cDep)[1];
+    //   xhit = BOW.x();
+    //   yhit = BOW.y();
+    // }
+  }
+
+  const float StepX{cEta / numberOfSteps};
+  const float StepY{cPhi / numberOfSteps};
+  const float StepZ{cDep / numberOfSteps};
+  
+  // check the status of truth information for this SiHit
+  // some Truth information is cut for pile up events
+  const HepMcParticleLink trklink{HepMcParticleLink(phit.trackNumber(), p_eventId)};
+  SiCharge::Process hitproc{SiCharge::track};
+  if (phit.trackNumber() != 0) {
+    if (not trklink.isValid()) {
+      hitproc = SiCharge::cut_track;
+    }
+  }
+
+  float dstep{-0.5};
+  for (int istep{0}; istep < numberOfSteps; ++istep) {
+    dstep += 1.0;
+    float z1{zhit + StepZ * dstep};
+
+    // Distance between charge and readout side.
+    // design->readoutSide() is +1 if readout side is in +ve depth axis direction and visa-versa.
+    float zReadout{static_cast<float>(0.5 * thickness - design->readoutSide() * z1)};
+    // const double spess{zReadout};
+
+    // if (m_doHistoTrap) {
+    //   m_h_depD->Fill(z1);
+    //   m_h_spess->Fill(spess);
+    // }
+
+    float t_drift{driftTime(zReadout, element)};  // !< t_drift: perpandicular drift time
+    if (t_drift>-2.0000002 and t_drift<-1.9999998) {
+      ATH_MSG_DEBUG("Checking for rounding errors in compression");
+      if ((fabs(z1) - 0.5 * thickness) < 0.000010) {
+        ATH_MSG_DEBUG("Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
+        if (z1 < 0.0) {
+          z1 = 0.0000005 - 0.5 * thickness;
+          // set new coordinate to be 0.5nm inside wafer volume.
+        } else {
+          z1 = 0.5 * thickness - 0.0000005;
+          // set new coordinate to be 0.5nm inside wafer volume.
+        }
+        zReadout = 0.5 * thickness - design->readoutSide() * z1;
+        t_drift = driftTime(zReadout, element);
+        if (t_drift>-2.0000002 and t_drift<-1.9999998) {
+          ATH_MSG_WARNING("Attempt failed. Making no correction.");
+        } else {
+          ATH_MSG_DEBUG("Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 << ", zReadout = " << zReadout << ", t_drift = " << t_drift);
+        }
+      } else {
+        ATH_MSG_DEBUG("No rounding error found. Making no correction.");
+      }
+    }
+    if (t_drift > 0.0) {
+      const float x1{xhit + StepX * dstep};
+      float y1{yhit + StepY * dstep};
+      y1 += tanLorentz * zReadout; // !< Taking into account the magnetic field
+      const float sigma{diffusionSigma(zReadout, element)};
+
+      for (int i{0}; i < m_numberOfCharges; ++i) {
+        const float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
+        const float xd{x1 + sigma * rx};
+        const float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
+        const float yd{y1 + sigma * ry};
+
+        // For charge trapping with Ramo potential
+        const double stripPitch{0.080}; // mm
+        double dstrip{y1 / stripPitch}; // mm
+        if (dstrip > 0.) {
+          dstrip -= static_cast<double>(static_cast<int>(dstrip));
+        } else {
+          dstrip -= static_cast<double>(static_cast<int>(dstrip)) + 1;
+        }
+
+        // now y will be x and z will be y ....just to make sure to confuse everebody
+        // double y0{dstrip * stripPitch}; // mm
+        // double z0{thickness - zReadout}; // mm
+
+        // -- Charge Trapping
+        // if (m_doTrapping) {
+        //   if (m_doHistoTrap) {
+        //     m_h_zhit->Fill(zhit);
+        //   }
+        //   double trap_pos{-999999.}, drift_time{-999999.}; // FIXME need better default values
+        //   if (chargeIsTrapped(spess, element, trap_pos, drift_time)) {
+        //     if (not m_doRamo) {
+        //       break;
+        //     } else {  // if we want to take into account also Ramo Potential
+        //       double Q_m2{0.}, Q_m1{0.}, Q_00{0.}, Q_p1{0.}, Q_p2{0.}; // Charges
+
+        //       dstrip = y1 / stripPitch; // mm
+        //       // need the distance from the nearest strips
+        //       // edge not centre, xtaka = 1/2*stripPitch
+        //       // centre of detector, y1=0, is in the middle of
+        //       // an interstrip gap
+        //       if (dstrip > 0.) {
+        //         dstrip -= static_cast<double>(static_cast<int>(dstrip));
+        //       } else {
+        //         dstrip -= static_cast<double>(static_cast<int>(dstrip)) + 1;
+        //       }
+
+        //       // now y will be x and z will be y ....just to make sure to confuse everebody
+        //       double yfin{dstrip * stripPitch}; // mm
+        //       double zfin{thickness - trap_pos}; // mm
+
+        //       m_radDamageTool->holeTransport(y0, z0, yfin, zfin, Q_m2, Q_m1, Q_00, Q_p1, Q_p2);
+        //       for (int strip{-2}; strip<=2; strip++) {
+        //         const double ystrip{yd + strip * stripPitch}; // mm
+        //         const SiLocalPosition position(element->hitLocalToLocal(xd, ystrip));
+        //         if (design->inActiveArea(position)) {
+        //           double charge{0.};
+        //           if (strip == -2) charge = Q_m2;
+        //           if (strip == -1) charge = Q_m1;
+        //           if (strip ==  0) charge = Q_00;
+        //           if (strip ==  1) charge = Q_p1;
+        //           if (strip ==  2) charge = Q_p2;
+        //           const double time{drift_time};
+        //           if (charge != 0.) {
+        //             inserter(SiSurfaceCharge(position, SiCharge(q1*charge, time, hitproc, trklink)));
+        //             continue;
+        //           }
+        //         }
+        //       }
+        //       ATH_MSG_INFO("strip zero charge = " << Q_00); // debug
+        //     } // m_doRamo==true
+        //   } // chargeIsTrapped()
+        // } // m_doTrapping==true
+        
+        if (not m_doRamo) {
+          const SiLocalPosition position{element->hitLocalToLocal(xd, yd)};
+          if (design->inActiveArea(position)) {
+            const float sdist{static_cast<float>(design->scaledDistanceToNearestDiode(position))}; // !< dist on the surface from the hit point to the nearest strip (diode)
+            const float t_surf{surfaceDriftTime(2.0 * sdist)}; // !< Surface drift time
+            const float totaltime{(m_tfix > -998.) ? m_tfix.value() : t_drift + timeOfFlight + t_surf}; // !< Total drift time
+            inserter(SiSurfaceCharge(position, SiCharge(q1, totaltime, hitproc, trklink)));
+          } else {
+            ATH_MSG_VERBOSE(std::fixed << std::setprecision(8) << "Local position (phi, eta, depth): ("
+                            << position.xPhi() << ", " << position.xEta() << ", " << position.xDepth() 
+                            << ") of the element is out of active area, charge = " << q1);
+          }
+        } // end of loop on charges
+      }
+    }
+  }
+  return;
+}
+
+// bool SCT_SurfaceChargesGenerator::chargeIsTrapped(double spess,
+//                                                   const SiDetectorElement* element,
+//                                                   double& trap_pos,
+//                                                   double& drift_time) const {
+//   if (element==nullptr) {
+//     ATH_MSG_ERROR("SCT_SurfaceChargesGenerator::chargeIsTrapped element is nullptr");
+//     return false;
+//   }
+//   bool isTrapped{false};
+//   const IdentifierHash hashId{element->identifyHash()};
+//   const SCT_ChargeTrappingCondData condData{m_radDamageTool->getCondData(hashId, spess)};
+//   const double electric_field{condData.getElectricField()};
+
+//   if (m_doHistoTrap) {
+//     const double mobChar{condData.getHoleDriftMobility()};
+//     m_h_efieldz->Fill(spess, electric_field);
+//     m_h_efield->Fill(electric_field);
+//     m_h_mob_Char->Fill(electric_field, mobChar);
+//     m_h_vel->Fill(electric_field, electric_field * mobChar);
+//   }
+//   const double t_electrode{condData.getTimeToElectrode()};
+//   drift_time = condData.getTrappingTime();
+//   const double z_trap{condData.getTrappingPositionZ()};
+//   trap_pos = spess - z_trap;
+//   if (m_doHistoTrap) {
+//     m_h_drift_time->Fill(drift_time);
+//     m_h_t_electrode->Fill(t_electrode);
+//     m_h_drift_electrode->Fill(drift_time, t_electrode);
+//     m_h_ztrap_tot->Fill(z_trap);
+//   }
+//   // -- Calculate if the charge is trapped, and at which distance
+//   // -- Charge gets trapped before arriving to the electrode
+//   if (drift_time < t_electrode) {
+//     isTrapped = true;
+//     ATH_MSG_INFO("drift_time: " << drift_time << " t_electrode:  " << t_electrode << " spess " << spess);
+//     ATH_MSG_INFO("z_trap: " << z_trap);
+//     if (m_doHistoTrap) {
+//       m_h_ztrap->Fill(z_trap);
+//       m_h_trap_drift_t->Fill(drift_time);
+//       m_h_drift1->Fill(spess, drift_time / t_electrode);
+//       m_h_gen->Fill(spess, drift_time);
+//       m_h_gen1->Fill(spess, z_trap);
+//       m_h_gen2->Fill(spess, z_trap / drift_time * t_electrode);
+//       m_h_velocity_trap->Fill(electric_field, z_trap / drift_time);
+//       m_h_mobility_trap->Fill(electric_field, z_trap / drift_time / electric_field);
+//       m_h_trap_pos->Fill(trap_pos);
+//     }
+//   } else {
+//     isTrapped = false;
+//     if (m_doHistoTrap) {
+//       const double z_trap{condData.getTrappingPositionZ()};
+//       m_h_no_ztrap->Fill(z_trap);
+//       m_h_notrap_drift_t->Fill(drift_time);
+//     }
+//   }
+//   return isTrapped;
+// }
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.h b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9ae5fcda18638ec41925745fc52f710fb0ad804
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/SCT_SurfaceChargesGenerator.h
@@ -0,0 +1,164 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * Header file for SCT_SurfaceChargesGenerator Class
+ * @brief Class to drift the charged hits to the sensor surface for SCT
+ * version 1.0a Szymon Gadomski 31.05.2001
+ * @author Szymon.Gadomski@cern.ch, Awatif.Belymam@cern.ch, Davide.Costanzo@cern.ch,    
+ * tgcornel@nikhef.nl, Grant.Gorfine@cern.ch, Paul.Bell@cern.ch, Jorgen.Dalmau@cern.ch, 
+ * This is based on the SCTtest3SurfaceChargesGenerator
+ * compared to "test3", changes are all related to interfaces
+ * this should work with the new SCT_BarrelModuleSideDesign
+ * Compared to "test2" the following have been added in "test3":
+ * - a possibility to work with long steps and to smear charge along
+ *   the step in smaller steps
+ * - Lorentz angle
+ * 19/04/2001 -  change of hit class to SiTrackerHit
+ * version 1.0 Szymon Gadomski 09/06/2001, compiles with framework
+ * 26/07/2001 - changed to work with SiDigitization-00-02-00, tested
+ * 20/10/2002 - Awatif Belymam
+ * 29/10/2002 - the thickness of sensors is obtained from the objects
+ *            - of SCT_ModuleSideDesign type instead from its jobOptions file.
+ *            - Changes are done as well in jobOptions files.
+ * 06/01/2004 - Everything is now in CLHEP units (mm, ns, MeV)
+ * 23/08/2007 - Kondo.Gnanvo@cern.ch           
+ *            - Conversion of the SCT_SurfaceChargesGenerator code Al gTool
+ */
+
+#ifndef FASERSCT_DIGITIZATION_SCT_SURFACECHARGESGENERATOR_H
+#define FASERSCT_DIGITIZATION_SCT_SURFACECHARGESGENERATOR_H
+
+//Inheritance
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FaserSCT_Digitization/ISCT_SurfaceChargesGenerator.h"
+
+#include "Identifier/IdentifierHash.h"
+// #include "InDetConditionsSummaryService/ISiliconConditionsTool.h"
+#include "InDetCondTools/ISiLorentzAngleTool.h"
+// #include "SCT_ConditionsTools/ISCT_RadDamageSummaryTool.h"
+// #include "SCT_ModuleDistortions/ISCT_ModuleDistortionsTool.h"
+#include "SiPropertiesTool/ISiPropertiesTool.h"
+
+// Gaudi
+#include "GaudiKernel/ITHistSvc.h" // for ITHistSvc
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include <iostream>
+
+// Charges and hits
+class FaserSiHit;
+
+// -- do charge trapping histos
+class ITHistSvc;
+class TH1F;
+class TH2F;
+class TProfile;
+
+namespace TrackerDD {
+  class SiDetectorElement;
+  class SCT_ModuleSideDesign;
+}
+
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+template <class HIT> class TimedHitPtr;
+
+class SCT_SurfaceChargesGenerator : public extends<AthAlgTool, ISCT_SurfaceChargesGenerator> {
+ public:
+
+  /**  constructor */
+  SCT_SurfaceChargesGenerator(const std::string& type, const std::string& name, const IInterface* parent);
+
+  /** Destructor */
+  virtual ~SCT_SurfaceChargesGenerator() = default;
+
+  /** AlgTool initialize */
+  virtual StatusCode initialize();
+
+  /** AlgTool finalize */
+  virtual StatusCode finalize();
+
+ private:
+
+  virtual void setFixedTime(float fixedTime)                             {m_tfix = fixedTime;}
+
+  /** create a list of surface charges from a hit */
+  virtual void process(const TrackerDD::SiDetectorElement* element, const TimedHitPtr<FaserSiHit>& phit, const ISiSurfaceChargesInserter& inserter, CLHEP::HepRandomEngine * rndmEngine) const;
+  void processSiHit(const TrackerDD::SiDetectorElement* element, const FaserSiHit& phit, const ISiSurfaceChargesInserter& inserter, float eventTime, unsigned short eventID, CLHEP::HepRandomEngine * rndmEngine) const;
+  
+  // some diagnostics methods are needed here too
+  float driftTime(float zhit, const TrackerDD::SiDetectorElement* element) const; //!< calculate drift time perpandicular to the surface for a charge at distance zhit from mid gap
+  float diffusionSigma(float zhit, const TrackerDD::SiDetectorElement* element) const; //!< calculate diffusion sigma from a gaussian dist scattered charge
+  float surfaceDriftTime(float ysurf) const; //!< Calculate of the surface drift time
+  float maxDriftTime(const TrackerDD::SiDetectorElement* element) const; //!< max drift charge equivalent to the detector thickness
+  float maxDiffusionSigma(const TrackerDD::SiDetectorElement* element) const; //!< max sigma diffusion
+
+  // trap_pos and drift_time are updated based on spess.
+//   bool chargeIsTrapped(double spess, const TrackerDD::SiDetectorElement* element, double& trap_pos, double& drift_time) const;
+
+  IntegerProperty m_numberOfCharges{this, "NumberOfCharges", 1, "number of charges"};
+  FloatProperty m_smallStepLength{this, "SmallStepLength", 5, "max internal step along the larger G4 step"};
+
+  /** related to the surface drift */
+  FloatProperty m_tSurfaceDrift{this, "SurfaceDriftTime", 10, "max surface drift time"};
+
+  FloatProperty m_tfix{this, "FixedTime", -999., "fixed time"};
+  FloatProperty m_tsubtract{this, "SubtractTime", -999., "subtract drift time from mid gap"};
+
+  BooleanProperty m_doDistortions{this, "doDistortions", false, "Simulation of module distortions"};
+  BooleanProperty m_useSiCondDB{this, "UseSiCondDB", false, "Usage of SiConditions DB values can be disabled to use setable ones"};
+  FloatProperty m_vdepl{this, "DepletionVoltage", 70., "depletion voltage, default 70V"};
+  FloatProperty m_vbias{this, "BiasVoltage", 150., "bias voltage, default 150V"};
+  BooleanProperty m_doTrapping{this, "doTrapping", false, "Flag to set Charge Trapping"};
+//   BooleanProperty m_doHistoTrap{this, "doHistoTrap", false, "Histogram the charge trapping effect"};
+  BooleanProperty m_doRamo{this, "doRamo", false, "Ramo Potential for charge trapping effect"};
+  BooleanProperty m_isOverlay{this, "isOverlay", false, "flag for overlay"};
+
+  //ToolHandles
+//   ToolHandle<ISCT_ModuleDistortionsTool> m_distortionsTool{this, "SCTDistortionsTool", "SCT_DistortionsTool", "Tool to retrieve SCT distortions"};
+  ToolHandle<ISiPropertiesTool> m_siPropertiesTool{this, "SiPropertiesTool", "SCT_SiPropertiesTool", "Tool to retrieve SCT silicon properties"};
+//   ToolHandle<ISCT_RadDamageSummaryTool> m_radDamageTool{this, "RadDamageSummaryTool", "SCT_RadDamageSummaryTool", "Tool to retrieve SCT radiation damages"};
+//   ToolHandle<ISiliconConditionsTool> m_siConditionsTool{this, "SiConditionsTool", "SCT_SiliconConditionsTool", "Tool to retrieve SCT silicon information"};
+  ToolHandle<ISiLorentzAngleTool> m_lorentzAngleTool{this, "LorentzAngleTool", "SiLorentzAngleTool/SCTLorentzAngleTool", "Tool to retreive Lorentz angle"};
+
+  ServiceHandle<ITHistSvc> m_thistSvc{this, "THistSvc", "THistSvc"};
+
+  float m_tHalfwayDrift{0.}; //!< Surface drift time
+  float m_distInterStrip{1.0}; //!< Inter strip distance normalized to 1
+  float m_distHalfInterStrip{0.}; //!< Half way distance inter strip
+
+  bool m_SurfaceDriftFlag{false}; //!< surface drift ON/OFF
+
+  // -- Histograms
+  TProfile* m_h_efieldz{nullptr};
+  TH1F* m_h_efield{nullptr};
+  TH1F* m_h_spess{nullptr};
+  TH1F* m_h_depD{nullptr};
+  TH2F* m_h_drift_electrode{nullptr};
+  TH1F* m_h_ztrap{nullptr};
+  TH1F* m_h_drift_time{nullptr};
+  TH1F* m_h_t_electrode{nullptr};
+  TH1F* m_h_zhit{nullptr};
+  TH1F* m_h_ztrap_tot{nullptr};
+  TH1F* m_h_no_ztrap{nullptr};
+  TH1F* m_h_trap_drift_t{nullptr};
+  TH1F* m_h_notrap_drift_t{nullptr};
+  TProfile* m_h_mob_Char{nullptr};
+  TProfile* m_h_vel{nullptr};
+  TProfile* m_h_drift1{nullptr};
+  TProfile* m_h_gen{nullptr};
+  TProfile* m_h_gen1{nullptr};
+  TProfile* m_h_gen2{nullptr};
+  TProfile* m_h_velocity_trap{nullptr};
+  TProfile* m_h_mobility_trap{nullptr};
+  TH1F* m_h_trap_pos{nullptr};
+};
+
+#endif // SCT_SURFACECHARGESGENERATOR_H
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/src/components/FaserSCT_Digitization_entries.cxx b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/components/FaserSCT_Digitization_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ea833080bce266204197ea69cdccc4c0752bf83d
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/src/components/FaserSCT_Digitization_entries.cxx
@@ -0,0 +1,18 @@
+#include "../SCT_Amp.h"
+#include "../SCT_FrontEnd.h"
+#include "../SCT_Digitization.h"
+#include "../SCT_DigitizationTool.h"
+#include "../SCT_SurfaceChargesGenerator.h"
+#include "../SCT_RandomDisabledCellGenerator.h"
+// Unused by ATLAS
+// #include "../SCT_DetailedSurfaceChargesGenerator.h" 
+
+DECLARE_COMPONENT( SCT_Amp )  
+DECLARE_COMPONENT( SCT_FrontEnd )
+DECLARE_COMPONENT( SCT_Digitization )
+DECLARE_COMPONENT( SCT_DigitizationTool )
+DECLARE_COMPONENT( SCT_SurfaceChargesGenerator )
+DECLARE_COMPONENT( SCT_RandomDisabledCellGenerator )
+// Unused by ATLAS
+// DECLARE_COMPONENT( SCT_DetailedSurfaceChargesGenerator )
+
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/test/FaserSCT_DigitizationDbg.py b/Tracker/TrackerDigitization/FaserSCT_Digitization/test/FaserSCT_DigitizationDbg.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd51e8f88249c522103f5288ec363256114a02a5
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/test/FaserSCT_DigitizationDbg.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python                                                                                                                                 
+"""Test various ComponentAccumulator Digitization configuration modules                                                                               
+                                                                                                                                                      
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration                                                                               
+"""
+import sys
+from AthenaCommon.Logging import log
+from AthenaCommon.Constants import DEBUG
+from AthenaCommon.Configurable import Configurable
+from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.TestDefaults import defaultTestFiles
+from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+#from Digitization.DigitizationParametersConfig import writeDigitizationMetadata                                                                      
+from FaserSCT_Digitization.FaserSCT_DigitizationConfigNew import SCT_DigitizationCfg
+#from MCTruthSimAlgs.RecoTimingConfig import MergeRecoTimingObjCfg                                                                                    
+
+# Set up logging and new style config                                                                                                                 
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+
+# Configure                                                                                                                                           
+ConfigFlags.Input.Files = ['g4.HITS.root']
+ConfigFlags.Output.RDOFileName = "myRDO.pool.root"
+ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-14"
+ConfigFlags.GeoModel.Align.Dynamic = False
+ConfigFlags.Concurrency.NumThreads = 1
+ConfigFlags.Beam.NumberOfCollisions = 0.
+
+ConfigFlags.GeoModel.FaserVersion = "FASER-00"               # Always needed                                                                          
+ConfigFlags.GeoModel.AtlasVersion = "ATLAS-R2-2016-01-00-01" # Always needed to fool autoconfig                                                       
+
+ConfigFlags.lock()
+
+# Core components                                                                                                                                     
+acc = MainServicesSerialCfg()
+acc.merge(PoolReadCfg(ConfigFlags))
+acc.merge(PoolWriteCfg(ConfigFlags))
+#acc.merge(writeDigitizationMetadata(ConfigFlags))                                                                                                    
+
+# Inner Detector                                                                                                                                      
+acc.merge(SCT_DigitizationCfg(ConfigFlags))
+
+# Timing                                                                                                                                              
+#acc.merge(MergeRecoTimingObjCfg(ConfigFlags))                                                                                                        
+
+# Dump config                                                                                                                                         
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
+# Execute and finish                                                                                                                                  
+sc = acc.run(maxEvents=3)
+# Success should be 0                                                                                                                                 
+sys.exit(not sc.isSuccess())
+
diff --git a/Tracker/TrackerDigitization/FaserSCT_Digitization/test/SCT_DigitizationConfigNew_test.py b/Tracker/TrackerDigitization/FaserSCT_Digitization/test/SCT_DigitizationConfigNew_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..4fbd20f575761bc28029c4139df6b5cbd4abd382
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSCT_Digitization/test/SCT_DigitizationConfigNew_test.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+"""Run tests on SCT_DigitizationConfigNew.py
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaCommon.Logging import log
+from AthenaCommon.Constants import DEBUG
+from AthenaCommon.Configurable import Configurable
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+from AthenaConfiguration.TestDefaults import defaultTestFiles
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from AtlasGeoModel.InDetGMConfig import InDetGeometryCfg
+from FaserSCT_Digitization.FaserSCT_DigitizationConfigNew import SCT_DigitizationHSCfg
+
+# Set up logging and new style config
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+# Configure
+ConfigFlags.Input.Files = defaultTestFiles.HITS
+ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-16"
+ConfigFlags.GeoModel.Align.Dynamic = False
+ConfigFlags.Concurrency.NumThreads = 1
+ConfigFlags.lock()
+# Construct our accumulator to run
+acc = MainServicesSerialCfg()
+acc.merge(PoolReadCfg(ConfigFlags))
+acc.merge(SCT_DigitizationHSCfg(ConfigFlags))
+# Dump config
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
+# Execute and finish
+acc.run(maxEvents=3)
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt b/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..afa4ae31542b62d1a6a15b5c9b76b16786d8bb16
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt
@@ -0,0 +1,24 @@
+################################################################################
+# Package: FaserSiDigitization
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserSiDigitization )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          Control/AthAllocators
+                          DetectorDescription/Identifier
+                          GaudiKernel
+                          Tracker/TrackerDetDescr/TrackerReadoutGeometry
+                          Tracker/TrackerSimEvent )
+
+# Component(s) in the package:
+atlas_add_library( FaserSiDigitization
+                   src/SiChargedDiode.cxx
+                   src/SiChargedDiodeCollection.cxx
+                   src/SiSurfaceCharge.cxx
+                   PUBLIC_HEADERS FaserSiDigitization
+                   LINK_LIBRARIES AthenaKernel AthAllocators Identifier GaudiKernel TrackerReadoutGeometry TrackerSimEvent )
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..da544c9d30a66d7dcb521188c6d363dc77919bd4
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+Tracker/TrackerDigitization/FaserSiDigitization
\ No newline at end of file
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..f45afd9fcd61f695e9d9f5f7b0bcc53d772e6c51
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISiChargedDiodesProcessorTool.h
+ * Header file for abstract base class ISiChargedDiodesProcessorTool
+ * (c) ATLAS Detector software
+ * Interface for the SiChargedDiode processor classes
+ * 23/08/2007 Kondo.Gnanvo@cern.ch, and others   
+*/
+
+#ifndef FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
+#define FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+
+class SiChargedDiodeCollection;
+class NPtGainSummaryData;
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+static const InterfaceID IID_ISiChargedDiodesProcessorTool("ISiChargedDiodesProcessorTool",1,0);
+
+class ISiChargedDiodesProcessorTool : virtual public IAlgTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  //Retrieve interface ID
+  static const InterfaceID & interfaceID() {return IID_ISiChargedDiodesProcessorTool; }
+
+  // Destructor:
+  virtual ~ISiChargedDiodesProcessorTool() {}
+
+  ///////////////////////////////////////////////////////////////////
+  // Pure virtual methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // process the collection of charged diodes
+  virtual void process(SiChargedDiodeCollection &collection, CLHEP::HepRandomEngine * rndmEngine) const =0;
+};
+
+#endif // FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h
new file mode 100644
index 0000000000000000000000000000000000000000..fadd13e4555c63976bee38629119e80f179a0755
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////// 
+// SiChargedDiode.h // Header file for class SiChargedDiode
+/////////////////////////////////////////////////////////////////// 
+// (c) ATLAS Detector software
+/////////////////////////////////////////////////////////////////// 
+// Class which contains the sum and the composition of all bare 
+//charges (SiTotalCharge) deposited in one SiDiode 
+/////////////////////////////////////////////////////////////////// 
+// Version 2.1 09/06/2001 David Calvet 
+// Revisited 04-03-03 Davide Costanzo
+//  added a int flag as a private data member to store the noise, 
+//  disconnected, bad_tot information. The relative bunch number is 
+//  also stored in this word. 
+//  the word will is meant to be copied as it is in the SDO
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERSIDIGITIZATION_SICHARGEDDIODE_H 
+#define FASERSIDIGITIZATION_SICHARGEDDIODE_H
+
+// Data member classes
+#include "TrackerSimEvent/SiTotalCharge.h"
+#include "TrackerReadoutGeometry/SiCellId.h"
+#include "TrackerReadoutGeometry/SiReadoutCellId.h"
+
+class SiHelper; // used to set the flag word
+//class SiChargedDiode;
+
+class SiChargedDiode {
+
+    friend class SiHelper;
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Constructor with parameters:
+    SiChargedDiode(const SiTotalCharge::alloc_t& alloc,
+                   const TrackerDD::SiCellId & diode, const TrackerDD::SiReadoutCellId & roCell,  int flagword=0, SiChargedDiode* nextInCluster=NULL);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // Diode which contains this charge:
+  const TrackerDD::SiCellId & diode() const;
+
+  // Readout cell associated to diode 
+  // (usually the same id as the diode except for ganged pixels):
+  const TrackerDD::SiReadoutCellId & getReadoutCell();
+
+  // total charge and its composition:
+  const SiTotalCharge & totalCharge() const;
+
+  // total deposited charge:
+  double charge() const;
+  
+  // flag, disconnected etc.
+  int flag() const;
+  
+  //neighbouring strip for navigation 
+  SiChargedDiode * nextInCluster();
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another charge:
+  void add(const SiCharge &charge);
+  // add a total charge
+  void add(const SiTotalCharge &totcharge);
+  //add a neighbouring strip for navigation 
+  void setNextInCluster(SiChargedDiode* nextInCluster);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiChargedDiode();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  TrackerDD::SiCellId m_diode; // SiDiode which contains this charge
+                          // the pointed SiDiode is owned by the SiChargedDiode
+  SiTotalCharge m_totalCharge; // total charge and its composition
+  TrackerDD::SiReadoutCellId m_readoutCell; //Readout cell associated to this diode
+  int m_word;   // a flag for noise etc etc as in InDetSimData
+  SiChargedDiode * m_nextInCluster; //the next strip to navigate to - allows traversing clusters since the SiChargedDiodeCollection is not guaranteed to be contiguous
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline const TrackerDD::SiCellId & SiChargedDiode::diode() const 
+{
+  return m_diode;
+}
+
+inline int SiChargedDiode::flag() const 
+{
+  return m_word;
+}
+
+inline const SiTotalCharge &SiChargedDiode::totalCharge() const
+{
+  return m_totalCharge;
+}
+inline const TrackerDD::SiReadoutCellId & SiChargedDiode::getReadoutCell() {
+  return m_readoutCell;
+}
+
+inline double SiChargedDiode::charge() const
+{
+  return m_totalCharge.charge();
+}
+
+inline SiChargedDiode * SiChargedDiode::nextInCluster()
+{
+  return m_nextInCluster;
+}
+
+inline void SiChargedDiode::add(const SiCharge &charge)
+{
+  m_totalCharge.add(charge);
+}
+
+inline void SiChargedDiode::add(const SiTotalCharge &totcharge)
+{
+  m_totalCharge.add(totcharge);
+}
+
+inline void SiChargedDiode::setNextInCluster(SiChargedDiode* nextInCluster)
+{
+   m_nextInCluster = nextInCluster;
+}
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiChargedDiode &chargedDiode);
+
+#endif // FASERSIDIGITIZATION_SICHARGEDDIODE_H
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f5a9f23734cfc1d48545565e58f5b36e90fe473
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h
@@ -0,0 +1,285 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiChargedDiodeCollection.h
+//   Header file for class SiChargedDiodeCollection
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class used to store the list of SiChargedDiode objects for one
+//  module (Pixel) or half module (SCT) and one event. 
+///////////////////////////////////////////////////////////////////
+// Version 3.0 09/07/2001 David Calvet
+// Davide Costanzo. Revisited version. 04-03-03
+//    - added a Identifier wafer_id to the private members
+//    - added a IdHelper to the private members
+//    - constructor modified to initialize wafer_id and IdHelper
+//    - replaced <list> with <map> and use the compact id of the 
+//      SiChargedDiode to map them.
+//    - Inherit from Identifiable to enforce the identify() method
+///////////////////////////////////////////////////////////////////
+#ifndef FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+#define FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+
+// Base class
+#include "Identifier/Identifiable.h"
+
+// Data member classes
+#include <unordered_map>
+#include "FaserSiDigitization/SiChargedDiode.h"
+#include "Identifier/Identifier.h"
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+
+// Input/output classes 
+#include "TrackerSimEvent/FaserSiHit.h"
+
+// STL includes
+#include <atomic>
+#include <set>
+#include <memory>
+
+class FaserDetectorID;
+namespace TrackerDD{
+  class SiDetectorElement;
+  class SiDetectorDesign;
+  class SiCellId;
+}
+
+#include "AthAllocators/ArenaPoolSTLAllocator.h"
+
+struct SiChargedDiodeHash
+{
+  size_t operator() (const TrackerDD::SiCellId & id) const
+  {
+    return id.word();
+  }
+};
+
+typedef std::unordered_map<TrackerDD::SiCellId,
+                           SiChargedDiode,
+                           SiChargedDiodeHash,
+                           std::equal_to<TrackerDD::SiCellId>,
+                           SG::ArenaPoolSTLAllocator<
+                            std::pair<const TrackerDD::SiCellId, SiChargedDiode> > >
+  SiChargedDiodeMap;
+
+
+// Iterator typedef to make it easier
+typedef SiChargedDiodeMap::iterator SiChargedDiodeIterator;
+
+
+
+//
+// A normal iteration over a SiChargedDiodeCollection will use
+// the unordered_map, so the ordering is not defined.  The observed
+// ordering can (and does) change depending on the compiler and library
+// version used.  In some cases, though, we are sensitive to the
+// order of iteration, for example in cases where we generate a random
+// number for each element of the collection.  To get results which
+// are identical across compilers, we need to instead do the iteration
+// in a well-defined order.
+//
+// This can be done using the methods sortedBegin and sortedEnd instead
+// of begin and end.  These work by maintaining a std::set of pointers
+// to the diodes, sorted by the diode number.  In order to avoid paying
+// the penalty for maintaining the sorted set when we don't need to, we only
+// start maintaining it the first time that it's requested.
+struct SiChargedDiodeOrderedSetCompare
+{
+  size_t operator() (const SiChargedDiode* a,
+                     const SiChargedDiode* b) const
+  {
+    return a->diode().word() < b->diode().word();
+  }
+};
+
+
+
+typedef std::set<SiChargedDiode*,
+                 SiChargedDiodeOrderedSetCompare,
+                 SG::ArenaPoolSTLAllocator<SiChargedDiode*> >
+  SiChargedDiodeOrderedSet;
+                 
+
+// Iterator typedef to make it easier
+typedef SiChargedDiodeOrderedSet::iterator SiChargedDiodeOrderedIterator;
+
+class SiChargedDiodeCollection : Identifiable {
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+
+  // Constructor with parameters:
+  //  ref. to the detector element for this collection
+  SiChargedDiodeCollection( );
+
+  SiChargedDiodeCollection(const TrackerDD::SiDetectorElement* );
+
+
+  // Destructor:
+  ~SiChargedDiodeCollection();
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // detector element:
+  const TrackerDD::SiDetectorElement * element() const;
+
+  // wafer identifier for this collection
+  virtual Identifier identify() const override final;
+  virtual IdentifierHash identifyHash() const override final;
+
+  // id helper for this collection
+  const FaserDetectorID* id_helper();
+  
+  // detector design:
+  const TrackerDD::SiDetectorDesign &design() const;
+
+  // translation from SiReadoutCellId to Identifier
+  Identifier getId(const TrackerDD::SiCellId& id) const 
+  { 
+    return (element()->identifierFromCellId(id)); 
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // clean up:
+  void clear();
+
+  // read/write access to the collection:
+  SiChargedDiodeMap &chargedDiodes();
+
+  // Set the SiDetectorElement
+  void setDetectorElement(const TrackerDD::SiDetectorElement *SiElement);
+
+  // Add a new SiCharge to the collection
+  // (add or merge in an existing SiChargedDiode):
+  //   Diode which contains the new charge
+  //   SiCharge to be added. 
+  void add(const TrackerDD::SiCellId & diode, const SiCharge &charge);
+  void add(const TrackerDD::SiCellId & diode, const SiTotalCharge &totcharge);
+
+  bool AlreadyHit(const TrackerDD::SiCellId & siId);
+  bool AlreadyHit(const Identifier & id);
+  SiChargedDiodeIterator begin();
+  SiChargedDiodeIterator end();
+  SiChargedDiodeOrderedIterator orderedBegin();
+  SiChargedDiodeOrderedIterator orderedEnd();
+  bool empty() const; // Test if there is anything in the collection.
+
+  // return a Charged diode given its CellId, NULL if doesn't exist
+  SiChargedDiode * find(const TrackerDD::SiCellId & siId);
+  // return a Charged diode given its identifier, NULL if doesn't exist
+  SiChargedDiode * find(Identifier);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+ private:
+  SiChargedDiodeCollection(const SiChargedDiodeCollection&);
+  SiChargedDiodeCollection &operator=(const SiChargedDiodeCollection&);
+  void order();
+  
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+ private:
+  //NB m_allocator should always be declared before m_chargedDiodes in
+  //the intialization list.  If the allocator is declared after
+  //m_chargedDiodes, when the collection is destroyed, the allocator
+  //will be destroyed (and the memory it manages freed) before the
+  //SiChargedDiodeMap.  This will cause a crash unless the
+  //SiChargedDiodeMap is empty.
+  SiTotalCharge::alloc_t m_allocator; 
+  SiChargedDiodeMap m_chargedDiodes; // list of SiChargedDiodes 
+  SiChargedDiodeOrderedSet m_orderedChargedDiodes; // list of SiChargedDiodes 
+  const TrackerDD::SiDetectorElement* m_sielement; // detector element
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+
+// Set the DetectorElement
+inline void SiChargedDiodeCollection::setDetectorElement(const TrackerDD::SiDetectorElement *SiElement) 
+{
+  m_sielement=SiElement;
+}
+
+inline SiChargedDiodeMap &SiChargedDiodeCollection::chargedDiodes()
+{
+  return m_chargedDiodes;
+}
+
+// access to the element
+inline const TrackerDD::SiDetectorElement *SiChargedDiodeCollection::element() const
+{
+  return m_sielement;
+}
+
+// access to the design
+inline const TrackerDD::SiDetectorDesign &SiChargedDiodeCollection::design() const
+{
+  return m_sielement->design();
+}
+
+// Get the Identifier of the collection
+inline Identifier SiChargedDiodeCollection::identify() const
+{
+  return m_sielement->identify();
+}
+
+// Get the Identifier of the collection
+inline IdentifierHash SiChargedDiodeCollection::identifyHash() const
+{
+  return m_sielement->identifyHash();
+}
+
+// Get the Id Helper
+inline const FaserDetectorID* SiChargedDiodeCollection::id_helper()
+{   
+  return m_sielement->getIdHelper();
+}
+
+
+inline SiChargedDiodeIterator SiChargedDiodeCollection::begin() 
+{
+  return m_chargedDiodes.begin();
+}
+
+inline SiChargedDiodeIterator SiChargedDiodeCollection::end() 
+{
+  return m_chargedDiodes.end();
+}
+
+inline SiChargedDiodeOrderedIterator SiChargedDiodeCollection::orderedBegin() 
+{
+  if (m_orderedChargedDiodes.empty() && !m_chargedDiodes.empty()) {
+    order();
+  }
+  return m_orderedChargedDiodes.begin();
+}
+
+inline SiChargedDiodeOrderedIterator SiChargedDiodeCollection::orderedEnd() 
+{
+  if (m_orderedChargedDiodes.empty() && !m_chargedDiodes.empty()) {
+    order();
+  }
+  return m_orderedChargedDiodes.end();
+}
+
+inline bool SiChargedDiodeCollection::empty() const {
+  return m_chargedDiodes.empty();
+}
+
+
+
+#endif // FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..1745878defc39fd913365ffba0702e2ff1048af2
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h
@@ -0,0 +1,208 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*************************************************************************
+    SiHelper for Silicons
+    This is used by the SiDigitization
+    ---------------------------------
+    ATLAS Collaboration
+
+
+    This is a short copy of the PixelSimHelper used by the SDO.
+    It is needed to set the word of the Charged Diodes in the same 
+    way as it will be registered in the SDO.
+  
+    D. Costanzo 4-3-03
+***************************************************************************/
+
+
+#ifndef FASERSIDIGITIZATION_SIHELPER_H
+#define FASERSIDIGITIZATION_SIHELPER_H
+
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/getMessageSvc.h"
+#include "FaserSiDigitization/SiChargedDiode.h"
+
+class SiHelper
+{
+ public:
+  // methods to set characteristics of a new object
+
+  static void noise(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void belowThreshold(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void disabled(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void badToT(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void disconnected(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void maskOut(SiChargedDiode& chDiode, bool flag);
+  static void ClusterUsed(SiChargedDiode& chDiode, bool flag);
+  static void SetBunch(SiChargedDiode& chDiode, int bunch, MsgStream* log=nullptr);
+  static void SetStripNum(SiChargedDiode& chDiode, int nstrip, MsgStream* log=nullptr);
+  static void SetTimeBin(SiChargedDiode& chDiode, int time, MsgStream* log=nullptr);
+
+  static bool isUsable(SiChargedDiode& chDiode);
+  static bool isNoise(SiChargedDiode& chDiode);
+  static bool isBelowThreshold(SiChargedDiode& chDiode);
+  static bool isDisabled(SiChargedDiode& chDiode);
+  static bool isBadToT(SiChargedDiode& chDiode);
+  static bool isDisconnected(SiChargedDiode& chDiode);
+  static bool isMaskOut(SiChargedDiode& chDiode);
+  static bool isClusterUsed(SiChargedDiode &chDiode);
+  static int  GetBunch(SiChargedDiode& chDiode);
+  static int  GetStripNum(SiChargedDiode& chDiode);
+  static int  GetTimeBin(SiChargedDiode& chDiode);
+
+ private:
+  enum {
+    NOISE_SET        = 0x1,  // main charge is noise
+    BT_SET           = 0x2,  // below threshold
+    DISABLED_SET     = 0x4,  // disabled
+    BADTOT_SET       = 0x8,  // bad TOT
+    DISCONNECTED_SET = 0x10, // disconnected
+    CLUSTERUSED_SET  = 0x20, // used in cluster - used by anyone???
+    MASKOUT_SET      = 0x40  // charge diode is masked out, not to be used for RDO creation
+  };
+};
+
+inline void SiHelper::maskOut(SiChargedDiode& chDiode, bool flag) {
+  if (flag) {
+    chDiode.m_word |=  MASKOUT_SET;
+  } else {
+    chDiode.m_word &= ~MASKOUT_SET;
+  }
+}
+    
+inline void SiHelper::noise(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  NOISE_SET;
+  } else {
+    chDiode.m_word &= ~NOISE_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::belowThreshold(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  BT_SET;
+  } else {
+    chDiode.m_word &= ~BT_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::disabled(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  DISABLED_SET;
+  } else {
+    chDiode.m_word &= ~DISABLED_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::badToT(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  BADTOT_SET;
+  } else {
+    chDiode.m_word &= ~BADTOT_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+
+inline void SiHelper::disconnected(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  DISCONNECTED_SET;
+  } else {
+    chDiode.m_word &= ~DISCONNECTED_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+
+
+inline void SiHelper::ClusterUsed(SiChargedDiode& chDiode, bool flag) {
+  if (flag) {
+    chDiode.m_word |=  CLUSTERUSED_SET;
+  } else {
+    chDiode.m_word &= ~CLUSTERUSED_SET;
+  }
+}
+
+inline void SiHelper::SetBunch(SiChargedDiode& chDiode, int bunch, MsgStream* log) {
+  //
+  // Code the bunch number in the 8 bits set corresponding to xx in xx00 
+  //
+  if (bunch > 0xff) {
+    if (log) (*log) << MSG::ERROR << "Bunch Number not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ( (bunch&0xff) <<8 )  ;
+}
+
+inline void SiHelper::SetStripNum(SiChargedDiode& chDiode, int nstrip, MsgStream* log) {
+  //
+  // Code the number of strips in the 12 bits set corresponding to xxx in 0xxx0000 
+  //
+  if (nstrip > 0xfff) {
+    if (log) (*log) << MSG::ERROR << "Number of strips not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ((nstrip&0xfff) << 16 ) ;
+}
+
+inline void SiHelper::SetTimeBin(SiChargedDiode& chDiode, int time, MsgStream* log) {
+  //
+  // Code the SCT Timebin number in the 3 bits set corresponding to x in x0000000
+  //
+  if (time > 0xf) {
+    if (log) (*log) << MSG::ERROR << "TimeBin not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ( (time&0xf) <<28 )  ;
+}
+
+////////////////////////////////////////////////////////////
+
+inline bool SiHelper::isUsable(SiChargedDiode& chDiode) {
+  return !SiHelper::isMaskOut(chDiode);
+  //  return (((chDiode.m_word & 0xff) == 0) ||     // no special status bits sets, either track, xtalk or random noise
+  //          (SiHelper::isClusterUsed(chDiode)) ); // cluster used - whatever that means - not set in digitization
+}
+
+inline bool SiHelper::isNoise(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & NOISE_SET);
+}
+
+inline bool SiHelper::isMaskOut(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & MASKOUT_SET);
+}
+
+inline bool SiHelper::isBelowThreshold(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & BT_SET);
+}
+    
+inline bool SiHelper::isDisabled(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & DISABLED_SET);
+}
+    
+inline bool SiHelper::isBadToT(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & BADTOT_SET);
+}
+
+inline bool SiHelper::isDisconnected(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & DISCONNECTED_SET);
+}
+
+inline bool SiHelper::isClusterUsed(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & CLUSTERUSED_SET);
+}
+
+inline int SiHelper::GetBunch(SiChargedDiode& chDiode) {
+return ( (chDiode.m_word >> 8) & 0xff );
+}
+
+inline int SiHelper::GetStripNum(SiChargedDiode& chDiode) {
+  return ( (chDiode.m_word >> 16) & 0xfff );
+}
+
+inline int SiHelper::GetTimeBin(SiChargedDiode& chDiode) {
+return ( (chDiode.m_word >> 28) & 0xf );
+}    
+
+
+#endif
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..f88065cf62253c5a7a9441649d007307f94406b2
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h
@@ -0,0 +1,86 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiSurfaceCharge.h
+//   Header file for class SiSurfaceCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains a charge located at the sensor surface
+///////////////////////////////////////////////////////////////////
+// Version 1.0 09/02/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERSIDIGITIZATION_SISURFACECHARGE_H
+#define FASERSIDIGITIZATION_SISURFACECHARGE_H
+
+//#include "SiTrackerDetDescr/SiLocalPosition.h"
+#include "TrackerReadoutGeometry/SiLocalPosition.h"
+#include "TrackerSimEvent/SiCharge.h"
+
+
+class SiSurfaceCharge {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Copy constructor:
+  SiSurfaceCharge(const SiSurfaceCharge &surfaceCharge);
+
+  // Constructor with parameters:
+  //   position at the sensor surface
+  //   charge located at this position
+  SiSurfaceCharge(const TrackerDD::SiLocalPosition &position,const SiCharge &charge);
+
+  // Destructor:
+  ~SiSurfaceCharge();
+
+  // Assignment operator:
+  SiSurfaceCharge &operator=(const SiSurfaceCharge &surfaceCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // position at the sensor surface:
+  TrackerDD::SiLocalPosition position() const;
+
+  // charge located at this position:
+  SiCharge charge() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiSurfaceCharge();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  TrackerDD::SiLocalPosition m_position; // position at the sensor surface
+  SiCharge m_charge; // charge located at this position
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiSurfaceCharge::~SiSurfaceCharge() 
+{}
+
+inline TrackerDD::SiLocalPosition SiSurfaceCharge::position() const
+{
+  return m_position;
+}
+
+inline SiCharge SiSurfaceCharge::charge() const
+{
+  return m_charge;
+}
+
+#endif // FASERSIDIGITIZATION_SISURFACECHARGE_H
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..622090839b51c6e19b1c04eeb5917b1509810b14
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiChargedDiode.cxx
+//   Implementation file for class SiChargedDiode
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 2.1 09/06/2001 David Calvet
+// Davide Costanzo. Revisited version. 04-03-03
+///////////////////////////////////////////////////////////////////
+
+#include "FaserSiDigitization/SiChargedDiode.h"
+
+
+// Constructor with parameters:
+SiChargedDiode::SiChargedDiode(const SiTotalCharge::alloc_t& alloc,
+                               const TrackerDD::SiCellId & diode, const TrackerDD::SiReadoutCellId & roCell,  int flagword, SiChargedDiode * nextInCluster) 
+  :  m_diode(diode),
+     m_totalCharge(alloc),
+     m_readoutCell(roCell),
+     m_word(flagword),
+     m_nextInCluster(nextInCluster)
+{}
+
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiChargedDiode &chargedDiode)
+{
+  out << "Diode=" << chargedDiode.diode()
+      << " " << chargedDiode.totalCharge();
+  return out;
+}
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..82ae6cb5562854c2225d8e89832128f70dd14b88
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx
@@ -0,0 +1,161 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// sichargeddiodecollection.cxx
+//   Implementation file for class SiChargedDiodeCollection
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 3.0 09/07/2001 David Calvet
+// 04-03-03 Revisited version. Davide Costanzo
+///////////////////////////////////////////////////////////////////
+// header file
+#include "FaserSiDigitization/SiChargedDiodeCollection.h"
+// member classes
+#include "FaserSiDigitization/SiHelper.h"
+#include "TrackerReadoutGeometry/SiDetectorDesign.h"
+#include "TrackerReadoutGeometry/SiReadoutCellId.h"
+#include "TrackerReadoutGeometry/SiCellId.h"
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/getMessageSvc.h"
+
+using namespace TrackerDD;
+
+
+
+SiChargedDiodeCollection::SiChargedDiodeCollection( ) :
+  m_chargedDiodes(),
+  m_sielement()
+{
+}
+
+SiChargedDiodeCollection::SiChargedDiodeCollection(const TrackerDD::SiDetectorElement* sielement ) :
+  m_chargedDiodes(),
+  m_sielement(sielement)
+{
+}
+
+
+SiChargedDiodeCollection::~SiChargedDiodeCollection()
+{
+}
+
+// Clean up the collection
+void SiChargedDiodeCollection::clear() {
+  m_sielement = 0;
+  m_chargedDiodes.erase(m_chargedDiodes.begin(), m_chargedDiodes.end() );
+  m_orderedChargedDiodes.clear();
+}
+
+// Add a new SiCharge to the collection 
+void SiChargedDiodeCollection::add(const SiCellId & diode,
+				   const SiCharge & charge)
+{
+  // check the pointer is correct
+  if (!diode.isValid()) return;
+
+  // find this diode in the charged diode collection
+  // find it by id in the map. 
+  //
+
+  SiChargedDiodeIterator the_diode = m_chargedDiodes.find(diode);
+
+  if(the_diode != m_chargedDiodes.end() ) {
+    // Add to existing charge
+    (*the_diode).second.add(charge);
+  } else {
+    // if the new diode has not been found in the collection
+    // get the read out cell from the design. 
+    //
+    SiReadoutCellId roCell=design().readoutIdOfCell(diode);
+    if (!roCell.isValid()) { // I don't think this can occur at this stage but cant hurt.
+      MsgStream log(Athena::getMessageSvc(),"SiChargedDiodeCollection");
+      log << MSG::FATAL << "Could not create SiReadoutCellId object !"<< endmsg;
+    }
+    // create a new charged diode
+    SiChargedDiode chargedDiode(m_allocator, diode,roCell);
+    // add the new charge to it
+    chargedDiode.add(charge);
+    if (charge.processType() == SiCharge::extraNoise) SiHelper::noise(chargedDiode,true);
+    // add the new charged diode to the charged diode collection
+    auto p = m_chargedDiodes.emplace(diode,chargedDiode);
+    if (!m_orderedChargedDiodes.empty()) {
+      m_orderedChargedDiodes.insert (&p.first->second);
+    }
+  }
+}
+
+// Add a new SiTotalCharge to the collection 
+void SiChargedDiodeCollection::add(const SiCellId & diode,
+				   const SiTotalCharge & totcharge)
+{
+  // check the pointer is correct
+  if (!diode.isValid()) return;
+
+  // find this diode in the charged diode collection
+  // find it by id in the map. 
+  //
+
+  SiChargedDiodeIterator the_diode = m_chargedDiodes.find(diode);
+
+  if(the_diode != m_chargedDiodes.end() ) {
+    // Add to existing charge
+    (*the_diode).second.add(totcharge);
+  } else {
+    // if the new diode has not been found in the collection
+    // get the read out cell from the design. 
+    //
+    SiReadoutCellId roCell=design().readoutIdOfCell(diode);
+    if (!roCell.isValid()) {  // I don't think this can occur at this stage but cant hurt.
+      MsgStream log(Athena::getMessageSvc(),"SiChargedDiodeCollection");
+      log << MSG::FATAL << "Could not create SiReadoutCellId object !"<< endmsg;
+    }
+    // create a new charged diode
+    SiChargedDiode chargedDiode(m_allocator, diode,roCell);
+    // add the new charge to it
+    chargedDiode.add(totcharge);
+    // add the new charged diode to the charged diode collection
+    auto p = m_chargedDiodes.emplace(diode,chargedDiode);
+    if (!m_orderedChargedDiodes.empty()) {
+      m_orderedChargedDiodes.insert (&p.first->second);
+    }
+  }
+}
+
+bool SiChargedDiodeCollection::AlreadyHit(const TrackerDD::SiCellId & siId) {
+  if(m_chargedDiodes.find(siId) == m_chargedDiodes.end() ) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool SiChargedDiodeCollection::AlreadyHit(const Identifier & id) {
+
+  const SiCellId cellId        = m_sielement->cellIdFromIdentifier(id);
+  return AlreadyHit(cellId);
+}
+
+SiChargedDiode * SiChargedDiodeCollection::find(const TrackerDD::SiCellId & siId) {
+  // get the compact Id to access the map
+  SiChargedDiodeIterator theEl = m_chargedDiodes.find(siId);
+  // if the diode exists return a pointer to it:
+  if (theEl == m_chargedDiodes.end() ) return NULL;
+  else return &( (*theEl).second);
+}		      
+
+SiChargedDiode * SiChargedDiodeCollection::find(Identifier siId) {
+
+  // Get the key for the map lookup
+  const SiCellId cellId        = m_sielement->cellIdFromIdentifier(siId);
+  return find(cellId);
+}		      
+
+void SiChargedDiodeCollection::order()
+{
+  for (auto& p : m_chargedDiodes) {
+    m_orderedChargedDiodes.insert (&p.second);
+  }
+}
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b1d5215f5c9a9d9d1f647eb41a0c47a6613d4fed
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiSurfaceCharge.cxx
+//   Implementation file for class SiSurfaceCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.0 01/02/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "FaserSiDigitization/SiSurfaceCharge.h"
+using namespace TrackerDD;
+// Copy constructor:
+SiSurfaceCharge::SiSurfaceCharge(const SiSurfaceCharge &surfaceCharge) :
+  m_position(surfaceCharge.m_position),
+  m_charge(surfaceCharge.m_charge)
+{}
+
+// Constructor with parameters:
+SiSurfaceCharge::SiSurfaceCharge(const SiLocalPosition &position,
+				 const SiCharge &charge) :
+  m_position(position),
+  m_charge(charge)
+{}
+
+// Assignment operator:
+SiSurfaceCharge &SiSurfaceCharge::operator=(const SiSurfaceCharge &surfaceCharge)
+{
+  if (this!=&surfaceCharge) {
+    m_position=surfaceCharge.m_position;
+    m_charge=surfaceCharge.m_charge;
+  } else {}
+  return *this;
+}
+
diff --git a/Tracker/TrackerSimEvent/TrackerSimEvent/FaserSiHit.h b/Tracker/TrackerSimEvent/TrackerSimEvent/FaserSiHit.h
index 8669b8809f5a98c6c0e579dd4703f72448bcf539..b17acf1db85d63a4fc006c450a34164a08be833d 100644
--- a/Tracker/TrackerSimEvent/TrackerSimEvent/FaserSiHit.h
+++ b/Tracker/TrackerSimEvent/TrackerSimEvent/FaserSiHit.h
@@ -141,8 +141,8 @@ private:
   HepMcParticleLink m_partLink;
   unsigned int m_ID;
 public:
-  // enum
-  //   { xDep = 2, xPhi = 0, xEta = 1};
+  enum
+    { xDep = 2, xPhi = 0, xEta = 1};
 };
 
 
diff --git a/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h b/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..81365d2fc68908e1b002e4f1dbcb0febe080c68e
--- /dev/null
+++ b/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h
@@ -0,0 +1,135 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCharge.h
+//   Header file for class SiCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains the bare charge deposited by a single process
+///////////////////////////////////////////////////////////////////
+// Version 1.4 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef SITRACKEREVENT_SICHARGE_H
+#define SITRACKEREVENT_SICHARGE_H
+
+#include <iostream>
+
+// Member classes
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+class SiCharge {
+
+public:
+  enum Process {no,track,diodeX_Talk,cellX_Talk,noise,extraNoise,cut_track};
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Copy constructor:
+  SiCharge(const SiCharge &charge);
+
+  // Constructor with parameters:
+  //   deposited charge
+  //   time of deposition
+  //   type of process which produced this charge
+  //   Particle Link to the particle generating the Charge
+  SiCharge(const double& charge,const double& time,
+	   const Process& processType,const HepMcParticleLink& PL);
+
+  SiCharge(const double& charge,const double& time,
+	   const Process& processType);
+
+  // Destructor:
+  ~SiCharge();
+
+  // Assignment operator:
+  SiCharge &operator=(const SiCharge &charge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // deposited charge:
+  double charge() const;
+
+  // time of deposition:
+  double time() const;
+
+  // type of process which produced this charge:
+  Process processType() const;
+
+  // Barcode of the particle generating the charge:
+  int trackBarcode() const;
+
+  // Particle Link of the particle generating the charge
+  const HepMcParticleLink& particleLink() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another charge, if the process and track are the same:
+  //   returns true if the charge was added
+  bool add(const SiCharge &charge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiCharge();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  double m_charge; // deposited charge
+  double m_time; // time of deposition
+  Process m_processType; // type of process which produced this charge
+  //  int m_trackNumber; // track number in case of track process
+  HepMcParticleLink m_partLink; //Replace the track number with a PL
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiCharge::~SiCharge() 
+{}
+
+inline double SiCharge::charge() const 
+{
+  return m_charge;
+}
+
+inline double SiCharge::time() const 
+{
+  return m_time;
+}
+
+inline SiCharge::Process SiCharge::processType() const 
+{
+  return m_processType;
+}
+
+inline int SiCharge::trackBarcode() const 
+{
+  return m_partLink.barcode();
+}
+
+inline const HepMcParticleLink& SiCharge::particleLink() const 
+{
+  return m_partLink;
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiCharge &charge);
+
+#endif // SITRACKEREVENT_SICHARGE_H
diff --git a/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h b/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..dec3f37333cea86d234560835b884200e1655806
--- /dev/null
+++ b/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h
@@ -0,0 +1,176 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiTotalCharge.h
+//   Header file for class SiTotalCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains the sum and the composition of all bare charges
+// corresponding to a single element
+///////////////////////////////////////////////////////////////////
+// Version 1.5 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef SITRACKEREVENT_SITOTALCHARGE_H
+#define SITRACKEREVENT_SITOTALCHARGE_H
+
+#include <list>
+#include "TrackerSimEvent/SiCharge.h"
+#include "AthAllocators/ArenaSharedHeapSTLAllocator.h"
+
+class SiTotalCharge {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  typedef SG::ArenaSharedHeapSTLAllocator<SiCharge> alloc_t;
+  typedef std::list<SiCharge, alloc_t> list_t;
+
+  // Implicit constructor:
+  SiTotalCharge(const alloc_t& alloc);
+
+  // Copy constructor:
+  SiTotalCharge(const SiTotalCharge &totalCharge);
+
+  // Destructor:
+  ~SiTotalCharge();
+
+  // Assignment operator:
+  SiTotalCharge &operator=(const SiTotalCharge &totalCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // total deposited charge in this element:
+  double charge() const;
+
+  // list of individual charges:
+  const list_t &chargeComposition() const;
+
+  // return true if the charge composition contains more than one charge:
+  bool complexCharge() const;
+
+  // return true if the main charge comes from a track (track/diodeX_Talk):
+  bool fromTrack() const;
+
+  // return true if the main charge is extraNoise:
+  bool extraNoise() const;
+
+  // return the barcode of the main charge:
+  int trackBarcode() const;
+
+  // returns the HepMcParticleLink of the main charge
+  const HepMcParticleLink& particleLink() const;
+
+  // return the time of the main charge
+  double time() const;
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another SiCharge:
+  void add(const SiCharge &charge);
+
+  // add another SiTotalCharge:
+  void add(const SiTotalCharge &totalCharge);
+
+  // remove time information of the SiCharge objects:
+  void removeTimeInformation();
+
+  // remove small SiCharge objects:
+  //   minimum charge allowed to keep a SiCharge in the composition list
+  void removeSmallCharges(const double minimumCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  // add another SiCharge to the charge composition (not the total value):
+  void addSiCharge(const SiCharge &charge);
+
+  // return the SiCharge corresponding to the process which deposited
+  // the biggest amount of charge (returns dummy charge if list is empty)
+  // (used to be a public method, but this caused problems if the list was empty):
+  const SiCharge& mainCharge() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  double m_charge; // total deposited charge in this element
+  list_t m_chargeComposition; // list of individual charges
+  HepMcParticleLink m_emptyLink;
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiTotalCharge::~SiTotalCharge()
+{
+}
+
+inline double SiTotalCharge::charge() const 
+{
+  return m_charge;
+}
+
+inline const SiTotalCharge::list_t &SiTotalCharge::chargeComposition() const 
+{
+  return m_chargeComposition;
+}
+
+inline bool SiTotalCharge::complexCharge() const 
+{
+  return (m_chargeComposition.size()>1);
+}
+
+inline bool SiTotalCharge::extraNoise() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return false;
+    }
+  return (mainCharge().processType()==SiCharge::extraNoise);
+}
+
+inline int SiTotalCharge::trackBarcode() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return 0;
+    }
+  return mainCharge().trackBarcode();
+}
+
+inline double SiTotalCharge::time() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return 0.0;
+    }
+  return mainCharge().time();
+}
+
+inline const HepMcParticleLink& SiTotalCharge::particleLink() const
+{
+  if(m_chargeComposition.empty())
+    {
+      return m_emptyLink;
+    }
+  return mainCharge().particleLink();
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiTotalCharge &totalCharge);
+
+#endif // SITRACKEREVENT_SITOTALCHARGE_H
diff --git a/Tracker/TrackerSimEvent/src/SiCharge.cxx b/Tracker/TrackerSimEvent/src/SiCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f24f342adb044ab4f6c79708207efff3b7193f2b
--- /dev/null
+++ b/Tracker/TrackerSimEvent/src/SiCharge.cxx
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCharge.cxx
+//   Implementation file for class SiCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.4 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "TrackerSimEvent/SiCharge.h"
+
+// Copy constructor:
+SiCharge::SiCharge(const SiCharge &charge) :
+  m_charge(charge.m_charge),
+  m_time(charge.m_time),
+  m_processType(charge.m_processType),
+  m_partLink(charge.m_partLink)
+{}
+
+// Constructor with parameters:
+SiCharge::SiCharge(const double& charge,const double& time,
+		   const Process& processType,const HepMcParticleLink& PL) :
+  m_charge(charge),
+  m_time(time),
+  m_processType(processType),
+  m_partLink(PL)
+{}
+
+SiCharge::SiCharge(const double& charge,const double& time,
+		   const Process& processType) :
+  m_charge(charge),
+  m_time(time),
+  m_processType(processType),
+  m_partLink(HepMcParticleLink((unsigned int) 0, 0))
+{}
+
+
+// Assignment operator:
+SiCharge &SiCharge::operator=(const SiCharge &charge)
+{
+  if (this!=&charge) {
+    m_charge=charge.m_charge;
+    m_time=charge.m_time;
+    m_processType=charge.m_processType;
+    m_partLink=charge.m_partLink;
+  } else {}
+  return *this;
+}
+
+// add another charge, if the process and track are the same:
+bool SiCharge::add(const SiCharge &charge)
+{
+  // check if the two charges are compatible
+  if (charge.m_processType!=m_processType || 
+      charge.m_partLink!=m_partLink ||
+      charge.m_time!=m_time) {
+    return false;
+  } else {
+    m_charge+=charge.m_charge;
+    return true;
+  }
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiCharge &charge)
+{
+  out << "Charge=" << charge.charge() << " Time=" << charge.time()
+      << " Process=";
+  if (charge.processType()==SiCharge::no) out << "no";
+  else if (charge.processType()==SiCharge::track) out << "track";
+  else if (charge.processType()==SiCharge::diodeX_Talk) out << "diodeX_Talk";
+  else if (charge.processType()==SiCharge::cellX_Talk) out << "cellX_Talk";
+  else if (charge.processType()==SiCharge::noise) out << "noise";
+  else if (charge.processType()==SiCharge::extraNoise) out << "extraNoise";
+  else if (charge.processType()==SiCharge::cut_track) out << "cut_track";
+  else out << "UNKNOWN !";
+  return (out << " Barcode=" << charge.trackBarcode());
+}
+
diff --git a/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx b/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2d17b4d1144e899f7d098bb3657f2d27ab669b98
--- /dev/null
+++ b/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiTotalCharge.cxx
+//   Implementation file for class SiTotalCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.5 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "TrackerSimEvent/SiTotalCharge.h"
+#include <iterator>
+
+// Implicit constructor:
+SiTotalCharge::SiTotalCharge(const alloc_t& alloc) :
+  m_charge(0),
+  m_chargeComposition(alloc),
+  m_emptyLink((unsigned int) 0, 0)
+{}
+
+// Copy constructor:
+SiTotalCharge::SiTotalCharge(const SiTotalCharge &totalCharge) :
+  m_charge(totalCharge.m_charge),
+  m_chargeComposition(totalCharge.m_chargeComposition),
+  m_emptyLink((unsigned int) 0, 0)
+{}
+
+// Assignment operator:
+SiTotalCharge &SiTotalCharge::operator=(const SiTotalCharge &totalCharge)
+{
+  if (this!=&totalCharge) {
+    m_charge=totalCharge.m_charge;
+    m_chargeComposition=totalCharge.m_chargeComposition;
+    m_emptyLink=totalCharge.m_emptyLink;
+  } else {}
+  return *this;
+}
+
+// give main single process charge:
+const SiCharge& SiTotalCharge::mainCharge() const
+{
+  // start with the first charge
+  list_t::const_iterator p_charge=m_chargeComposition.begin();
+
+  // main charge to be determined, initialized to the first one
+  list_t::const_iterator main_charge = p_charge;
+  ++p_charge;
+  // look for the biggest amount of charge in the remaining charges
+  for( ; p_charge!=m_chargeComposition.end() ; ++p_charge) {
+    if (p_charge->charge()>main_charge->charge()) main_charge=p_charge;
+  }
+  return *main_charge;
+}
+
+bool SiTotalCharge::fromTrack() const 
+{
+  if(m_chargeComposition.size()==0)
+    {
+      return false;
+    }
+  SiCharge::Process process=mainCharge().processType();
+  return (process==SiCharge::track || 
+	  process==SiCharge::cut_track || 
+	  process==SiCharge::diodeX_Talk);
+}
+
+// add another charge:
+void SiTotalCharge::add(const SiCharge &charge)
+{
+  // increase the total deposited charge
+  m_charge+=charge.charge();
+
+  // add the SiCharge to the list of charges
+  addSiCharge(charge);
+}
+
+// add another total charge:
+void SiTotalCharge::add(const SiTotalCharge &totalCharge)
+{
+  // increase the total deposited charge
+  m_charge+=totalCharge.charge();
+
+  // add the new list of charges to the present list of charges
+  for(list_t::const_iterator p_charge=
+	totalCharge.chargeComposition().begin() ;
+      p_charge!=totalCharge.chargeComposition().end() ; ++p_charge) {
+    addSiCharge(*p_charge);
+  }
+}
+
+// remove time information of the SiCharge objects:
+void SiTotalCharge::removeTimeInformation()
+{
+  // save the old charge composition
+  list_t oldComposition;
+  m_chargeComposition.swap(oldComposition);
+
+  // loop on all old charges
+  for(list_t::const_iterator p_charge=oldComposition.begin() ;
+      p_charge!=oldComposition.end() ; ++p_charge) {
+    // add the old charge (without time) to the list
+    addSiCharge(SiCharge(p_charge->charge(),0,
+			 p_charge->processType(),p_charge->particleLink()));
+  }
+}
+
+// remove small SiCharge objects:
+void SiTotalCharge::removeSmallCharges(const double minimumCharge)
+{
+  // loop on all charges
+  for(list_t::iterator p_charge=m_chargeComposition.begin() ;
+      p_charge!=m_chargeComposition.end() ; ) { 
+    // !!! p_charge is changed in the loop !!!
+
+    // if the charge is too small remove it from list
+    if (p_charge->charge()>-minimumCharge && 
+	p_charge->charge()<minimumCharge) {
+      p_charge=m_chargeComposition.erase(p_charge);
+    } else {
+      ++p_charge;
+    }
+  }
+}
+
+// add another SiCharge to the charge composition (not the total value):
+void SiTotalCharge::addSiCharge(const SiCharge &charge)
+{
+  // try to merge the SiCharge in the list of existing charges
+  for(list_t::iterator p_charge=m_chargeComposition.begin() ;
+      p_charge!=m_chargeComposition.end() ; ++p_charge) {
+    if (p_charge->add(charge)) return;
+  }
+  // add the charge to the list if not merged in existing one
+  m_chargeComposition.push_back(charge);
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiTotalCharge &totalCharge)
+{
+  out << "Total charge=" << totalCharge.charge() 
+      << " Composition:" << std::endl;
+  copy(totalCharge.chargeComposition().begin(),
+       totalCharge.chargeComposition().end(),
+       std::ostream_iterator<SiCharge>(out,"\n"));
+  return out;
+}
+