From e12aa8ed4345e136e4de7e2382171dba8da38d25 Mon Sep 17 00:00:00 2001
From: Soshi Tsuno <soshi.tsuno@cern.ch>
Date: Thu, 16 Feb 2017 16:45:58 +0100
Subject: [PATCH] fix coverity defect (PixelDigitization-02-03-30)

  * Fix coverity defect.
	* Tagged as PixelDigitization-02-03-30.

2017-02-10  Soshi Tsuno
  * Add front-end simulation tool.
  * Delete PixelCellDiscriminator. Now this functionality is done in front-end sim tool.
	* Tagged as PixelDigitization-02-03-29.
---
 .../PixelDigitization/doc/mainpage.h          | 250 ---------
 .../python/PixelDigitizationConfig.py         |  75 +--
 .../python/PixelDigitizationConfigDb.py       |   7 +-
 .../PixelDigitization/src/FEI3SimTool.cxx     | 133 +++++
 .../PixelDigitization/src/FEI3SimTool.h       |  33 ++
 .../PixelDigitization/src/FEI4SimTool.cxx     | 186 +++++++
 .../PixelDigitization/src/FEI4SimTool.h       |  28 +
 .../PixelDigitization/src/FrontEndSimTool.h   | 100 ++++
 .../src/PixelCellDiscriminator.cxx            | 153 ------
 .../src/PixelCellDiscriminator.h              |  89 ---
 .../src/PixelDigitizationTool.cxx             | 516 +++---------------
 .../src/PixelDigitizationTool.h               | 196 ++-----
 .../PixelDigitization/src/TimeSvc.cxx         |   7 +-
 .../PixelDigitization/src/TimeSvc.h           |   3 +-
 .../components/PixelDigitization_entries.cxx  |  12 +-
 15 files changed, 662 insertions(+), 1126 deletions(-)
 delete mode 100755 InnerDetector/InDetDigitization/PixelDigitization/doc/mainpage.h
 create mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.cxx
 create mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.h
 create mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.cxx
 create mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.h
 create mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/FrontEndSimTool.h
 delete mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.cxx
 delete mode 100644 InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.h

diff --git a/InnerDetector/InDetDigitization/PixelDigitization/doc/mainpage.h b/InnerDetector/InDetDigitization/PixelDigitization/doc/mainpage.h
deleted file mode 100755
index 4c603ca87b8..00000000000
--- a/InnerDetector/InDetDigitization/PixelDigitization/doc/mainpage.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-/**
-@mainpage PixelDigitization
-@author fredrik.tegenfeldt@cern.ch
-
-@section PixelDigitizationIntro Introduction
-
-The package PixelDigitization provides the simulation of the pixel
-detector response. It reads the pixel detector hits generated by
-Geant4 and 'digitizes' the information. In addition several other
-detector effects not necessarily related to hits are treated.  The
-result is output as so called RDO objects. These are then read by e.g
-the clustering and tracking algorithm further upstream of the
-processing.
-
-@section PixelDigitizationClasses Classes
-
-The package consists of three groups of classes:
--# main class PixelDigitization : the user interface, reads the input hits and generates the output RDOs
--# surface charge generator : generates the initial charge collection from the Geant4 hits
--# charge processors : simulates various detector effects and operates on the current collection of charges
-
-Together with SCT_Digitization, the package inherits functionality from SiDigitization.
-Briefly they are:
-
-<table border="0">
-<tr>
- <td> 1. SiDigitization </td>                <td>: contains common framework with SCT_Digitization </td>
-</tr>
-<tr>
- <td> 2. SiChargedDiodeProcessor </td>       <td>: charged diode processor; all charge modifiers must inherit from this class </td>
-</tr>
-<tr>
- <td> 3. SiChargedDiode </td>                <td>: a class that contains the charge of a given pixel element </td>
-</tr>
-<tr>
- <td> 4. SiChargedDiodeCollection </td>      <td>: the container used internally to keep track of the generated charges </td>
-</tr>
-<tr>
- <td> 5. SiHelper </td>                      <td>: static class with members operating on the SiChargeDiode status flag </td>
-</tr>
-<tr>
- <td> 6. SiRandomDisabledCellGenerator </td> <td>: disables random pixels according to a given probability </td>
-</tr>
-</table>
-
-<b>NOTE: the current software design of the charge processors should be migrated to using (private) AlgTools (F.T, 26/7/2007)</b>
-
-In the table below, all the classes in the package are summarized.
-Columns 2-4 refers to how they operate on the collection of charged
-diodes.
-
-<table>
-  <tr style="background-color: rgb(255, 255, 153);">
-   <td style="text-align: center;"><b>Class</b><br></td>
-   <td style="text-align: center;"><b>Modifies</b><br></td>
-   <td style="text-align: center;"><b>Adds</b><br></td>
-   <td style="text-align: center;"><b>Removes</b><br></td>
-   <td style="text-align: center;"><b>Description</b><br></td>
-  </tr>
-  <tr>
-   <td>PixelDigitization<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td>main class<br></td>
-  </tr>
-  <tr>
-   <td>PixelSimpleSurfaceChargesGenerator<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td>generates the initial charge collection from the G4 hits<br></td>
-  </tr>
-  <tr>
-   <td>PixelChargeSmearer<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;"> <br></td>
-   <td>adds random gaussian noise to existing charges<br></td>
-  </tr>
-  <tr>
-   <td>PixelDiodeCrossTalkGenerator<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td>generates cross talk<br></td>
-  </tr>
-  <tr>
-   <td>PixelGangedMerger<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td>merges ganged pixels<br></td>
-  </tr>
-  <tr>
-   <td>SpecialPixelGenerator<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td>simulates special pixels using special pixel maps, simulated or from cond. DB<br></td>
-  </tr>
-  <tr>
-   <td>PixelTimeWalkGenerator<br></td>
-   <td style="text-align: center;">X<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td>simulates the timing of the RDOs<br></td>
-  </tr>
-  <tr>
-   <td>PixelCellDiscriminator<br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;"> <br></td>
-   <td style="text-align: center;">X<br></td>
-   <td>simulates the discrimination<br></td>
-  </tr>
-</table>
-
-@section PixelDigitizationFromTOTtoRDO From TOT to RDO
-The order of the following subsections follow the actual order they are executed.
-
-@subsection PixelDigitizationSurfaceCharge 1. Surface charge
-
-<em>Uses class PixelSimpleSurfaceChargesGenerator</em>
-
-The algorithm finds the entry and exit points of the track in the
-detector element. This distance is divided into a number of steps
-(default = 5). It is then assumed that an equal fraction of the total
-charge is deposited at each step. The obtained charge is then split
-into several charges (default = 100), each of which are then diffused
-to the surface of the detector. It takes into account the Lorentz
-angle and the stochastic nature of the diffusion.
-
-@subsection PixelDigitizationCrossTalk 2. Cross talk
-
-<em>Uses class PixelDiodeCrossTalkGenerator</em>
-
-Cross talk is generated if the original pixel has a minimum charge of
-3 times the discriminator threshold. If that is true, the neighboring
-pixels with one side in common will be given a charge. The length of
-the common side is referred to as intersection length. For a neighbor
-with the same column number this length will be 400 microns (600 for
-long pixels). If the row number is the same, the length is then 50
-microns. The deposited charge is proportional (jobOpt DiodeCrossTalk)
-to the product of this length and the original charge.
-
-@subsection PixelDigitizationThermalNoise 3. Thermal noise
-
-<em>Uses class PixelChargeSmearer</em>
-
-Each charge created up to this point is smeared with a gaussian of a
-given amplitude (currently 200e-). This does not create any new
-charged pixels.
-
-@subsection PixelDigitizationGeneralNoise 4. General noise
-
-<em>Uses class PixelNoisyCellGenerator</em>
-
-The purpose with this is to add noise to random pixels irrespective if
-they have hits or not. As with the thermal noise, this adds a
-gaussian. However, in this case the mean is 3 sigma over the
-discriminator threshold with the same spread as the threshold. This
-will both modify existing charges and create new charged pixels.
-
-@subsection PixelDigitizationMergeGangedPixels 5. Merge ganged pixels
-
-<em>Uses class PixelGangedMerger</em>
-
-This modifier merges ganged pixels and masks out the pixel not corresponding
-to the read out electronics (is the mask out really needed??).
-
-@subsection PixelDigitizationSpecialPixels 6. Special pixels
-
-<em>Uses class SpecialPixelGenerator</em>
-
-In reality the detector will have problematic pixels that either will
-be completely silent or noisy. They are masked out using special pixel
-maps. The maps may be obtained from conditions database or simulated
-using a set of probabilities. If they are simulated, there is the
-option of simulating various Interval Of Validity (IOV) scenarios. All
-types of special pixels are defined here.
-
-In addition to the special pixel maps, pixels may also be randomly disabled
-independently of the special pixel map. This is to simulate random inefficiencies.
-The frequency is controlled through a single probability.
-
-@subsection PixelDigitizationRandomDisabling 7. Random disabling
-
-<em>Uses class SiRandomDisabledCellGenerator</em>
-
-The purpose of this modifer is to randomly disable pixelson an event-by-event basis.
-This simulates random inefficiences arising from non-masked pixels being temporarily disabled.
-A pixel is declared as disabled if a flat random number is below RndDisableProb.
-
-@subsection PixelDigitizationTimingAndDiscrimination 8. Timing and discrimination
-
-<em>Uses class PixelTimeWalkGenerator and PixelCellDiscriminator</em>
-
-The timing is simulated as follows:
-
--# set time to an offset value (jobOption: TimeZero)
--# calculate time walk using the threshold and intime threshold (parametrised); the result is smeared by a gaussian
--# add random jitter (jobOption: TimeJitter - flat distribution [-jitter/2, +jitter/2] )
--# add G4Time and subtract ComTime (if used)
--# BCID = time/TimePerBCO 
-
-If the obtained BCID is outside the range [0,timeBCN-1], the pixel is
-flagged as below threshold and thus removed from further processing.
-
-The discrimination compares the charge of the pixel with a threshold
-drawn randomly from a gaussian with mean and width from conditions
-database. Optionally, they may be set in jobOptions (DiscrThresh and
-DiscrThreshVar). If the charge is below the obtained threshold, the
-pixel is flagged as such.
-
-@subsection PixelDigitizationToTCalculationAndRDO 9. ToT calculation and RDO
-
-The TOT is calculated using a paremtrization where the parameters are
-either supplied by the user or taken from cond DB.
-
-For each valid
-charge collection, a RDO is created and stored in storegate.In
-addition a collection of SDO objects (not clear if they are
-used??). The collection contains a map between the deposited charge
-and the truth (InDetSimData).For debugging purposes there exists an
-option RDOfromSPM. If set, a RDO collection will be created containing
-just the special pixel map. The RDOs in this collection will have a
-fixed ToT and time. Its name is derived by adding the postfix "_SPM"
-to the RDO collection name. Both RDO collections can be viewed using
-for example the PixelMonitoring package.
-
-@section PixelDigitizationExtras Extra Pages
-
- - @ref PixelDigitizationUsedPackages
- - @ref PixelDigitizationRequirements
-*/
-
-/**
-@page PixelDigitizationUsedPackages Used Packages
-@htmlinclude used_packages.html
-*/
-
-/**
-@page PixelDigitizationRequirements Requirements
-@include requirements
-*/
-
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfig.py b/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfig.py
index 8b10fcc232a..69ad0c471a0 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfig.py
+++ b/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfig.py
@@ -158,15 +158,38 @@ def TimeSvc(name="TimeSvc", **kwargs):
     kwargs.setdefault("TimeBCN",timeBCN)
     return CfgMgr.TimeSvc(name, **kwargs)
 
-def PixelCellDiscriminator(name="PixelCellDiscriminator", **kwargs):
+def PixelRandomDisabledCellGenerator(name="PixelRandomDisabledCellGenerator", **kwargs):
     kwargs.setdefault("RndmSvc", digitizationFlags.rndmSvc())
     kwargs.setdefault("RndmEngine", "PixelDigitization")
-    return CfgMgr.PixelCellDiscriminator(name, **kwargs)
+    return CfgMgr.PixelRandomDisabledCellGenerator(name, **kwargs)
 
-def PixelRandomDisabledCellGenerator(name="PixelRandomDisabledCellGenerator", **kwargs):
+def FrontEndSimTool(name="FrontEndSimTool", **kwargs):
     kwargs.setdefault("RndmSvc", digitizationFlags.rndmSvc())
     kwargs.setdefault("RndmEngine", "PixelDigitization")
-    return CfgMgr.PixelRandomDisabledCellGenerator(name, **kwargs)
+    return CfgMgr.FrontEndSimTool(name, **kwargs)
+
+def FEI4SimTool(name="FEI4SimTool", **kwargs):
+    kwargs.setdefault("RndmSvc", digitizationFlags.rndmSvc())
+    kwargs.setdefault("RndmEngine", "PixelDigitization")
+    kwargs.setdefault("BarrelToTthreshold", [-1])
+    kwargs.setdefault("EndcapToTthreshold", [-1,-1,-1])
+    kwargs.setdefault("HitDiscConfig", 2)
+    kwargs.setdefault("TimingTune", 2015)
+    return CfgMgr.FEI4SimTool(name, **kwargs)
+
+def FEI3SimTool(name="FEI3SimTool", **kwargs):
+    kwargs.setdefault("RndmSvc", digitizationFlags.rndmSvc())
+    kwargs.setdefault("RndmEngine", "PixelDigitization")
+    kwargs.setdefault("BarrelToTthreshold", [-1, 5, 5, 5])    # first argument is dummy
+    kwargs.setdefault("EndcapToTthreshold", [ 5, 5, 5])
+    kwargs.setdefault("BarrelLatency", [ -1, 151, 256, 256])
+    kwargs.setdefault("EndcapLatency", [256, 256, 256])
+    kwargs.setdefault("BarrelHitDuplication", [False, False, False, False])
+    kwargs.setdefault("EndcapHitDuplication", [False, False, False])
+    kwargs.setdefault("BarrelSmallHitToT", [-1, -1, -1, -1])
+    kwargs.setdefault("EndcapSmallHitToT", [-1, -1, -1])
+    kwargs.setdefault("TimingTune", 2015)
+    return CfgMgr.FEI3SimTool(name, **kwargs)
 
 def BasicPixelDigitizationTool(name="PixelDigitizationTool", **kwargs):
     from AthenaCommon import CfgGetter
