diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eSuperCellTowerMapper.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eSuperCellTowerMapper.h
index 3f6e12a184e639d5d86b2204f39987c09f08c60a..a201461f1810839594e01db228aae4322ad398e8 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eSuperCellTowerMapper.h
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eSuperCellTowerMapper.h
@@ -45,7 +45,7 @@ class eSuperCellTowerMapper: public AthAlgTool, virtual public IeSuperCellTowerM
   SG::ReadHandleKey<xAOD::TriggerTowerContainer> m_triggerTowerCollectionSGKey {this, "xODTriggerTowers", "xAODTriggerTowers", "xAODTriggerTowers"};
 
   virtual int FindAndConnectTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov, bool doPrint) override;
-  virtual int ConnectSuperCellToTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) override;
+  virtual void ConnectSuperCellToTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) override;
   virtual int FindTowerIDForSuperCell(int towereta, int towerphi) override;
   virtual void PrintCellSpec(const CaloSampling::CaloSample sample, int layer, const int region, const int eta_index, const int phi_index, const int pos_neg, int iETower, int iCell, int prov, Identifier ID, bool doenergysplit) override;
 
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTower.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTower.h
index 4b9e0710b3b691af51f835c3f9f297d6de4c6281..a0777b7e0b86ecfb60d333d1e85dc94bb8f9a1d7 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTower.h
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTower.h
@@ -46,7 +46,7 @@ namespace LVL1 {
     eTower(float eta, float phi, int id_modifier, int posneg);
     
     /** Destructor */
-    virtual ~eTower();
+    virtual ~eTower() = default;
     
     /** Clear supercell ET values */
     void clearET();
@@ -61,8 +61,8 @@ namespace LVL1 {
     void recordMD_ET(float et, int cell);
 
     /** Get coordinates of tower */
-    int iEta();
-    int iPhi();
+    int iEta() const;
+    int iPhi() const;
     float eta() {return m_eta;};
     float phi() {return m_phi;};
     float eta() const {return m_eta;};
@@ -118,7 +118,7 @@ namespace LVL1 {
     std::vector<Identifier> getLayerSCIDs(unsigned int layer) const;
 
     /** Apply supercell noise cut **/
-    bool noiseCut(int et, int layer);
+    bool noiseCut(int et, int layer) const;
 
     void setPosNeg(int posneg);
 
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTowerBuilder.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTowerBuilder.h
index e8a0050c288d6122c8b965c854c215475ba6f153..d4960ac37e8e241bae0833f03abd9de5ffacac06 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTowerBuilder.h
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/eTowerBuilder.h
@@ -25,7 +25,7 @@ class eTowerBuilder: public AthAlgTool, virtual public IeTowerBuilder {
 
  public:
   eTowerBuilder(const std::string& type,const std::string& name,const IInterface* parent);
-  virtual ~eTowerBuilder();
+  virtual ~eTowerBuilder() = default;
 
   virtual void init(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
   virtual void execute(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
@@ -33,12 +33,12 @@ class eTowerBuilder: public AthAlgTool, virtual public IeTowerBuilder {
 
  private:
 
-  virtual void BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
-  virtual void BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
-  virtual void BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
-  virtual void BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
-  virtual void BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) override ;
-  virtual void BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainerRawRaw,float eta, float phi, float keybase, int posneg) override ;
+  virtual void BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const override ;
+  virtual void BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const override ;
+  virtual void BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const override ;
+  virtual void BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const override ;
+  virtual void BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const override ;
+  virtual void BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainerRawRaw,float eta, float phi, float keybase, int posneg) const override ;
 
 };
 
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXCompression.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXCompression.h
new file mode 100644
index 0000000000000000000000000000000000000000..2be7f14681cb6ce620cf99b57ee6165eb65dd3bf
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXCompression.h
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+/***************************************************************************
+                          jFEXCompression.h  -  description
+                             -------------------
+    begin                : 07-02-2019 
+    email                : Alan.Watson@cern.ch antonio.jacques.costa@cern.ch
+ ***************************************************************************/
+
+                                                                                
+ #ifndef jFEXCompression_H
+ #define jFEXCompression_H
+                                                                                
+#include <array>
+
+namespace LVL1 {
+
+/**
+LAr supercell data are received by the jFEX in a 10-bit multi-linear encoded form.
+This simple utility class contains 3 functions:
+  - Compress:  encodes a signed integer MeV value
+  - Expand:    decodes a 10 bit unsigned int into a signed integer MeV value
+  - Threshold: applies a threshold (in MeV) to the compressed code, zeroing if below
+  - Linearize: decodes a 10 bit unsigned int into the unsigned 16 bit jFEX ET with
+               least count of 25 MeV. A user-defined threshold (in MeV) can be 
+               applied, but as the jFEX ET is positive a negative threshold is
+               equivalent to a threshold of 0.
+  */
+class jFEXCompression {
+
+public: 
+  /** Compress data */
+  static unsigned int Compress(int Et);
+  /** Uncompress data */
+  static int Expand(unsigned int code);
+  /** Apply threshold to compressed data */
+  static unsigned int Threshold(unsigned int code, int threshold = -800);
+  /** Linearize LAr code to jFEX internal format */
+  static unsigned int Linearize(unsigned int code, int threshold = 0);
+ 
+private: 
+  /** Maximum ET value that can be encoded */
+  static const int s_maxET = 1019200;
+  /** Number of ranges */
+  static const unsigned int s_nRanges = 6;
+  /** Step sizes in each range, MeV */
+  static const int s_steps[s_nRanges];
+  /** Minimum ET values in each range, MeV */
+  static const int s_minET[s_nRanges];
+  /** Minimum code value in each range */
+  static const int s_minCode[s_nRanges];
+  /** Indicates no data present */
+  static const int s_NoData = 0;
+  /** LAr underflow code */
+  static const unsigned int s_LArUnderflow = 1;
+  /** LAr overflow code */
+  static const unsigned int s_LArOverflow  = 1020;
+  /** Reserved code value */
+  static const unsigned int s_LArReserved  = 1021;
+  /** Invalid code value */
+  static const unsigned int s_LArInvalid   = 1022;
+  /** LAr saturated code */
+  static const unsigned int s_LArSaturated = 1023;
+  /** Maximum code value */
+  static const unsigned int s_LArMaxCode   = 1023;
+  /** L1Calo ET digit step */
+  static const unsigned int s_jFEXstep     = 25;
+  /** L1Calo saturated/overflow */
+  static const unsigned int s_jFEXOverflow = 0xffff;
+  /** Error return value */
+  static const int s_error = -999;
+};
+
+
+}//end of ns
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXDriver.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXDriver.h
new file mode 100644
index 0000000000000000000000000000000000000000..915cb1fea83778ccba12cfb5f40257f9aba7e695
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXDriver.h
@@ -0,0 +1,58 @@
+#ifndef JFEXDRIVER_H
+#define JFEXDRIVER_H
+
+// STL
+#include <string>
+
+// Athena/Gaudi
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "L1CaloFEXSim/jTowerBuilder.h"
+#include "L1CaloFEXSim/jSuperCellTowerMapper.h"
+#include "L1CaloFEXToolInterfaces/IjFEXSysSim.h"
+#include "L1CaloFEXSim/jFEXSim.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+//#include "L1CaloFEXSim/jFEXOutputCollection.h"
+
+class CaloIdManager;
+
+namespace LVL1 {
+
+class jFEXDriver : public AthAlgorithm
+{
+ public:
+  //using AthReentrantAlgorithm::AthReentrantAlgorithm;
+
+  jFEXDriver(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual ~jFEXDriver();
+
+  virtual StatusCode initialize();
+  virtual StatusCode execute(/*const EventContext& ctx*/);// const;
+  StatusCode finalize();
+
+ private:
+
+  int m_numberOfEvents = 0;
+
+  SG::WriteHandleKey<LVL1::jTowerContainer> m_jTowerContainerSGKey {this, "MyETowers", "jTowerContainer", "MyETowers"};
+
+  //SG::WriteHandleKey<jFEXOutputCollection> m_jFEXOutputCollectionSGKey {this, "MyOutputs", "jFEXOutputCollection", "MyOutputs"};
+
+  SG::ReadHandleKey<CaloCellContainer> m_scellsCollectionSGKey {this, "SCell", "SCell", "SCell"};
+
+  ToolHandle<IjTowerBuilder> m_jTowerBuilderTool {this, "jTowerBuilderTool", "LVL1::jTowerBuilder", "Tool that builds jTowers for simulation"};
+  ToolHandle<IjSuperCellTowerMapper> m_jSuperCellTowerMapperTool {this, "jSuperCellTowerMapperTool", "LVL1::jSuperCellTowerMapper", "Tool that maps supercells to jTowers"};
+  ToolHandle<IjFEXSysSim> m_jFEXSysSimTool {this, "jFEXSysSimTool", "LVL1::jFEXSysSim", "Tool that creates the jFEX System Simulation"};
+
+  std::map<Identifier, std::pair<int,int> > m_cell_to_tower_map;
+
+};
+
+} // end of LVL1 namespace
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXFPGA.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXFPGA.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dc46a77f34e90fe398df89ccb122d604d592bc2
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXFPGA.h
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXFPGA.h  -  
+//                              -------------------
+//     begin                : 15 10 2019
+//     email                : jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+
+#ifndef jFEXFPGA_H
+#define jFEXFPGA_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "L1CaloFEXToolInterfaces/IjFEXFPGA.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+//#include "L1CaloFEXToolInterfaces/IjFEXtauAlgo.h"
+//#include "L1CaloFEXToolInterfaces/IjFEXegAlgo.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+//#include "L1CaloFEXSim/jFEXOutputCollection.h"
+
+namespace LVL1 {
+  
+  //Doxygen class description below:
+  /** The jFEXFPGA class defines the structure of a single jFEX FPGA
+      Its purpose is:
+      - to emulate the steps taken in processing data for a single jFEX FPGA in hardware and firmware
+      - It will need to interact with jTowers and produce the eTOBs.  It will be created and handed data by jFEXSim
+  */
+  
+  class jFEXFPGA : public AthAlgTool, virtual public IjFEXFPGA {
+    
+  public:
+    /** Constructors */
+    jFEXFPGA(const std::string& type,const std::string& name,const IInterface* parent);
+
+    /** standard Athena-Algorithm method */
+    virtual StatusCode initialize() override;
+    /** Destructor */
+    virtual ~jFEXFPGA();
+
+    virtual StatusCode init(int id, int efexid) override ;
+
+    virtual StatusCode execute() override ;
+
+    virtual void reset() override ;
+
+    virtual int ID() override {return m_id;}
+
+    virtual void SetTowersAndCells_SG( int [][9] ) override ;
+    virtual void SetTowersAndCells_SG( int [][8] ) override ;
+
+    /** Internal data */
+  private:
+
+    int m_id;
+    int m_jfexid;
+
+    int m_jTowersIDs_Wide [16][9];
+    int m_jTowersIDs_Thin [16][8];
+    std::map<int,jTower> m_jTowersColl;
+
+    CaloCellContainer m_sCellsCollection;
+
+    SG::ReadHandleKey<LVL1::jTowerContainer> m_jFEXFPGA_jTowerContainerKey {this, "MyETowers", "jTowerContainer", "Input container for jTowers"};
+
+    //SG::ReadHandleKey<jFEXOutputCollection> m_jFEXFPGA_jFEXOutputCollectionKey {this, "MyOutputs", "jFEXOutputCollection", "Input container for jFEXOutputCollection"};
+
+    //ToolHandle<IjFEXtauAlgo> m_jFEXtauAlgoTool {this, "jFEXtauAlgoTool", "LVL1::jFEXtauAlgo", "Tool that runs the jFEX tau algorithm"};
+    //ToolHandle<IjFEXegAlgo> m_jFEXegAlgoTool {this, "jFEXegAlgoTool", "LVL1::jFEXegAlgo", "Tool that runs the jFEX e/gamma algorithm"};
+    
+  };
+  
+} // end of namespace
+
+//CLASS_DEF( LVL1::jFEXFPGA , 136060357 , 1 )
+
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSim.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSim.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c79fb57d6a8b0af7fae111488c29c76adb9fdb4
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSim.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSim.h  -  
+//                              -------------------
+//     begin                : 22 08 2019
+//     email                : jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+
+#ifndef jFEXSim_H
+#define jFEXSim_H
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "L1CaloFEXToolInterfaces/IjFEXSim.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jFEXFPGA.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+namespace LVL1 {
+  
+  //Doxygen class description below:
+  /** The jFEXSim class defines the structure of a single jFEX
+      Its purpose is:
+      - to emulate the steps taken in processing data for a single jFEX in hardware and firmware
+      - It will need to interact with jTowers and produce the eTOBs.  It will be created and handed data by jFEXSysSim
+  */
+  
+  class jFEXSim : public AthAlgTool, virtual public IjFEXSim {
+    
+  public:
+
+    /** Constructors */
+    jFEXSim(const std::string& type,const std::string& name,const IInterface* parent);
+
+    /** Destructor */
+    virtual ~jFEXSim();
+
+    /** standard Athena-Algorithm method */
+    virtual StatusCode initialize() override;
+    /** standard Athena-Algorithm method */
+    virtual StatusCode finalize  () override;
+
+    virtual void init (int id) override ;
+
+    virtual void reset () override ;
+
+    virtual void execute() override ;
+
+    virtual int ID() override {return m_id;}
+    
+    virtual void SetTowersAndCells_SG(int tmp[16][9]) override;
+    virtual void SetTowersAndCells_SG(int tmp[16][8]) override;
+
+    virtual StatusCode NewExecute(int tmp[16*4][9]) override;
+    virtual StatusCode NewExecute(int tmp[16*4][8]) override;
+
+    /** Internal data */
+  private:
+
+    int m_id;
+
+    int m_jTowersIDs_Wide [16*4][9];
+    int m_jTowersIDs_Thin [16*4][8];
+
+    std::map<int,jTower> m_jTowersColl;
+    CaloCellContainer m_sCellsCollection;
+    std::vector<jFEXFPGA*> m_jFEXFPGACollection;
+
+    ToolHandle<IjFEXFPGA> m_jFEXFPGATool {this, "jFEXFPGATool", "LVL1::jFEXFPGA", "Tool that simulates the FPGA hardware"};
+
+    
+  };
+  
+} // end of namespace
+
+//CLASS_DEF( LVL1::jFEXSim , 246128035 , 1 )
+
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSysSim.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSysSim.h
new file mode 100644
index 0000000000000000000000000000000000000000..5426e0d1627e5a38ea566295cb35b1d8d1a328f0
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jFEXSysSim.h
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSysSim.h  -  
+//                              -------------------
+//     begin                : 12 07 2019
+//     email                : alison.elliot@cern.ch, jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+
+#ifndef jFEXSysSim_H
+#define jFEXSysSim_H
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "L1CaloFEXToolInterfaces/IjFEXSysSim.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "L1CaloFEXSim/jFEXSim.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+namespace LVL1 {
+  
+  //Doxygen class description below:
+  /** The jFEXSysSim class defines the structure of the jFEX system
+      Its purpose is:
+      - to follow the structure of the 24 jFEXes and their FPGAs in as much
+      detail as necessary to simulate the output of the system
+      It will need to interact with jTowers and produce the eTOBs
+  */
+
+  class jFEXSysSim : public AthAlgTool, virtual public IjFEXSysSim {
+    
+  public:
+    
+    /** Constructors */
+
+    jFEXSysSim(const std::string& type,const std::string& name,const IInterface* parent);
+    /** Destructor */
+    jFEXSysSim&& operator= (const jFEXSysSim& ) = delete;
+
+    /** standard Athena-Algorithm method */
+    virtual StatusCode initialize() override;
+    /** standard Athena-Algorithm method */
+    virtual StatusCode finalize  () override;
+
+    virtual StatusCode execute() override ;
+
+    virtual void init() override ;
+
+    virtual void cleanup() override;
+
+    virtual int calcTowerID(int eta, int phi, int mod) override ;
+
+    /** Internal data */
+  private:
+
+    std::vector<jFEXSim*>  m_jFEXCollection;
+    
+    ToolHandle<IjFEXSim> m_jFEXSimTool       {this, "jFEXSimTool",    "LVL1::jFEXSim",    "Tool that creates the jFEX Simulation"};
+
+    SG::ReadHandleKey<LVL1::jTowerContainer> m_jTowerContainerSGKey {this, "MyETowers", "jTowerContainer", "Input container for jTowers"};
+    SG::ReadHandleKey<CaloCellContainer> m_scellsCollectionSGKey {this, "SCell", "SCell", "SCell"};
+
+    std::map<int,jTower> m_jTowersColl;
+    
+  };
+  
+} // end of namespace
+
+//CLASS_DEF( LVL1::jFEXSysSim , 141823245 , 1 )
+
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jSuperCellTowerMapper.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jSuperCellTowerMapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..40412e60fbda57ab65a4fedd33cc97282b29b5ff
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jSuperCellTowerMapper.h
@@ -0,0 +1,55 @@
+/*
+    Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#ifndef JSUPERCELLTOWERMAPPER_H
+#define JSUPERCELLTOWERMAPPER_H
+
+// STL
+#include <string>
+
+// Athena/Gaudi
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "L1CaloFEXToolInterfaces/IjSuperCellTowerMapper.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+
+class CaloIdManager;
+
+namespace LVL1 {
+
+
+class jSuperCellTowerMapper: public AthAlgTool, virtual public IjSuperCellTowerMapper
+{
+ public:
+  jSuperCellTowerMapper(const std::string& type,const std::string& name,const IInterface* parent);
+  virtual ~jSuperCellTowerMapper();
+
+  /** standard Athena-Algorithm method */
+  virtual StatusCode initialize() override;
+  
+  virtual StatusCode AssignSuperCellsToTowers(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw) override;
+  virtual StatusCode AssignTriggerTowerMapper(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw) override;
+  
+  virtual void reset() override;
+
+ private:
+
+  SG::ReadHandleKey<CaloCellContainer> m_scellsCollectionSGKey {this, "SCell", "SCell", "SCell"};
+  SG::ReadHandleKey<xAOD::TriggerTowerContainer> m_triggerTowerCollectionSGKey {this, "xODTriggerTowers", "xAODTriggerTowers", "xAODTriggerTowers"};
+
+  virtual int FindAndConnectTower(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov, bool doPrint) override;
+  virtual void ConnectSuperCellToTower(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) override;
+  virtual int FindTowerIDForSuperCell(int towereta, int towerphi) override;
+  virtual void PrintCellSpec(const CaloSampling::CaloSample sample, int layer, const int region, const int eta_index, const int phi_index, const int pos_neg, int iETower, int iCell, int prov, Identifier ID, bool doenergysplit) override;
+
+};
+
+} // end of LVL1 namespace
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTower.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTower.h
new file mode 100644
index 0000000000000000000000000000000000000000..77577e2e3945e3ec209dcc95cc1fcbdea8f13374
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTower.h
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jTower.h  -  description
+//                              -------------------
+//     begin                : 19 02 2019
+//     email                : Alan.Watson@cern.ch, jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+
+#ifndef jTower_H
+#define jTower_H
+
+#include <vector>
+#include "AthenaKernel/CLASS_DEF.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+#include "xAODBase/IParticle.h"
+#include "xAODCore/AuxStoreAccessorMacros.h"
+
+namespace LVL1 {
+  
+  //Doxygen class description below:
+  /** The jTower class is an interface object for jFEX trigger algorithms
+      The purposes are twofold:
+      - to provide inputs to the algorithms in a way that reflects the cell
+      structure within a tower (the basic element of an jFEX algorithm window)
+      - to hide the details of the individual data sources, e.g. which hadronic
+      cells are LAr and which are HEC, from the algorithms
+      It needs to contain supercell ET values and a tower coordinate or identifier
+      (not yet defined). ET values should be on the jFEX's internal ET scale, not MeV.
+      This should be a purely transient object, but will need to enter the transient
+      event store (so class_def etc will be needed before it can be used for real)
+  */
+  
+  class jTower {
+    
+  public:
+    
+    /** Constructors */
+    jTower();
+    jTower(float eta, float phi, int id_modifier, int posneg);
+    
+    /** Destructor */
+    virtual ~jTower() = default;
+
+    /** Clear supercell ET values */
+    void clearET();
+    
+    /** Clear and resize Identifier value vector */
+    void clear_EM_scIDs();
+    void clear_HAD_scIDs();
+
+    /** Add to ET of a specified cell in MeV */
+    void addET(float et, int cell);
+
+    /** Add to ET of a specified cell */
+    void recordMD_ET(float et, int cell);
+
+    /** Get coordinates of tower */
+    int iEta() const;
+    int iPhi() const;
+    float eta() {return m_eta;};
+    float phi() {return m_phi;};
+    float eta() const {return m_eta;};
+    float phi() const {return m_phi;};
+    
+    void setEta(const float thiseta){ m_eta = thiseta; }
+
+    int id() {return m_tower_id;};
+
+    int id() const {return m_tower_id;}
+
+    float constid() const {return m_tower_id;};
+
+    /** Get ET of a specified cell in MeV */
+    int getET(unsigned int layer, int cell = 0) const;
+    
+    /** Get ET sum of all cells in the jTower in MeV */
+    int getTotalET() const;
+
+    /** Get total ET sum of all cells in a given layer in MeV */
+    int getLayerTotalET(unsigned int layer) const;
+
+    /** Get vector of ET values for a given layer in MeV */
+    std::vector<int> getLayerETvec(unsigned int layer) const;
+    
+    /** Get vector of all ET values in MeV */
+    std::vector<int> getETs() const {return m_et;};
+
+    /** Get ET of a specified cell in MeV FLOAT VERSION */
+    float getET_float(unsigned int layer, int cell = 0) const;
+
+    /** Get ET sum of all cells in the jTower in MeV FLOAT VERSION */
+    float getTotalET_float() const;
+
+    /** Get total ET sum of all cells in a given layer in MeV FLOAT VERSION */
+    float getLayerTotalET_float(unsigned int layer) const;
+
+    /** Get vector of ET values for a given layer in MeV FLOAT VERSION */
+    std::vector<float> getLayerETvec_float(unsigned int layer) const;
+
+    /** Get vector of all ET values in MeV FLOAT VERSION */
+    std::vector<float> getETs_float() const {return m_et_float;};
+
+    void setET(int cell, float et, int layer);
+
+    /** Set supercell position ID **/
+    void setSCID(Identifier ID, int cell, float et, int layer, bool doenergysplit);
+
+    std::vector<Identifier> getEMSCIDs() const { return m_EM_scID; }
+    std::vector<Identifier> getHADSCIDs() const { return m_HAD_scID; }
+
+    Identifier getEMSCID(int cell) const { return m_EM_scID[cell]; }
+    Identifier getHADSCID(int cell) const { return m_HAD_scID[cell]; }
+
+    std::vector<Identifier> getLayerSCIDs(unsigned int layer) const;
+
+    /** Apply supercell noise cut **/
+    bool noiseCut(int et, int layer) const;
+
+    void setPosNeg(int posneg);
+
+    inline int getPosNeg() const {return m_posneg;}
+
+    /** Internal data */
+  private:
+    float m_eta;
+    float m_phi;
+    std::vector<Identifier> m_EM_scID;
+    std::vector<Identifier> m_HAD_scID;
+    std::vector<int> m_et;    
+    std::vector<float> m_et_float;
+    int m_tower_id;
+    int m_posneg = 0;
+    int m_noisecutPS = 100;
+    int m_noisecutL1 = 100;
+    int m_noisecutL2 = 100;
+    int m_noisecutL3 = 100;
+    int m_noisecutHad = 100;
+
+  };
+  
+} // end of namespace
+
+CLASS_DEF( LVL1::jTower , 41848655 , 1 )
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerBuilder.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerBuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..a78434ea13576c735a11a8f87b73ae8d684136a5
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerBuilder.h
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#ifndef JTOWERBUILDER_H
+#define JTOWERBUILDER_H
+
+// STL
+#include <string>
+
+// Athena/Gaudi
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "L1CaloFEXToolInterfaces/IjTowerBuilder.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+
+class CaloIdManager;
+
+namespace LVL1 {
+
+class jTowerBuilder: public AthAlgTool, virtual public IjTowerBuilder {
+
+ public:
+  jTowerBuilder(const std::string& type,const std::string& name,const IInterface* parent);
+  virtual ~jTowerBuilder() = default;
+
+  virtual void init(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) override ;
+  virtual void execute(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) override ;
+  virtual void reset() override ;
+
+ private:
+
+  virtual void BuildEMBjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildTRANSjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildEMEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildEMIEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildHECjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildAllTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const override ;
+  virtual void BuildSingleTower(std::unique_ptr<jTowerContainer> & jTowerContainerRawRaw,float eta, float phi, float keybase, int posneg) const override ;
+
+};
+
+} // end of LVL1 namespace
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerContainer.h b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..5437adcea501725175cd0ae508d052eea8bab07a
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/L1CaloFEXSim/jTowerContainer.h
@@ -0,0 +1,85 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Stolen shamelessly from CaloCellContainer.h and modified as required
+
+#ifndef JTOWERCONTAINER_H
+#define JTOWERCONTAINER_H
+
+/** 
+   @class jTowerContainer
+   @brief Container class for jTower
+
+   jTowerContainer is a container of all jFEX jTowers.
+   It derives from DataVector<jTower>.
+
+ */
+
+#include "AthContainers/DataVector.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "L1CaloFEXSim/jTower.h"
+
+#include "Identifier/IdentifierHash.h"
+#include "CxxUtils/PackedArray.h"
+#include "CxxUtils/CachedValue.h"
+#include "AthLinks/tools/findInContainer.h"
+
+namespace LVL1 {
+
+class jTowerContainer : public DataVector<LVL1::jTower>
+{
+
+ public:
+
+
+ /** @brief type to be used for the internal lookup table, and to return list of towers */
+  typedef std::vector<const LVL1::jTower> jTowerVector;
+  
+ /** @brief Return from non-const findTowerVector. */
+  typedef std::vector<LVL1::jTower> MutablejTowerVector;
+  
+  /** @brief Main constructor */
+  jTowerContainer(SG::OwnershipPolicy ownPolicy=SG::OWN_ELEMENTS ) ;
+  //jTowerContainer() ;
+
+  /** @brief Sized constructor */
+  jTowerContainer(size_t n, SG::OwnershipPolicy ownPolicy=SG::OWN_ELEMENTS );
+
+  /**  @brief destructor */  
+  virtual ~jTowerContainer() { };
+
+  /** @brief reimplementation of const push_back */
+  void push_back(float eta, float phi, float keybase, int posneg);
+
+  /** @brief utility function to help speed up accessing towers */
+  bool fillContainerMap();
+
+  /** @brief dump (obsolete) */
+  void print() const;
+
+  /** @brief fast find method given identifier. */ 
+  const LVL1::jTower * findTower(int towerID) const;
+  
+  /** @brief fast find method given identifier. */ 
+  LVL1::jTower * findTower(int towerID);
+
+  /** @brief clear map */
+  void clearContainerMap();
+
+ private:
+  /** @brief get message service */
+  IMessageSvc* msgSvc() const;
+
+  //* @brief Keeps track of the towerID of each jTower associated to each MAP index *.
+  std::map<int,int> m_map_towerID_containerIndex;
+};
+
+}
+CLASS_DEF( LVL1::jTowerContainer , 1141097037 , 1 )
+SG_BASE(LVL1::jTowerContainer, DataVector<LVL1::jTower> );
+
+#endif
+
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/python/jFEXDriverConfig.py b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/python/jFEXDriverConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..a28716c5bc0a19bedca95c33868594ba4bc60bab
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/python/jFEXDriverConfig.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+from L1CaloFEXSim.L1CaloFEXSimConf import LVL1__jFEXDriver
+
+class Run3jFEXDriver (LVL1__jFEXDriver):
+    __slots__ = []
+    def __init__(self, name):
+        print("GONDOR CALLS FOR MORE AID")
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/share/jFEXDriverJobOptions.py b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/share/jFEXDriverJobOptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbd95f60bd03d4ac62e5cce939f4e2e42e80e5e9
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/share/jFEXDriverJobOptions.py
@@ -0,0 +1,60 @@
+#jps.AthenaCommonFlags.AccessMode = "POOLAccess" # use POOL read mode because reading calocells
+#svcMgr.EventSelector.InputCollections = jps.AthenaCommonFlags.FilesInput()
+from AthenaCommon.GlobalFlags  import globalflags
+import AthenaPoolCnvSvc.ReadAthenaPool
+
+if type(theApp).__name__ == "fakeAppMgr": theApp.initialize() #this line cuts off pathena when joboption parsing ... since all outputs now declared
+
+#from RecExConfig import AutoConfiguration
+#AutoConfiguration.ConfigureSimulationOrRealData()
+#AutoConfiguration.ConfigureGeo()
+#AutoConfiguration.ConfigureConditionsTag()
+#from AthenaCommon.DetFlags import DetFlags
+#DetFlags.detdescr.all_setOff()
+#DetFlags.detdescr.Calo_setOn()
+#include("RecExCond/AllDet_detDescr.py")
+
+#include( "CaloConditions/CaloConditions_jobOptions.py" )
+include( "LArDetDescr/LArDetDescr_joboptions.py" )
+
+
+include( "RegistrationServices/IOVRegistrationSvc_jobOptions.py" )
+
+IOVBeginRun   = IOVRunNumberMin
+IOVEndRun     = IOVRunNumberMax
+IOVBeginLB = IOVLBNumberMin
+IOVEndLB   = IOVLBNumberMax
+
+import RegistrationServices.IOVRegistrationSvc
+regSvc = svcMgr.IOVRegistrationSvc
+
+
+#svcMgr.IOVDbSvc.DBInstance=""
+
+if "GlobalTag" not in dir():
+    GlobalTag     = 'OFLCOND-CSC-00-01-00' #Sadly event his doesn't work for the 14 TeV jetjet sample 'OFLCOND-MC15c-SDR-14-02' #This works for 13 TeV 'OFLCOND-CSC-00-01-00'    #No idea what this is: COMCOND-BLKPST-004-05'
+
+#svcMgr.IOVDbSvc.GlobalTag = GlobalTag
+
+svcMgr.IOVDbSvc.GlobalTag=globalflags.ConditionsTag()
+
+# configure detector description from metadata in input file
+from RecExConfig import AutoConfiguration
+AutoConfiguration.ConfigureSimulationOrRealData()
+AutoConfiguration.ConfigureGeo()
+AutoConfiguration.ConfigureConditionsTag()
+from AthenaCommon.DetFlags import DetFlags
+DetFlags.detdescr.all_setOff()
+DetFlags.detdescr.Calo_setOn()
+include("RecExCond/AllDet_detDescr.py")
+
+svcMgr += CfgMgr.THistSvc()
+#svcMgr.THistSvc.Output += ["ISO DATAFILE='tobIso.root' OPT='RECREATE'"]
+svcMgr.THistSvc.Output += ["ANALYSIS DATAFILE='myfile_jfex.root' OPT='RECREATE'"]
+#######################################################
+log.info("==========================================================")
+log.info("Scheduling jFEXDriver")
+athAlgSeq += CfgMgr.LVL1__jFEXDriver('MyjFEXDriver')
+#athAlgSeq += CfgMgr.LVL1__jFEXNtupleWriter('MyjFEXNtupleWriter')
+log.info("==========================================================")
+#######################################################
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/eFEXDriver_entries.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/FEXDriver_entries.cxx
similarity index 66%
rename from Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/eFEXDriver_entries.cxx
rename to Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/FEXDriver_entries.cxx
index 7be93248f17983beb88ef89375fd04a5807d21a8..54c03b62f05e7ac406c81a6d9247573eb7db7edc 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/eFEXDriver_entries.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/components/FEXDriver_entries.cxx
@@ -9,6 +9,10 @@
 #include "L1CaloFEXSim/eFEXtauAlgo.h"
 #include "L1CaloFEXSim/eFEXegAlgo.h"
 #include "L1CaloFEXSim/eFEXNtupleWriter.h"
+#include "L1CaloFEXSim/jFEXDriver.h"
+#include "L1CaloFEXSim/jFEXSysSim.h"
+#include "L1CaloFEXSim/jFEXSim.h"
+#include "L1CaloFEXSim/jFEXFPGA.h"
 
 using namespace LVL1;
 
@@ -21,3 +25,10 @@ DECLARE_COMPONENT(eFEXFPGA)
 DECLARE_COMPONENT(eFEXtauAlgo)
 DECLARE_COMPONENT(eFEXegAlgo)
 DECLARE_COMPONENT(eFEXNtupleWriter)
+
+DECLARE_COMPONENT(jFEXDriver)
+DECLARE_COMPONENT(jFEXSysSim)
+DECLARE_COMPONENT(jFEXSim)
+DECLARE_COMPONENT(jTowerBuilder)
+DECLARE_COMPONENT(jSuperCellTowerMapper)
+DECLARE_COMPONENT(jFEXFPGA)
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eFEXSim.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eFEXSim.cxx
index 0863dd16d569f6f78c19df343fb1b4ed164a8952..c99a2b9e51ee2a1aa49e76689789abd73685a6fe 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eFEXSim.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eFEXSim.cxx
@@ -47,10 +47,13 @@ namespace LVL1 {
   void eFEXSim::reset()
   {
 
+    int rows = sizeof m_eTowersIDs / sizeof m_eTowersIDs[0];
+    int cols = sizeof m_eTowersIDs[0] / sizeof m_eTowersIDs[0][0];
+
     m_id = -1;
     m_eFEXFPGACollection.clear();
-    for (int i=0; i<10; i++){
-      for (int j=0; j<18; j++){
+    for (int i=0; i<rows; i++){
+      for (int j=0; j<cols; j++){
 	  m_eTowersIDs[i][j] = 0;
 	}
     }
@@ -126,7 +129,7 @@ StatusCode eFEXSim::NewExecute(int tmp_eTowersIDs_subset[10][18]){
       tmp_eTowersIDs_subset_FPGA[myrow][mycol-12] = tmp_eTowersIDs_subset[myrow][mycol];
     }
   }
-  ATH_CHECK(m_eFEXFPGATool->init(0, m_id));
+  ATH_CHECK(m_eFEXFPGATool->init(3, m_id));
   m_eFEXFPGATool->SetTowersAndCells_SG(tmp_eTowersIDs_subset_FPGA);
   ATH_CHECK(m_eFEXFPGATool->execute());
   m_eFEXFPGATool->reset();
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eSuperCellTowerMapper.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eSuperCellTowerMapper.cxx
index 26f61e7fbe3e21237eb193a95edde59a808690ad..9c2c32490e02214e56e08a5d977287a084196d50 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eSuperCellTowerMapper.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eSuperCellTowerMapper.cxx
@@ -57,7 +57,9 @@ StatusCode eSuperCellTowerMapper::initialize()
     
 }
 
-StatusCode eSuperCellTowerMapper::AssignTriggerTowerMapper(/*eTowerContainer* my_eTowerContainerRaw*/ std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw){
+StatusCode eSuperCellTowerMapper::AssignTriggerTowerMapper(std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw){
+
+  static constexpr float pi_over_32 = std::acos(-1)/32;
   
   SG::ReadHandle<xAOD::TriggerTowerContainer> jk_triggerTowerCollection(m_triggerTowerCollectionSGKey/*,ctx*/);
   if(!jk_triggerTowerCollection.isValid()){
@@ -67,7 +69,7 @@ StatusCode eSuperCellTowerMapper::AssignTriggerTowerMapper(/*eTowerContainer* my
 
   for(auto eachTower : *jk_triggerTowerCollection) {
     if(fabs(eachTower->eta())<1.5 && eachTower->sampling()==1) {
-      int i_phi = int(eachTower->phi()/(3.14159/32));
+      int i_phi = int(eachTower->phi()/pi_over_32);
       int etaSign{-1};
       int towerID_Modifier{100000};
       if (eachTower->eta() > 0) {
@@ -87,7 +89,7 @@ StatusCode eSuperCellTowerMapper::AssignTriggerTowerMapper(/*eTowerContainer* my
         if (targetTower->getET_float(4, 0) > 0) {
           ATH_MSG_WARNING("\n==== eSuperCellTowerMapper ============ Hadronic layer energy filled more than once - it will be ignored. (Needs investigation).  Please report this!");
         }
-        targetTower->setET(10, int(eachTower->cpET()) * 0.5 * 1000., 4);
+        targetTower->setET(10, int(eachTower->cpET()) * 500., 4);  // cf 0.5 * 1000.0
       } else {
         ATH_MSG_WARNING("\n==== eSuperCellTowerMapper ============ Tower id is officially unknown - it will be ignored. (Needs investigation).  Please report this!");
       }
@@ -101,7 +103,7 @@ void eSuperCellTowerMapper::reset(){
 }
 
   // works for real supercells from MC
-  StatusCode eSuperCellTowerMapper::AssignSuperCellsToTowers(/*eTowerContainer* my_eTowerContainerRaw*/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw)
+  StatusCode eSuperCellTowerMapper::AssignSuperCellsToTowers(std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw)
 {
 
   bool doPrint = false;
@@ -117,16 +119,17 @@ void eSuperCellTowerMapper::reset(){
   const CaloCell_Base_ID* idHelper = nullptr;
   ATH_CHECK( detStore()->retrieve (idHelper, "CaloCell_SuperCell_ID") );
 
-  for (CaloCellContainer::const_iterator cell = jk_scellsCollection->begin(); cell != jk_scellsCollection->end(); ++cell){
-    const CaloSampling::CaloSample sample = (*cell)->caloDDE()->getSampling();
-    const Identifier ID = (*cell)->ID(); // super cell unique ID
+  for (const auto& cell : * jk_scellsCollection){
+
+    const CaloSampling::CaloSample sample = (cell)->caloDDE()->getSampling();
+    const Identifier ID = (cell)->ID(); // super cell unique ID
     int region = idHelper->region(ID);
     int layer = -1;
     int pos_neg = idHelper->pos_neg(ID);
     int eta_index = idHelper->eta(ID);
     const int phi_index = idHelper->phi(ID);
-    float et = (*cell)->energy();
-    int prov = (*cell)->provenance();
+    float et = (cell)->energy();
+    int prov = (cell)->provenance();
 
     /*
   CaloSampling:
@@ -193,17 +196,17 @@ void eSuperCellTowerMapper::reset(){
 }
 
 
-  int eSuperCellTowerMapper::ConnectSuperCellToTower(/*eTowerContainer* my_eTowerContainerRaw*/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit){
-
-  if(my_eTowerContainerRaw->findTower(iETower)){
-    (my_eTowerContainerRaw->findTower(iETower))->setSCID(ID,iCell,et,layer,doenergysplit);
+void eSuperCellTowerMapper::ConnectSuperCellToTower(std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit){
+    
+  LVL1::eTower * tmpTower = my_eTowerContainerRaw->findTower(iETower);
+  
+  if(tmpTower){
+    tmpTower->setSCID(ID,iCell,et,layer,doenergysplit);
   }
 
-  return 1;
-
 }
 
-  int eSuperCellTowerMapper::FindAndConnectTower(/*eTowerContainer* my_eTowerContainerRaw*/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov,bool doPrint)
+  int eSuperCellTowerMapper::FindAndConnectTower(std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov,bool doPrint)
 {
 
   // bool for the special case of 1.8 < eta < 2.0 only in the front layer
@@ -750,22 +753,20 @@ int eSuperCellTowerMapper::FindTowerIDForSuperCell(int towereta, int towerphi)
   }
   }
   
-  if(true){
-    ATH_MSG_DEBUG("ASSIGNED CELL:::  CASE: " << sampleName
-	      << "\tSample: " << sample
-	      << "\tLayer: " << layer
-	      << "\tRegion: " << region
-	      << "\tEta_Index: " << eta_index
-	      << "\tPhi_Index: " << phi_index
-	      << "\tPosNeg: " << pos_neg
-	      << "\tiETower: " << iETower
-	      << "\tiCell: " << iCell
-	      << "\tDoEnergySplit: " << doenergysplit
-	      << "\tProvenance: " << prov
-	      << "\tID: " << ID
-		  << " ");
-  }
-
+  ATH_MSG_DEBUG("ASSIGNED CELL:::  CASE: " << sampleName
+		<< "\tSample: " << sample
+		<< "\tLayer: " << layer
+		<< "\tRegion: " << region
+		<< "\tEta_Index: " << eta_index
+		<< "\tPhi_Index: " << phi_index
+		<< "\tPosNeg: " << pos_neg
+		<< "\tiETower: " << iETower
+		<< "\tiCell: " << iCell
+		<< "\tDoEnergySplit: " << doenergysplit
+		<< "\tProvenance: " << prov
+		<< "\tID: " << ID
+		<< " ");
+  
   return;
 }
 
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTower.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTower.cxx
index f104b748ff06fd0c0d24f069f16188afbd6696b6..59e00379e613827304fb7e48c2783a31c593f331 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTower.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTower.cxx
@@ -44,10 +44,6 @@ namespace LVL1 {
     this->clearET();
   }
   
-  /** Destructor */
-  eTower::~eTower(){
-  }
-  
   /** Clear and resize ET value vector */
   void eTower::clearET()
   {
@@ -102,7 +98,7 @@ namespace LVL1 {
     int outET = eFEXCompression::Expand(ecode);
     
     //noise cut
-    bool SCpass = noiseCut(outET,layer);
+    const bool SCpass = noiseCut(outET,layer);
     if (SCpass){ m_et[cell] = outET;}
     else{ m_et[cell] = 0; }
   }
@@ -125,17 +121,16 @@ namespace LVL1 {
       int outET = eFEXCompression::Expand(ecode);
       
       //noise cut
-      bool SCpass = noiseCut(outET,layer);
+      const bool SCpass = noiseCut(outET,layer);
       if (SCpass){ m_et[cell] = outET;}
       else{ m_et[cell] = 0; }
       
     }
     else{
 
-      float et1 = et/2;
-      float et2 = et/2;
-      addET(et1, cell);
-      addET(et2, cell+1);
+      float et_half = et*0.5;
+      addET(et_half, cell);
+      addET(et_half, cell+1);
 
       unsigned int ecode1 = eFEXCompression::Compress(m_et_float[cell]);
       int outET1 = eFEXCompression::Expand(ecode1);
@@ -143,10 +138,10 @@ namespace LVL1 {
       int outET2 = eFEXCompression::Expand(ecode2);
 
       //noise cuts
-      bool SCpass1 = noiseCut(outET1,layer);
+      const bool SCpass1 = noiseCut(outET1,layer);
       if (SCpass1){ m_et[cell] = outET1;}
       else{ m_et[cell] = 0; }
-      bool SCpass2 = noiseCut(outET2,layer);
+      const bool SCpass2 = noiseCut(outET2,layer);
       if (SCpass2){ m_et[cell+1] = outET2;}
       else{ m_et[cell+1] = 0; }
 
@@ -157,7 +152,7 @@ namespace LVL1 {
   }
 
   /** Apply noise cut per layer **/
-  bool eTower::noiseCut(int et, int layer)
+  bool eTower::noiseCut(int et, int layer) const
   {
 
     bool pass=true;                                                                                                         
@@ -185,18 +180,19 @@ namespace LVL1 {
   /** Return global eta index.
       Should be derived from tower ID, should be corrected in the future.
       Need to also think what index range should be (thinking ahead to Run2) */
-  int eTower::iEta() {
-    int index = (m_eta + 2.5)/0.1;
+  int eTower::iEta() const {
+    const int index = (m_eta + 2.5)/0.1; // /0.1;  // Equivalent to divide by 0.1 which is the Tower size
     return index;
   }
   
   /** Return global phi index.
       Should be derived from tower ID, should be corrected in the future.
       Decision here is whether phi is signed or not */
-  int eTower::iPhi() {
+  int eTower::iPhi() const {
     int index = 32*m_phi/M_PI;
     if (m_phi < 0) index = 32*(m_phi + 2*M_PI)/M_PI;
-    return index;
+    const int cindex = index;
+    return cindex;
   }
   
   /** Return ET of specified supercell */
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerBuilder.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerBuilder.cxx
index 473d387d8a1580e2ce3a56235ddcc817838264cb..a3e27dfafc0a095d16f0656ea5510785a0ca7ba3 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerBuilder.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerBuilder.cxx
@@ -34,29 +34,22 @@ eTowerBuilder::eTowerBuilder(const std::string& type,const std::string& name,con
   declareInterface<IeTowerBuilder>(this);
 }
 
-eTowerBuilder::~eTowerBuilder()
-{
-}
-
 
 void eTowerBuilder::init(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
 {
 
   execute(eTowerContainerRaw);
-  return;
 }
 
 
 void eTowerBuilder::reset() 
 {
-  return;
 }
 
 
 void eTowerBuilder::execute(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
 {
   BuildAllTowers(eTowerContainerRaw);
-  return;
 }
  
   // TOWER IDs FOR CLARITY
@@ -69,7 +62,7 @@ void eTowerBuilder::execute(std::unique_ptr<eTowerContainer> & eTowerContainerRa
   // Left Hadronic Endcap ID Tower = 11100000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone eTowers.
   // Right Haronic Endcap ID Tower = 22200000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone eTowers.
 
- void eTowerBuilder::BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
+ void eTowerBuilder::BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const
 {
   // Regions 0 only.  Region 1 is 'transition region'.
   for (int ieta = 0; ieta < 14; ++ieta) { // loop over 14 eta steps (ignoring last step as it is transition region)
@@ -79,10 +72,9 @@ void eTowerBuilder::execute(std::unique_ptr<eTowerContainer> & eTowerContainerRa
     }
   }
 
-  return;
 }
 
-void eTowerBuilder::BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
+void eTowerBuilder::BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const
 {
 
   int TRANS_MODIFIER = 14;
@@ -95,10 +87,9 @@ void eTowerBuilder::BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerC
     }
   }
 
-  return;
 }
 
-  void eTowerBuilder::BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
+  void eTowerBuilder::BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const
 {
   // Region 1
   int EME_MODIFIER = 15;
@@ -142,12 +133,11 @@ void eTowerBuilder::BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerC
     EME_MODIFIER++;
   }
 
-  return;
 
 }
 
 // REDUNDANT AND NOT USED==========================================================================================================
-  void eTowerBuilder::BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
+  void eTowerBuilder::BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const
 {
 
   // Region 0
@@ -171,25 +161,21 @@ void eTowerBuilder::BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerC
     HEC_MODIFIER++;
   }
 
-  return;
-
 }
 
-void eTowerBuilder::BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainerRaw,float eta, float phi, float keybase, int posneg) 
+void eTowerBuilder::BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainerRaw,float eta, float phi, float keybase, int posneg) const
 {
 
   eTowerContainerRaw->push_back(eta, phi, keybase, posneg);
 
-  return;
 
 }
 
-void eTowerBuilder::BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) 
+void eTowerBuilder::BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainerRaw) const
 {
   BuildEMBeTowers(eTowerContainerRaw);
   BuildTRANSeTowers(eTowerContainerRaw);
   BuildEMEeTowers(eTowerContainerRaw);
-  return;
 
 }
 
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerContainer.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerContainer.cxx
index 9d7cd000f3f8a58f4ba2a32119f7082d2913e30d..076f76ce2f082ab0bc61836546e69607590c2784 100644
--- a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerContainer.cxx
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/eTowerContainer.cxx
@@ -36,7 +36,7 @@ const LVL1::eTower * eTowerContainer::findTower(int towerID) const
   if(container_index >= 0){
     return (*this)[container_index];
   }
-  return 0;
+  return nullptr;
 }
 
 LVL1::eTower * eTowerContainer::findTower(int towerID)
@@ -46,7 +46,7 @@ LVL1::eTower * eTowerContainer::findTower(int towerID)
   if(container_index >= 0){
     return (*this)[container_index];
   }
-  return 0;
+  return nullptr;
 }
 
 void eTowerContainer::clearContainerMap()
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXCompression.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXCompression.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c6f0c8d2fc069fbcf33892ada14063c0e14ce14d
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXCompression.cxx
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+/***************************************************************************
+                          jFEXCompression.cxx  -  description
+                             -------------------
+    begin                : 07-02-2019
+    email                : Alan.Watson@cern.ch antonio.jacques.costa@cern.ch
+ ***************************************************************************/
+
+#include "L1CaloFEXSim/jFEXCompression.h"
+
+namespace LVL1 {
+
+const int jFEXCompression::s_steps[] = {25, 50, 100, 200, 400, 102400};
+const int jFEXCompression::s_minET[] = {-750, 1600, 6400, 25600, 102400, 200000};
+const int jFEXCompression::s_minCode[] = {2, 96, 192, 384, 768, 1012};
+
+unsigned int jFEXCompression::Compress(int Et) {
+
+  // Check for overflow
+  if (Et >= s_maxET) return s_LArOverflow;
+ 
+  // Find which range the ET value is in
+  int range = -1;
+  for (unsigned int i = 0; i < s_nRanges; i++) {
+    if (Et < s_minET[i]) break;
+    range = i;
+  }
+
+  // Calculate code
+  unsigned int code = 0;
+
+  if (range < 0) {
+    // Below minimum value
+    code = s_LArUnderflow; 
+  }
+  else {
+    // Lies inside one of the value ranges
+    int steps = (Et - s_minET[range])/s_steps[range];
+    code = s_minCode[range] + steps;
+  }
+
+  return code;
+}
+
+int jFEXCompression::Expand(unsigned int code) {
+
+  // Deal with special codes first:
+  if (code == s_NoData)  return 0;
+  if (code == s_LArInvalid || code == s_LArReserved || code > s_LArMaxCode) return s_error; 
+  if (code == s_LArOverflow || code == s_LArSaturated) return s_maxET;
+
+  /** Now expand code into an ET value.
+      Start by finding what range the code is in */
+  int range = 0;
+  for (unsigned int i = 0; i < s_nRanges-1; ++i) {
+    if (code < (unsigned int)s_minCode[i+1]) break;
+    range++;
+  }
+  /// Now expand the value
+  int Et = s_minET[range] + (code-s_minCode[range])*s_steps[range];
+  
+  return Et;
+}
+
+
+unsigned int jFEXCompression::Threshold(unsigned int code, int threshold) {
+
+  /// Convert threshold into a compressed code
+  unsigned int cut = jFEXCompression::Compress(threshold);
+
+  /// Zero code if < threshold
+  if (code < cut) code = 0;
+
+  return code;
+}
+
+
+unsigned int jFEXCompression::Linearize(unsigned int code, int threshold) {
+
+  /// Apply the threshold. Since jFEX ET is positive, minimum threshold is 0.
+  if (threshold < 0) threshold = 0;
+  code = jFEXCompression::Threshold(code, threshold);
+
+  /// Expand the ET value
+  int Et = jFEXCompression::Expand(code);
+
+  // Check for overflow
+  if (Et >= s_maxET) return s_jFEXOverflow;
+
+  /// Convert to jFEX digit scale
+  unsigned int jFexET = Et/s_jFEXstep;
+  return jFexET;
+}
+
+} // end of namespace bracket
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXDriver.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXDriver.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b923ed86d5af903f68ac123418f889b8487ad184
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXDriver.cxx
@@ -0,0 +1,171 @@
+/*
+    Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#undef NDEBUG
+
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerBuilder.h"
+#include "L1CaloFEXSim/jFEXDriver.h"
+
+#include "L1CaloFEXSim/jSuperCellTowerMapper.h"
+
+#include "L1CaloFEXSim/jFEXSim.h"
+//#include "L1CaloFEXSim/jFEXOutputCollection.h"
+//#include "L1CaloFEXSim/jFEXegTOB.h"
+
+#include "TROOT.h"
+#include "TH1.h"
+#include "TH1F.h"
+#include "TPad.h"
+#include "TCanvas.h"
+
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/ReadHandle.h"
+
+#include "L1CaloFEXSim/jTowerContainer.h"
+
+#include <cassert>
+#include "SGTools/TestStore.h"
+
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ITHistSvc.h"
+
+#include <ctime>
+
+#define DEBUG_VHB 1
+
+
+namespace LVL1 {
+
+  jFEXDriver::jFEXDriver(const std::string& name, ISvcLocator* pSvcLocator)
+    :  AthAlgorithm(name, pSvcLocator)//AthReentrantAlgorithm(name, pSvcLocator)
+  { 
+  
+  }
+
+
+ jFEXDriver::~jFEXDriver()
+{
+  ATH_MSG_DEBUG("Destroying " << name() << "...");
+}
+
+
+StatusCode jFEXDriver::initialize()
+{
+
+  m_numberOfEvents = 1;
+
+  ServiceHandle<ITHistSvc> histSvc("THistSvc","");
+  StatusCode scHist = histSvc.retrieve();
+  if (scHist ==  StatusCode::FAILURE) {ATH_MSG_ERROR("Failed to retrieve THistSvc"); }
+
+  //Reta
+  TH1F* hReta = new TH1F("Reta", "Reta",20,0,1);
+  hReta->GetXaxis()->SetTitle("TObs Reta");
+  hReta->GetYaxis()->SetTitle("Events");
+  
+  StatusCode scReg = histSvc->regHist("/ISO/Reta", hReta); 
+  if (scReg ==  StatusCode::FAILURE) {ATH_MSG_ERROR("Failed to define stream"); }
+
+
+  ATH_CHECK( m_jTowerBuilderTool.retrieve() );
+
+  ATH_CHECK( m_jSuperCellTowerMapperTool.retrieve() );
+
+  ATH_CHECK( m_jFEXSysSimTool.retrieve() );
+
+  ATH_CHECK( m_jTowerContainerSGKey.initialize() );
+
+  //ATH_CHECK( m_jFEXOutputCollectionSGKey.initialize() );
+
+  return StatusCode::SUCCESS;
+
+}
+
+
+StatusCode jFEXDriver::finalize()
+{
+  ATH_MSG_DEBUG("Finalizing " << name() << "...");
+  return StatusCode::SUCCESS;
+}
+
+
+  StatusCode jFEXDriver::execute(/*const EventContext& ctx*/) //const
+{
+
+  ATH_MSG_DEBUG("Executing " << name() << ", processing event number " << m_numberOfEvents );
+
+  // OLD DIMA STUFF---------------------- Maybe useful in the future again
+  //if (fabsf((*cell)->eta()) > 2.55) continue;
+  //if (!((*cell)->provenance() & 0x40)) continue; // BCID cut
+  //// if (!((*cell)->provenance() & 0x200)) continue;
+  //// 8192 & 0x40 = 0
+  //// 8256 & 0x40 = 64
+  //// 8704 & 0x40 = 0
+  //// 8768 & 0x40 = 64
+
+  // STEP 0 - Make a fresh local jTowerContainer
+  std::unique_ptr<jTowerContainer> local_jTowerContainerRaw = std::make_unique<jTowerContainer>();
+
+  // STEP 1 TO BE REPLACED IN THE NEAR FUTURE - KEPT HERE FOR REFERENCE
+  // STEP 1 - Do some monitoring (code to exported in the future to another algorithm accessing only StoreGate and not appearing in this algorithm)
+  /*
+  jFEXOutputCollection* my_jFEXOutputCollection = new jFEXOutputCollection();
+  bool savetob = true;
+  if(savetob)
+  {
+    StatusCode sctob = evtStore()->record(my_jFEXOutputCollection,"jFEXOutputCollection");
+    if(sctob == StatusCode::SUCCESS){}
+    else if (sctob == StatusCode::FAILURE){ATH_MSG_ERROR("Event " << m_numberOfEvents << " , Failed to put jFEXOutputCollection into Storegate.");}
+    
+    
+    //SG::WriteHandle<jFEXOutputCollection> jFEXOutputCollectionSG(m_jFEXOutputCollectionSGKey,ctx);
+    //ATH_CHECK(jFEXOutputCollectionSG.record(std::make_unique<jFEXOutputCollection>()));
+    
+  }
+  */
+
+  // STEP 2 - Make some jTowers and fill the local container
+  ATH_CHECK( m_jTowerBuilderTool.retrieve() );
+  m_jTowerBuilderTool->init(local_jTowerContainerRaw);
+  local_jTowerContainerRaw->clearContainerMap();
+  local_jTowerContainerRaw->fillContainerMap();
+
+  // STEP 3 - Do the supercell-tower mapping - put this information into the jTowerContainer
+  ATH_CHECK( m_jSuperCellTowerMapperTool.retrieve() );
+  ATH_CHECK(m_jSuperCellTowerMapperTool->AssignSuperCellsToTowers(local_jTowerContainerRaw));
+  ATH_CHECK(m_jSuperCellTowerMapperTool->AssignTriggerTowerMapper(local_jTowerContainerRaw));
+
+  // STEP 4 - Write the completed jTowerContainer into StoreGate (move the local copy in memory)
+  SG::WriteHandle<LVL1::jTowerContainer> jTowerContainerSG(m_jTowerContainerSGKey/*, ctx*/);
+  ATH_CHECK(jTowerContainerSG.record(std::move(/*my_jTowerContainerRaw*/local_jTowerContainerRaw)));
+
+  // STEP 5 - Set up the jFEXSysSim
+  ATH_CHECK( m_jFEXSysSimTool.retrieve() );
+  m_jFEXSysSimTool->init();
+
+  // STEP 6 - Run THE jFEXSysSim
+  ATH_CHECK(m_jFEXSysSimTool->execute());
+
+  // STEP 7 - Close and clean the event  
+  m_jFEXSysSimTool->cleanup();
+  m_jSuperCellTowerMapperTool->reset();
+  m_jTowerBuilderTool->reset();
+
+  ATH_MSG_DEBUG("Executed " << name() << ", closing event number " << m_numberOfEvents );
+
+  m_numberOfEvents++;
+
+  return StatusCode::SUCCESS;
+}
+  
+  
+} // end of LVL1 namespace
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXFPGA.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXFPGA.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b1a4a5c297e13b3659a25415bf3c445877a3b006
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXFPGA.cxx
@@ -0,0 +1,128 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXFPGA  -  description
+//                              -------------------
+//     begin                : 19 10 2020
+//     email                : jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+#include "L1CaloFEXSim/jFEXFPGA.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+//#include "L1CaloFEXSim/jFEXegAlgo.h" //for the future
+//#include "L1CaloFEXSim/jFEXegTOB.h" //for the future
+//#include "L1CaloFEXSim/jFEXOutputCollection.h" //for the future
+//#include "L1CaloFEXSim/jFEXtauAlgo.h" //for the future
+//#include "L1CaloFEXSim/jFEXtauTOB.h" //for the future
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/ITHistSvc.h"
+#include <vector>
+#include "TH1F.h"
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/ReadHandle.h"
+#include "SGTools/TestStore.h"
+
+
+namespace LVL1 {
+
+  // default constructor for persistency
+
+jFEXFPGA::jFEXFPGA(const std::string& type,const std::string& name,const IInterface* parent):
+  AthAlgTool(type,name,parent)
+{
+  declareInterface<IjFEXFPGA>(this);
+}
+  
+    
+  /** Destructor */
+  jFEXFPGA::~jFEXFPGA()
+  {
+  }
+
+//================ Initialisation =================================================
+  
+StatusCode jFEXFPGA::initialize()
+{
+
+  ATH_CHECK(m_jFEXFPGA_jTowerContainerKey.initialize());
+  //ATH_CHECK(m_jFEXFPGA_jFEXOutputCollectionKey.initialize());
+  return StatusCode::SUCCESS;
+}
+  
+
+StatusCode jFEXFPGA::init(int id, int jfexid)
+{
+  m_id = id;
+  m_jfexid = jfexid;
+
+  return StatusCode::SUCCESS;
+
+}
+
+void jFEXFPGA::reset(){
+
+  m_id = -1;
+  m_jfexid = -1;
+
+}
+
+StatusCode jFEXFPGA::execute(){
+
+  SG::ReadHandle<jTowerContainer> jk_jFEXFPGA_jTowerContainer(m_jFEXFPGA_jTowerContainerKey/*,ctx*/);
+  if(!jk_jFEXFPGA_jTowerContainer.isValid()){
+    ATH_MSG_FATAL("Could not retrieve jk_jFEXFPGA_jTowerContainer " << m_jFEXFPGA_jTowerContainerKey.key() );
+    return StatusCode::FAILURE;
+  }
+    
+  return StatusCode::SUCCESS;
+
+}
+
+void jFEXFPGA::SetTowersAndCells_SG(int tmp_jTowersIDs_subset[][9]){
+    
+  const int rows = 16;
+  const int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+  
+  std::copy(&tmp_jTowersIDs_subset[0][0], &tmp_jTowersIDs_subset[0][0]+(rows*cols),&m_jTowersIDs_Wide[0][0]);
+  
+  if(true){ //this prints out the jTower IDs that each FPGA is responsible for
+    ATH_MSG_DEBUG("\n==== jFEXFPGA ========= FPGA (" << m_id << ") IS RESPONSIBLE FOR eTOWERS :");
+    for (int thisRow=rows-1; thisRow>=0; thisRow--){
+      for (int thisCol=0; thisCol<cols; thisCol++){
+	if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << m_jTowersIDs_Wide[thisRow][thisCol] << "  "); }
+	else { ATH_MSG_DEBUG("|  " << m_jTowersIDs_Wide[thisRow][thisCol] << "  |"); }
+      }
+    }
+  }
+  
+}
+
+  void jFEXFPGA::SetTowersAndCells_SG(int tmp_jTowersIDs_subset[][8]){
+
+    const int rows = 16;
+    const int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+    
+    std::copy(&tmp_jTowersIDs_subset[0][0], &tmp_jTowersIDs_subset[0][0]+(rows*cols),&m_jTowersIDs_Thin[0][0]);
+
+    if(false){ //this prints out the jTower IDs that each FPGA is responsible for
+      ATH_MSG_DEBUG("\n==== jFEXFPGA ========= FPGA (" << m_id << ") IS RESPONSIBLE FOR eTOWERS :");
+      for (int thisRow=rows-1; thisRow>=0; thisRow--){
+	for (int thisCol=0; thisCol<cols; thisCol++){
+	  if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << m_jTowersIDs_Thin[thisRow][thisCol] << "  "); }
+	  else { ATH_MSG_DEBUG("|  " << m_jTowersIDs_Thin[thisRow][thisCol] << "  |"); }
+	}
+      }
+    }
+
+  }
+  
+} // end of namespace bracket
+
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSim.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSim.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1add3ba1bd790a5727893f94be44a3c4e47a2cd0
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSim.cxx
@@ -0,0 +1,326 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSim  -  description
+//                              -------------------
+//     begin                : 19 10 2020
+//     email                : jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#include "L1CaloFEXSim/jFEXSim.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jFEXFPGA.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/ServiceHandle.h"
+
+namespace LVL1 {
+
+  jFEXSim::jFEXSim(const std::string& type,const std::string& name,const IInterface* parent):
+    AthAlgTool(type,name,parent)
+  {
+    declareInterface<IjFEXSim>(this);
+  }
+
+
+  //================ Initialisation =================================================
+
+  StatusCode jFEXSim::initialize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  //================ Finalisation =================================================
+
+  StatusCode jFEXSim::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+
+  void jFEXSim::reset()
+  {
+
+    m_id = -1;
+    m_jFEXFPGACollection.clear();
+
+    int rows = sizeof m_jTowersIDs_Thin / sizeof m_jTowersIDs_Thin[0];
+    int cols = sizeof m_jTowersIDs_Thin[0] / sizeof m_jTowersIDs_Thin[0][0];
+    for (int i=0; i<rows; i++){
+      for (int j=0; j<cols; j++){
+	  m_jTowersIDs_Thin[i][j] = 0;
+	}
+    }
+
+
+    rows = sizeof m_jTowersIDs_Wide / sizeof m_jTowersIDs_Wide[0];
+    cols = sizeof m_jTowersIDs_Wide[0] / sizeof m_jTowersIDs_Wide[0][0];
+    for (int i=0; i<rows; i++){
+      for (int j=0; j<cols; j++){
+	m_jTowersIDs_Wide[i][j] = 0;
+      }
+    }
+    
+  }
+
+  void jFEXSim::init(int id)
+  {
+    m_id = id;
+  }
+
+  /** Destructor */
+  jFEXSim::~jFEXSim()
+  {
+  }
+  
+ void jFEXSim::execute(){
+
+ }
+
+StatusCode jFEXSim::NewExecute(int tmp_jTowersIDs_subset[16*4][9]){
+
+  const int nrows = 16;
+  const int ncols = 9;
+
+  int tmp_jTowersIDs_subset_FPGA[nrows][ncols];
+
+  ATH_CHECK( m_jFEXFPGATool.retrieve() );
+
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = 0; myrow<nrows; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(0, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows; myrow<nrows*2; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-nrows][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(1, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+
+
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*2; myrow<nrows*3; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*2)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(2, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+
+  //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*3; myrow<nrows*4; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*3)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(3, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 3---------------------------------------------------------------------------------------------------------------------------------------------
+
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode jFEXSim::NewExecute(int tmp_jTowersIDs_subset[16*4][8]){
+
+  //std::copy(&tmp_jTowersIDs_subset[0][0], &tmp_jTowersIDs_subset[0][0]+(10*18),&m_jTowersIDs[0][0]);
+
+  const int nrows = 16;
+  const int ncols = 8;
+
+  int tmp_jTowersIDs_subset_FPGA[nrows][ncols];
+
+  ATH_CHECK( m_jFEXFPGATool.retrieve() );
+  
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = 0; myrow<nrows; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(0, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+  
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows; myrow<nrows*2; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-nrows][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(1, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+
+
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*2; myrow<nrows*3; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*2)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(2, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+
+  //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*3; myrow<nrows*4; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*3)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  ATH_CHECK(m_jFEXFPGATool->init(3, m_id));
+  m_jFEXFPGATool->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  ATH_CHECK(m_jFEXFPGATool->execute());
+  m_jFEXFPGATool->reset();
+  //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+
+  return StatusCode::SUCCESS;
+
+}
+
+void jFEXSim::SetTowersAndCells_SG(int tmp_jTowersIDs_subset[16][8]){ // METHOD USING ONLY IDS
+
+  const int nrows = 16;
+  const int ncols = 8;
+
+  std::copy(&tmp_jTowersIDs_subset[0][0], &tmp_jTowersIDs_subset[0][0]+(nrows*ncols),&m_jTowersIDs_Thin[0][0]);
+
+  int tmp_jTowersIDs_subset_FPGA[nrows][ncols];
+  
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = 0; myrow<nrows; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }  
+  m_jFEXFPGACollection.at(0)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows; myrow<nrows*2; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-nrows][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  m_jFEXFPGACollection.at(1)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+  
+
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*2; myrow<nrows*3; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*2)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  m_jFEXFPGACollection.at(2)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+  
+  //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+  memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+  for (int myrow = nrows*3; myrow<nrows*4; myrow++){
+    for (int mycol = 0; mycol<ncols; mycol++){
+      tmp_jTowersIDs_subset_FPGA[myrow-(nrows*3)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+    }
+  }
+  m_jFEXFPGACollection.at(3)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+  //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+  
+}
+
+  void jFEXSim::SetTowersAndCells_SG(int tmp_jTowersIDs_subset[16][9]){ // METHOD USING ONLY IDS
+
+    const int nrows = 16;
+    const int ncols = 9;
+
+    std::copy(&tmp_jTowersIDs_subset[0][0], &tmp_jTowersIDs_subset[0][0]+(nrows*ncols),&m_jTowersIDs_Wide[0][0]);
+
+    int tmp_jTowersIDs_subset_FPGA[nrows][ncols];
+
+    //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+    memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+    for (int myrow = 0; myrow<nrows; myrow++){
+      for (int mycol = 0; mycol<ncols; mycol++){
+	tmp_jTowersIDs_subset_FPGA[myrow][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+      }
+    }
+    m_jFEXFPGACollection.at(0)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+    //FPGA 0----------------------------------------------------------------------------------------------------------------------------------------------
+
+    //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+    memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+    for (int myrow = nrows; myrow<nrows*2; myrow++){
+      for (int mycol = 0; mycol<ncols; mycol++){
+	tmp_jTowersIDs_subset_FPGA[myrow-nrows][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+      }
+    }
+    m_jFEXFPGACollection.at(1)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+    //FPGA 1----------------------------------------------------------------------------------------------------------------------------------------------
+
+
+    //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+    memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+    for (int myrow = nrows*2; myrow<nrows*3; myrow++){
+      for (int mycol = 0; mycol<ncols; mycol++){
+	tmp_jTowersIDs_subset_FPGA[myrow-(nrows*2)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+      }
+    }
+    m_jFEXFPGACollection.at(2)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+    //FPGA 2----------------------------------------------------------------------------------------------------------------------------------------------
+
+    //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+    memset(tmp_jTowersIDs_subset_FPGA, 0, sizeof tmp_jTowersIDs_subset_FPGA);
+    for (int myrow = nrows*3; myrow<nrows*4; myrow++){
+      for (int mycol = 0; mycol<ncols; mycol++){
+	tmp_jTowersIDs_subset_FPGA[myrow-(nrows*3)][mycol] = tmp_jTowersIDs_subset[myrow][mycol];
+      }
+    }
+    m_jFEXFPGACollection.at(3)->SetTowersAndCells_SG(tmp_jTowersIDs_subset_FPGA);
+    //FPGA 3----------------------------------------------------------------------------------------------------------------------------------------------
+
+  }
+  
+
+} // end of namespace bracket
+
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSysSim.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSysSim.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cdafd17b8cdb8c5b9ab80e66174120918cd2683b
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jFEXSysSim.cxx
@@ -0,0 +1,558 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSysSim  -  description
+//                              -------------------
+//     begin                : 19 10 2020
+//     email                : jacob.julian.kempster@cern.ch alison.elliot@cern.ch
+//  ***************************************************************************/
+
+#include "L1CaloFEXSim/jFEXSysSim.h"
+#include "L1CaloFEXSim/jFEXSim.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/ReadHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+
+
+#include <ctime>
+
+namespace LVL1 {
+  
+  
+  // default constructor for persistency
+
+  jFEXSysSim::jFEXSysSim(const std::string& type,const std::string& name,const IInterface* parent):
+    AthAlgTool(type,name,parent)
+  {
+    declareInterface<IjFEXSysSim>(this);
+
+  }
+
+    
+  /** Destructor */
+  //jFEXSysSim::~jFEXSysSim()
+  //{
+  //}
+
+  //================ Initialisation =================================================
+
+  StatusCode jFEXSysSim::initialize()
+  {
+    
+    ATH_CHECK(m_jTowerContainerSGKey.initialize());
+
+    ATH_CHECK( m_jFEXSimTool.retrieve() );
+
+    return StatusCode::SUCCESS;
+  }
+
+  //================ Finalisation =================================================
+
+  StatusCode jFEXSysSim::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  
+  void jFEXSysSim::init()  {
+
+  }
+
+  void jFEXSysSim::cleanup()  {
+
+    m_jFEXCollection.clear();
+    m_jTowersColl.clear();
+
+  }
+
+
+  int jFEXSysSim::calcTowerID(int eta, int phi, int mod)  {
+
+    return ((64*eta) + phi + mod);
+
+  }
+
+  StatusCode jFEXSysSim::execute()  {    
+
+    SG::ReadHandle<LVL1::jTowerContainer> this_jTowerContainer(m_jTowerContainerSGKey/*,ctx*/);
+    if(!this_jTowerContainer.isValid()){
+      ATH_MSG_FATAL("Could not retrieve jTowerContainer " << m_jTowerContainerSGKey.key());
+      return StatusCode::FAILURE;
+    }
+
+    // We need to split the towers into 6 blocks in eta and 4 blocks in phi.
+
+    // boundaries in eta: -2.5, -1.6, -0.8, 0.0, 0.8, 1.6, 2.5
+    // Written explicitly:
+    // -2.5 -> -1.6
+    // -1.6 -> -0.8
+    // -0.8 -> 0.0
+    // 0.0 -> 0.8
+    // 0.8 -> 1.6
+    // 1.6 -> 2.5
+
+    // boundaries in phi: 0.0, 1.6, 3.2, 4.8, 6.4
+    // Written explicitly:
+    // 0.0 -> 1.6
+    // 1.6 -> 3.2
+    // 3.2 -> 4.8
+    // 4.8 -> 6.4
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    // C-SIDE NEGATIVE JFEX
+    // LEFT-MOST
+    // DO THE LEFT-MOST (NEGATIVE ETA) JFEX FIRST
+    int fpgacounter = 0;
+    //id_modifier + phi + (64 * eta)
+    int emecEta = 24; int emecPhi = 0; int emecMod = 500000;
+    int initialEMEC = calcTowerID(emecEta,emecPhi,emecMod); //501536;
+
+
+    int thisJFEX = 0;
+    if(true){ // JFEX 0
+      thisJFEX = 0;
+      
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+      
+      // let's try doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][9];
+      
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMEC part
+      for(int thisCol=0; thisCol<9; thisCol++){
+	for(int thisRow=0; thisRow<rows; thisRow++){
+
+	  int towerid = initialEMEC - (thisCol * 64) + thisRow;
+
+	  //if( (thisJFEX == 21) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+	  
+	  tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+	  tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+	}
+      }
+
+      if(false){
+        ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+	for (int thisRow=rows-1; thisRow>=0; thisRow--){
+          for (int thisCol=0; thisCol<cols; thisCol++){
+            int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+            const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+            const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+            if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowerphi << "][" << tmptowereta << "])  "); }
+            else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+          }
+        }
+      }
+
+
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      //fgpacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    // C-SIDE NEGATIVE JFEX
+    // INNER-LEFT
+    // DO THE INNER-LEFT (NEGATIVE ETA) JFEX SECOND
+    fpgacounter = 0;
+    //id_modifier + phi + (64 * eta)
+    emecEta = 15; emecPhi = 0; emecMod = 500000;
+    initialEMEC = calcTowerID(emecEta,emecPhi,emecMod); //500960;
+    int transEta = 14; int transPhi = 0; int transMod = 300000;
+    int initialTRANS = calcTowerID(transEta,transPhi,transMod); //300896;
+    int embEta = 13; int embPhi = 0; int embMod = 100000;
+    int initialEMB = calcTowerID(embEta,embPhi,embMod); //100832
+
+    if(true){ // JFEX 1
+      thisJFEX = 1;
+
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+
+      // let's try doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][8];
+
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMEC part
+      for(int thisRow=0; thisRow<rows; thisRow++){
+	
+	int towerid = initialEMEC /*- (thisCol * 64)*/ + thisRow;
+	
+	//if( (thisJFEX == 21) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+	
+	tmp_jTowersIDs_subset[thisRow][0/*thisCol*/] = towerid;
+	tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+	
+	std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+	
+      }
+
+      // set the TRANS part
+      for(int thisRow = 0; thisRow < rows; thisRow++){
+
+	int towerid = initialTRANS + thisRow;
+
+	//if( (thisJFEX == 21) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+	tmp_jTowersIDs_subset[thisRow][1] = towerid;
+	tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+      }
+
+      // set the EMB part
+      for(int thisCol = 2; thisCol < cols; thisCol++){
+	for(int thisRow=0; thisRow<rows; thisRow++){
+
+	  int towerid = initialEMB - ( (thisCol-2) * 64) + thisRow;
+
+	  //if( (thisJFEX == 21) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+	  tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+	  tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+	}
+      }
+      
+
+      if(false){
+	ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+	for (int thisRow=rows-1; thisRow>=0; thisRow--){
+          for (int thisCol=0; thisCol<cols; thisCol++){
+            int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+            const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+            const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+            if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowerphi << "][" << tmptowereta << "])  "); }
+            else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+          }
+        }
+      }
+
+
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      fpgacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------    
+    // C-SIDE NEGATIVE JFEXs
+    // CENTRAL-LEFT
+    // DO THE CENTRAL-LEFT JFEXs (NEGATIVE ETA) THIRD
+    fpgacounter = 0;
+    //id_modifier + phi + (64 * eta)
+    embEta = 7; embPhi = 0; embMod = 100000;
+    initialEMB = calcTowerID(embEta,embPhi,embMod); //100448
+
+    if(true){ // jFEX 2
+      thisJFEX = 2;
+      
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+      
+      // doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][8];
+
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMB part
+      for(int thisCol = 0; thisCol < cols; thisCol++){
+        for(int thisRow=0; thisRow<rows; thisRow++){
+	  int towerid = -1;
+
+	  int tmp_initEMB = initialEMB;
+
+	  towerid = tmp_initEMB - ( (thisCol) * 64) + thisRow;
+
+	  //if( (thisJFEX == 22) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+          tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+
+          tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+        }
+      }
+      
+
+      if(false){
+	ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+        for (int thisRow=rows-1; thisRow>=0; thisRow--){
+          for (int thisCol=0; thisCol<cols; thisCol++){
+            int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+            const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+            const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+            if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  "); }
+            else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+	  }
+        }
+      }
+
+      //tool use instead
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      fpgacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    // A-SIDE POSITIVE JFEXs
+    // CENTRAL-RIGHT JFEXs
+    // DO THE CENTRAL-RIGHT JFEXs (POSITIVE ETA) FOURTH
+    fpgacounter = 0;
+    //id_modifier + phi + (64 * eta)
+    embEta = 0; embPhi = 0; embMod = 200000;
+    initialEMB = calcTowerID(embEta,embPhi,embMod); //200000
+
+    if(true){ // jFEX 3
+      thisJFEX = 3;
+      if(fpgacounter > 0){  initialEMB += 16; }
+
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+
+      // doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][8];
+
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMB part
+      for(int thisCol = 0; thisCol < cols; thisCol++){
+        for(int thisRow=0; thisRow<rows; thisRow++){
+          int towerid = -1;
+
+          int tmp_initEMB = initialEMB;
+
+          towerid = tmp_initEMB + ( (thisCol) * 64) + thisRow;
+
+          //if( (thisJFEX == 22) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+          tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+
+          tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+        }
+      }
+
+      if(false){
+        ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+        for (int thisRow=rows-1; thisRow>=0; thisRow--){
+          for (int thisCol=0; thisCol<cols; thisCol++){
+            int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+            const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+            const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+            if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  "); }
+            else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+          }
+        }
+      }
+
+      //tool use instead
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      fpgacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    // A-SIDE POSITIVE JFEXs
+    // INNER-RIGHT JFEXs
+    // DO THE INNER-RIGHT JFEXs (POSITIVE ETA) FIFTH
+    fpgacounter = 0;
+    emecEta = 15; emecPhi = 0; emecMod = 600000;
+    initialEMEC = calcTowerID(emecEta,emecPhi,emecMod); //600960;
+    transEta = 14; transPhi = 0; transMod = 400000;
+    initialTRANS = calcTowerID(transEta,transPhi,transMod); //400896;
+    embEta = 8; embPhi = 0; embMod = 200000;
+    initialEMB = calcTowerID(embEta,embPhi,embMod); //200512;
+
+    if(true){ // jFEX 4
+      thisJFEX = 4;
+
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+
+      // doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][8];
+
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMB part
+      for(int thisCol = 0; thisCol < 6; thisCol++){
+        for(int thisRow=0; thisRow<rows; thisRow++){
+          int towerid = initialEMB + ( (thisCol) * 64) + thisRow;
+
+          //if( (thisJFEX == 23) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+          tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+          tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+        }
+      }
+      // set the TRANS part
+      for(int thisRow = 0; thisRow < rows; thisRow++){
+        int towerid = initialTRANS + thisRow;
+
+        //if( (thisJFEX == 23) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+        tmp_jTowersIDs_subset[thisRow][6] = towerid;
+        tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+      }
+      // set the EMEC part
+      for(int thisRow=0; thisRow<rows; thisRow++){
+	int towerid = initialEMEC + /*( (thisCol-8) * 64)*/ + thisRow;
+
+	//if( (thisJFEX == 23) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+	
+	tmp_jTowersIDs_subset[thisRow][7/*thisCol*/] = towerid;
+	tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+	
+	std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+	
+      }
+
+
+      if(false){
+	ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+	for (int thisRow=rows-1; thisRow>=0; thisRow--){
+	  for (int thisCol=0; thisCol<cols; thisCol++){
+	    int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+	    const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+	    const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+	    if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  "); }
+	    else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+	  }
+	}
+      }
+
+      //tool use instead
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      fpgacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+    // A-SIDE POSITIVE JFEXs
+    // RIGHT-MOST
+    // DO THE RIGHT-MOST (POSITIVE ETA) JFEXs SIXTH
+    fpgacounter = 0;
+    //id_modifier + phi + (64 * eta)
+    emecEta = 16; emecPhi = 0; emecMod = 600000;
+    initialEMEC = calcTowerID(emecEta,emecPhi,emecMod); //601024;
+
+    if(true){ // jFEX 5
+      thisJFEX = 5;
+
+      // decide which subset of towers (and therefore supercells) should go to the jFEX
+      std::map<int,jTower> tmp_jTowersColl_subset;
+
+      // let's try doing this with an array initially just containing tower IDs.
+      int tmp_jTowersIDs_subset [16*4][9];
+
+      int rows = sizeof tmp_jTowersIDs_subset / sizeof tmp_jTowersIDs_subset[0];
+      int cols = sizeof tmp_jTowersIDs_subset[0] / sizeof tmp_jTowersIDs_subset[0][0];
+
+      // set the EMEC part
+      for(int thisCol=0; thisCol<9; thisCol++){
+        for(int thisRow=0; thisRow<rows; thisRow++){
+
+          int towerid = initialEMEC + (thisCol * 64) + thisRow;
+
+          //if( (thisJFEX == 21) && (thisRow >= 7)){ towerid -= 64; }; // we'll bring this back in if need to apply FPGA or jFEX overlap
+
+          tmp_jTowersIDs_subset[thisRow][thisCol] = towerid;
+          tmp_jTowersColl_subset.insert( std::map<int, jTower>::value_type(towerid,  *(this_jTowerContainer->findTower(towerid))));
+
+	  std::vector<Identifier> supercellIDs = this_jTowerContainer->findTower(towerid)->getEMSCIDs();
+
+        }
+      }
+
+      if(false){
+        ATH_MSG_DEBUG("CONTENTS OF jFEX " << thisJFEX << " :");
+        for (int thisRow=rows-1; thisRow>=0; thisRow--){
+          for (int thisCol=0; thisCol<cols; thisCol++){
+            int tmptowerid = tmp_jTowersIDs_subset[thisRow][thisCol];
+            const float tmptowereta = this_jTowerContainer->findTower(tmptowerid)->eta();
+            const float tmptowerphi = this_jTowerContainer->findTower(tmptowerid)->phi();
+	    if(thisCol != cols-1){ ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowerphi << "][" << tmptowereta << "])  "); }
+            else { ATH_MSG_DEBUG("|  " << tmptowerid << "([" << tmptowereta << "][" << tmptowerphi << "])  |"); }
+          }
+        }
+      }
+
+      m_jFEXSimTool->init(thisJFEX);
+      ATH_CHECK(m_jFEXSimTool->NewExecute(tmp_jTowersIDs_subset));
+      m_jFEXSimTool->reset();
+
+      fpgacounter++;
+
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+    //Collate TOBS returned from jFEXSims. Should that be here?
+    // ToDo
+    // To implement
+    // {--Implement--}
+
+
+    //Send TOBs to bytestream?
+    // ToDo
+    // To implement
+    // {--Implement--}
+
+    return StatusCode::SUCCESS;
+
+  }
+
+  
+} // end of namespace bracket
+
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jSuperCellTowerMapper.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jSuperCellTowerMapper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b8e89064fbcf1beb1ee468ec3ae55b0a5354c7ed
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jSuperCellTowerMapper.cxx
@@ -0,0 +1,781 @@
+/*
+    Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "L1CaloFEXSim/jTowerBuilder.h"
+#include "TROOT.h"
+#include "TH1.h"
+#include "TH1F.h"
+#include "TPad.h"
+#include "TCanvas.h"
+#include "L1CaloFEXSim/jSuperCellTowerMapper.h"
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/errorcheck.h"
+
+//using Athena_test::URNG;
+//using Athena_test::randi_seed;
+//using Athena_test::randf_seed;
+
+// This is a class which is designed to receive in a list of supercells and a list of jTowers and match them together appropriately.
+
+
+/* VERY IMPORTANT NOTE.  ARE YOU CONFUSED ABOUT SAMPLING IDs? WANT TO KNOW WHERE ON EARTH THEY COME FROM? FINDING OBSCURE VALUES THAT ARE APPARENTLY MEANINGLESS?
+
+LOOK HERE!: athena/Calorimeter/CaloGeoHelpers/CaloGeoHelpers/CaloSampling.def
+
+*/
+
+
+namespace LVL1 {
+
+jSuperCellTowerMapper::jSuperCellTowerMapper(const std::string& type,const std::string& name,const IInterface* parent):
+  AthAlgTool(type,name,parent)
+{
+  declareInterface<IjSuperCellTowerMapper>(this);
+
+}
+
+jSuperCellTowerMapper::~jSuperCellTowerMapper()
+{
+
+}
+
+StatusCode jSuperCellTowerMapper::initialize()
+{
+ 
+  ATH_CHECK( m_scellsCollectionSGKey.initialize() );
+  ATH_CHECK( m_triggerTowerCollectionSGKey.initialize() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+StatusCode jSuperCellTowerMapper::AssignTriggerTowerMapper(std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw){
+  
+  static constexpr float pi_over_32 = std::acos(-1)/32;
+
+  SG::ReadHandle<xAOD::TriggerTowerContainer> jk_triggerTowerCollection(m_triggerTowerCollectionSGKey/*,ctx*/);
+  if(!jk_triggerTowerCollection.isValid()){
+    ATH_MSG_FATAL("Could not retrieve jk_triggerTowerCollection " << m_triggerTowerCollectionSGKey.key() );
+    return StatusCode::FAILURE;
+  }
+
+  for(auto eachTower : *jk_triggerTowerCollection) {
+
+    if(fabs(eachTower->eta())<1.5 && eachTower->sampling()==1) {
+      int i_phi = int(eachTower->phi()/pi_over_32);
+      int etaSign{-1};
+      int towerID_Modifier{100000};
+      if (eachTower->eta() > 0) {
+        etaSign = 1;
+        towerID_Modifier = 200000;
+      }
+      int i_eta = int(eachTower->eta() * 10) * etaSign;
+      if(i_eta * etaSign == -14) {
+        towerID_Modifier = 300000;
+      } else if (i_eta * etaSign == 14) {
+        towerID_Modifier = 400000;
+      }
+      int towerid = FindTowerIDForSuperCell(i_eta, i_phi) + towerID_Modifier;
+      LVL1::jTower * targetTower; 
+      if((targetTower = my_jTowerContainerRaw->findTower(towerid))) {
+        if (targetTower->getET_float(4, 0) > 0) {
+          ATH_MSG_WARNING("\n==== jSuperCellTowerMapper ============ Hadronic layer energy filled more than once - it will be ignored. (Needs investigation).  Please report this!");
+        }
+        targetTower->setET(10, int(eachTower->cpET()) * 500., 4); // cf 0.5 * 1000.0
+      } else {
+        ATH_MSG_WARNING("\n==== jSuperCellTowerMapper ============ Tower ID is officially unknown - it will be ignored. (Needs investigation).  Please report this!");
+      }
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+
+void jSuperCellTowerMapper::reset(){
+  return;
+}
+
+  // works for real supercells from MC
+  StatusCode jSuperCellTowerMapper::AssignSuperCellsToTowers(std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw)
+{
+
+  bool doPrint = false;
+
+  SG::ReadHandle<CaloCellContainer> jk_scellsCollection(m_scellsCollectionSGKey/*,ctx*/);
+  if(!jk_scellsCollection.isValid()){
+    ATH_MSG_FATAL("Could not retrieve jk_scellsCollection " << m_scellsCollectionSGKey.key() );
+    return StatusCode::FAILURE;
+  }
+
+  //const CaloCell_Base_ID* idHelper = caloIdManager->getCaloCell_SuperCell_ID(); // getting the id helper class
+  const CaloCell_Base_ID* idHelper = nullptr;
+  ATH_CHECK( detStore()->retrieve (idHelper, "CaloCell_SuperCell_ID") );
+
+  for (const auto& cell : * jk_scellsCollection){
+
+    const CaloSampling::CaloSample sample = (cell)->caloDDE()->getSampling();
+    const Identifier ID = (cell)->ID(); // super cell unique ID
+    int region = idHelper->region(ID);
+    int layer = -1;
+    int pos_neg = idHelper->pos_neg(ID);
+    int eta_index = idHelper->eta(ID);
+    const int phi_index = idHelper->phi(ID);
+    float et = (cell)->energy();
+    int prov = (cell)->provenance();
+
+    /*
+  CaloSampling:
+    PreSamplerB  0
+           EMB1  1
+           EMB2  2
+           EMB3  3
+
+    PreSamplerE  4
+           EME1  5
+           EME2  6
+           EME3  7
+
+           HEC0  8
+           HEC1  9
+           HEC2  10
+           HEC3  11
+    */
+
+    //We need to explicitly avoid +/- 3 pos_neg supercells! These go beyond |eta| == 2.5
+    if(abs(pos_neg) == 3){ continue; }
+
+    // LOCAL TO GLOBAL ETA INDEX PATCH - USE A 'TOWER OFFSET' TO MARK THE START OF THE ETA_INDEX COUNTING (e.g. the rounded eta value of the innermost supercell)
+    switch(sample){
+    case CaloSampling::PreSamplerB: { break; }
+    case CaloSampling::EMB1: {
+      if(region == 1){ eta_index += 56; }
+      break;
+    }
+    case CaloSampling::EMB2: {
+      if(region == 1){ eta_index += 56; }
+      break;
+    }
+    case CaloSampling::EMB3: { break; }
+    case CaloSampling::PreSamplerE: { eta_index += 15; break; }
+    case CaloSampling::EME1: {
+      if(region == 0){ eta_index += 14; }
+      else if (region == 1){ /* doesn't exist */ }
+      else if (region == 2){ eta_index += 60; }
+      else if (region == 3){ eta_index += 108; } //6 supercell region
+      else if (region == 4){ eta_index += 80; }
+      else if (region == 5){ eta_index += 24; }
+      break;
+    }
+    case CaloSampling::EME2: {
+      if(region == 0){ eta_index += 14; }
+      else if (region == 1){ eta_index += 57; }
+      break;
+    }
+    case CaloSampling::EME3: { eta_index += 15; break; }
+    case CaloSampling::HEC0:
+    case CaloSampling::HEC1:
+    case CaloSampling::HEC2:
+    case CaloSampling::HEC3: { eta_index += 15; break; }
+    default: { /*ATH_MSG_DEBUG("Not doing anything since sample = " << sample);*/ break; }
+    }
+
+    FindAndConnectTower(my_jTowerContainerRaw,sample,region,layer,pos_neg,eta_index,phi_index,ID,et,prov,doPrint);
+
+  }
+
+  return StatusCode::SUCCESS;
+  
+}
+
+
+void jSuperCellTowerMapper::ConnectSuperCellToTower(std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw,int iJTower, Identifier ID, int iCell, float et, int layer, bool doenergysplit){
+
+  LVL1::jTower * tmpTower = my_jTowerContainerRaw->findTower(iJTower);
+
+  if(tmpTower){
+    tmpTower->setSCID(ID,iCell,et,layer,doenergysplit);
+  }
+
+}
+
+  int jSuperCellTowerMapper::FindAndConnectTower(std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov,bool doPrint)
+{
+
+  // bool for the special case of 1.8 < eta < 2.0 only in the front layer
+  bool doenergysplit = false;
+  
+  // bool as a flag to enable or disable the connection of supercells to towers according to their location and identities
+  bool validcell = true;
+
+  // We tell the jTower which supercell unique ID is in each of it's available 'slots'
+  int towereta = -99; // to be filled with tower eta value to help find it
+  int towerphi = -99; // to be filled with tower phi value to help find it
+  int iJTower = -99; // The tower ID which the supercell will be assigned to
+  int iCell = -1; // The position within the Tower that the supercell will be assigned to
+  int towerID_Modifier = -999999999; // adjustable tower ID modifier to fit tower Id scheme
+
+  /*    
+  ** iCell Numbering Scheme **
+  
+  Let's use the following scheme (from low to high eta regardless of detector side):
+  Layer 0:  Cell 0 (Anything EM related)
+  Layer 1:  Cell 1 (HEC or TILE, if we have them!)
+  */
+  
+
+  /*
+  ** Structure of the EMB in Supercells **
+  
+  0 < 1.4 in steps of 0.1 == 14 towers
+  1.4 < 1.52 in steps of 0.12  ==> THIS TOWER IS MOVED TO TRANS TOWER REGION
+  14 towers total (all by presampler)
+  64 towers in phi in total
+  
+  896 towers in EMB per side
+  1792 towers in EMB total  
+  */
+  
+  /*
+  ** Structure of the TRANS in Supercells **
+
+  1.4 < 1.5, 1 special tower made from EMB and EME supercells together
+  1 tower in eta
+  64 towers in phi
+
+  64 towers in TRANS total
+  */
+
+  /*
+  ** Structure of the EMEC in Supercells **
+  
+  1.375 < 1.5, funny behaviour, treated as 1 special tower ==> 1 tower === TRANSITION TOWER NOW!
+  1.5 < 1.8 standard towers by presampler ==> 3 towers
+  1.8 < 2.0 standard towers by back ==> 2 towers
+  2.0 < 2.4 standard towers by back ==> 4 towers
+  2.4 < 2.5 standard tower by back ==> 1 tower
+  2.5 < 3.1, funny behaviour, treated as 3 wide towers ==> 3 towers.   Also wide in phi!  ===> WE DON'T CARE ABOUT |ETA| > 2.5
+  3.1 < 3.2 standard tower by back ==> 1 tower.  Also wide in phi!  ===> WE DON'T CARE ABOUT |ETA| > 2.5
+  10 towers in eta in total (by different means) (IGNORING ABOVE |ETA| > 2.5)
+  64 towers initially in phi (IGNORING ABOVE |ETA| > 2.5)
+  
+  640 towers in EME per side
+  1280 towers in EME total  
+  */
+  
+
+  /*
+  ** Structure of the HEC in Supercells **
+  
+  1.5 - 2.5, [Region 0] standard towers by presampler ==> layer on top of existing towers
+  
+  */
+  
+  /*
+  ** Notes on overall structure **
+    Total number of expected towers can be as high as: 896+640 = 1536 per side + 64 transition region towers (TRANS) each side = 3200 total <=== This is the correct value!
+  */
+
+  /*
+  ** Notes on Tower ID Number Scheme **
+
+    Left Barrel IETower = 100000 + X
+    Right Barrel IETower = 200000 + X
+    Left TRANS IETower = 300000 + X;
+    Right TRANS IETower = 400000 + X;
+    Left Endcap IETower = 500000 + X
+    Right Endcap IETower = 600000 + X
+    Left Hadronic Endcap IETower =  11100000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone jTowers.
+    Right Hadronic Endcap IETower =  22200000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone jTowers.
+
+  */
+
+
+  //----------------------------------------------------------
+
+  // Begin assigning supercells to Towers
+
+  //----------------------------------------------------------
+
+  switch (sample) {
+    // E.M. Barrel (EMB)
+  case CaloSampling::PreSamplerB: { // DONE
+    // Presampler of the EMBarrel.  Supercells are 0.1 x 0.1 unless stated otherwise
+    // Region 0 has 14 supercells in 0 < eta < 1.4 and 64 supercells in phi.
+    // Region 0 has 1 supercell (0.12 x 0.1) in 1.4 < eta < 1.52 and 64 supercells in phi.  // Documentation describes this as Region 1 but the code does not. We go with Region 0.
+
+    layer = 0; // By definition for jFEX
+    
+    towereta = eta_index; // Layer 0 has super cells which are 0.1 x 0.1 - i.e. the full width of a tower - sothe eta_index matches up to the Tower Eta
+    towerphi = phi_index; // phi is standard also
+    
+    if(eta_index == 14){ // special treatment for TRANSITION tower
+      if(pos_neg < 0){ towerID_Modifier = 300000; }
+      else if(pos_neg > 0){ towerID_Modifier = 400000; }
+      iCell = 0; // By definition for jFEX
+    }
+    else{ // standard treatment for non-transition towers
+      if(pos_neg < 0){ towerID_Modifier = 100000; }
+      else if(pos_neg > 0){ towerID_Modifier = 200000; }
+      iCell = 0; // By definition for jFEX
+    }
+
+    break;
+  }
+  case CaloSampling::EMB1: 
+  case CaloSampling::EMB2: {
+    // Layer 1 of the EMBarrel.  Supercells are 0.025 x 0.1 unless stated otherwise
+    // Region 0 has 56 supercells in 0 < eta < 1.4 and 64 supercells in phi.
+    // Region 1 has 3 supercells in 1.4 < eta < 1.475 and 64 supercells in phi.
+    
+    // Layer 2 of the EMBarrel.  Supercells are 0.025 x 0.1 unless stated otherwise
+    // Region 0 has 56 supercells in 0 < eta < 1.4 and 64 supercells in phi.
+    // Region 1 has 1 supercells (0.075 x 0.1) in 1.4 < eta < 1.475 and 64 supercells in phi.
+
+    if (region == 0) {
+      towereta = eta_index / 4; // this divides integers by 4 and truncates away the decimals (rounds DOWN to an integer)
+      towerphi = phi_index;
+      if(pos_neg < 0){ towerID_Modifier = 100000; }
+      else if(pos_neg > 0){ towerID_Modifier = 200000; }
+    }
+    else if (region == 1){
+      towereta = 14; // hardcoded but is correct
+      towerphi = phi_index;
+      if(pos_neg < 0){ towerID_Modifier = 300000; }
+      else if(pos_neg > 0){ towerID_Modifier = 400000; }
+    }
+    else {
+      ATH_MSG_DEBUG("[CaloSampling::EMB1 or CaloSampling::EMB2] -> invalid 'region' value: " << region << " (Under investigation) ");
+    }
+
+    switch(sample){
+    case CaloSampling::EMB1: { 
+      iCell = 0; // By definition for jFEX
+      layer = 0; // By definition for jFEX
+      break;
+    }
+    case CaloSampling::EMB2: { 
+      //if (region == 0) { iCell = (eta_index % 4) + 5; }
+      //else if (region == 1){ iCell = 5; }
+      iCell = 0; // By definition for jFEX      
+      layer = 0; // By definition for jFEX
+      break;
+    }
+    default: {
+      ATH_MSG_DEBUG("CaloSampling::EMBX -> invalid sample for assigning iCell value! " << sample << " (Under investigation) ");
+      break;
+    }
+    }
+
+    break;
+  }
+  case CaloSampling::EMB3: {
+    // Layer 3 of the EMBarrel.  Supercells are 0.1 x 0.1 unless stated otherwise
+    // Region 0 has 14 supercells in 0 < eta < 1.4 and 64 supercells in phi.
+    // Region 1 does not exist
+    
+    layer = 0; // By definition for jFEX
+    towereta = eta_index; // Analogous to PreSamplerB
+    towerphi = phi_index;
+    
+    iCell = 0; // By definition for jFEX
+    
+    if(pos_neg < 0){ towerID_Modifier = 100000; }
+    else if(pos_neg > 0){ towerID_Modifier = 200000; }
+    
+    break;
+  }
+    // E.M. End-cap (EMEC)
+  case CaloSampling::PreSamplerE: {
+    // Region 1 has 3 supercells in 1.5 < eta < 1.8, and 64 supercells in phi.
+    // Supercells are 0.1 x 0.1.
+    
+    layer = 0; // By definition for jFEX
+
+    towereta = eta_index;
+    towerphi = phi_index;
+    
+    iCell = 0; // By definition for jFEX
+    
+    if(pos_neg < 0){ towerID_Modifier = 500000; }
+    else if(pos_neg > 0){ towerID_Modifier = 600000; }
+    
+    break;
+  }
+  case CaloSampling::EME1: {
+    // Layer 1 of the EM End-Cap.  Supercells very frequently change in size.
+    // Region 0 has 1 supercell in 1.375 < eta < 1.5, and 64 supercells in phi.  Supercells are 0.125 x 0.1.
+    // Region 1 has 12 supercells in 1.5 < eta < 1.8, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 2 has 6 (now 12??) supercells in 1.8 < eta < 2.0, and 64 supercells in phi.  Supercells are 0.0333 (0.016667 ???) x 0.1.
+    // Region 3 has 16 supercells in 2.0 < eta < 2.4, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 4 has 1 supercell in 2.4 < eta < 2.5, and 64 supercells in phi.  Supercells are 0.1 x 0.1.
+    // Region 5 has 3 supercells in 2.5 < eta < 3.1, and 32 supercells in phi.  Supercells are 0.2 x 0.2.
+    // Region 6 has 1 supercell in 3.1 < eta < 3.2, and 32 supercells in phi.  Supercells are 0.1 x 0.2
+    
+    // 1.375 < 1.5, funny behaviour, treated as 1 special tower ==> 1 tower
+    // 1.5 < 1.8 standard towers by presampler ==> 3 towers
+    // 1.8 < 2.0 standard towers by back ==> 2 towers
+    // 2.0 < 2.4 standard towers by back ==> 4 towers
+    // 2.4 < 2.5 standard tower by back ==> 1 tower
+    // 2.5 < 3.1, funny behaviour, treated as 3 wide towers ==> 3 towers
+    // 3.1 < 3.2, funny behaviour, treated as 1 tower ==> 1 tower
+    // 15 towers in total (by different means)
+    
+    layer = 0; // By definition for jFEX
+    
+    switch (region) {
+    case 0: { // special treatment for transition region
+      
+      towereta = eta_index;
+      towerphi = phi_index;
+
+      iCell = 0; // By definition for jFEX
+      break;
+    }
+    case 2: {
+
+      towereta = (eta_index / 4);
+      towerphi = phi_index;
+      
+      //iCell = (eta_index % 4) + 1;
+      iCell = 0; // By definition for jFEX
+      break;
+    }
+    case 3: {
+
+      // calc ID
+      towereta = (eta_index / 6);
+      towerphi = phi_index;
+      
+      //iCell = (eta_index % 6) + 1;
+      iCell = 0; // By definition for jFEX
+      
+      /*
+      if(iCell == 1){ iCell = 1; doenergysplit = false; }
+      else if( iCell == 2 ){ iCell = 1; doenergysplit = true; }
+      else if( iCell == 3 ){ iCell = 2; doenergysplit = false; }
+      else if( iCell == 4 ){ iCell = 3; doenergysplit = false; }
+      else if( iCell == 5 ){ iCell = 3; doenergysplit = true; }
+      else if( iCell == 6 ){ iCell = 4; doenergysplit = false; }
+      */
+
+      break;
+
+      // OUTDATED CODE LEFT HERE AS A FRIENDLY REMINDER OF SPECIAL STRUCTURE INCASE A FUTURE ISSUE ARISES======================
+      // Begin Dima---
+      // This is the special region, with 6 supercells per tower
+      // Idea here is to divide 2 out of 6 by 2 and add half ET to each of 2 "normal" SC
+      //iJTower = (eta_index / 6) + 18;
+
+      // These are the cells we will split
+      //if (eta_index % 3 == 1) {
+      //iCell = (eta_index % 6 < 3 ? 0 : 2);
+      //iCell2 = iCell + 1;
+      //} else {
+      // These ones just need assigning to the correct location
+      // So that 0, 2, 3, 5 => 0, 1, 2, 3
+      //iCell = (eta_index % 6) / 1.45;
+      //}
+      // end DIMA---
+      // ======================================================================================================================
+    }
+    case 4: {
+
+      towereta = (eta_index / 4);
+      towerphi = phi_index;
+      
+      //iCell = (eta_index % 4) + 1;
+      iCell = 0; // By definition for jFEX
+      break;
+    }
+    case 5: {
+
+      towereta = eta_index ;
+      towerphi = phi_index;
+      
+      //iCell = 1;
+      iCell = 0; // By definition for jFEX
+      break;
+    }
+    default: {
+      // This should never fire because we don't go beyond 2.5 
+      ATH_MSG_DEBUG("CaloSampling::EME1 -> invalid 'region' value: " << region << " (Under investigation) ");
+      break;
+    }
+      break;
+    }
+
+    if(region != 0){
+      if(pos_neg < 0){ towerID_Modifier = 500000; }
+      else if(pos_neg > 0){ towerID_Modifier = 600000; }
+    }
+    else if(region == 0){
+      // TRANSITION REGION TREATMENT!
+      if(pos_neg < 0){ towerID_Modifier = 300000; }
+      else if(pos_neg > 0){ towerID_Modifier = 400000; }
+    }
+
+    break;
+  }
+  case CaloSampling::EME2: {
+    
+    // Layer 2 of the EM End-Cap.  Supercells very frequently change in size.
+    // Region 0 has 1 supercell in 1.375 < eta < 1.425, and 64 supercells in phi.  Supercells are 0.05 x 0.1.
+    // Region 0 also has 3 supercells in 1.425 < eta < 1.5, and 64 supercells in phi.  Supercells are 0.025 x 0.1
+    // Region 1 has 12 supercells in 1.5 < eta < 1.8, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 2 has 8 supercells in 1.8 < eta < 2.0, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 3 has 16 supercells in 2.0 < eta < 2.4, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 4 has 4 supercells in 2.4 < eta < 2.5, and 64 supercells in phi.  Supercells are 0.025 x 0.1.
+    // Region 5 has 3 supercells in 2.5 < eta < 3.1, and 32 supercells in phi.  Supercells are 0.2 x 0.2.
+    // Region 6 has 1 supercell in 3.1 < eta < 3.2, and 32 supercells in phi.  Supercells are 0.1 x 0.2
+    
+    layer = 0; // By definition for jFEX
+    
+    switch (region) {
+    case 0: { // special treatment for TRANSITON region
+
+      //layer = 3; // change layer label for ET threshold treatment since we are treating this as a layer3 cell - it's an extreme special case cell as part of tne transition region
+      layer = 0; // By definition for jFEX
+
+      towereta = eta_index;
+      towerphi = phi_index;
+
+      //iCell = 9;
+      iCell = 0; // By definition for jFEX
+
+      break;
+    }
+    case 1: {
+
+      towereta = (eta_index / 4);
+      towerphi = phi_index;
+      
+      //iCell = (eta_index % 4) + 5;
+      iCell = 0; // By definition for jFEX
+
+      break;
+    }
+    default: {
+      ATH_MSG_DEBUG("CaloSampling::EME2 -> invalid 'region' value: " << region << " (Under investigation) ");
+      break;
+    }
+      break;
+    }
+    
+    if(region == 0){
+      // TRANSITION REGION TREATMENT! 
+      if(pos_neg < 0){ towerID_Modifier = 300000; } 
+      else if(pos_neg > 0){ towerID_Modifier = 400000; }
+    }
+    else {
+      if( (eta_index / 4) < 15 ){ 
+	if(pos_neg < 0){ towerID_Modifier = 300000; }
+	else if(pos_neg > 0){ towerID_Modifier = 400000; }
+      }
+      else{
+	if(pos_neg < 0){ towerID_Modifier = 500000; }
+	else if(pos_neg > 0){ towerID_Modifier = 600000; }
+      }
+    }
+
+    break;
+  }
+  case CaloSampling::EME3: {
+    
+    // Layer 3 of the EM End-Cap.  Supercells are 0.1 x 0.1 unless stated otherwise.
+    // Region 0 does not exist.
+    // Region 1 has 3 supercells in 1.5 < eta < 1.8, and 64 supercells in phi.  Supercells are 0.1 x 0.1.
+    // Region 2 has 2 supercells in 1.8 < eta < 2.0, and 64 supercells in phi.  Supercells are 0.1 x 0.1.
+    // Region 3 has 4 supercells in 2.0 < eta < 2.4, and 64 supercells in phi.  Supercells are 0.1 x 0.1.
+    // Region 4 has 1 supercells in 2.4 < eta < 2.5, and 64 supercells in phi.  Supercells are 0.1 x 0.1.
+    // No other Regions exist
+    
+    layer = 0; // By definition for jFEX
+    
+    switch (region) {
+    case 0: {
+
+      towereta = eta_index;
+      towerphi = phi_index;
+      
+      //iCell = 9; // By definition
+      iCell = 0; // By definition for jFEX
+
+      break;
+    }
+    default: {
+      ATH_MSG_DEBUG("CaloSampling::EME3 -> invalid 'region' value: " << region << " (Under investigation) ");
+      break;
+    }
+      break;
+    }
+    
+    if(pos_neg < 0){ towerID_Modifier = 500000; }
+    else if(pos_neg > 0){ towerID_Modifier = 600000; }
+
+    break;
+  }
+    // Hadronic End-cap (HEC)
+  case CaloSampling::HEC0:
+  case CaloSampling::HEC1:
+  case CaloSampling::HEC2:
+  case CaloSampling::HEC3: {
+    
+    // All Layers of the Hadronic End-Cap.
+    // Region 0 has 10 supercells in 1.5 < eta < 2.5, and 32 supercells in phi.  Supercells are 0.1 x 0.1.
+    // Region 1 has 4 supercells in 2.5 < eta < 3.3, and 16 supercells in phi.  Supercells are 0.2 x 0.2.
+    
+    switch(region){
+    case 0: {
+
+      towereta = eta_index;
+      towerphi = phi_index;
+      
+      layer = 1; // By definition for jFEX
+      
+      switch (sample){ // only one supercell per layer in all regions for HECX
+      case CaloSampling::HEC0: { iCell = 1;/*iCell = 10;*/ break; }
+      case CaloSampling::HEC1: { iCell = 1;/*iCell = 11;*/ break; }
+      case CaloSampling::HEC2: { iCell = 1;/*iCell = 12;*/ break; }
+      case CaloSampling::HEC3: { iCell = 1;/*iCell = 13;*/ break; }
+      default: {
+	ATH_MSG_DEBUG("CaloSampling::HECX -> invalid sample for assigning iCell value! " << sample << " (Under investigation) ");
+	break;
+      }
+      }
+      break;
+      
+    }
+    case 1: {
+      validcell = false; // any region 1 HEC cells are actually with eta > 2.5
+      ATH_MSG_DEBUG("CaloSampling::HECX Region 1 invalid as outside of eta range! Should be included in the future!");
+      break;
+    }
+    default: { break; }
+    }
+    
+    // Tower connection
+    if(pos_neg < 0){ towerID_Modifier = 500000; }
+    else if(pos_neg > 0){ towerID_Modifier = 600000; }
+    
+    break;
+  }
+  case CaloSampling::TileBar0:
+  case CaloSampling::TileBar1:
+  case CaloSampling::TileBar2: {
+    REPORT_MESSAGE_WITH_CONTEXT (MSG::DEBUG, "jSuperCellTowerMapper") << "Supercell is from Tile Barrel - it will be ignored.";
+    validcell = false;
+    //ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell is from Tile Barrel - it will be ignored.");
+    break;
+  }
+  case CaloSampling::TileGap1:
+  case CaloSampling::TileGap2:
+  case CaloSampling::TileGap3: {
+    //ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell is from Tile Gap (ITC and scintillator) - it will be ignored.");
+    validcell = false;
+    break;
+  }
+  case CaloSampling::TileExt0:
+  case CaloSampling::TileExt1:
+  case CaloSampling::TileExt2: {
+    //ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell is from Tile Extended Barrel - it will be ignored.");
+    validcell = false;
+    break;
+  }
+  case CaloSampling::FCAL0:
+  case CaloSampling::FCAL1:
+  case CaloSampling::FCAL2: {
+    //ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell is from Forward EM endcap - it will be ignored.");
+    validcell = false;
+    break;
+  }
+  case CaloSampling::MINIFCAL0:
+  case CaloSampling::MINIFCAL1:
+  case CaloSampling::MINIFCAL2:
+  case CaloSampling::MINIFCAL3: {
+    //ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercells is from MiniFCAL - it will be ignored.");
+    validcell = false;
+    break;
+  }
+  case CaloSampling::Unknown: {
+    //ATH_MSG_WARNING("\n==== jSuperCellTowerMapper ============ Supercell sampling is officially unknown - it will be ignored. (Needs investigation).  Please report this!");
+    validcell = false;
+    break;
+  }
+  default: {
+    ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell has invalid CaloSampling value: " << sample << " (Needs investigation).  Please report this!");
+    validcell = false;
+    break;
+  }
+  }
+
+  if(validcell){
+    iJTower = FindTowerIDForSuperCell(towereta, towerphi) + towerID_Modifier;
+    if(doPrint){
+      PrintCellSpec(sample, layer, region, eta_index, phi_index, pos_neg, iJTower, iCell, prov, ID, doenergysplit);
+    }
+    ConnectSuperCellToTower( my_jTowerContainerRaw, iJTower, ID, iCell, et, layer, doenergysplit);
+  }
+
+  // END ITERATING OVER SUPER CELLS+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++
+  
+  return 1;
+  
+  }
+
+int jSuperCellTowerMapper::FindTowerIDForSuperCell(int towereta, int towerphi)
+{
+
+  return (towerphi + (64 * towereta));
+
+}
+
+  void jSuperCellTowerMapper::PrintCellSpec(const CaloSampling::CaloSample sample, int layer, const int region, const int eta_index, const int phi_index, const int pos_neg, int iJTower, int iCell, int prov, Identifier ID ,bool doenergysplit)
+{
+  
+  std::string sampleName = "";
+  
+  switch (sample) {
+  case CaloSampling::PreSamplerB: { sampleName = "PreSamplerB"; break; }
+  case CaloSampling::EMB1: { sampleName = "EMB1"; break; }
+  case CaloSampling::EMB2: { sampleName = "EMB2"; break; }
+  case CaloSampling::EMB3: { sampleName = "EMB3"; break; }
+  case CaloSampling::PreSamplerE: { sampleName = "PreSamplerE"; break; }
+  case CaloSampling::EME1: { sampleName = "EME1"; break; }
+  case CaloSampling::EME2: { sampleName = "EME2"; break; }
+  case CaloSampling::EME3: { sampleName = "EME3"; break; }
+  case CaloSampling::HEC0: { sampleName = "HEC0"; break; }
+  case CaloSampling::HEC1: { sampleName = "HEC1"; break; }
+  case CaloSampling::HEC2: { sampleName = "HEC2"; break; }
+  case CaloSampling::HEC3: { sampleName = "HEC3"; break; }
+  default: {
+    ATH_MSG_DEBUG("\n==== jSuperCellTowerMapper ============ Supercell has invalid CaloSampling value: " << sample << " (Needs investigation).  Please report this!");
+    break;
+  }
+  }
+  
+  ATH_MSG_DEBUG("ASSIGNED CELL:::  CASE: " << sampleName
+		<< "\tSample: " << sample
+		<< "\tLayer: " << layer
+		<< "\tRegion: " << region
+		<< "\tEta_Index: " << eta_index
+		<< "\tPhi_Index: " << phi_index
+		<< "\tPosNeg: " << pos_neg
+		<< "\tiJTower: " << iJTower
+		<< "\tiCell: " << iCell
+		<< "\tDoEnergySplit: " << doenergysplit
+		<< "\tProvenance: " << prov
+		<< "\tID: " << ID
+		<< " ");
+  
+  return;
+}
+
+
+} // end of LVL1 namespace
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTower.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTower.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f10d8a27a5716d49c9e8f7639ffcb6062165c479
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTower.cxx
@@ -0,0 +1,336 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jTower.h  -  description
+//                              -------------------
+//     begin                : 19 02 2019
+//     email                : Alan.Watson@cern.ch, jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jFEXCompression.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include <cmath>
+
+
+namespace LVL1 {
+
+  const int s_cells[] = {1,1};
+  const int s_offsets[] = {0,1};
+  
+  // default constructor
+  jTower::jTower():
+    m_eta(0.),
+    m_phi(0.),
+    m_tower_id(-9999999),
+    m_posneg(0)
+  {
+    this->clearET();
+  }
+  
+  /** constructs a tower and sets the coordinates and identifier */
+  jTower::jTower(float eta, float phi, int id_modifier, int posneg):
+    m_eta(eta),
+    m_phi(phi),
+    m_tower_id(id_modifier + phi + (64 * eta)),
+    m_posneg(posneg)
+  {
+    this->clearET();
+  }
+  
+  
+  /** Clear and resize ET value vector */
+  void jTower::clearET()
+  {
+    m_et.clear();
+    m_et.resize(2);
+    m_et_float.clear();
+    m_et_float.resize(2);
+    for (unsigned int i=0; i<m_et.size(); i++){
+      m_et[i] = 0;
+      m_et_float[i] = 0.0;
+    }
+  }
+
+  /** Clear and resize EM SC Identifier value vector */
+  void jTower::clear_EM_scIDs()
+  {
+    m_EM_scID.clear();
+  }
+
+  /** Clear and resize HAD SC Identifier value vector */
+  void jTower::clear_HAD_scIDs()
+  {
+    m_HAD_scID.clear();
+  }
+
+
+  void jTower::setPosNeg(int posneg){
+    
+    m_posneg = posneg;
+
+    return;
+
+  }
+
+  /** Add ET to a specified cell */
+  void jTower::addET(float et, int cell)
+  {
+    /// Check cell index in range for layer - should probably throw a warning...
+    if (cell < 0  || cell > 2){ return; }
+    
+    m_et_float[cell] += et;
+
+    return;
+
+  }
+  void jTower::setET(int cell, float et, int layer) {
+    /// Check cell index in range for layer
+
+    if((layer < 0) || (layer > 2)){
+      return; //need to throw an error really...
+    }
+
+    if (cell < 0  || cell > 2){ return; } //need to throw an error really...
+      
+    addET(et, cell);
+    
+    //multi linear digitisation encoding
+    unsigned int ecode = jFEXCompression::Compress(m_et_float[cell]);
+    int outET = jFEXCompression::Expand(ecode);
+    
+    //noise cut
+    const bool SCpass = noiseCut(outET,layer);
+    if (SCpass){ m_et[cell] = outET;}
+    else{ m_et[cell] = 0; }
+    
+    return;
+
+  }
+
+  /** Set supercell position ID and ET**/
+  void jTower::setSCID(Identifier ID, int cell, float et, int layer, bool doenergysplit)
+  {
+
+    if((layer < 0) || (layer > 2)){
+      std::stringstream errMsg;
+      errMsg << "Attempt to set jTower SCID in invalid layer (" << layer << ")";
+      throw std::runtime_error(errMsg.str().c_str());
+      return; //need to throw an error really...
+    }
+    
+    /// Check cell index in range for layer
+    if (cell < 0  || cell > 2){
+      std::stringstream errMsg;
+      errMsg << "Attempt to set jTower SCID in invalid cell slot (" << cell << ")";
+      throw std::runtime_error(errMsg.str().c_str());
+      return; 
+    }
+
+    if(!doenergysplit){
+
+      addET(et, cell);
+
+      if(layer == 0){
+	m_EM_scID.push_back(ID);
+      }
+      else if(layer == 1){
+	m_HAD_scID.push_back(ID);
+      }
+	
+      //multi linear digitisation encoding
+      unsigned int ecode = jFEXCompression::Compress(m_et_float[cell]); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+      int outET = jFEXCompression::Expand(ecode); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+      //noise cut
+      const bool SCpass = noiseCut(outET,layer);
+      if (SCpass){ m_et[cell] = outET;}
+      else{ m_et[cell] = 0; }
+      
+    }
+    else{
+
+      float et_half = et*0.5;
+      addET(et_half, cell);
+      addET(et_half, cell+1);
+
+      unsigned int ecode1 = jFEXCompression::Compress(m_et_float[cell]); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+      int outET1 = jFEXCompression::Expand(ecode1); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+      unsigned int ecode2 = jFEXCompression::Compress(m_et_float[cell+1]); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+      int outET2 = jFEXCompression::Expand(ecode2); //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+
+      //noise cuts
+      const bool SCpass1 = noiseCut(outET1,layer);
+      if (SCpass1){ m_et[cell] = outET1;}
+      else{ m_et[cell] = 0; }
+      const bool SCpass2 = noiseCut(outET2,layer);
+      if (SCpass2){ m_et[cell+1] = outET2;}
+      else{ m_et[cell+1] = 0; }
+
+    }
+
+    return;
+
+  }
+
+  /** Apply noise cut per layer **/
+  bool jTower::noiseCut(int et, int layer) const //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+  {
+
+    bool pass=true;                                                                                                         
+    if(layer==0) {
+      if(et<m_noisecutPS){ pass = false; } //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+    } 
+    else if (layer==1) {
+      if(et<m_noisecutL1){ pass = false; } //PROBABLY NOT TRUSTWORTHY - NEED TO UPDATE FOR JFEX
+    } 
+    else { pass = false; }
+    
+    return pass;
+
+  }
+
+  /** Return global eta index.
+      Should be derived from tower ID, should be corrected in the future.
+      Need to also think what index range should be (thinking ahead to Run2) */
+  int jTower::iEta() const {
+    const int index = (m_eta + 2.5)*10; // /0.1;  // Equivalent to divide by 0.1 which is the Tower size
+    return index;
+  }
+  
+  /** Return global phi index.
+      Should be derived from tower ID, should be corrected in the future.
+      Decision here is whether phi is signed or not */
+  int jTower::iPhi() const {
+    int index = 32*m_phi/M_PI;
+    if (m_phi < 0) index = 32*(m_phi + 2*M_PI)/M_PI;
+    const int cindex = index;
+    return cindex;
+  }
+  
+  /** Return ET of specified supercell */
+  int jTower::getET(unsigned int layer,  int cell) const {
+    
+    /// Check cell index in range for layer
+    if (layer > 2 || cell < 0 || cell >= s_cells[layer]) return 0;
+    
+    // Return ET
+    return m_et[s_offsets[layer] + cell];
+    
+  }
+
+  /** Return ET of specified supercell FLOAT VERSION */
+  float jTower::getET_float(unsigned int layer, int cell) const {
+
+    /// Check cell index in range for layer
+    if (layer > 2 || cell < 0 || cell >= s_cells[layer]) return 0;
+
+    // Return ET
+    return m_et_float[s_offsets[layer] + cell];
+
+  }
+
+  /** Return ET of all supercells together*/
+  int jTower::getTotalET() const{
+    
+    int tmp = 0;
+    for (unsigned int i=0; i<m_et.size(); i++){
+      tmp += m_et[i];
+    }
+
+    return tmp;
+    
+  }
+
+  /** Return ET of all supercells together FLOAT VERSION */
+  float jTower::getTotalET_float() const{
+
+    float tmp = 0;
+    for (unsigned int i=0; i<m_et_float.size(); i++){
+      tmp += m_et_float[i];
+    }
+
+    return tmp;
+
+  }
+
+  
+  /** Return supercell ET values for specified layer */
+  std::vector<int> jTower::getLayerETvec(unsigned int layer) const {
+    
+    /// Create empty vector of data
+    std::vector<int> cells;
+    
+    /// Check cell index in range for layer
+    if (layer > 2) return cells;
+    
+    /// Fill output vector
+    for (int cell = 0; cell < s_cells[layer]; ++cell) cells.push_back(m_et[s_offsets[layer] + cell]);
+    
+    return cells;
+  }
+
+
+  /** Return supercell ET values for specified layer FLOAT VERSION */
+  std::vector<float> jTower::getLayerETvec_float(unsigned int layer) const {
+
+    /// Create empty vector of data
+    std::vector<float> cells;
+
+    /// Check cell index in range for layer
+    if (layer > 2) return cells;
+
+    /// Fill output vector
+    for (int cell = 0; cell < s_cells[layer]; ++cell) cells.push_back(m_et_float[s_offsets[layer] + cell]);
+
+    return cells;
+  }
+
+
+  /** Return supercell ET values for specified layer */
+  int jTower::getLayerTotalET(unsigned int layer) const {
+        
+    if (layer == 0){
+      return m_et[0];
+    }
+    else if (layer == 1){
+      return (m_et[1]);
+    }
+    
+    return 0;
+    
+  }
+
+  /** Return supercell ET values for specified layer FLOAT VERSION */
+  float jTower::getLayerTotalET_float(unsigned int layer) const {
+
+    if (layer == 0){
+      return m_et_float[0];
+    }
+    else if (layer == 1){
+      return (m_et_float[1]);
+    }
+
+    return 0;
+
+  }
+
+  std::vector<Identifier> jTower::getLayerSCIDs(unsigned int layer) const{
+
+    if (layer == 0){
+      return m_EM_scID;
+    }
+    else if (layer == 1){
+      return m_HAD_scID;
+    }
+
+    return std::vector<Identifier>();
+
+  }
+
+  
+} // end of namespace bracket
+
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerBuilder.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerBuilder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fd2263c86a0cd65755d0d6e480e94725829d4f64
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerBuilder.cxx
@@ -0,0 +1,199 @@
+/*
+    Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerBuilder.h"
+
+#include "L1CaloFEXSim/jTowerContainer.h"
+
+#include "TROOT.h"
+#include "TH1.h"
+#include "TH1F.h"
+#include "TPad.h"
+#include "TCanvas.h"
+
+// TOWER IS A COLLECTION OF SUPER CELLS
+// IT SHOULD HAVE A UNIQUE ID
+// IT SHOULD BE ABLE TO RETURN LIST OF SUPER CELLS BELONGING TO IT
+
+// THIS IS A CLASS DESIGNED TO BUILD AN JTOWER USING THE JTOWER CLASS AND THEN PRINT THE RELEVANT INFORMATION TO THE SCREEN USING FUNCTION CALLS FROM THE JTOWER CLASS
+
+namespace LVL1 {
+
+jTowerBuilder::jTowerBuilder(const std::string& type,const std::string& name,const IInterface* parent):
+    AthAlgTool(type,name,parent)
+{
+  declareInterface<IjTowerBuilder>(this);
+}
+
+
+void jTowerBuilder::init(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) 
+{
+
+  execute(jTowerContainerRaw);
+
+}
+
+
+void jTowerBuilder::reset() 
+{
+
+}
+
+
+void jTowerBuilder::execute(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) 
+{
+  BuildAllTowers(jTowerContainerRaw);
+}
+ 
+  // TOWER IDs FOR CLARITY
+  // Left Barrel IETower = 100000 + X
+  // Right Barrel IETower = 200000 + X
+  // Left Transition ID Tower = 300000 + X;
+  // Right Transition ID Tower = 400000 + X;
+  // Left Endcap ID Tower = 500000 + X
+  // Right Endcap ID Tower = 600000 + X
+  // Left Hadronic Endcap ID Tower = 11100000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone jTowers.
+  // Right Haronic Endcap ID Tower = 22200000 + X --> These are just Layer 5 of Endcap Towers.  They will never be generated as standalone jTowers.
+
+ void jTowerBuilder::BuildEMBjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const 
+{
+  // Regions 0 only.  Region 1 is 'transition region'.
+  for (int ieta = 0; ieta < 14; ++ieta) { // loop over 14 eta steps (ignoring last step as it is transition region)
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 100000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 200000, 1);
+    }
+  }
+
+}
+
+void jTowerBuilder::BuildTRANSjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const
+{
+
+  int TRANS_MODIFIER = 14;
+  int tmpVal = TRANS_MODIFIER;
+
+  for (int ieta = tmpVal; ieta < tmpVal + 1; ieta++){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 300000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 400000, 1);
+    }
+  }
+
+}
+
+  void jTowerBuilder::BuildEMEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const
+{
+  // Region 1
+  int EME_MODIFIER = 15;
+  int tmpVal = EME_MODIFIER;
+
+  for (int ieta = tmpVal; ieta < tmpVal + 3; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 500000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 600000, 1);
+    }
+    EME_MODIFIER++;
+  }
+
+  // Region 2
+  tmpVal = EME_MODIFIER;
+  for (int ieta = tmpVal; ieta < tmpVal + 2; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 500000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 600000, 1);
+    }
+    EME_MODIFIER++;
+  }
+
+  // Region 3
+  tmpVal = EME_MODIFIER;
+  for (int ieta = tmpVal; ieta < tmpVal + 4; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 500000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 600000, 1);
+    }
+    EME_MODIFIER++;
+  }
+
+  // Region 4
+  tmpVal = EME_MODIFIER;
+  for (int ieta = tmpVal; ieta < tmpVal + 1; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 500000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 600000, 1);
+    }
+    EME_MODIFIER++;
+  }
+
+
+}
+
+  void jTowerBuilder::BuildEMIEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const
+  {
+    int EMEI_MODIFIER = 25;
+    int tmpVal = EMEI_MODIFIER;
+
+    for (int ieta = tmpVal; ieta < tmpVal + 25; ++ieta){ // loop over eta steps
+      for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+	BuildSingleTower(jTowerContainerRaw, ieta, iphi, 700000, -1);
+	BuildSingleTower(jTowerContainerRaw, ieta, iphi, 800000, 1);
+      }
+      EMEI_MODIFIER++;
+    }
+
+  }
+
+// REDUNDANT AND NOT USED, BUT MAY BE REQUIRED IN FUTURE ==========================================================================================================
+  void jTowerBuilder::BuildHECjTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const
+{
+
+  // Region 0
+  int HEC_MODIFIER = 29;
+  int tmpVal = HEC_MODIFIER;
+  for (int ieta = tmpVal; ieta < tmpVal + 10; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 64; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 11100000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 22200000, 1);
+    }
+    HEC_MODIFIER++;
+  }
+
+  // Region 1
+  tmpVal = HEC_MODIFIER;
+  for (int ieta = tmpVal; ieta < tmpVal + 4; ++ieta){ // loop over eta steps
+    for (int iphi = 0; iphi < 32; ++iphi){ // loop over 64 phi steps
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 11100000, -1);
+      BuildSingleTower(jTowerContainerRaw, ieta, iphi, 22200000, 1);
+    }
+    HEC_MODIFIER++;
+  }
+
+}
+
+void jTowerBuilder::BuildSingleTower(std::unique_ptr<jTowerContainer> & jTowerContainerRaw,float eta, float phi, float keybase, int posneg)  const
+{
+
+  jTowerContainerRaw->push_back(eta, phi, keybase, posneg);
+
+}
+
+void jTowerBuilder::BuildAllTowers(std::unique_ptr<jTowerContainer> & jTowerContainerRaw) const
+{
+  BuildEMBjTowers(jTowerContainerRaw);
+  BuildTRANSjTowers(jTowerContainerRaw);
+  BuildEMEjTowers(jTowerContainerRaw);
+  BuildEMIEjTowers(jTowerContainerRaw);
+
+}
+
+} // end of LVL1 namespace
diff --git a/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerContainer.cxx b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerContainer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6517e9604e538ea794628ea0e1abd70b95c73ac0
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEX/L1CaloFEXSim/src/jTowerContainer.cxx
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Code stolen shamelessly from Calorimeter/CaloEvent/src/CaloCellContainer.cxx and modified
+
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "AthenaKernel/errorcheck.h"
+#include "CLHEP/Geometry/Vector3D.h"
+#include <boost/algorithm/cxx11/partition_point.hpp>
+#include <atomic>
+
+namespace LVL1{
+
+jTowerContainer::jTowerContainer(SG::OwnershipPolicy ownPolicy) : 
+  DataVector<LVL1::jTower>(ownPolicy)
+{ 
+  m_map_towerID_containerIndex.clear();
+}
+
+void jTowerContainer::push_back(float eta, float phi, float keybase, int posneg)
+{
+  DataVector<LVL1::jTower>::push_back(std::make_unique<jTower>(eta,phi,keybase,posneg));
+}
+
+void jTowerContainer::print() const {
+  REPORT_MESSAGE_WITH_CONTEXT (MSG::WARNING, "jTowerContainer") << "jTowerContainer::print not implemented";
+}
+
+
+const LVL1::jTower * jTowerContainer::findTower(int towerID) const
+{
+  int container_index = -1;
+  container_index = m_map_towerID_containerIndex.find(towerID)->second;
+  if(container_index >= 0){
+    return (*this)[container_index];
+  }
+  return nullptr;
+}
+
+LVL1::jTower * jTowerContainer::findTower(int towerID)
+{
+  int container_index = -1;
+  container_index = m_map_towerID_containerIndex.find(towerID)->second;
+  if(container_index >= 0){
+    return (*this)[container_index];
+  }
+  return nullptr;
+}
+
+void jTowerContainer::clearContainerMap()
+{
+  m_map_towerID_containerIndex.clear();
+}
+
+bool jTowerContainer::fillContainerMap(){
+  clearContainerMap();
+  size_t ntowers = size();
+  for (size_t itower = 0; itower < ntowers; itower++) {
+    const jTower * theTower = (*this)[itower];
+    int towerID = theTower->constid();
+    int container_index = itower;
+    m_map_towerID_containerIndex.insert(std::pair<int,int>(towerID,container_index));
+  }
+  return true;
+}
+
+}
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeSuperCellTowerMapper.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeSuperCellTowerMapper.h
index f21e9141df814256fc1ae6140ef341a02e2888ed..7ff82b0e33dc762d921c521d3c3184cb6dc632f4 100644
--- a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeSuperCellTowerMapper.h
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeSuperCellTowerMapper.h
@@ -39,7 +39,7 @@ Interface definition for eSuperCellTowerMapper
     virtual void reset() = 0;
     
     virtual int FindAndConnectTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov, bool doPrint) = 0;
-    virtual int ConnectSuperCellToTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) = 0;
+    virtual void ConnectSuperCellToTower(/*eTowerContainer**/std::unique_ptr<eTowerContainer> & my_eTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) = 0;
     virtual int FindTowerIDForSuperCell(int towereta, int towerphi) = 0;
     virtual void PrintCellSpec(const CaloSampling::CaloSample sample, int layer, const int region, const int eta_index, const int phi_index, const int pos_neg, int iETower, int iCell, int prov, Identifier ID, bool doenergysplit) = 0;
 
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeTowerBuilder.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeTowerBuilder.h
index 1416a55ffc8a558f6671ce0ddb7242a220bf4361..19d3c0f7a05e5d914ba94aa0ac862d4fdc02d759 100644
--- a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeTowerBuilder.h
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IeTowerBuilder.h
@@ -29,12 +29,12 @@ Interface definition for eTowerBuilder
   public:
     static const InterfaceID& interfaceID( ) ;
 
-    virtual void BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
-    virtual void BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
-    virtual void BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0 ;
-    virtual void BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
-    virtual void BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
-    virtual void BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainer,float eta, float phi, float keybase, int posneg) = 0;
+    virtual void BuildEMBeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) const = 0;
+    virtual void BuildTRANSeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) const = 0;
+    virtual void BuildEMEeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) const = 0 ;
+    virtual void BuildHECeTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) const = 0;
+    virtual void BuildAllTowers(std::unique_ptr<eTowerContainer> & eTowerContainer) const = 0;
+    virtual void BuildSingleTower(std::unique_ptr<eTowerContainer> & eTowerContainer,float eta, float phi, float keybase, int posneg) const = 0;
     
     virtual void init(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
     virtual void execute(std::unique_ptr<eTowerContainer> & eTowerContainer) = 0;
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXFPGA.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXFPGA.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed00d8380c5cfe8491ee6f5f7622bfcf44c918bd
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXFPGA.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXFPGA.h  -
+//                              -------------------
+//     begin                : 23 03 2019
+//     email                :  jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#ifndef IjFEXFPGA_H
+#define IjFEXFPGA_H
+
+
+#include "GaudiKernel/IAlgTool.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+
+namespace LVL1 {
+  
+/*
+Interface definition for jFEXFPGA
+*/
+
+  static const InterfaceID IID_IjFEXFPGA("LVL1::IjFEXFPGA", 1, 0);
+
+  class IjFEXFPGA : virtual public IAlgTool {
+  public:
+    static const InterfaceID& interfaceID( ) ;
+
+    virtual StatusCode init(int id, int efexid) = 0;
+
+    virtual StatusCode execute() = 0;
+
+    virtual void reset() = 0;
+
+    virtual int ID() = 0;
+
+    virtual void SetTowersAndCells_SG(int [][9]) = 0;
+    virtual void SetTowersAndCells_SG(int [][8]) = 0;
+
+  private:
+
+  };
+
+  inline const InterfaceID& LVL1::IjFEXFPGA::interfaceID()
+  {
+    return IID_IjFEXFPGA;
+  }
+
+} // end of namespace
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSim.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSim.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e19c33c4256bc3ef6e8b4c4ca1da5dc3280ee7e
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSim.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSim.h  -
+//                              -------------------
+//     begin                : 23 03 2019
+//     email                :  jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#ifndef IjFEXSim_H
+#define IjFEXSim_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloEvent/CaloCellContainer.h"
+
+namespace LVL1 {
+  
+/*
+Interface definition for jFEXSim
+*/
+
+  static const InterfaceID IID_IjFEXSim("LVL1::IjFEXSim", 1, 0);
+
+  class IjFEXSim : virtual public IAlgTool {
+  public:
+    static const InterfaceID& interfaceID( ) ;
+
+    virtual void init(int id) = 0;
+
+    virtual void reset() = 0;
+
+    virtual void execute() = 0;
+    virtual int ID() = 0;
+    virtual void SetTowersAndCells_SG(int tmp[16][9]) = 0;
+    virtual void SetTowersAndCells_SG(int tmp[16][8]) = 0;
+
+    virtual StatusCode NewExecute(int tmp[16*4][9]) = 0;
+    virtual StatusCode NewExecute(int tmp[16*4][8]) = 0;
+
+  private:
+
+  };
+
+  inline const InterfaceID& LVL1::IjFEXSim::interfaceID()
+  {
+    return IID_IjFEXSim;
+  }
+
+} // end of namespace
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSysSim.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSysSim.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d90ca57d830900623b7b6fe4f734fae69ee5787
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjFEXSysSim.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           jFEXSysSim.h  -
+//                              -------------------
+//     begin                : 23 03 2019
+//     email                :  jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#ifndef IjFEXSysSim_H
+#define IjFEXSysSim_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloEvent/CaloCellContainer.h"
+
+namespace LVL1 {
+  
+/*
+Interface definition for jFEXSysSim
+*/
+
+  static const InterfaceID IID_IjFEXSysSim("LVL1::IjFEXSysSim", 1, 0);
+
+  class IjFEXSysSim : virtual public IAlgTool {
+  public:
+    static const InterfaceID& interfaceID( ) ;
+    
+    virtual StatusCode execute() = 0;
+
+    virtual void init() = 0;
+
+    virtual void cleanup() = 0;
+
+    virtual int calcTowerID(int eta, int phi, int mod) = 0 ;
+    
+  private:
+
+  };
+
+  inline const InterfaceID& LVL1::IjFEXSysSim::interfaceID()
+  {
+    return IID_IjFEXSysSim;
+  }
+
+} // end of namespace
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjSuperCellTowerMapper.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjSuperCellTowerMapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..82ee76ec2957dab096158e95b26ac918a765d290
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjSuperCellTowerMapper.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           IjSuperCellTowerMapper.h  -
+//                              -------------------
+//     begin                : 23 03 2019
+//     email                :  jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#ifndef IjSuperCellTowerMapper_H
+#define IjSuperCellTowerMapper_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "CaloIdentifier/CaloIdManager.h"
+#include "CaloIdentifier/CaloCell_SuperCell_ID.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+#include "xAODTrigL1Calo/TriggerTowerContainer.h"
+
+namespace LVL1 {
+  
+/*
+Interface definition for jSuperCellTowerMapper
+*/
+
+  static const InterfaceID IID_IjSuperCellTowerMapper("LVL1::IjSuperCellTowerMapper", 1, 0);
+
+  class IjSuperCellTowerMapper : virtual public IAlgTool {
+  public:
+    static const InterfaceID& interfaceID( ) ;
+
+    virtual StatusCode AssignSuperCellsToTowers(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw) = 0;
+    virtual StatusCode AssignTriggerTowerMapper(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw) = 0;
+    
+    virtual void reset() = 0;
+    
+    virtual int FindAndConnectTower(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw,CaloSampling::CaloSample sample,const int region, int layer, const int pos_neg, const int eta_index, const int phi_index, Identifier ID, float et, int prov, bool doPrint) = 0;
+    virtual void ConnectSuperCellToTower(/*jTowerContainer**/std::unique_ptr<jTowerContainer> & my_jTowerContainerRaw, int iETower, Identifier ID, int iCell, float et, int layer, bool doenergysplit) = 0;
+    virtual int FindTowerIDForSuperCell(int towereta, int towerphi) = 0;
+    virtual void PrintCellSpec(const CaloSampling::CaloSample sample, int layer, const int region, const int eta_index, const int phi_index, const int pos_neg, int iETower, int iCell, int prov, Identifier ID, bool doenergysplit) = 0;
+
+  private:
+
+  };
+
+  inline const InterfaceID& LVL1::IjSuperCellTowerMapper::interfaceID()
+  {
+    return IID_IjSuperCellTowerMapper;
+  }
+
+} // end of namespace
+
+#endif
diff --git a/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjTowerBuilder.h b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjTowerBuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f3e69de5a25fb7b23441cc07c2763dde65f336e
--- /dev/null
+++ b/Trigger/TrigT1/L1CaloFEXToolInterfaces/L1CaloFEXToolInterfaces/IjTowerBuilder.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//***************************************************************************
+//                           IjTowerBuilder.h  -
+//                              -------------------
+//     begin                : 23 03 2019
+//     email                :  jacob.julian.kempster@cern.ch
+//  ***************************************************************************/
+
+#ifndef IjTowerBuilder_H
+#define IjTowerBuilder_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "CaloEvent/CaloCellContainer.h"
+#include "L1CaloFEXSim/jTower.h"
+#include "L1CaloFEXSim/jTowerContainer.h"
+
+namespace LVL1 {
+  
+/*
+Interface definition for jTowerBuilder
+*/
+
+  static const InterfaceID IID_IjTowerBuilder("LVL1::IjTowerBuilder", 1, 0);
+
+  class IjTowerBuilder : virtual public IAlgTool {
+  public:
+    static const InterfaceID& interfaceID( ) ;
+
+    virtual void BuildEMBjTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0;
+    virtual void BuildTRANSjTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0;
+    virtual void BuildEMEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0 ;
+    virtual void BuildEMIEjTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0 ;
+    virtual void BuildHECjTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0;
+    virtual void BuildAllTowers(std::unique_ptr<jTowerContainer> & jTowerContainer) const = 0;
+    virtual void BuildSingleTower(std::unique_ptr<jTowerContainer> & jTowerContainer,float eta, float phi, float keybase, int posneg) const = 0;
+    
+    virtual void init(std::unique_ptr<jTowerContainer> & jTowerContainer) = 0;
+    virtual void execute(std::unique_ptr<jTowerContainer> & jTowerContainer) = 0;
+    virtual void reset() = 0;
+
+
+  private:
+
+  };
+
+  inline const InterfaceID& LVL1::IjTowerBuilder::interfaceID()
+  {
+    return IID_IjTowerBuilder;
+  }
+
+} // end of namespace
+
+#endif