diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt b/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..afa4ae31542b62d1a6a15b5c9b76b16786d8bb16
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/CMakeLists.txt
@@ -0,0 +1,24 @@
+################################################################################
+# Package: FaserSiDigitization
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserSiDigitization )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          Control/AthAllocators
+                          DetectorDescription/Identifier
+                          GaudiKernel
+                          Tracker/TrackerDetDescr/TrackerReadoutGeometry
+                          Tracker/TrackerSimEvent )
+
+# Component(s) in the package:
+atlas_add_library( FaserSiDigitization
+                   src/SiChargedDiode.cxx
+                   src/SiChargedDiodeCollection.cxx
+                   src/SiSurfaceCharge.cxx
+                   PUBLIC_HEADERS FaserSiDigitization
+                   LINK_LIBRARIES AthenaKernel AthAllocators Identifier GaudiKernel TrackerReadoutGeometry TrackerSimEvent )
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..da544c9d30a66d7dcb521188c6d363dc77919bd4
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+Tracker/TrackerDigitization/FaserSiDigitization
\ No newline at end of file
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..f45afd9fcd61f695e9d9f5f7b0bcc53d772e6c51
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/ISiChargedDiodesProcessorTool.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * ISiChargedDiodesProcessorTool.h
+ * Header file for abstract base class ISiChargedDiodesProcessorTool
+ * (c) ATLAS Detector software
+ * Interface for the SiChargedDiode processor classes
+ * 23/08/2007 Kondo.Gnanvo@cern.ch, and others   
+*/
+
+#ifndef FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
+#define FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+
+class SiChargedDiodeCollection;
+class NPtGainSummaryData;
+namespace CLHEP {
+  class HepRandomEngine;
+}
+
+static const InterfaceID IID_ISiChargedDiodesProcessorTool("ISiChargedDiodesProcessorTool",1,0);
+
+class ISiChargedDiodesProcessorTool : virtual public IAlgTool {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  //Retrieve interface ID
+  static const InterfaceID & interfaceID() {return IID_ISiChargedDiodesProcessorTool; }
+
+  // Destructor:
+  virtual ~ISiChargedDiodesProcessorTool() {}
+
+  ///////////////////////////////////////////////////////////////////
+  // Pure virtual methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // process the collection of charged diodes
+  virtual void process(SiChargedDiodeCollection &collection, CLHEP::HepRandomEngine * rndmEngine) const =0;
+};
+
+#endif // FASERSIDIGITIZATION_ISICHARGEDDIODESPROCESSORTOOL_H
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h
new file mode 100644
index 0000000000000000000000000000000000000000..fadd13e4555c63976bee38629119e80f179a0755
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiode.h
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////// 
+// SiChargedDiode.h // Header file for class SiChargedDiode
+/////////////////////////////////////////////////////////////////// 
+// (c) ATLAS Detector software
+/////////////////////////////////////////////////////////////////// 
+// Class which contains the sum and the composition of all bare 
+//charges (SiTotalCharge) deposited in one SiDiode 
+/////////////////////////////////////////////////////////////////// 
+// Version 2.1 09/06/2001 David Calvet 
+// Revisited 04-03-03 Davide Costanzo
+//  added a int flag as a private data member to store the noise, 
+//  disconnected, bad_tot information. The relative bunch number is 
+//  also stored in this word. 
+//  the word will is meant to be copied as it is in the SDO
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERSIDIGITIZATION_SICHARGEDDIODE_H 
+#define FASERSIDIGITIZATION_SICHARGEDDIODE_H
+
+// Data member classes
+#include "TrackerSimEvent/SiTotalCharge.h"
+#include "TrackerReadoutGeometry/SiCellId.h"
+#include "TrackerReadoutGeometry/SiReadoutCellId.h"
+
+class SiHelper; // used to set the flag word
+//class SiChargedDiode;
+
+class SiChargedDiode {
+
+    friend class SiHelper;
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Constructor with parameters:
+    SiChargedDiode(const SiTotalCharge::alloc_t& alloc,
+                   const TrackerDD::SiCellId & diode, const TrackerDD::SiReadoutCellId & roCell,  int flagword=0, SiChargedDiode* nextInCluster=NULL);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // Diode which contains this charge:
+  const TrackerDD::SiCellId & diode() const;
+
+  // Readout cell associated to diode 
+  // (usually the same id as the diode except for ganged pixels):
+  const TrackerDD::SiReadoutCellId & getReadoutCell();
+
+  // total charge and its composition:
+  const SiTotalCharge & totalCharge() const;
+
+  // total deposited charge:
+  double charge() const;
+  
+  // flag, disconnected etc.
+  int flag() const;
+  
+  //neighbouring strip for navigation 
+  SiChargedDiode * nextInCluster();
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another charge:
+  void add(const SiCharge &charge);
+  // add a total charge
+  void add(const SiTotalCharge &totcharge);
+  //add a neighbouring strip for navigation 
+  void setNextInCluster(SiChargedDiode* nextInCluster);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiChargedDiode();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  TrackerDD::SiCellId m_diode; // SiDiode which contains this charge
+                          // the pointed SiDiode is owned by the SiChargedDiode
+  SiTotalCharge m_totalCharge; // total charge and its composition
+  TrackerDD::SiReadoutCellId m_readoutCell; //Readout cell associated to this diode
+  int m_word;   // a flag for noise etc etc as in InDetSimData
+  SiChargedDiode * m_nextInCluster; //the next strip to navigate to - allows traversing clusters since the SiChargedDiodeCollection is not guaranteed to be contiguous
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline const TrackerDD::SiCellId & SiChargedDiode::diode() const 
+{
+  return m_diode;
+}
+
+inline int SiChargedDiode::flag() const 
+{
+  return m_word;
+}
+
+inline const SiTotalCharge &SiChargedDiode::totalCharge() const
+{
+  return m_totalCharge;
+}
+inline const TrackerDD::SiReadoutCellId & SiChargedDiode::getReadoutCell() {
+  return m_readoutCell;
+}
+
+inline double SiChargedDiode::charge() const
+{
+  return m_totalCharge.charge();
+}
+
+inline SiChargedDiode * SiChargedDiode::nextInCluster()
+{
+  return m_nextInCluster;
+}
+
+inline void SiChargedDiode::add(const SiCharge &charge)
+{
+  m_totalCharge.add(charge);
+}
+
+inline void SiChargedDiode::add(const SiTotalCharge &totcharge)
+{
+  m_totalCharge.add(totcharge);
+}
+
+inline void SiChargedDiode::setNextInCluster(SiChargedDiode* nextInCluster)
+{
+   m_nextInCluster = nextInCluster;
+}
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiChargedDiode &chargedDiode);
+
+#endif // FASERSIDIGITIZATION_SICHARGEDDIODE_H
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f5a9f23734cfc1d48545565e58f5b36e90fe473
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiChargedDiodeCollection.h
@@ -0,0 +1,285 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiChargedDiodeCollection.h
+//   Header file for class SiChargedDiodeCollection
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class used to store the list of SiChargedDiode objects for one
+//  module (Pixel) or half module (SCT) and one event. 
+///////////////////////////////////////////////////////////////////
+// Version 3.0 09/07/2001 David Calvet
+// Davide Costanzo. Revisited version. 04-03-03
+//    - added a Identifier wafer_id to the private members
+//    - added a IdHelper to the private members
+//    - constructor modified to initialize wafer_id and IdHelper
+//    - replaced <list> with <map> and use the compact id of the 
+//      SiChargedDiode to map them.
+//    - Inherit from Identifiable to enforce the identify() method
+///////////////////////////////////////////////////////////////////
+#ifndef FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+#define FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+
+// Base class
+#include "Identifier/Identifiable.h"
+
+// Data member classes
+#include <unordered_map>
+#include "FaserSiDigitization/SiChargedDiode.h"
+#include "Identifier/Identifier.h"
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+
+// Input/output classes 
+#include "TrackerSimEvent/FaserSiHit.h"
+
+// STL includes
+#include <atomic>
+#include <set>
+#include <memory>
+
+class FaserDetectorID;
+namespace TrackerDD{
+  class SiDetectorElement;
+  class SiDetectorDesign;
+  class SiCellId;
+}
+
+#include "AthAllocators/ArenaPoolSTLAllocator.h"
+
+struct SiChargedDiodeHash
+{
+  size_t operator() (const TrackerDD::SiCellId & id) const
+  {
+    return id.word();
+  }
+};
+
+typedef std::unordered_map<TrackerDD::SiCellId,
+                           SiChargedDiode,
+                           SiChargedDiodeHash,
+                           std::equal_to<TrackerDD::SiCellId>,
+                           SG::ArenaPoolSTLAllocator<
+                            std::pair<const TrackerDD::SiCellId, SiChargedDiode> > >
+  SiChargedDiodeMap;
+
+
+// Iterator typedef to make it easier
+typedef SiChargedDiodeMap::iterator SiChargedDiodeIterator;
+
+
+
+//
+// A normal iteration over a SiChargedDiodeCollection will use
+// the unordered_map, so the ordering is not defined.  The observed
+// ordering can (and does) change depending on the compiler and library
+// version used.  In some cases, though, we are sensitive to the
+// order of iteration, for example in cases where we generate a random
+// number for each element of the collection.  To get results which
+// are identical across compilers, we need to instead do the iteration
+// in a well-defined order.
+//
+// This can be done using the methods sortedBegin and sortedEnd instead
+// of begin and end.  These work by maintaining a std::set of pointers
+// to the diodes, sorted by the diode number.  In order to avoid paying
+// the penalty for maintaining the sorted set when we don't need to, we only
+// start maintaining it the first time that it's requested.
+struct SiChargedDiodeOrderedSetCompare
+{
+  size_t operator() (const SiChargedDiode* a,
+                     const SiChargedDiode* b) const
+  {
+    return a->diode().word() < b->diode().word();
+  }
+};
+
+
+
+typedef std::set<SiChargedDiode*,
+                 SiChargedDiodeOrderedSetCompare,
+                 SG::ArenaPoolSTLAllocator<SiChargedDiode*> >
+  SiChargedDiodeOrderedSet;
+                 
+
+// Iterator typedef to make it easier
+typedef SiChargedDiodeOrderedSet::iterator SiChargedDiodeOrderedIterator;
+
+class SiChargedDiodeCollection : Identifiable {
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+
+  // Constructor with parameters:
+  //  ref. to the detector element for this collection
+  SiChargedDiodeCollection( );
+
+  SiChargedDiodeCollection(const TrackerDD::SiDetectorElement* );
+
+
+  // Destructor:
+  ~SiChargedDiodeCollection();
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // detector element:
+  const TrackerDD::SiDetectorElement * element() const;
+
+  // wafer identifier for this collection
+  virtual Identifier identify() const override final;
+  virtual IdentifierHash identifyHash() const override final;
+
+  // id helper for this collection
+  const FaserDetectorID* id_helper();
+  
+  // detector design:
+  const TrackerDD::SiDetectorDesign &design() const;
+
+  // translation from SiReadoutCellId to Identifier
+  Identifier getId(const TrackerDD::SiCellId& id) const 
+  { 
+    return (element()->identifierFromCellId(id)); 
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // clean up:
+  void clear();
+
+  // read/write access to the collection:
+  SiChargedDiodeMap &chargedDiodes();
+
+  // Set the SiDetectorElement
+  void setDetectorElement(const TrackerDD::SiDetectorElement *SiElement);
+
+  // Add a new SiCharge to the collection
+  // (add or merge in an existing SiChargedDiode):
+  //   Diode which contains the new charge
+  //   SiCharge to be added. 
+  void add(const TrackerDD::SiCellId & diode, const SiCharge &charge);
+  void add(const TrackerDD::SiCellId & diode, const SiTotalCharge &totcharge);
+
+  bool AlreadyHit(const TrackerDD::SiCellId & siId);
+  bool AlreadyHit(const Identifier & id);
+  SiChargedDiodeIterator begin();
+  SiChargedDiodeIterator end();
+  SiChargedDiodeOrderedIterator orderedBegin();
+  SiChargedDiodeOrderedIterator orderedEnd();
+  bool empty() const; // Test if there is anything in the collection.
+
+  // return a Charged diode given its CellId, NULL if doesn't exist
+  SiChargedDiode * find(const TrackerDD::SiCellId & siId);
+  // return a Charged diode given its identifier, NULL if doesn't exist
+  SiChargedDiode * find(Identifier);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+ private:
+  SiChargedDiodeCollection(const SiChargedDiodeCollection&);
+  SiChargedDiodeCollection &operator=(const SiChargedDiodeCollection&);
+  void order();
+  
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+ private:
+  //NB m_allocator should always be declared before m_chargedDiodes in
+  //the intialization list.  If the allocator is declared after
+  //m_chargedDiodes, when the collection is destroyed, the allocator
+  //will be destroyed (and the memory it manages freed) before the
+  //SiChargedDiodeMap.  This will cause a crash unless the
+  //SiChargedDiodeMap is empty.
+  SiTotalCharge::alloc_t m_allocator; 
+  SiChargedDiodeMap m_chargedDiodes; // list of SiChargedDiodes 
+  SiChargedDiodeOrderedSet m_orderedChargedDiodes; // list of SiChargedDiodes 
+  const TrackerDD::SiDetectorElement* m_sielement; // detector element
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+
+// Set the DetectorElement
+inline void SiChargedDiodeCollection::setDetectorElement(const TrackerDD::SiDetectorElement *SiElement) 
+{
+  m_sielement=SiElement;
+}
+
+inline SiChargedDiodeMap &SiChargedDiodeCollection::chargedDiodes()
+{
+  return m_chargedDiodes;
+}
+
+// access to the element
+inline const TrackerDD::SiDetectorElement *SiChargedDiodeCollection::element() const
+{
+  return m_sielement;
+}
+
+// access to the design
+inline const TrackerDD::SiDetectorDesign &SiChargedDiodeCollection::design() const
+{
+  return m_sielement->design();
+}
+
+// Get the Identifier of the collection
+inline Identifier SiChargedDiodeCollection::identify() const
+{
+  return m_sielement->identify();
+}
+
+// Get the Identifier of the collection
+inline IdentifierHash SiChargedDiodeCollection::identifyHash() const
+{
+  return m_sielement->identifyHash();
+}
+
+// Get the Id Helper
+inline const FaserDetectorID* SiChargedDiodeCollection::id_helper()
+{   
+  return m_sielement->getIdHelper();
+}
+
+
+inline SiChargedDiodeIterator SiChargedDiodeCollection::begin() 
+{
+  return m_chargedDiodes.begin();
+}
+
+inline SiChargedDiodeIterator SiChargedDiodeCollection::end() 
+{
+  return m_chargedDiodes.end();
+}
+
+inline SiChargedDiodeOrderedIterator SiChargedDiodeCollection::orderedBegin() 
+{
+  if (m_orderedChargedDiodes.empty() && !m_chargedDiodes.empty()) {
+    order();
+  }
+  return m_orderedChargedDiodes.begin();
+}
+
+inline SiChargedDiodeOrderedIterator SiChargedDiodeCollection::orderedEnd() 
+{
+  if (m_orderedChargedDiodes.empty() && !m_chargedDiodes.empty()) {
+    order();
+  }
+  return m_orderedChargedDiodes.end();
+}
+
+inline bool SiChargedDiodeCollection::empty() const {
+  return m_chargedDiodes.empty();
+}
+
+
+
+#endif // FASERSIDIGITIZATION_SICHARGEDDIODECOLLECTION_H
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..1745878defc39fd913365ffba0702e2ff1048af2
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiHelper.h
@@ -0,0 +1,208 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*************************************************************************
+    SiHelper for Silicons
+    This is used by the SiDigitization
+    ---------------------------------
+    ATLAS Collaboration
+
+
+    This is a short copy of the PixelSimHelper used by the SDO.
+    It is needed to set the word of the Charged Diodes in the same 
+    way as it will be registered in the SDO.
+  
+    D. Costanzo 4-3-03
+***************************************************************************/
+
+
+#ifndef FASERSIDIGITIZATION_SIHELPER_H
+#define FASERSIDIGITIZATION_SIHELPER_H
+
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/getMessageSvc.h"
+#include "FaserSiDigitization/SiChargedDiode.h"
+
+class SiHelper
+{
+ public:
+  // methods to set characteristics of a new object
+
+  static void noise(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void belowThreshold(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void disabled(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void badToT(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void disconnected(SiChargedDiode& chDiode, bool flag, bool mask=false);
+  static void maskOut(SiChargedDiode& chDiode, bool flag);
+  static void ClusterUsed(SiChargedDiode& chDiode, bool flag);
+  static void SetBunch(SiChargedDiode& chDiode, int bunch, MsgStream* log=nullptr);
+  static void SetStripNum(SiChargedDiode& chDiode, int nstrip, MsgStream* log=nullptr);
+  static void SetTimeBin(SiChargedDiode& chDiode, int time, MsgStream* log=nullptr);
+
+  static bool isUsable(SiChargedDiode& chDiode);
+  static bool isNoise(SiChargedDiode& chDiode);
+  static bool isBelowThreshold(SiChargedDiode& chDiode);
+  static bool isDisabled(SiChargedDiode& chDiode);
+  static bool isBadToT(SiChargedDiode& chDiode);
+  static bool isDisconnected(SiChargedDiode& chDiode);
+  static bool isMaskOut(SiChargedDiode& chDiode);
+  static bool isClusterUsed(SiChargedDiode &chDiode);
+  static int  GetBunch(SiChargedDiode& chDiode);
+  static int  GetStripNum(SiChargedDiode& chDiode);
+  static int  GetTimeBin(SiChargedDiode& chDiode);
+
+ private:
+  enum {
+    NOISE_SET        = 0x1,  // main charge is noise
+    BT_SET           = 0x2,  // below threshold
+    DISABLED_SET     = 0x4,  // disabled
+    BADTOT_SET       = 0x8,  // bad TOT
+    DISCONNECTED_SET = 0x10, // disconnected
+    CLUSTERUSED_SET  = 0x20, // used in cluster - used by anyone???
+    MASKOUT_SET      = 0x40  // charge diode is masked out, not to be used for RDO creation
+  };
+};
+
+inline void SiHelper::maskOut(SiChargedDiode& chDiode, bool flag) {
+  if (flag) {
+    chDiode.m_word |=  MASKOUT_SET;
+  } else {
+    chDiode.m_word &= ~MASKOUT_SET;
+  }
+}
+    
+inline void SiHelper::noise(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  NOISE_SET;
+  } else {
+    chDiode.m_word &= ~NOISE_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::belowThreshold(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  BT_SET;
+  } else {
+    chDiode.m_word &= ~BT_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::disabled(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  DISABLED_SET;
+  } else {
+    chDiode.m_word &= ~DISABLED_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+    
+inline void SiHelper::badToT(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  BADTOT_SET;
+  } else {
+    chDiode.m_word &= ~BADTOT_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+
+inline void SiHelper::disconnected(SiChargedDiode& chDiode, bool flag, bool mask) {
+  if (flag) {
+    chDiode.m_word |=  DISCONNECTED_SET;
+  } else {
+    chDiode.m_word &= ~DISCONNECTED_SET;
+  }
+  if (mask) SiHelper::maskOut(chDiode,true);
+}
+
+
+inline void SiHelper::ClusterUsed(SiChargedDiode& chDiode, bool flag) {
+  if (flag) {
+    chDiode.m_word |=  CLUSTERUSED_SET;
+  } else {
+    chDiode.m_word &= ~CLUSTERUSED_SET;
+  }
+}
+
+inline void SiHelper::SetBunch(SiChargedDiode& chDiode, int bunch, MsgStream* log) {
+  //
+  // Code the bunch number in the 8 bits set corresponding to xx in xx00 
+  //
+  if (bunch > 0xff) {
+    if (log) (*log) << MSG::ERROR << "Bunch Number not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ( (bunch&0xff) <<8 )  ;
+}
+
+inline void SiHelper::SetStripNum(SiChargedDiode& chDiode, int nstrip, MsgStream* log) {
+  //
+  // Code the number of strips in the 12 bits set corresponding to xxx in 0xxx0000 
+  //
+  if (nstrip > 0xfff) {
+    if (log) (*log) << MSG::ERROR << "Number of strips not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ((nstrip&0xfff) << 16 ) ;
+}
+
+inline void SiHelper::SetTimeBin(SiChargedDiode& chDiode, int time, MsgStream* log) {
+  //
+  // Code the SCT Timebin number in the 3 bits set corresponding to x in x0000000
+  //
+  if (time > 0xf) {
+    if (log) (*log) << MSG::ERROR << "TimeBin not allowed" << endmsg;
+  }
+  chDiode.m_word = chDiode.m_word | ( (time&0xf) <<28 )  ;
+}
+
+////////////////////////////////////////////////////////////
+
+inline bool SiHelper::isUsable(SiChargedDiode& chDiode) {
+  return !SiHelper::isMaskOut(chDiode);
+  //  return (((chDiode.m_word & 0xff) == 0) ||     // no special status bits sets, either track, xtalk or random noise
+  //          (SiHelper::isClusterUsed(chDiode)) ); // cluster used - whatever that means - not set in digitization
+}
+
+inline bool SiHelper::isNoise(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & NOISE_SET);
+}
+
+inline bool SiHelper::isMaskOut(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & MASKOUT_SET);
+}
+
+inline bool SiHelper::isBelowThreshold(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & BT_SET);
+}
+    
+inline bool SiHelper::isDisabled(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & DISABLED_SET);
+}
+    
+inline bool SiHelper::isBadToT(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & BADTOT_SET);
+}
+
+inline bool SiHelper::isDisconnected(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & DISCONNECTED_SET);
+}
+
+inline bool SiHelper::isClusterUsed(SiChargedDiode& chDiode) {
+  return (chDiode.m_word & CLUSTERUSED_SET);
+}
+
+inline int SiHelper::GetBunch(SiChargedDiode& chDiode) {
+return ( (chDiode.m_word >> 8) & 0xff );
+}
+
+inline int SiHelper::GetStripNum(SiChargedDiode& chDiode) {
+  return ( (chDiode.m_word >> 16) & 0xfff );
+}
+
+inline int SiHelper::GetTimeBin(SiChargedDiode& chDiode) {
+return ( (chDiode.m_word >> 28) & 0xf );
+}    
+
+
+#endif
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..f88065cf62253c5a7a9441649d007307f94406b2
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/FaserSiDigitization/SiSurfaceCharge.h
@@ -0,0 +1,86 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiSurfaceCharge.h
+//   Header file for class SiSurfaceCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains a charge located at the sensor surface
+///////////////////////////////////////////////////////////////////
+// Version 1.0 09/02/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERSIDIGITIZATION_SISURFACECHARGE_H
+#define FASERSIDIGITIZATION_SISURFACECHARGE_H
+
+//#include "SiTrackerDetDescr/SiLocalPosition.h"
+#include "TrackerReadoutGeometry/SiLocalPosition.h"
+#include "TrackerSimEvent/SiCharge.h"
+
+
+class SiSurfaceCharge {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Copy constructor:
+  SiSurfaceCharge(const SiSurfaceCharge &surfaceCharge);
+
+  // Constructor with parameters:
+  //   position at the sensor surface
+  //   charge located at this position
+  SiSurfaceCharge(const TrackerDD::SiLocalPosition &position,const SiCharge &charge);
+
+  // Destructor:
+  ~SiSurfaceCharge();
+
+  // Assignment operator:
+  SiSurfaceCharge &operator=(const SiSurfaceCharge &surfaceCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // position at the sensor surface:
+  TrackerDD::SiLocalPosition position() const;
+
+  // charge located at this position:
+  SiCharge charge() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiSurfaceCharge();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  TrackerDD::SiLocalPosition m_position; // position at the sensor surface
+  SiCharge m_charge; // charge located at this position
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiSurfaceCharge::~SiSurfaceCharge() 
+{}
+
+inline TrackerDD::SiLocalPosition SiSurfaceCharge::position() const
+{
+  return m_position;
+}
+
+inline SiCharge SiSurfaceCharge::charge() const
+{
+  return m_charge;
+}
+
+#endif // FASERSIDIGITIZATION_SISURFACECHARGE_H
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..622090839b51c6e19b1c04eeb5917b1509810b14
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiode.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiChargedDiode.cxx
+//   Implementation file for class SiChargedDiode
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 2.1 09/06/2001 David Calvet
+// Davide Costanzo. Revisited version. 04-03-03
+///////////////////////////////////////////////////////////////////
+
+#include "FaserSiDigitization/SiChargedDiode.h"
+
+
+// Constructor with parameters:
+SiChargedDiode::SiChargedDiode(const SiTotalCharge::alloc_t& alloc,
+                               const TrackerDD::SiCellId & diode, const TrackerDD::SiReadoutCellId & roCell,  int flagword, SiChargedDiode * nextInCluster) 
+  :  m_diode(diode),
+     m_totalCharge(alloc),
+     m_readoutCell(roCell),
+     m_word(flagword),
+     m_nextInCluster(nextInCluster)
+{}
+
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiChargedDiode &chargedDiode)
+{
+  out << "Diode=" << chargedDiode.diode()
+      << " " << chargedDiode.totalCharge();
+  return out;
+}
+
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..82ae6cb5562854c2225d8e89832128f70dd14b88
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiChargedDiodeCollection.cxx
@@ -0,0 +1,161 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// sichargeddiodecollection.cxx
+//   Implementation file for class SiChargedDiodeCollection
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 3.0 09/07/2001 David Calvet
+// 04-03-03 Revisited version. Davide Costanzo
+///////////////////////////////////////////////////////////////////
+// header file
+#include "FaserSiDigitization/SiChargedDiodeCollection.h"
+// member classes
+#include "FaserSiDigitization/SiHelper.h"
+#include "TrackerReadoutGeometry/SiDetectorDesign.h"
+#include "TrackerReadoutGeometry/SiReadoutCellId.h"
+#include "TrackerReadoutGeometry/SiCellId.h"
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/getMessageSvc.h"
+
+using namespace TrackerDD;
+
+
+
+SiChargedDiodeCollection::SiChargedDiodeCollection( ) :
+  m_chargedDiodes(),
+  m_sielement()
+{
+}
+
+SiChargedDiodeCollection::SiChargedDiodeCollection(const TrackerDD::SiDetectorElement* sielement ) :
+  m_chargedDiodes(),
+  m_sielement(sielement)
+{
+}
+
+
+SiChargedDiodeCollection::~SiChargedDiodeCollection()
+{
+}
+
+// Clean up the collection
+void SiChargedDiodeCollection::clear() {
+  m_sielement = 0;
+  m_chargedDiodes.erase(m_chargedDiodes.begin(), m_chargedDiodes.end() );
+  m_orderedChargedDiodes.clear();
+}
+
+// Add a new SiCharge to the collection 
+void SiChargedDiodeCollection::add(const SiCellId & diode,
+				   const SiCharge & charge)
+{
+  // check the pointer is correct
+  if (!diode.isValid()) return;
+
+  // find this diode in the charged diode collection
+  // find it by id in the map. 
+  //
+
+  SiChargedDiodeIterator the_diode = m_chargedDiodes.find(diode);
+
+  if(the_diode != m_chargedDiodes.end() ) {
+    // Add to existing charge
+    (*the_diode).second.add(charge);
+  } else {
+    // if the new diode has not been found in the collection
+    // get the read out cell from the design. 
+    //
+    SiReadoutCellId roCell=design().readoutIdOfCell(diode);
+    if (!roCell.isValid()) { // I don't think this can occur at this stage but cant hurt.
+      MsgStream log(Athena::getMessageSvc(),"SiChargedDiodeCollection");
+      log << MSG::FATAL << "Could not create SiReadoutCellId object !"<< endmsg;
+    }
+    // create a new charged diode
+    SiChargedDiode chargedDiode(m_allocator, diode,roCell);
+    // add the new charge to it
+    chargedDiode.add(charge);
+    if (charge.processType() == SiCharge::extraNoise) SiHelper::noise(chargedDiode,true);
+    // add the new charged diode to the charged diode collection
+    auto p = m_chargedDiodes.emplace(diode,chargedDiode);
+    if (!m_orderedChargedDiodes.empty()) {
+      m_orderedChargedDiodes.insert (&p.first->second);
+    }
+  }
+}
+
+// Add a new SiTotalCharge to the collection 
+void SiChargedDiodeCollection::add(const SiCellId & diode,
+				   const SiTotalCharge & totcharge)
+{
+  // check the pointer is correct
+  if (!diode.isValid()) return;
+
+  // find this diode in the charged diode collection
+  // find it by id in the map. 
+  //
+
+  SiChargedDiodeIterator the_diode = m_chargedDiodes.find(diode);
+
+  if(the_diode != m_chargedDiodes.end() ) {
+    // Add to existing charge
+    (*the_diode).second.add(totcharge);
+  } else {
+    // if the new diode has not been found in the collection
+    // get the read out cell from the design. 
+    //
+    SiReadoutCellId roCell=design().readoutIdOfCell(diode);
+    if (!roCell.isValid()) {  // I don't think this can occur at this stage but cant hurt.
+      MsgStream log(Athena::getMessageSvc(),"SiChargedDiodeCollection");
+      log << MSG::FATAL << "Could not create SiReadoutCellId object !"<< endmsg;
+    }
+    // create a new charged diode
+    SiChargedDiode chargedDiode(m_allocator, diode,roCell);
+    // add the new charge to it
+    chargedDiode.add(totcharge);
+    // add the new charged diode to the charged diode collection
+    auto p = m_chargedDiodes.emplace(diode,chargedDiode);
+    if (!m_orderedChargedDiodes.empty()) {
+      m_orderedChargedDiodes.insert (&p.first->second);
+    }
+  }
+}
+
+bool SiChargedDiodeCollection::AlreadyHit(const TrackerDD::SiCellId & siId) {
+  if(m_chargedDiodes.find(siId) == m_chargedDiodes.end() ) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool SiChargedDiodeCollection::AlreadyHit(const Identifier & id) {
+
+  const SiCellId cellId        = m_sielement->cellIdFromIdentifier(id);
+  return AlreadyHit(cellId);
+}
+
+SiChargedDiode * SiChargedDiodeCollection::find(const TrackerDD::SiCellId & siId) {
+  // get the compact Id to access the map
+  SiChargedDiodeIterator theEl = m_chargedDiodes.find(siId);
+  // if the diode exists return a pointer to it:
+  if (theEl == m_chargedDiodes.end() ) return NULL;
+  else return &( (*theEl).second);
+}		      
+
+SiChargedDiode * SiChargedDiodeCollection::find(Identifier siId) {
+
+  // Get the key for the map lookup
+  const SiCellId cellId        = m_sielement->cellIdFromIdentifier(siId);
+  return find(cellId);
+}		      
+
+void SiChargedDiodeCollection::order()
+{
+  for (auto& p : m_chargedDiodes) {
+    m_orderedChargedDiodes.insert (&p.second);
+  }
+}
diff --git a/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b1d5215f5c9a9d9d1f647eb41a0c47a6613d4fed
--- /dev/null
+++ b/Tracker/TrackerDigitization/FaserSiDigitization/src/SiSurfaceCharge.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiSurfaceCharge.cxx
+//   Implementation file for class SiSurfaceCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.0 01/02/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "FaserSiDigitization/SiSurfaceCharge.h"
+using namespace TrackerDD;
+// Copy constructor:
+SiSurfaceCharge::SiSurfaceCharge(const SiSurfaceCharge &surfaceCharge) :
+  m_position(surfaceCharge.m_position),
+  m_charge(surfaceCharge.m_charge)
+{}
+
+// Constructor with parameters:
+SiSurfaceCharge::SiSurfaceCharge(const SiLocalPosition &position,
+				 const SiCharge &charge) :
+  m_position(position),
+  m_charge(charge)
+{}
+
+// Assignment operator:
+SiSurfaceCharge &SiSurfaceCharge::operator=(const SiSurfaceCharge &surfaceCharge)
+{
+  if (this!=&surfaceCharge) {
+    m_position=surfaceCharge.m_position;
+    m_charge=surfaceCharge.m_charge;
+  } else {}
+  return *this;
+}
+
diff --git a/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h b/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..81365d2fc68908e1b002e4f1dbcb0febe080c68e
--- /dev/null
+++ b/Tracker/TrackerSimEvent/TrackerSimEvent/SiCharge.h
@@ -0,0 +1,135 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCharge.h
+//   Header file for class SiCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains the bare charge deposited by a single process
+///////////////////////////////////////////////////////////////////
+// Version 1.4 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef SITRACKEREVENT_SICHARGE_H
+#define SITRACKEREVENT_SICHARGE_H
+
+#include <iostream>
+
+// Member classes
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+class SiCharge {
+
+public:
+  enum Process {no,track,diodeX_Talk,cellX_Talk,noise,extraNoise,cut_track};
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  // Copy constructor:
+  SiCharge(const SiCharge &charge);
+
+  // Constructor with parameters:
+  //   deposited charge
+  //   time of deposition
+  //   type of process which produced this charge
+  //   Particle Link to the particle generating the Charge
+  SiCharge(const double& charge,const double& time,
+	   const Process& processType,const HepMcParticleLink& PL);
+
+  SiCharge(const double& charge,const double& time,
+	   const Process& processType);
+
+  // Destructor:
+  ~SiCharge();
+
+  // Assignment operator:
+  SiCharge &operator=(const SiCharge &charge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // deposited charge:
+  double charge() const;
+
+  // time of deposition:
+  double time() const;
+
+  // type of process which produced this charge:
+  Process processType() const;
+
+  // Barcode of the particle generating the charge:
+  int trackBarcode() const;
+
+  // Particle Link of the particle generating the charge
+  const HepMcParticleLink& particleLink() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another charge, if the process and track are the same:
+  //   returns true if the charge was added
+  bool add(const SiCharge &charge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  SiCharge();
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  double m_charge; // deposited charge
+  double m_time; // time of deposition
+  Process m_processType; // type of process which produced this charge
+  //  int m_trackNumber; // track number in case of track process
+  HepMcParticleLink m_partLink; //Replace the track number with a PL
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiCharge::~SiCharge() 
+{}
+
+inline double SiCharge::charge() const 
+{
+  return m_charge;
+}
+
+inline double SiCharge::time() const 
+{
+  return m_time;
+}
+
+inline SiCharge::Process SiCharge::processType() const 
+{
+  return m_processType;
+}
+
+inline int SiCharge::trackBarcode() const 
+{
+  return m_partLink.barcode();
+}
+
+inline const HepMcParticleLink& SiCharge::particleLink() const 
+{
+  return m_partLink;
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiCharge &charge);
+
+#endif // SITRACKEREVENT_SICHARGE_H
diff --git a/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h b/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h
new file mode 100644
index 0000000000000000000000000000000000000000..dec3f37333cea86d234560835b884200e1655806
--- /dev/null
+++ b/Tracker/TrackerSimEvent/TrackerSimEvent/SiTotalCharge.h
@@ -0,0 +1,176 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiTotalCharge.h
+//   Header file for class SiTotalCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Class which contains the sum and the composition of all bare charges
+// corresponding to a single element
+///////////////////////////////////////////////////////////////////
+// Version 1.5 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#ifndef SITRACKEREVENT_SITOTALCHARGE_H
+#define SITRACKEREVENT_SITOTALCHARGE_H
+
+#include <list>
+#include "TrackerSimEvent/SiCharge.h"
+#include "AthAllocators/ArenaSharedHeapSTLAllocator.h"
+
+class SiTotalCharge {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+public:
+
+  typedef SG::ArenaSharedHeapSTLAllocator<SiCharge> alloc_t;
+  typedef std::list<SiCharge, alloc_t> list_t;
+
+  // Implicit constructor:
+  SiTotalCharge(const alloc_t& alloc);
+
+  // Copy constructor:
+  SiTotalCharge(const SiTotalCharge &totalCharge);
+
+  // Destructor:
+  ~SiTotalCharge();
+
+  // Assignment operator:
+  SiTotalCharge &operator=(const SiTotalCharge &totalCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // total deposited charge in this element:
+  double charge() const;
+
+  // list of individual charges:
+  const list_t &chargeComposition() const;
+
+  // return true if the charge composition contains more than one charge:
+  bool complexCharge() const;
+
+  // return true if the main charge comes from a track (track/diodeX_Talk):
+  bool fromTrack() const;
+
+  // return true if the main charge is extraNoise:
+  bool extraNoise() const;
+
+  // return the barcode of the main charge:
+  int trackBarcode() const;
+
+  // returns the HepMcParticleLink of the main charge
+  const HepMcParticleLink& particleLink() const;
+
+  // return the time of the main charge
+  double time() const;
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // add another SiCharge:
+  void add(const SiCharge &charge);
+
+  // add another SiTotalCharge:
+  void add(const SiTotalCharge &totalCharge);
+
+  // remove time information of the SiCharge objects:
+  void removeTimeInformation();
+
+  // remove small SiCharge objects:
+  //   minimum charge allowed to keep a SiCharge in the composition list
+  void removeSmallCharges(const double minimumCharge);
+
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+private:
+
+  // add another SiCharge to the charge composition (not the total value):
+  void addSiCharge(const SiCharge &charge);
+
+  // return the SiCharge corresponding to the process which deposited
+  // the biggest amount of charge (returns dummy charge if list is empty)
+  // (used to be a public method, but this caused problems if the list was empty):
+  const SiCharge& mainCharge() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+private:
+  double m_charge; // total deposited charge in this element
+  list_t m_chargeComposition; // list of individual charges
+  HepMcParticleLink m_emptyLink;
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiTotalCharge::~SiTotalCharge()
+{
+}
+
+inline double SiTotalCharge::charge() const 
+{
+  return m_charge;
+}
+
+inline const SiTotalCharge::list_t &SiTotalCharge::chargeComposition() const 
+{
+  return m_chargeComposition;
+}
+
+inline bool SiTotalCharge::complexCharge() const 
+{
+  return (m_chargeComposition.size()>1);
+}
+
+inline bool SiTotalCharge::extraNoise() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return false;
+    }
+  return (mainCharge().processType()==SiCharge::extraNoise);
+}
+
+inline int SiTotalCharge::trackBarcode() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return 0;
+    }
+  return mainCharge().trackBarcode();
+}
+
+inline double SiTotalCharge::time() const 
+{
+  if(m_chargeComposition.empty())
+    {
+      return 0.0;
+    }
+  return mainCharge().time();
+}
+
+inline const HepMcParticleLink& SiTotalCharge::particleLink() const
+{
+  if(m_chargeComposition.empty())
+    {
+      return m_emptyLink;
+    }
+  return mainCharge().particleLink();
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiTotalCharge &totalCharge);
+
+#endif // SITRACKEREVENT_SITOTALCHARGE_H
diff --git a/Tracker/TrackerSimEvent/src/SiCharge.cxx b/Tracker/TrackerSimEvent/src/SiCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f24f342adb044ab4f6c79708207efff3b7193f2b
--- /dev/null
+++ b/Tracker/TrackerSimEvent/src/SiCharge.cxx
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCharge.cxx
+//   Implementation file for class SiCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.4 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "TrackerSimEvent/SiCharge.h"
+
+// Copy constructor:
+SiCharge::SiCharge(const SiCharge &charge) :
+  m_charge(charge.m_charge),
+  m_time(charge.m_time),
+  m_processType(charge.m_processType),
+  m_partLink(charge.m_partLink)
+{}
+
+// Constructor with parameters:
+SiCharge::SiCharge(const double& charge,const double& time,
+		   const Process& processType,const HepMcParticleLink& PL) :
+  m_charge(charge),
+  m_time(time),
+  m_processType(processType),
+  m_partLink(PL)
+{}
+
+SiCharge::SiCharge(const double& charge,const double& time,
+		   const Process& processType) :
+  m_charge(charge),
+  m_time(time),
+  m_processType(processType),
+  m_partLink(HepMcParticleLink((unsigned int) 0, 0))
+{}
+
+
+// Assignment operator:
+SiCharge &SiCharge::operator=(const SiCharge &charge)
+{
+  if (this!=&charge) {
+    m_charge=charge.m_charge;
+    m_time=charge.m_time;
+    m_processType=charge.m_processType;
+    m_partLink=charge.m_partLink;
+  } else {}
+  return *this;
+}
+
+// add another charge, if the process and track are the same:
+bool SiCharge::add(const SiCharge &charge)
+{
+  // check if the two charges are compatible
+  if (charge.m_processType!=m_processType || 
+      charge.m_partLink!=m_partLink ||
+      charge.m_time!=m_time) {
+    return false;
+  } else {
+    m_charge+=charge.m_charge;
+    return true;
+  }
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiCharge &charge)
+{
+  out << "Charge=" << charge.charge() << " Time=" << charge.time()
+      << " Process=";
+  if (charge.processType()==SiCharge::no) out << "no";
+  else if (charge.processType()==SiCharge::track) out << "track";
+  else if (charge.processType()==SiCharge::diodeX_Talk) out << "diodeX_Talk";
+  else if (charge.processType()==SiCharge::cellX_Talk) out << "cellX_Talk";
+  else if (charge.processType()==SiCharge::noise) out << "noise";
+  else if (charge.processType()==SiCharge::extraNoise) out << "extraNoise";
+  else if (charge.processType()==SiCharge::cut_track) out << "cut_track";
+  else out << "UNKNOWN !";
+  return (out << " Barcode=" << charge.trackBarcode());
+}
+
diff --git a/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx b/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2d17b4d1144e899f7d098bb3657f2d27ab669b98
--- /dev/null
+++ b/Tracker/TrackerSimEvent/src/SiTotalCharge.cxx
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiTotalCharge.cxx
+//   Implementation file for class SiTotalCharge
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.5 08/06/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "TrackerSimEvent/SiTotalCharge.h"
+#include <iterator>
+
+// Implicit constructor:
+SiTotalCharge::SiTotalCharge(const alloc_t& alloc) :
+  m_charge(0),
+  m_chargeComposition(alloc),
+  m_emptyLink((unsigned int) 0, 0)
+{}
+
+// Copy constructor:
+SiTotalCharge::SiTotalCharge(const SiTotalCharge &totalCharge) :
+  m_charge(totalCharge.m_charge),
+  m_chargeComposition(totalCharge.m_chargeComposition),
+  m_emptyLink((unsigned int) 0, 0)
+{}
+
+// Assignment operator:
+SiTotalCharge &SiTotalCharge::operator=(const SiTotalCharge &totalCharge)
+{
+  if (this!=&totalCharge) {
+    m_charge=totalCharge.m_charge;
+    m_chargeComposition=totalCharge.m_chargeComposition;
+    m_emptyLink=totalCharge.m_emptyLink;
+  } else {}
+  return *this;
+}
+
+// give main single process charge:
+const SiCharge& SiTotalCharge::mainCharge() const
+{
+  // start with the first charge
+  list_t::const_iterator p_charge=m_chargeComposition.begin();
+
+  // main charge to be determined, initialized to the first one
+  list_t::const_iterator main_charge = p_charge;
+  ++p_charge;
+  // look for the biggest amount of charge in the remaining charges
+  for( ; p_charge!=m_chargeComposition.end() ; ++p_charge) {
+    if (p_charge->charge()>main_charge->charge()) main_charge=p_charge;
+  }
+  return *main_charge;
+}
+
+bool SiTotalCharge::fromTrack() const 
+{
+  if(m_chargeComposition.size()==0)
+    {
+      return false;
+    }
+  SiCharge::Process process=mainCharge().processType();
+  return (process==SiCharge::track || 
+	  process==SiCharge::cut_track || 
+	  process==SiCharge::diodeX_Talk);
+}
+
+// add another charge:
+void SiTotalCharge::add(const SiCharge &charge)
+{
+  // increase the total deposited charge
+  m_charge+=charge.charge();
+
+  // add the SiCharge to the list of charges
+  addSiCharge(charge);
+}
+
+// add another total charge:
+void SiTotalCharge::add(const SiTotalCharge &totalCharge)
+{
+  // increase the total deposited charge
+  m_charge+=totalCharge.charge();
+
+  // add the new list of charges to the present list of charges
+  for(list_t::const_iterator p_charge=
+	totalCharge.chargeComposition().begin() ;
+      p_charge!=totalCharge.chargeComposition().end() ; ++p_charge) {
+    addSiCharge(*p_charge);
+  }
+}
+
+// remove time information of the SiCharge objects:
+void SiTotalCharge::removeTimeInformation()
+{
+  // save the old charge composition
+  list_t oldComposition;
+  m_chargeComposition.swap(oldComposition);
+
+  // loop on all old charges
+  for(list_t::const_iterator p_charge=oldComposition.begin() ;
+      p_charge!=oldComposition.end() ; ++p_charge) {
+    // add the old charge (without time) to the list
+    addSiCharge(SiCharge(p_charge->charge(),0,
+			 p_charge->processType(),p_charge->particleLink()));
+  }
+}
+
+// remove small SiCharge objects:
+void SiTotalCharge::removeSmallCharges(const double minimumCharge)
+{
+  // loop on all charges
+  for(list_t::iterator p_charge=m_chargeComposition.begin() ;
+      p_charge!=m_chargeComposition.end() ; ) { 
+    // !!! p_charge is changed in the loop !!!
+
+    // if the charge is too small remove it from list
+    if (p_charge->charge()>-minimumCharge && 
+	p_charge->charge()<minimumCharge) {
+      p_charge=m_chargeComposition.erase(p_charge);
+    } else {
+      ++p_charge;
+    }
+  }
+}
+
+// add another SiCharge to the charge composition (not the total value):
+void SiTotalCharge::addSiCharge(const SiCharge &charge)
+{
+  // try to merge the SiCharge in the list of existing charges
+  for(list_t::iterator p_charge=m_chargeComposition.begin() ;
+      p_charge!=m_chargeComposition.end() ; ++p_charge) {
+    if (p_charge->add(charge)) return;
+  }
+  // add the charge to the list if not merged in existing one
+  m_chargeComposition.push_back(charge);
+}
+
+///////////////////////////////////////////////////////////////////
+// Input/Output stream functions:
+///////////////////////////////////////////////////////////////////
+std::ostream &operator<<(std::ostream &out,const SiTotalCharge &totalCharge)
+{
+  out << "Total charge=" << totalCharge.charge() 
+      << " Composition:" << std::endl;
+  copy(totalCharge.chargeComposition().begin(),
+       totalCharge.chargeComposition().end(),
+       std::ostream_iterator<SiCharge>(out,"\n"));
+  return out;
+}
+