@@ -196,44 +219,32 @@ def BasicPixelDigitizationTool(name="PixelDigitizationTool", **kwargs):
       ServiceMgr += pixelSiPropertiesSvc
     kwargs.setdefault("InputObjectName", "PixelHits")
     pixTools = []
-    pixTools += ['PixelDiodeCrossTalkGenerator']
-    pixTools += ['PixelChargeSmearer']
-    pixTools += ['PixelNoisyCellGenerator']
-    pixTools += ['PixelGangedMerger']
-    pixTools += ['PixelRandomDisabledCellGenerator']
-    pixTools += ['PixelCellDiscriminator']
-    kwargs.setdefault("PixelTools", pixTools)
     chargeTools = []
+    feSimTools = []
     if GeometryFlags.isSLHC():
+      pixTools += ['PixelDiodeCrossTalkGenerator']
+      pixTools += ['PixelChargeSmearer']
+      pixTools += ['PixelNoisyCellGenerator']
+      pixTools += ['PixelGangedMerger']
+      pixTools += ['PixelRandomDisabledCellGenerator']
       chargeTools += ['IblPlanarBichselChargeTool']
+      feSimTools += ['FEI4SimTool']
     else:
+      pixTools += ['PixelDiodeCrossTalkGenerator']
+      pixTools += ['PixelChargeSmearer']
+      pixTools += ['PixelNoisyCellGenerator']
+      pixTools += ['PixelGangedMerger']
+      pixTools += ['PixelRandomDisabledCellGenerator']
       chargeTools += ['DBMChargeTool']
       chargeTools += ['PixelECBichselChargeTool']
       chargeTools += ['PixelBarrelBichselChargeTool']
       chargeTools += ['IblPlanarBichselChargeTool']
       chargeTools += ['Ibl3DBichselChargeTool']
+      feSimTools += ['FEI4SimTool']
+      feSimTools += ['FEI3SimTool']
+    kwargs.setdefault("PixelTools", pixTools)
     kwargs.setdefault("ChargeTools", chargeTools)
-    if GeometryFlags.isSLHC():
-        LVL1Latency = [255, 255, 255, 255, 255, 16, 255]
-        ToTMinCut = [0, 0, 0, 0, 0, 0, 0]
-        ApplyDupli = [False, False, False, False, False, False, False]
-        LowTOTduplication = [0, 0, 0, 0, 0, 0, 0]
-        kwargs.setdefault("LVL1Latency", LVL1Latency)
-        kwargs.setdefault("ToTMinCut", ToTMinCut)
-        kwargs.setdefault("ApplyDupli", ApplyDupli)
-        kwargs.setdefault("LowTOTduplication", LowTOTduplication)
-    else:
-        # For LVL1Latency, ToTMinCut, ApplyDupli and LowTOTduplication, first component [0] is always for IBL, even for run 1 production.
-        # The order is IBL, BL, L1, L2, EC, DBM
-        # For IBL and DBM, values of LVL1Latency and LowToTDupli are superseded by values driven by HitDiscCnfg settings, in PixelDigitizationTool.cxx
-        LVL1Latency = [16, 150, 255, 255, 255, 16]
-        ToTMinCut = [0, 6, 6, 6, 6, 0]
-        ApplyDupli = [True, False, False, False, False, False]
-        LowTOTduplication = [0, 7, 7, 7, 7, 0]
-        kwargs.setdefault("LVL1Latency", LVL1Latency)
-        kwargs.setdefault("ToTMinCut", ToTMinCut)
-        kwargs.setdefault("ApplyDupli", ApplyDupli)
-        kwargs.setdefault("LowTOTduplication", LowTOTduplication)
+    kwargs.setdefault("FrontEndSimTools", feSimTools)
     if digitizationFlags.doXingByXingPileUp(): # PileUpTool approach
         kwargs.setdefault("FirstXing", Pixel_FirstXing() )
         kwargs.setdefault("LastXing", Pixel_LastXing() )
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfigDb.py b/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfigDb.py
index 5c9c61a125c..581cbafd9a0 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfigDb.py
+++ b/InnerDetector/InDetDigitization/PixelDigitization/python/PixelDigitizationConfigDb.py
@@ -11,13 +11,10 @@ addAlgorithm("PixelDigitization.PixelDigitizationConfig.PixelDigitizationHS"  ,
 addAlgorithm("PixelDigitization.PixelDigitizationConfig.PixelDigitizationPU"  , "PixelDigitizationPU")
 addTool("PixelDigitization.PixelDigitizationConfig.getPixelRange", "PixelRange")
 addService("PixelDigitization.PixelDigitizationConfig.ChargeCollProbSvc","ChargeCollProbSvc")
-addTool("PixelDigitization.PixelDigitizationConfig.SurfaceChargesTool", "SurfaceChargesTool")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelNoisyCellGenerator", "PixelNoisyCellGenerator")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelGangedMerger", "PixelGangedMerger")
-addTool("PixelDigitization.PixelDigitizationConfig.SpecialPixelGenerator", "SpecialPixelGenerator")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelChargeSmearer", "PixelChargeSmearer")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelDiodeCrossTalkGenerator", "PixelDiodeCrossTalkGenerator")
-addTool("PixelDigitization.PixelDigitizationConfig.PixelCellDiscriminator", "PixelCellDiscriminator")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelRandomDisabledCellGenerator", "PixelRandomDisabledCellGenerator")
 addTool("PixelDigitization.PixelDigitizationConfig.DBMChargeTool","DBMChargeTool")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelBarrelChargeTool","PixelBarrelChargeTool")
@@ -25,8 +22,10 @@ addTool("PixelDigitization.PixelDigitizationConfig.PixelECChargeTool","PixelECCh
 addTool("PixelDigitization.PixelDigitizationConfig.IblPlanarChargeTool","IblPlanarChargeTool")
 addTool("PixelDigitization.PixelDigitizationConfig.Ibl3DChargeTool","Ibl3DChargeTool")
 addTool("PixelDigitization.PixelDigitizationConfig.SubChargesTool","SubChargesTool")
+addTool("PixelDigitization.PixelDigitizationConfig.FrontEndSimTool","FrontEndSimTool")
+addTool("PixelDigitization.PixelDigitizationConfig.FEI4SimTool","FEI4SimTool")
+addTool("PixelDigitization.PixelDigitizationConfig.FEI3SimTool","FEI3SimTool")
 addService("PixelDigitization.PixelDigitizationConfig.TimeSvc","TimeSvc")
-addService("PixelDigitization.PixelDigitizationConfig.CalibSvc","CalibSvc")
 addTool("PixelDigitization.PixelDigitizationConfig.PixelOverlayDigitizationTool", "PixelOverlayDigitizationTool")
 addAlgorithm("PixelDigitization.PixelDigitizationConfig.PixelOverlayDigitization", "PixelOverlayDigitization")
 
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.cxx
new file mode 100644
index 00000000000..b9aa4180865
--- /dev/null
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.cxx
@@ -0,0 +1,133 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FEI3SimTool.h"
+
+#include "InDetReadoutGeometry/PixelModuleDesign.h"
+
+#include "SiDigitization/SiHelper.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+
+FEI3SimTool::FEI3SimTool( const std::string& type, const std::string& name,const IInterface* parent):
+  FrontEndSimTool(type,name,parent),
+  m_BarrelHitDuplication({false,false,false,false,false,false,false}),
+  m_EndcapHitDuplication({false,false,false,false,false,false,false}),
+  m_BarrelSmallHitToT({7,7,7,7,7,7,7}),
+  m_EndcapSmallHitToT({7,7,7,7,7,7,7}),
+  m_timingTune(2015)
+{
+  declareProperty("BarrelHitDuplication", m_BarrelHitDuplication);
+  declareProperty("EndcapHitDuplication", m_EndcapHitDuplication);
+  declareProperty("BarrelSmallHitToT",    m_BarrelSmallHitToT);
+  declareProperty("EndcapSmallHitToT",    m_EndcapSmallHitToT);
+	declareProperty("TimingTune",           m_timingTune, "Version of the timing calibration");	
+}
+
+FEI3SimTool::~FEI3SimTool() { }
+
+StatusCode FEI3SimTool::initialize() {
+  CHECK(FrontEndSimTool::initialize());
+  ATH_MSG_DEBUG("FEI3SimTool::initialize()");
+	return StatusCode::SUCCESS;
+}
+
+StatusCode FEI3SimTool::finalize() {
+  ATH_MSG_DEBUG("FEI3SimTool::finalize()");
+	return StatusCode::SUCCESS;
+}
+
+void FEI3SimTool::process(SiChargedDiodeCollection &chargedDiodes,PixelRDO_Collection &rdoCollection) {
+
+  const InDetDD::PixelModuleDesign *p_design = static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
+  if (p_design->getReadoutTechnology()!=InDetDD::PixelModuleDesign::FEI3) { return; }
+
+  const PixelID* pixelId = static_cast<const PixelID *>(chargedDiodes.element()->getIdHelper());
+  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes.identify()); // wafer hash
+
+  int barrel_ec   = pixelId->barrel_ec(chargedDiodes.element()->identify());
+  int layerIndex  = pixelId->layer_disk(chargedDiodes.element()->identify());
+  int moduleIndex = pixelId->eta_module(chargedDiodes.element()->identify());
+
+  for (SiChargedDiodeIterator i_chargedDiode=chargedDiodes.begin(); i_chargedDiode!=chargedDiodes.end(); ++i_chargedDiode) {
+
+    Identifier diodeID = chargedDiodes.getId((*i_chargedDiode).first);
+
+    // Apply analogu threshold, timing simulation
+    double th0  = m_pixelCalibSvc->getThreshold(diodeID);
+    double ith0 = m_pixelCalibSvc->getTimeWalk(diodeID);
+
+    double threshold = th0+m_pixelCalibSvc->getThresholdSigma(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine)+m_pixelCalibSvc->getNoise(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine);
+    double intimethreshold = (ith0/th0)*threshold;
+
+    if ((*i_chargedDiode).second.charge()>threshold) {
+      int bunchSim;
+      if ((*i_chargedDiode).second.totalCharge().fromTrack()) {
+        if (m_timingTune==2015) { bunchSim = m_TimeSvc->relativeBunch2015((*i_chargedDiode).second.totalCharge(),barrel_ec,layerIndex,moduleIndex); }
+        else                    { bunchSim = m_TimeSvc->relativeBunch2009(threshold,intimethreshold,(*i_chargedDiode).second.totalCharge(),1); }
+      } 
+      else {
+        bunchSim = CLHEP::RandFlat::shootInt(m_rndmEngine,m_TimeSvc->getTimeBCN());
+      }
+
+      if (bunchSim<0 || bunchSim>m_TimeSvc->getTimeBCN()) { SiHelper::belowThreshold((*i_chargedDiode).second,true,true); }
+      else                                                {  SiHelper::SetBunch((*i_chargedDiode).second,bunchSim); }
+    } 
+    else {
+      SiHelper::belowThreshold((*i_chargedDiode).second,true,true);
+    }
+
+    //===============
+    // Filter events
+    //===============
+    if (SiHelper::isMaskOut((*i_chargedDiode).second))  { continue; } 
+    if (SiHelper::isDisabled((*i_chargedDiode).second)) { continue; } 
+
+    if (!m_pixelConditionsSvc->isActive(moduleHash,diodeID)) {
+      SiHelper::disabled((*i_chargedDiode).second,true,true);
+      continue;
+    }
+
+    // charge to ToT conversion
+    double tot    = m_pixelCalibSvc->getTotMean(diodeID,(*i_chargedDiode).second.charge());
+    double totsig = m_pixelCalibSvc->getTotRes(diodeID,tot);
+    int nToT = static_cast<int>(CLHEP::RandGaussZiggurat::shoot(m_rndmEngine,tot,totsig));
+
+    if (nToT<1) { nToT=1; }
+
+    if (barrel_ec==0 && nToT<=m_BarrelToTthreshold.at(layerIndex)) { continue; }
+    if (barrel_ec!=0 && nToT<=m_EndcapToTthreshold.at(layerIndex)) { continue; }
+
+    if (barrel_ec==0 && nToT>=m_BarrelLatency.at(layerIndex)) { continue; }
+    if (barrel_ec!=0 && nToT>=m_EndcapLatency.at(layerIndex)) { continue; }
+
+    int flag  = (*i_chargedDiode).second.flag();
+    int bunch = (flag>>8)&0xff;
+
+    InDetDD::SiReadoutCellId cellId=(*i_chargedDiode).second.getReadoutCell();
+    const Identifier id_readout = chargedDiodes.element()->identifierFromCellId(cellId);
+
+    // Front-End simulation
+    if (bunch>=0 && bunch<m_TimeSvc->getTimeBCN()) {
+      Pixel1RawData *p_rdo = new Pixel1RawData(id_readout,nToT,bunch,0,bunch);
+      rdoCollection.push_back(p_rdo);
+    }
+
+    // Duplication mechanism for FEI3 small hits :
+    if (barrel_ec==0 && m_BarrelHitDuplication.at(layerIndex)) {
+      if (nToT<=m_BarrelSmallHitToT.at(layerIndex) && bunch>0 && bunch<=m_TimeSvc->getTimeBCN()) {
+        Pixel1RawData *p_rdo = new Pixel1RawData(id_readout,nToT,bunch-1,0,bunch-1);
+        rdoCollection.push_back(p_rdo);
+      }
+    }
+    if (barrel_ec!=0 && m_EndcapHitDuplication.at(layerIndex)) {
+      if (nToT<=m_EndcapSmallHitToT.at(layerIndex) && bunch>0 && bunch<=m_TimeSvc->getTimeBCN()) {
+        Pixel1RawData *p_rdo = new Pixel1RawData(id_readout,nToT,bunch-1,0,bunch-1);
+        rdoCollection.push_back(p_rdo);
+      }
+    }
+  }
+  return;
+}
+
+
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.h b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.h
new file mode 100644
index 00000000000..b7c9c41d811
--- /dev/null
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI3SimTool.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PIXELDIGITIZATION_FEI3SimTool_H
+#define PIXELDIGITIZATION_FEI3SimTool_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FrontEndSimTool.h"
+
+class FEI3SimTool:public FrontEndSimTool {
+
+  public:
+    FEI3SimTool( const std::string& type, const std::string& name,const IInterface* parent);
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+    virtual ~FEI3SimTool();
+    virtual void process(SiChargedDiodeCollection &chargedDiodes,PixelRDO_Collection &rdoCollection);
+
+  private:
+    FEI3SimTool();
+
+    std::vector<bool> m_BarrelHitDuplication;
+    std::vector<bool> m_EndcapHitDuplication;
+    std::vector<int>  m_BarrelSmallHitToT;
+    std::vector<int>  m_EndcapSmallHitToT;
+
+    int m_timingTune;
+
+};
+
+#endif // PIXELDIGITIZATION_FEI3SimTool_H
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.cxx
new file mode 100644
index 00000000000..2335f0ee3f6
--- /dev/null
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.cxx
@@ -0,0 +1,186 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FEI4SimTool.h"
+
+#include "InDetReadoutGeometry/PixelModuleDesign.h"
+
+#include "SiDigitization/SiHelper.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+
+FEI4SimTool::FEI4SimTool( const std::string& type, const std::string& name,const IInterface* parent):
+  FrontEndSimTool(type,name,parent),
+  m_HitDiscConfig(2),
+  m_timingTune(2015)
+{
+  declareProperty("HitDiscConfig", m_HitDiscConfig);
+	declareProperty("TimingTune",    m_timingTune, "Version of the timing calibration");	
+}
+
+FEI4SimTool::~FEI4SimTool() { }
+
+StatusCode FEI4SimTool::initialize() {
+  CHECK(FrontEndSimTool::initialize());
+  ATH_MSG_DEBUG("FEI4SimTool::initialize()");
+
+  if (m_HitDiscConfig<0 || m_HitDiscConfig>2) {
+    ATH_MSG_FATAL("HitDisConfig must be [0-2], but not " << m_HitDiscConfig);
+    return StatusCode::FAILURE;
+  }
+	return StatusCode::SUCCESS;
+}
+
+StatusCode FEI4SimTool::finalize() {
+  ATH_MSG_DEBUG("FEI4SimTool::finalize()");
+	return StatusCode::SUCCESS;
+}
+
+void FEI4SimTool::process(SiChargedDiodeCollection &chargedDiodes,PixelRDO_Collection &rdoCollection) {
+
+  const InDetDD::PixelModuleDesign *p_design = static_cast<const InDetDD::PixelModuleDesign*>(&(chargedDiodes.element())->design());
+  if (p_design->getReadoutTechnology()!=InDetDD::PixelModuleDesign::FEI4) { return; }
+
+  const PixelID* pixelId = static_cast<const PixelID *>(chargedDiodes.element()->getIdHelper());
+  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes.identify()); // wafer hash
+
+  int maxFEI4SmallHit = 2;
+  int overflowToT     = 16;
+  if (m_HitDiscConfig==0) { maxFEI4SmallHit=0; overflowToT=14; }
+  if (m_HitDiscConfig==1) { maxFEI4SmallHit=1; overflowToT=15; }
+  if (m_HitDiscConfig==2) { maxFEI4SmallHit=2; overflowToT=16; }
+
+  int barrel_ec   = pixelId->barrel_ec(chargedDiodes.element()->identify());
+  int layerIndex  = pixelId->layer_disk(chargedDiodes.element()->identify());
+  int moduleIndex = pixelId->eta_module(chargedDiodes.element()->identify());
+
+  std::vector<Pixel1RawData*> p_rdo_small_fei4;
+  int nSmallHitsFEI4 = 0;
+  std::vector<int> row, col;
+  const int maxRow = p_design->rowsPerCircuit();
+  const int maxCol = p_design->columnsPerCircuit();
+  std::vector<std::vector<int>> FEI4Map(maxRow+1,std::vector<int>(maxCol+1));
+
+  for (SiChargedDiodeIterator i_chargedDiode=chargedDiodes.begin(); i_chargedDiode!=chargedDiodes.end(); ++i_chargedDiode) {
+
+    Identifier diodeID = chargedDiodes.getId((*i_chargedDiode).first);
+
+    // Apply analogu threshold, timing simulation
+    double th0  = m_pixelCalibSvc->getThreshold(diodeID);
+    double ith0 = m_pixelCalibSvc->getTimeWalk(diodeID);
+
+    double threshold = th0+m_pixelCalibSvc->getThresholdSigma(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine)+m_pixelCalibSvc->getNoise(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine);
+    double intimethreshold = (ith0/th0)*threshold;
+
+    if ((*i_chargedDiode).second.charge()>threshold) {
+      int bunchSim;
+      if ((*i_chargedDiode).second.totalCharge().fromTrack()) {
+        if (m_timingTune==2015) { bunchSim = m_TimeSvc->relativeBunch2015((*i_chargedDiode).second.totalCharge(),barrel_ec,layerIndex,moduleIndex); }
+        else                    { bunchSim = m_TimeSvc->relativeBunch2009(threshold,intimethreshold,(*i_chargedDiode).second.totalCharge(),0); }
+      } 
+      else {
+        bunchSim = CLHEP::RandFlat::shootInt(m_rndmEngine,m_TimeSvc->getTimeBCN());
+      }
+
+      if (bunchSim<0 || bunchSim>m_TimeSvc->getTimeBCN()) { SiHelper::belowThreshold((*i_chargedDiode).second,true,true); }
+      else                                                {  SiHelper::SetBunch((*i_chargedDiode).second,bunchSim); }
+    } 
+    else {
+      SiHelper::belowThreshold((*i_chargedDiode).second,true,true);
+    }
+
+    //===============
+    // Filter events
+    //===============
+    if (SiHelper::isMaskOut((*i_chargedDiode).second))  { continue; } 
+    if (SiHelper::isDisabled((*i_chargedDiode).second)) { continue; } 
+
+    if (!m_pixelConditionsSvc->isActive(moduleHash,diodeID)) {
+      SiHelper::disabled((*i_chargedDiode).second,true,true);
+      continue;
+    }
+
+    // charge to ToT conversion
+    double tot    = m_pixelCalibSvc->getTotMean(diodeID,(*i_chargedDiode).second.charge());
+    double totsig = m_pixelCalibSvc->getTotRes(diodeID,tot);
+    int nToT = static_cast<int>(CLHEP::RandGaussZiggurat::shoot(m_rndmEngine,tot,totsig));
+
+    const PixelID* pixelId = static_cast<const PixelID*>(chargedDiodes.element()->getIdHelper());
+    if (pixelId->is_dbm(chargedDiodes.element()->identify())) {
+      nToT = 8*((*i_chargedDiode).second.charge() - 1200. )/(8000. - 1200.);
+    }
+
+    if (nToT<1) { nToT=1; }
+
+    // FEI4 HitDiscConfig
+    if (nToT==2 && maxFEI4SmallHit==2) { nToT=1; }
+    if (nToT>=overflowToT) { nToT=overflowToT; }
+
+    if (barrel_ec==0 && nToT<=m_BarrelToTthreshold.at(layerIndex)) { continue; }
+    if (barrel_ec!=0 && nToT<=m_EndcapToTthreshold.at(layerIndex)) { continue; }
+
+    int flag  = (*i_chargedDiode).second.flag();
+    int bunch = (flag>>8)&0xff;
+
+    InDetDD::SiReadoutCellId cellId=(*i_chargedDiode).second.getReadoutCell();
+    const Identifier id_readout = chargedDiodes.element()->identifierFromCellId(cellId);
+
+    int iirow = cellId.phiIndex();
+    int iicol = cellId.etaIndex();
+    if (iicol>=maxCol) { iicol=iicol-maxCol; } // FEI4 copy mechanism works per FE.
+
+    // Front-End simulation
+    if (bunch>=0 && bunch<m_TimeSvc->getTimeBCN()) {
+      Pixel1RawData *p_rdo = new Pixel1RawData(id_readout,nToT,bunch,0,bunch);
+      if (nToT>maxFEI4SmallHit) {
+        rdoCollection.push_back(p_rdo);
+        FEI4Map[iirow][iicol] = 2; //Flag for "big hits"
+      }
+      else {
+        p_rdo_small_fei4.push_back(p_rdo);
+        row.push_back(iirow);
+        col.push_back(iicol);
+        FEI4Map[iirow][iicol] = 1; //Flag for low hits
+        nSmallHitsFEI4++;
+      }
+    }
+  }
+
+  // Copy mechanism for IBL small hits:
+  if (nSmallHitsFEI4>0) {
+    bool recorded = false;
+
+    //First case: Record small hits which are in the same Pixel Digital Region than a big hit:
+    for (int ismall=0; ismall<nSmallHitsFEI4; ismall++) {
+      int rowPDR = row[ismall]/2;
+      int colPDR = col[ismall]/2;
+      for (int rowBigHit=2*rowPDR; rowBigHit!=2*rowPDR+2 && rowBigHit<maxRow; ++rowBigHit) {
+        for (int colBigHit=2*colPDR; colBigHit!=2*colPDR+2 && colBigHit<maxCol; ++colBigHit) {
+          ATH_MSG_DEBUG("rowBig = " << rowBigHit << " colBig = " << colBigHit << " Map Content = " << FEI4Map[rowBigHit][colBigHit]);
+          if (FEI4Map[rowBigHit][colBigHit]==2 && !recorded) {
+            rdoCollection.push_back(p_rdo_small_fei4[ismall]);
+            recorded = true;
+          }
+        }
+      }
+
+      // Second case: Record small hits which are phi-neighbours with a big hit:
+      if (!recorded && row[ismall]<maxRow-1) {
+        if (FEI4Map[row[ismall]+1][col[ismall]]==2) {
+          rdoCollection.push_back(p_rdo_small_fei4[ismall]);
+          recorded = true;
+        }
+      }
+      if (!recorded && row[ismall]!=0) {
+        if (FEI4Map[row[ismall]-1][col[ismall]]==2) {
+          rdoCollection.push_back(p_rdo_small_fei4[ismall]);
+          recorded = true;
+        }
+      }
+    }
+  }
+
+  return;
+}
+
+
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.h b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.h
new file mode 100644
index 00000000000..c38774a8789
--- /dev/null
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/FEI4SimTool.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PIXELDIGITIZATION_FEI4SimTool_H
+#define PIXELDIGITIZATION_FEI4SimTool_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FrontEndSimTool.h"
+
+class FEI4SimTool:public FrontEndSimTool {
+
+  public:
+    FEI4SimTool( const std::string& type, const std::string& name,const IInterface* parent);
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+    virtual ~FEI4SimTool();
+    virtual void process(SiChargedDiodeCollection &chargedDiodes,PixelRDO_Collection &rdoCollection);
+
+  private:
+    FEI4SimTool();
+
+    int m_HitDiscConfig;
+    int m_timingTune;
+};
+
+#endif // PIXELDIGITIZATION_FEI4SimTool_H
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/FrontEndSimTool.h b/InnerDetector/InDetDigitization/PixelDigitization/src/FrontEndSimTool.h
new file mode 100644
index 00000000000..90a68cf6665
--- /dev/null
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/FrontEndSimTool.h
@@ -0,0 +1,100 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PIXELDIGITIZATION_FrontEndSimTool_H
+#define PIXELDIGITIZATION_FrontEndSimTool_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "CLHEP/Random/RandomEngine.h"
+#include "AtlasCLHEP_RandomGenerators/RandGaussZiggurat.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+
+#include "SiDigitization/SiChargedDiodeCollection.h"
+#include "InDetRawData/InDetRawDataCLASS_DEF.h"
+
+#include "InDetConditionsSummaryService/IInDetConditionsSvc.h"
+#include "PixelConditionsServices/IPixelCalibSvc.h"
+#include "TimeSvc.h"
+
+static const InterfaceID IID_IFrontEndSimTool("FrontEndSimTool", 1, 0);
+
+class FrontEndSimTool:public AthAlgTool,virtual public IAlgTool {
+
+  public:
+    FrontEndSimTool( const std::string& type, const std::string& name,const IInterface* parent):
+      AthAlgTool(type,name,parent),
+      m_rndmSvc("AtRndmGenSvc",name),
+      m_rndmEngineName("PixelDigitization"),
+      m_rndmEngine(nullptr),
+      m_pixelConditionsSvc("PixelConditionsSummarySvc",name),
+      m_pixelCalibSvc("PixelCalibSvc",name),
+      m_TimeSvc("TimeSvc",name),
+      m_BarrelToTthreshold({-1,-1,-1,-1,-1,-1,-1}),
+      m_EndcapToTthreshold({-1,-1,-1,-1,-1,-1,-1}),
+      m_BarrelLatency({256,256,256,256,256,256,256}),
+      m_EndcapLatency({256,256,256,256,256,256,256})
+  {
+    declareInterface<FrontEndSimTool>(this);
+    declareProperty("RndmSvc",                   m_rndmSvc,        "Random number service used in FE simulation");
+    declareProperty("RndmEngine",                m_rndmEngineName, "Random engine name");
+    declareProperty("PixelConditionsSummarySvc", m_pixelConditionsSvc);
+    declareProperty("PixelCalibSvc",             m_pixelCalibSvc);
+    declareProperty("TimeSvc",                   m_TimeSvc);
+    declareProperty("BarrelToTthreshold",        m_BarrelToTthreshold);
+    declareProperty("EndcapToTthreshold",        m_EndcapToTthreshold);
+    declareProperty("BarrelLatency",             m_BarrelLatency);
+    declareProperty("EndcapLatency",             m_EndcapLatency);
+  }
+
+    static const InterfaceID& interfaceID() { return IID_IFrontEndSimTool; }
+
+    virtual StatusCode initialize() {
+      CHECK(AthAlgTool::initialize()); 
+
+      CHECK(m_rndmSvc.retrieve());
+
+      CHECK(m_pixelConditionsSvc.retrieve());
+
+      CHECK(m_pixelCalibSvc.retrieve());
+
+      CHECK(m_TimeSvc.retrieve());
+
+      m_rndmEngine = m_rndmSvc->GetEngine(m_rndmEngineName);
+      if (!m_rndmEngine) {
+        ATH_MSG_ERROR("Could not find RndmEngine : " << m_rndmEngineName);
+        return StatusCode::FAILURE;
+      }
+      else {
+        ATH_MSG_DEBUG("Found RndmEngine : " << m_rndmEngineName);
+      }
+
+      return StatusCode::SUCCESS;
+    }
+
+    virtual StatusCode finalize() { return StatusCode::FAILURE; }
+    virtual ~FrontEndSimTool() {}
+    virtual void process(SiChargedDiodeCollection &chargedDiodes,PixelRDO_Collection &rdoCollection) = 0;
+
+  private:
+    FrontEndSimTool();
+
+  protected:
+    ServiceHandle<IAtRndmGenSvc> m_rndmSvc;
+    std::string                  m_rndmEngineName;
+    CLHEP::HepRandomEngine      *m_rndmEngine;	
+
+    ServiceHandle<IInDetConditionsSvc>   m_pixelConditionsSvc;
+    ServiceHandle<IPixelCalibSvc>        m_pixelCalibSvc;
+    ServiceHandle<TimeSvc>               m_TimeSvc;
+
+    std::vector<int> m_BarrelToTthreshold;
+    std::vector<int> m_EndcapToTthreshold;
+    std::vector<int> m_BarrelLatency;
+    std::vector<int> m_EndcapLatency;
+
+};
+
+#endif // PIXELDIGITIZATION_FrontEndSimTool_H
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.cxx
deleted file mode 100644
index 6b6fef7182b..00000000000
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.cxx
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-/////////////////////////////////////////////////////////////////// 
-// PixelCellDiscriminator.cxx 
-//   Implementation file for class PixelCellDiscriminator 
-/////////////////////////////////////////////////////////////////// 
-// (c) ATLAS Detector software 
-/////////////////////////////////////////////////////////////////// 
-
-#include "PixelCellDiscriminator.h"
-#include "SiDigitization/SiChargedDiodeCollection.h"
-#include "SiDigitization/SiHelper.h"
-#include "InDetReadoutGeometry/PixelModuleDesign.h"
-#include "PixelConditionsServices/IPixelCalibSvc.h"
-#include "TimeSvc.h"
-// random number service
-#include "CLHEP/Random/RandomEngine.h"
-#include "AtlasCLHEP_RandomGenerators/RandGaussZiggurat.h"
-#include "CLHEP/Random/RandFlat.h"
-////#include "InDetIdentifier/PixelID.h"
-#include "AthenaKernel/IAtRndmGenSvc.h"
-
-using namespace InDetDD;
-
-static const InterfaceID IID_IPixelCellDiscriminator("PixelCellDiscriminator", 1, 0);
-const InterfaceID& PixelCellDiscriminator::interfaceID( ){ return IID_IPixelCellDiscriminator; }
-
-// Constructor with parameters:
-PixelCellDiscriminator::PixelCellDiscriminator(const std::string& type, const std::string& name,const IInterface* parent):
-  AthAlgTool(type,name,parent),
-  m_TimeSvc("TimeSvc",name),
-  m_pixelCalibSvc("PixelCalibSvc", name),
-  m_rndmSvc("AtDSFMTGenSvc",name),
-  m_rndmEngineName("PixelDigitization"),
-  m_rndmEngine(0),
-  m_timingTune(2015)
-{  
-	declareInterface< PixelCellDiscriminator >( this );
-	declareProperty("RndmSvc",m_rndmSvc,"Random Number Service used in Pixel digitization");
-	declareProperty("RndmEngine",m_rndmEngineName,"Random engine name");
-	declareProperty("TimeSvc",m_TimeSvc);
-	declareProperty("TimingTune",m_timingTune,"Version of the timing tune");	
-}
-
-// Destructor:
-PixelCellDiscriminator::~PixelCellDiscriminator()
-{}
-
-//----------------------------------------------------------------------
-// Initialize
-//----------------------------------------------------------------------
-StatusCode PixelCellDiscriminator::initialize() {
-
-  CHECK(m_TimeSvc.retrieve());
-
-  CHECK(m_pixelCalibSvc.retrieve());
-
-  CHECK(m_rndmSvc.retrieve());
-  m_rndmEngine = m_rndmSvc->GetEngine(m_rndmEngineName);
-  if (!m_rndmEngine) {
-    ATH_MSG_ERROR("Could not find RndmEngine : " << m_rndmEngineName);
-    return StatusCode::FAILURE;
-  } 
-  else { 
-    ATH_MSG_DEBUG("Found RndmEngine : " << m_rndmEngineName);  
-  }
-
-  ATH_MSG_DEBUG ( "PixelCellDiscriminator::initialize()");
-  return StatusCode::SUCCESS;
-}
-
-//----------------------------------------------------------------------
-// finalize
-//----------------------------------------------------------------------
-StatusCode PixelCellDiscriminator::finalize() {
-  return StatusCode::SUCCESS;
-}
-
-// process the collection of charged diodes
-void PixelCellDiscriminator::process(SiChargedDiodeCollection &collection) const
-{   
-  bool ComputeTW = false;
-  const PixelModuleDesign *p_design = static_cast<const PixelModuleDesign*>(&(collection.element()->design()));
-  if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI3) {
-    ComputeTW = true;
-  }
-
-  const PixelID* pixelId = static_cast<const PixelID *>((collection.element())->getIdHelper());
-
-  for(SiChargedDiodeIterator i_chargedDiode=collection.begin() ;
-      i_chargedDiode!=collection.end() ; ++i_chargedDiode) {
-
-    int BCN = m_TimeSvc->getTimeBCN();
-
-    Identifier diodeID = collection.getId((*i_chargedDiode).first);
-
-    //
-    // calculate the threshold:
-    //    th0      : mean value
-    //    th0 sigma: variation of whatever sample the mean was obtained
-    //    noise    : actually a noise level that logically should be added to
-    //               the charge <- TODO!
-    //
-    double th0  = m_pixelCalibSvc->getThreshold(diodeID);
-    double ith0 = m_pixelCalibSvc->getTimeWalk(diodeID);
-    // Flers: here I rely on CalibSvc providing correct values for th0, ith0
-    // if that's not true, need to figure out if we are in dbm and set
-    // th0, ith0, e.g.
-    //                      if (dbm) { th0=1200.; ith0=1500.; }
-    double threshold = th0 +
-      m_pixelCalibSvc->getThresholdSigma(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine) +
-      m_pixelCalibSvc->getNoise(diodeID)*CLHEP::RandGaussZiggurat::shoot(m_rndmEngine);
-     
-    double intimethreshold  =  (ith0/th0)*threshold;
-    // double overdrive        =  intimethreshold - threshold ;
-    // compute overcharge for this diode
-    double overcharge=(*i_chargedDiode).second.charge()-threshold;
-    // if the discriminator fires
-    if (overcharge>0) {
-      // compute the relative bunch number 
-      // if hit comes from track or Xtalk calculates Bunch Crossing with TimeWalk (timing algoritm)
-      // else (i.e. is a noise hit or ...) assigns a random BC
-      int bunch;
-      if( (*i_chargedDiode).second.totalCharge().fromTrack()){
-        if (m_timingTune==2015) {
-          // Timing tune from 2015 collision data.
-          int bec      = pixelId->barrel_ec(collection.element()->identify());
-          int layerID  = pixelId->layer_disk(collection.element()->identify());
-          int moduleID = pixelId->eta_module(collection.element()->identify());
-          bunch = m_TimeSvc->relativeBunch2015((*i_chargedDiode).second.totalCharge(),bec,layerID,moduleID);
-        }
-        else {
-          // Old tune from 2010 cosmic data.
-          bunch=m_TimeSvc->relativeBunch(threshold, intimethreshold, (*i_chargedDiode).second.totalCharge(), ComputeTW);
-        }
-      } else {
-        bunch=CLHEP::RandFlat::shootInt(m_rndmEngine,BCN);
-      }
-      if (bunch<0 || bunch>BCN) { //If bunch is out of range, set below threshold (keep hits with +1 BC, for hit duplication). 
-        SiHelper::belowThreshold((*i_chargedDiode).second,true,true);
-      } else {  
-        SiHelper::SetBunch((*i_chargedDiode).second,bunch);
-      }
-      //ATH_MSG_DEBUG ( (*i_chargedDiode).second.totalCharge().fromTrack() <<" Charge = " << (*i_chargedDiode).second.charge()
-      //<< " , bunch = " << bunch << " , BCN = " << BCN);
-    } else {
-      //Set the Below threshold flag if charge < threshold
-      SiHelper::belowThreshold((*i_chargedDiode).second,true,true);
-    }
-  }
-}
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.h b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.h
deleted file mode 100644
index b2a79990948..00000000000
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelCellDiscriminator.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-/////////////////////////////////////////////////////////////////// 
-// PixelCellDiscriminator.cxx 
-//   Implementation file for class PixelCellDiscriminator 
-/////////////////////////////////////////////////////////////////// 
-// (c) ATLAS Detector software 
-/////////////////////////////////////////////////////////////////// 
-//
-// Configurable Parameters:
-// -RndmSvc		Random Number Service used in Pixel digitization
-// -RndmEngine		Random engine name
-//
-//////////////////////////////////////////////////////////////////
-
-
-/** @class PixelCellDiscriminator
- * @brief simulates the discriminator, including the timing
- * @author Francesco De Lorenzi
- *
- * \b Description
- *
- * The flow of the algorithm is (for each charged pixel):
- * -# simulate the threshold using a gaussian
- * -# smear the obtained threshold with a gaussian with mean=0
- * -# calculate the intime threshold
- * -# discriminate : check if charge is larger than obtained threshold
- * -# if charge \e ABOVE threshold
- *    - if main charge from track: calculate timing (bunch) using the bunch calculator
- *    - else : set the bunch to a random number [0..TimeBCN-1] - hit is just noise
- *    - if timing is outside allowed range ([0,TimeBCN-1] then pixel is set to 'below threshold'
- * -# if charge \e BELOW threshold
- *    - flag pixel as 'below threshold'
- *
- */
-#ifndef PIXELDIGITIZATION_PIXELCELLDISCRIMINATOR_H
-#define PIXELDIGITIZATION_PIXELCELLDISCRIMINATOR_H
-
-// Base class
-#include "SiDigitization/ISiChargedDiodesProcessorTool.h"
-#include "AthenaBaseComps/AthAlgTool.h"
-
-namespace CLHEP {
-  class HepRandomEngine;
-}
-class TimeSvc;
-class IPixelCalibSvc;
-
-class IAtRndmGenSvc;
-class PixelCellDiscriminator : public AthAlgTool, virtual public ISiChargedDiodesProcessorTool {
-
-public:
-
-  //Constructor:
-  PixelCellDiscriminator( const std::string& type, const std::string& name,const IInterface* parent);
-			 
-
-  /** Destructor */
-  virtual ~PixelCellDiscriminator();
-
-  /** AlgTool InterfaceID */
-  static const InterfaceID& interfaceID() ;
-
-
-  /** AlgTool initialize */
-  virtual StatusCode initialize();
-
-  /** AlgTool finalize */
-  virtual StatusCode finalize();
-
-  /** process the collection of charged pixels */
-  virtual void process(SiChargedDiodeCollection &collection) const;
-
-private:   
-
-  /** empty constructor made private */
-  PixelCellDiscriminator();
-  
-  ServiceHandle<TimeSvc> m_TimeSvc;
-  ServiceHandle<IPixelCalibSvc> m_pixelCalibSvc;
-  ServiceHandle<IAtRndmGenSvc> m_rndmSvc;
-  std::string m_rndmEngineName;
-  CLHEP::HepRandomEngine* m_rndmEngine;
-  int m_timingTune;
-};
-
-#endif
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.cxx
index 7c05c096493..87d5c2d72a4 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.cxx
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.cxx
@@ -11,58 +11,33 @@
 
 // Pixel digitization includes
 #include "PixelDigitizationTool.h"
-#include "PixelDiodeCrossTalkGenerator.h"
-#include "PixelCellDiscriminator.h"
-#include "PixelNoisyCellGenerator.h"
-#include "PixelChargeSmearer.h"
-#include "PixelGangedMerger.h"
-#include "TimeSvc.h"
-#include "PixelRandomDisabledCellGenerator.h"
+
 #include "PileUpTools/PileUpMergeSvc.h"
 #include "AthenaKernel/IAtRndmGenSvc.h"
-#include "InDetSimEvent/SiHitCollection.h"
 
-// Mother Package includes
-#include "SiDigitization/SiHelper.h"
 #include "SiDigitization/SiChargedDiodeCollection.h"
-#include "SiDigitization/ISiChargedDiodesProcessorTool.h"
-
-#include "SubChargesTool.h"
-
-// Det Descr
 #include "Identifier/Identifier.h"
-#include "InDetReadoutGeometry/PixelDetectorManager.h"
-#include "InDetReadoutGeometry/SiReadoutCellId.h"
-#include "InDetReadoutGeometry/SiDetectorDesign.h"
-#include "InDetReadoutGeometry/SiCellId.h"
 #include "InDetIdentifier/PixelID.h"
-#include "InDetSimData/InDetSimDataCollection.h"
 
-// Random numbers
-#include "AtlasCLHEP_RandomGenerators/RandGaussZiggurat.h"
-#include "CLHEP/Random/RandFlat.h"
+// STSTST #include "AtlasCLHEP_RandomGenerators/RandGaussZiggurat.h"
+// STSTST #include "CLHEP/Random/RandFlat.h"
 
-// Gaudi includes
 #include "AthenaKernel/errorcheck.h"
-
-// DataHandle
 #include "StoreGate/DataHandle.h"
 #include "CxxUtils/make_unique.h"
 
-//
 #include <limits>
 #include <cstdint>
 static constexpr unsigned int crazyParticleBarcode(std::numeric_limits<int32_t>::max());
 //Barcodes at the HepMC level are int
 
-using namespace InDetDD;
+// STSTST using namespace InDetDD;
 
 // Constructor with parameters:
 PixelDigitizationTool::PixelDigitizationTool(const std::string &type,
                                              const std::string &name,
                                              const IInterface * pIID) :
   PileUpToolBase(type,name,pIID),
-  m_offlineCalibSvc("PixelOfflineCalibSvc", name),
   m_rdoContainer("PixelRDOs"),
   m_simDataColl("PixelSDO_Map"),
   m_HardScatterSplittingMode(0),
@@ -71,48 +46,32 @@ PixelDigitizationTool::PixelDigitizationTool(const std::string &type,
   m_onlyHitElements(false),
   m_diodesProcsTool(),
   m_chargeTool(),
-  m_pixelCalibSvc("PixelCalibSvc",name),
+  m_fesimTool(),
   m_detID(nullptr),
   m_vetoThisBarcode(crazyParticleBarcode),
   m_timedHits(nullptr),
   m_rndmSvc("AtRndmGenSvc",name),
   m_mergeSvc("PileUpMergeSvc",name),
-  m_TimeSvc("TimeSvc",name),
-  m_pixelConditionsSvc("PixelConditionsSummarySvc",name),
   m_rndmEngine(nullptr),
   m_detManager(nullptr),
   m_inputObjectName(""),
   m_createNoiseSDO(false)
 {
-  declareProperty("PixelTools",               m_diodesProcsTool,   "List of processor tools");
-  declareProperty("ChargeTools",              m_chargeTool,        "List of charge tools");
-  declareProperty("RndmSvc",                  m_rndmSvc,                   "Random number service used in Pixel Digitization");
-  declareProperty("MergeSvc",                 m_mergeSvc,                  "Merge service used in Pixel digitization");
-  declareProperty("TimeSvc",                  m_TimeSvc,                   "Time Svc");
-  declareProperty("PixelCalibSvc",            m_pixelCalibSvc);
-  declareProperty("PixelConditionsSummarySvc",m_pixelConditionsSvc);
-  declareProperty("OfflineCalibSvc",         m_offlineCalibSvc);
-  declareProperty("InputObjectName",         m_inputObjectName,        "Input Object name" );
-  declareProperty("CreateNoiseSDO",          m_createNoiseSDO,      "Set create noise SDO flag");
-
-  declareProperty("RDOCollName",        m_rdoContainer,          "RDO collection name");
-  declareProperty("SDOCollName",        m_simDataColl,           "SDO collection name");
-
-  declareProperty("LVL1Latency",        m_maxToT,               "LVL1 latency (max possible ToT)");
-  declareProperty("ToTMinCut",          m_minToT,               "Minimum ToT cut (online cut)");
-  declareProperty("ApplyDupli",         m_applyDupli,           "Duplicate low ToT hits");
-  declareProperty("LowTOTduplication",  m_maxToTForDupli,       "ToT value below which the hit is duplicated");
-
-  // random number stream name
-  declareProperty("RndmEngine",         m_rndmEngineName,       "Random engine name");
-
-  declareProperty("OnlyHitElements",    m_onlyHitElements,      "Process only elements with hits");
+  declareProperty("PixelTools",       m_diodesProcsTool, "List of processor tools");
+  declareProperty("ChargeTools",      m_chargeTool,      "List of charge tools");
+  declareProperty("FrontEndSimTools", m_fesimTool,       "List of Front-End simulation tools");
+  declareProperty("RndmSvc",          m_rndmSvc,         "Random number service used in Pixel Digitization");
+  declareProperty("MergeSvc",         m_mergeSvc,        "Merge service used in Pixel digitization");
+  declareProperty("InputObjectName",  m_inputObjectName, "Input Object name" );
+  declareProperty("CreateNoiseSDO",   m_createNoiseSDO,  "Set create noise SDO flag");
+  declareProperty("RDOCollName",      m_rdoContainer,    "RDO collection name");
+  declareProperty("SDOCollName",      m_simDataColl,     "SDO collection name");
+  declareProperty("RndmEngine",       m_rndmEngineName,  "Random engine name");
+  declareProperty("OnlyHitElements",  m_onlyHitElements, "Process only elements with hits");
   declareProperty("HardScatterSplittingMode", m_HardScatterSplittingMode, "Control pileup & signal splitting" );
   declareProperty("ParticleBarcodeVeto",m_vetoThisBarcode=crazyParticleBarcode, "Barcode of particle to ignore");
 }
 
-
-// Initialize method:
 StatusCode PixelDigitizationTool::initialize() {
   ATH_MSG_DEBUG("PixelDigitizationTool::Initialize()");
 
@@ -128,17 +87,6 @@ StatusCode PixelDigitizationTool::initialize() {
   // Initialize services
   CHECK(m_mergeSvc.retrieve());
 
-  CHECK(m_TimeSvc.retrieve());
-
-  CHECK(m_pixelCalibSvc.retrieve());
-
-  CHECK(m_pixelConditionsSvc.retrieve());
-
-  if (!m_offlineCalibSvc.empty()) {
-    CHECK(m_offlineCalibSvc.retrieve());
-    ATH_MSG_INFO("Retrieved tool " <<  m_offlineCalibSvc.type());
-  }
-
   // Initialize random number generator
   CHECK(m_rndmSvc.retrieve());
   m_rndmEngine = m_rndmSvc->GetEngine(m_rndmEngineName);
@@ -161,10 +109,15 @@ StatusCode PixelDigitizationTool::initialize() {
 
   CHECK(m_chargeTool.retrieve());
 
+  CHECK(m_fesimTool.retrieve());
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode PixelDigitizationTool::finalize() {
   return StatusCode::SUCCESS;
 }
 
-// Digitize method:
 StatusCode PixelDigitizationTool::processAllSubEvents() {
 
   //===============
@@ -174,22 +127,6 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
   ATH_MSG_DEBUG("Prepare event");
   CHECK(prepareEvent(0));
 
-  if (!m_rdoContainer.isValid()) {
-    if (!(m_rdoContainer=CxxUtils::make_unique<PixelRDO_Container>(m_detID->wafer_hash_max())).isValid()) {
-      ATH_MSG_FATAL("Could not create PixelRDO_Container");
-      return StatusCode::FAILURE;
-    }
-  }
-  ATH_MSG_DEBUG("PixelRDO_Container " << m_rdoContainer.name() << " registered in StoreGate");
-
-  if (!m_simDataColl.isValid()) {
-    if (!(m_simDataColl = CxxUtils::make_unique<InDetSimDataCollection>()).isValid()) {
-      ATH_MSG_FATAL("Could not create InDetSimDataCollection");
-      return StatusCode::FAILURE;
-    }
-  }
-  ATH_MSG_DEBUG("InDetSimDataCollection " << m_simDataColl.name() << " registered in StoreGate");
-
   // Get the container(s)
   typedef PileUpMergeSvc::TimedList<SiHitCollection>::type TimedHitCollList;
   TimedHitCollList hitCollList;
@@ -198,15 +135,6 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
 
   // Create hit collection
   m_timedHits     = new TimedHitCollection<SiHit>(numberOfSiHits);
-  auto chargedDiodes = std::make_unique<SiChargedDiodeCollection>();
-
-  std::vector<bool> processedElements; /**< vector of processed elements - set by digitizeHits() */
-  processedElements.resize(m_detID->wafer_hash_max(),false);
-
-  //================
-  // Generate event
-  //================
-  ATH_MSG_VERBOSE("Digitize hits");
 
   // Now merge all collections into one
   for (TimedHitCollList::iterator iColl=hitCollList.begin(); iColl!=hitCollList.end(); iColl++) {
@@ -216,11 +144,27 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
     if (m_HardScatterSplittingMode==1 && !m_HardScatterSplittingSkipper) { m_HardScatterSplittingSkipper=true; }
     const SiHitCollection* p_collection(iColl->second);
     m_timedHits->insert(iColl->first, p_collection);
-    ATH_MSG_DEBUG ( "SiTrackerHitCollection found with"<<p_collection->size()<<" hits");    // loop on the hit collections
+    ATH_MSG_DEBUG("SiTrackerHitCollection found with"<<p_collection->size()<<" hits");    // loop on the hit collections
   }
 
+  //===============
+  // Digitize hits
+  //===============
+  CHECK(digitizeEvent());
+
+  ATH_MSG_DEBUG("Digitize success!");
+  return StatusCode::SUCCESS;
+}
+
+StatusCode PixelDigitizationTool::digitizeEvent() {
+  ATH_MSG_VERBOSE("PixelDigitizationTool::digitizeEvent()");
+
+  SiChargedDiodeCollection  *chargedDiodes = new SiChargedDiodeCollection;
+
+  std::vector<bool> processedElements;
+  processedElements.resize(m_detID->wafer_hash_max(),false);
+
   // Loop over the Detectors with hits
-  ATH_MSG_DEBUG("Digitizing hits");
   TimedHitCollection<SiHit>::const_iterator firstHit, lastHit;
   while (m_timedHits->nextDetectorElement(firstHit,lastHit)) {
 
@@ -230,13 +174,10 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
     Identifier id = PID->wafer_id((*firstHit)->getBarrelEndcap(),(*firstHit)->getLayerDisk(),(*firstHit)->getPhiModule(),(*firstHit)->getEtaModule());
 
     // Get the det element from the manager
-    SiDetectorElement* sielement = m_detManager->getDetectorElement(id);
+    InDetDD::SiDetectorElement* sielement = m_detManager->getDetectorElement(id);
 
     if (sielement==0) {
-      ATH_MSG_DEBUG(" Barrel=" << (*firstHit)->getBarrelEndcap() << 
-                    " Layer="  << (*firstHit)->getLayerDisk() << 
-                    " Eta="    << (*firstHit)->getEtaModule() << 
-                    " Phi="    << (*firstHit)->getPhiModule());
+      ATH_MSG_DEBUG(" Barrel=" << (*firstHit)->getBarrelEndcap() << " Layer="  << (*firstHit)->getLayerDisk() << " Eta="    << (*firstHit)->getEtaModule() << " Phi="    << (*firstHit)->getPhiModule());
       ATH_MSG_ERROR("detector manager could not find element with id = " << id);
       break;
     }
@@ -249,9 +190,9 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
       //skip hits which are more than 10us away
       if (fabs((*phit)->meanTime())<10000.0*CLHEP::ns) {
         ATH_MSG_DEBUG("HASH = " << m_detID->wafer_hash(m_detID->wafer_id((*phit)->getBarrelEndcap(),(*phit)->getLayerDisk(),(*phit)->getPhiModule(),(*phit)->getEtaModule())));
-        ATH_MSG_DEBUG("calling process() for all methods");
 
         // Apply charge collection tools
+        ATH_MSG_DEBUG("calling process() for all methods");
         for (unsigned int itool=0; itool<m_chargeTool.size(); itool++) {
           ATH_MSG_DEBUG("Executing tool " << m_chargeTool[itool]->name());
           if (m_chargeTool[itool]->charge(*phit,*chargedDiodes,*sielement)==StatusCode::FAILURE) { break; }
@@ -268,11 +209,7 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
     }
 
     ATH_MSG_DEBUG("Hit collection ID=" << m_detID->show_to_string(chargedDiodes->identify()));
-    ATH_MSG_DEBUG("in digitize elements with hits: ec - layer - eta - phi  "
-                  << m_detID->barrel_ec(chargedDiodes->identify()) << " - "
-                  << m_detID->layer_disk(chargedDiodes->identify()) << " - "
-                  << m_detID->eta_module(chargedDiodes->identify()) << " - "
-                  << m_detID->phi_module(chargedDiodes->identify()));
+    ATH_MSG_DEBUG("in digitize elements with hits: ec - layer - eta - phi  " << m_detID->barrel_ec(chargedDiodes->identify()) << " - " << m_detID->layer_disk(chargedDiodes->identify()) << " - " << m_detID->eta_module(chargedDiodes->identify()) << " - " << m_detID->phi_module(chargedDiodes->identify()));
 
     IdentifierHash idHash = chargedDiodes->identifyHash();
 
@@ -281,11 +218,17 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
 
     // Create and store RDO and SDO
     if (!chargedDiodes->empty()) {
-      PixelRDO_Collection *RDOColl=this->createRDO(chargedDiodes.get());
-  
+
+      PixelRDO_Collection *RDOColl = new PixelRDO_Collection(chargedDiodes->identifyHash());
+      RDOColl->setIdentifier(chargedDiodes->identify());
+      for (unsigned int itool=0; itool<m_fesimTool.size(); itool++) {
+        ATH_MSG_DEBUG("Executing tool " << m_fesimTool[itool]->name());
+        m_fesimTool[itool]->process(*chargedDiodes,*RDOColl);
+      }
       CHECK(m_rdoContainer->addCollection(RDOColl,RDOColl->identifyHash()));
+ 
       ATH_MSG_DEBUG("Pixel RDOs '" << RDOColl->identifyHash() << "' added to container");
-      addSDO(chargedDiodes.get());
+      addSDO(chargedDiodes);
     }
     chargedDiodes->clear();
   }
@@ -301,13 +244,9 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
         IdentifierHash idHash = i;
         if (!idHash.is_valid()) { ATH_MSG_ERROR("PixelDetector element id hash is invalid = " << i); }
 
-        const SiDetectorElement *element = m_detManager->getDetectorElement(idHash);
+        const InDetDD::SiDetectorElement *element = m_detManager->getDetectorElement(idHash);
         if (element) {
-          ATH_MSG_DEBUG ("In digitize of untouched elements: layer - phi - eta  "
-              << m_detID->layer_disk(element->identify()) << " - "
-              << m_detID->phi_module(element->identify()) << " - "
-              << m_detID->eta_module(element->identify()) << " - "
-              << "size: " << processedElements.size());
+          ATH_MSG_DEBUG ("In digitize of untouched elements: layer - phi - eta  " << m_detID->layer_disk(element->identify()) << " - " << m_detID->phi_module(element->identify()) << " - " << m_detID->eta_module(element->identify()) << " - " << "size: " << processedElements.size());
 
           chargedDiodes->setDetectorElement(element);
           ATH_MSG_DEBUG("Digitize non hit element");
@@ -321,11 +260,16 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
 
           // Create and store RDO and SDO
           if (!chargedDiodes->empty()) {
-            PixelRDO_Collection *RDOColl=this->createRDO(chargedDiodes.get());
-
+            PixelRDO_Collection *RDOColl = new PixelRDO_Collection(chargedDiodes->identifyHash());
+            RDOColl->setIdentifier(chargedDiodes->identify());
+            for (unsigned int itool=0; itool<m_fesimTool.size(); itool++) {
+              ATH_MSG_DEBUG("Executing tool " << m_fesimTool[itool]->name());
+              m_fesimTool[itool]->process(*chargedDiodes,*RDOColl);
+            }
             CHECK(m_rdoContainer->addCollection(RDOColl,RDOColl->identifyHash()));
+
             ATH_MSG_DEBUG("Pixel RDOs '" << RDOColl->identifyHash() << "' added to container");
-            addSDO(chargedDiodes.get());
+            addSDO(chargedDiodes);
           }
           chargedDiodes->clear();
         }
@@ -334,11 +278,6 @@ StatusCode PixelDigitizationTool::processAllSubEvents() {
   }
   ATH_MSG_DEBUG("non-hits processed");
 
-  ATH_MSG_DEBUG("Digitize success!");
-  return StatusCode::SUCCESS;
-}
-
-StatusCode PixelDigitizationTool::finalize() {
   return StatusCode::SUCCESS;
 }
 
@@ -391,237 +330,12 @@ void PixelDigitizationTool::addSDO(SiChargedDiodeCollection* collection) {
   }
 }
 
-PixelRDO_Collection *PixelDigitizationTool::createRDO(SiChargedDiodeCollection *chargedDiodes) {
-
-  // Create the collection
-  Identifier collID = chargedDiodes->identify();
-  ATH_MSG_DEBUG("PixelDigitizationTool::createRDO() collection : " << m_detID->show_to_string(collID));
-  IdentifierHash idhash = chargedDiodes->identifyHash();
-  PixelRDO_Collection* PixelRDOColl = new PixelRDO_Collection(idhash);
-  PixelRDOColl->setIdentifier(collID );
-
-  // Determine the Pixel Region (IBL, BL, L1, L2, EC, DBM, ITk 5th layer), to be used for latency, ToT cut and duplication:
-  const PixelID* pixelId = static_cast<const PixelID *>(chargedDiodes->element()->getIdHelper());
-
-  const IdentifierHash moduleHash = pixelId->wafer_hash(chargedDiodes->identify()); // wafer hash
-
-//  int barrel_ec  = pixelId->barrel_ec(moduleHash);
-//  int layerIndex = pixelId->layer_disk(moduleHash);
-  int barrel_ec  = pixelId->barrel_ec(chargedDiodes->element()->identify());
-  int layerIndex = pixelId->layer_disk(chargedDiodes->element()->identify());
-  if (layerIndex>=4)     { layerIndex=6; }  // ITk 5th layer
-  if (abs(barrel_ec)==2) { layerIndex=4; }  // disks
-  if (abs(barrel_ec)==4) { layerIndex=5; }  // DBM
-
-  const PixelModuleDesign *p_design = static_cast<const PixelModuleDesign*>(&(chargedDiodes->element())->design());
-  std::vector<Pixel1RawData*> p_rdo_small_fei4;
-  int maxFEI4SmallHit = 2;
-  int nSmallHitsFEI4 = 0;
-  std::vector<int> row;
-  std::vector<int> col;
-  const int maxRow = p_design->rowsPerCircuit();
-  const int maxCol = p_design->columnsPerCircuit();
-  std::vector < std::vector < int > > FEI4Map ( maxRow+1, std::vector < int > ( maxCol+1) );
-  ATH_MSG_DEBUG ( "layerIndex = " << layerIndex << " MaxRow = " << maxRow << " MaxCol = " << maxCol);
-
-  int overflowIBLToT = 14;
-  if (!m_offlineCalibSvc.empty()) {
-    overflowIBLToT = m_offlineCalibSvc->getIBLToToverflow();
-    if (overflowIBLToT==14) { maxFEI4SmallHit=0; }
-    if (overflowIBLToT==15) { maxFEI4SmallHit=1; }
-    if (overflowIBLToT==16) { maxFEI4SmallHit=2; }
-  }
-
-  // ToT scale, to be used for FEI4, which has at most 4 bits for ToT,
-  // so physical ToT values are from 1 to 15
-  //
-  // Loop over the charged diodes.
-
-  for (SiChargedDiodeIterator i_chargedDiode=chargedDiodes->begin(); i_chargedDiode!=chargedDiodes->end(); ++i_chargedDiode) {
-    //
-    // Charged diode flag:
-    //====================
-    // I.  Mask = 0xff
-    // 0x1  : Noise
-    // 0x2  : Below threshold
-    // 0x4  : Disabled
-    // 0x8  : Corrupted TOT
-    //
-    // II. Mask = 0xff00
-    // Shift right 8 bits => relative bunch number (0 or 1 for CTB 2004)
-    // The bunch number is 1 if the time walk is larger than a cutoff (TimeCut in jobopts)
-    //---------------------------------
-    //
-    // If diode is disconnected/disabled skip it
-    //
-    Identifier diodeID = chargedDiodes->getId((*i_chargedDiode).first);
-
-    //  unsigned int flagmask = (*i_chargedDiode).second.flag() & 0xFE ;
-    //  if(!flagmask ) {
-    //
-    // Check if diode is masked out or has been disable by random mapping - if not, create the RDO.
-    //
-    bool maskedOut = false;
-    if (SiHelper::isMaskOut((*i_chargedDiode).second))  { maskedOut=true; } 
-    if (SiHelper::isDisabled((*i_chargedDiode).second)) { maskedOut=true; } 
-
-    if (!m_pixelConditionsSvc.empty()) {
-      bool active = m_pixelConditionsSvc->isActive(moduleHash,diodeID);
-      if (!active) {
-        SiHelper::disabled((*i_chargedDiode).second,true,true);
-        maskedOut=true;
-      }
-    }
-
-    if (!maskedOut) {
-
-      // calculate ToT from the total charge, add gaussian smearing
-      // take the integer value to get the actual observed ToT
-      // minimum ToT = 1
-
-      double tot    = m_pixelCalibSvc->getTotMean(diodeID,(*i_chargedDiode).second.charge());
-      double totsig = m_pixelCalibSvc->getTotRes(diodeID,tot);
-      int nToT = static_cast<int>(CLHEP::RandGaussZiggurat::shoot(m_rndmEngine,tot,totsig));
-      if (nToT<1) { nToT=1; }
-
-      // Fix for IBL, it sets the most probable value for a mip to 8.
-      // Need to keep it hardcoded for a cache (no header change)
-      // but when moving to full release, one has to accomodate additional
-      // properties and a proper function.
-      // - HitDiscriminator configuration
-      // - Referenca value (a mip)
-      // - ToT for that reference value
-
-      if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI4) {
-        const PixelID* pixelId = static_cast<const PixelID *>(chargedDiodes->element()->getIdHelper());
-        if (pixelId->is_dbm(chargedDiodes->element()->identify())) {
-          nToT = 8*((*i_chargedDiode).second.charge() - 1200. )/(8000. - 1200.);
-        }
-        if (nToT<=0) nToT=1;
-        if (nToT==2 && maxFEI4SmallHit==2) { nToT=1; }
-        if (nToT>=overflowIBLToT) { nToT=overflowIBLToT; }
-      }
-      int flag   = (*i_chargedDiode).second.flag();
-      int bunch  = (flag >>  8) & 0xff;
-      //
-      ATH_MSG_DEBUG("RDO: " << (*i_chargedDiode).second.charge() << "  " << nToT << "  " << bunch << "  " << flag << "  " << layerIndex);
-
-      if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI3) {
-        if (nToT>m_maxToT.at(layerIndex)) continue; // skip hits with ToT exceeding LVL1 Latency
-        if (nToT<m_minToT.at(layerIndex)) continue; // skip hits with ToT less than ToT cut
-      }
-
-      //       float kToT= m_totparA + m_totparB / ( m_totparC + (*i_chargedDiode).second.charge() ) ;
-      //       float kToTs  =  CLHEP::RandGaussZiggurat::shoot( m_rndmEngine, kToT ,  m_totparP1 + m_totparP2 * kToT ) ;
-      //       int nToT  =  static_cast<int>(kToTs) ;
-      //       if( nToT < 1 ) nToT=1;
-      //
-      // Fill the RDO word as in PixelRDO_Cnv.
-      //  This incomprehensible code is to fill the RDO as they do in the
-      //  zebra converter.
-      //  (code from PixelRDO_Cnv.cxx, some comments removed)
-
-      SiReadoutCellId cellId=(*i_chargedDiode).second.getReadoutCell();
-      const Identifier id_readout = chargedDiodes->element()->identifierFromCellId(cellId);
-
-      int iirow = cellId.phiIndex();
-      int iicol = cellId.etaIndex();
-      if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI4 && iicol>=maxCol) { iicol=iicol-maxCol; } // FEI4 copy mechanism works per FE.
-
-      //if (correct_id_readout!=diodeID) {
-      //  ATH_MSG_DEBUG ( "correct_readout_id != diodeID" );
-      // }
-      // Create hit only if bunch within the acceptance (not for IBL and DBM):
-
-      if (p_design->getReadoutTechnology()!=PixelModuleDesign::FEI4) {
-        if (bunch >= 0 && bunch < m_TimeSvc->getTimeBCN()) {
-          Pixel1RawData *p_rdo= new Pixel1RawData(id_readout, nToT, bunch, 0, bunch );
-          PixelRDOColl->push_back(p_rdo);
-        }
-      } else {
-        // IBL: if big hit, create RDO and record it. If small hit, create RDO and store it in a vector:
-
-        if ( nToT > maxFEI4SmallHit ) {
-          if ( bunch >= 0 && bunch < m_TimeSvc->getTimeBCN()) {
-            Pixel1RawData *p_rdo= new Pixel1RawData(id_readout, nToT, bunch, 0, bunch );
-            PixelRDOColl->push_back(p_rdo);
-            FEI4Map[iirow][iicol] = 2; //Flag for "big hits"
-          }
-        } else {
-          if ( bunch >= 0 && bunch < m_TimeSvc->getTimeBCN()) {
-            Pixel1RawData *p_rdo= new Pixel1RawData(id_readout, nToT, bunch, 0, bunch );
-            p_rdo_small_fei4.push_back(p_rdo);
-            row.push_back(iirow);
-            col.push_back(iicol);
-            nSmallHitsFEI4++;
-            FEI4Map[iirow][iicol] = 1; //Flag for low hits
-            ATH_MSG_DEBUG ( "Row small = " << iirow << " col small = " << iicol << " ToT = " << nToT << " Bunch = " << bunch << " ismallhits = " << nSmallHitsFEI4);
-          }
-        }
-      }
-      // Duplication mechanism for FEI3 small hits :
-      if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI3) {
-        if (m_applyDupli.at(layerIndex)) {
-          if (nToT<=m_maxToTForDupli.at(layerIndex) && bunch>0 && bunch<=m_TimeSvc->getTimeBCN()) {
-            Pixel1RawData *p_rdo= new Pixel1RawData(id_readout, nToT, bunch-1, 0, bunch-1 );
-            PixelRDOColl->push_back(p_rdo);
-          }
-        }
-      }
-    }
-  }
-  // Copy mechanism for IBL small hits:
-  if (p_design->getReadoutTechnology()==PixelModuleDesign::FEI4 && m_applyDupli.at(layerIndex) && nSmallHitsFEI4>0){
-    bool recorded = false;
-    //First case: Record small hits which are in the same Pixel Digital Region than a big hit:
-
-    for ( int ismall = 0; ismall != nSmallHitsFEI4; ++ismall ) {
-      int rowPDR = row[ismall]/2;
-      int colPDR = col[ismall]/2;
-      for ( int rowBigHit = 2*rowPDR; rowBigHit != 2*rowPDR+2 && rowBigHit < maxRow; ++rowBigHit ) {
-        for ( int colBigHit = 2*colPDR; colBigHit != 2*colPDR+2 && colBigHit < maxCol; ++colBigHit ) {
-          ATH_MSG_DEBUG ( "rowBig = " << rowBigHit << " colBig = " << colBigHit << " Map Content = " << FEI4Map[rowBigHit][colBigHit]);
-          if ( FEI4Map[rowBigHit][colBigHit] == 2 && !recorded) {
-            PixelRDOColl->push_back(p_rdo_small_fei4[ismall]);
-            recorded = true;
-          }
-        }
-      }
-      // Second case: Record small hits which are phi-neighbours with a big hit:
-
-      if ( !recorded && row[ismall] < maxRow - 1 ) {
-        if ( FEI4Map[row[ismall]+1][col[ismall]] == 2 ) {
-          PixelRDOColl->push_back(p_rdo_small_fei4[ismall]);
-          recorded = true;
-        }
-      }
-      if ( !recorded && row[ismall] != 0 ) {
-        if ( FEI4Map[row[ismall]-1][col[ismall]] == 2 ) {
-          PixelRDOColl->push_back(p_rdo_small_fei4[ismall]);
-          recorded = true;
-        }
-      }
-    }
-  }
-  return PixelRDOColl;
-}
-
 //----------------------------------------------------------------------
 // PrepareEvent method:
 //----------------------------------------------------------------------
 StatusCode PixelDigitizationTool::prepareEvent(unsigned int) {
   ATH_MSG_VERBOSE("PixelDigitizationTool::prepareEvent()");
 
-  m_HardScatterSplittingSkipper = false;
-  return StatusCode::SUCCESS;
-}
-
-//----------------------------------------------------------------------
-// MergeEvent method:
-//----------------------------------------------------------------------
-StatusCode PixelDigitizationTool::mergeEvent() {
-  ATH_MSG_VERBOSE("PixelDigitizationTool::mergeEvent()");
-
   //===============
   // Prepare event
   //===============
@@ -632,6 +346,7 @@ StatusCode PixelDigitizationTool::mergeEvent() {
       return StatusCode::FAILURE;
     }
   }
+  ATH_MSG_DEBUG("PixelRDO_Container " << m_rdoContainer.name() << " registered in StoreGate");
 
   if (!m_simDataColl.isValid()) {
     if (!(m_simDataColl = CxxUtils::make_unique<InDetSimDataCollection>()).isValid()) {
@@ -639,85 +354,29 @@ StatusCode PixelDigitizationTool::mergeEvent() {
       return StatusCode::FAILURE;
     }
   }
+  ATH_MSG_DEBUG("InDetSimDataCollection " << m_simDataColl.name() << " registered in StoreGate");
 
-  auto chargedDiodes = std::make_unique<SiChargedDiodeCollection>();
-
-  std::vector<bool> processedElements;
-  processedElements.resize(m_detID->wafer_hash_max(),false);
-
-  //================
-  // Generate event
-  //================
-  // Loop over the Detectors with hits
-  TimedHitCollection<SiHit>::const_iterator firstHit, lastHit;
-  while (m_timedHits->nextDetectorElement(firstHit,lastHit)) {
-
-    // Create the identifier for the collection
-    const PixelID* PID = static_cast<const PixelID*>(m_detID);
-    Identifier id = PID->wafer_id((*firstHit)->getBarrelEndcap(),(*firstHit)->getLayerDisk(),(*firstHit)->getPhiModule(),(*firstHit)->getEtaModule());
-
-    // Get the det element from the manager
-    SiDetectorElement* sielement = m_detManager->getDetectorElement(id);
-    if (sielement==0) { break; }
-
-    // Create the charged diodes collection
-    chargedDiodes->setDetectorElement(sielement);
-
-    // Loop over the hits and created charged diodes:
-    for (TimedHitCollection<SiHit>::const_iterator phit=firstHit; phit!=lastHit; phit++) {
-      //skip hits which are more than 10us away
-      if (fabs((*phit)->meanTime())<10000.0*CLHEP::ns) {
-        // Apply charge collection tools
-        for (unsigned int itool=0; itool<m_chargeTool.size(); itool++) {
-          if (m_chargeTool[itool]->charge(*phit,*chargedDiodes,*sielement)==StatusCode::FAILURE) { break; }
-        }
-      }
-    }
-
-    // Apply processor tools
-    for (unsigned int itool=0; itool<m_diodesProcsTool.size(); itool++) {
-      m_diodesProcsTool[itool]->process(*chargedDiodes);
-    }
-
-    IdentifierHash idHash = chargedDiodes->identifyHash();
+  m_HardScatterSplittingSkipper = false;
+  return StatusCode::SUCCESS;
+}
 
-    assert(idHash<processedElements.size());
-    processedElements[idHash] = true;
+//----------------------------------------------------------------------
+// MergeEvent method:
+//----------------------------------------------------------------------
+StatusCode PixelDigitizationTool::mergeEvent() {
+  ATH_MSG_VERBOSE("PixelDigitizationTool::mergeEvent()");
 
-    // Create and store RDO and SDO
-    if (!chargedDiodes->empty()) {
-      PixelRDO_Collection *RDOColl=this->createRDO(chargedDiodes.get());
+  //===============
+  // Digitize hits
+  //===============
+  CHECK(digitizeEvent());
 
-      CHECK(m_rdoContainer->addCollection(RDOColl,RDOColl->identifyHash()));
-      addSDO(chargedDiodes.get());
-    }
-    chargedDiodes->clear();
+  for (std::vector<SiHitCollection*>::iterator it = hitCollPtrs.begin();it!=hitCollPtrs.end();it++) {
+    (*it)->Clear();
+    delete(*it);
   }
-  delete m_timedHits;
-  m_timedHits = 0;
+  hitCollPtrs.clear();
 
-  if (!m_onlyHitElements) {
-    for (unsigned int i=0; i < processedElements.size(); i++) {
-      if (!processedElements[i]) {
-        IdentifierHash idHash = i;
-        const SiDetectorElement * element = m_detManager->getDetectorElement(idHash);
-        if (element) {
-          chargedDiodes->setDetectorElement(element);
-          // Apply processor tools
-          for (unsigned int itool=0; itool<m_diodesProcsTool.size(); itool++) {
-            m_diodesProcsTool[itool]->process(*chargedDiodes);
-          }
-          if (!chargedDiodes->empty()) {
-            PixelRDO_Collection *RDOColl=this->createRDO(chargedDiodes.get());
-            CHECK(m_rdoContainer->addCollection(RDOColl,RDOColl->identifyHash()));
-            addSDO(chargedDiodes.get());
-          }
-          chargedDiodes->clear();
-        }
-      }
-    }
-  }
-  ATH_MSG_DEBUG("Digitize success!");
   return StatusCode::SUCCESS;
 }
 
@@ -737,22 +396,17 @@ StatusCode PixelDigitizationTool::processBunchXing(int bunchXing, SubEventIterat
   SubEventIterator iEvt = bSubEvents;
   for (; iEvt!=eSubEvents; iEvt++) {
     StoreGateSvc& seStore = *iEvt->ptr()->evtStore();
-    ATH_MSG_VERBOSE("SubEvt StoreGate " << seStore.name() << " :"
-                    << " bunch crossing : " << bunchXing
-                    << " time offset : " << iEvt->time()
-                    << " event number : " << iEvt->ptr()->eventNumber()
-                    << " run number : " << iEvt->ptr()->runNumber());
+    ATH_MSG_VERBOSE("SubEvt StoreGate " << seStore.name() << " :" << " bunch crossing : " << bunchXing << " time offset : " << iEvt->time() << " event number : " << iEvt->ptr()->eventNumber() << " run number : " << iEvt->ptr()->runNumber());
 
     const SiHitCollection* seHitColl(0);
-    if (!seStore.retrieve(seHitColl,m_inputObjectName).isSuccess()) {
-      msg(MSG::ERROR) << "SubEvent Pixel SiHitCollection not found in StoreGate " << seStore.name() << endmsg;
-      return StatusCode::FAILURE;
-    }
+
+    CHECK(seStore.retrieve(seHitColl,m_inputObjectName));
     ATH_MSG_DEBUG("SiHitCollection found with " << seHitColl->size() << " hits");
 
     PileUpTimeEventIndex timeIndex(iEvt->time(),iEvt->index());
     SiHitCollection *hitCollPtr = new SiHitCollection(*seHitColl);
     m_timedHits->insert(timeIndex,hitCollPtr);
+    hitCollPtrs.push_back(hitCollPtr);
   }
 
   return StatusCode::SUCCESS;
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.h b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.h
index 95c0dadc9c7..b4bab15c059 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.h
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/PixelDigitizationTool.h
@@ -8,82 +8,9 @@
 ///////////////////////////////////////////////////////////////////
 // (c) ATLAS Detector software
 ///////////////////////////////////////////////////////////////////
-// Top tool class for Pixel digitization
-///////////////////////////////////////////////////////////////////
-//
-// Configurable Parameters:
-// -RndmSvc			Random number service used in Pixel Digitization
-// -MergeSvc			Merge service used in Pixel digitization
-// -TimeSvc			Time Svc
-// -InputObjectName		Input Object name
-// -CreateNoiseSDO		Set create noise SDO flag
-// -ManagerName			Pixel manager name
-// -RDOCollName			RDO collection name
-// -SDOCollName			SDO collection name
-// -LowTOTduplication		ToT value below which the hit is duplicated
-// -LVL1Latency			LVL1 latency (max possible ToT)
-// -RndmEngine			Random engine name
-// -UsePixCondSum		Use PixelConditionsSummarySvc
-// -EnableNoise			Enable noise generation
-// -EnableSpecialPixels		Enable special pixels
-// -OnlyHitElements		Process only elements with hits
-//
-///////////////////////////////////////////////////////////////////////////////
-
-/** @class PixelDigitizationTool
- * @brief The main pixel digitization class
- * @author David Calvet
- * @author Davide Costanzo
- * @author Fredrik Tegenfeldt
- *
- * \b Description
- *
- * This is the main class for the pixel digitization process. That is, for each event it
- * reads the Geant 4 produced hits and simulates the detector respons.
- *
- * The current design uses so called 'charge processors' for each simulated
- * process that affects the digitization.
- * Such a processor inherits from SiDigitization::SiChargedDiodesProcessor.
- * The number of processors is not explicetly limited apart from performance issues.
- *
- * The class inherits from the standard ATHENA Algorithm (via SiDigitization).
- * Before running over the events the class is initialized:
- *
- * - retrieve services, random number generator, etc
- * - add charge processors in time order (follow the links for detailed documentation)
- *      -# @link PixelSimpleSurfaceChargesGenerator Surface charge generator @endlink    MUST BE FIRST generates the charges produced by the tracks
- *      -# @link PixelDiodeCrossTalkGenerator       Cross talk               @endlink    adds cross talk
- *      -# @link PixelChargeSmearer                 Smearing                 @endlink    smear charges
- *      -# @link PixelNoisyCellGenerator            Noise                    @endlink    add noise
- *      -# @link PixelGangedMerger                  Ganged pixels            @endlink    merge ganged pixels
- *      -# @link PixelRandomDisabledCellGenerator   Random disabling         @endlink    randomly disable pixels
- *      -# @link PixelTimeWalkGenerator             Timing                   @endlink    simulate the timing
- *      -# @link PixelCellDiscriminator             Discriminate             @endlink    discriminate and throw away charges below threshold
- *
- * Other charge processors may of course be added.
- *
- * <b>--- NOTE: This design does not conform with ATHENA standards. The charge processors
- * should be converted into (private) AlgTools ---</b>
- *
- * In execute(), the hit collections are digitized
- * - update special pixel map
- *     - if update then simulate a new map
- *     - if using conditions DB, retrieve a pointer of the (updated) map
- * - create Pixel RDO container and store it in StoreGate
- * - if a RDO for the special pixel map is requested, create and store it with the same name with a postfix "_SPM"
- * - create a SDO collection
- *
- * The output will per event be
- * -# a collection of RDOs retrievable from StoreGate with the name RDOCollName (see job options)
- * -# a collection of SDOs; idem but SDOCollName
- * -# optionally a collection of RDOs for each special pixel maps (useful for debugging)
- *
- */
-
 #ifndef PIXELDIGITIZATION_PIXELDIGITIZATIONTOOL_H
 #define PIXELDIGITIZATION_PIXELDIGITIZATIONTOOL_H
 
-// Base class
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "PileUpTools/PileUpToolBase.h"
 #include "HitManagement/TimedHitCollection.h"
@@ -93,109 +20,70 @@
 #include "GaudiKernel/ToolHandle.h"
 #include "GaudiKernel/ServiceHandle.h"
 
-#include "SiPropertiesSvc/ISiPropertiesSvc.h"
-#include "PixelConditionsTools/IModuleDistortionsTool.h"
-#include "AthenaKernel/IAtRndmGenSvc.h"
-
+// STSTST #include "AthenaKernel/IAtRndmGenSvc.h"
 #include "StoreGate/WriteHandle.h"
 
-// Conditions
-#include "PixelConditionsServices/IPixelCalibSvc.h"
-#include "PixelConditionsServices/ISpecialPixelMapSvc.h"
-#include "InDetConditionsSummaryService/IInDetConditionsSvc.h"
-#include "PixelConditionsServices/IPixelOfflineCalibSvc.h"
-
-class PixelID;
-class SiChargedDiodeCollection;
-class ISiChargedDiodesProcessorTool;
-class InDetSimDataCollection;
-class DetectorSpecialPixelMap;
-class PixelGangedMerger;
-class SpecialPixelGenerator;
-class PixelCellDiscriminator;
-class PixelDiodeCrossTalkGenerator;
-class PixelChargeSmearer;
-class TimeSvc;
-class PixelRandomDisabledCellGenerator;
-class ISiChargedDiodeCollection;
-class SubChargesTool;
-class IPixelOfflineCalibSvc;
-
-class IInDetConditionsSvc;
-
-namespace CLHEP {
-  class HepRandomEngine;
-}
-
-namespace InDetDD{
-  class SiDetectorElement;
-  class SiDetectorManager;
-}
+#include "InDetSimData/InDetSimDataCollection.h"
+#include "SiDigitization/ISiChargedDiodesProcessorTool.h"
+#include "SubChargesTool.h"
+#include "FrontEndSimTool.h"
 
-class PixelDigitizationTool : public PileUpToolBase {
-
-public:
-  PixelDigitizationTool(const std::string &type, const std::string &name, const IInterface *pIID);
+#include "InDetReadoutGeometry/PixelDetectorManager.h"
 
-  virtual StatusCode initialize();
-  virtual StatusCode processAllSubEvents();
-  virtual StatusCode finalize();
+class PixelDigitizationTool : public PileUpToolBase {
 
-  PixelRDO_Collection *createRDO(SiChargedDiodeCollection *c); // create RDO from given collection
+  public:
+    PixelDigitizationTool(const std::string &type, const std::string &name, const IInterface *pIID);
 
-  StatusCode prepareEvent(unsigned int);
-  StatusCode mergeEvent();
-  virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final;
+    virtual StatusCode initialize();
+    virtual StatusCode processAllSubEvents();
+    virtual StatusCode finalize();
 
-protected:
-  void addSDO(SiChargedDiodeCollection *collection);
+    StatusCode prepareEvent(unsigned int);
+    StatusCode digitizeEvent();
+    StatusCode mergeEvent();
+    virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final;
 
-private:
-  ServiceHandle<IPixelOfflineCalibSvc> m_offlineCalibSvc;
+  protected:
+    void addSDO(SiChargedDiodeCollection *collection);
 
-  PixelDigitizationTool();
-  PixelDigitizationTool(const PixelDigitizationTool&);
-  PixelDigitizationTool &operator=(const PixelDigitizationTool&);
+  private:
 
-  SG::WriteHandle<PixelRDO_Container>     m_rdoContainer;
-  SG::WriteHandle<InDetSimDataCollection> m_simDataColl;
+    PixelDigitizationTool();
+    PixelDigitizationTool(const PixelDigitizationTool&);
+    PixelDigitizationTool &operator=(const PixelDigitizationTool&);
 
-  std::vector<int>  m_maxToT;            /**< LVL1 latency (max ToT readout from pixels) */
-  std::vector<int>  m_minToT;            /**< ToT cut */
-  std::vector<bool> m_applyDupli;        /**< Apply hit duplication */
-  std::vector<int>  m_maxToTForDupli;    /**< Maximum ToT for hit duplication */
+    std::vector<SiHitCollection*> hitCollPtrs;
 
-  int               m_HardScatterSplittingMode; /**< Process all SiHit or just those from signal or background events */
-  bool              m_HardScatterSplittingSkipper;
-  std::string       m_rndmEngineName;/**< name of random engine, actual pointer in SiDigitization */
+    SG::WriteHandle<PixelRDO_Container>     m_rdoContainer;
+    SG::WriteHandle<InDetSimDataCollection> m_simDataColl;
 
-  // Conditions database options
-  bool              m_onlyHitElements;            /**< process only elements with hits */
+    int               m_HardScatterSplittingMode;
+    bool              m_HardScatterSplittingSkipper;
+    std::string       m_rndmEngineName;
 
-  ToolHandleArray<ISiChargedDiodesProcessorTool> m_diodesProcsTool;
-  ToolHandleArray<SubChargesTool>                m_chargeTool;
+    bool              m_onlyHitElements;
 
-  ServiceHandle<IPixelCalibSvc>          m_pixelCalibSvc;
+    ToolHandleArray<ISiChargedDiodesProcessorTool> m_diodesProcsTool;
+    ToolHandleArray<SubChargesTool>                m_chargeTool;
+    ToolHandleArray<FrontEndSimTool>               m_fesimTool;
 
-  const PixelID            *m_detID;     /**< the ID helper */
+    const PixelID            *m_detID;
 
-  IntegerProperty           m_vetoThisBarcode;
+    IntegerProperty           m_vetoThisBarcode;
 
-  TimedHitCollection<SiHit> *m_timedHits;
+    TimedHitCollection<SiHit> *m_timedHits;
 
-protected:
-  //The following are copied over from SiDigitization.h
-  ServiceHandle <IAtRndmGenSvc> m_rndmSvc;
-  ServiceHandle <PileUpMergeSvc> m_mergeSvc;
+  protected:
 
-  ServiceHandle<TimeSvc>             m_TimeSvc;
-  ServiceHandle<IInDetConditionsSvc> m_pixelConditionsSvc;
+    ServiceHandle <IAtRndmGenSvc> m_rndmSvc;
+    ServiceHandle <PileUpMergeSvc> m_mergeSvc;
 
-  CLHEP::HepRandomEngine *m_rndmEngine;
-  const InDetDD::SiDetectorManager *m_detManager;
+    CLHEP::HepRandomEngine *m_rndmEngine;
+    const InDetDD::SiDetectorManager *m_detManager;
 
-  std::string   m_inputObjectName;
-  bool          m_createNoiseSDO;
+    std::string   m_inputObjectName;
+    bool          m_createNoiseSDO;
 
 };
 
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.cxx
index 8e878fd34db..78b9115a8d2 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.cxx
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.cxx
@@ -2,14 +2,10 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-//////////////////////////////////////////////////////////////////
-// PixelCellDiscriminator.cxx
-//   Implementation file for class PixelCellDiscriminator
 ///////////////////////////////////////////////////////////////////
 // (c) ATLAS Detector software
 ///////////////////////////////////////////////////////////////////
 
-#include "PixelCellDiscriminator.h"
 #include "InDetSimEvent/SiTotalCharge.h"
 #include <cmath>
 #include "CLHEP/Random/RandomEngine.h"
@@ -20,6 +16,7 @@
 
 TimeSvc::TimeSvc(const std::string& name, ISvcLocator* svc):
   AthService(name,svc),
+  m_ComputedTime(nullptr),
   m_useComTime(false),
   m_comTime(0.0),
   m_timePerBCO(25.0),
@@ -89,7 +86,7 @@ StatusCode TimeSvc::finalize() {
   return StatusCode::SUCCESS;
 }
 
-int TimeSvc::relativeBunch(const double threshold, const double intimethreshold, const SiTotalCharge &totalCharge, bool CTW) const {
+int TimeSvc::relativeBunch2009(const double threshold, const double intimethreshold, const SiTotalCharge &totalCharge, bool CTW) const {
 
   int BCID=0;
   double myTimeWalkEff = 0.;
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.h b/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.h
index aa375ee96e6..dee38b40286 100644
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.h
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/TimeSvc.h
@@ -79,7 +79,6 @@
 
 #include "CommissionEvent/ComTime.h"
 
-class PixelCellDiscriminator;
 class SiTotalCharge;
 
 class IAtRndmGenSvc;
@@ -101,7 +100,7 @@ class TimeSvc : public AthService, virtual public IInterface {
     virtual StatusCode finalize();
     virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvIf );
 
-    int relativeBunch(const double threshold, const double intimethreshold, const SiTotalCharge &totalCharge, bool CTW) const;
+    int relativeBunch2009(const double threshold, const double intimethreshold, const SiTotalCharge &totalCharge, bool CTW) const;
 
     int relativeBunch2015(const SiTotalCharge &totalCharge, int barrel_ec, int layer_disk, int moduleID) const;
 
diff --git a/InnerDetector/InDetDigitization/PixelDigitization/src/components/PixelDigitization_entries.cxx b/InnerDetector/InDetDigitization/PixelDigitization/src/components/PixelDigitization_entries.cxx
index 337e7fcb5c7..d090a2c6a7c 100755
--- a/InnerDetector/InDetDigitization/PixelDigitization/src/components/PixelDigitization_entries.cxx
+++ b/InnerDetector/InDetDigitization/PixelDigitization/src/components/PixelDigitization_entries.cxx
@@ -4,12 +4,10 @@
 #include "src/PixelDigitizationTool.h"
 #include "src/PixelNoisyCellGenerator.h"
 #include "src/PixelGangedMerger.h"
-#include "src/PixelCellDiscriminator.h"
 #include "src/PixelChargeSmearer.h"
 #include "src/PixelDiodeCrossTalkGenerator.h"
 #include "src/PixelRandomDisabledCellGenerator.h"
 #include "src/TimeSvc.h"
-#include "src/SubChargesTool.h"
 #include "src/PixelBarrelChargeTool.h"
 #include "src/PixelBarrelBichselChargeTool.h"
 #include "src/PixelECChargeTool.h"
@@ -19,17 +17,16 @@
 #include "src/IblPlanarBichselChargeTool.h"
 #include "src/Ibl3DChargeTool.h"
 #include "src/Ibl3DBichselChargeTool.h"
-#include "src/SubChargesTool.h"
 #include "src/ChargeCollProbSvc.h"
 #include "src/BichselSimTool.h"
+#include "src/FEI4SimTool.h"
+#include "src/FEI3SimTool.h"
 
 DECLARE_ALGORITHM_FACTORY(PixelDigitization)
 DECLARE_TOOL_FACTORY(BichselSimTool)
 DECLARE_TOOL_FACTORY(PixelDigitizationTool)
 DECLARE_TOOL_FACTORY(PixelNoisyCellGenerator)
 DECLARE_TOOL_FACTORY(PixelGangedMerger)
-DECLARE_TOOL_FACTORY(PixelCellDiscriminator)
-DECLARE_TOOL_FACTORY(PixelCellDiscriminator)
 DECLARE_TOOL_FACTORY(PixelChargeSmearer)
 DECLARE_TOOL_FACTORY(PixelDiodeCrossTalkGenerator)
 DECLARE_TOOL_FACTORY(PixelRandomDisabledCellGenerator)
@@ -42,6 +39,8 @@ DECLARE_TOOL_FACTORY(IblPlanarChargeTool)
 DECLARE_TOOL_FACTORY(IblPlanarBichselChargeTool)
 DECLARE_TOOL_FACTORY(Ibl3DChargeTool)
 DECLARE_TOOL_FACTORY(Ibl3DBichselChargeTool)
+DECLARE_TOOL_FACTORY(FEI4SimTool)
+DECLARE_TOOL_FACTORY(FEI3SimTool)
 //DECLARE_TOOL_FACTORY(SubChargesTool)
 DECLARE_SERVICE_FACTORY(ChargeCollProbSvc)
 DECLARE_SERVICE_FACTORY(TimeSvc)
@@ -52,7 +51,6 @@ DECLARE_FACTORY_ENTRIES(PixelDigitization) {
   DECLARE_TOOL(PixelDigitizationTool)
   DECLARE_TOOL(PixelNoisyCellGenerator)
   DECLARE_TOOL(PixelGangedMerger)
-  DECLARE_TOOL(PixelCellDiscriminator)
   DECLARE_TOOL(PixelChargeSmearer)
   DECLARE_TOOL(PixelDiodeCrossTalkGenerator)
   DECLARE_TOOL(PixelRandomDisabledCellGenerator)
@@ -65,6 +63,8 @@ DECLARE_FACTORY_ENTRIES(PixelDigitization) {
   DECLARE_TOOL(IblPlanarBichselChargeTool)
   DECLARE_TOOL(Ibl3DChargeTool)
   DECLARE_TOOL(Ibl3DBichselChargeTool)
+  DECLARE_TOOL(FEI4SimTool)
+  DECLARE_TOOL(FEI3SimTool)
  // DECLARE_TOOL(SubChargesTool)
   DECLARE_SERVICE(ChargeCollProbSvc)
   DECLARE_SERVICE(TimeSvc)
-- 
GitLab