diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
index 0de09f0f4850afd6eb7c0dcdf14c4b96def781c5..b26a5e174221e3819c8274554f96a7326c40be15 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
@@ -47,30 +47,15 @@ find_package( CLHEP )
 find_package( Geant4 )
 find_package( HepMC )
 find_package( HepPDT )
-find_package( ROOT COMPONENTS Cint Core Tree TreePlayer MathCore Hist RIO pthread MathMore Minuit Minuit2 Matrix Physics HistPainter Rint TMVA Graf Graf3d Gpad Html Postscript Gui GX11TTF GX11 )
+find_package( ROOT COMPONENTS Cint Core Tree MathCore Hist RIO pthread MathMore Minuit Minuit2 Matrix Physics HistPainter Rint TMVA Graf Graf3d Gpad Html Postscript Gui GX11TTF GX11 )
 find_package( XercesC )
 
+# tag ROOTTreePlayerLibs was not recognized in automatic conversion in cmt2cmake
+
 # Component(s) in the package:
 atlas_add_root_dictionary( ISF_FastCaloSimParametrizationLib
                            ISF_FastCaloSimParametrizationLibDictSource
-                           ROOT_HEADERS
-                          ISF_FastCaloSimParametrization/MeanAndRMS.h
-                          ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h
-                          ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h
-                          ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h
-                          ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h
-                          ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h
-                          ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
-                          ISF_FastCaloSimParametrization/TFCSFunction.h
-                          ISF_FastCaloSimParametrization/TreeReader.h
-                          ISF_FastCaloSimParametrization/firstPCA.h
-                          ISF_FastCaloSimParametrization/secondPCA.h
-                          ISF_FastCaloSimParametrization/TFCS2Function.h
-                          ISF_FastCaloSimParametrization/TFCS2DFunction.h
-                          ISF_FastCaloSimParametrization/DetailedShapeBinning.h
-                          ISF_FastCaloSimParametrization/FitDetailedShape.h
-                          ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h
-                          Root/LinkDef.h
+                           ROOT_HEADERS ISF_FastCaloSimParametrization/MeanAndRMS.h ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h ISF_FastCaloSimParametrization/TreeReader.h ISF_FastCaloSimParametrization/TFCS2Function.h ISF_FastCaloSimParametrization/TFCS2DFunction.h ISF_FastCaloSimParametrization/DetailedShapeBinning.h ISF_FastCaloSimParametrization/FitDetailedShape.h ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h  Root/LinkDef.h
                            EXTERNAL_PACKAGES  ROOT HepPDT XercesC CLHEP HepMC Geant4 )
 
 atlas_add_library( ISF_FastCaloSimParametrizationLib
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloDetDescrElement.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloDetDescrElement.h
new file mode 100755
index 0000000000000000000000000000000000000000..2eca531869fd5552d14445476e044182da2c1185
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloDetDescrElement.h
@@ -0,0 +1,249 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CALOGEODETECTORELEMENT_H
+#define CALOGEODETECTORELEMENT_H
+
+class CaloGeometry;
+
+#include "Identifier/Identifier.h"
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+
+class CaloGeoDetDescrElement
+{
+ friend class CaloGeometry;
+ public:
+  CaloGeoDetDescrElement() {
+    m_identify = 0;
+    m_hash_id = 0;
+    m_calosample = 0;
+    m_eta = 0;
+    m_phi = 0;
+    m_deta = 0;
+    m_dphi = 0;
+    m_r = 0;
+    m_eta_raw = 0;
+    m_phi_raw = 0;
+    m_r_raw = 0;
+    m_dr = 0;
+    m_x = 0;
+    m_y = 0;
+    m_z = 0;
+    m_x_raw = 0;
+    m_y_raw = 0;
+    m_z_raw = 0;
+    m_dx = 0;
+    m_dy = 0;
+    m_dz = 0;
+  };
+
+  /** @brief virtual destructor
+   */
+  virtual ~CaloGeoDetDescrElement() {};
+
+  /** @brief cell eta
+   */
+  float eta() const;
+  /** @brief cell phi
+   */
+  float phi() const;
+  /** @brief cell r
+   */
+  float r() const;
+  /** @brief cell eta_raw
+   */
+  float eta_raw() const;
+  /** @brief cell phi_raw
+   */
+  float phi_raw() const;
+  /** @brief cell r_raw
+   */
+  float r_raw() const;
+  /** @brief cell dphi
+   */
+  float dphi() const;
+  /** @brief cell deta
+   */
+  float deta() const;
+  /** @brief cell dr
+   */
+  float dr() const;
+    
+  /** @brief cell x
+   */
+  float x() const;
+  /** @brief cell y
+   */
+  float y() const;
+  /** @brief cell z
+   */
+  float z() const;
+  /** @brief cell x_raw
+   */
+  float x_raw() const;
+  /** @brief cell y_raw
+   */
+  float y_raw() const;
+  /** @brief cell z_raw
+   */
+  float z_raw() const;
+  /** @brief cell dx
+   */
+  float dx() const;
+  /** @brief cell dy
+   */
+  float dy() const;
+  /** @brief cell dz
+   */
+  float dz() const;
+  
+  /** @brief cell identifier
+   */
+  Identifier identify() const;
+  
+  unsigned long long calo_hash() const;
+
+  int getSampling() const ;
+
+ //ACH protected:  
+ //
+  long long m_identify;
+  long long m_hash_id;
+  
+  int m_calosample;
+   
+  /** @brief cylindric coordinates : eta
+   */
+  float m_eta;
+  /** @brief cylindric coordinates : phi
+   */
+  float m_phi;
+
+ /** @brief this one is cached for algorithm working in transverse Energy
+    */
+  float m_sinTh; 
+   /** @brief this one is cached for algorithm working in transverse Energy   
+   */
+  float m_cosTh;
+
+  /** @brief cylindric coordinates : delta eta
+   */
+  float m_deta;
+  /** @brief cylindric coordinates : delta phi
+   */
+  float m_dphi;
+
+  /** @brief cylindric coordinates : r
+   */
+   
+  float m_volume;    
+  
+  /** @brief cache to allow fast px py pz computation
+   */
+  float m_sinPhi;
+
+  /** @brief cache to allow fast px py pz computation
+  */
+  float m_cosPhi;
+
+  /** @brief cylindric coordinates : r
+   */
+  float m_r;
+  /** @brief cylindric coordinates : eta_raw
+   */
+  float m_eta_raw;
+  /** @brief cylindric coordinates : phi_raw
+   */
+  float m_phi_raw;
+  /** @brief cylindric coordinates : r_raw
+   */
+  float m_r_raw;
+  /** @brief cylindric coordinates : delta r
+   */
+  float m_dr;
+  
+  /** @brief cartesian coordinates : X
+   */
+  float m_x;
+  /** @brief cartesian coordinates : Y
+   */
+  float m_y;
+  /** @brief cartesian coordinates : Z
+   */
+  float m_z;
+  /** @brief cartesian coordinates : X raw
+   */
+  float m_x_raw;
+  /** @brief cartesian coordinates : Y raw
+   */
+  float m_y_raw;
+  /** @brief cartesian coordinates : Z raw
+   */
+  float m_z_raw;
+  /** @brief cartesian coordinates : delta X
+   */
+  float m_dx;
+  /** @brief cartesian coordinates : delta Y
+   */
+  float m_dy;
+  /** @brief cartesian coordinates : delta Z
+   */
+  float m_dz;
+  
+};
+
+inline Identifier CaloGeoDetDescrElement::identify() const
+{ 
+	Identifier id((unsigned long long) m_identify);
+	return id;	
+}
+
+inline unsigned long long CaloGeoDetDescrElement::calo_hash() const
+{
+	return m_hash_id;
+}
+
+inline int CaloGeoDetDescrElement::getSampling() const
+{ return m_calosample;}
+inline float CaloGeoDetDescrElement::eta() const
+{ return m_eta;}
+inline float CaloGeoDetDescrElement::phi() const
+{ return m_phi;}
+inline float CaloGeoDetDescrElement::r() const
+{ return m_r;}
+inline float CaloGeoDetDescrElement::eta_raw() const
+{ return m_eta_raw;}
+inline float CaloGeoDetDescrElement::phi_raw() const
+{ return m_phi_raw;}
+inline float CaloGeoDetDescrElement::r_raw() const
+{ return m_r_raw;}
+inline float CaloGeoDetDescrElement::deta() const
+{ return m_deta;}
+inline float CaloGeoDetDescrElement::dphi() const
+{ return m_dphi;}
+inline float CaloGeoDetDescrElement::dr() const
+{ return m_dr;}
+
+inline float CaloGeoDetDescrElement::x() const
+{ return m_x;}
+inline float CaloGeoDetDescrElement::y() const
+{ return m_y;}
+inline float CaloGeoDetDescrElement::z() const
+{ return m_z;}
+inline float CaloGeoDetDescrElement::x_raw() const
+{ return m_x_raw;}
+inline float CaloGeoDetDescrElement::y_raw() const
+{ return m_y_raw;}
+inline float CaloGeoDetDescrElement::z_raw() const
+{ return m_z_raw;}
+inline float CaloGeoDetDescrElement::dx() const
+{ return m_dx;}
+inline float CaloGeoDetDescrElement::dy() const
+{ return m_dy;}
+inline float CaloGeoDetDescrElement::dz() const
+{ return m_dz;}
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h
index e60dfa2bc6f07fe440ee777cdab8c6ae469b3a10..5d5095e313c72a8e4ed26ec88ec0425af36900d7 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h
@@ -14,21 +14,22 @@
 #include "ISF_FastCaloSimParametrization/ICaloGeometry.h"
 #include "ISF_FastCaloSimParametrization/MeanAndRMS.h"
 #include "ISF_FastCaloSimParametrization/FSmap.h"
+#include "ISF_FastCaloSimParametrization/FCAL_ChannelMap.h"
 
-class CaloDetDescrElement;
+class CaloGeoDetDescrElement;
 class TCanvas;
 class TGraphErrors;
 
-typedef std::map< Identifier , const CaloDetDescrElement* > t_cellmap;
-typedef std::map< double , const CaloDetDescrElement* > t_eta_cellmap;
+typedef std::map< Identifier , const CaloGeoDetDescrElement* > t_cellmap;
+typedef std::map< double , const CaloGeoDetDescrElement* > t_eta_cellmap;
 
 class CaloGeometryLookup {
   public:
     CaloGeometryLookup(int ind=0);
     virtual ~CaloGeometryLookup();
 
-    bool IsCompatible(const CaloDetDescrElement* cell);
-    void add(const CaloDetDescrElement* cell);
+    bool IsCompatible(const CaloGeoDetDescrElement* cell);
+    void add(const CaloGeoDetDescrElement* cell);
     t_cellmap::size_type size() const {return m_cells.size();};
     int index() const {return m_index;};
     void set_index(int ind) {m_index=ind;};
@@ -75,7 +76,7 @@ class CaloGeometryLookup {
     int cell_grid_phi() const {return m_cell_grid_phi;};
     void set_xy_grid_adjustment_factor(float factor) {m_xy_grid_adjustment_factor=factor;};
 
-    virtual const CaloDetDescrElement* getDDE(float eta,float phi,float* distance=0,int* steps=0);
+    virtual const CaloGeoDetDescrElement* getDDE(float eta,float phi,float* distance=0,int* steps=0);
 
   protected:
     float neta_double() {return (maxeta_raw()-mineta_raw())/deta().mean();};
@@ -94,11 +95,11 @@ class CaloGeometryLookup {
     int raw_eta_position_to_index(float eta_raw) const {return TMath::Floor((eta_raw-mineta_raw())/m_deta_double);};
     int raw_phi_position_to_index(float phi_raw) const {return TMath::Floor((phi_raw-minphi_raw())/m_dphi_double);};
     bool index_range_adjust(int& ieta,int& iphi);
-    float calculate_distance_eta_phi(const CaloDetDescrElement* DDE,float eta,float phi,float& dist_eta0,float& dist_phi0);
+    float calculate_distance_eta_phi(const CaloGeoDetDescrElement* DDE,float eta,float phi,float& dist_eta0,float& dist_phi0);
 
     int m_index;
     t_cellmap m_cells;
-    std::vector< std::vector< const CaloDetDescrElement* > > m_cell_grid;
+    std::vector< std::vector< const CaloGeoDetDescrElement* > > m_cell_grid;
     int m_cell_grid_eta,m_cell_grid_phi;
     float m_mineta,m_maxeta,m_minphi,m_maxphi;
     float m_mineta_raw,m_maxeta_raw,m_minphi_raw,m_maxphi_raw;
@@ -123,9 +124,11 @@ class CaloGeometry : virtual public ICaloGeometry {
 
     virtual void Validate();
 
-    virtual const CaloDetDescrElement* getDDE(Identifier identify);
+    virtual const CaloGeoDetDescrElement* getDDE(Identifier identify);
+    virtual const CaloGeoDetDescrElement* getDDE(int sampling, Identifier identify);
 
-    virtual const CaloDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0);
+    virtual const CaloGeoDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0);
+    virtual const CaloGeoDetDescrElement* getFCalDDE(int sampling,float eta,float phi,float z);
 
     double deta(int sample,double eta) const;
     void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const;
@@ -149,9 +152,10 @@ class CaloGeometry : virtual public ICaloGeometry {
     bool DoGraphs() const {return m_dographs;};
 
     TCanvas* DrawGeoForPhi0();
+    FCAL_ChannelMap* GetFCAL_ChannelMap(){return &m_FCal_ChannelMap;}
 
   protected:
-    virtual void addcell(const CaloDetDescrElement* cell);
+    virtual void addcell(const CaloGeoDetDescrElement* cell);
 
     virtual void post_process(int layer);
 
@@ -176,7 +180,7 @@ class CaloGeometry : virtual public ICaloGeometry {
 
     bool m_dographs;
     std::vector< TGraphErrors* > m_graph_layers;
-
+		FCAL_ChannelMap m_FCal_ChannelMap;
     /*
        double  m_min_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
        double  m_max_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometryFromFile.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometryFromFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a1b749dead73fc1686b3a99603c6c00072b6478
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometryFromFile.h
@@ -0,0 +1,22 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CaloGeometryFromFile_h
+#define CaloGeometryFromFile_h
+
+#include "ISF_FastCaloSimParametrization/CaloGeometry.h"
+
+
+class CaloGeometryFromFile:public CaloGeometry {
+public :
+   CaloGeometryFromFile();
+   virtual ~CaloGeometryFromFile();
+   
+   virtual bool LoadGeometryFromFile(TString filename,TString treename);
+   virtual bool LoadFCalGeometryFromFiles(TString filename1,TString filename2,TString filename3);
+   void DrawFCalGraph(int isam,int color);
+};
+
+#endif
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h
index b7c5aa2ac9d0556410f9ef4ce2f561f08e04ce96..4aaeefbb0837f8dee01965ba8cd516fe11ca24a4 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h
@@ -2,15 +2,15 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef TFCSSimulationState_h
+#ifndef EnergyParametrizationValidation_h
 #define EnergyParametrizationValidation_h
 
 class EnergyParametrizationValidation
 {
   public:
-    //EnergyParametrizationValidation();
-    //virtual ~EnergyParametrizationValidation(){};
-    static void autozoom(TH1D* h1, TH1D* h2, double &min, double &max, double &rmin, double &rmax);
+    EnergyParametrizationValidation() {};
+    ~EnergyParametrizationValidation() {};
+    static void autozoom(TH1D* h1, double &min, double &max, double &rmin, double &rmax);
     static TH1D* refill(TH1D* h_in,double min, double max, double rmin, double rmax);
 
   private:
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FCAL_ChannelMap.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FCAL_ChannelMap.h
new file mode 100755
index 0000000000000000000000000000000000000000..49365dd83db4af3016b89fbbc49363413d21b8fd
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FCAL_ChannelMap.h
@@ -0,0 +1,287 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ***************************************************************************
+// Liquid Argon FCAL detector description package
+// -----------------------------------------
+// Copyright (C) 1998 by ATLAS Collaboration
+//
+//
+// 10-Sep-2000 S.Simion   Handling of the FCAL read-out identifiers
+//    Jan-2001 R.Sobie    Modify for persistency
+//    Feb-2002 R.Sobie    Use same FCAL geometry files as simulation 
+// ***************************************************************************
+
+#ifndef FCAL_CHANNELMAP_H
+#define FCAL_CHANNELMAP_H
+
+
+//<<<<<< INCLUDES                                                       >>>>>>
+
+
+#include <math.h>
+#include <vector>
+#include <functional>
+#include <map>
+#include <string>
+#include <stdexcept>
+
+
+/** This class contains the tube and tile maps for the FCAL <br>
+ * A tile is of a set of FCAL tubes
+  */
+class FCAL_ChannelMap
+{
+public:
+
+    
+
+    //
+    //	 Typedefs:
+    //	
+    typedef unsigned int                          tileName_t;
+    typedef unsigned int                          tubeID_t;
+
+    //------------ TubePosition:  X,Y Position of an FCAL Tube---- //
+    //                                                             //
+    class TubePosition {                                           //
+    public:                                                        //
+      TubePosition();                                              //
+      TubePosition(tileName_t name, float x, float y, std::string hvFT);//
+      tileName_t  get_tileName() const;                            //
+      float       x() const;                                       //
+      float       y() const;                                       //
+      std::string getHVft() const;                                 //Gabe
+    private:                                                       //
+      tileName_t  m_tileName;                                      //
+      float       m_x;                                             //
+      float       m_y;                                             //
+      std::string m_hvFT;                                          // Gabe
+    };                                                             //
+    //-------------------------------------------------------------//
+
+
+
+    /**  Constructors: */
+    FCAL_ChannelMap( int itemp);
+
+    typedef std::map<tubeID_t,  TubePosition >  tubeMap_t;
+    typedef tubeMap_t::size_type       		tubemap_sizetype;
+    typedef tubeMap_t::value_type 	        tubemap_valuetype;
+    typedef tubeMap_t::const_iterator	      	tubemap_const_iterator;
+
+    /** tubeMap access functions */
+    tubemap_const_iterator       tubemap_begin        (int isam) const;
+    tubemap_const_iterator       tubemap_end          (int isam) const;
+    tubemap_sizetype             tubemap_size         (int isam) const;
+
+
+    // Get the tube by copy number:
+    tubemap_const_iterator getTubeByCopyNumber ( int isam, int copyNo) const;
+
+
+    /**  ---- For the new LArFCAL_ID Identifier 
+     */ 
+
+    bool getTileID(int isam, 
+		   float x, 
+		   float y, 
+		   int& eta, 
+		   int& phi) const throw (std::range_error);
+
+    /** For reconstruction, decoding of tile identifiers */
+    float x(int isam, 
+	    int eta, 
+	    int phi) const throw(std::range_error) ;
+    float y(int isam, 
+	    int eta, 
+	    int phi) const throw(std::range_error) ;
+
+    void tileSize(int sam, int eta, int phi, 
+		  float& dx, float& dy) const throw(std::range_error) ;
+
+    void tileSize(int isam, int ntubes, float& dx, float& dy) const;
+
+
+    /** print functions */
+    void print_tubemap  (int isam) const;
+
+    /** set and get for the inversion flags
+    */ 
+
+    bool invert_x() const; 
+    bool invert_xy() const ; 
+    void set_invert_x(bool ); 
+    void set_invert_xy(bool ); 
+
+
+    // Fill this.  The information comes from the database.
+    void add_tube (const std::string & tileName, int mod, int id, int i, int j, double xCm, double yCm);//original
+    void add_tube (const std::string & tileName, int mod, int id, int i, int j, double xCm, double yCm, std::string hvFT);//29-03-07 include HV 
+
+
+    // Finish the job. Create the tile map.
+    void finish();
+
+
+    class TilePosition {
+    public:
+	TilePosition();
+	TilePosition(float x, float y, int ntubes);
+	float         x() const;
+	float         y() const;
+	unsigned int  ntubes() const;
+    private:
+	float        m_x;
+	float        m_y;
+	unsigned int m_ntubes;
+    };
+
+    /** TileMap */
+    typedef std::map<tileName_t, TilePosition >   tileMap_t;
+    typedef tileMap_t::size_type       		  tileMap_sizetype;
+    typedef tileMap_t::value_type              	  tileMap_valuetype;
+    typedef tileMap_t::const_iterator		  tileMap_const_iterator;
+
+    // Methods to iterate over the tile map:
+    tileMap_const_iterator begin(int isam) const {return m_tileMap[isam-1].begin();}
+    tileMap_const_iterator end(int isam)   const {return m_tileMap[isam-1].end(); };
+    
+
+private:
+    /** Geometrical parameters here, in CLHEP::cm please to be compatible with G3 */
+    static const double m_tubeSpacing[];
+    double 		m_tubeDx[3];
+    double 		m_tubeDy[3];
+    double 		m_tileDx[3];
+    double 		m_tileDy[3];
+    mutable bool	m_invert_x;   // Some geometry need x inverted
+    mutable bool	m_invert_xy;  // Some geometry need xy crossed 
+    
+    tileMap_t   	                        m_tileMap[3];
+    void                                        create_tileMap( int isam );
+
+  /** TubeMap */ 
+  tubeMap_t                                 	m_tubeMap[3];
+  std::vector<tubemap_const_iterator>           m_tubeIndex[3];
+};
+
+
+// Tube Position functions
+
+inline
+FCAL_ChannelMap::TubePosition::TubePosition() 
+    :
+  m_tileName(0),
+  m_x(0),
+  m_y(0),
+  m_hvFT("")
+{}
+ 
+inline
+FCAL_ChannelMap::TubePosition::TubePosition(tileName_t name, float x, float y, std::string hvFT)
+    :
+    m_tileName(name),
+    m_x(x),
+    m_y(y),
+    m_hvFT(hvFT)
+{}
+
+
+inline FCAL_ChannelMap::tileName_t
+FCAL_ChannelMap::TubePosition::get_tileName() const
+{
+    return m_tileName;
+}
+
+
+inline float
+FCAL_ChannelMap::TubePosition::x() const
+{
+    return m_x;
+}
+ 
+inline float
+FCAL_ChannelMap::TubePosition::y() const
+{
+    return m_y;
+}
+
+
+inline std::string
+FCAL_ChannelMap::TubePosition::getHVft() const
+{
+  return m_hvFT;
+}
+
+
+// Tile Position functions
+
+inline
+FCAL_ChannelMap::TilePosition::TilePosition() 
+    :
+    m_x(0),
+    m_y(0),
+    m_ntubes(0)
+{}
+ 
+inline
+FCAL_ChannelMap::TilePosition::TilePosition(float x, float y, int ntubes)
+    :
+    m_x(x),
+    m_y(y),
+    m_ntubes(ntubes)
+{}
+
+
+inline float
+FCAL_ChannelMap::TilePosition::x() const
+{
+    return m_x;
+}
+ 
+inline float
+FCAL_ChannelMap::TilePosition::y() const
+{
+    return m_y;
+}
+ 
+inline unsigned int
+FCAL_ChannelMap::TilePosition::ntubes() const
+{
+    return m_ntubes;
+}
+
+inline
+bool FCAL_ChannelMap::invert_x() const {
+return m_invert_x;
+}
+
+inline
+bool FCAL_ChannelMap::invert_xy() const {
+return m_invert_xy;
+}
+
+inline
+void FCAL_ChannelMap::set_invert_x(bool flag ){
+m_invert_x = flag; 
+return ;
+}
+
+inline
+void FCAL_ChannelMap::set_invert_xy(bool flag ){
+m_invert_xy = flag; 
+return ;
+}
+
+//#include "CLIDSvc/CLASS_DEF.h"
+//CLASS_DEF(FCAL_ChannelMap, 74242524, 1)
+ 
+#endif // LARDETDESCR_FCAL_CHANNELMAP_H
+
+
+
+
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h
index 13f304cb5a48ad5e0ac33e2d8c58696d18f8c269..41b8a326b50db1fb5b972cecfcafd6b65125f365 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h
@@ -7,17 +7,18 @@
 
 #include "Identifier/Identifier.h"
 #include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimParametrization/CaloDetDescrElement.h"
 
-class CaloDetDescrElement;
+class CaloGeoDetDescrElement;
 class ICaloGeometry {
 public :
    virtual bool PostProcessGeometry() = 0;
 
    virtual void Validate() = 0;
 
-   virtual const CaloDetDescrElement* getDDE(Identifier identify) = 0;
+   virtual const CaloGeoDetDescrElement* getDDE(Identifier identify) = 0;
    
-   virtual const CaloDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0) = 0;
+   virtual const CaloGeoDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0) = 0;
    
    virtual double deta(int sample,double eta) const = 0;
    virtual void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const = 0;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h
index 16c990d63cbde92b344ea2736cdebc6d8bc91e81..09654054d50c337453e1407385adb21760b9e7ef 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h
@@ -13,12 +13,13 @@ class TFCSExtrapolationState;
 
 static const InterfaceID IID_IFastCaloSimCaloExtrapolation("IFastCaloSimCaloExtrapolation", 1, 0);
    
-class IFastCaloSimCaloExtrapolation : virtual public IAlgTool {
+class IFastCaloSimCaloExtrapolation : virtual public IAlgTool
+{
  public:
    /** AlgTool interface methods */
    static const InterfaceID& interfaceID() { return IID_IFastCaloSimCaloExtrapolation; }
 
-   virtual void* extrapolate(TFCSTruthState* truth,TFCSExtrapolationState& result) = 0;
+   virtual void extrapolate(TFCSExtrapolationState& result,const TFCSTruthState* truth) = 0;
 
 };
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h
index 2d8b54825da701c4326530419128de8cf257d062..d7d691d48769e8dcc1f45a70e44e11ed1e5de504 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h
@@ -25,13 +25,15 @@
 #include "TrkParameters/TrackParameters.h"
 //#####################################
 
-#include "ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h"
+#include "ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h"
 #include "ISF_FastCaloSimParametrization/IFastCaloSimGeometryHelper.h"
 #include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 
-namespace Trk {
+namespace Trk
+{
   class TrackingVolume;
 }
+
 #include "TrkExInterfaces/ITimedExtrapolator.h" 
 #include "TrkEventPrimitives/PdgToParticleHypothesis.h"
 class ICaloSurfaceHelper;
@@ -200,9 +202,13 @@ class ISF_HitAnalysis : public AthAlgorithm {
    std::vector< CaloCell_ID_FCS::CaloSample > m_surfacelist;
    
    //CaloGeometryFromCaloDDM* m_CaloGeometry;
+   
    /** The FastCaloSimGeometryHelper tool */
    ToolHandle<IFastCaloSimGeometryHelper> m_CaloGeometryHelper;
 
+   /** The FastCaloSimCaloExtrapolation tool */
+   ToolHandle<IFastCaloSimCaloExtrapolation> m_FastCaloSimCaloExtrapolation;
+ 
    bool   isCaloBarrel(int sample) const;
    double deta(int sample,double eta) const;
    void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h
deleted file mode 100644
index 3488f519b6c5ac7fbe58041dcede2f87f4e1e687..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef ISF_FASTCALOSIMPARAMETRIZATION_INTARRAY_H
-#define ISF_FASTCALOSIMPARAMETRIZATION_INTARRAY_H
-#include "ISF_FastCaloSimEvent/IntArray.h"
-
-#endif // not ISF_FASTCALOSIMPARAMETRIZATION_INTARRAY_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
deleted file mode 100644
index 13ccc11f6c4078a3d65684463b689bd37255d1b3..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCS1DFunctionHistogram_h
-#define TFCS1DFunctionHistogram_h
-
-#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-#include "TH1.h"
-#include <vector>
-
-class TFCS1DFunctionHistogram:public TFCS1DFunction
-{
-	
-  public:
-    TFCS1DFunctionHistogram();
-    TFCS1DFunctionHistogram(TH1* hist, int,double);
-    
-    void Initialize(TH1* hist, int,double);
-    virtual double rnd_to_fct(double rnd);
-    
-    TH1* vector_to_histo();
-    void smart_rebin_loop(TH1* hist, int,double);
-    TH1D* smart_rebin(TH1D* , double );
-    double* histo_to_array(TH1*);
-    double sample_from_histo(TH1* hist, double);
-    double sample_from_histovalues(double);
-	  double InverseCumulant(double y);
-	  double get_inverse(double rnd);
-	  double linear(double x1,double x2,double y1,double y2,double x);
-	  
-  private:
-
-    vector<float> m_HistoBorders;
-    vector<float> m_HistoContents;
-    
-  ClassDef(TFCS1DFunctionHistogram,1)  //TFCS1DFunctionHistogram
-
-};
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h
deleted file mode 100644
index 5f92d674d9a86a63fd28a7a83ca5a25d2b02980c..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCS1DFunctionRegression_h
-#define TFCS1DFunctionRegression_h
-
-#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
-#include "TTree.h"
-#include "TH1.h"
-#include <vector>
-
-class TFCS1DFunctionRegression:public TFCS1DFunction
-{
-  public:
-  	
-    TFCS1DFunctionRegression();
-    TFCS1DFunctionRegression(TH1* hist);
-    
-    virtual void Initialize(TH1* hist);
-    void storeRegression(string);
-    virtual double rnd_to_fct(double rnd);
-    
-  //ACH private:
-    
-    vector<vector<double> > m_fWeightMatrix0to1;
-    vector<vector<double> > m_fWeightMatrix1to2;
-    
-    double regression_value(double uniform);
-    void get_weights(std::string);
-    void validate(int,std::string);
-		  
-  ClassDef(TFCS1DFunctionRegression,1)  //TFCS1DFunctionRegression
-  
-};
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h
deleted file mode 100644
index 043b11ac8a449920958c437595d1a16b40f6a041..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCS1DFunctionRegressionTF_h
-#define TFCS1DFunctionRegressionTF_h
-
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h"
-#include "TH1.h"
-#include <vector>
-
-class TFCS1DFunctionRegressionTF:public TFCS1DFunctionRegression
-{
-  public:
-  	
-    TFCS1DFunctionRegressionTF();
-    void storeRegression(string, float, float);
-
-    virtual double rnd_to_fct(double rnd);
-    double retransform(double value);
-    
-  private:
-    
-    vector<vector<double> > m_fWeightMatrix0to1;
-    vector<vector<double> > m_fWeightMatrix1to2;
-    float m_rangeval;
-    float m_startval;
-		
-  public:
-    ClassDef(TFCS1DFunctionRegressionTF,1)
-  
-};
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h
index 9b9e3396a3b1111d524afc3002d12e65089623dd..ec0a7a561f44aa91283c70b0c1f2ad81eed7d196 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h
@@ -40,9 +40,10 @@ class TreeReader //: public TTreeFormulaManager
  public:
 
   TreeReader();               // Default ctor
-  TreeReader(TTree* n);       // ctor with ntuple
   virtual ~TreeReader();      // dtor
 
+  TreeReader(TTree* n);       // ctor with ntuple
+ 
   void   SetTree(TTree* n);       //
   double GetVariable(const char* c, int entry=-2); // return variable s for a given entry (<0 -> current entry)
   int    GetEntry(int entry=-1);     // Read a given entry in the buffer (-1 -> next entry);
@@ -50,7 +51,12 @@ class TreeReader //: public TTreeFormulaManager
   TTree* GetTree()                { return m_tree    ; }
   void   Restart()                    {m_currentEntry = -1;}
 
-  ClassDef(TreeReader,0);  // Integrate this class into ROOT (must be the last member)
+  ClassDef(TreeReader,1)  // Integrate this class into ROOT (must be the last member)
+  
 };
 
+#if defined(__MAKECINT__)
+#pragma link C++ class TreeReader+;
+#endif
+
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx
index e088e3e3523b0decc004fb07e338a5cec8c54f3b..5c2378bb79610bb353b3e5f28ec37b5787be60cd 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx
@@ -16,23 +16,13 @@
 
 using namespace std;
 
-void EnergyParametrizationValidation::autozoom(TH1D* h1, TH1D* /*h2*/, double &min, double &max, double &rmin, double &rmax)
+void EnergyParametrizationValidation::autozoom(TH1D* h1, double &min, double &max, double &rmin, double &rmax)
 {
  
- //int checksim=0;
- 
  double min1,min2,max1,max2;
  min1=min2=h1->GetXaxis()->GetXmin();
  max1=max2=h1->GetXaxis()->GetXmax();
  
- //double eps1=0.001;
- //double eps2=0.001;
- 
- //double ave1,ave2;
- 
- //double int1=h1->Integral();
- //double int2=h2->Integral();
- 
  for(int b=1;b<=h1->GetNbinsX();b++)
  {
   if(h1->GetBinContent(b)>0)
@@ -52,31 +42,6 @@ void EnergyParametrizationValidation::autozoom(TH1D* h1, TH1D* /*h2*/, double &m
  
  min=min1;max=max1;
 
- /*if(checksim)
- {
-  for(int b=1;b<=h2->GetNbinsX();b++)
-  {
-   if(h2->GetBinContent(b)>int2*eps2)
-   {
-    min2=h2->GetBinCenter(b);
-    break;
-   }
-  }
-  for(int b=h2->GetNbinsX();b>=1;b--)
-  {
-   if(h2->GetBinContent(b)>int2*eps2)
-   {
-    max2=h2->GetBinCenter(b);
-    break;
-   }
-  }
-  
-  min=min1;
-  if(min2<min1) min=min2;
-  max=max1;
-  if(max2>max1) max=max2;
-  
- }*/
  
  rmin=min-0.5*h1->GetBinWidth(1);
  rmax=max+0.5*h1->GetBinWidth(1);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx
deleted file mode 100644
index 2298acdeb1092567af4e6b0e3d194a7184f22b62..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx
+++ /dev/null
@@ -1,4 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h
index 634915782fe0d266888a99ecc198905356872f50..a113a69f0229249527ee49e0c614fdbeb7536cb7 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h
@@ -14,6 +14,7 @@
 #pragma link C++ class firstPCA;
 #pragma link C++ class secondPCA;
 #pragma link C++ class DetailedShowerShape;
+#pragma link C++ class ShowerShapeBinning; 
 #pragma link C++ class TFCS2DFunction;
 #pragma link C++ class TFCS2Function;
 #pragma link C++ class FitDetailedShape;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx
deleted file mode 100644
index e7eac1231f69bba27674cffb24f4af52574b5862..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-using namespace std;
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h"
-#include "TMath.h"
-#include <iostream>
-
-//=============================================
-//======= TFCSFunctionRegression =========
-//=============================================
-
-TFCS1DFunctionHistogram::TFCS1DFunctionHistogram()
-{
-}
-
-TFCS1DFunctionHistogram::TFCS1DFunctionHistogram(TH1* hist, int verbose, double cut_maxdev)
-{
-  Initialize(hist, verbose,cut_maxdev);
-}
-
-void TFCS1DFunctionHistogram::Initialize(TH1* hist, int verbose,double cut_maxdev)
-{
-
-  smart_rebin_loop(hist, verbose,cut_maxdev);
-
-  //test the sampling
-  /*
-     TH1D* h_test=new TH1D("h_test","h_test",5000,m_histo->GetXaxis()->GetXmin(),m_histo->GetXaxis()->GetXmax());
-     for(int i=0;i<10000;i++)
-     {
-     double random=myRandom->Uniform(1);
-     double *histoVals=histo_to_array();
-     double value=sample_from_histo(random,histoVals);
-     h_test->Fill(value);
-     }
-     TH1* h_cum=get_cumul(h_test);
-     TFile* testfile=new TFile("samplingtest.root","RECREATE");
-     testfile->Add(h_test);
-     testfile->Add(h_cum);
-     testfile->Add(m_histo);
-     testfile->Write();
-     */
-
-
-}
-
-double* TFCS1DFunctionHistogram::histo_to_array(TH1* hist)
-{
-
-  TH1D* h_clone=(TH1D*)hist->Clone("h_clone");
-  h_clone->Scale(1.0/h_clone->Integral());
-
-  double *histoVals=new double[h_clone->GetNbinsX()];
-  histoVals[0]=h_clone->GetBinContent(1);
-  for (int i=1; i<h_clone->GetNbinsX(); i++)
-  {
-    histoVals[i]=histoVals[i-1] + h_clone->GetBinContent(i+1);
-  }
-
-  // cleanup
-  //delete[] histoVals;
-
-  return histoVals;
-
-}
-
-double TFCS1DFunctionHistogram::sample_from_histo(TH1* hist, double random)
-{
-
-  double* histoVals=histo_to_array(hist);
-  double value=0.0;
-  int chosenBin = (int)TMath::BinarySearch(hist->GetNbinsX(), histoVals, random);
-  value = hist->GetBinCenter(chosenBin+2);
-
-  // cleanup
-  delete[] histoVals;
-
-  return value;
-
-}
-
-double TFCS1DFunctionHistogram::sample_from_histovalues(double random)
-{ 
-  double value=0.0;
-
-  TH1* hist=vector_to_histo(); hist->SetName("hist");
-  double *histoVals=histo_to_array(hist);
-  int chosenBin = (int)TMath::BinarySearch(hist->GetNbinsX(), histoVals, random);
-  value = hist->GetBinCenter(chosenBin+2);
-
-  return value;
-}
-
-
-
-TH1* TFCS1DFunctionHistogram::vector_to_histo()
-{
-
-  double *bins=new double[m_HistoBorders.size()];
-  for(unsigned int i=0;i<m_HistoBorders.size();i++)
-    bins[i]=m_HistoBorders[i];
-
-  TH1* h_out=new TH1D("h_out","h_out",m_HistoBorders.size()-1,bins);
-  for(int b=1;b<=h_out->GetNbinsX();b++)
-    h_out->SetBinContent(b,m_HistoContents[b-1]);
-
-  return h_out;
-
-}
-
-void TFCS1DFunctionHistogram::smart_rebin_loop(TH1* hist, int verbose, double cut_maxdev)
-{
-
-  m_HistoContents.clear();
-  m_HistoBorders.clear();
-
-  double maxdev=-1;
-  double change=0.0001; double step=0.00005;
-  TH1D* h_input; TH1D* h_output;
-  int i=0;
-  while(1)
-  {
-    if(i==0) h_input=(TH1D*)hist->Clone("h_input");
-
-    TH1D* h_out=smart_rebin(h_input,change); h_out->SetName("h_out");
-
-    maxdev=get_maxdev(hist,h_out);
-    if(verbose==2) cout<<"Iteration nr. "<<i<<" change "<<change<<" bins "<<h_out->GetNbinsX()<<"-> maxdev="<<maxdev<<endl;
-
-    if(maxdev<cut_maxdev)
-    {
-      h_input=(TH1D*)h_out->Clone("h_input");
-      change+=step;
-      i++;
-    }
-    if(maxdev>cut_maxdev)
-    {
-      change-=step;
-      h_output=(TH1D*)h_input->Clone("h_output");
-      break;
-    }
-
-    delete h_out;
-
-  }
-
-  cout<<"Info: Rebinned histogram has "<<h_output->GetNbinsX()<<" bins."<<endl;
-
-  for(int b=1;b<=h_output->GetNbinsX();b++)
-    m_HistoContents.push_back(h_output->GetBinContent(b));
-
-  for(int b=1;b<=h_output->GetNbinsX();b++)
-    m_HistoBorders.push_back((float)h_output->GetBinLowEdge(b));
-
-  m_HistoBorders.push_back((float)h_output->GetXaxis()->GetXmax());
-
-}
-
-TH1D* TFCS1DFunctionHistogram::smart_rebin(TH1D* h_input, double change)
-{
-
-  //int debug=0;
-
-  vector<double> content;
-  vector<double> binborder;
-
-  content.clear();
-  binborder.clear();
-
-  binborder.push_back(h_input->GetXaxis()->GetXmin());
-
-  double sum=0;
-  double sumwidth=0;
-  int count=0;
-  for(int b=1;b<h_input->GetNbinsX();b++)
-  {
-    double thisBin=h_input->GetBinContent(b);
-    double nextBin=h_input->GetBinContent(b+1);
-    double width=h_input->GetBinWidth(b);
-    if(fabs(nextBin/thisBin-1.0)>=change)
-    {
-      sum+=thisBin*width;
-      sumwidth+=width;
-      count++;
-      binborder.push_back(h_input->GetBinLowEdge(b+1));
-
-      //divide the sum by the number of summed bins:
-      //content.push_back(sum/(double)count);
-      content.push_back(sum/sumwidth);
-
-      //Reset the sum:
-      sum=0;
-      sumwidth=0;
-      count=0;
-    }
-    else
-    {
-      //do not add this bin to the new vector of bins, but add to the sum
-      sum+=thisBin*width;
-      sumwidth+=width;
-      count++;
-    }
-  }
-  //last bin is special:
-  binborder.push_back(h_input->GetXaxis()->GetXmax());
-  if(count==0) //that means the previous-to-last bin was written out, so simpy add the last one:
-  {
-    content.push_back(h_input->GetBinContent(h_input->GetNbinsX()));
-  }
-  if(count>0)
-  {
-    sum+=h_input->GetBinContent(h_input->GetNbinsX())*h_input->GetBinWidth(h_input->GetNbinsX());
-    sumwidth+=h_input->GetBinWidth(h_input->GetNbinsX());
-    count++;
-    content.push_back(sum/sumwidth);
-  }
-
-  double* bins=new double[content.size()+1];
-  for(unsigned int i=0;i<binborder.size();i++)
-    bins[i]=binborder[i];
-
-  TH1D* h_out=new TH1D("h_out","h_out",content.size(),bins);
-  for(unsigned int b=1;b<=content.size();b++)
-    h_out->SetBinContent(b,content[b-1]);
-
-  delete [] bins;
-
-  return h_out;
-
-}
-
-double TFCS1DFunctionHistogram::rnd_to_fct(double rnd)
-{
-
-  //double value1=sample_from_histovalues(rnd);
-  double value2=get_inverse(rnd);
-  return value2;
-
-}
-
-
-double TFCS1DFunctionHistogram::linear(double x1,double x2,double y1,double y2,double x)
-{
-  double y=-1;
-
-  double eps=0.0000000001;
-  if((x2-x1)<eps) y=y1;
-  else
-  {
-    double m=(y2-y1)/(x2-x1);
-    double n=y1-m*x1;
-    y=m*x+n;
-  }
-
-  return y;
-}
-
-
-double TFCS1DFunctionHistogram::get_inverse(double rnd)
-{
-
-  TH1* hist=vector_to_histo(); hist->SetName("hist");
-
-  double value = 0.;
-  for(int b=1;b<=hist->GetNbinsX();b++)
-  {
-    double y=hist->GetBinContent(b);
-    if(y>rnd && b!=1)
-    {
-      //use linear extrapolation to get exact x value
-      double x1=hist->GetBinCenter(b-1);
-      double x2=hist->GetBinCenter(b);
-      double y1=hist->GetBinContent(b-1);
-      double y2=hist->GetBinContent(b);
-      double y=linear(y1,y2,x1,x2,rnd);
-      //cout<<"x1 "<<x1<<" x2 "<<x2<<" y1 "<<y1<<" y2 "<<y2 <<" rnd "<<rnd<<" value "<<y<<endl;
-      value=y;
-      b=hist->GetNbinsX()+1;
-    }
-  }
-
-  return value;
-}
-
-double TFCS1DFunctionHistogram::InverseCumulant(double y)
-{
-
-  TH1* hist=vector_to_histo(); hist->SetName("hist");
-
-  int bin = 0;
-  int nbin = hist->GetNbinsX();
-  double min = 99999999;
-  for (int i=1; i<=hist->GetNbinsX()-2; i++)
-  {
-    if(fabs(hist->GetBinContent(i)-y)<min)
-    {
-      min = fabs(hist->GetBinContent(i)-y);
-      bin = i ;
-    }
-  }
-  bin = TMath::Max(bin,1);
-  bin = TMath::Min(bin,hist->GetNbinsX());
-
-  //std::cout<<bin <<std::endl;
-
-  double AvNuEvPerBin;
-  double Tampon = 0 ;
-  for (int i=1; i<=nbin; i++)
-  {
-    Tampon += hist->GetBinContent(i);
-  }
-
-  AvNuEvPerBin = Tampon/nbin;
-
-  double x;
-  double x0, x1, y0, y1;
-  double total = hist->GetNbinsX()*AvNuEvPerBin;
-  double supmin = 0.5/total;
-
-  x0 = hist->GetBinLowEdge(TMath::Max(bin,1));
-  x1 = hist->GetBinLowEdge(TMath::Min(bin,hist->GetNbinsX())+1);
-
-  y0 = hist->GetBinContent(TMath::Max(bin-1,0)); // Y0 = F(x0); Y0 >= 0
-  y1 = hist->GetBinContent(TMath::Min(bin, hist->GetNbinsX()+1));  // Y1 = F(x1);  Y1 <= 1
-
-  //Zero bin
-  if (bin == 0)
-  {
-    y0 = supmin;
-    y1 = supmin;
-  }
-  if (bin == 1) {
-    y0 = supmin;
-  }
-  if (bin > hist->GetNbinsX()) {
-    y0 = 1.-supmin;
-    y1 = 1.-supmin;
-  }
-  if (bin == hist->GetNbinsX()) {
-    y1 = 1.-supmin;
-  }
-
-  ////////////////////////
-
-  if(y0 == x1)
-  {
-    x = x0;
-  }
-  else
-  {
-    x = x0 + (y-y0)*(x1-x0)/(y1-y0);
-  }
-
-  return x;
-
-}
-
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCS1DFunctionHistogram)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx
deleted file mode 100644
index 3d477f8e7448758f33699c7318388216efedd34e..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-using namespace std;
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h"
-
-#include "TMVA/Config.h"
-#include "TMVA/Tools.h"
-#include "TMVA/Reader.h"
-#include "TMVA/Factory.h"
-#include "TRandom3.h"
-#include "TFile.h"
-#include "TString.h"
-#include "TMath.h"
-
-#include "TMVA/IMethod.h"
-#include "TMVA/MethodMLP.h"
-
-
-//=============================================
-//======= TFCS1DFunctionRegression =========
-//=============================================
-
-TFCS1DFunctionRegression::TFCS1DFunctionRegression()
-{
-}
-
-TFCS1DFunctionRegression::TFCS1DFunctionRegression(TH1* hist)
-{
-	
-  Initialize(hist);
-  
-}
-
-
-void TFCS1DFunctionRegression::Initialize(TH1* /*hist*/)
-{
- //not needed
-}
-
-void TFCS1DFunctionRegression::storeRegression(string weightfilename)
-{
-  
-	get_weights(weightfilename);
- 	
-  //for testing:
-  validate(10,weightfilename);
- 
-}
-
-
-void TFCS1DFunctionRegression::validate(int Ntoys,string weightfilename)
-{
- 
- TRandom* myRandom=new TRandom3(); myRandom->SetSeed(0);
- 
- //calculate regression from the weights and compare to TMVA value:
- cout<<endl;
- cout<<"--- Validating the regression value:"<<endl;
- for(int i=0;i<Ntoys;i++)
- {
-  double random=myRandom->Uniform(1);
-  cout<<"myvalue "<<regression_value(random)<<" TMVA value "<<tmvaregression_application(random,weightfilename)<<endl;
- }
- 
-}
-
-
-void TFCS1DFunctionRegression::get_weights(string /*weightfile*/)
-{
-
-/*
-
- using namespace TMVA;
- int debug=1;
- 
- TString myMethodList = "" ;
- TMVA::Tools::Instance();
- 
- std::map<std::string,int> Use;
-
- // --- Mutidimensional likelihood and Nearest-Neighbour methods
- Use["PDERS"]           = 0;   Use["PDEFoam"]         = 0;   Use["KNN"]            = 0;
- Use["LD"]		          = 0;   Use["FDA_GA"]          = 0;   Use["FDA_MC"]          = 0;
- Use["FDA_MT"]          = 0;   Use["FDA_GAMT"]        = 0;   Use["MLP"]             = 1; 
- Use["SVM"]             = 0;   Use["BDT"]             = 0;   Use["BDTG"]            = 0;
- // ---------------------------------------------------------------
-
- // Select methods (don't look at this code - not of interest)
- if (myMethodList != "")
- {
-  for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;
-  std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
-  for (UInt_t i=0; i<mlist.size(); i++)
-  {
-   std::string regMethod(mlist[i]);
-   if (Use.find(regMethod) == Use.end())
-   {
-    std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
-    for(std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
-    std::cout << std::endl;
-   }
-   Use[regMethod] = 1;
-  }
- }
- 
- // --------------------------------------------------------------------------------------------------
- 
- TMVA::Reader *reader = new TMVA::Reader( "!Color:Silent");    
- 
- Float_t y=0.5; //just a dummy
- reader->AddVariable( "y", &y );
- 
- TString dir   = Form("%s/",weightfile.c_str());
- TString prefix = "TMVARegression";
- 
- for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++)
- {
-  if (it->second)
-  {
-   TString methodName = it->first + " method";
-   TString weightfile = dir + prefix + "_" + TString(it->first) + ".weights.xml";
-   reader->BookMVA( methodName, weightfile ); 
-  }
- }
- 
- TMVA::IMethod* m=reader->FindMVA("MLP method");
- TMVA::MethodMLP *mlp = dynamic_cast<TMVA::MethodMLP*>(m);
- TObjArray* Network=mlp->fNetwork;
- int num_neurons_input=((TObjArray*)Network->At(1))->GetEntriesFast()-1;
- if(debug) cout<<"num_neurons_input "<<num_neurons_input<<endl;
-// mlp->MakeClass(Form("mlpcode_neurons%i.C",num_neurons_input));
- 
- int fLayers = Network->GetEntriesFast();
- 
- for(int a=0;a<((TObjArray*)Network->At(1))->GetEntriesFast();a++)
- {
-  vector<double> thisvector;
-  for(int b=0;b<((TObjArray*)Network->At(0))->GetEntriesFast();b++)
-   thisvector.push_back(0);
-  m_fWeightMatrix0to1.push_back(thisvector);
- }
- 
- for(int a=0;a<((TObjArray*)Network->At(2))->GetEntriesFast();a++)
- {
-  vector<double> thisvector;
-  for(int b=0;b<((TObjArray*)Network->At(1))->GetEntriesFast();b++)
-   thisvector.push_back(0);
-  m_fWeightMatrix1to2.push_back(thisvector);
- }
- 
- 
- TObjArray* curLayer= (TObjArray*)Network->At(0);
- Int_t numNeurons = curLayer->GetEntriesFast();
- for (Int_t n = 0; n < numNeurons; n++)
- {  
-  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
-  int numSynapses = neuron->NumPostLinks();
-  for (int s = 0; s < numSynapses; s++)
-  {
-   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
-   m_fWeightMatrix0to1[s][n]=synapse->GetWeight();
-   if(debug) cout<<"fWeightMatrix0to1["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
-  }
- }
- 
- curLayer= (TObjArray*)Network->At(1);
- numNeurons = curLayer->GetEntriesFast();
- for (Int_t n = 0; n < numNeurons; n++)
- {  
-  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
-  int numSynapses = neuron->NumPostLinks();
-  for (int s = 0; s < numSynapses; s++)
-  {
-   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
-   m_fWeightMatrix1to2[s][n]=synapse->GetWeight();
-   if(debug) cout<<"fWeightMatrix1to2["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
-  }
- }
- 
- delete reader;
-
-*/
- 
-}
-
-double TFCS1DFunctionRegression::regression_value(double uniform)
-{
- double myresult=-1;
- 
- int n_neurons=m_fWeightMatrix0to1.size()-1;
- 
- int fLayers=3;
- vector<int> fLayerSize;
- fLayerSize.push_back(2);
- fLayerSize.push_back(n_neurons+1);
- fLayerSize.push_back(1);
- 
- vector<vector<double> > fWeights;
- for(int l=0;l<fLayers;l++)
- {
-  vector<double> thisvector;
-  for(int i=0;i<fLayerSize[l];i++)
-   thisvector.push_back(0); //placeholder
-  fWeights.push_back(thisvector);
- }
- 
- for (int l=0; l<fLayers; l++)
-  for (int i=0; i<fLayerSize[l]; i++)
-   fWeights[l][i]=0;
-
- for (int l=0; l<fLayers-1; l++)
-  fWeights[l][fLayerSize[l]-1]=1;
-
- for (int i=0; i<fLayerSize[0]-1; i++)
-  fWeights[0][i]=uniform;
-
- // layer 0 to 1
- for (int o=0; o<fLayerSize[1]-1; o++)
- {
-  for (int i=0; i<fLayerSize[0]; i++)
-  {
-   fWeights[1][o] += m_fWeightMatrix0to1[o][i] * fWeights[0][i];
-  }
-  fWeights[1][o] = tanh(fWeights[1][o]);
- }
- 
- // layer 1 to 2
- for (int o=0; o<fLayerSize[2]; o++)
- {
-  for (int i=0; i<fLayerSize[1]; i++)
-  {
-   fWeights[2][o] += m_fWeightMatrix1to2[o][i] * fWeights[1][i];
-  }
- }
- 
- myresult=fWeights[2][0];
- 
- return myresult;
- 
-}
-
-
-double TFCS1DFunctionRegression::rnd_to_fct(double rnd)
-{
-  
-  double value=regression_value(rnd); 
-  return value;
-  
-}
-
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCS1DFunctionRegression)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx
deleted file mode 100644
index 9636c85a5d61fa61797587c3dee0b049a170e4cb..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-using namespace std;
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h"
-#include "TFile.h"
-#include "TString.h"
-#include "TMath.h"
-
-
-//=============================================
-//======= TFCS1DFunctionRegressionTF =========
-//=============================================
-
-using namespace std;
-
-TFCS1DFunctionRegressionTF::TFCS1DFunctionRegressionTF()
-{
-  m_rangeval = 0;
-  m_startval = 0;
-}
-
-void TFCS1DFunctionRegressionTF::storeRegression(string weightfilename, float rangeval, float startval)
-{
-  
-  m_rangeval=rangeval;
-  m_startval=startval;
-  
-	get_weights(weightfilename);
- 
-}
-
-double TFCS1DFunctionRegressionTF::retransform(double value)
-{
- 
- return (value*m_rangeval+m_startval);
- 
-}
-
-double TFCS1DFunctionRegressionTF::rnd_to_fct(double rnd)
-{
-  
-  double value=regression_value(rnd); 
-  if(m_rangeval>0)
-   value=retransform(value);
-  return value;
-  
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCS1DFunctionRegressionTF)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx
deleted file mode 100644
index 44f9472f8813bff3610d12242c5c2064a184b45b..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-using namespace std;
-#include "ISF_FastCaloSimParametrization/TFCSFunction.h"
-#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h"
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h"
-#include "ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h"
-#include "TRandom1.h"
-#include <sstream>  
-#include <iostream>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <ftw.h>
-#include <stdexcept>
-
-//=============================================
-//======= TFCSFunction =========
-//=============================================
-
-TFCSFunction::TFCSFunction()
-{
-  
-}
-
-
-TFCS1DFunction* TFCSFunction::Create(TH1* hist,int skip_regression,int neurons_start, int neurons_end, double maxdev_regression, double maxdev_smartrebin, int ntoys)
-{
- int verbose_level=1;
- 
- // This function is called by the user when he wants a histogram to be transformed into a space efficient variant for the parametrization.
- // All code that decides whether a histogram should be transformed into a TFCS1DFunctionRegression or TFCS1DFunctionHistogram
- // should go here. 
- 
- TRandom1* random=new TRandom1();
- random->SetSeed(0);
- int myrand=floor(random->Uniform()*1000000);
- stringstream ss;
- ss << myrand;
- string myrandstr = ss.str();
- 
- string xmlweightfilename="regressionweights"+myrandstr;
- string outfilename="TMVAReg"+myrandstr+".root";
- float rangeval, startval;
- TFCS1DFunction* fct=new TFCS1DFunction(hist);
- TFCS1DFunctionRegression* freg;
- TFCS1DFunctionRegressionTF* fregTF;
- TFCS1DFunctionHistogram* fhis;
- int status;
- //try
- //{
-  status=fct->testHisto(hist,xmlweightfilename,rangeval,startval,outfilename,skip_regression,neurons_start,neurons_end,maxdev_regression,ntoys);
- //}
- //catch(std::runtime_error &e)
- //{
- // cout<<"An exception occured: "<<e.what()<<endl;
- // cout<<"Continuing anyway :P"<<endl;
- // status=3;
- //}
- 
- if(verbose_level==1) cout<<"--- testHisto status="<<status<<endl;
- if(status==1)
- {
- 	if(verbose_level==1) cout<<"Regression"<<endl;
-  freg=new TFCS1DFunctionRegression();
-  freg->storeRegression(xmlweightfilename);
-  cout<<"xmlweightfilename: "<<xmlweightfilename<<endl;
-  if (remove(outfilename.c_str()) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << outfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "/TMVARegression_MLP.weights.xml; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
-  return freg;
- }
- if(status==2)
- {
- 	if(verbose_level==1) cout<<"Regression and Transformation"<<endl;
-  fregTF=new TFCS1DFunctionRegressionTF();
-  fregTF->storeRegression(xmlweightfilename,rangeval,startval);
-  cout<<"xmlweightfilename: "<<xmlweightfilename<<endl;
-  if (remove(outfilename.c_str()) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << outfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "/TMVARegression_MLP.weights.xml; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
-  return fregTF;
- }
- if(status==3)
- {
-  cout<<"xmlweightfilename: "<<xmlweightfilename<<endl;
-  if (remove(outfilename.c_str()) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << outfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "/TMVARegression_MLP.weights.xml; exiting" << endl;
-    return 0;
-  }
-  if (remove(Form("%s",xmlweightfilename.c_str())) != 0) {
-    cout << "Error in TFCSFunction: unable to remove " << xmlweightfilename.c_str() << "; exiting" << endl;
-    return 0;
-  }
- 	if(verbose_level==1) cout<<"Histogram"<<endl;
-  fhis=new TFCS1DFunctionHistogram(hist, verbose_level,maxdev_smartrebin);
-  return fhis;
- }
- if(status==0)
- {
- 	cout<<"something went wrong :("<<endl;
-  return 0;	
- }
- 
- //delete the weight file folder:
- 
- return 0; 
- 
-}
-
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSFunction)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
index c6c5956e8b617a00789f89ea9e7438b39cf429e2..56e8a183b701d8732571beb278788b759d1bad13 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
@@ -22,11 +22,8 @@
 Class for Tree reading through TFormula.
 ______________________________________________________________________________*/
 
-ClassImp(TreeReader) // Integrate this class into ROOT
 
-//============================================================
 TreeReader::TreeReader()
-  //============================================================
 {
   // Default constructor.
   m_isChain = false;
@@ -36,6 +33,12 @@ TreeReader::TreeReader()
   m_entries = -1;
 }
 
+TreeReader::~TreeReader()
+{
+  m_formulae.clear();
+}
+
+
 //============================================================
 TreeReader::TreeReader(TTree* n)
   //============================================================
@@ -46,14 +49,6 @@ TreeReader::TreeReader(TTree* n)
   SetTree(n);
 }
 
-//============================================================
-TreeReader::~TreeReader()
-  //============================================================
-{
-  // Destructor.
-  m_formulae.clear();
-}
-
 //============================================================
 void TreeReader::SetTree(TTree* n)
   //============================================================
@@ -140,3 +135,7 @@ int TreeReader::GetEntry(int entry)
   return 0;
 }
 
+
+
+//ClassImp(TreeReader) // Integrate this class into ROOT
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements
deleted file mode 100644
index 4b9a97ad0c1167038a069c646901b2a47e196690..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements
+++ /dev/null
@@ -1,90 +0,0 @@
-package ISF_FastCaloSimParametrization
-author <Zdenek.Hubacek@cern.ch>
-
-manager Elmar Ritsch <Elmar.Ritsch@cern.ch>
-manager Zdenek Hubacek <Zdenek.Hubacek@cern.ch>
-
-use AtlasPolicy                 AtlasPolicy-*
-use StoreGate                   StoreGate-*                     Control
-use AthenaKernel                AthenaKernel-*                  Control
-use GaudiInterface              GaudiInterface-*                External
-use AthenaBaseComps             AthenaBaseComps-*               Control
-use CaloDetDescr                CaloDetDescr-*                  Calorimeter
-use AtlasROOT                   AtlasROOT-*                     External
-use Identifier                  Identifier-*                    DetectorDescription
-use AtlasCLHEP                  AtlasCLHEP-*                    External
-use LArElecCalib                LArElecCalib-*                  LArCalorimeter
-
-######################
-use TrkParameters               TrkParameters-*                 Tracking/TrkEvent
-use TrkEventPrimitives          TrkEventPrimitives-*   Tracking/TrkEvent
-use TrkExInterfaces             TrkExInterfaces-*               Tracking/TrkExtrapolation
-use AtlasHepMC                  AtlasHepMC-*                    External
-use HepPDT                      v*                              LCG_Interfaces
-######################
-
-use CaloInterface               CaloInterface-*                 Calorimeter
-use BarcodeInterfaces                BarcodeInterfaces-*                  Simulation/Barcode
-use ISF_Interfaces              ISF_Interfaces-*                Simulation/ISF/ISF_Core
-use ISF_FastCaloSimEvent        ISF_FastCaloSimEvent-*          Simulation/ISF/ISF_FastCaloSim
-
-private
-use Geant4                      Geant4-*                        External
-use EventInfo                   EventInfo-*                     Event
-use GeoModelInterfaces          GeoModelInterfaces-*            DetectorDescription/GeoModel
-# For reading file/DB metadata
-use AthenaPoolUtilities         AthenaPoolUtilities-*           Database/AthenaPOOL
-
-use GeneratorObjects            GeneratorObjects-*              Generators
-use TileSimEvent                TileSimEvent-*                  TileCalorimeter
-use TileDetDescr                TileDetDescr-*                  TileCalorimeter
-use LArSimEvent                 LArSimEvent-*                   LArCalorimeter
-use GeoAdaptors                 GeoAdaptors-*                   DetectorDescription/GeoModel
-use CaloIdentifier              CaloIdentifier-*                Calorimeter
-use CaloGeoHelpers              CaloGeoHelpers-*                Calorimeter
-use TileConditions              TileConditions-*                TileCalorimeter
-
-use NavFourMom                  NavFourMom-*                    Event
-use ISF_Event                   ISF_Event-*                     Simulation/ISF/ISF_Core
-use CaloEvent                   CaloEvent-*                     Calorimeter
-use ISF_FastCaloSimInterfaces   ISF_FastCaloSimInterfaces-*     Simulation/ISF/ISF_FastCaloSim
-
-####################
-use CaloTrackingGeometry        CaloTrackingGeometry-*          Calorimeter
-use TrkMaterialOnTrack          TrkMaterialOnTrack-*            Tracking/TrkEvent
-use TrkSurfaces                 TrkSurfaces-*                   Tracking/TrkDetDescr
-use TrkGeometry         TrkGeometry-*          Tracking/TrkDetDescr
-####################
-
-
-end_private
-
-apply_tag ROOTGraphicsLibs
-apply_tag ROOTMathLibs
-apply_tag ROOTTMVALibs
-apply_tag ROOTTreePlayerLibs
-
-# Create a named installed library
-library ISF_FastCaloSimParametrizationLib "../Root/*.cxx ../src/*.cxx"
-apply_pattern named_installed_library library=ISF_FastCaloSimParametrizationLib
-
-# Create the CINT dictionary
-private
-macro_append extra_root_cint_includes " -p -I$(CaloGeoHelpers_root) "
-end_private
-apply_pattern have_root_headers root_headers="MeanAndRMS.h TFCSLateralShapeParametrization.h TFCSNNLateralShapeParametrization.h TFCSSimpleLateralShapeParametrization.h TFCS1DFunctionRegression.h TFCS1DFunctionHistogram.h TFCSFunction.h TreeReader.h firstPCA.h secondPCA.h TFCS2Function.h TFCS2DFunction.h DetailedShapeBinning.h FitDetailedShape.h TFCS2DFunctionRegression.h TFCS1DFunctionRegressionTF.h ../Root/LinkDef.h" \ 
-              headers_lib=ISF_FastCaloSimParametrizationLib 
-
-macro_append ISF_FastCaloSimParametrizationLib_shlibflags "-L$(ROOTSYS)/lib -lTree -lTreePlayer"
-apply_pattern cmake_add_command command="find_package(ROOT COMPONENTS Tree TreePlayer)"
-
-library ISF_FastCaloSimParametrization *.cxx components/*.cxx
-macro_append ISF_FastCaloSimParametrization_dependencies " ISF_FastCaloSimParametrizationLib"
-apply_pattern component_library
-
-apply_pattern declare_joboptions files="*.py"
-apply_pattern declare_python_modules files="*.py"
-
-private
-#macro cppdebugflags '$(cppdebugflags_s)'
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cb881836b9c4571ac50d2004d33fff54a3872b20
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.cxx
@@ -0,0 +1,484 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TFCS1DRegression.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+
+#include "TMVA/Config.h"
+#include "TMVA/Tools.h"
+#include "TMVA/Reader.h"
+#include "TMVA/Factory.h"
+#include "TRandom1.h"
+#include "TFile.h"
+#include "TString.h"
+#include "TMath.h"
+
+#include "TMVA/DataLoader.h"
+
+#include "TMVA/IMethod.h"
+#include "TMVA/MethodMLP.h"
+
+using namespace std;
+
+
+void TFCS1DRegression::storeRegression(string weightfilename, vector<vector<double> > &fWeightMatrix0to1, vector<vector<double> > &fWeightMatrix1to2)
+{
+  
+	get_weights(weightfilename, fWeightMatrix0to1, fWeightMatrix1to2);
+ 	
+  //for testing:
+  //validate(10,weightfilename);
+ 
+}
+
+void TFCS1DRegression::validate(int Ntoys,string weightfilename)
+{
+ 
+ TRandom1* myRandom=new TRandom1(); myRandom->SetSeed(0);
+ 
+ //calculate regression from the weights and compare to TMVA value:
+ cout<<endl;
+ cout<<"--- Validating the regression value:"<<endl;
+ for(int i=0;i<Ntoys;i++)
+ {
+  double random=myRandom->Uniform(1);
+  //double myval=regression_value(random);
+  double myval=-1;
+  double tmvaval=tmvaregression_application(random,weightfilename);
+  cout<<"myvalue "<<myval<<" TMVA value "<<tmvaval<<endl;
+ }
+}
+
+TH1* TFCS1DRegression::transform(TH1* h_input, float &rangeval, float& startval)
+{
+
+  bool do_transform=false;
+  float xmin=h_input->GetXaxis()->GetXmin();
+  float xmax=h_input->GetXaxis()->GetXmax();
+  if(xmin<0 || xmax>1) do_transform=true;
+
+  TH1D* h_out;
+
+  if(do_transform)
+  {
+    int nbins=h_input->GetNbinsX();
+    double min=0;
+    double max=1;
+    h_out=new TH1D("h_out","h_out",nbins,min,max);
+
+    for(int b=1;b<=nbins;b++)
+      h_out->SetBinContent(b,h_input->GetBinContent(b));
+
+    //store the inital range
+    rangeval=xmax-xmin;
+    startval=xmin;
+  }
+  if(!do_transform)
+  {
+    rangeval=-1;
+    h_out=(TH1D*)h_input->Clone("h_out");
+  }
+  return h_out;
+
+}
+
+double TFCS1DRegression::get_range_low(TH1* hist)
+{
+  double range_low=0.0;
+  int bin_start=-1;
+  for(int b=1;b<=hist->GetNbinsX();b++)
+  {
+    if(hist->GetBinContent(b)>0 && bin_start<0)
+    {
+      bin_start=b;
+      range_low=hist->GetBinContent(b);
+      b=hist->GetNbinsX()+1;
+    }
+  }
+  return range_low;
+}
+
+TH1* TFCS1DRegression::get_cumul(TH1* hist)
+{
+  TH1D* h_cumul=(TH1D*)hist->Clone("h_cumul");
+  double sum=0;
+  for(int b=1;b<=h_cumul->GetNbinsX();b++)
+  {
+    sum+=hist->GetBinContent(b);
+    h_cumul->SetBinContent(b,sum);
+  }
+  return h_cumul; 
+}
+
+int TFCS1DRegression::testHisto(TH1* hist, std::string weightfilename, float &rangeval, float &startval, std::string outfilename, int neurons_start, int neurons_end, double cut_maxdev, int ntoys)
+{
+  //int debug=1;
+
+  //transform the histogram
+  TH1* h_transf=transform(hist, rangeval, startval); h_transf->SetName("h_transf");
+  
+  //new! map the y-axis to 0-1:
+  
+  
+  //Turn the histogram into a tree:
+  std::vector<double> contents;
+  std::vector<double> centers;
+  for(int b=1;b<=h_transf->GetNbinsX();b++)
+  {
+    contents.push_back(h_transf->GetBinContent(b));
+    centers.push_back(h_transf->GetBinCenter(b));
+  }
+
+  TTree* tree=new TTree("tree","tree");
+  Float_t x,y;
+  tree->Branch("x",&x,"x/F");
+  tree->Branch("y",&y,"y/F");
+
+  for(unsigned int i=0;i<centers.size();i++)
+  {
+    y=(Float_t)(contents[i]);   //xvals are the BinContents
+    x=(Float_t)(centers[i]);    //yvals are the BinCenters
+
+    tree->Fill();
+  }
+  
+  double range_low=get_range_low(h_transf);
+
+  TRandom1* myRandom=new TRandom1(); myRandom->SetSeed(0);
+  
+  int do_range=1;
+  double maxdev=1000;
+  int neurons=neurons_start;
+  std::vector<TH1*> histos;
+  while(maxdev>cut_maxdev && neurons<=neurons_end)
+  {
+  	
+   int pass_training=0;
+   try
+   {
+    TFCS1DRegression::tmvaregression_training(neurons, tree, weightfilename, outfilename, pass_training);
+   }
+   catch(std::runtime_error &e)
+   {
+    std::cout<<"An exception occured: "<<e.what()<<std::endl;
+    std::cout<<"Continuing anyway :P"<<std::endl;
+    pass_training=0;
+   }
+    
+   if(pass_training)
+   {
+    
+    std::cout<<"Testing the regression with "<<ntoys<<" toys"<<std::endl;
+    TH1* h_output=(TH1*)h_transf->Clone("h_output");
+    h_output->Reset();
+    for(int i=0;i<ntoys;i++)
+    {
+     double random=myRandom->Uniform(1);
+     if(do_range && random<range_low) random=range_low;
+     double value=TFCS1DRegression::tmvaregression_application(random,weightfilename);
+     h_output->Fill(value);    
+    }
+     
+    TH1* h_cumul=get_cumul(h_output);
+    h_cumul->SetName(Form("h_cumul_neurons%i",neurons));
+    histos.push_back(h_cumul);
+     
+    maxdev=TFCS1DFunction::get_maxdev(h_transf,h_cumul);
+    std::cout<<"---> Neurons="<<neurons<<" MAXDEV="<<maxdev<<"%"<<std::endl;
+   }
+   
+   neurons++;
+   
+  }
+  
+  //TH1* histclone=(TH1*)hist->Clone("histclone");
+
+  /* 
+     TFile* out_iteration=new TFile(Form("output/iteration_%s.root",label.c_str()),"RECREATE");
+     for(int h=0;h<histos.size();h++)
+     {
+     out_iteration->Add(histos[h]);
+     }
+     out_iteration->Add(histclone);
+     out_iteration->Write();
+     out_iteration->Close();
+     */
+
+  int regression_success=1;
+  if(maxdev>cut_maxdev) regression_success=0;
+
+  int status=0;
+  if(regression_success)
+  {
+    std::cout<<"Regression successful. Weights are stored."<<std::endl;
+    if(rangeval<0)  status=1;
+    if(rangeval>=0) status=2;
+  }
+
+  if(!regression_success)
+  {
+    std::cout<<"Regression failed. Histogram is stored."<<std::endl;
+    status=3;
+  } //!success
+
+  return status;
+
+}
+
+
+double TFCS1DRegression::tmvaregression_application(double uniform, std::string weightfile)
+{
+
+ using namespace TMVA;
+ 
+ TString myMethodList = "" ;
+ TMVA::Tools::Instance();
+ 
+ std::map<std::string,int> Use;
+ 
+ Use["PDERS"]           = 0;   Use["PDEFoam"]         = 0;   Use["KNN"]            = 0;
+ Use["LD"]             = 0;   Use["FDA_GA"]          = 0;   Use["FDA_MC"]          = 0;
+ Use["FDA_MT"]          = 0;   Use["FDA_GAMT"]        = 0;   Use["MLP"]             = 1; 
+ Use["SVM"]             = 0;   Use["BDT"]             = 0;   Use["BDTG"]            = 0;
+ 
+ // Select methods (don't look at this code - not of interest)
+ if(myMethodList != "")
+ {
+  for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;
+  std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
+  for (UInt_t i=0; i<mlist.size(); i++)
+  {
+   std::string regMethod(mlist[i]);
+   if (Use.find(regMethod) == Use.end())
+   {
+    std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
+    for(std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
+    std::cout << std::endl;
+    return 0;
+   }
+   Use[regMethod] = 1;
+  }
+ }
+ 
+ // --------------------------------------------------------------------------------------------------
+ 
+ TMVA::Reader *reader = new TMVA::Reader( "!Color:Silent");    
+ 
+ Float_t y=uniform;
+ reader->AddVariable( "y", &y );
+ 
+ TString dir    = Form("dl/%s/",weightfile.c_str());
+ TString prefix = "TMVARegression";
+ 
+ // Book method(s)
+ for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++)
+ {
+  if (it->second)
+  {
+   TString methodName = it->first + " method";
+   TString weightfilename = dir + prefix + "_" + TString(it->first) + ".weights.xml";
+   reader->BookMVA( methodName, weightfilename ); 
+  }
+ }
+ 
+ Float_t val = (reader->EvaluateRegression("MLP method"))[0];
+ 
+ delete reader;
+ return val;
+
+  return 0;
+}
+
+void TFCS1DRegression::tmvaregression_training(int neurons, TTree *regTree, std::string weightfile, std::string outfilename, int& pass_training)
+{
+
+  using namespace TMVA;
+
+  TString myMethodList = "" ;
+  TMVA::Tools::Instance();
+  std::map<std::string,int> Use;
+
+  Use["PDERS"] = 0;  Use["PDEFoam"] = 0; Use["KNN"] = 0;  Use["LD"]  = 0; Use["FDA_GA"] = 0; Use["FDA_MC"] = 0;
+  Use["FDA_MT"] = 0; Use["FDA_GAMT"] = 0; Use["MLP"] = 1; Use["SVM"] = 0; Use["BDT"] = 0; Use["BDTG"] = 0;
+
+  std::cout << std::endl; std::cout << "==> Start TMVARegression with "<<neurons<<" Neurons "<<std::endl;
+
+  if(myMethodList != "")
+  {
+    for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;
+    std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
+    for (UInt_t i=0; i<mlist.size(); i++)
+    {
+      std::string regMethod(mlist[i]);
+      if (Use.find(regMethod) == Use.end())
+      {
+        std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
+        for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
+        std::cout << std::endl;
+        return;
+      }
+      Use[regMethod] = 1;
+    }
+  }
+  
+  TFile* outputFile = TFile::Open( outfilename.c_str(), "RECREATE" );
+
+  TMVA::DataLoader *dl=new TMVA::DataLoader("dl");
+
+  TMVA::Factory *factory = new TMVA::Factory( "TMVARegression", outputFile, "!V:!Silent:Color:DrawProgressBar:AnalysisType=Regression" );
+
+  TString dirname=Form("%s/",weightfile.c_str());
+  (TMVA::gConfig().GetIONames()).fWeightFileDir = dirname;
+  
+  dl->AddVariable( "y", "y", 'F' );
+  dl->AddTarget( "x" );
+  
+  Double_t regWeight  = 1.0;   
+
+  dl->AddRegressionTree( regTree, regWeight );
+  TCut mycut = "";
+  //dl->PrepareTrainingAndTestTree( mycut,"nTrain_Regression=0:nTest_Regression=1:SplitMode=Block:NormMode=NumEvents:!V" );
+  dl->PrepareTrainingAndTestTree( mycut,"nTrain_Regression=0:nTest_Regression=0:SplitMode=Alternate:NormMode=NumEvents:!V" );
+  
+  factory->BookMethod(dl, TMVA::Types::kMLP, "MLP",
+  Form("!H:!V:VerbosityLevel=Info:NeuronType=sigmoid:NCycles=20000:HiddenLayers=%i:TestRate=6:TrainingMethod=BFGS:Sampling=0.3:SamplingEpoch=0.8:ConvergenceImprove=1e-6:ConvergenceTests=15:!UseRegulator",neurons)); 
+
+  // Train MVAs using the set of training events
+  factory->TrainAllMethods();
+  
+  // ---- Evaluate all MVAs using the set of test events
+  //factory->TestAllMethods();
+
+  // ----- Evaluate and compare performance of all configured MVAs
+  //factory->EvaluateAllMethods();
+
+  // Save the output
+  outputFile->Close();
+
+  std::cout << "==> Wrote root file: " << outputFile->GetName() << std::endl;
+  std::cout << "==> TMVARegression is done!" << std::endl;      
+  
+  delete factory;  
+  delete dl;
+  
+  pass_training=1;
+
+}
+
+
+void TFCS1DRegression::get_weights(string weightfile, vector<vector<double> > &fWeightMatrix0to1, vector<vector<double> > &fWeightMatrix1to2)
+{
+ 
+ using namespace TMVA;
+ int debug=1;
+ 
+ TString myMethodList = "" ;
+ TMVA::Tools::Instance();
+ 
+ std::map<std::string,int> Use;
+
+ // --- Mutidimensional likelihood and Nearest-Neighbour methods
+ Use["PDERS"]           = 0;   Use["PDEFoam"]         = 0;   Use["KNN"]            = 0;
+ Use["LD"]		          = 0;   Use["FDA_GA"]          = 0;   Use["FDA_MC"]          = 0;
+ Use["FDA_MT"]          = 0;   Use["FDA_GAMT"]        = 0;   Use["MLP"]             = 1; 
+ Use["SVM"]             = 0;   Use["BDT"]             = 0;   Use["BDTG"]            = 0;
+ // ---------------------------------------------------------------
+
+ // Select methods (don't look at this code - not of interest)
+ if (myMethodList != "")
+ {
+  for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;
+  std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
+  for (UInt_t i=0; i<mlist.size(); i++)
+  {
+   std::string regMethod(mlist[i]);
+   if (Use.find(regMethod) == Use.end())
+   {
+    std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
+    for(std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
+    std::cout << std::endl;
+   }
+   Use[regMethod] = 1;
+  }
+ }
+ 
+ // --------------------------------------------------------------------------------------------------
+ 
+ TMVA::Reader *reader = new TMVA::Reader( "!Color:Silent");    
+ 
+ Float_t y=0.5; //just a dummy
+ reader->AddVariable( "y", &y );
+ 
+ TString dir   = Form("dl/%s/",weightfile.c_str());
+ TString prefix = "TMVARegression";
+ 
+ for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++)
+ {
+  if (it->second)
+  {
+   TString methodName = it->first + " method";
+   TString weightfilename = dir + prefix + "_" + TString(it->first) + ".weights.xml";
+   reader->BookMVA( methodName, weightfilename ); 
+  }
+ }
+ 
+ TMVA::IMethod* m=reader->FindMVA("MLP method");
+ TMVA::MethodMLP *mlp = dynamic_cast<TMVA::MethodMLP*>(m);
+ TObjArray* Network=mlp->fNetwork;
+ int num_neurons_input=((TObjArray*)Network->At(1))->GetEntriesFast()-1;
+ if(debug) cout<<"num_neurons_input "<<num_neurons_input<<endl;
+// mlp->MakeClass(Form("mlpcode_neurons%i.C",num_neurons_input));
+ 
+ int fLayers = Network->GetEntriesFast();
+ 
+ for(int a=0;a<((TObjArray*)Network->At(1))->GetEntriesFast();a++)
+ {
+  vector<double> thisvector;
+  for(int b=0;b<((TObjArray*)Network->At(0))->GetEntriesFast();b++)
+   thisvector.push_back(0);
+  fWeightMatrix0to1.push_back(thisvector);
+ }
+ 
+ for(int a=0;a<((TObjArray*)Network->At(2))->GetEntriesFast();a++)
+ {
+  vector<double> thisvector;
+  for(int b=0;b<((TObjArray*)Network->At(1))->GetEntriesFast();b++)
+   thisvector.push_back(0);
+  fWeightMatrix1to2.push_back(thisvector);
+ }
+ 
+ 
+ TObjArray* curLayer= (TObjArray*)Network->At(0);
+ Int_t numNeurons = curLayer->GetEntriesFast();
+ for (Int_t n = 0; n < numNeurons; n++)
+ {  
+  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
+  int numSynapses = neuron->NumPostLinks();
+  for (int s = 0; s < numSynapses; s++)
+  {
+   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
+   fWeightMatrix0to1[s][n]=synapse->GetWeight();
+   if(debug) cout<<"fWeightMatrix0to1["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
+  }
+ }
+ 
+ curLayer= (TObjArray*)Network->At(1);
+ numNeurons = curLayer->GetEntriesFast();
+ for (Int_t n = 0; n < numNeurons; n++)
+ {  
+  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
+  int numSynapses = neuron->NumPostLinks();
+  for (int s = 0; s < numSynapses; s++)
+  {
+   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
+   fWeightMatrix1to2[s][n]=synapse->GetWeight();
+   if(debug) cout<<"fWeightMatrix1to2["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
+  }
+ }
+ 
+ delete reader;
+ 
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.h
new file mode 100644
index 0000000000000000000000000000000000000000..61c41d95a12357235116d49e3979a7926ba73096
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCS1DRegression.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TFCS1DRegression_h
+#define TFCS1DRegression_h
+
+// STL includes
+#include <string>
+
+#include "TH1.h"
+#include "TTree.h"
+
+class TFCS1DRegression
+{
+  public:
+    TFCS1DRegression() {};
+    ~TFCS1DRegression() {};
+    
+    static int testHisto(TH1* hist, std::string, float&, float&, std::string, int, int, double, int);
+    static void storeRegression(string, vector<vector<double> > &fWeightMatrix0to1, vector<vector<double> > &fWeightMatrix1to2);
+    static void get_weights(string weightfile, vector<vector<double> > &fWeightMatrix0to1, vector<vector<double> > &fWeightMatrix1to2);
+    
+    static TH1* transform(TH1* h_input, float &rangeval, float& startval);
+    static double get_range_low(TH1* hist);
+    static void tmvaregression_training(int, TTree *regTree, std::string, std::string, int&);
+    static TH1* get_cumul(TH1* hist);
+    static double tmvaregression_application(double, std::string);
+    static void validate(int,string);
+    
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class TFCS1DRegression+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..234903d818e4b16023c836dd0b7e1521474d3edf
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.cxx
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCS1DFunctionRegression.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunctionRegressionTF.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunctionHistogram.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+
+#include "TFCSFunction.h"
+#include "TFCS1DRegression.h"
+
+#include "TFile.h"
+#include "TRandom1.h"
+
+
+#include <iostream>
+
+//#include <string>
+#include <sstream>
+
+using namespace std;
+
+//=============================================
+//======= TFCSFunction =========
+//=============================================
+
+
+TFCS1DFunction* TFCSFunction::Create(TH1* hist,int skip_regression,int neurons_start, int neurons_end, double maxdev_regression, double maxdev_smartrebin, int ntoys)
+{
+ int verbose_level=1;
+ 
+ // This function is called by the user when he wants a histogram to be transformed into a space efficient variant for the parametrization.
+ // All code that decides whether a histogram should be transformed into a TFCS1DFunctionRegression or TFCS1DFunctionHistogram
+ // should go here. 
+ 
+ TRandom1* random=new TRandom1();
+ random->SetSeed(0);
+ int myrand=floor(random->Uniform()*1000000);
+ stringstream ss;
+ ss << myrand;
+ string myrandstr = ss.str();
+ 
+ string xmlweightfilename="regressionweights"+myrandstr;
+ string outfilename="TMVAReg"+myrandstr+".root";
+ float rangeval, startval;
+ 
+ TFCS1DFunctionRegression* freg=0;
+ TFCS1DFunctionRegressionTF* fregTF=0;
+ TFCS1DFunctionHistogram* fhis=0;
+ 
+ int status=3;
+ 
+ if(!skip_regression)
+  status=TFCS1DRegression::testHisto(hist,xmlweightfilename,rangeval,startval,outfilename,neurons_start,neurons_end,maxdev_regression,ntoys);
+ 
+ if(verbose_level==1) cout<<"--- testHisto status="<<status<<endl;
+ if(status==1)
+ {
+ 	if(verbose_level==1) cout<<"Regression"<<endl;
+  freg=new TFCS1DFunctionRegression();
+  vector<vector<double> > fWeightMatrix0to1;
+  vector<vector<double> > fWeightMatrix1to2;
+  TFCS1DRegression::storeRegression(xmlweightfilename, fWeightMatrix0to1, fWeightMatrix1to2);
+  freg->set_weights(fWeightMatrix0to1, fWeightMatrix1to2);
+  remove(outfilename.c_str());
+  remove(Form("dl/%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str()));
+  remove(Form("dl/%s",xmlweightfilename.c_str()));
+  return freg;
+ }
+ if(status==2)
+ {
+ 	if(verbose_level==1) cout<<"Regression and Transformation"<<endl;
+  fregTF=new TFCS1DFunctionRegressionTF(rangeval,startval);
+  vector<vector<double> > fWeightMatrix0to1;
+  vector<vector<double> > fWeightMatrix1to2;
+  TFCS1DRegression::storeRegression(xmlweightfilename, fWeightMatrix0to1, fWeightMatrix1to2);
+  fregTF->set_weights(fWeightMatrix0to1, fWeightMatrix1to2);
+  remove(outfilename.c_str());
+  remove(Form("dl/%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str()));
+  remove(Form("dl/%s",xmlweightfilename.c_str()));
+  return fregTF;
+ }
+ if(status==3)
+ {
+  cout<<"xmlweightfilename: "<<xmlweightfilename<<endl;
+  remove(outfilename.c_str());
+  remove(Form("dl/%s/TMVARegression_MLP.weights.xml",xmlweightfilename.c_str()));
+  remove(Form("dl/%s",xmlweightfilename.c_str()));
+ 	if(verbose_level==1) cout<<"Histogram"<<endl;
+  fhis=new TFCS1DFunctionHistogram(hist, verbose_level,maxdev_smartrebin);
+  return fhis;
+ }
+ if(status==0)
+ {
+ 	cout<<"something went wrong :("<<endl;
+  return 0;	
+ }
+ 
+ return 0;
+ 
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.h
similarity index 67%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.h
index 996ae2c4908ffad73c35156f4d65891e80d41375..623e8f036f7216bd4c4a014004bf88610f6b2c79 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/TFCSFunction.h
@@ -6,17 +6,24 @@
 #define TFCSFunction_h
 
 #include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
 
 class TFCSFunction
 {
   public:
-    TFCSFunction();
-    virtual ~TFCSFunction() {}
+    TFCSFunction() {};
+    //virtual ~TFCSFunction() {};
+    ~TFCSFunction() {};
+    
     static TFCS1DFunction* Create(TH1* hist,int,int,int,double,double,int);
+  
   private:
 
   ClassDef(TFCSFunction,1)
+ 
 };
 
+#if defined(__MAKECINT__)
+#pragma link C++ class TFCSFunction+;
+#endif
+
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.cxx
similarity index 99%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.cxx
index b1b5f6876e314041af9af8c20707bf66e500c1bb..83a74beb242c81592aac5358abbe5b82e3f13a62 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.cxx
@@ -17,7 +17,7 @@ using namespace std;
 #include "TPrincipal.h"
 #include "TMath.h"
 #include "TBrowser.h"
-#include "ISF_FastCaloSimParametrization/firstPCA.h"
+#include "firstPCA.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
 #include "TLorentzVector.h"
 #include "TChain.h"
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.h
similarity index 92%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.h
index 8ac9fde492877e73008d5a5293d8f2be3514285e..6bc044711a0af14237d2ba562abd34af7ba2da10 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/firstPCA.h
@@ -7,6 +7,8 @@
 #include "TChain.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
 
+using namespace std;
+
 class firstPCA
 {
   public:
@@ -43,5 +45,9 @@ class firstPCA
   
 };
 
+#if defined(__MAKECINT__)
+#pragma link C++ class firstPCA+;
+#endif
+
 #endif
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.cxx
similarity index 97%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.cxx
index 85b1cc5ce3e760cac0cd873a9548485f74cb67fa..40e46192ae0b8e3cc46a61e2207b3e299ce3b9c1 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.cxx
@@ -2,7 +2,6 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-using namespace std;
 #include "TMatrixF.h"
 #include "TMatrixD.h"
 #include "TMatrixDSym.h"
@@ -19,17 +18,18 @@ using namespace std;
 #include "TPrincipal.h"
 #include "TMath.h"
 #include "TBrowser.h"
-#include "ISF_FastCaloSimParametrization/secondPCA.h"
-#include "ISF_FastCaloSimParametrization/firstPCA.h"
-#include "ISF_FastCaloSimParametrization/TreeReader.h"
-#include "ISF_FastCaloSimParametrization/TFCSFunction.h"
+#include "secondPCA.h"
+#include "firstPCA.h"
+#include "TFCSFunction.h"
 #include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
-#include "ISF_FastCaloSimParametrization/IntArray.h"
+#include "ISF_FastCaloSimParametrization/TreeReader.h"
+#include "ISF_FastCaloSimEvent/IntArray.h"
 
 #include <iostream>
 #include <sstream>
 
+using namespace std;
+
 secondPCA::secondPCA(string firstpcafilename, string outfilename)
 {
  m_firstpcafilename=firstpcafilename;
@@ -227,6 +227,8 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
  
  cout<<"--- Application to get Mean and RMS of the PCA transformed data"<<endl;
  TreeReader* reader_treeGauss = new TreeReader();
+
+ cout<<"check1"<<endl;
  reader_treeGauss->SetTree(T_Gauss);
  
  vector<double> data_PCA_min; vector<double> data_PCA_max;
@@ -300,10 +302,8 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
  for (auto it = h_data_PCA.begin(); it != h_data_PCA.end(); ++it)
   delete *it;
  h_data_PCA.clear();
-
  
  //get the lower ranges and store them:
-
  double* lowerBound=new double[layer.size()];
  for(unsigned int l=0;l<layer.size();l++)
  {
@@ -341,7 +341,9 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
  //call the TFCS1DFunction to decide whether or not to use regression:
  for(unsigned int l=0;l<layer.size();l++)
  {
- 	cout<<"Now create the fct object for "<<layer[l]<<endl;
+ 	cout<<endl;
+ 	cout<<"====> Now create the fct object for "<<layer[l]<<" <===="<<endl;
+  cout<<endl;
   stringstream ss;
   ss << bin;
   string binstring = ss.str();
@@ -362,6 +364,7 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
 double secondPCA::get_lowerBound(TH1D* h_cumulative)
 {
  
+ /*
  double range_low=0;
  int bin_start,bin_end;
  bin_start=bin_end=-1;
@@ -378,8 +381,9 @@ double secondPCA::get_lowerBound(TH1D* h_cumulative)
  	 bin_end=b;
  	}
  }
- 
  return range_low;
+ */
+ return h_cumulative->GetBinContent(1);
  
 }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.h
similarity index 85%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.h
index 6c6f354678f08602c7602367bca3bd5de49efa85..a8993ba5c3b595b6a060702310b50c7430a24eb3 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/epara/secondPCA.h
@@ -6,11 +6,11 @@
 #define secondPCA_h
 
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
-#include "ISF_FastCaloSimParametrization/firstPCA.h"
-//#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
-//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
+#include "firstPCA.h"
 
-class secondPCA:public firstPCA
+using namespace std;
+
+class secondPCA: public firstPCA
 {
   public:
   	
@@ -45,5 +45,9 @@ class secondPCA:public firstPCA
   
 };
 
+#if defined(__MAKECINT__)
+#pragma link C++ class secondPCA+;
+#endif
+
 #endif
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..df0bb9782a64249b75b07addf554c95413a534aa
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.cxx
@@ -0,0 +1,1119 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/* Class to implement:
+ *
+ *      - calculate optimal binning
+ *      - produce distributions
+ *      - create TTree for NN regression
+ *
+ *    <a.hasib@cern.ch>
+ *****************************************************/
+#include <iostream>
+#include <tuple>
+#include <algorithm>
+
+#include "TString.h"
+#include "TMath.h"
+#include "TFile.h"
+#include "TH1.h"
+#include "TH2.h"
+
+#include "ShowerShapeBinning.h"
+
+
+
+using namespace std;
+
+
+ShowerShapeBinning::ShowerShapeBinning()
+{
+   m_debug = 0;
+
+   m_calolayer      = -1;
+   m_PCAbin         = 0;
+   m_nbinsR         = 0;
+   m_nbinsAlpha     = 0;
+   m_mincalosize    = 0.;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+   m_tolerance      = 0.;
+}
+
+
+ShowerShapeBinning::~ShowerShapeBinning()
+{
+   if (hEnergyDensity)
+   {
+      delete hEnergyDensity;
+   }
+   if (hEnergy)
+   {
+      delete hEnergy;
+   }
+   if (hLnEnergy)
+   {
+      delete hLnEnergy;
+   }
+   if (hLnEnergyDensity)
+   {
+      delete hLnEnergyDensity;
+   }
+}
+
+
+void ShowerShapeBinning::CreateHitsAlphaDrNtuple(std::string inputHits)
+{
+   // * get the input hits file
+
+   cout << "* Reading input hits file = " << inputHits.c_str() << endl;
+
+   TFile *inputHitsFile = TFile::Open(inputHits.c_str());
+
+   // * get the TTrees from hitsFile
+
+   TTree *hitsTree   = (TTree *)inputHitsFile->Get("hits");
+   TTree *globalTree = (TTree *)inputHitsFile->Get("global");
+
+
+   // * initialize the hits and global TTrees
+   InitHitsTree(hitsTree, globalTree);
+
+   // * Get the global variables
+   globalTree->GetEntry(0);
+
+   float etaCenter = m_etaCenter;
+   float phiCenter = m_phiCenter;
+   float etaShift  = m_etaShift;
+   float phiShift  = m_phiShift;
+
+   float cell_r    = m_cellr;
+   float cell_z    = m_cellz;
+   float cell_eta  = m_celleta;
+   float cell_deta = m_cellDeta;
+   float cell_dphi = m_cellDphi;
+
+
+   if (m_debug)
+   {
+      cout << " eta center = " << etaCenter << ", phi center = " << phiCenter << " , eta shift = " << etaShift << " , phi shift = " << phiShift << ", cell r = " << cell_r << ", cell z = " << cell_z << ", cell eta = " << cell_eta << ", cell deta = " << cell_deta << ", cell dpi = " << cell_dphi << endl;
+   }
+
+   // * define alpha and dr histograms needed to determine binning
+
+   float alphaMin = TMath::Pi() / 8; // * to cover the crack region in a single bin
+   float alphaMax = 2 * TMath::Pi() + alphaMin;
+   float rMax     = 10000;
+
+   // * use fine binning for the initial histograms
+   TH1F *h_alpha = new TH1F("h_alpha", "h_alpha", 630000, alphaMin, alphaMax);
+   TH1F *h_dr    = new TH1F("h_dr", "h_dr", 75000000, 0, rMax);
+
+   TH1F *h_alphaE = new TH1F("h_alphaE", "h_alphaE", 630000, alphaMin, alphaMax);
+
+   TH1F *hdeta = new TH1F("hdeta", "hdeta", 100, -0.2, 0.2);
+   TH1F *hdphi = new TH1F("hdphi", "hdphi", 100, -0.2, 0.2);
+
+   TH1F *hdetaE = new TH1F("hdetaE", "hdetaE", 100, -0.2, 0.2);
+   TH1F *hdphiE = new TH1F("hdphiE", "hdphiE", 100, -0.2, 0.2);
+
+   TH1F *hdeta_corr = new TH1F("hdeta_corr", "hdeta_corr", 100, -0.2, 0.2);
+   TH1F *hdphi_corr = new TH1F("hdphi_corr", "hdphi_corr", 100, -0.2, 0.2);
+
+   //* plot energy heatmap before binning optimization
+   TH2F *hDetaDphi  = new TH2F("hDetaDphi", "hDetaDphi", 100, -0.02, 0.02, 100, -0.02, 0.02);
+   TH2F *hDetaDphiE = new TH2F("hDetaDphiE", "hDetaDphiE", 100, -0.02, 0.02, 100, -0.02, 0.02);
+
+   TH2F *hDetaDphi_corr  = new TH2F("hDetaDphi_corr", "hDetaDphi_corr", 100, -0.02, 0.02, 100, -0.02, 0.02);
+   TH2F *hDetaDphiE_corr = new TH2F("hDetaDphiE_corr", "hDetaDphiE_corr", 100, -0.02, 0.02, 100, -0.02, 0.02);
+
+
+   // * define output file to save h_alpha h_dr and TTree with alpha, dr and energy
+
+   std::string HitsAlphaDr = m_topDir + m_particle + "/HitsAlphaDr_" + m_fileName + ".root";
+   if (m_debug)
+   {
+      cout << " hits alpha dr = " << HitsAlphaDr << endl;
+   }
+
+
+   TFile *hitsAlphaDrFile     = new TFile(HitsAlphaDr.c_str(), "recreate");
+   TTree *m_hitsAlphaDrNtuple = new TTree("hitsAlphaDr", "hitsAlphaDr");
+   BookHitsAlphaDrTree(m_hitsAlphaDrNtuple);
+
+   // float sumetaenergy = 0.;
+   // float sumphienergy = 0.;
+   // float energytotal  = 0;
+
+   // for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   // {
+   //    hitsTree->GetEntry(ihit);
+   //    int eventNumber = m_eventNumber;
+
+   //    float energy_hit = m_energy;
+   //    float deta       = m_deta;
+   //    float dphi       = m_dphi;
+
+   //    sumetaenergy += deta * energy_hit;
+   //    sumphienergy += dphi * energy_hit;
+   //    energytotal  += energy_hit;
+   // }
+
+   // float shiftyeta = sumetaenergy / energytotal;
+   // float shiftyphi = sumphienergy / energytotal;
+
+   // cout << " shwifty eta =" << shiftyeta << " shwifty phi = " << shiftyphi << endl;
+
+
+
+   // * loop through all hits
+
+   cout << " Looping over nhits = " << hitsTree->GetEntries() << endl;
+
+   for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   {
+      hitsTree->GetEntry(ihit);
+
+
+
+      int eventNumber = m_eventNumber;
+
+      float energy_hit = m_energy;
+      float eta_hit    = m_etaHit;
+      float phi_hit    = m_phiHit;
+
+      float eta_entrance = m_etaEntrance;
+      float phi_entrance = m_phiEntrance;
+
+      float deta = m_deta;
+      float dphi = m_dphi;
+
+      float deta_mm, dphi_mm;
+      tie(deta_mm, dphi_mm) = GetUnitsmm(eta_hit, deta, dphi, cell_r, cell_z);
+
+      hdeta->Fill(deta_mm);
+      hdphi->Fill(dphi_mm);
+
+      hdetaE->Fill(deta_mm, energy_hit);
+      hdphiE->Fill(dphi_mm, energy_hit);
+
+
+
+      // * calculate the corrected deta, dphi
+
+      float deta_corr = deta - etaShift;
+      float dphi_corr = dphi - phiShift;
+
+      if (m_debug)
+      {
+         cout << "energy hit = " << energy_hit << ", eta hit = " << eta_hit << ", deta = " << deta << ", dphi = " << dphi << ", deta corr = " << deta_corr << ", dphi corr = " << dphi_corr << endl;
+      }
+
+
+      // * get the co-ordinates in mm
+
+      float deta_corr_mm, dphi_corr_mm;
+      tie(deta_corr_mm, dphi_corr_mm) = GetUnitsmm(eta_hit, deta_corr, dphi_corr, cell_r, cell_z);
+
+      hdeta_corr->Fill(deta_corr);
+      hdphi_corr->Fill(dphi_corr);
+
+
+
+      if (m_debug)
+      {
+         cout << "in mm deta corr = " << deta_corr_mm << " dphi corr = " << dphi_corr_mm << endl;
+      }
+
+
+      // * save TH2 of eta-phi w/ and w/o energy weighted
+      hDetaDphi->Fill(deta, dphi);
+      hDetaDphiE->Fill(deta, dphi, energy_hit);
+
+      hDetaDphi_corr->Fill(deta_corr, dphi_corr);
+      hDetaDphiE_corr->Fill(deta_corr, dphi_corr, energy_hit);
+
+
+      // * calculate r and alpha co-ordiantes
+
+      float delta_r = TMath::Sqrt(dphi_corr_mm * dphi_corr_mm + deta_corr_mm * deta_corr_mm);
+      float alpha   = TMath::ATan2(dphi_corr_mm, deta_corr_mm);
+
+      if (alpha < (TMath::Pi() / 8.))
+      {
+         alpha = 2 * TMath::Pi() + alpha;
+      }
+
+      if (m_debug)
+      {
+         cout << " delta r = " << delta_r << " mm, alpha = " << alpha << " mm" << endl;
+      }
+
+      h_alpha->Fill(alpha);
+      h_alphaE->Fill(alpha, energy_hit);
+
+      // * reweight r with hit energy,  if energy > 1 MeV weigher = energy, otherwise weight = 1
+      if (energy_hit > 1.)
+      {
+         h_dr->Fill(delta_r, energy_hit);
+      }
+      else
+      {
+         h_dr->Fill(delta_r, 1);
+      }
+
+
+      // * fill the TTree
+      m_eventNumber = eventNumber;
+      m_alpha       = alpha;
+      m_dr          = delta_r;
+      m_energy      = energy_hit;
+      m_hitsAlphaDrNtuple->Fill();
+   }//end loop over hits
+
+
+
+   hitsAlphaDrFile->cd();
+   m_hitsAlphaDrNtuple->Write();
+   globalTree->CloneTree()->Write();
+   h_alpha->Write();
+   h_dr->Write();
+
+   h_alphaE->Write();
+   //
+   //  hdeta_corr->Write();
+   //  hdphi_corr->Write();
+   //
+
+   hdeta->Write();
+   hdetaE->Write();
+   hdeta_corr->Write();
+
+   hdphi->Write();
+   hdphiE->Write();
+   hdphi_corr->Write();
+
+   hDetaDphi->Write();
+   hDetaDphiE->Write();
+   hDetaDphi_corr->Write();
+   hDetaDphiE_corr->Write();
+
+   hitsAlphaDrFile->Close();
+   inputHitsFile->Close();
+}
+
+
+void ShowerShapeBinning::RunBinning()
+{
+   std::string HitsAlphaDr = m_topDir + m_particle + "/HitsAlphaDr_" + m_fileName + ".root";
+   if (m_debug)
+   {
+      cout << " hits alpha dr = " << HitsAlphaDr << endl;
+   }
+
+   // * identify the file
+   TFile *hitsAlphaDrFile = TFile::Open(HitsAlphaDr.c_str());
+
+   // * read the histograms needed
+   h_alpha = (TH1F *)hitsAlphaDrFile->Get("h_alpha");
+   h_dr    = (TH1F *)hitsAlphaDrFile->Get("h_dr");
+
+   // * initialize the TTrees needed
+   TTree *hitsAlphaDrTree = (TTree *)hitsAlphaDrFile->Get("hitsAlphaDr");
+   TTree *globalTree      = (TTree *)hitsAlphaDrFile->Get("global");
+   InitHitsAlphaDrTree(hitsAlphaDrTree, globalTree);
+
+
+   // * get bin alpha bin boundaries
+
+   int nAlphaBins       = m_nbinsAlpha;
+   int nAlphaBoundaries = nAlphaBins + 1;
+   xbinsAlpha.clear();
+   xbinsAlpha = Getxbins(h_alpha, nAlphaBins);
+
+   float xAlphaBins[nAlphaBoundaries];
+   for (int i = 0; i < nAlphaBoundaries; i++)
+   {
+      xAlphaBins[i] = xbinsAlpha.at(i);
+      if (m_debug)
+      {
+         cout << " BIN ALPHA  " << i << ":  " << xAlphaBins[i] << endl;
+      }
+   }
+
+   // * r binning is iterative to ensure no empty bins
+
+   bool isEmptyBin = true;
+   int  incr       = 0;
+
+   // * hack to know the final nbinsR reached
+
+   int final_nbinsR = -1;
+
+   while (isEmptyBin)
+   {
+      if (incr == m_nbinsR - 2)
+      {
+         cout << " * ERROR: No empty bin requirement cannot be reached. Decrease tolerance! " << endl;
+         exit(EXIT_FAILURE);
+      }
+
+      int nRbinsMax    = m_nbinsR;
+      int nRBins       = nRbinsMax - incr;
+      int nRBoundaries = nRBins + 1;
+
+      cout << " Starting r binning with nbins = " << nRBins << endl;
+
+      std::vector<float> ybinsr = Getxbins(h_dr, nRBins);
+
+      // * first combine the up to last 5 bins with bin width calculated with nRbinsMax
+      // * if there is still empty bin, calculate bin width with nRbinsMax-1 and repeat
+
+
+
+      for (int ibin = 0; ibin < 5; ibin++)
+      {
+         if (ibin > 0)
+         {
+            cout << " * trying to combine bin = " << ibin << endl;
+         }
+
+         if (ibin > 0)
+         {
+            nRBoundaries = nRBoundaries - 1;
+         }
+
+         float yRBins[nRBoundaries];
+
+         for (int i = 0; i < nRBoundaries; i++)
+         {
+            yRBins[i] = ybinsr.at(i);
+
+            if (ibin > 0)
+            {
+               yRBins[nRBoundaries - 1] = ybinsr.at(ybinsr.size() - 1);
+            }
+            if (m_debug)
+            {
+               cout << " BIN R " << i << ": " << yRBins[i] << endl;
+            }
+         }
+
+         // * save the final r binning selected
+         ybinsR.clear();
+         for (unsigned int i = 0; i < sizeof(yRBins); i++)
+         {
+            ybinsR.push_back(yRBins[i]);
+
+            final_nbinsR = sizeof(yRBins);
+         }
+
+
+         // * define histograms needed
+
+         hHits            = new TH2F("hHits", "hHits", nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+         hEnergyDensity   = new TH2F("hEnergyDensity", "hEnergyDensity", nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+         hEnergy          = new TH2F("hEnergy", "hEnergy", nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+         hLnEnergy        = new TH2F("hLnEnergy", "hLnEnergy", nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+         hLnEnergyDensity = new TH2F("hLnEnergyDensity", "hLnEnergyDensity", nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+
+         hGradient = new TH1F("hGradient", "hGradient", nRBoundaries - 1, yRBins);
+
+
+         // * loop over events to fill histograms with this binning
+         cout << " * Start looping over " << hitsAlphaDrTree->GetEntries() << " hits ..." << endl;
+
+
+
+         for (int ihit = 0; ihit < hitsAlphaDrTree->GetEntries(); ihit++)
+         {
+            if (ihit % (hitsAlphaDrTree->GetEntries() / 10) == 0)
+            {
+               cout << " Hit: " << ihit << endl;
+            }
+
+            bool isNewEvent      = false;
+            int  NextEventNumber = -1;
+
+            if (ihit != hitsAlphaDrTree->GetEntries() - 1)
+            {
+               hitsAlphaDrTree->GetEntry(ihit + 1);
+               NextEventNumber = m_eventNumber;
+            }
+
+            hitsAlphaDrTree->GetEntry(ihit);
+
+            int eventNumber = m_eventNumber;
+
+
+            if (ihit == 0)
+            {
+               // * define the histogram for the first hit
+               halphadrE = new TH2F(Form("halphadrE_%i", eventNumber), Form("halphadrE_%i", eventNumber), nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+               halphadrE->Sumw2();
+            }
+
+            float alpha  = m_alpha;
+            float dr     = m_dr;
+            float energy = m_energy;
+
+            if (m_debug)
+            {
+               cout << " alpha = " << alpha << " dr = " << dr << " energy = " << energy << endl;
+            }
+
+
+            hHits->Fill(alpha, dr, 1);
+            halphadrE->Fill(alpha, dr, energy);
+
+
+            if (NextEventNumber != eventNumber or ihit == hitsAlphaDrTree->GetEntries() - 1)
+            {
+               // if the next event has a different eventNumber then normalize
+
+               isNewEvent = true;
+
+               if (m_debug)
+               {
+                  cout << " integral = " << halphadrE->Integral() << endl;
+               }
+
+               if (halphadrE->Integral() > 0)
+               {
+                  halphadrE->Scale(1 / (halphadrE->Integral()));
+                  hEnergy->Add(halphadrE);
+               }
+
+               if (halphadrE)
+               {
+                  delete halphadrE;
+               }
+            }
+
+            if (isNewEvent and ihit != hitsAlphaDrTree->GetEntries() - 1)
+            {
+               halphadrE = new TH2F(Form("halphadrE_%i", eventNumber), Form("halphadrE_%i", eventNumber), nAlphaBins, xAlphaBins, nRBoundaries - 1, yRBins);
+               halphadrE->Sumw2();
+            }
+         }
+         cout << " *Checking if there are empty bins with tolerance = " << m_tolerance << endl;
+         isEmptyBin = CheckEmptyBin();
+
+         cout << " isEmptyBin = " << isEmptyBin << endl;
+
+         if (!isEmptyBin)
+         {
+            break;
+         }
+
+         if (hHits)
+         {
+            delete hHits;
+         }
+         if (hEnergyDensity)
+         {
+            delete hEnergyDensity;
+         }
+         if (hEnergy)
+         {
+            delete hEnergy;
+         }
+         if (hLnEnergy)
+         {
+            delete hLnEnergy;
+         }
+         if (hLnEnergyDensity)
+         {
+            delete hLnEnergyDensity;
+         }
+         if (hGradient)
+         {
+            delete hGradient;
+         }
+
+         cout << " end loop to combine bins" << endl;
+      }// end loop to combine up to 5 bins
+
+      incr++;
+   } // end of while loop
+
+   // * set the nbsinR
+
+   set_nbinsR(final_nbinsR);
+
+
+   // * Define validation histogram
+
+   hValidation = new TH2F("hValidation", "hValidation", 10, -0.5, 9.5, 14, 0.5, 14.5);
+
+   // * check granularity requirement
+   bool isGranularityOK = CheckGranularity(globalTree);
+
+   // * check gradient requirement
+
+   bool isGradientOK = CheckGradient();
+
+   if (isGranularityOK and isGradientOK)
+   {
+      hValidation->Fill(m_PCAbin, m_calolayer, 1);
+   }
+   else if (isGranularityOK and !isGradientOK)
+   {
+      hValidation->Fill(m_PCAbin, m_calolayer, 2);
+   }
+   else if (!isGranularityOK and isGradientOK)
+   {
+      hValidation->Fill(m_PCAbin, m_calolayer, 3);
+   }
+   else if (!isGranularityOK and !isGradientOK)
+   {
+      hValidation->Fill(m_PCAbin, m_calolayer, 4);
+   }
+}
+
+
+void ShowerShapeBinning::CreateNNinput()
+{
+   // * Create NNinput TTrees
+   std::string NNinput      = m_topDir + m_particle + "/NNinput_"/*nbinsR" + std::to_string(m_nbinsR) + "_"*/ + m_fileName + ".root";
+   TFile       *NNinputFile = new TFile(NNinput.c_str(), "recreate");
+
+   TTree *NNbinCenter = new TTree("NNbinCenter", "NNbinCenter");
+   TTree *NNprob      = new TTree("NNprob", "NNprob");
+
+   BookNNinputTree(NNbinCenter, NNprob);
+
+   // * Normalize the energy weighted histogram
+   TH2F *hEnergyNorm = (TH2F *)hEnergy->Clone("hEnergyNorm");
+   hEnergyNorm->Scale(1 / hEnergyNorm->Integral());
+
+   for (int ibinx = 0; ibinx < hEnergy->GetNbinsX() + 1; ibinx++)
+   {
+      float Alphamin = hEnergy->GetXaxis()->GetBinLowEdge(ibinx);
+      float Alphamax = hEnergy->GetXaxis()->GetBinUpEdge(ibinx);
+
+      for (int ibiny = 0; ibiny < hEnergy->GetNbinsY() + 1; ibiny++)
+      {
+         float Rmin = hEnergy->GetXaxis()->GetBinLowEdge(ibiny);
+         float Rmax = hEnergy->GetYaxis()->GetBinUpEdge(ibiny);
+
+         float area = TMath::Pi() * (Rmax * Rmax - Rmin * Rmin) * ((Alphamax - Alphamin) / (2 * TMath::Pi()));
+         // * for energy tree
+         if (ibinx > 0 and ibiny > 0)
+         {
+            m_alphaBinCenter  = hEnergy->GetXaxis()->GetBinCenter(ibinx);
+            m_rBinCenter      = hEnergy->GetYaxis()->GetBinCenter(ibiny);
+            m_Hits            = hHits->GetBinContent(ibinx, ibiny);
+            m_Energy          = hEnergy->GetBinContent(ibinx, ibiny);
+            m_EnergyDensity   = hEnergyDensity->GetBinContent(ibinx, ibiny);
+            m_LnEnergy        = TMath::Log(hEnergy->GetBinContent(ibinx, ibiny));
+            m_LnEnergyDensity = TMath::Log(hEnergyDensity->GetBinContent(ibinx, ibiny));
+
+            if (m_debug)
+            {
+               cout << " i = " << ibinx << " j = " << ibiny << endl;
+               cout << " alpha = " << m_alphaBinCenter << endl;
+               cout << " r = " << m_rBinCenter << endl;
+               cout << " LN energy density = " << m_LnEnergyDensity << endl;
+               cout << "LN energy = " << m_LnEnergy << endl;
+               cout << "====================================" << endl;
+            }
+
+            NNbinCenter->Fill();
+         }
+
+
+         // * for probability tree: uses bin boundary instead of center
+
+         m_alphaBin = xbinsAlpha.at(ibinx);
+         if (ibiny == 0)
+         {
+            m_rBin = TMath::Log(ybinsR.at(1)) - 1;
+         }
+         else
+         {
+            m_rBin = TMath::Log(ybinsR.at(ibiny));
+         }
+
+         // * calculate r prob
+         if (ibiny == 0)
+         {
+            m_rProb = 0;
+         }
+         else if (ibiny > 0)
+         {
+            m_rProb = hEnergyNorm->Integral(1, hEnergyNorm->GetNbinsX(), 1, ibiny);
+         }
+
+         // * calculate alpha prob
+
+         float alpha_tot = 0;
+
+         if (ibinx == 0 and ibiny == 0)
+         {
+            m_alphaProb = 0;
+         }
+         else if (ibiny == 0 and ibinx > 0)
+         {
+            alpha_tot   = hEnergyNorm->Integral(1, hEnergyNorm->GetNbinsX(), 1, 1);
+            m_alphaProb = hEnergyNorm->Integral(1, ibinx, 1, 1) / alpha_tot;
+         }
+         else if (ibinx > 0 and ibiny > 0)
+         {
+            alpha_tot   = hEnergyNorm->Integral(1, hEnergyNorm->GetNbinsX(), ibiny, ibiny);
+            m_alphaProb = hEnergyNorm->Integral(1, ibinx, ibiny, ibiny) / alpha_tot;
+         }
+
+         // * weight: don't understand this? needs to be reviewed!
+
+         if (ibiny == 0)
+         {
+            m_weight = 1. / 15;
+         }
+         else if (ibiny == hEnergyNorm->GetNbinsY())
+         {
+            m_weight = 1.;
+         }
+         else
+         {
+            m_weight = area;
+         }
+
+         NNprob->Fill();
+      }
+   }
+
+   // * write the TTrees and relevant histograms
+
+   NNinputFile->cd();
+   NNbinCenter->Write();
+   NNprob->Write();
+   hHits->Write();
+   hEnergy->Write();
+   hEnergyNorm->Write();
+   hEnergyDensity->Write();
+   hLnEnergy->Write();
+   hLnEnergyDensity->Write();
+   hGradient->Write();
+   hValidation->Write();
+   h_alpha->Write();
+   h_dr->Write();
+   NNinputFile->Close();
+
+   //  std::string inputDistrFile = m_topDir + m_particle + "/InputDistribution_" + m_particle + ".root";
+   //  TFile       *fout          = TFile::Open(inputDistrFile.c_str(), "update");
+   //  TH2F        *hClone        = (TH2F *)hLnEnergyDensity->Clone(Form("hLnEnergyDensity_layer%i_pca%i", m_calolayer, m_PCAbin));
+   //  fout->cd();
+   //  hClone->Write();
+   //  fout->Close();
+}
+
+
+bool ShowerShapeBinning::CheckEmptyBin()
+{
+   bool isEmpty = false;
+
+   for (int ibinx = 0; ibinx < hEnergy->GetNbinsX() + 1; ibinx++)
+   {
+      float Alphamin = hEnergy->GetXaxis()->GetBinLowEdge(ibinx);
+      float Alphamax = hEnergy->GetXaxis()->GetBinUpEdge(ibinx);
+
+      for (int ibiny = 0; ibiny < hEnergy->GetNbinsY() + 1; ibiny++)
+      {
+         float Rmin = hEnergy->GetYaxis()->GetBinLowEdge(ibiny);
+         float Rmax = hEnergy->GetYaxis()->GetBinUpEdge(ibiny);
+
+         float area = TMath::Pi() * (Rmax * Rmax - Rmin * Rmin) * (Alphamax - Alphamin) / (2 * TMath::Pi());
+
+         if (ibinx > 0 and ibiny > 0)
+         {
+            float energy = hEnergy->GetBinContent(ibinx, ibiny);
+            hLnEnergy->SetBinContent(ibinx, ibiny, TMath::Log(energy));
+            hEnergyDensity->SetBinContent(ibinx, ibiny, energy / area);
+            float density = hEnergyDensity->GetBinContent(ibinx, ibiny);
+            hLnEnergyDensity->SetBinContent(ibinx, ibiny, TMath::Log(density));
+            if (m_debug)
+            {
+               cout << " BIN (" << ibinx << "," << ibiny << ") = " << density << endl;
+            }
+            if (density < m_tolerance)
+            {
+               cout << " EMPTY BIN (" << ibinx << "," << ibiny << ") = " << density << endl;
+               isEmpty = true;
+               return isEmpty;
+            }
+         }
+      } // end loop over ybins
+   }    //end loop over xbins
+
+   return isEmpty;
+}
+
+
+bool ShowerShapeBinning::CheckGranularity(TTree *tree)
+{
+   bool isGoodGranularity = false;
+
+   // * get the r granularity for the first 3 bins
+
+   float rgranularity = ybinsR.at(3) - ybinsR.at(0);
+
+
+
+   // * read the variables needed from the TTree
+   tree->GetEntry(0);
+
+   float cell_r    = m_cellr;
+   float cell_z    = m_cellz;
+   float cell_eta  = m_celleta;
+   float cell_deta = m_cellDeta;
+   float cell_dphi = m_cellDphi;
+
+   if (m_debug)
+   {
+      cout << "cell r = " << cell_r << ", cell z = " << cell_z << ", cell eta = " << cell_eta << ", cell deta = " << cell_deta << ", cell dpi = " << cell_dphi << endl;
+   }
+
+
+   // * get the cell dimensions in mm
+   float cell_deta_mm, cell_dphi_mm;
+
+   tie(cell_deta_mm, cell_dphi_mm) = GetUnitsmm(cell_eta, cell_deta, cell_dphi, cell_r, cell_z);
+
+   float minCellGranularity = TMath::Min(cell_deta_mm, cell_dphi_mm);
+
+   // * calculate the max and min alpha bin width, already in mm
+
+   std::vector<float> alphaBinWidth;
+
+   for (unsigned int i = 0; i < xbinsAlpha.size() - 1; i++)
+   {
+      alphaBinWidth.push_back(xbinsAlpha.at(i + 1) - xbinsAlpha.at(i));
+   }
+
+   float alphaMax = *std::max_element(alphaBinWidth.begin(), alphaBinWidth.end());
+   float alphaMin = *std::min_element(alphaBinWidth.begin(), alphaBinWidth.end());
+
+   // * calculate eta/phi max & min from alpha max & min and r
+
+   float etaMax = TMath::Sqrt((rgranularity * rgranularity) / (1 + TMath::Tan(alphaMax) * TMath::Tan(alphaMax)));
+   float etaMin = TMath::Sqrt((rgranularity * rgranularity) / (1 + TMath::Tan(alphaMax) * TMath::Tan(alphaMin)));
+   float phiMax = fabs(etaMax * TMath::Tan(alphaMax));
+   float phiMin = fabs(etaMin * TMath::Tan(alphaMin));
+
+   if (m_debug)
+   {
+      cout << " alphaMin = " << alphaMin << " alphaMax = " << alphaMax << " etaMin = " << etaMin << " etaMax = " << etaMax << " phiMin = " << phiMin << " phiMax = " << phiMax << endl;
+   }
+
+   // * check if the granularity of the parametrization is smaller than cell granularity
+
+   float minParamGranularity = 0;
+
+   if (minCellGranularity == cell_deta_mm)
+   {
+      minParamGranularity = TMath::Max(etaMin, etaMax);
+   }
+   else if (minCellGranularity == cell_dphi_mm)
+   {
+      minParamGranularity = TMath::Max(phiMin, phiMax);
+   }
+
+   if (minCellGranularity >= minParamGranularity)
+   {
+      isGoodGranularity = true;
+      cout << " * Granularity is OK! " << endl;
+   }
+   else
+   {
+      cout << " * Granularity Problem " << endl;
+      cout << " Cell min granularity  = " << minCellGranularity << endl;
+      cout << " Parametrization min granularity = " << minParamGranularity << endl;
+   }
+
+
+   return isGoodGranularity;
+}
+
+
+bool ShowerShapeBinning::CheckGradient()
+{
+   cout << " * Checking gradient of energy density ..." << endl;
+
+   bool isGradientOK = true;
+
+   for (int ibiny = 2; ibiny < hEnergyDensity->GetNbinsY(); ibiny++)
+   {
+      float relvar1     = 0;
+      float relvar2     = 0;
+      float errGradient = 0;
+
+      float Lnrelvar1     = 0;
+      float Lnrelvar2     = 0;
+      float LnerrGradient = 0;
+
+
+      for (int ibinx = 1; ibinx < hEnergyDensity->GetNbinsX() + 1; ibinx++)
+      {
+         relvar1 += (hEnergyDensity->GetBinContent(ibinx, ibiny) - hEnergyDensity->GetBinContent(ibinx, ibiny - 1)) / (hEnergyDensity->GetBinContent(ibinx, ibiny));
+
+         relvar2 += (hEnergyDensity->GetBinContent(ibinx, ibiny + 1) - hEnergyDensity->GetBinContent(ibinx, ibiny)) / (hEnergyDensity->GetBinContent(ibinx, ibiny));
+
+         errGradient += (hEnergyDensity->GetBinError(ibinx, ibiny) - hEnergyDensity->GetBinError(ibinx, ibiny - 1)) / (hEnergyDensity->GetBinError(ibinx, ibiny - 1));
+
+
+         Lnrelvar1     += (TMath::Log(hEnergyDensity->GetBinContent(ibinx, ibiny)) - TMath::Log(hEnergyDensity->GetBinContent(ibinx, ibiny - 1)));
+         Lnrelvar2     += (TMath::Log(hEnergyDensity->GetBinContent(ibinx, ibiny + 1)) - TMath::Log(hEnergyDensity->GetBinContent(ibinx, ibiny)));
+         LnerrGradient += (TMath::Log(hEnergyDensity->GetBinError(ibinx, ibiny)) - TMath::Log(hEnergyDensity->GetBinError(ibinx, ibiny - 1)));
+      }
+      relvar1 = relvar1 / hEnergyDensity->GetNbinsX();
+      relvar2 = relvar2 / hEnergyDensity->GetNbinsX();
+
+      Lnrelvar1 = Lnrelvar1 / hEnergyDensity->GetNbinsX();
+      Lnrelvar2 = Lnrelvar2 / hEnergyDensity->GetNbinsX();
+
+
+      hGradient->Fill(hEnergyDensity->GetYaxis()->GetBinCenter(ibiny), Lnrelvar1);
+      hGradient->SetBinError(ibiny, LnerrGradient);
+
+      float grad_tolerance = 0.;
+
+      if (ibiny < int(hEnergyDensity->GetNbinsY() / 3.))
+      {
+         grad_tolerance = 0.1;
+      }
+      else if (ibiny >= int(hEnergyDensity->GetNbinsY() / 3.) and ibiny < 2 * (int(hEnergyDensity->GetNbinsY() / 3.)))
+      {
+         grad_tolerance = 0.3;
+      }
+      else if (ibiny >= 2 * (int(hEnergyDensity->GetNbinsY() / 3.)))
+      {
+         grad_tolerance = 0.8;
+      }
+
+      if (fabs(Lnrelvar1) > grad_tolerance and fabs(Lnrelvar2) > grad_tolerance)
+      {
+         isGradientOK = false;
+
+         cout << " * Gradient Problem ....." << endl;
+         cout << " (ibiny, Ln(DelRho(E)_j), Ln(DelRho(E)_j+1) ) = (" << ibiny << ", " << Lnrelvar1 << ", " << Lnrelvar2 << " )" << endl;
+         cout << " (ibiny, DelRho(E)_j, DelRho(E)_j+1 ) = (" << ibiny << ", " << relvar1 << ", " << relvar2 << " )" << endl;
+      }
+   }
+
+   return isGradientOK;
+}
+
+
+std::vector<float> ShowerShapeBinning::Getxbins(TH1F *histo, int nbins)
+{
+   // * calculate variable bin width in alpha and dr making sure each bin has almost equal amount of hits.
+
+   bool isAlpha = true;
+
+   std::vector<float> xbins;
+
+
+   std::string title = histo->GetTitle();
+
+   if (title.compare("h_dr") == 0)
+   {
+      isAlpha = false;
+   }
+
+   if (m_debug)
+   {
+      cout << "title = " << title.c_str() << " isAlpha = " << isAlpha << endl;
+   }
+
+   if (isAlpha)
+   {
+      xbins.push_back(TMath::Pi() / 8);
+   }
+   else
+   {
+      xbins.push_back(0);
+   }
+
+
+
+   float AvgHitsPerBin = histo->Integral() / nbins;
+
+
+   float hitCounts = 0;
+
+   for (int ibin = 1; ibin < histo->GetNbinsX() + 1; ibin++)
+   {
+      if (hitCounts < AvgHitsPerBin)
+      {
+         hitCounts = hitCounts + histo->GetBinContent(ibin);
+      }
+      else if (hitCounts >= AvgHitsPerBin)
+      {
+         xbins.push_back(histo->GetBinLowEdge(ibin) + histo->GetBinWidth(ibin));
+         hitCounts = 0;
+      }
+   }
+
+   int   nRmax = histo->FindLastBinAbove(0);
+   float Rmax  = histo->GetBinLowEdge(nRmax) + histo->GetBinWidth(nRmax);
+
+   if (isAlpha)
+   {
+      xbins.push_back(2 * TMath::Pi() + TMath::Pi() / 8);
+   }
+   else
+   {
+      xbins.push_back(Rmax);
+   }
+
+   return xbins;
+}
+
+
+std::tuple<float, float> ShowerShapeBinning::GetUnitsmm(float eta_hit, float d_eta, float d_phi, float cell_r, float cell_z)
+{
+   float phi_dist2r = 1.0;
+   float dist000    = TMath::Sqrt(cell_r * cell_r + cell_z * cell_z);
+
+   float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-eta_hit) / (1.0 + TMath::Exp(-2 * eta_hit)));
+
+   d_eta = d_eta * eta_jakobi * dist000;
+   d_phi = d_phi * cell_r * phi_dist2r;
+
+   if (m_debug)
+   {
+      cout << " in function deta = " << d_eta << " dphi = " << d_phi << endl;
+   }
+   return std::make_tuple(d_eta, d_phi);
+}
+
+
+void ShowerShapeBinning::InitHitsTree(TTree *hitsNtuple, TTree *globalNtuple)
+{
+   m_eventNumber = -1;
+   m_energy      = 0.;
+   m_etaHit      = 0.;
+   m_phiHit      = 0.;
+   m_etaEntrance = 0.;
+   m_phiEntrance = 0.;
+   m_deta        = 0.;
+   m_dphi        = 0.;
+   m_PCA         = 0;
+
+   m_etaCenter = 0.;
+   m_phiCenter = 0.;
+   m_etaShift  = 0.;
+   m_phiShift  = 0.;
+   m_cellr     = 0.;
+   m_cellz     = 0.;
+   m_celleta   = 0.;
+   m_cellDeta  = 0.;
+   m_cellDphi  = 0.;
+
+   hitsNtuple->SetBranchAddress("eventNumber", &m_eventNumber);
+   hitsNtuple->SetBranchAddress("energy_hit", &m_energy);
+   hitsNtuple->SetBranchAddress("eta_hit", &m_etaHit);
+   hitsNtuple->SetBranchAddress("phi_hit", &m_phiHit);
+   hitsNtuple->SetBranchAddress("eta_entrance", &m_etaEntrance);
+   hitsNtuple->SetBranchAddress("phi_entrance", &m_phiEntrance);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("delta_phi", &m_dphi);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("pca_bin", &m_PCA);
+
+   globalNtuple->SetBranchAddress("eta_center", &m_etaCenter);
+   globalNtuple->SetBranchAddress("phi_center", &m_phiCenter);
+   globalNtuple->SetBranchAddress("eta_shift", &m_etaShift);
+   globalNtuple->SetBranchAddress("phi_shift", &m_phiShift);
+   globalNtuple->SetBranchAddress("cell_r", &m_cellr);
+   globalNtuple->SetBranchAddress("cell_z", &m_cellz);
+   globalNtuple->SetBranchAddress("cell_eta", &m_celleta);
+   globalNtuple->SetBranchAddress("cell_deta", &m_cellDeta);
+   globalNtuple->SetBranchAddress("cell_dphi", &m_cellDphi);
+}
+
+
+void ShowerShapeBinning::BookHitsAlphaDrTree(TTree *hitsNtuple)
+{
+   m_eventNumber = -1;
+   m_alpha       = 0.;
+   m_dr          = 0.;
+
+
+   hitsNtuple->Branch("eventNumber", &m_eventNumber);
+   hitsNtuple->Branch("energy", &m_energy);
+   hitsNtuple->Branch("alpha", &m_alpha);
+   hitsNtuple->Branch("dr", &m_dr);
+}
+
+
+void ShowerShapeBinning::InitHitsAlphaDrTree(TTree *hitsNtuple, TTree *globalNtuple)
+{
+   m_eventNumber = -1;
+   m_energy      = 0;
+   m_alpha       = 0.;
+   m_dr          = 0.;
+
+
+   m_etaCenter = 0.;
+   m_phiCenter = 0.;
+   m_etaShift  = 0.;
+   m_phiShift  = 0.;
+   m_cellr     = 0.;
+   m_cellz     = 0.;
+   m_celleta   = 0.;
+   m_cellDeta  = 0.;
+   m_cellDphi  = 0.;
+
+   hitsNtuple->SetBranchAddress("eventNumber", &m_eventNumber);
+   hitsNtuple->SetBranchAddress("energy", &m_energy);
+   hitsNtuple->SetBranchAddress("alpha", &m_alpha);
+   hitsNtuple->SetBranchAddress("dr", &m_dr);
+
+   globalNtuple->SetBranchAddress("eta_center", &m_etaCenter);
+   globalNtuple->SetBranchAddress("phi_center", &m_phiCenter);
+   globalNtuple->SetBranchAddress("eta_shift", &m_etaShift);
+   globalNtuple->SetBranchAddress("phi_shift", &m_phiShift);
+   globalNtuple->SetBranchAddress("cell_r", &m_cellr);
+   globalNtuple->SetBranchAddress("cell_z", &m_cellz);
+   globalNtuple->SetBranchAddress("cell_eta", &m_celleta);
+   globalNtuple->SetBranchAddress("cell_deta", &m_cellDeta);
+   globalNtuple->SetBranchAddress("cell_dphi", &m_cellDphi);
+}
+
+
+void ShowerShapeBinning::BookNNinputTree(TTree *energyNtuple, TTree *probNtuple)
+{
+   m_alphaBinCenter  = 0.;
+   m_rBinCenter      = 0.;
+   m_Hits            = 0.;
+   m_Energy          = 0.;
+   m_EnergyDensity   = 0.;
+   m_LnEnergy        = 0.;
+   m_LnEnergyDensity = 0.;
+
+
+   m_alphaProb = 0.;
+   m_rProb     = 0.;
+   m_alphaBin  = 0.;
+   m_rBin      = 0.;
+   m_weight    = 0.;
+
+   energyNtuple->Branch("alpha", &m_alphaBinCenter);
+   energyNtuple->Branch("r", &m_rBinCenter);
+   energyNtuple->Branch("Hits", &m_Hits);
+   energyNtuple->Branch("Energy", &m_Energy);
+   energyNtuple->Branch("EnergyDensity", &m_EnergyDensity);
+   energyNtuple->Branch("LnEnergy", &m_LnEnergy);
+   energyNtuple->Branch("LnEnergyDensity", &m_LnEnergyDensity);
+
+   probNtuple->Branch("alpha_prob", &m_alphaProb);
+   probNtuple->Branch("r_prob", &m_rProb);
+   probNtuple->Branch("alpha_bin", &m_alphaBin);
+   probNtuple->Branch("r_bin", &m_rBin);
+   probNtuple->Branch("weight", &m_weight);
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..02a6174e7376ee2f0487fd6fee0dd64802e55f61
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeBinning.h
@@ -0,0 +1,153 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ShowerShapeBinning_h
+#define ShowerShapeBinning_h
+
+#include "TChain.h"
+#include "TTree.h"
+#include "TH1.h"
+
+
+class ShowerShapeBinning
+{
+public:
+
+
+   ShowerShapeBinning();
+
+   ~ShowerShapeBinning();
+
+   void CreateHitsAlphaDrNtuple(std::string);
+   void RunBinning();
+   bool CheckEmptyBin();
+   void CreateNNinput();
+   bool CheckGranularity(TTree *);
+   bool CheckGradient();
+
+   std::vector<float> Getxbins(TH1F *histo, int nbins);
+
+   std::tuple<float, float> GetUnitsmm(float eta_hits, float deta, float dphi, float cellr, float cellz);
+
+   void InitHitsTree(TTree *, TTree *);
+
+   void BookHitsAlphaDrTree(TTree *);
+   void InitHitsAlphaDrTree(TTree *, TTree *);
+   void BookNNinputTree(TTree *, TTree *);
+
+
+
+   // * setter methods
+   void set_calolayer(int calolayer_) { m_calolayer = calolayer_; }
+   void set_PCAbin(int PCAbin_) { m_PCAbin = PCAbin_; }
+   void set_nbinsR(int nbinsR_) { m_nbinsR = nbinsR_; }
+   void set_nbinsAlpha(int nbinsAlpha_) { m_nbinsAlpha = nbinsAlpha_; }
+   void set_mincalosize(float mincalosize_) { m_mincalosize = mincalosize_; }
+   void set_particle(string particle_) { m_particle = particle_; }
+   void set_energy(float energy_) { m_particleEnergy = energy_; }
+   void set_eta(float etamin_, float etamax_) { m_etamin = etamin_; m_etamax = etamax_; }
+   void set_tolerance(float tolerance_) { m_tolerance = tolerance_; }
+
+   void set_topDir(string topDir_) { m_topDir = topDir_; }
+   void set_fileName(string fileName_) { m_fileName = fileName_; }
+
+
+private:
+
+   // * settings
+   int m_calolayer;
+   int m_PCAbin;
+   int m_PCA; // ttree variable
+   int m_nbinsR;
+   int m_nbinsAlpha;
+   float m_mincalosize;
+   string m_particle;
+   float m_particleEnergy; // in Gev
+   float m_etamin;
+   float m_etamax;
+   float m_tolerance;
+
+   int m_debug;
+
+
+   std::string m_topDir;
+   std::string m_fileName;
+
+
+   // * for hits TTree
+   int m_eventNumber;
+   float m_energy;
+   float m_etaHit;
+   float m_phiHit;
+   float m_etaEntrance;
+   float m_phiEntrance;
+   float m_deta;
+   float m_dphi;
+
+
+   float m_etaCenter;
+   float m_phiCenter;
+   float m_etaShift;
+   float m_phiShift;
+   float m_cellr;
+   float m_cellz;
+   float m_celleta;
+   float m_cellDeta;
+   float m_cellDphi;
+
+   // * hits TTree with alpha and dr
+
+   float m_alpha;
+   float m_dr;
+
+   // * alpha and dr bin widths
+   std::vector<float> xbinsAlpha;
+   std::vector<float> ybinsR;
+
+
+   // * histograms
+
+   TH2F *halphadrE;
+
+   TH1F *h_alpha;
+   TH1F *h_dr;
+
+
+   TH2F *hHits;
+   TH2F *hEnergyDensity;
+   TH2F *hEnergy;
+
+
+   TH2F *hLnEnergy;
+   TH2F *hLnEnergyDensity;
+
+   TH1F *hGradient;
+
+   TH2F *hValidation;
+
+   // * NNinput TTree variables
+
+   float m_alphaBinCenter;
+   float m_rBinCenter;
+   float m_Hits;
+   float m_Energy;
+   float m_EnergyDensity;
+   float m_LnEnergy;
+   float m_LnEnergyDensity;
+
+   float m_alphaProb;
+   float m_rProb;
+   float m_alphaBin;
+   float m_rBin;
+   float m_weight;
+
+
+   ClassDef(ShowerShapeBinning, 1);
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class ShowerShapeBinning+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..982a32f99599481b53014569659bc5d697067338
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.cxx
@@ -0,0 +1,652 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/****************************************
+* Macro to make pretty plots
+* <a.hasib@cern.ch>
+****************************************/
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+
+
+
+#include "TLine.h"
+#include "TLatex.h"
+#include "TCanvas.h"
+#include "TStyle.h"
+#include "TROOT.h"
+#include "TLatex.h"
+
+
+
+#include "ShowerShapePlotting.h"
+#include "AtlasStyle.h"
+
+using namespace std;
+
+
+ShowerShapePlotting::ShowerShapePlotting()
+{
+   gROOT->SetBatch(kTRUE);
+   gStyle->SetOptStat(0);
+   //gStyle->SetPalette(1);
+
+   m_calolayer      = 0;
+   m_PCAbin         = 0;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+
+   m_topDir        = "";
+   m_fileName      = "";
+   m_outputDirName = "";
+   m_NNinputName   = "";
+   m_NNoutputName  = "";
+}
+
+
+ShowerShapePlotting::~ShowerShapePlotting()
+{
+}
+
+
+void ShowerShapePlotting::PlotEnergyDensityGradient()
+{
+   cout << " * Plotting energy density gradient..." << endl;
+
+   TFile *NNinputFile = TFile::Open(m_NNinputName.c_str());
+
+   TH1F *hist = (TH1F *)NNinputFile->Get("hGradient");
+
+   hist->SetTitle("");
+
+   for (int i = 0; i < hist->GetNbinsX(); i++)
+   {
+      hist->SetBinError(i, 0);
+   }
+
+
+
+   hist->SetMarkerStyle(20);
+   hist->SetMarkerSize(1);
+   hist->GetYaxis()->SetLabelSize(.02);
+   hist->GetXaxis()->SetLabelSize(.02);
+   //hist->GetYaxis()->SetRangeUser(-1,0);
+   hist->SetMaximum(0);
+   hist->GetYaxis()->SetTitle("#it{log}(#rho(E)) variation");
+   hist->GetXaxis()->SetTitle("r [mm]");
+
+
+
+   TCanvas *c0 = new TCanvas("c0", "Gradient", 800, 800);
+   c0->SetLogx();
+   c0->SetRightMargin(0.13);
+
+   hist->Draw("P");
+
+
+   int nzoom1 = int((hist->GetNbinsX()) / 3. * 2.) - 1;
+   int nzoom2 = int((hist->GetNbinsX()) / 3.) - 1;
+
+   std::cout << "ZOOM VALUES : " << nzoom1 << " " << nzoom2 << std::endl;
+
+   float Rzoom2 = hist->GetXaxis()->GetBinLowEdge(nzoom2);
+   float Rzoom1 = hist->GetXaxis()->GetBinLowEdge(nzoom1);
+   float Rzoom0 = hist->GetXaxis()->GetBinLowEdge(hist->GetNbinsX()) + hist->GetXaxis()->GetBinWidth(hist->GetNbinsX());
+
+   TLine *lg1p = new TLine(0, -0.1, Rzoom2, -0.1);
+   lg1p->SetLineWidth(2);
+   lg1p->SetLineColor(kBlue);
+   lg1p->Draw();
+
+   TLine *lg2 = new TLine(Rzoom2, -0.1, Rzoom2, -0.3);
+   lg2->SetLineWidth(2);
+   lg2->SetLineStyle(7);
+   lg2->SetLineColor(kBlue);
+   lg2->Draw();
+
+   TLine *lg2p = new TLine(Rzoom2, -0.3, Rzoom1, -0.3);
+   lg2p->SetLineWidth(2);
+   lg2p->SetLineColor(kBlue);
+   lg2p->Draw();
+
+   TLine *lg3 = new TLine(Rzoom1, -0.3, Rzoom1, -0.8);
+   lg3->SetLineWidth(2);
+   lg3->SetLineStyle(7);
+   lg3->SetLineColor(kBlue);
+   lg3->Draw();
+
+   TLine *lg3p = new TLine(Rzoom1, -0.8, Rzoom0, -0.8);
+   lg3p->SetLineWidth(2);
+   lg3p->SetLineColor(kBlue);
+   lg3p->Draw();
+
+
+   TLatex *l = new TLatex(60, -0.1, "ATLAS");
+   l->SetTextSize(.03);
+   l->SetTextFont(72);
+
+   TLatex *l2 = new TLatex(300, -0.1, "Simulation Preliminary");
+   l2->SetTextSize(.03);
+   l2->SetTextFont(42);
+
+   std::string labeltitle = CreateLabels();
+   TLatex      *l3        = new TLatex(-1, 0.01, labeltitle.c_str());
+   l3->SetTextSize(.02);
+   l3->SetTextFont(42);
+
+   l->Draw();
+   l2->Draw();
+   l3->Draw();
+
+   c0->Update();
+   c0->SaveAs((m_outputDirName + "/EnergyDensityGradient.png").c_str());
+}
+
+
+void ShowerShapePlotting::PlotPolar(std::vector<string> histNameVec, bool isOutput)
+{
+   cout << " * Plotting NNinput polar plots ..." << endl;
+
+   //gStyle->SetPalette(1);
+   SetCustomPalette();
+   std::string labeltitle = CreateLabels();
+
+
+   TFile *NNinputFile  = TFile::Open(m_NNinputName.c_str());
+   TFile *NNoutputFile = TFile::Open(m_NNoutputName.c_str());
+
+
+   for (unsigned int ihist = 0; ihist < histNameVec.size(); ihist++)
+   {
+      TH2F *href = (TH2F *)NNinputFile->Get((histNameVec.at(ihist)).c_str());
+      TH2F *hout;
+
+
+
+      std::string label;
+
+      if ((histNameVec.at(ihist)).compare("hHits") == 0)
+      {
+         label = "Number of hits";
+      }
+      else if ((histNameVec.at(ihist)).compare("hEnergy") == 0)
+      {
+         label = "E [MeV] ";
+      }
+      else if ((histNameVec.at(ihist)).compare("hEnergyDensity") == 0)
+      {
+         label = "#rho(E) [MeV/mm^{2}]";
+      }
+      else if ((histNameVec.at(ihist)).compare("hLnEnergy") == 0)
+      {
+         label = "#it{log}(E) [MeV]";
+      }
+      else if ((histNameVec.at(ihist)).compare("hLnEnergyDensity") == 0)
+      {
+         label = "#it{log}(#rho(E)) [MeV/mm^{2}]";
+      }
+
+
+      // * loop over different zoom
+
+      for (int izoom = 0; izoom < 3; izoom++)
+      {
+         float  zoom      = -1;
+         string labelzoom = "";
+
+         if (izoom == 0)
+         {
+            zoom      = href->GetYaxis()->GetBinLowEdge(href->GetNbinsY()) + href->GetYaxis()->GetBinWidth(href->GetNbinsY());
+            labelzoom = "zoom0";
+         }
+         else if (izoom == 1)
+         {
+            int nzoom = int(2. * (href->GetNbinsY()) / 3.) - 1;
+            zoom      = href->GetYaxis()->GetBinLowEdge(nzoom);
+            labelzoom = "zoom1";
+         }
+         else if (izoom == 2)
+         {
+            int nzoom = int((href->GetNbinsY()) / 3.) - 1;
+            zoom      = href->GetYaxis()->GetBinLowEdge(nzoom);
+            labelzoom = "zoom2";
+         }
+
+
+
+         float myr[3];
+         myr[0] = -zoom;
+         myr[1] = 0;
+         myr[2] = zoom;
+
+         TLatex *l = new TLatex(-1 * zoom, -1.15 * zoom, "ATLAS");
+         l->SetTextSize(.03);
+         l->SetTextFont(72);
+
+         TLatex *l2 = new TLatex(-0.7 * zoom, -1.15 * zoom, "Simulation Preliminary");
+         l2->SetTextSize(.03);
+         l2->SetTextFont(42);
+
+         TLatex *lInputTitle = new TLatex(-zoom, 1.02 * zoom, (labeltitle + ", " + labelzoom + ", NN input").c_str());
+         lInputTitle->SetTextSize(.02);
+         lInputTitle->SetTextFont(42);
+
+
+         TLatex *lOutputTitle = new TLatex(-zoom, 1.02 * zoom, (labeltitle + ", " + labelzoom + ", NN output, neurons =" + std::to_string(m_neurons)).c_str());
+         lOutputTitle->SetTextSize(.02);
+         lOutputTitle->SetTextFont(42);
+
+
+         TLatex *lRatioTitle = new TLatex(-zoom, 1.02 * zoom, (labeltitle + ", " + labelzoom + ", Ratio, neurons =" + std::to_string(m_neurons)).c_str());
+         lRatioTitle->SetTextSize(.02);
+         lRatioTitle->SetTextFont(42);
+
+
+         TH2F *hdummy = new TH2F(("hdummy" + histNameVec.at(ihist) + labelzoom).c_str(), "", 2, myr, 2, myr);
+         hdummy->GetYaxis()->SetRangeUser(-float(zoom), float(zoom));
+         hdummy->GetXaxis()->SetRangeUser(-float(zoom), float(zoom));
+         hdummy->GetYaxis()->SetLabelSize(.02);
+         hdummy->GetXaxis()->SetLabelSize(.02);
+
+         hdummy->GetXaxis()->SetTitle("x [mm]");
+         hdummy->GetYaxis()->SetTitle("y [mm]");
+
+
+         href->SetContour(20);
+         href->GetYaxis()->SetRangeUser(-float(zoom), float(zoom));
+         href->GetZaxis()->SetLabelSize(0.02);
+         href->GetZaxis()->SetTitle(label.c_str());
+         href->GetZaxis()->SetTitleSize(0.03);
+         href->GetZaxis()->SetTitleOffset(1.3);
+         href->Sumw2();
+
+
+         TCanvas *c1 = new TCanvas(("NNinput_" + histNameVec.at(ihist) + labelzoom).c_str(), ("NNinput_" + histNameVec.at(ihist) + labelzoom).c_str(), 800, 800);
+         c1->cd();
+         c1->SetRightMargin(0.14);
+         hdummy->Draw("COLZ");
+         href->Draw("COLZ POL SAME");
+
+         l->Draw();
+         l2->Draw();
+         lInputTitle->Draw();
+
+         c1->SaveAs((m_outputDirName + "NNinput_" + histNameVec.at(ihist) + "_" + labelzoom + ".png").c_str());
+         c1->Close();
+
+         if (isOutput)
+         {
+            hout = (TH2F *)NNoutputFile->Get((histNameVec.at(ihist)).c_str());
+            //hout->Scale(1 / hout->Integral());
+            hout->SetContour(20);
+            hout->GetYaxis()->SetRangeUser(-float(zoom), float(zoom));
+            //hout->GetZaxis()->SetRangeUser(0, .012);
+            hout->GetZaxis()->SetLabelSize(0.02);
+            hout->GetZaxis()->SetTitle(label.c_str());
+            hout->GetZaxis()->SetTitleSize(0.03);
+            hout->GetZaxis()->SetTitleOffset(1.3);
+            hout->Sumw2();
+
+
+
+            TCanvas *c2 = new TCanvas(("NNoutput_" + histNameVec.at(ihist) + labelzoom).c_str(), ("NNoutput_" + histNameVec.at(ihist) + labelzoom).c_str(), 800, 800);
+            c2->cd();
+            c2->SetRightMargin(0.14);
+            hdummy->Draw("COLZ");
+            hout->Draw("COLZ POL SAME");
+
+            l->Draw();
+            l2->Draw();
+            lOutputTitle->Draw();
+
+            c2->SaveAs((m_outputDirName + "NNoutput_" + histNameVec.at(ihist) + "_" + labelzoom + ".png").c_str());
+            c2->Close();
+
+            // * ratio
+            TH2F *hratio = (TH2F *)href->Clone(("hratio_" + histNameVec.at(ihist) + labelzoom).c_str());
+            hratio->Divide(hout);
+            hratio->GetZaxis()->SetTitle("");
+            hratio->GetZaxis()->SetRangeUser(0, +1.5);
+
+            TCanvas *c3 = new TCanvas(("Ratio_" + histNameVec.at(ihist) + labelzoom).c_str(), ("Ratio_" + histNameVec.at(ihist) + labelzoom).c_str(), 800, 800);
+            c3->cd();
+            c3->SetRightMargin(0.14);
+            hdummy->Draw("COLZ");
+            hratio->Draw("COLZ POL SAME");
+
+            l->Draw();
+            l2->Draw();
+            lRatioTitle->Draw();
+
+            c3->SaveAs((m_outputDirName + "Ratio_" + histNameVec.at(ihist) + "_" + labelzoom + ".png").c_str());
+            c3->Close();
+         }
+      }
+   }
+}
+
+
+void ShowerShapePlotting::CreateValidationPlot()
+{
+   SetCustomPalette();
+
+
+
+   TFile *NNinputFile = TFile::Open(m_NNinputName.c_str());
+
+   TH2F *hist = (TH2F *)NNinputFile->Get("hValidation");
+   hist->SetTitle("");
+
+
+   TCanvas *c1 = new TCanvas("c1", "c1", 800, 800);
+
+   c1->SetRightMargin(0.13);
+   c1->cd();
+   hist->Draw("COLZ");
+
+   TLatex *l = new TLatex();
+   l->SetTextSize(.02);
+   l->DrawLatex(-1, -1, "1 = all OK, 2 = bad gradient, 3 = bad granularity, 4 = bad gradient and granularity");
+
+   std::string labeltitle = CreateLabels();
+
+   TLatex *l2 = new TLatex(0, 14.6, labeltitle.c_str());
+   l2->SetTextSize(.02);
+   l2->Draw();
+
+   c1->SaveAs((m_outputDirName + "ValidationPlot.png").c_str());
+   c1->Close();
+}
+
+
+std::string ShowerShapePlotting::CreateLabels()
+{
+   std::string energy;
+
+   stringstream energyvalue;
+   energyvalue << fixed << setprecision(0) << m_particleEnergy;
+   energy = energyvalue.str() + " GeV";
+
+   std::string eta;
+
+   stringstream etamin, etamax;
+
+   etamin << fixed << setprecision(2) << m_etamin;
+   etamax << fixed << setprecision(2) << m_etamax;
+
+   eta = etamin.str() + " < |#eta| < " + etamax.str();
+
+
+   std::string particle;
+
+   if (m_particle.compare("el_1mm") == 0)
+   {
+      particle = "e^{#pm} (1mm)";
+   }
+   else if (m_particle.compare("el_opt") == 0)
+   {
+      particle = "e^{#pm} (opt)";
+   }
+   else if (m_particle.compare("pion") == 0)
+   {
+      particle = "#pi^{#pm}";
+   }
+   else if (m_particle.compare("photon") == 0)
+   {
+      particle = "#gamma^0";
+   }
+
+   std::string calolayer;
+
+   if (4 > m_calolayer > 0)
+   {
+      calolayer = "EMB" + std::to_string(m_calolayer);
+   }
+   else if (m_calolayer == 0)
+   {
+      calolayer = "PreSamplerB";
+   }
+   else if (m_calolayer == 12)
+   {
+      calolayer = "TileBar0";
+   }
+   else if (m_calolayer == 13)
+   {
+      calolayer = "TileBar1";
+   }
+   else if (m_calolayer == 14)
+   {
+      calolayer = "TileBar2";
+   }
+
+   std::string binpca;
+
+   binpca = "bin(PCA) = " + std::to_string(m_PCAbin);
+
+   TFile *NNinputFile  = TFile::Open(m_NNinputName.c_str());
+   TH2F *h = (TH2F*)NNinputFile->Get("hLnEnergyDensity");
+   int final_nbinsR = h->GetNbinsY();
+   int final_nbinsAlpha = h->GetNbinsX();
+
+   std::string bin;
+
+   bin = "#alpha nbins = " + std::to_string(final_nbinsAlpha) + ", r nbins = " + std::to_string(final_nbinsR);
+
+   std::string label = energy + " " + particle + ", " + eta + ", " + calolayer + ", " + binpca + ", " + bin;
+
+   return label;
+}
+
+
+void ShowerShapePlotting::SetCustomPalette()
+{
+   /*
+    * const Int_t NRGBs = 6;
+    * const Int_t NCont = 50;
+    *
+    * Double_t stops[NRGBs] = { 0.00, 0.1, 0.34, 0.61, 0.84, 1.00 };
+    * Double_t red[NRGBs]   = { 0.99, 0.0, 0.00, 0.87, 1.00, 0.51 };
+    * Double_t green[NRGBs] = { 0.00, 0.0, 0.81, 1.00, 0.20, 0.00 };
+    * Double_t blue[NRGBs]  = { 0.99, 0.0, 1.00, 0.12, 0.00, 0.00 };
+    *
+    *
+    * TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
+    * gStyle->SetNumberContours(NCont);
+    *
+    *
+    */
+
+   Double_t stops[5] = { 0.00, 0.24, 0.61, 0.84, 1.00 };
+   Double_t red[5]   = { 0.00, 0.00, 0.87, 1.00, 0.51 };
+   Double_t green[5] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
+   Double_t blue[5]  = { 0.51, 1.00, 0.12, 0.00, 0.00 };
+
+   UInt_t npoints   = 5;
+   Int_t  ncontours = 20;
+
+   TColor::CreateGradientColorTable(npoints, stops, red, green, blue, ncontours);
+   gStyle->SetNumberContours(ncontours);
+}
+
+
+void ShowerShapePlotting::CreateHTML(std::vector<string> histNameVec)
+{
+   cout << " * Creating HTML with plots ... " << endl;
+
+   //  std::string file = m_outputDirName + "../" + m_particle + "_" + std::to_string(m_particleEnergy) + "_eta_" + std::to_string(m_etamin) + "_" + std::to_string(m_etamax) + "_nbinsR" + std::to_string(m_nbinsR) + "_neuron" + std::to_string(m_neurons) + ".html";
+
+   std::string file = m_outputDirName + "../" + m_particle + "_" + std::to_string(m_particleEnergy) + "_eta_" + std::to_string(m_etamin) + "_" + std::to_string(m_etamax) + "_nbinsR" + std::to_string(m_nbinsR) + "_layer" + std::to_string(m_calolayer) + "_pca" + std::to_string(m_PCAbin) + ".html";
+
+   std::string labeltitle = CreateLabels();
+
+   //  std::string outdir = "plots_nbinsR" + std::to_string(m_nbinsR) + "_neuron" + std::to_string(m_neurons) + "/";
+
+   std::string outdir = "plots_layer" + std::to_string(m_calolayer) + "_pca" + std::to_string(m_PCAbin) + "/";
+
+   ofstream myhtml;
+   myhtml.open(file.c_str(), std::ios_base::trunc);
+
+   if (myhtml.is_open())
+   {
+      myhtml << "<p align=\"center\" class=\"style3\"> Plots for : " << labeltitle.c_str() << "</p>\n";
+      myhtml << "<table align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\"><tr>\n";
+
+      myhtml << "<td align=\"center\" class=\"style2\">  </td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\">Validation</td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\">Gradient</td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\"> </td>\n";
+      myhtml << "</tr><tr>\n";
+      myhtml << "<td align=\"left\" class=\"style2\" ><br> " << "input" << " </td>\n";
+      myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << "ValidationPlot.png" << "\"><img src=\"" << outdir.c_str() << "/" << "ValidationPlot.png" << "\" width=\"450\" height=\"450\"  ></a><br> (input)</td>\n";
+      myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << "EnergyDensityGradient.png" << "\"><img src=\"" << outdir.c_str() << "/" << "EnergyDensityGradient.png" << "\" width=\"450\" height=\"450\"  ></a><br> (output)</td>\n";
+      myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << "" << "\"><img src=\"" << outdir.c_str() << "/" << "" << "\" width=\"450\" height=\"450\"  ></a><br> (output)</td>\n";
+      myhtml << "</tr><tr>\n";
+
+      myhtml << "<td align=\"center\" class=\"style2\">Variable</td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\">NN input</td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\">NN ouput</td>\n";
+      myhtml << "<td align=\"center\" class=\"style2\">Ratio (input/ouput) </td>\n";
+      myhtml << "</tr><tr>\n";
+
+
+
+      for (unsigned int ihist = 0; ihist < histNameVec.size(); ihist++)
+      {
+         for (int izoom = 0; izoom < 3; izoom++)
+         {
+            std::string NNinputFig  = "NNinput_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+            std::string NNoutputFig = "NNoutput_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+            std::string NNratioFig  = "Ratio_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+
+            myhtml << "<td align=\"left\" class=\"style2\" ><br> " << (histNameVec.at(ihist) + "_zoom" + std::to_string(izoom)).c_str() << " </td>\n";
+            myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << NNinputFig << "\"><img src=\"" << outdir.c_str() << "/" << NNinputFig << "\" width=\"450\" height=\"450\"  ></a><br> (input)</td>\n";
+            myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << NNoutputFig << "\"><img src=\"" << outdir.c_str() << "/" << NNoutputFig << "\" width=\"450\" height=\"450\"  ></a><br> (output)</td>\n";
+            myhtml << "<td align=\"center\" class=\"style1\" ><a  href=\"" << outdir.c_str() << "/" << NNratioFig << "\"><img src=\"" << outdir.c_str() << "/" << NNratioFig << "\" width=\"450\" height=\"450\"  ></a><br> (output)</td>\n";
+
+            myhtml << "</tr><tr>\n";
+         }
+      }
+      myhtml << "</body>\n";
+      myhtml << "</html>\n";
+      myhtml.close();
+   }
+   else
+   {
+      std::cout << "Error opening html file";
+   }
+}
+
+
+void ShowerShapePlotting::CreatePlotBook(std::vector<string> histNameVec)
+{
+   cout << " * Creating  plot book ... " << endl;
+
+   //  std::string file = m_outputDirName + "../plot_books/" + m_particle + "_" + std::to_string(m_particleEnergy) + "_eta_" + std::to_string(m_etamin) + "_" + std::to_string(m_etamax) + "_nbinsR" + std::to_string(m_nbinsR) + "_layer" + std::to_string(m_calolayer) + "_pca" + std::to_string(m_PCAbin) + ".tex";
+
+   std::string file = m_outputDirName + "../plot_books/" + m_particle + "_" + std::to_string(m_particleEnergy) + "_eta_" + std::to_string(m_etamin) + "_" + std::to_string(m_etamax) + /*"_nbinsR" + std::to_string(m_nbinsR) +*/ ".tex";
+
+   std::string labeltitle = CreateLabels();
+
+
+   // std::string outdir = "../plots_nbinsR" + std::to_string(m_nbinsR) + "_layer" + std::to_string(m_calolayer) + "_pca" + std::to_string(m_PCAbin) + "/";
+
+   std::string outdir = "../plots_layer" + std::to_string(m_calolayer) + "_pca" + std::to_string(m_PCAbin) + "/";
+
+
+   ofstream mylatex;
+   mylatex.open(file.c_str());
+
+   if (mylatex.is_open())
+   {
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\documentclass[english,professionalfonts]{beamer}" << endl;
+      mylatex << "\\usefonttheme{serif}" << endl;
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\usepackage{beamerthemesplit}" << endl;
+      mylatex << "\\usepackage{multicol}" << endl;
+      mylatex << "\\usepackage{amsmath}" << endl;
+      mylatex << "\\usepackage{amssymb}" << endl;
+      mylatex << "\\usepackage{array}" << endl;
+      mylatex << "\\usepackage{graphicx}" << endl;
+      mylatex << "\\usepackage{multimedia}" << endl;
+      mylatex << "\\usepackage{hyperref}" << endl;
+      mylatex << "\\usepackage{url}" << endl;
+      mylatex << "%% Define a new 'leo' style for the package that will use a smaller font." << endl;
+      mylatex << "\\makeatletter" << endl;
+      mylatex << "\\def\\url@leostyle{\\@ifundefined{selectfont}{\\def\\UrlFont{\\sf}}{\\def\\UrlFont{\\small\\ttfamily}}}" << endl;
+      mylatex << "\\makeatother" << endl;
+      mylatex << "%% Now actually use the newly defined style." << endl;
+      mylatex << "\\urlstyle{leo}" << endl;
+      mylatex << "\\usepackage{cancel}" << endl;
+      mylatex << "\\usepackage{color}" << endl;
+      mylatex << "\\usepackage{verbatim}" << endl;
+      mylatex << "\\usepackage{epsfig}" << endl;
+      mylatex << "\\usepackage{fancybox}" << endl;
+      mylatex << "\\usepackage{xcolor}" << endl;
+      mylatex << "%\\usepackage{fontspec}" << endl;
+      mylatex << "%\\usepackage{booktabs,caption}" << endl;
+      mylatex << "%\\usepackage{eulervm}" << endl;
+      mylatex << "\\usepackage{textpos}" << endl;
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\usetheme{Warsaw}" << endl;
+      mylatex << "\\usecolortheme{default}" << endl;
+      mylatex << "%\\setbeamercovered{transparent}" << endl;
+      mylatex << "\\beamertemplatenavigationsymbolsempty" << endl;
+      mylatex << "%\\setbeamertemplate" << endl;
+      mylatex << "\\setbeamertemplate{footline}[page number]" << endl;
+      mylatex << "%%\\setsansfont{Fontin Sans}" << endl;
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\definecolor{jgreen}{cmyk}{0.99,0,0.52,0}" << endl;
+      mylatex << "\\definecolor{green}{rgb}{0.,.6,0.}" << endl;
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\title{Shower shape parametrization : Plotbook}" << endl;
+      mylatex << "\\author{ Hasib Ahmed}" << endl;
+      mylatex << "\\institute{ University of Edinburgh}" << endl;
+      mylatex << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
+      mylatex << "\\begin{document}" << endl;
+
+
+      mylatex << "\\begin{frame}" << endl;
+      mylatex << "\\frametitle{Parameters}" << endl;
+      mylatex << "\\begin{center}" << endl;
+      mylatex << "\\begin{itemize}" << endl;
+      // mylatex << "\\item Particle = " + m_particle << endl;
+      mylatex << "\\item Energy = " + std::to_string(m_particleEnergy) + "GeV" << endl;
+      mylatex << "\\item " + std::to_string(m_etamin) + "$< |\\eta| <$" + std::to_string(m_etamax) << endl;
+      mylatex << "\\item Calorimeter layer = " + std::to_string(m_calolayer) << endl;
+      mylatex << "\\item PCA bin = " + std::to_string(m_PCAbin) << endl;
+      mylatex << "\\end{itemize}" << endl;
+      mylatex << "\\end{center}" << endl;
+      mylatex << "\\end{frame}" << endl;
+
+
+      for (unsigned int ihist = 0; ihist < histNameVec.size(); ihist++)
+      {
+         for (int izoom = 0; izoom < 3; izoom++)
+         {
+            std::string NNinputFig  = "NNinput_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+            std::string NNoutputFig = "NNoutput_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+            std::string NNratioFig  = "Ratio_" + histNameVec.at(ihist) + "_" + "zoom" + std::to_string(izoom) + ".png";
+
+            mylatex << "\\begin{frame}" << endl;
+            mylatex << "\\frametitle{Input distro: " + histNameVec.at(ihist) + "Zoom " + std::to_string(izoom) + "}" << endl;
+            mylatex << "\\begin{center}" << endl;
+            mylatex << "\\includegraphics[width=8cm]{" + outdir + "/" + NNinputFig + "}" << endl;
+            mylatex << "\\end{center}" << endl;
+            mylatex << "\\end{frame}" << endl;
+         }
+      }
+      mylatex << "\\end{document}" << endl;
+      mylatex.close();
+   }
+   else
+   {
+      cout << " ERROR::The python file cannot be opened!" << endl;
+   }
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.h
new file mode 100644
index 0000000000000000000000000000000000000000..0546bebfa5f4a5b0583d86115f5a25d4c34f6049
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapePlotting.h
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ShowerShapePlotting_h
+#define ShowerShapePlotting_h
+
+#include "TH1.h"
+#include "TH2.h"
+#include "TFile.h"
+
+class ShowerShapePlotting
+{
+public:
+
+   ShowerShapePlotting();
+
+   ~ShowerShapePlotting();
+
+
+   void PlotEnergyDensityGradient();
+   void PlotPolar(std::vector<string>, bool);
+   void CreateValidationPlot();
+
+
+   std::string CreateLabels();
+   void SetCustomPalette();
+   void CreateHTML(std::vector<string> );
+   void CreatePlotBook(std::vector<string> );
+
+   void set_calolayer(int calolayer_) { m_calolayer = calolayer_; }
+   void set_PCAbin(int PCAbin_) { m_PCAbin = PCAbin_; }
+   void set_nbinsR(int nbinsR_) { m_nbinsR = nbinsR_; }
+   void set_particle(string particle_) { m_particle = particle_; }
+   void set_energy(float energy_) { m_particleEnergy = energy_; }
+   void set_eta(float etamin_, float etamax_) { m_etamin = etamin_; m_etamax = etamax_; }
+
+
+   void set_topDir(string topDir_) { m_topDir = topDir_; }
+   void set_fileName(string fileName_) { m_fileName = fileName_; }
+   void set_outputDirName(string outputDirName_) { m_outputDirName = outputDirName_; }
+   void set_NNinputName(string NNinputName_) { m_NNinputName = NNinputName_; }
+   void set_NNoutputName(string NNoutputName_) { m_NNoutputName = NNoutputName_; }
+
+   void set_neurons(int neurons_) { m_neurons = neurons_; }
+
+
+
+private:
+
+   TFile *m_file;
+
+   int m_calolayer;
+   int m_PCAbin;
+   int m_nbinsR;
+   string m_particle;
+   float m_particleEnergy; // in Gev
+   float m_etamin;
+   float m_etamax;
+
+   int m_neurons;
+   string m_topDir;
+   string m_fileName;
+   string m_outputDirName;
+   string m_NNinputName;
+   string m_NNoutputName;
+
+   ClassDef(ShowerShapePlotting, 1);
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class ShowerShapePlotting+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2a4cf7aa9327216ecc437f280329df9edbd2f98a
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.cxx
@@ -0,0 +1,412 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*****************************************************
+ * Class to implement NN regression in input variables
+ * <a.hasib@cern.ch>
+ ****************************************************/
+
+#include "ShowerShapeRegression.h"
+
+
+#include "TH2.h"
+#include "TString.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TObjString.h"
+#include "TSystem.h"
+#include "TROOT.h"
+#include "TRandom.h"
+#include "TRandom1.h"
+#include "TRandom3.h"
+#include "TMath.h"
+
+#include "TMVA/Tools.h"
+#include "TMVA/Factory.h"
+#include "TMVA/DataLoader.h"
+#include "TMVA/Reader.h"
+#include "TMVA/Config.h"
+
+
+#include <iostream>
+
+
+
+using namespace std;
+using namespace TMVA;
+
+ShowerShapeRegression::ShowerShapeRegression()
+{
+   m_calolayer      = 0;
+   m_PCAbin         = 0;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+
+   m_topDir        = "";
+   m_fileName      = "";
+   m_outputDirName = "";
+   m_NNinputName   = "";
+   m_NNoutputName  = "";
+
+   m_neurons      = 0;
+   m_hiddenLayers = 0;
+}
+
+
+ShowerShapeRegression::~ShowerShapeRegression()
+{
+}
+
+
+void ShowerShapeRegression::Run(std::vector<string> targetVarVec)
+{
+   TFile *NNinputFile  = TFile::Open(m_NNinputName.c_str());
+   TFile *NNoutputFile = TFile::Open(m_NNoutputName.c_str(), "recreate");
+
+   TRandom1 *myRandom = new TRandom1();
+   myRandom->SetSeed(0);
+
+   TRandom1 *myRandom2 = new TRandom1();
+   myRandom2->SetSeed(1000);
+
+   TH2F *hinput = (TH2F*)NNinputFile->Get("hEnergyNorm");
+
+   int Ntoys = 5000; //hinput->GetEntries();
+
+
+   for (unsigned int itarget = 0; itarget < targetVarVec.size(); itarget++)
+   {
+      string histoName = "h" + targetVarVec.at(itarget);
+
+      TH2F *hin = (TH2F *)NNinputFile->Get(histoName.c_str());
+
+
+      cout << " ======> Run regrression training with target variable = " << (targetVarVec.at(itarget)).c_str() << " <======" << endl;
+
+      TMVARegressionTraining(targetVarVec.at(itarget));
+
+      //* Define a histogram with alpha and Ln(r) boundaries
+
+      int nalpha = hin->GetNbinsX() + 1;
+      int nr = hin->GetNbinsY() + 1;
+
+      // * get the bin boundaries
+
+      float xbinsalpha[nalpha];
+      float xbinsLnr[nr];
+
+      for (int ibin = 1; ibin < nalpha; ++ibin)
+      {
+         xbinsalpha[ibin - 1] = hin->GetXaxis()->GetBinLowEdge(ibin);
+
+         if (ibin == nalpha - 1 )
+            xbinsalpha[ibin] = hin->GetXaxis()->GetBinUpEdge(ibin);
+      }
+
+      for (int ibin = 0; ibin < nr; ibin++)
+      {
+         xbinsLnr[ibin - 1] = TMath::Log(hin->GetYaxis()->GetBinLowEdge(ibin));
+
+         if (ibin == nr - 1)
+            xbinsLnr[ibin] = TMath::Log(hin->GetXaxis()->GetBinUpEdge(ibin));
+      }
+
+      TH2F* houtLn = new TH2F("houtLn", "houtLn", nalpha - 1, xbinsalpha, nr - 1, xbinsLnr);
+      TH2F *hout = (TH2F *)hin->Clone(histoName.c_str());
+      hout->Reset();
+
+      //* Use random numbers for tmva application
+
+      for (int it = 0; it < Ntoys; ++it)
+      {
+         double random = myRandom->Uniform(0, 1);
+         double random2 = myRandom2->Uniform(0, 1);
+
+         std::vector<float> value = TMVARegressionApplication(random, random2, targetVarVec.at(itarget));
+
+         houtLn->Fill(value.at(0), value.at(1));
+         hout->Fill(value.at(0), TMath::Exp(value.at(1)));
+
+      }
+
+
+      // // * change Ln(r) to r
+
+      // TH2F *hout = (TH2F *)hin->Clone(histoName.c_str());
+      // hout->Reset();
+
+
+      // for (int ibinx = 1; ibinx < houtLn->GetNbinsX() + 1; ibinx++)
+      // {
+      //    for (int ibiny = 1; ibiny < houtLn->GetNbinsY() + 1; ibiny++)
+      //    {
+      //       hout->SetBinContent(ibinx, ibiny, houtLn->GetBinContent(ibinx, ibiny));
+      //       hout->SetBinError(ibinx, ibiny, houtLn->GetBinError(ibinx, ibiny));
+      //    }
+      // }
+      //
+
+      hout->Scale(1 / (hout->Integral()));
+      houtLn->Scale(1 / (houtLn->Integral()));
+      NNoutputFile->cd();
+      hout->Write();
+      houtLn->Write();
+   }
+
+   NNoutputFile->Close();
+}
+
+
+void ShowerShapeRegression::TMVARegressionTraining(std::string target)
+{
+   // * Read training and tets data
+   //cout<<" NNinput file = "<<m_NNinputName.c_str()<<endl;
+   TFile *NNinputFile = TFile::Open(m_NNinputName.c_str());
+
+   if (!NNinputFile)
+   {
+      cout << "ERROR:: inputFile cannot be opened" << endl;
+      exit(EXIT_FAILURE);
+   }
+
+   TTree *regTree = (TTree *)NNinputFile->Get("NNprob"); //will change
+
+   TString myMethodList = "";
+
+   // * load the TMVA libaray
+   TMVA::Tools::Instance();
+
+   // * Default MVA methods to be trained + tested
+   std::map<std::string, int> Use;
+
+   // Mutidimensional likelihood and Nearest-Neighbour methods
+   Use["PDERS"]   = 0;
+   Use["PDEFoam"] = 0;
+   Use["KNN"]     = 0;
+   //
+   // Linear Discriminant Analysis
+   Use["LD"] = 0;
+   //
+   // Function Discriminant analysis
+   Use["FDA_GA"]   = 0;
+   Use["FDA_MC"]   = 0;
+   Use["FDA_MT"]   = 0;
+   Use["FDA_GAMT"] = 0;
+   //
+   // Neural Network
+   Use["MLP"] = 1;
+   Use["DNN"] = 0;
+   //
+   // Support Vector Machine
+   Use["SVM"] = 0;
+   //
+   // Boosted Decision Trees
+   Use["BDT"]  = 0;
+   Use["BDTG"] = 0;
+
+
+
+   std::cout << std::endl;
+   std::cout << "==> Start TMVARegression" << std::endl;
+
+   // * Select methods
+   if (myMethodList != "")
+   {
+      for (std::map<std::string, int>::iterator it = Use.begin(); it != Use.end(); it++)
+      {
+         it->second = 0;
+      }
+      std::vector<TString> mlist = gTools().SplitString(myMethodList, ',');
+      for (UInt_t i = 0; i < mlist.size(); i++)
+      {
+         std::string regMethod(mlist[i]);
+         if (Use.find(regMethod) == Use.end())
+         {
+            std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
+            for (std::map<std::string, int>::iterator it = Use.begin(); it != Use.end(); it++)
+            {
+               std::cout << it->first << " ";
+            }
+            std::cout << std::endl;
+            return;
+         }
+         Use[regMethod] = 1;
+      }
+   }
+
+
+   // * create ouput regression file
+   string regRootFileName = m_topDir + m_particle + "/" + "NNreg_" + target + "_neuron" + std::to_string(m_neurons) + "_nbinsR" + std::to_string(m_nbinsR) + m_fileName + ".root";
+
+   string RegWeightDir = "RegWeight_" + target + "_neuron" + std::to_string(m_neurons) + "_nbinsR" + std::to_string(m_nbinsR) + m_fileName;
+
+
+
+   TFile *NNregFile = TFile::Open(regRootFileName.c_str(), "recreate");
+
+   // * create factory object
+
+   TMVA::Factory *factory = new TMVA::Factory("TMVARegression", NNregFile, "V:!Silent:Color:DrawProgressBar:AnalysisType=Regression");
+
+   // * create dataloader to read the input variables
+
+   TMVA::DataLoader *dataloader = new TMVA::DataLoader(RegWeightDir);
+   cout << " reg weight dir = " << RegWeightDir.c_str() << endl;
+
+
+   // define input variables that shall be used for training
+
+   dataloader->AddVariable("alpha_prob", "AlphaProb", 'F');
+   dataloader->AddVariable("r_prob", "rProb", 'F');
+
+
+   dataloader->AddTarget("alpha_bin", "alpha", 'F');
+   dataloader->AddTarget("r_bin", "r", 'F');
+
+   //dataloader->AddRegressionTree(regTree, 1.0);
+   dataloader->AddSignalTree(regTree, 1.0, "Train Tree");
+   dataloader->AddSignalTree(regTree, 1.0, "Test Tree");
+
+   //TCut mycut = "";
+
+   // * Neural network (MLP)
+   if (Use["MLP"])
+   {
+      factory->BookMethod(dataloader, TMVA::Types::kMLP, "MLP", Form("!H:!V:VarTransform=Norm:NeuronType=tanh:NCycles=20000:HiddenLayers=%i,%i,%i,%i:TestRate=6:TrainingMethod=BFGS:Sampling=0.3:SamplingEpoch=0.8:ConvergenceImprove=1e-6:ConvergenceTests=20:!UseRegulator", m_neurons, m_neurons, m_neurons, m_neurons));
+   }
+
+
+   // * Train MVAs using the set of training events
+   factory->TrainAllMethods();
+   // * Evaluate all MVAs using the set of test events
+   factory->TestAllMethods();
+   // * Evaluate and compare performance of all configured MVAs
+   factory->EvaluateAllMethods();
+
+   // * Save the output
+   NNregFile->Close();
+   std::cout << "==> Wrote root file: " << NNregFile->GetName() << std::endl;
+   std::cout << "==> TMVARegression is done!" << std::endl;
+
+   if (factory)
+   {
+      delete factory;
+   }
+   if (dataloader)
+   {
+      delete dataloader;
+   }
+}
+
+
+std::vector<float> ShowerShapeRegression::TMVARegressionApplication(float xval, float yval, string target)
+{
+   std::vector<float> value;
+
+   TString myMethodList = "";
+
+   // This loads the library
+   TMVA::Tools::Instance();
+
+   // Default MVA methods to be trained + tested
+   std::map<std::string, int> Use;
+
+
+   // --- Mutidimensional likelihood and Nearest-Neighbour methods
+   Use["PDERS"]   = 0;
+   Use["PDEFoam"] = 0;
+   Use["KNN"]     = 0;
+   //
+   // --- Linear Discriminant Analysis
+   Use["LD"] = 0;
+   //
+   // --- Function Discriminant analysis
+   Use["FDA_GA"]   = 0;
+   Use["FDA_MC"]   = 0;
+   Use["FDA_MT"]   = 0;
+   Use["FDA_GAMT"] = 0;
+   //
+   // --- Neural Network
+   Use["MLP"] = 1;
+   //
+   // --- Support Vector Machine
+   Use["SVM"] = 0;
+   //
+   // --- Boosted Decision Trees
+   Use["BDT"]  = 0;
+   Use["BDTG"] = 0;
+
+
+
+   // Select methods
+   if (myMethodList != "")
+   {
+      for (std::map<std::string, int>::iterator it = Use.begin(); it != Use.end(); it++)
+      {
+         it->second = 0;
+      }
+      std::vector<TString> mlist = gTools().SplitString(myMethodList, ',');
+      for (UInt_t i = 0; i < mlist.size(); i++)
+      {
+         std::string regMethod(mlist[i]);
+         if (Use.find(regMethod) == Use.end())
+         {
+            std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
+            for (std::map<std::string, int>::iterator it = Use.begin(); it != Use.end(); it++)
+            {
+               std::cout << it->first << " ";
+            }
+            std::cout << std::endl;
+            exit(EXIT_FAILURE);
+         }
+         Use[regMethod] = 1;
+      }
+   }
+
+
+   TMVA::Reader *reader = new TMVA::Reader("!Color:!Silent");
+
+   // Create a set of variables and declare them to the reader
+
+   float alpha = xval;
+   float r     = yval;
+
+   reader->AddVariable("alpha_prob", &alpha);
+   reader->AddVariable("r_prob", &r);
+
+
+   // --- Book the MVA methods
+   // string RegDir = m_topDir+m_particle+"/RegWeight/"+target+"_nbinsR"+std::to_string(m_nbinsR)+m_fileName;
+
+   TString dir    = "RegWeight_" + target + "_neuron" + std::to_string(m_neurons) + "_nbinsR" + std::to_string(m_nbinsR) + m_fileName + "/weights/";
+   TString prefix = "TMVARegression";
+
+   // Book method(s)
+   for (std::map<std::string, int>::iterator it = Use.begin(); it != Use.end(); it++)
+   {
+      if (it->second)
+      {
+         TString methodName = it->first + " method";
+         TString weightfile = dir + prefix + "_" + TString(it->first) + ".weights.xml";
+         reader->BookMVA(methodName, weightfile);
+      }
+   }
+
+   float val = (reader->EvaluateRegression("MLP method"))[0];
+   float val2 = (reader->EvaluateRegression("MLP method"))[1];
+
+   value.push_back(val);
+   value.push_back(val2);
+
+
+   if (reader)
+   {
+      delete reader;
+   }
+
+
+   return value;
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2f2b212e23ecb8c77dc332c05c3be6ba5854f6f
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeRegression.h
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ShowerShapeRegression_h
+#define ShowerShapeRegression_h
+
+class ShowerShapeRegression
+{
+public:
+
+   ShowerShapeRegression();
+   ~ShowerShapeRegression();
+
+   void Run(std::vector<string> );
+
+   void TMVARegressionTraining(std::string);
+
+   std::vector<float> TMVARegressionApplication(float, float, string);
+
+
+
+   void set_calolayer(int calolayer_) { m_calolayer = calolayer_; }
+   void set_PCAbin(int PCAbin_) { m_PCAbin = PCAbin_; }
+   void set_nbinsR(int nbinsR_) { m_nbinsR = nbinsR_; }
+   void set_particle(string particle_) { m_particle = particle_; }
+   void set_energy(float energy_) { m_particleEnergy = energy_; }
+   void set_eta(float etamin_, float etamax_) { m_etamin = etamin_; m_etamax = etamax_; }
+
+
+   void set_topDir(string topDir_) { m_topDir = topDir_; }
+   void set_fileName(string fileName_) { m_fileName = fileName_; }
+   void set_outputDirName(string outputDirName_) { m_outputDirName = outputDirName_; }
+   void set_NNinputName(string NNinputName_) { m_NNinputName = NNinputName_; }
+   void set_NNoutputName(string NNoutputName_) { m_NNoutputName = NNoutputName_; }
+
+   void set_neurons(int neurons_) { m_neurons = neurons_; }
+   void set_hiddenLayers(int hiddenLayers_) { m_hiddenLayers = hiddenLayers_; }
+
+
+
+private:
+
+   int m_calolayer;
+   int m_PCAbin;
+   int m_nbinsR;
+   string m_particle;
+   float m_particleEnergy; // in Gev
+   float m_etamin;
+   float m_etamax;
+
+   string m_topDir;
+   string m_fileName;
+   string m_outputDirName;
+   string m_NNinputName;
+   string m_NNoutputName;
+
+   // * TMVA parameters
+
+   int m_neurons;
+   int m_hiddenLayers;
+
+
+
+   ClassDef(ShowerShapeRegression, 1);
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class ShowerShapeRegression+;
+#endif
+
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..155a8bab7aaf9e9eef5aac52583cb962b7cf96b9
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.cxx
@@ -0,0 +1,712 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*******************************************************
+* Uses the flat Ntuples created by ShowerShapeThinning.cxx
+* Studies different aspects of the shower
+* Studies reweighting scheme to have the shower center at (0,0)
+* <a.hasib@cern.ch>
+**********************************************************/
+
+#include <iostream>
+
+#include "ShowerShapeStudy.h"
+#include "TString.h"
+#include "TMath.h"
+#include "TFile.h"
+#include "TH1.h"
+#include "TH2.h"
+
+
+using namespace std;
+
+ShowerShapeStudy::ShowerShapeStudy()
+{
+   m_debug = 0;
+
+   m_calolayer      = -1;
+   m_PCAbin         = 0;
+   m_nbinsR         = 0;
+   m_nbinsAlpha     = 0;
+   m_mincalosize    = 0.;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+   m_tolerance      = 0.;
+
+   cellDeta = 0;
+   cellDphi = 0;
+   cellr    = 0;
+   cellz    = 0;
+   celleta  = 0;
+}
+
+
+ShowerShapeStudy::~ShowerShapeStudy()
+{
+}
+
+
+std::tuple<float, float> ShowerShapeStudy::GetShift(int ievent)
+{
+   cout << "* Reading input hits file = " << m_hitsNtupleName.c_str() << endl;
+
+   TFile *inputHitsFile = TFile::Open(m_hitsNtupleName.c_str());
+
+   // * get the TTrees from hitsFile
+
+   TTree *hits   = (TTree *)inputHitsFile->Get("hits");
+   TTree *global = (TTree *)inputHitsFile->Get("global");
+
+   InitHitsTree(hits, global);
+
+   float sumDetaEnergy = 0;
+   float sumDphiEnergy = 0;
+   float Etotal        = 0;
+
+
+
+   for (int ihit = 0; ihit < hits->GetEntries(); ihit++)
+   {
+      hits->GetEntry(ihit);
+
+      float eventNumber = m_eventNumber;
+      float energy_hit  = m_energy;
+      float deta        = m_deta;
+      float dphi        = m_dphi;
+
+      if (eventNumber == ievent)
+      {
+         sumDetaEnergy += deta * energy_hit;
+         sumDphiEnergy += dphi * energy_hit;
+         Etotal        += energy_hit;
+      }
+   }
+
+   float etaShift = sumDetaEnergy / Etotal;
+   float phiShift = sumDphiEnergy / Etotal;
+
+   return (std::make_tuple(etaShift, phiShift));
+}
+
+
+void ShowerShapeStudy::EachParticleShower()
+{
+   // * get the input hits file
+
+   cout << "* Reading input hits file = " << m_hitsNtupleName.c_str() << endl;
+
+   TFile *inputHitsFile = TFile::Open(m_hitsNtupleName.c_str());
+
+   // * get the TTrees from hitsFile
+
+   TTree *hitsTree   = (TTree *)inputHitsFile->Get("hits");
+   TTree *globalTree = (TTree *)inputHitsFile->Get("global");
+
+
+   // * initialize the hits and global TTrees
+   InitHitsTree(hitsTree, globalTree);
+
+   // * Get the global variables
+   globalTree->GetEntry(0);
+
+   float etaCenter = m_etaCenter;
+   float phiCenter = m_phiCenter;
+   float etaShift  = m_etaShift;
+   float phiShift  = m_phiShift;
+
+   //cout << " 0th eta , phi shifts = " << etaShift << " , " << phiShift << endl;
+
+
+   float cell_r    = m_cellr;
+   float cell_z    = m_cellz;
+   float cell_eta  = m_celleta;
+   float cell_deta = m_cellDeta;
+   float cell_dphi = m_cellDphi;
+
+   float sumDetaEnergy = 0;
+   float sumDphiEnergy = 0;
+   float Etotal        = 0;
+
+   float sumEtaEnergy = 0;
+   float sumPhiEnergy = 0;
+
+
+   TH2F *hdetadphi0  = nullptr;
+   TH2F *hdetadphiE0 = nullptr;
+   TH1F *hdetaE0     = nullptr;
+
+   std::string file     = m_topDir + m_particle + "/EachParticleShower_" + m_fileName + ".root";
+   TFile       *outfile = new TFile(file.c_str(), "recreate");
+
+
+
+   int particleCount = 0;
+   int passEvent     = 0;
+
+   float etaShift2, phiShift2 = 0;
+
+   for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   {
+      hitsTree->GetEntry(ihit);
+
+      if (m_PCA != m_PCAbin)
+      {
+         continue;
+      }
+      passEvent++;
+
+
+
+      bool isNewEvent      = false;
+      int  NextEventNumber = -1;
+
+      if (ihit != hitsTree->GetEntries() - 1)
+      {
+         hitsTree->GetEntry(ihit + 1);
+         NextEventNumber = m_eventNumber;
+      }
+
+
+      hitsTree->GetEntry(ihit);
+
+
+
+      int eventNumber = m_eventNumber;
+
+      float energy_hit = m_energy;
+      float eta_hit    = m_etaHit;
+      float phi_hit    = m_phiHit;
+
+      float eta_entrance = m_etaEntrance;
+      float phi_entrance = m_phiEntrance;
+
+      float etaShift2 = 0, phiShift2 = 0;
+      if (passEvent == 1 or NextEventNumber != eventNumber)
+      {
+         tie(etaShift2, phiShift2) = GetShift(eventNumber);
+      }
+
+      // * calculate the corrected deta, dphi
+
+      float deta0 = m_deta - etaShift2;
+      float dphi0 = m_dphi - phiShift2;
+
+      float deta0_mm, dphi0_mm;
+      tie(deta0_mm, dphi0_mm) = GetUnitsmm(eta_hit, deta0, dphi0, cell_r, cell_z);
+
+      if (m_debug)
+      {
+         cout << "deta0 = " << deta0 << ", " << "dphi0 = " << dphi0 << ", deta0_mm =" << deta0_mm << ", dphi0_mm =" << dphi0_mm << endl;
+      }
+
+      int nbins = 400;
+      int low   = -100;
+      int high  = 100;
+
+
+
+      if (passEvent == 1)
+      {
+         cout << " Defining histogram for each particle..." << endl;
+         // * define the histogram for the first hit
+         hdetaE0     = new TH1F(Form("hdetaE0_%i", eventNumber), Form("hdetaE0_%i", eventNumber), nbins, low, high);
+         hdetadphi0  = new TH2F(Form("hdetadphi0_%i", eventNumber), Form("hdetadphi0_%i", eventNumber), nbins, low, high, nbins, low, high);
+         hdetadphiE0 = new TH2F(Form("hdetadphiE0_%i", eventNumber), Form("hdetadphiE0_%i", eventNumber), nbins, low, high, nbins, low, high);
+      }
+
+      hdetaE0->Fill(deta0_mm, energy_hit);
+      hdetadphi0->Fill(deta0_mm, dphi0_mm);
+      hdetadphiE0->Fill(deta0_mm, dphi0_mm, energy_hit);
+
+
+
+      if (NextEventNumber != eventNumber or ihit == hitsTree->GetEntries() - 1)
+      {
+         // if the next event has a different eventNumber then write
+
+         isNewEvent = true;
+         particleCount++;
+
+         outfile->cd();
+         hdetaE0->Write();
+         hdetadphi0->Write();
+         hdetadphiE0->Write();
+
+         delete hdetaE0;
+         delete hdetadphi0;
+         delete hdetadphiE0;
+      }
+
+
+
+      if (isNewEvent and ihit != hitsTree->GetEntries() - 1)
+      {
+         hdetaE0     = new TH1F(Form("hdetaE0_%i", eventNumber), Form("hdetaE0_%i", eventNumber), nbins, low, high);
+         hdetadphi0  = new TH2F(Form("hdetadphi0_%i", eventNumber), Form("hdetadphi0_%i", eventNumber), nbins, low, high, nbins, low, high);
+         hdetadphiE0 = new TH2F(Form("hdetadphiE0_%i", eventNumber), Form("hdetadphiE0_%i", eventNumber), nbins, low, high, nbins, low, high);
+      }
+
+
+      if (particleCount == 20)
+      {
+         outfile->Close();
+         cout << " Reach number of particles = " << particleCount << " exiting..." << endl;
+         break;
+      }
+   }
+}
+
+
+void ShowerShapeStudy::InvesitageShowerCenter(std::string inputHits)
+{
+   // * get the input hits file
+
+   cout << "* Reading input hits file = " << inputHits.c_str() << endl;
+
+   TFile *inputHitsFile = TFile::Open(inputHits.c_str());
+
+   // * get the TTrees from hitsFile
+
+   TTree *hitsTree   = (TTree *)inputHitsFile->Get("hits");
+   TTree *globalTree = (TTree *)inputHitsFile->Get("global");
+
+
+   // * initialize the hits and global TTrees
+   InitHitsTree(hitsTree, globalTree);
+
+   // * Get the global variables
+   globalTree->GetEntry(0);
+
+   float etaCenter = m_etaCenter;
+   float phiCenter = m_phiCenter;
+   float etaShift  = m_etaShift;
+   float phiShift  = m_phiShift;
+
+   //cout << " 0th eta , phi shifts = " << etaShift << " , " << phiShift << endl;
+
+
+   float cell_r    = m_cellr;
+   float cell_z    = m_cellz;
+   float cell_eta  = m_celleta;
+   float cell_deta = m_cellDeta;
+   float cell_dphi = m_cellDphi;
+
+   float sumDetaEnergy = 0;
+   float sumDphiEnergy = 0;
+   float Etotal        = 0;
+
+   float sumEtaEnergy = 0;
+   float sumPhiEnergy = 0;
+
+
+   float alphaMin = TMath::Pi() / 8; // * to cover the crack region in a single bin
+   float alphaMax = 2 * TMath::Pi() + alphaMin;
+   float rMax     = 10000;
+
+   TH1F *h_dr2_orig  = new TH1F("h_dr2_orig", "h_dr2_orig", 75000000, 0, rMax * rMax);
+   TH1F *h_dr2E_orig = new TH1F("h_dr2E_orig", "h_dr2E_orig", 75000000, 0, rMax * rMax);
+
+   //TH1F *h_dr2  = new TH1F("h_dr2", "h_dr2", 75000000, 0, rMax * rMax);
+   //TH1F *h_dr2E = new TH1F("h_dr2E", "h_dr2E", 75000000, 0, rMax * rMax);
+
+   //TH1F *hdeta0 = new TH1F("hdeta0", "hdeta0", 100, -0.2, 0.2);
+   //TH1F *hdphi0 = new TH1F("hdphi0", "hdphi0", 100, -0.2, 0.2);
+
+   //TH1F *hdeta0_mm = new TH1F("hdeta0_mm", "hdeta0_mm", 10000, -500, 500);
+   //TH1F *hdphi0_mm = new TH1F("hdphi0_mm", "hdphi0_mm", 10000, -500, 500);
+
+   //TH1F *hdeta1 = new TH1F("hdeta1", "hdeta1", 100, -0.2, 0.2);
+   //TH1F *hdphi1 = new TH1F("hdphi1", "hdphi1", 100, -0.2, 0.2);
+
+
+   TH1F *hdeta0_mm = new TH1F("hdeta0_mm", "hdeta0_mm", 1000, -500, 500);
+   TH1F *hdphi0_mm = new TH1F("hdphi0_mm", "hdphi0_mm", 1000, -500, 500);
+
+   TH1F *hdeta1_mm = new TH1F("hdeta1_mm", "hdeta1_mm", 1000, -500, 500);
+   TH1F *hdphi1_mm = new TH1F("hdphi1_mm", "hdphi1_mm", 1000, -500, 500);
+
+   //TH1F *hdeta2 = new TH1F("hdeta2", "hdeta2", 100, -0.2, 0.2);
+   //TH1F *hdphi2 = new TH1F("hdphi2", "hdphi2", 100, -0.2, 0.2);
+
+   //TH1F *hdeta2_mm = new TH1F("hdeta2_mm", "hdeta2_mm", 10000, -500, 500);
+   //TH1F *hdphi2_mm = new TH1F("hdphi2_mm", "hdphi2_mm", 10000, -500, 500);
+
+   //TH1F *hdeta0E = new TH1F("hdeta0E", "hdeta0E", 100, -0.2, 0.2);
+   //TH1F *hdphi0E = new TH1F("hdphi0E", "hdphi0E", 100, -0.2, 0.2);
+
+   //TH1F *hdeta0E_mm = new TH1F("hdeta0E_mm", "hdeta0E_mm", 10000, -500, 500);
+   //TH1F *hdphi0E_mm = new TH1F("hdphi0E_mm", "hdphi0E_mm", 10000, -500, 500);
+
+   //TH1F *hdeta1E = new TH1F("hdeta1E", "hdeta1E", 100, -0.2, 0.2);
+   //TH1F *hdphi1E = new TH1F("hdphi1E", "hdphi1E", 100, -0.2, 0.2);
+
+   TH1F *hdeta0E_mm = new TH1F("hdeta0E_mm", "hdeta0E_mm", 1000, -500, 500);
+   TH1F *hdphi0E_mm = new TH1F("hdphi0E_mm", "hdphi0E_mm", 1000, -500, 500);
+
+   TH1F *hdeta1E_mm = new TH1F("hdeta1E_mm", "hdeta1E_mm", 1000, -500, 500);
+   TH1F *hdphi1E_mm = new TH1F("hdphi1E_mm", "hdphi1E_mm", 1000, -500, 500);
+
+   TH2F *hdeta0dphi0E_mm = new TH2F("hdeta0dphi0E_mm", "hdeta0dphi0E_mm", 1000, -500, 500, 1000, -500, 500);
+   TH2F *hdeta0dphi0_mm  = new TH2F("hdeta0dphi0_mm", "hdeta0dphi0_mm", 1000, -500, 500, 1000, -500, 500);
+
+
+   TH2F *hdeta1dphi1E_mm = new TH2F("hdeta1dphi1E_mm", "hdeta1dphi1E_mm", 1000, -500, 500, 1000, -500, 500);
+   TH2F *hdeta1dphi1_mm  = new TH2F("hdeta1dphi1_mm", "hdeta1dphi1_mm", 1000, -500, 500, 1000, -500, 500);
+
+
+   // TH1F *hdeta2E = new TH1F("hdeta2E", "hdeta2E", 100, -0.2, 0.2);
+   //TH1F *hdphi2E = new TH1F("hdphi2E", "hdphi2E", 100, -0.2, 0.2);
+
+   //TH1F *hdeta2E_mm = new TH1F("hdeta2E_mm", "hdeta2E_mm", 10000, -500, 500);
+   //TH1F *hdphi2E_mm = new TH1F("hdphi2E_mm", "hdphi2E_mm", 10000, -500, 500);
+
+   TH1F *h_alpha0  = new TH1F("h_alpha0", "h_alpha0", 630000, alphaMin, alphaMax);
+   TH1F *h_alpha0E = new TH1F("h_alpha0E", "h_alpha0E", 630000, alphaMin, alphaMax);
+
+   TH1F *h_alpha1  = new TH1F("h_alpha1", "h_alpha1", 630000, alphaMin, alphaMax);
+   TH1F *h_alpha1E = new TH1F("h_alpha1E", "h_alpha1E", 630000, alphaMin, alphaMax);
+
+
+   cout << " Running over nhits = " << hitsTree->GetEntries() << endl;
+
+   for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   {
+      hitsTree->GetEntry(ihit);
+
+      if (m_PCA != m_PCAbin)
+      {
+         continue;
+      }
+
+      int eventNumber = m_eventNumber;
+
+      float energy_hit = m_energy;
+      float eta_hit    = m_etaHit;
+      float phi_hit    = m_phiHit;
+
+      float eta_entrance = m_etaEntrance;
+      float phi_entrance = m_phiEntrance;
+
+      // float deta = m_deta;
+      // float dphi = m_dphi;
+
+
+      // * calculate the corrected deta, dphi
+
+      float deta0 = m_deta;
+      float dphi0 = m_dphi;
+
+      float deta0_mm, dphi0_mm;
+      tie(deta0_mm, dphi0_mm) = GetUnitsmm(eta_hit, deta0, dphi0, cell_r, cell_z);
+
+      hdeta0_mm->Fill(deta0_mm);
+      hdeta0E_mm->Fill(deta0_mm, energy_hit);
+
+      hdphi0_mm->Fill(dphi0_mm);
+      hdphi0E_mm->Fill(dphi0_mm, energy_hit);
+
+      hdeta0dphi0_mm->Fill(deta0_mm, dphi0_mm);
+      hdeta0dphi0E_mm->Fill(deta0_mm, dphi0_mm, energy_hit);
+
+      float delta_r0 = TMath::Sqrt(dphi0_mm * dphi0_mm + deta0_mm * deta0_mm);
+      float alpha0   = TMath::ATan2(dphi0_mm, deta0_mm);
+
+      if (alpha0 < (TMath::Pi() / 8.))
+      {
+         alpha0 = 2 * TMath::Pi() + alpha0;
+      }
+
+      h_alpha0->Fill(alpha0);
+      h_alpha0E->Fill(alpha0, energy_hit);
+
+
+      float deta = m_deta - etaShift;
+      float dphi = DeltaPhi(m_dphi, phiShift);
+
+      //  if (m_debug)
+      //{
+      //cout << " deta = " << m_deta << ", dphi = " << m_dphi << ", deta corr = " << deta << ", dphi corr = " << dphi << endl;
+      //}
+
+      //hdeta1->Fill(deta);
+      //hdeta1E->Fill(deta, energy_hit);
+
+      //  hdphi1->Fill(dphi);
+      //  hdphi1E->Fill(dphi, energy_hit);
+
+
+
+      // * get the uncorrected co-ordinate in mm
+      float deta_mm, dphi_mm;
+      tie(deta_mm, dphi_mm) = GetUnitsmm(eta_hit, deta, dphi, cell_r, cell_z);
+
+      hdeta1_mm->Fill(deta_mm);
+      hdeta1E_mm->Fill(deta_mm, energy_hit);
+
+      hdphi1_mm->Fill(dphi_mm);
+      hdphi1E_mm->Fill(dphi_mm, energy_hit);
+
+      hdeta1dphi1_mm->Fill(deta_mm, dphi_mm);
+      hdeta1dphi1E_mm->Fill(deta_mm, dphi_mm, energy_hit);
+
+      float alpha1 = TMath::ATan2(dphi_mm, deta_mm);
+
+      if (alpha1 < (TMath::Pi() / 8.))
+      {
+         alpha1 = 2 * TMath::Pi() + alpha1;
+      }
+
+      h_alpha1->Fill(alpha1);
+      h_alpha1E->Fill(alpha1, energy_hit);
+
+
+
+      //cout << " deta = " << deta << " deta_mm =" << deta_mm << "dphi = " << dphi << "dph_mm =" << dphi_mm << endl;
+
+      float delta_r2 = dphi_mm * dphi_mm + deta_mm * deta_mm;
+
+      h_dr2_orig->Fill(delta_r2);
+      h_dr2E_orig->Fill(delta_r2, energy_hit);
+
+
+      if (delta_r2 < 100)
+      {
+         sumDetaEnergy += deta * energy_hit;
+         sumDphiEnergy += dphi * energy_hit;
+         sumEtaEnergy  += eta_hit * energy_hit;
+         sumPhiEnergy  += phi_hit * energy_hit;
+
+         Etotal += energy_hit;
+      }
+   }
+
+   float etaShift2 = sumDetaEnergy / Etotal;
+   float phiShift2 = sumDphiEnergy / Etotal;
+
+   float etaCenter2 = sumEtaEnergy / Etotal;
+   float phiCenter2 = sumPhiEnergy / Etotal;
+
+   cout << " 1st eta center, phi center =" << etaCenter2 << ", " << phiCenter2 << endl;
+   cout << " 1st eta , phi shifts = " << etaShift2 << " , " << phiShift2 << endl;
+
+   //float alphaMin = TMath::Pi() / 8; // * to cover the crack region in a single bin
+   //float alphaMax = 2 * TMath::Pi() + alphaMin;
+   //float rMax     = 10000;
+
+
+   TH1F *h_alpha  = new TH1F("h_alpha", "h_alpha", 630000, alphaMin, alphaMax);
+   TH1F *h_alphaE = new TH1F("h_alphaE", "h_alphaE", 630000, alphaMin, alphaMax);
+
+   TH2F *hdeta2dphi2E_mm = new TH2F("hdeta2dphi2E_mm", "hdeta2dphi2E_mm", 1000, -500, 500, 1000, -500, 500);
+   TH2F *hdeta2dphi2_mm  = new TH2F("hdeta2dphi2_mm", "hdeta2dphi2_mm", 1000, -500, 500, 1000, -500, 500);
+
+
+   for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   {
+      hitsTree->GetEntry(ihit);
+
+      //* apply pca bin choice
+      if (m_PCA != m_PCAbin)
+      {
+         continue;
+      }
+
+
+      int eventNumber = m_eventNumber;
+
+      float energy_hit = m_energy;
+      float eta_hit    = m_etaHit;
+      float phi_hit    = m_phiHit;
+
+      float eta_entrance = m_etaEntrance;
+      float phi_entrance = m_phiEntrance;
+
+      //float deta = m_deta;
+      //float dphi = m_dphi;
+
+      // * calculate the corrected deta, dphi
+
+      float deta = m_deta - etaShift;
+      float dphi = DeltaPhi(m_dphi, phiShift);
+
+      //if (m_debug)
+      //{
+      //cout << " deta = " << m_deta << ", dphi = " << m_dphi << ", deta corr = " << deta << ", dphi corr = " << dphi << endl;
+      //}
+
+
+      // * get the uncorrected co-ordinate in mm
+      float deta_mm, dphi_mm;
+      tie(deta_mm, dphi_mm) = GetUnitsmm(eta_hit, deta, dphi, cell_r, cell_z);
+
+      //cout<<" deta mm = "<<deta_mm<<endl;
+      //cout<<" dphi mm = "<<dphi_mm<<endl;
+
+      float delta_r2 = (dphi_mm * dphi_mm + deta_mm * deta_mm);
+
+      // if (delta_r2 > 1000)
+      // {
+      //    continue;
+      // }
+      // float hit_eta_corr = eta_hit - etaCenter2;
+      // float hit_phi_corr = phi_hit - phiCenter2;
+
+
+      float deta_corr = deta - etaShift2;
+      float dphi_corr = DeltaPhi(dphi, phiShift2);
+
+
+      float deta_corr_mm, dphi_corr_mm;
+      tie(deta_corr_mm, dphi_corr_mm) = GetUnitsmm(eta_hit, deta_corr, dphi_corr, cell_r, cell_z);
+
+
+      hdeta2dphi2_mm->Fill(deta_corr_mm, dphi_corr_mm);
+      hdeta2dphi2E_mm->Fill(deta_corr_mm, dphi_corr_mm, energy_hit);
+
+
+      // * calculate r and alpha co-ordiantes
+
+      float delta_r = TMath::Sqrt(dphi_corr_mm * dphi_corr_mm + deta_corr_mm * deta_corr_mm);
+      float alpha   = TMath::ATan2(dphi_corr_mm, deta_corr_mm);
+
+      // h_dr2->Fill(delta_r * delta_r);
+      // h_dr2E->Fill(delta_r * delta_r, energy_hit);
+
+
+      if (alpha < (TMath::Pi() / 8.))
+      {
+         alpha = 2 * TMath::Pi() + alpha;
+      }
+
+      h_alpha->Fill(alpha);
+      h_alphaE->Fill(alpha, energy_hit);
+   }
+
+
+
+   std::string showercenter = m_topDir + m_particle + "/InvesitageShowerCenter_" + m_fileName + ".root";
+   TFile       *outfile     = new TFile(showercenter.c_str(), "recreate");
+   outfile->cd();
+   //hdeta1->Write();
+   //hdeta1E->Write();
+   hdeta0_mm->Write();
+   hdeta0E_mm->Write();
+
+   hdeta1_mm->Write();
+   hdeta1E_mm->Write();
+   //hdphi1->Write();
+   //hdphi1E->Write();
+   hdphi0_mm->Write();
+   hdphi0E_mm->Write();
+
+   hdphi1_mm->Write();
+   hdphi1E_mm->Write();
+   //h_dr2->Write();
+   //h_dr2E->Write();
+   h_dr2_orig->Write();
+   h_dr2E_orig->Write();
+
+
+   hdeta0dphi0E_mm->Write();
+   hdeta0dphi0_mm->Write();
+
+   hdeta1dphi1E_mm->Write();
+   hdeta1dphi1_mm->Write();
+
+   h_alpha0->Write();
+   h_alpha0E->Write();
+
+   h_alpha1->Write();
+   h_alpha1E->Write();
+
+   h_alpha->Write();
+   h_alphaE->Write();
+
+   hdeta2dphi2_mm->Write();
+   hdeta2dphi2E_mm->Write();
+
+
+   outfile->Close();
+}
+
+
+std::tuple<float, float> ShowerShapeStudy::GetUnitsmm(float eta_hit, float d_eta, float d_phi, float cell_r, float cell_z)
+{
+   float phi_dist2r = 1.0;
+   float dist000    = TMath::Sqrt(cell_r * cell_r + cell_z * cell_z);
+
+   float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-eta_hit) / (1.0 + TMath::Exp(-2 * eta_hit)));
+
+   d_eta = d_eta * eta_jakobi * dist000;
+   d_phi = d_phi * cell_r * phi_dist2r;
+
+   if (m_debug)
+   {
+      cout << " in function deta = " << d_eta << " dphi = " << d_phi << endl;
+   }
+   return std::make_tuple(d_eta, d_phi);
+}
+
+
+float ShowerShapeStudy::DeltaPhi(float phi1, float phi2)
+{
+   double result = phi1 - phi2;
+
+   while (result > TMath::Pi())
+   {
+      result -= 2 * TMath::Pi();
+   }
+   while (result <= -TMath::Pi())
+   {
+      result += 2 * TMath::Pi();
+   }
+   return result;
+}
+
+
+void ShowerShapeStudy::InitHitsTree(TTree *hitsNtuple, TTree *globalNtuple)
+{
+   m_eventNumber = -1;
+   m_energy      = 0.;
+   m_etaHit      = 0.;
+   m_phiHit      = 0.;
+   m_etaEntrance = 0.;
+   m_phiEntrance = 0.;
+   m_deta        = 0.;
+   m_dphi        = 0.;
+   m_PCA         = 0;
+
+   m_etaCenter = 0.;
+   m_phiCenter = 0.;
+   m_etaShift  = 0.;
+   m_phiShift  = 0.;
+   m_cellr     = 0.;
+   m_cellz     = 0.;
+   m_celleta   = 0.;
+   m_cellDeta  = 0.;
+   m_cellDphi  = 0.;
+
+   hitsNtuple->SetBranchAddress("eventNumber", &m_eventNumber);
+   hitsNtuple->SetBranchAddress("energy_hit", &m_energy);
+   hitsNtuple->SetBranchAddress("eta_hit", &m_etaHit);
+   hitsNtuple->SetBranchAddress("phi_hit", &m_phiHit);
+   hitsNtuple->SetBranchAddress("eta_entrance", &m_etaEntrance);
+   hitsNtuple->SetBranchAddress("phi_entrance", &m_phiEntrance);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("delta_phi", &m_dphi);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("pca_bin", &m_PCA);
+
+   globalNtuple->SetBranchAddress("eta_center", &m_etaCenter);
+   globalNtuple->SetBranchAddress("phi_center", &m_phiCenter);
+   globalNtuple->SetBranchAddress("eta_shift", &m_etaShift);
+   globalNtuple->SetBranchAddress("phi_shift", &m_phiShift);
+   globalNtuple->SetBranchAddress("cell_r", &m_cellr);
+   globalNtuple->SetBranchAddress("cell_z", &m_cellz);
+   globalNtuple->SetBranchAddress("cell_eta", &m_celleta);
+   globalNtuple->SetBranchAddress("cell_deta", &m_cellDeta);
+   globalNtuple->SetBranchAddress("cell_dphi", &m_cellDphi);
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.h
new file mode 100644
index 0000000000000000000000000000000000000000..66def975662fafdf9dba2a23f5da57a3af8c11af
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeStudy.h
@@ -0,0 +1,109 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ShowerShapeStudy_h
+#define ShowerShapeStudy_h
+
+#include "TTree.h"
+
+
+
+class ShowerShapeStudy
+{
+public:
+   ShowerShapeStudy();
+   ~ShowerShapeStudy();
+
+   std::tuple<float, float> GetShift(int);
+
+   void EachParticleShower();
+   void InvesitageShowerCenter(std::string inputHits);
+
+
+   std::tuple<float, float> GetUnitsmm(float eta_hits, float deta, float dphi, float cellr, float cellz);
+
+   void InitHitsTree(TTree *, TTree *);
+
+   //void BookHitsAlphaDrTree(TTree *);
+   float DeltaPhi(float, float);
+
+   // * setter methods
+   void set_calolayer(int calolayer_) { m_calolayer = calolayer_; }
+   void set_PCAbin(int PCAbin_) { m_PCAbin = PCAbin_; }
+   void set_nbinsR(int nbinsR_) { m_nbinsR = nbinsR_; }
+   void set_nbinsAlpha(int nbinsAlpha_) { m_nbinsAlpha = nbinsAlpha_; }
+   void set_mincalosize(float mincalosize_) { m_mincalosize = mincalosize_; }
+   void set_particle(string particle_) { m_particle = particle_; }
+   void set_energy(float energy_) { m_particleEnergy = energy_; }
+   void set_eta(float etamin_, float etamax_) { m_etamin = etamin_; m_etamax = etamax_; }
+   void set_tolerance(float tolerance_) { m_tolerance = tolerance_; }
+
+   void set_topDir(string topDir_) { m_topDir = topDir_; }
+   void set_fileName(string fileName_) { m_fileName = fileName_; }
+   void set_hitsNtupleName(string hitsNtupleName_) { m_hitsNtupleName = hitsNtupleName_; }
+
+
+
+private:
+   // * settings
+   int m_calolayer;
+   int m_PCAbin;
+   int m_PCA; // ttree variable
+   int m_nbinsR;
+   int m_nbinsAlpha;
+   float m_mincalosize;
+   string m_particle;
+   float m_particleEnergy; // in Gev
+   float m_etamin;
+   float m_etamax;
+   float m_tolerance;
+   string m_hitsNtupleName;
+
+   int m_debug;
+
+
+   std::string m_topDir;
+   std::string m_fileName;
+
+
+
+   // * cell geometry
+
+   float cellDeta;
+   float cellDphi;
+   float cellr;
+   float cellz;
+   float celleta;
+
+   // * for hits TTree
+   int m_eventNumber;
+   float m_energy;
+   float m_etaHit;
+   float m_phiHit;
+   float m_etaEntrance;
+   float m_phiEntrance;
+   float m_deta;
+   float m_dphi;
+
+
+   float m_etaCenter;
+   float m_phiCenter;
+   float m_etaShift;
+   float m_phiShift;
+   float m_cellr;
+   float m_cellz;
+   float m_celleta;
+   float m_cellDeta;
+   float m_cellDphi;
+
+
+
+   ClassDef(ShowerShapeStudy, 1);
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class ShowerShapeThinning+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..91471d4297f8cd08881905ec7a1695f131d20048
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.cxx
@@ -0,0 +1,753 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/****************************************************
+ * Class to implement:
+ *      - looping over events
+ *      - create flat ntuple with hits
+ *      - create another ntuple with alpha and r
+ *
+ *    <a.hasib@cern.ch>
+ *****************************************************/
+#include <iostream>
+#include <tuple>
+#include <algorithm>
+
+#include "TString.h"
+#include "TMath.h"
+#include "TFile.h"
+#include "TH1.h"
+#include "TH2.h"
+
+#include "ShowerShapeThinning.h"
+#include "tools/CaloGeometryFromFile.h"
+#include "tools/CaloDetDescr/CaloDetDescrElement.h"
+
+
+
+using namespace std;
+
+
+ShowerShapeThinning::ShowerShapeThinning()
+{
+   m_debug = 0;
+
+   m_calolayer      = -1;
+   m_PCAbin         = 0;
+   m_nbinsR         = 0;
+   m_nbinsAlpha     = 0;
+   m_mincalosize    = 0.;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+   m_tolerance      = 0.;
+
+   m_chain = 0;
+   m_tree  = 0;
+
+
+   cellDeta = 0;
+   cellDphi = 0;
+   cellr    = 0;
+   cellz    = 0;
+   celleta  = 0;
+}
+
+
+ShowerShapeThinning::ShowerShapeThinning(TChain *chain, TTree *tree)
+{
+   m_debug = 0;
+
+   m_calolayer      = -1;
+   m_PCAbin         = 0;
+   m_nbinsR         = 0;
+   m_nbinsAlpha     = 0;
+   m_mincalosize    = 0.;
+   m_particle       = "";
+   m_particleEnergy = 0.;
+   m_etamin         = 0.;
+   m_etamax         = 0.;
+   m_tolerance      = 0.;
+
+   m_chain = chain;
+   m_tree  = tree;
+
+   cellDeta = 0;
+   cellDphi = 0;
+   cellr    = 0;
+   cellz    = 0;
+   celleta  = 0;
+}
+
+
+ShowerShapeThinning::~ShowerShapeThinning()
+{
+   if (m_cellVector)
+   {
+      delete m_cellVector;
+   }
+   if (m_truthCollection)
+   {
+      delete m_truthCollection;
+   }
+   if (m_truthPx)
+   {
+      delete m_truthPx;
+   }
+   if (m_truthPy)
+   {
+      delete m_truthPy;
+   }
+   if (m_truthPz)
+   {
+      delete m_truthPz;
+   }
+   if (m_truthE)
+   {
+      delete m_truthE;
+   }
+}
+
+
+void ShowerShapeThinning::CreateHitsNtuple(TFile *file)
+{
+   // *define TTree for per hits and global variables
+
+   TTree *m_hitsNtuple   = new TTree("hits", "hits");
+   TTree *m_globalNtuple = new TTree("global", "global");
+
+   // * book the hits and global TTree
+   BookHitsTree(m_hitsNtuple, m_globalNtuple);
+
+
+   // * get the PCA bins
+   auto vbinsPCA = GetPCAbins();
+
+   // * initialize the input TTree
+   InitInputTree();
+
+
+   // * intialize variables that needs to be saved in hits TTree
+
+   float sumDetaEnergy = 0.;
+   float sumDphiEnergy = 0.;
+   float sumEta        = 0.;
+   float sumPhi        = 0.;
+   float Etotal        = 0.;
+   int   nhits         = 0;
+
+   // * pca file requires special counter since some are run over inclusive eta with a particular eta selection;
+
+   int pcaEvent = -1;
+
+   // * loop over events
+
+   for (int ievent = 0; ievent < m_chain->GetEntries(); ievent++)
+   {
+      if (ievent % 200 == 0)
+      {
+         cout << " Event: " << ievent << endl;
+      }
+
+      m_chain->GetEntry(ievent);
+
+      TLorentzVector TruthParticle;
+      TruthParticle.SetPxPyPzE(m_truthPx->at(0), m_truthPy->at(0), m_truthPz->at(0), m_truthE->at(0));
+
+
+
+      if (fabs(TruthParticle.Eta()) < m_etamin or fabs(TruthParticle.Eta()) > m_etamax)
+      {
+         continue;
+      }
+
+      pcaEvent++;
+
+      if (vbinsPCA.at(pcaEvent) != m_PCAbin)
+      {
+         continue;
+      }
+
+
+      // * loop over the cells and hits in each cell
+
+      for (unsigned int icell = 0; icell < (*m_cellVector).size(); icell++)
+      {
+         for (unsigned int ihit = 0; ihit < ((FCS_matchedcell)(*m_cellVector)[icell]).hit.size(); ihit++)
+         {
+            float energy = ((FCS_matchedcell)(*m_cellVector)[icell]).hit[ihit].hit_energy;
+            float posx   = ((FCS_matchedcell)(*m_cellVector)[icell]).hit[ihit].hit_x;
+            float posy   = ((FCS_matchedcell)(*m_cellVector)[icell]).hit[ihit].hit_y;
+            float posz   = ((FCS_matchedcell)(*m_cellVector)[icell]).hit[ihit].hit_z;
+
+            TVector3 *pos = new TVector3(posx, posy, posz);
+
+            // * hit eta, phi
+            float etaHit = pos->PseudoRapidity();
+            float phiHit = pos->Phi();
+
+            // * entrance eta
+            float etaEntrance = (*m_truthCollection)[0].TTC_entrance_eta[0];
+            float phiEntrance = (*m_truthCollection)[0].TTC_entrance_phi[0];
+
+            float deta = etaHit - etaEntrance;
+
+
+            // * calculate dphi
+            float y_entrance = ((*m_truthCollection)[0].TTC_entrance_r[0]) * TMath::Sin((*m_truthCollection)[0].TTC_entrance_phi[0]);
+            float x_entrance = ((*m_truthCollection)[0].TTC_entrance_r[0]) * TMath::Cos((*m_truthCollection)[0].TTC_entrance_phi[0]);
+
+            TVector2 *entrance = new TVector2(x_entrance, y_entrance);
+            TVector2 *hit      = new TVector2(pos->X(), pos->Y());
+
+            float dphi = hit->DeltaPhi(*entrance);
+
+
+            // * to calculate eta and phi shift
+
+            sumDetaEnergy += deta * energy;
+            sumDphiEnergy += dphi * energy;
+            Etotal        += energy;
+
+            // * to calculate eta center and phi center
+
+            sumEta += etaHit;
+            sumPhi += phiHit;
+            nhits++;
+
+            // * fill the hits TTree
+            m_eventNumber = ievent; // save the event number;
+            m_energy      = energy;
+            m_etaHit      = etaHit;
+            m_phiHit      = phiHit;
+            m_etaEntrance = etaEntrance;
+            m_phiEntrance = phiEntrance;
+            m_deta        = deta;
+            m_dphi        = dphi;
+            m_PCA         = vbinsPCA.at(pcaEvent);
+            m_hitsNtuple->Fill();
+         } // end loop over cells
+      }    // end loop over hits
+   }       // end loop over events
+
+   if (m_debug)
+   {
+      cout << " sum eta = " << sumEta << endl;
+      cout << " sum phi = " << sumPhi << endl;
+
+      cout << " sumDetaEnergy = " << sumDetaEnergy << endl;
+      cout << " sumDphiEnergy = " << sumDphiEnergy << endl;
+      cout << " Etotal = " << Etotal << endl;
+   }
+
+   float etaCenter = sumEta / nhits;
+   float phiCenter = sumPhi / nhits;
+
+   float etaShift = sumDetaEnergy / Etotal;
+   float phiShift = sumDphiEnergy / Etotal;
+
+   if (m_debug)
+   {
+      cout << " etaCenter = " << etaCenter << endl;
+      cout << " phiCenter = " << phiCenter << endl;
+      cout << " nhits = " << nhits << endl;
+
+      cout << " etaShift = " << etaShift << endl;
+      cout << " phiShift = " << phiShift << endl;
+   }
+
+   // * get cell geometry
+
+   GetCellGeom(etaCenter, phiCenter);
+
+   if (m_debug)
+   {
+      cout << " cell r = " << cellr << ", cell z = " << cellz << ", cell eta = " << celleta << ", cell deta= " << cellDeta << ", cell dpi = " << cellDphi << endl;
+   }
+
+
+
+   //* fill global TTree
+
+   m_etaCenter = etaCenter;
+   m_phiCenter = phiCenter;
+   m_etaShift  = etaShift;
+   m_phiShift  = phiShift;
+   m_cellr     = cellr;
+   m_cellz     = cellz;
+   m_celleta   = celleta;
+   m_cellDeta  = cellDeta;
+   m_cellDphi  = cellDphi;
+   m_globalNtuple->Fill();
+
+
+   // * write the TTree
+
+   file->cd();
+   m_hitsNtuple->Write();
+   m_globalNtuple->Write();
+   file->Close();
+}
+
+
+void ShowerShapeThinning::CreateHitsAlphaDrNtuple(std::string inputHits)
+{
+   // * get the input hits file
+
+
+   cout << "* Reading input hits file = " << inputHits.c_str() << endl;
+
+   TFile *inputHitsFile = TFile::Open(inputHits.c_str());
+
+   // * get the TTrees from hitsFile
+
+   TTree *hitsTree   = (TTree *)inputHitsFile->Get("hits");
+   TTree *globalTree = (TTree *)inputHitsFile->Get("global");
+
+
+   // * initialize the hits and global TTrees
+   InitHitsTree(hitsTree, globalTree);
+
+   // * Get the global variables
+   globalTree->GetEntry(0);
+
+   float etaCenter = m_etaCenter;
+   float phiCenter = m_phiCenter;
+   float etaShift  = m_etaShift;
+   float phiShift  = m_phiShift;
+
+   float cell_r    = m_cellr;
+   float cell_z    = m_cellz;
+   float cell_eta  = m_celleta;
+   float cell_deta = m_cellDeta;
+   float cell_dphi = m_cellDphi;
+
+
+   if (m_debug)
+   {
+      cout << " eta center = " << etaCenter << ", phi center = " << phiCenter << " , eta shift = " << etaShift << " , phi shift = " << phiShift << ", cell r = " << cell_r << ", cell z = " << cell_z << ", cell eta = " << cell_eta << ", cell deta = " << cell_deta << ", cell dpi = " << cell_dphi << endl;
+   }
+
+   // * define alpha and dr histograms needed to determine binning
+
+   float alphaMin = TMath::Pi() / 8;    // * to cover the crack region in a single bin
+   float alphaMax = 2 * TMath::Pi() + alphaMin;
+   float rMax     = 10000;
+
+   // * use fine binning for the initial histograms
+   TH1F *h_alpha = new TH1F("h_alpha", "h_alpha", 630000, alphaMin, alphaMax);
+   TH1F *h_dr    = new TH1F("h_dr", "h_dr", 75000000, 0, rMax);
+
+   TH1F *h_alphaE = new TH1F("h_alphaE", "h_alphaE", 630000, alphaMin, alphaMax);
+
+   TH1F *hdeta_corr = new TH1F("hdeta_corr", "hdeta_corr", 100, -0.2, 0.2);
+   TH1F *hdphi_corr = new TH1F("hdphi_corr", "hdphi_corr", 100, -0.2, 0.2);
+
+   // plot energy heatmap before binning optimization
+   TH2F *hDetaDphi  = new TH2F("hDetaDphi", "hDetaDphi", 100, -0.02, 0.02, 100, -0.02, 0.02);
+   TH2F *hDetaDphiE = new TH2F("hDetaDphiE", "hDetaDphiE", 100, -0.02, 0.02, 100, -0.02, 0.02);
+
+   TH2F *hDetaDphi_corr  = new TH2F("hDetaDphi_corr", "hDetaDphi_corr", 100, -0.02, 0.02, 100, -0.02, 0.02);
+   TH2F *hDetaDphiE_corr = new TH2F("hDetaDphiE_corr", "hDetaDphiE_corr", 100, -0.02, 0.02, 100, -0.02, 0.02);
+
+
+   // * define output file to save h_alpha h_dr and TTree with alpha, dr and energy
+
+   std::string HitsAlphaDr = m_topDir + m_particle + "/HitsAlphaDr_" + m_fileName + ".root";
+   if (m_debug)
+   {
+      cout << " hits alpha dr = " << HitsAlphaDr << endl;
+   }
+
+
+   TFile *hitsAlphaDrFile     = new TFile(HitsAlphaDr.c_str(), "recreate");
+   TTree *m_hitsAlphaDrNtuple = new TTree("hitsAlphaDr", "hitsAlphaDr");
+   BookHitsAlphaDrTree(m_hitsAlphaDrNtuple);
+
+
+   // * loop through all hits
+
+   cout << " Looping over nhits = " << hitsTree->GetEntries() << endl;
+
+   for (int ihit = 0; ihit < hitsTree->GetEntries(); ihit++)
+   {
+      hitsTree->GetEntry(ihit);
+
+      int eventNumber = m_eventNumber;
+
+      float energy_hit = m_energy;
+      float eta_hit    = m_etaHit;
+      float phi_hit    = m_phiHit;
+
+      float eta_entrance = m_etaEntrance;
+      float phi_entrance = m_phiEntrance;
+
+      float deta = m_deta;
+      float dphi = m_dphi;
+
+      // * calculate the corrected deta, dphi
+
+      float deta_corr = deta - etaShift;
+      float dphi_corr = dphi - phiShift;
+
+      if (m_debug)
+      {
+         cout << "energy hit = " << energy_hit << ", eta hit = " << eta_hit << ", deta = " << deta << ", dphi = " << dphi << ", deta corr = " << deta_corr << ", dphi corr = " << dphi_corr << endl;
+      }
+
+
+      // * get the co-ordinates in mm
+
+      float deta_corr_mm, dphi_corr_mm;
+      tie(deta_corr_mm, dphi_corr_mm) = GetUnitsmm(eta_hit, deta_corr, dphi_corr, cell_r, cell_z);
+
+      hdeta_corr->Fill(deta_corr);
+      hdphi_corr->Fill(dphi_corr);
+
+
+
+      if (m_debug)
+      {
+         cout << "in mm deta corr = " << deta_corr_mm << " dphi corr = " << dphi_corr_mm << endl;
+      }
+
+
+      // * save TH2 of eta-phi w/ and w/o energy weighted
+      hDetaDphi->Fill(deta, dphi);
+      hDetaDphiE->Fill(deta, dphi, energy_hit);
+
+      hDetaDphi_corr->Fill(deta_corr, dphi_corr);
+      hDetaDphiE_corr->Fill(deta_corr, dphi_corr, energy_hit);
+
+
+      // * calculate r and alpha co-ordiantes
+
+      float delta_r = TMath::Sqrt(dphi_corr_mm * dphi_corr_mm + deta_corr_mm * deta_corr_mm);
+      float alpha   = TMath::ATan2(dphi_corr_mm, deta_corr_mm);
+
+      if (alpha < (TMath::Pi() / 8.))
+      {
+         alpha = 2 * TMath::Pi() + alpha;
+      }
+
+      if (m_debug)
+      {
+         cout << " delta r = " << delta_r << " mm, alpha = " << alpha << " mm" << endl;
+      }
+
+      h_alpha->Fill(alpha);
+      h_alphaE->Fill(alpha, energy_hit);
+
+      // * reweight r with hit energy,  if energy > 1 MeV weigher = energy, otherwise weight = 1
+      if (energy_hit > 1.)
+      {
+         h_dr->Fill(delta_r, energy_hit);
+      }
+      else
+      {
+         h_dr->Fill(delta_r, 1);
+      }
+
+
+      // * fill the TTree
+      m_eventNumber = eventNumber;
+      m_alpha       = alpha;
+      m_dr          = delta_r;
+      m_energy      = energy_hit;
+      m_hitsAlphaDrNtuple->Fill();
+   }   //end loop over hits
+
+
+
+   hitsAlphaDrFile->cd();
+   m_hitsAlphaDrNtuple->Write();
+   globalTree->CloneTree()->Write();
+   h_alpha->Write();
+   h_dr->Write();
+
+   h_alphaE->Write();
+
+   hdeta_corr->Write();
+   hdphi_corr->Write();
+
+   hDetaDphi->Write();
+   hDetaDphiE->Write();
+   hDetaDphi_corr->Write();
+   hDetaDphiE_corr->Write();
+
+   hitsAlphaDrFile->Close();
+   inputHitsFile->Close();
+}
+
+
+std::vector<float> ShowerShapeThinning::Getxbins(TH1F *histo, int nbins)
+{
+   // * calculate variable bin width in alpha and dr making sure each bin has almost equal amount of hits.
+
+   bool isAlpha = true;
+
+   std::vector<float> xbins;
+
+
+   std::string title = histo->GetTitle();
+
+   if (title.compare("h_dr") == 0)
+   {
+      isAlpha = false;
+   }
+
+   if (m_debug)
+   {
+      cout << "title = " << title.c_str() << " isAlpha = " << isAlpha << endl;
+   }
+
+   if (isAlpha)
+   {
+      xbins.push_back(TMath::Pi() / 8);
+   }
+   else
+   {
+      xbins.push_back(0);
+   }
+
+
+
+   float AvgHitsPerBin = histo->Integral() / nbins;
+
+
+   float hitCounts = 0;
+
+   for (int ibin = 1; ibin < histo->GetNbinsX() + 1; ibin++)
+   {
+      if (hitCounts < AvgHitsPerBin)
+      {
+         hitCounts = hitCounts + histo->GetBinContent(ibin);
+      }
+      else if (hitCounts >= AvgHitsPerBin)
+      {
+         xbins.push_back(histo->GetBinLowEdge(ibin) + histo->GetBinWidth(ibin));
+         hitCounts = 0;
+      }
+   }
+
+   int   nRmax = histo->FindLastBinAbove(0);
+   float Rmax  = histo->GetBinLowEdge(nRmax) + histo->GetBinWidth(nRmax);
+
+   if (isAlpha)
+   {
+      xbins.push_back(2 * TMath::Pi() + TMath::Pi() / 8);
+   }
+   else
+   {
+      xbins.push_back(Rmax);
+   }
+
+   return xbins;
+}
+
+
+void ShowerShapeThinning::GetCellGeom(float etacentre, float phicentre)
+{
+   int layer = m_calolayer;
+
+   CaloGeometryFromFile *geo = new CaloGeometryFromFile();
+
+   geo->LoadGeometryFromFile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSim/ATLAS-GEO-20-00-01.root", "ATLAS-GEO-20-00-01");
+
+
+   const CaloGeoDetDescrElement *cell;
+   cell = geo->getDDE(layer, etacentre, phicentre);
+
+   cellr    = cell->r();
+   cellz    = cell->z();
+   cellDphi = cell->dphi();
+   cellDeta = cell->deta();
+   celleta  = cell->eta();
+}
+
+
+std::tuple<float, float> ShowerShapeThinning::GetUnitsmm(float eta_hit, float d_eta, float d_phi, float cell_r, float cell_z)
+{
+   float phi_dist2r = 1.0;
+   float dist000    = TMath::Sqrt(cell_r * cell_r + cell_z * cell_z);
+
+   float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-eta_hit) / (1.0 + TMath::Exp(-2 * eta_hit)));
+
+   d_eta = d_eta * eta_jakobi * dist000;
+   d_phi = d_phi * cell_r * phi_dist2r;
+
+   if (m_debug)
+   {
+      cout << " in function deta = " << d_eta << " dphi = " << d_phi << endl;
+   }
+   return std::make_tuple(d_eta, d_phi);
+}
+
+
+vector<int> ShowerShapeThinning::GetPCAbins()
+{
+   vector<int> binsPCA;
+
+   int bin = 0;
+   m_tree->SetBranchAddress("firstPCAbin", &bin);
+
+   for (int ientry = 0; ientry < m_tree->GetEntries(); ientry++)
+   {
+      m_tree->GetEntry(ientry);
+      if (m_debug)
+      {
+         cout << " bin = " << bin << endl;
+      }
+      binsPCA.push_back(bin);
+   }
+
+   return binsPCA;
+}
+
+
+void ShowerShapeThinning::InitInputTree()
+{
+   m_cellVector      = nullptr;
+   m_truthCollection = nullptr;
+   m_truthPx         = nullptr;
+   m_truthPy         = nullptr;
+   m_truthPz         = nullptr;
+   m_truthE          = nullptr;
+
+
+   TString layer = Form("Sampling_%i", m_calolayer);
+   if (m_debug)
+   {
+      cout << " layer = " << layer << endl;
+   }
+
+
+   m_chain->SetBranchAddress(layer, &m_cellVector);
+   m_chain->SetBranchAddress("TruthCollection", &m_truthCollection);
+   m_chain->SetBranchAddress("TruthPx", &m_truthPx);
+   m_chain->SetBranchAddress("TruthPy", &m_truthPy);
+   m_chain->SetBranchAddress("TruthPz", &m_truthPz);
+   m_chain->SetBranchAddress("TruthE", &m_truthE);
+}
+
+
+void ShowerShapeThinning::BookHitsTree(TTree *hitsNtuple, TTree *globalNtuple)
+{
+   m_eventNumber = -1;
+   m_energy      = 0.;
+   m_etaHit      = 0.;
+   m_phiHit      = 0.;
+   m_etaEntrance = 0.;
+   m_phiEntrance = 0.;
+   m_deta        = 0.;
+   m_dphi        = 0.;
+   m_PCA         = 0;
+
+   m_etaCenter = 0.;
+   m_phiCenter = 0.;
+   m_etaShift  = 0.;
+   m_phiShift  = 0.;
+   m_cellr     = 0.;
+   m_cellz     = 0.;
+   m_celleta   = 0.;
+   m_cellDeta  = 0.;
+   m_cellDphi  = 0.;
+
+   hitsNtuple->Branch("eventNumber", &m_eventNumber);
+   hitsNtuple->Branch("energy_hit", &m_energy);
+   hitsNtuple->Branch("eta_hit", &m_etaHit);
+   hitsNtuple->Branch("phi_hit", &m_phiHit);
+   hitsNtuple->Branch("eta_entrance", &m_etaEntrance);
+   hitsNtuple->Branch("phi_entrance", &m_phiEntrance);
+   hitsNtuple->Branch("delta_eta", &m_deta);
+   hitsNtuple->Branch("delta_phi", &m_dphi);
+   hitsNtuple->Branch("delta_eta", &m_deta);
+   hitsNtuple->Branch("pca_bin", &m_PCA);
+
+   globalNtuple->Branch("eta_center", &m_etaCenter);
+   globalNtuple->Branch("phi_center", &m_phiCenter);
+   globalNtuple->Branch("eta_shift", &m_etaShift);
+   globalNtuple->Branch("phi_shift", &m_phiShift);
+   globalNtuple->Branch("cell_r", &m_cellr);
+   globalNtuple->Branch("cell_z", &m_cellz);
+   globalNtuple->Branch("cell_eta", &m_celleta);
+   globalNtuple->Branch("cell_deta", &m_cellDeta);
+   globalNtuple->Branch("cell_dphi", &m_cellDphi);
+}
+
+
+void ShowerShapeThinning::InitHitsTree(TTree *hitsNtuple, TTree *globalNtuple)
+{
+   m_eventNumber = -1;
+   m_energy      = 0.;
+   m_etaHit      = 0.;
+   m_phiHit      = 0.;
+   m_etaEntrance = 0.;
+   m_phiEntrance = 0.;
+   m_deta        = 0.;
+   m_dphi        = 0.;
+   m_PCA         = 0;
+
+   m_etaCenter = 0.;
+   m_phiCenter = 0.;
+   m_etaShift  = 0.;
+   m_phiShift  = 0.;
+   m_cellr     = 0.;
+   m_cellz     = 0.;
+   m_celleta   = 0.;
+   m_cellDeta  = 0.;
+   m_cellDphi  = 0.;
+
+   hitsNtuple->SetBranchAddress("eventNumber", &m_eventNumber);
+   hitsNtuple->SetBranchAddress("energy_hit", &m_energy);
+   hitsNtuple->SetBranchAddress("eta_hit", &m_etaHit);
+   hitsNtuple->SetBranchAddress("phi_hit", &m_phiHit);
+   hitsNtuple->SetBranchAddress("eta_entrance", &m_etaEntrance);
+   hitsNtuple->SetBranchAddress("phi_entrance", &m_phiEntrance);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("delta_phi", &m_dphi);
+   hitsNtuple->SetBranchAddress("delta_eta", &m_deta);
+   hitsNtuple->SetBranchAddress("pca_bin", &m_PCA);
+
+   globalNtuple->SetBranchAddress("eta_center", &m_etaCenter);
+   globalNtuple->SetBranchAddress("phi_center", &m_phiCenter);
+   globalNtuple->SetBranchAddress("eta_shift", &m_etaShift);
+   globalNtuple->SetBranchAddress("phi_shift", &m_phiShift);
+   globalNtuple->SetBranchAddress("cell_r", &m_cellr);
+   globalNtuple->SetBranchAddress("cell_z", &m_cellz);
+   globalNtuple->SetBranchAddress("cell_eta", &m_celleta);
+   globalNtuple->SetBranchAddress("cell_deta", &m_cellDeta);
+   globalNtuple->SetBranchAddress("cell_dphi", &m_cellDphi);
+}
+
+
+void ShowerShapeThinning::BookHitsAlphaDrTree(TTree *hitsNtuple)
+{
+   m_eventNumber = -1;
+   m_alpha       = 0.;
+   m_dr          = 0.;
+
+
+   hitsNtuple->Branch("eventNumber", &m_eventNumber);
+   hitsNtuple->Branch("energy", &m_energy);
+   hitsNtuple->Branch("alpha", &m_alpha);
+   hitsNtuple->Branch("dr", &m_dr);
+}
+
+
+float ShowerShapeThinning::DeltaPhi(float phi1, float phi2)
+{
+   double result = phi1 - phi2;
+
+   while (result > TMath::Pi())
+   {
+      result -= 2 * TMath::Pi();
+   }
+   while (result <= -TMath::Pi())
+   {
+      result += 2 * TMath::Pi();
+   }
+   return result;
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..4679991d0bb900466cd94b4d0385719c6fbd8380
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/ShowerShapeThinning.h
@@ -0,0 +1,151 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ShowerShapeThinning_h
+#define ShowerShapeThinning_h
+
+#include "TChain.h"
+#include "TTree.h"
+#include "TH1.h"
+
+#include "tools/FCS_Cell.h"
+
+
+
+class ShowerShapeThinning
+{
+public:
+
+
+   ShowerShapeThinning();
+   ShowerShapeThinning(TChain *chain, TTree *tree);
+   ~ShowerShapeThinning();
+
+
+
+   void CreateHitsNtuple(TFile *file);
+
+   void CreateHitsAlphaDrNtuple(std::string);
+
+   std::vector<float> Getxbins(TH1F *histo, int nbins);
+
+   vector<int> GetPCAbins();
+   void GetCellGeom(float etacentre, float phicentre);
+
+   std::tuple<float, float> GetUnitsmm(float eta_hits, float deta, float dphi, float cellr, float cellz);
+   void InitInputTree();
+   void BookHitsTree(TTree *, TTree *);
+   void InitHitsTree(TTree *, TTree *);
+   void BookHitsAlphaDrTree(TTree *);
+   float DeltaPhi(float, float);
+
+
+
+   // * setter methods
+   void set_calolayer(int calolayer_) { m_calolayer = calolayer_; }
+   void set_PCAbin(int PCAbin_) { m_PCAbin = PCAbin_; }
+   void set_nbinsR(int nbinsR_) { m_nbinsR = nbinsR_; }
+   void set_nbinsAlpha(int nbinsAlpha_) { m_nbinsAlpha = nbinsAlpha_; }
+   void set_mincalosize(float mincalosize_) { m_mincalosize = mincalosize_; }
+   void set_particle(string particle_) { m_particle = particle_; }
+   void set_energy(float energy_) { m_particleEnergy = energy_; }
+   void set_eta(float etamin_, float etamax_) { m_etamin = etamin_; m_etamax = etamax_; }
+   void set_tolerance(float tolerance_) { m_tolerance = tolerance_; }
+
+   void set_topDir(string topDir_) { m_topDir = topDir_; }
+   void set_fileName(string fileName_) { m_fileName = fileName_; }
+   void set_hitsNtupleName(string hitsNtupleName_) { m_hitsNtupleName = hitsNtupleName_; }
+
+
+private:
+
+   // * settings
+   int m_calolayer;
+   int m_PCAbin;
+   int m_PCA; // ttree variable
+   int m_nbinsR;
+   int m_nbinsAlpha;
+   float m_mincalosize;
+   string m_particle;
+   float m_particleEnergy; // in Gev
+   float m_etamin;
+   float m_etamax;
+   float m_tolerance;
+   string m_hitsNtupleName;
+
+   int m_debug;
+
+   TChain *m_chain;
+   TTree *m_tree;
+
+   std::string m_topDir;
+   std::string m_fileName;
+
+
+
+   // * cell geometry
+
+   float cellDeta;
+   float cellDphi;
+   float cellr;
+   float cellz;
+   float celleta;
+
+   // * reading input TTree
+
+   FCS_matchedcellvector *m_cellVector;
+   std::vector<FCS_truth> *m_truthCollection;
+   std::vector<float> *m_truthPx;
+   std::vector<float> *m_truthPy;
+   std::vector<float> *m_truthPz;
+   std::vector<float> *m_truthE;
+
+   // * for hits TTree
+   int m_eventNumber;
+   float m_energy;
+   float m_etaHit;
+   float m_phiHit;
+   float m_etaEntrance;
+   float m_phiEntrance;
+   float m_deta;
+   float m_dphi;
+
+
+   float m_etaCenter;
+   float m_phiCenter;
+   float m_etaShift;
+   float m_phiShift;
+   float m_cellr;
+   float m_cellz;
+   float m_celleta;
+   float m_cellDeta;
+   float m_cellDphi;
+
+   // * hits TTree with alpha and dr
+
+   float m_alpha;
+   float m_dr;
+
+   // * alpha and dr bin widths
+   std::vector<float> xbinsAlpha;
+   std::vector<float> ybinsR;
+
+
+   // * histograms
+
+   TH2F *halphadrE;
+
+   TH1F *h_alpha;
+   TH1F *h_dr;
+
+
+
+   ClassDef(ShowerShapeThinning, 1);
+};
+
+#if defined(__MAKECINT__)
+#pragma link C++ class ShowerShapeThinning+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/DetailedShapeBinning.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/DetailedShapeBinning.cxx
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/DetailedShapeBinning.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/DetailedShapeBinning.cxx
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/DetailedShapeBinning.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/DetailedShapeBinning.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/DetailedShapeBinning.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/DetailedShapeBinning.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/FitDetailedShape.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/FitDetailedShape.cxx
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/FitDetailedShape.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/FitDetailedShape.cxx
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FitDetailedShape.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/FitDetailedShape.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FitDetailedShape.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/FitDetailedShape.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunction.cxx
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunction.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunction.cxx
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunction.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunction.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunction.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunctionRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunctionRegression.cxx
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunctionRegression.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunctionRegression.cxx
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunctionRegression.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2DFunctionRegression.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2Function.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2Function.cxx
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2Function.cxx
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2Function.cxx
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2Function.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2Function.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2Function.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/shapepara/old/TFCS2Function.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_ntuple.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_ntuple.py
index f7c63f00997a6d67e507a1e04d8661e53ff7bf53..a5d4fad17e3c8a9c9b7248510dc3160d78744ff9 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_ntuple.py
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/ISF_ntuple.py
@@ -94,6 +94,13 @@ FCSgeoHelper=FastCaloSimGeometryHelper()
 ToolSvc+=FCSgeoHelper
 ISF_HitAnalysis.CaloGeometryHelper=FCSgeoHelper
 
+from AthenaCommon.CfgGetter import getPublicTool
+#ISF_HitAnalysis.FastCaloSimCaloExtrapolation= 'ISF_FastCaloSimCaloExtrapolation'
+ISF_HitAnalysis.FastCaloSimCaloExtrapolation= getPublicTool('ISF_FastCaloSimCaloExtrapolation')
+ISF_HitAnalysis.FastCaloSimCaloExtrapolation.OutputLevel = DEBUG
+ToolSvc.ISF_FastCaloSimCaloExtrapolation.OutputLevel = DEBUG
+
+
 from GaudiSvc.GaudiSvcConf import THistSvc
 ServiceMgr += THistSvc()
 #name the output file here
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
index 5ac7ff959dd9fcf420607736c021cdaac11aacd2..b29503c6fd6e4e2af40c798401e9a18fbf3792ea 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
@@ -12,7 +12,8 @@
 #include <TVector3.h>
 #include <TLegend.h>
 
-#include "CaloDetDescr/CaloDetDescrElement.h"
+//#include "CaloDetDescr/CaloDetDescrElement.h"
+#include "ISF_FastCaloSimParametrization/CaloDetDescrElement.h"
 #include "CaloGeoHelpers/CaloSampling.h"
 #include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 //#include "TMVA/Tools.h"
@@ -59,7 +60,7 @@ bool CaloGeometryLookup::has_overlap(CaloGeometryLookup* ref)
 {
   if(m_cells.size()==0) return false;
   for(t_cellmap::iterator ic=m_cells.begin();ic!=m_cells.end();++ic) {
-    const CaloDetDescrElement* cell=ic->second;
+    const CaloGeoDetDescrElement* cell=ic->second;
     if(ref->IsCompatible(cell)) return true;
   }
   return false;
@@ -68,17 +69,17 @@ bool CaloGeometryLookup::has_overlap(CaloGeometryLookup* ref)
 void CaloGeometryLookup::merge_into_ref(CaloGeometryLookup* ref)
 {
   for(t_cellmap::iterator ic=m_cells.begin();ic!=m_cells.end();++ic) {
-    const CaloDetDescrElement* cell=ic->second;
+    const CaloGeoDetDescrElement* cell=ic->second;
     ref->add(cell);
   }
 }
 
 
-bool CaloGeometryLookup::IsCompatible(const CaloDetDescrElement* cell)
+bool CaloGeometryLookup::IsCompatible(const CaloGeoDetDescrElement* cell)
 {
   if(m_cells.size()==0) return true;
   t_cellmap::iterator ic=m_cells.begin();
-  const CaloDetDescrElement* refcell=ic->second;
+  const CaloGeoDetDescrElement* refcell=ic->second;
   int sampling=refcell->getSampling();
   if(cell->getSampling()!=sampling) return false;
   if(cell->eta_raw()*refcell->eta_raw()<0) return false;
@@ -124,7 +125,7 @@ bool CaloGeometryLookup::IsCompatible(const CaloDetDescrElement* cell)
   return true;  
 }
 
-void CaloGeometryLookup::add(const CaloDetDescrElement* cell)
+void CaloGeometryLookup::add(const CaloGeoDetDescrElement* cell)
 {
   if(cell->getSampling()<21) {
     m_deta.add(cell->deta());
@@ -193,7 +194,7 @@ void CaloGeometryLookup::post_process()
 {
   if(size()==0) return;
   t_cellmap::iterator ic=m_cells.begin();
-  const CaloDetDescrElement* refcell=ic->second;
+  const CaloGeoDetDescrElement* refcell=ic->second;
   int sampling=refcell->getSampling();
   if(sampling<21) {
     double rneta=neta_double()-neta();
@@ -262,10 +263,10 @@ void CaloGeometryLookup::post_process()
       }
     }
   }  
-  //cout<<"Grid: Sampling "<<sampling<<"_"<<index()<<": "<<ncells<<"/"<<size()<<" cells filled, "<<nempty<<" empty grid positions"<<endl;
+  //  cout<<"Grid: Sampling "<<sampling<<"_"<<index()<<": "<<ncells<<"/"<<size()<<" cells filled, "<<nempty<<" empty grid positions deta="<<m_deta_double<<" dphi="<<m_dphi_double<<endl;
 }
 
-float CaloGeometryLookup::calculate_distance_eta_phi(const CaloDetDescrElement* DDE,float eta,float phi,float& dist_eta0,float& dist_phi0)
+float CaloGeometryLookup::calculate_distance_eta_phi(const CaloGeoDetDescrElement* DDE,float eta,float phi,float& dist_eta0,float& dist_phi0)
 {
   dist_eta0=(eta - DDE->eta())/m_deta_double;
   dist_phi0=(TVector2::Phi_mpi_pi(phi - DDE->phi()))/m_dphi_double;
@@ -274,10 +275,10 @@ float CaloGeometryLookup::calculate_distance_eta_phi(const CaloDetDescrElement*
   return TMath::Max(abs_dist_eta0,abs_dist_phi0)-0.5;
 }
 
-const CaloDetDescrElement* CaloGeometryLookup::getDDE(float eta,float phi,float* distance,int* steps) 
+const CaloGeoDetDescrElement* CaloGeometryLookup::getDDE(float eta,float phi,float* distance,int* steps) 
 {
   float dist;
-  const CaloDetDescrElement* bestDDE=0;
+  const CaloGeoDetDescrElement* bestDDE=0;
   if(!distance) distance=&dist;
   *distance=+10000000;
   int intsteps=0;
@@ -293,7 +294,7 @@ const CaloDetDescrElement* CaloGeometryLookup::getDDE(float eta,float phi,float*
   int iphi=raw_phi_position_to_index(raw_phi);
   index_range_adjust(ieta,iphi);
   
-  const CaloDetDescrElement* newDDE=m_cell_grid[ieta][iphi];
+  const CaloGeoDetDescrElement* newDDE=m_cell_grid[ieta][iphi];
   float bestdist=+10000000;
   ++(*steps);
   int nsearch=0;
@@ -316,7 +317,7 @@ const CaloDetDescrElement* CaloGeometryLookup::getDDE(float eta,float phi,float*
     ieta+=TMath::Nint(dist_eta0);
     iphi+=TMath::Nint(dist_phi0);
     index_range_adjust(ieta,iphi);
-    const CaloDetDescrElement* oldDDE=newDDE;
+    const CaloGeoDetDescrElement* oldDDE=newDDE;
     newDDE=m_cell_grid[ieta][iphi];
     ++(*steps);
     ++nsearch;
@@ -364,6 +365,8 @@ const CaloDetDescrElement* CaloGeometryLookup::getDDE(float eta,float phi,float*
   return bestDDE;
 }
 
+
+
 /*
 void CaloGeometryLookup::CalculateTransformation()
 {
@@ -381,7 +384,7 @@ void CaloGeometryLookup::CalculateTransformation()
 
   int sampling=0;
   for(t_cellmap::iterator ic=m_cells.begin();ic!=m_cells.end();++ic) {
-    CaloDetDescrElement* refcell=ic->second;
+    CaloGeoDetDescrElement* refcell=ic->second;
     sampling=refcell->getSampling();
     if(sampling<21) {
       eta=refcell->eta();
@@ -437,7 +440,7 @@ void CaloGeometryLookup::CalculateTransformation()
 }
 */
 
-CaloGeometry::CaloGeometry() : m_cells_in_sampling(MAX_SAMPLING),m_cells_in_sampling_for_phi0(MAX_SAMPLING),m_cells_in_regions(MAX_SAMPLING),m_isCaloBarrel(MAX_SAMPLING),m_dographs(false)
+CaloGeometry::CaloGeometry() : m_cells_in_sampling(MAX_SAMPLING),m_cells_in_sampling_for_phi0(MAX_SAMPLING),m_cells_in_regions(MAX_SAMPLING),m_isCaloBarrel(MAX_SAMPLING),m_dographs(false),m_FCal_ChannelMap(0)
 {
   //TMVA::Tools::Instance();
   for(int i=0;i<2;++i) {
@@ -463,13 +466,16 @@ CaloGeometry::~CaloGeometry()
 {
 }
 
-void CaloGeometry::addcell(const CaloDetDescrElement* cell) 
+void CaloGeometry::addcell(const CaloGeoDetDescrElement* cell) 
 {
   int sampling=cell->getSampling();
   Identifier identify=cell->identify();
   
-  m_cells[identify]=cell;
-  m_cells_in_sampling[sampling][identify]=cell;
+  //m_cells[identify]=cell;
+  //m_cells_in_sampling[sampling][identify]=cell;
+  
+  m_cells[identify]= new CaloGeoDetDescrElement(*cell);
+  m_cells_in_sampling[sampling][identify]= new CaloGeoDetDescrElement(*cell);
   
   CaloGeometryLookup* lookup=0;
   for(unsigned int i=0;i<m_cells_in_regions[sampling].size();++i) {
@@ -610,7 +616,7 @@ void CaloGeometry::InitRZmaps()
   }  
 
   for(t_cellmap::iterator calo_iter=m_cells.begin();calo_iter!=m_cells.end();++calo_iter) {
-    const CaloDetDescrElement* theDDE=(*calo_iter).second;
+    const CaloGeoDetDescrElement* theDDE=(*calo_iter).second;
     if(theDDE) {
       ++nok;
       int sample=theDDE->getSampling();
@@ -761,7 +767,7 @@ TCanvas* CaloGeometry::DrawGeoForPhi0()
     cout<<"Start sample "<<sample<<" ("<<SamplingName(sample)<<")"<<endl;
     int ngr=0;
     for(t_eta_cellmap::iterator calo_iter=m_cells_in_sampling_for_phi0[sample].begin();calo_iter!=m_cells_in_sampling_for_phi0[sample].end();++calo_iter) {
-      const CaloDetDescrElement* theDDE=(*calo_iter).second;
+      const CaloGeoDetDescrElement* theDDE=(*calo_iter).second;
       if(theDDE) {
         TVector3 cv;
         TGraph* gr=new TGraph(5);
@@ -846,19 +852,23 @@ TCanvas* CaloGeometry::DrawGeoForPhi0()
   return c;
 }
 
-const CaloDetDescrElement* CaloGeometry::getDDE(Identifier identify) 
+const CaloGeoDetDescrElement* CaloGeometry::getDDE(Identifier identify) 
 {
   return m_cells[identify];
 }
+const CaloGeoDetDescrElement* CaloGeometry::getDDE(int sampling,Identifier identify) 
+{
+  return m_cells_in_sampling[sampling][identify];
+}
 
-const CaloDetDescrElement* CaloGeometry::getDDE(int sampling,float eta,float phi,float* distance,int* steps) 
+const CaloGeoDetDescrElement* CaloGeometry::getDDE(int sampling,float eta,float phi,float* distance,int* steps) 
 {
   if(sampling<0) return 0;
   if(sampling>=MAX_SAMPLING) return 0;
   if(m_cells_in_regions[sampling].size()==0) return 0;
   
   float dist;
-  const CaloDetDescrElement* bestDDE=0;
+  const CaloGeoDetDescrElement* bestDDE=0;
   if(!distance) distance=&dist;
   *distance=+10000000;
   int intsteps;
@@ -879,7 +889,7 @@ const CaloDetDescrElement* CaloGeometry::getDDE(int sampling,float eta,float phi
           cout<<"CaloGeometry::getDDE : check map"<<j<<" skip_range_check="<<skip_range_check<<endl;
         }
         float newdist;
-        const CaloDetDescrElement* newDDE=m_cells_in_regions[sampling][j]->getDDE(eta,phi,&newdist,&intsteps);
+        const CaloGeoDetDescrElement* newDDE=m_cells_in_regions[sampling][j]->getDDE(eta,phi,&newdist,&intsteps);
         if(m_debug) {
           cout<<"CaloGeometry::getDDE : map"<<j<<" dist="<<newdist<<" best dist="<<*distance<<" steps="<<intsteps<<endl;
         }
@@ -893,38 +903,59 @@ const CaloDetDescrElement* CaloGeometry::getDDE(int sampling,float eta,float phi
       if(bestDDE) break;
     }
   } else {
-    for(int skip_range_check=0;skip_range_check<=1;++skip_range_check) {
-      for(unsigned int j=0;j<m_cells_in_regions[sampling].size();++j) {
-        if(!skip_range_check) {
-          if(eta<m_cells_in_regions[sampling][j]->minx()) continue;
-          if(eta>m_cells_in_regions[sampling][j]->maxx()) continue;
-          if(phi<m_cells_in_regions[sampling][j]->miny()) continue;
-          if(phi>m_cells_in_regions[sampling][j]->maxy()) continue;
-        }  
-        if(steps) intsteps=*steps;
-         else intsteps=0;
-        if(m_debug) {
-          cout<<"CaloGeometry::getDDE : check map"<<j<<" skip_range_check="<<skip_range_check<<endl;
-        }
-        float newdist;
-        const CaloDetDescrElement* newDDE=m_cells_in_regions[sampling][j]->getDDE(eta,phi,&newdist,&intsteps);
-        if(m_debug) {
-          cout<<"CaloGeometry::getDDE : map"<<j<<" dist="<<newdist<<" best dist="<<*distance<<" steps="<<intsteps<<endl;
-        }
-        if(newdist<*distance) {
-          bestDDE=newDDE;
-          *distance=newdist;
-          if(steps) beststeps=intsteps;
-          if(newdist<-0.1) break; //stop, we are well within the hit cell
-        }
-      }
-      if(bestDDE) break;
-    }  
+		return 0;
+    //for(int skip_range_check=0;skip_range_check<=1;++skip_range_check) {
+      //for(unsigned int j=0;j<m_cells_in_regions[sampling].size();++j) {
+        //if(!skip_range_check) {
+          //if(eta<m_cells_in_regions[sampling][j]->minx()) continue;
+          //if(eta>m_cells_in_regions[sampling][j]->maxx()) continue;
+          //if(phi<m_cells_in_regions[sampling][j]->miny()) continue;
+          //if(phi>m_cells_in_regions[sampling][j]->maxy()) continue;
+        //}  
+        //if(steps) intsteps=*steps;
+         //else intsteps=0;
+        //if(m_debug) {
+          //cout<<"CaloGeometry::getDDE : check map"<<j<<" skip_range_check="<<skip_range_check<<endl;
+        //}
+        //float newdist;
+        //const CaloGeoDetDescrElement* newDDE=m_cells_in_regions[sampling][j]->getDDE(eta,phi,&newdist,&intsteps);
+        //if(m_debug) {
+          //cout<<"CaloGeometry::getDDE : map"<<j<<" dist="<<newdist<<" best dist="<<*distance<<" steps="<<intsteps<<endl;
+        //}
+        //if(newdist<*distance) {
+          //bestDDE=newDDE;
+          //*distance=newdist;
+          //if(steps) beststeps=intsteps;
+          //if(newdist<-0.1) break; //stop, we are well within the hit cell
+        //}
+      //}
+      //if(bestDDE) break;
+    //}  
   }
   if(steps) *steps=beststeps;
   return bestDDE;
 }
 
+const CaloGeoDetDescrElement* CaloGeometry::getFCalDDE(int sampling,float x,float y,float z){
+		int isam = sampling - 20;
+		int iphi,ieta;
+		Long64_t mask1[]{0x34,0x34,0x35};
+		Long64_t mask2[]{0x36,0x36,0x37};
+		m_FCal_ChannelMap.getTileID(isam, x, y, ieta, iphi);
+		//cout << ieta << ""
+		Long64_t id = (ieta << 5) + 2*iphi;
+		if(isam==2)id+= (8<<8);
+		
+		if(z>0) id+=(mask2[isam-1] << 12);
+		else id+=(mask1[isam-1] << 12);
+		//if(z<0) cout << "CaloGeometry::getFCalDDE: Identifier: " << (id << 44) << " " << m_cells[id << 44]->identify() << endl;
+		id = id << 44; 
+		Identifier identify((unsigned long long)id);
+		return m_cells[identify];
+		//return m_cells_in_sampling[sampling][id << 12];
+}
+
+
 bool CaloGeometry::PostProcessGeometry()
 {
   for(int i=0;i<MAX_SAMPLING;++i) {
@@ -958,7 +989,7 @@ void CaloGeometry::Validate()
   int ntest=0;
   cout<<"start CaloGeometry::Validate()"<<endl;
   for(t_cellmap::iterator ic=m_cells.begin();ic!=m_cells.end();++ic) {
-    const CaloDetDescrElement* cell=ic->second;
+    const CaloGeoDetDescrElement* cell=ic->second;
     int sampling=cell->getSampling();
     if(sampling>=21) continue;
 
@@ -973,7 +1004,7 @@ void CaloGeometry::Validate()
       float eta=cell->eta()+1.5*(gRandom->Rndm()-0.5)*cell->deta();
       float phi=cell->phi()+1.5*(gRandom->Rndm()-0.5)*cell->dphi();
       float distance;
-      const CaloDetDescrElement* foundcell=getDDE(sampling,eta,phi,&distance,&steps);
+      const CaloGeoDetDescrElement* foundcell=getDDE(sampling,eta,phi,&distance,&steps);
       if(m_debug && foundcell) {
         cout<<"CaloGeometry::Validate(), irnd="<<irnd<<", foundcell id="<<foundcell->identify()<<", "<<steps<<" steps"<<endl; 
       }  
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromCaloDDM.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromCaloDDM.cxx
index 28aca4bf137ce3ccf54a47e59b13fa53939074d1..31b8d21fde64563eb6e3a77b0db425ed993bbbee 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromCaloDDM.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromCaloDDM.cxx
@@ -3,7 +3,8 @@
 */
 
 #include "CaloGeometryFromCaloDDM.h"
-#include "CaloDetDescr/CaloDetDescrElement.h"
+//#include "CaloDetDescr/CaloDetDescrElement.h"
+#include "ISF_FastCaloSimParametrization/CaloDetDescrElement.h"
 #include "CaloDetDescr/CaloDetDescrManager.h"
 
 using namespace std;
@@ -19,15 +20,15 @@ CaloGeometryFromCaloDDM::~CaloGeometryFromCaloDDM()
 bool CaloGeometryFromCaloDDM::LoadGeometryFromCaloDDM(const CaloDetDescrManager* calo_dd_man)
 {
   int jentry=0;
-  for(CaloDetDescrManager::calo_element_const_iterator calo_iter=calo_dd_man->element_begin();calo_iter<calo_dd_man->element_end();++calo_iter) {
-    const CaloDetDescrElement* pcell=*calo_iter;
-    addcell(pcell);
-
-    if(jentry%25000==0) {
-      cout<<jentry<<" : "<<pcell->getSampling()<<", "<<pcell->identify()<<endl;
-    }
-    ++jentry;
-  }
+  //for(CaloDetDescrManager::calo_element_const_iterator calo_iter=calo_dd_man->element_begin();calo_iter<calo_dd_man->element_end();++calo_iter) {
+    //const CaloGeoDetDescrElement* pcell=*calo_iter;
+    //addcell(pcell);
+
+    //if(jentry%25000==0) {
+      //cout<<jentry<<" : "<<pcell->getSampling()<<", "<<pcell->identify()<<endl;
+    //}
+    //++jentry;
+  //}
 
   return PostProcessGeometry();
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromFile.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromFile.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6fd5d3037c1862ef35b1d84ed2675aaaa61ceb1d
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometryFromFile.cxx
@@ -0,0 +1,363 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimParametrization/CaloGeometryFromFile.h"
+#include <TTree.h>
+#include <TFile.h>
+#include "ISF_FastCaloSimParametrization/CaloDetDescrElement.h"
+#include <fstream>
+#include <sstream>
+#include <TGraph.h>
+#include "TH2D.h"
+
+#include <fstream>
+#include <map>
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+map<unsigned long long, unsigned long long> g_cellId_vs_cellHashId_map;
+
+CaloGeometryFromFile::CaloGeometryFromFile() : CaloGeometry()
+{
+	ifstream textfile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSimV2/cellId_vs_cellHashId_map.txt");
+	unsigned long long id, hash_id; 
+	cout << "Loading cellId_vs_cellHashId_map" << endl;
+	int i=0;
+	string line;
+	stringstream s;
+	while(1){
+		//getline(textfile,line);
+		s.str(line);
+	  textfile >> id;
+		if(textfile.eof())break;
+		textfile >> hash_id;
+		g_cellId_vs_cellHashId_map[id]=hash_id;
+		if(i%10000==0)cout << "Line: " << i << " line " << line << " id " << hex << id << " hash_id " << dec << hash_id << endl;
+		i++;
+	}
+	cout << "Done." << endl;
+	
+}
+
+CaloGeometryFromFile::~CaloGeometryFromFile()
+{
+}
+
+bool CaloGeometryFromFile::LoadGeometryFromFile(TString filename,TString treename)
+{
+  TTree *tree;
+  TFile *f = TFile::Open(filename);
+  if(!f) return false;
+  f->GetObject(treename,tree);
+  if(!tree) return false;
+
+  TTree* fChain = tree;
+  
+  CaloGeoDetDescrElement cell;
+  
+  // List of branches
+  TBranch        *b_identifier;   //!
+  TBranch        *b_calosample;   //!
+  TBranch        *b_eta;   //!
+  TBranch        *b_phi;   //!
+  TBranch        *b_r;   //!
+  TBranch        *b_eta_raw;   //!
+  TBranch        *b_phi_raw;   //!
+  TBranch        *b_r_raw;   //!
+  TBranch        *b_x;   //!
+  TBranch        *b_y;   //!
+  TBranch        *b_z;   //!
+  TBranch        *b_x_raw;   //!
+  TBranch        *b_y_raw;   //!
+  TBranch        *b_z_raw;   //!
+  TBranch        *b_deta;   //!
+  TBranch        *b_dphi;   //!
+  TBranch        *b_dr;   //!
+  TBranch        *b_dx;   //!
+  TBranch        *b_dy;   //!
+  TBranch        *b_dz;   //!
+  
+  fChain->SetMakeClass(1);
+  fChain->SetBranchAddress("identifier", &cell.m_identify, &b_identifier);
+  fChain->SetBranchAddress("calosample", &cell.m_calosample, &b_calosample);
+  fChain->SetBranchAddress("eta", &cell.m_eta, &b_eta);
+  fChain->SetBranchAddress("phi", &cell.m_phi, &b_phi);
+  fChain->SetBranchAddress("r", &cell.m_r, &b_r);
+  fChain->SetBranchAddress("eta_raw", &cell.m_eta_raw, &b_eta_raw);
+  fChain->SetBranchAddress("phi_raw", &cell.m_phi_raw, &b_phi_raw);
+  fChain->SetBranchAddress("r_raw", &cell.m_r_raw, &b_r_raw);
+  fChain->SetBranchAddress("x", &cell.m_x, &b_x);
+  fChain->SetBranchAddress("y", &cell.m_y, &b_y);
+  fChain->SetBranchAddress("z", &cell.m_z, &b_z);
+  fChain->SetBranchAddress("x_raw", &cell.m_x_raw, &b_x_raw);
+  fChain->SetBranchAddress("y_raw", &cell.m_y_raw, &b_y_raw);
+  fChain->SetBranchAddress("z_raw", &cell.m_z_raw, &b_z_raw);
+  fChain->SetBranchAddress("deta", &cell.m_deta, &b_deta);
+  fChain->SetBranchAddress("dphi", &cell.m_dphi, &b_dphi);
+  fChain->SetBranchAddress("dr", &cell.m_dr, &b_dr);
+  fChain->SetBranchAddress("dx", &cell.m_dx, &b_dx);
+  fChain->SetBranchAddress("dy", &cell.m_dy, &b_dy);
+  fChain->SetBranchAddress("dz", &cell.m_dz, &b_dz);
+  
+  Long64_t nentries = fChain->GetEntriesFast();
+  for (Long64_t jentry=0; jentry<nentries;jentry++) {
+    Long64_t ientry = fChain->LoadTree(jentry);
+    if (ientry < 0) break;
+    fChain->GetEntry(jentry);
+    
+    if (g_cellId_vs_cellHashId_map.find(cell.m_identify)!=g_cellId_vs_cellHashId_map.end()) cell.m_hash_id=g_cellId_vs_cellHashId_map[cell.m_identify];
+    else cout << endl << "ERROR: Cell id not found in the cellId_vs_cellHashId_map!!!" << endl << endl;
+    
+    const CaloGeoDetDescrElement* pcell=new CaloGeoDetDescrElement(cell);
+    int sampling = pcell->getSampling();
+    
+    
+    if(sampling >20) continue;
+    this->addcell(pcell);
+		
+    if(jentry%25000==0) {
+    //if(jentry==nentries-1) {
+			cout << "Checking loading cells from file" << endl;
+      cout<<jentry<<" : "<<pcell->getSampling()<<", "<<pcell->identify()<<endl;
+
+      
+      
+      
+      //if(jentry>5) break;
+    }
+  }
+	//cout<<"all : "<<m_cells.size()<<endl;
+  //unsigned long long max(0);
+  //unsigned long long min_id=m_cells_in_sampling[0].begin()->first;
+  //for(int i=0;i<21;++i) {
+		////cout<<"  cells sampling "<<i<<" : "<<m_cells_in_sampling[i].size()<<" cells";
+		////cout<<", "<<m_cells_in_regions[i].size()<<" lookup map(s)"<<endl;
+		//for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+			////cout << it->second->getSampling() << " " << it->first << endl;
+			//if(min_id/10 >=  it->first){
+				////cout << "Warning: Identifiers are not in increasing order!!!!" << endl;
+				////cout << min_id << " " << it->first << endl;
+				
+			//}
+			//if(min_id > it->first)min_id = it->first;
+		//}
+	//}
+	//cout << "Min id for samplings < 21: " << min_id << endl;
+  delete f;
+	//return true;
+	bool ok = PostProcessGeometry();
+	
+	cout << "Result of PostProcessGeometry(): " << ok << endl;
+	const CaloGeoDetDescrElement* mcell=0;
+	unsigned long long cellid64(3179554531063103488);
+	Identifier cellid(cellid64);
+	mcell=this->getDDE(cellid); //This is working also for the FCal
+	
+	std::cout << "\n \n";
+	std::cout << "Testing whether CaloGeometry is loaded properly" << std::endl;
+	if(!mcell)std::cout << "Cell is not found" << std::endl;
+	std::cout << "Identifier " << mcell->identify() <<" sampling " << mcell->getSampling() << " eta: " << mcell->eta() << " phi: " << mcell->phi() << std::endl<< std::endl;
+	
+	const CaloGeoDetDescrElement* mcell2 = this->getDDE(mcell->getSampling(),mcell->eta(),mcell->phi());
+	std::cout << "Identifier " << mcell2->identify() <<" sampling " << mcell2->getSampling() << " eta: " << mcell2->eta() << " phi: " << mcell2->phi() << std::endl<< std::endl;
+	
+  return ok;
+}
+
+
+bool CaloGeometryFromFile::LoadFCalGeometryFromFiles(TString filename1,TString filename2,TString filename3){
+	
+	vector<ifstream*> electrodes(3);
+  
+  electrodes[0]=new ifstream(filename1);
+  electrodes[1]=new ifstream(filename2);
+  electrodes[2]=new ifstream(filename3);
+	
+	
+	int	thisTubeId;
+  int    thisTubeI;
+	int    thisTubeJ;
+	//int    thisTubeID;
+	//int    thisTubeMod;
+	double thisTubeX;
+	double thisTubeY;
+	TString tubeName;
+	
+	//int second_column;
+	string seventh_column;
+	string eight_column;
+	int ninth_column;
+
+	
+	
+	
+	
+	int i;
+	for(int imodule=1;imodule<=3;imodule++){
+		
+		i=0;
+		//while(i<50){
+		while(1){
+		
+		  //cout << electrodes[imodule-1]->eof() << endl;
+			(*electrodes[imodule-1]) >> tubeName;
+			if(electrodes[imodule-1]->eof())break;
+			(*electrodes[imodule-1]) >> thisTubeId; // ?????
+			(*electrodes[imodule-1]) >> thisTubeI;
+			(*electrodes[imodule-1]) >> thisTubeJ;
+			(*electrodes[imodule-1]) >> thisTubeX;
+			(*electrodes[imodule-1]) >> thisTubeY;
+			(*electrodes[imodule-1]) >> seventh_column;
+			(*electrodes[imodule-1]) >> eight_column;
+			(*electrodes[imodule-1]) >> ninth_column;
+			
+			tubeName.ReplaceAll("'","");
+			string tubeNamestring=tubeName.Data();
+			
+			std::istringstream tileStream1(std::string(tubeNamestring,1,1));
+		  std::istringstream tileStream2(std::string(tubeNamestring,3,2));
+		  std::istringstream tileStream3(std::string(tubeNamestring,6,3));
+		  int a1=0,a2=0,a3=0;
+		  if (tileStream1) tileStream1 >> a1;
+		  if (tileStream2) tileStream2 >> a2;
+		  if (tileStream3) tileStream3 >> a3;
+			
+			//unsigned int tileName= (a3 << 16) + a2;
+			stringstream s;
+			
+			
+			m_FCal_ChannelMap.add_tube(tubeNamestring, imodule, thisTubeId, thisTubeI,thisTubeJ, thisTubeX, thisTubeY,seventh_column);
+			
+			
+			
+			//cout << "FCal electrodes: " << tubeName << " " << second_column << " " << thisTubeI << " " << thisTubeJ << " " << thisTubeX << " " << thisTubeY << " " << seventh_column << " " << eight_column << " " << ninth_column << endl;
+			//cout << tileStream1.str() << " " << tileStream2.str() << " " << tileStream3.str() << endl;
+			//cout << a1 << " " << a2 << " " << a3 << " " << tileName << endl;
+			i++;
+		}
+	}
+	m_FCal_ChannelMap.finish(); // Creates maps
+	
+	unsigned long long phi_index,eta_index;
+	float x,y,dx,dy;
+	long id;
+	//auto it =m_cells_in_sampling[20].rbegin();
+	//it--;
+	//unsigned long long identify=it->first;
+	//for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+	//	
+	//}
+	long mask1[]{0x34,0x34,0x35};
+	long mask2[]{0x36,0x36,0x37};
+	
+	for(int imap=1;imap<=3;imap++){
+		for(auto it=m_FCal_ChannelMap.begin(imap);it!=m_FCal_ChannelMap.end(imap);it++){
+			phi_index = it->first & 0xffff;
+			eta_index = it->first >> 16;
+			CaloGeoDetDescrElement *DDE =new CaloGeoDetDescrElement; // side C
+			CaloGeoDetDescrElement *DDE2 =new CaloGeoDetDescrElement; // side A
+			x=it->second.x();
+			y=it->second.y();
+			m_FCal_ChannelMap.tileSize(imap, eta_index, phi_index,dx,dy);
+			//if(imap==2) eta_index+=100;
+			//if(imap==3) eta_index+=200;
+			//cout << imap << " " << eta_index << " " << phi_index << " " <<  it->first << " " << (eta_index << 16) + phi_index << endl;
+			
+			DDE->m_calosample=imap+20;
+			DDE->m_x=x;
+			DDE->m_y=y;
+			DDE->m_x_raw=x;
+			DDE->m_y_raw=y;
+			DDE->m_dx=dx;
+			DDE->m_dy=dy;
+			
+			DDE2->m_calosample=imap+20;
+			DDE2->m_x=x;
+			DDE2->m_y=y;
+			DDE2->m_x_raw=x;
+			DDE2->m_y_raw=y;
+			DDE2->m_dx=dx;
+			DDE2->m_dy=dy;
+			
+			id=(mask1[imap-1]<<12) + (eta_index << 5) +2*phi_index;
+			if(imap==2) id+= (8<<8);
+			DDE->m_identify=(id << 44);
+			//DDE->m_identify=(id << 12);
+			//cout << DDE->identify() << endl;
+			if (g_cellId_vs_cellHashId_map.find(DDE->m_identify)!=g_cellId_vs_cellHashId_map.end()) DDE->m_hash_id=g_cellId_vs_cellHashId_map[DDE->m_identify];
+			else cout << endl << "ERROR: Cell id not found in the cellId_vs_cellHashId_map!!!" << endl << endl;
+			
+			addcell(DDE);
+			id=(mask2[imap-1]<<12) + (eta_index << 5) +2*phi_index;
+			if(imap==2) id+= (8<<8);
+			DDE2->m_identify=(id << 44);
+						//DDE->m_identify=(id << 12);
+			if (g_cellId_vs_cellHashId_map.find(DDE2->m_identify)!=g_cellId_vs_cellHashId_map.end()) DDE2->m_hash_id=g_cellId_vs_cellHashId_map[DDE2->m_identify];
+			else cout << endl << "ERROR: Cell id not found in the cellId_vs_cellHashId_map!!!" << endl << endl;
+			addcell(DDE2);
+		}
+	
+	}
+	//auto it =m_cells_in_sampling[0].begin();
+	//it--;
+	//unsigned long long identify=it->first;
+	////cout << "min identifier from sampling < 21: " << identify << endl;
+	
+	for(int i=0;i<21;++i) {
+	//for(int i=21;i<MAX_SAMPLING;++i) {
+        cout<<"  cells sampling "<<i<<" : "<<m_cells_in_sampling[i].size()<<" cells";
+        cout<<", "<<m_cells_in_regions[i].size()<<" lookup map(s)"<<endl;
+        int k=0;
+        for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+					if(k<10){
+						cout << "  cells sampling "<< it->second->getSampling() << " : " << it->first << endl;
+						const CaloGeoDetDescrElement *DDE = this->getDDE(it->second->getSampling(),it->second->eta(),it->second->phi());
+						cout << "  cells sampling "<< DDE->getSampling()  << " : " << DDE->identify()  << endl;
+						DDE = this->getDDE(it->first);
+						cout << "  cells sampling "<< DDE->getSampling()  << " : " << DDE->identify() << endl << endl;
+					}
+					k++;
+				}
+        
+  }
+	return true;
+}
+
+void CaloGeometryFromFile::DrawFCalGraph(int isam,int color){
+	
+	stringstream ss;
+	ss << "FCal" << isam - 20 << endl;
+	TString name = ss.str().c_str();
+	
+	const int size=m_cells_in_sampling[isam].size();
+	double x[size];
+	double y[size];
+	//const CaloGeoDetDescrElement* cell;
+	int i=0;
+	for(auto it=m_cells_in_sampling[isam].begin();it!=m_cells_in_sampling[isam].end();it++){
+		x[i]=it->second->x();
+		y[i]=it->second->y();
+		i++;
+	}
+	// cout << size << endl;
+	//TH2D* h = new TH2D("","",10,-0.5,0.5,10,-0.5,0.5);
+	//h->SetStats(0);
+	//h->Draw();
+	TGraph* graph = new TGraph(size,x,y);
+	graph->SetLineColor(color);
+	graph->SetTitle(name);
+	graph->SetMarkerStyle(21);
+	graph->SetMarkerColor(color);
+	graph->SetMarkerSize(0.5);
+	graph->GetXaxis()->SetTitle("x");
+	graph->GetYaxis()->SetTitle("y");
+	
+	graph->Draw("AP");
+
+	
+	
+}	
+		
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FCAL_ChannelMap.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FCAL_ChannelMap.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..7171f9893815099da1c2b09788d0994b1ec8720a
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FCAL_ChannelMap.cxx
@@ -0,0 +1,491 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ***************************************************************************
+// Liquid Argon FCAL detector description package
+// -----------------------------------------
+// Copyright (C) 1998 by ATLAS Collaboration
+//
+//
+// 10-Sep-2000 S.Simion   Handling of the FCAL read-out identifiers
+//    Jan-2001 R.Sobie    Modify for persistency
+//    Feb-2002 R.Sobie    Use same FCAL geometry files as simulation 
+//****************************************************************************
+
+#include "ISF_FastCaloSimParametrization/FCAL_ChannelMap.h"
+//#include "CLHEP/Units/SystemOfUnits.h"
+//#include "boost/io/ios_state.hpp"
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include <stdio.h>
+
+/* === Geometrical parameters === */
+//const double cm = 0.01;
+const double cm = 10.;
+//const double FCAL_ChannelMap::m_tubeSpacing[] = {0.75*CLHEP::cm, 0.8179*CLHEP::cm, 0.90*CLHEP::cm};
+const double FCAL_ChannelMap::m_tubeSpacing[] = {0.75*cm, 0.8179*cm, 0.90*cm};
+
+FCAL_ChannelMap::FCAL_ChannelMap( int flag)          
+{
+
+  /* === Initialize geometrical dimensions */
+  for(int i=0; i<3; i++){
+    m_tubeDx[i] = m_tubeSpacing[i] / 2.;
+    m_tubeDy[i] = m_tubeSpacing[i] * sqrt(3.)/2.;
+  }
+
+  // FCAL1 small cells are 2x2 tubes
+  m_tileDx[0] = 2. * m_tubeSpacing[0];
+  m_tileDy[0] = 2. * m_tubeSpacing[0] * sqrt(3.)/2.;
+  
+  // FCAL2 small cells are 2x3 tubes
+  m_tileDx[1] = 2. * m_tubeSpacing[1];
+  m_tileDy[1] = 3. * m_tubeSpacing[1] * sqrt(3.)/2.;
+
+  // FCAL3 cells are 6x6 tubes
+  m_tileDx[2] = 6. * m_tubeSpacing[2];
+  m_tileDy[2] = 6. * m_tubeSpacing[2] * sqrt(3.)/2.;
+
+
+  m_invert_x = flag & 1; 
+  m_invert_xy = flag & 2; 
+
+}
+
+
+void FCAL_ChannelMap::finish() {
+  create_tileMap(1);
+  create_tileMap(2);
+  create_tileMap(3);
+}
+
+// *********************************************************************
+// Read tube mapping tables
+//
+// Jan 23,2002    R. Sobie
+// ********************************************************************
+
+
+//original
+void FCAL_ChannelMap::add_tube(const std::string & tileName, int mod, int /*id*/, int i, int j, double x, double y) {
+
+  // Get three integers from the tileName:
+  std::istringstream tileStream1(std::string(tileName,1,1));
+  std::istringstream tileStream2(std::string(tileName,3,2));
+  std::istringstream tileStream3(std::string(tileName,6,3));
+  int a1=0,a2=0,a3=0;
+  if (tileStream1) tileStream1 >> a1;
+  if (tileStream2) tileStream2 >> a2;
+  if (tileStream3) tileStream3 >> a3;
+
+  tileName_t tilename = (a3 << 16) + a2;
+
+  TubePosition tb(tilename, x*cm, y*cm,"");
+  // Add offsets, becaues iy and ix can be negative HMA
+  
+  i = i+200;
+  j = j+200;
+  //  m_tubeMap[mod-1][(j <<  16) + i] = tb;
+  unsigned int ThisId = (j<<16) + i;
+  tubemap_const_iterator p = m_tubeMap[mod-1].insert(m_tubeMap[mod-1].end(),std::make_pair(ThisId,tb));
+  m_tubeIndex[mod-1].push_back(p);
+}
+
+
+//Gabe: new to include HV and LARFCALELECRTODES ID
+void FCAL_ChannelMap::add_tube(const std::string & tileName, int mod, int /*id*/, int i, int j, double x, double y, std::string hvFT) {
+
+  // Get three integers from the tileName:
+  std::istringstream tileStream1(std::string(tileName,1,1));
+  std::istringstream tileStream2(std::string(tileName,3,2));
+  std::istringstream tileStream3(std::string(tileName,6,3));
+  int a1=0,a2=0,a3=0;
+  if (tileStream1) tileStream1 >> a1;
+  if (tileStream2) tileStream2 >> a2;
+  if (tileStream3) tileStream3 >> a3;
+
+  tileName_t tilename = (a3 << 16) + a2;
+
+  TubePosition tb(tilename, x*cm,y*cm, hvFT);
+  // Add offsets, becaues iy and ix can be negative HMA
+  
+  i = i+200;
+  j = j+200;
+  //  m_tubeMap[mod-1][(j <<  16) + i] = tb;
+  unsigned int ThisId = (j<<16) + i;
+  tubemap_const_iterator p = m_tubeMap[mod-1].insert(m_tubeMap[mod-1].end(),std::make_pair(ThisId,tb));
+  m_tubeIndex[mod-1].push_back(p);
+}
+
+FCAL_ChannelMap::tubemap_const_iterator FCAL_ChannelMap::getTubeByCopyNumber( int isam, int copyNo) const {
+  return m_tubeIndex[isam-1][copyNo];
+}
+
+
+// *********************************************************************
+// Create tile mapping tables
+//
+// Jan 23,2002    R. Sobie
+// ********************************************************************
+void
+FCAL_ChannelMap::create_tileMap(int isam)
+{
+  tileMap_const_iterator tile;
+  tubemap_const_iterator first = m_tubeMap[isam-1].begin();
+  tubemap_const_iterator  last = m_tubeMap[isam-1].end();
+
+  // Loop over tubes -> find unique tiles and fill the descriptors
+  while (first != last){
+
+    tileName_t tileName = (first->second).get_tileName();
+    tile                = m_tileMap[isam-1].find(tileName);
+
+    if (tile == m_tileMap[isam-1].end()){             // New tile found
+      float x             = (first->second).x();
+      float y             = (first->second).y();
+      unsigned int ntubes = 1;
+      TilePosition tp(x, y, ntubes);
+      m_tileMap[isam-1][tileName] = tp; 
+    }
+    else{                                             // Existing tile
+      float x             = (tile->second).x() + (first->second).x();
+      float y             = (tile->second).y() + (first->second).y();
+      unsigned int ntubes = (tile->second).ntubes() + 1;
+      TilePosition tp(x, y, ntubes);
+      m_tileMap[isam-1][tileName] = tp; 
+    }
+    ++first;
+  }
+
+  //
+  // List the number of tubes and tiles 
+  //
+  // std::cout << "FCAL::create_tilemap: FCAL # " << isam  
+  //	    << " Number of tiles = " << m_tileMap[isam-1].size() 
+  //	    << " Number of tubes = " << m_tubeMap[isam-1].size()
+  //	    << std::endl;
+
+  // this->print_tubemap(isam);
+  
+  
+  //
+  // loop over tiles and set (x,y) to average tile positions
+  //
+  tileMap_const_iterator tilefirst = m_tileMap[isam-1].begin();
+  tileMap_const_iterator tilelast  = m_tileMap[isam-1].end();
+  while (tilefirst != tilelast) {
+    tileName_t tileName = tilefirst->first;
+    unsigned int ntubes = (tilefirst->second).ntubes();
+    float xtubes        = (float) ntubes;
+    float x             = (tilefirst->second).x() / xtubes;
+    float y             = (tilefirst->second).y() / xtubes;
+    TilePosition tp(x, y, ntubes);
+    m_tileMap[isam-1][tileName] = tp; 
+    ++tilefirst;
+  }
+
+}
+
+//---------- for New LArFCAL_ID ------------------------ 
+
+// *********************************************************************
+//  get Tile ID
+//  
+// Original code: Stefan Simion, Randy Sobie
+// -------------------------------------------------------------------
+//   This function computes the tile identifier for any given position 
+//   Inputs:
+//   - isam the sampling number, from G3 data;
+//   - x the tube x position, in CLHEP::cm, from G3 data;
+//   - y the tube y position, in CLHEP::cm, from G3 data.
+//   Outputs:
+//   - pair of indices eta, phi 
+//
+//   Attention side-effect: x is changed by this function.
+// -------------------------------------------------------------------- 
+//   June 2002  HMA 
+// ***********************************************************************
+bool 
+FCAL_ChannelMap::getTileID(int isam, float x_orig, float y_orig, 
+	int& eta, int& phi) const throw (std::range_error) 
+{
+
+//  /* ### MIRROR for compatibility between G3 and ASCII files ### */
+
+  float x = x_orig; 
+  float y = y_orig; 
+
+  if(m_invert_xy){
+    x = y_orig; 
+    y = x_orig; 
+  } 
+
+  if(m_invert_x) x = -x;
+  
+  /* === Compute the tubeID */
+  int ktx = (int) (x / m_tubeDx[isam-1]);
+  int kty = (int) (y / m_tubeDy[isam-1]);
+  if (x < 0.) ktx--;
+  if (y < 0.) kty--;
+
+  // S.M.: in case we lookup real positions inside the Tile (not only
+  // integer grids for the tubes) half of the time we are outisde a
+  // tube bin since the integer pattern of the tubes is like in this
+  // sketch:
+  //
+  // # # # #
+  //  # # # #
+  // # # # #
+  // 
+  // in order to avoid this problem we have to make sure the integer
+  // indices for x and y have either both to be even or both to be odd
+  // (For Module 0 one has to be odd the other even ...). We take the
+  // y-index and check for odd/even and change the x-index in case
+  // it's different from the first tube in the current sampling ...
+  // 
+  // S.M. update: in case we are in a hole of the integer grid the
+  // relative x and y w.r.t to the original tube are used to assign a
+  // tube according to the hexagonal pattern.
+
+  tubemap_const_iterator  it = m_tubeMap[isam-1].begin();
+  unsigned int firstId = it->first;
+
+  // take offset from actual map 
+  int ix = ktx+((int)((firstId&0xffff)-it->second.x()/m_tubeDx[isam-1]))+1;
+  int iy = kty+((int)((firstId>>16)-it->second.y()/m_tubeDy[isam-1]))+1;
+  
+  int isOddEven = (((firstId>>16)%2)+(firstId%2))%2;
+  bool movex = false;
+
+  if ( (iy%2) != ((ix+isOddEven)%2) ) {
+    double yc = y/m_tubeDy[isam-1] - kty - 0.5;
+    if ( fabs(yc) > 0.5/sqrt(3) ) {
+      double xk = x/m_tubeDx[isam-1] - ktx;
+      if ( xk > 0.5 ) {
+	xk = 1 - xk;
+      }
+      double yn = 0.5-xk/3;
+      if ( fabs(yc) > fabs(yn) ) {
+	if ( yc > 0 ) 
+	  iy++;
+	else
+	  iy--;
+      }
+      else 
+	movex = true;
+    }
+    else 
+      movex = true;
+    if ( movex ) {
+      if ( x/m_tubeDx[isam-1] - ktx > 0.5 ) 
+	ix++;
+      else
+	ix--;
+    }
+  }
+
+  tubeID_t tubeID = (iy << 16) + ix;
+
+  it = m_tubeMap[isam-1].find(tubeID);
+  if (it != m_tubeMap[isam-1].end()){
+    tileName_t tilename = (it->second).get_tileName();
+    phi = tilename & 0xffff;
+    eta = tilename >> 16;
+    return true ;
+  } 
+  // reach here only if it failed the second time. 
+
+  return false; 
+
+}
+
+
+
+/* ----------------------------------------------------------------------
+   To decode the tile x position from the tile identifier
+   ---------------------------------------------------------------------- */
+float 
+FCAL_ChannelMap::x(int isam, int eta, int phi) const
+                                    throw(std::range_error)
+{
+  if(m_invert_xy){ 
+   // temp turn off the flag 
+   m_invert_xy=false; 
+   float y1 =  y(isam,eta,phi); 
+   m_invert_xy=true; 
+   return y1; 
+  } 
+  float x;
+
+  tileName_t tilename = (eta << 16) + phi  ; 
+
+  tileMap_const_iterator it = m_tileMap[isam-1].find(tilename);
+  if(it != m_tileMap[isam-1].end())
+  {
+    x = (it->second).x(); 
+  } else 
+  { // can't find the tile, throw exception. 
+      char l_str[200] ;
+      snprintf(l_str, sizeof(l_str),
+   "Error in FCAL_ChannelMap::x, wrong tile,phi= %d ,eta=: %d ",phi,eta);
+      std::string errorMessage(l_str);
+      throw std::range_error(errorMessage.c_str());
+  }
+
+  if(m_invert_x) {
+    return -x;
+  }
+  else {
+    return x;
+  }
+
+  return x; 
+
+}
+
+
+/* ----------------------------------------------------------------------
+   To decode the tile y position from the tile identifier
+   ---------------------------------------------------------------------- */
+float 
+FCAL_ChannelMap::y(int isam, int eta, int phi) const
+                                    throw(std::range_error)
+{
+  if(m_invert_xy){
+
+   // temp turn off the flag 
+   m_invert_xy=false; 
+   float x1 =  x(isam,eta,phi); 
+   m_invert_xy=true; 
+   return x1; 
+
+  }
+
+  float y;
+
+  tileName_t tilename = (eta << 16) + phi  ; 
+
+  tileMap_const_iterator it = m_tileMap[isam-1].find(tilename);
+  if(it != m_tileMap[isam-1].end())
+  {
+    y = (it->second).y(); 
+  } else 
+  { // can't find the tile, throw exception. 
+      char l_str[200] ;
+      snprintf(l_str, sizeof(l_str),
+   "Error in FCAL_ChannelMap::x, wrong tile,phi= %d ,eta=: %d",phi,eta);
+      std::string errorMessage(l_str);
+      throw std::range_error(errorMessage.c_str());
+  }
+
+  return y; 
+}
+
+/* ----------------------------------------------------------------------
+   To decode the tile dx size from the tile identifier
+   ---------------------------------------------------------------------- */
+
+void FCAL_ChannelMap::tileSize(int sam, int ntubes, float &dx, float &dy) const {
+
+  dx = m_tubeDx[sam-1];
+  dy = m_tubeDy[sam-1];
+  //      float ntubes =  (it->second).ntubes(); 
+  if(sam == 1 || sam == 3) { 
+    float scale =sqrt(ntubes);  
+    dx = dx * scale; 
+    dy = dy * scale; 
+  } 
+  else  {
+    float scale = sqrt(ntubes/1.5); 
+    dx = dx * scale; 
+    dy = dy * scale * 1.5 ;               
+  }
+  
+
+  // There is a fundamental discrepancy between dx and dy. A cell will
+  // contain twice as many distinct x-positions as y-positions.  Diagram:
+  
+  // . . . .        -
+  //. . . .         -
+  //  . . . .       -   4 x dy
+  // . . . .        -
+  // ||||||||             
+  //    8 x dx 
+  
+  dx = 2*dx;
+  
+  if(m_invert_xy){
+    // switch xy 
+    float temp = dx; 
+    dx = dy;
+    dy = temp;
+  } 
+  
+}
+
+void FCAL_ChannelMap::tileSize(int sam, int eta, int phi,
+	float& dx, float& dy ) const  throw(std::range_error)
+{
+  
+  tileName_t tilename = (eta << 16) + phi  ; 
+  
+  tileMap_const_iterator it = m_tileMap[sam-1].find(tilename);
+  if(it != m_tileMap[sam-1].end()) {
+    int ntubes =  (it->second).ntubes(); 
+    tileSize(sam,ntubes,dx,dy);
+    return ; 
+  }
+  else {
+    // can't find the tile, throw exception. 
+    char l_str[200] ;
+    snprintf(l_str, sizeof(l_str),
+	    "Error in FCAL_ChannelMap::tilesize, wrong tile,phi= %d ,eta=: %d ",phi,eta);
+    std::string errorMessage(l_str);
+    throw std::range_error(errorMessage.c_str());
+  }
+}
+
+
+// ********************** print_tubemap *************************************
+void
+FCAL_ChannelMap::print_tubemap( int imap) const
+{
+  FCAL_ChannelMap::tubemap_const_iterator it = m_tubeMap[imap-1].begin();
+
+  //boost::io::ios_all_saver ias (std::cout);
+  std::cout << "First 10 elements of the New FCAL tube map : " << imap << std::endl;
+  std::cout.precision(5);
+  for ( int i=0;  i<10; i++, it++)
+    std::cout << std::hex << it->first << "\t" 
+	      << (it->second).get_tileName() << std::dec <<"\t" 
+	      << (it->second).x() <<"\t" 
+	      << (it->second).y() << std::endl;
+
+}
+
+
+// ********************** tubemap_begin **************************************
+FCAL_ChannelMap::tubemap_const_iterator
+FCAL_ChannelMap::tubemap_begin (int imap ) const
+{
+  return m_tubeMap[imap-1].begin();
+}
+
+
+// ********************** tubemap_end ****************************************
+FCAL_ChannelMap::tubemap_const_iterator
+FCAL_ChannelMap::tubemap_end (int imap ) const
+{
+  return m_tubeMap[imap-1].end();
+}
+
+// ********************** tubemap_size ***************************************
+FCAL_ChannelMap::tubemap_sizetype
+FCAL_ChannelMap::tubemap_size (int imap) const
+{
+  return m_tubeMap[imap-1].size();
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
index 2e9fe8772b5804c4042bc2fe9f6dd5c3cf298270..9636aa76757f88a1536dcc2f285dae4803d9e8ea 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
@@ -2,9 +2,17 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#include "ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h"
+#include "FastCaloSimCaloExtrapolation.h"
+
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+
 #include "ISF_FastCaloSimParametrization/IFastCaloSimGeometryHelper.h"
 
+#include "TrkParameters/TrackParameters.h"
+#include "TrkGeometry/TrackingGeometry.h"
+#include "HepPDT/ParticleData.hh"
+#include "HepPDT/ParticleDataTable.hh"
+
 #include "CaloTrackingGeometry/ICaloSurfaceHelper.h"
 #include "CaloTrackingGeometry/ICaloSurfaceBuilder.h"
 #include "CaloDetDescr/ICaloCoordinateTool.h"
@@ -21,15 +29,20 @@ FastCaloSimCaloExtrapolation::FastCaloSimCaloExtrapolation(const std::string& t,
 {
   declareInterface<IFastCaloSimCaloExtrapolation>(this);
 
-  declareProperty("CaloBoundaryR", m_CaloBoundaryR);
-  declareProperty("CaloBoundaryZ", m_CaloBoundaryZ);
-  declareProperty("CaloMargin", m_calomargin);
-  //######################
+  m_surfacelist.resize(0);
+  m_surfacelist.push_back(CaloCell_ID_FCS::PreSamplerB);
+  m_surfacelist.push_back(CaloCell_ID_FCS::PreSamplerE);
+  m_surfacelist.push_back(CaloCell_ID_FCS::EME1);
+  m_surfacelist.push_back(CaloCell_ID_FCS::EME2);
+  m_surfacelist.push_back(CaloCell_ID_FCS::FCAL0);
 
+  declareProperty("CaloBoundaryR",                  m_CaloBoundaryR);
+  declareProperty("CaloBoundaryZ",                  m_CaloBoundaryZ);
+  declareProperty("CaloMargin",                     m_calomargin);
+  declareProperty("Surfacelist",                    m_surfacelist );
   declareProperty("Extrapolator",                   m_extrapolator );
   declareProperty("CaloEntrance",                   m_caloEntranceName );
   declareProperty("CaloSurfaceHelper",              m_caloSurfaceHelper );
-
   declareProperty("CaloGeometryHelper",             m_CaloGeometryHelper );
 }
 
@@ -77,12 +90,595 @@ StatusCode FastCaloSimCaloExtrapolation::initialize() {
   return StatusCode::SUCCESS;
 }		 
 
-StatusCode FastCaloSimCaloExtrapolation::finalize() {
-  ATH_MSG_INFO( "doing finalize()" );
+StatusCode FastCaloSimCaloExtrapolation::finalize()
+{
+  ATH_MSG_INFO( "Finalizing FastCaloSimCaloExtrapolation" );
 
   return StatusCode::SUCCESS;
 }
 
+
+void FastCaloSimCaloExtrapolation::extrapolate(TFCSExtrapolationState& result,const TFCSTruthState* truth)
+{
+  //UPDATE EXTRAPOLATION
+  ATH_MSG_INFO("Start FastCaloSimCaloExtrapolation::extrapolate");
+  std::vector<Trk::HitInfo>* hitVector = caloHits(truth);
+  ATH_MSG_INFO("Done FastCaloSimCaloExtrapolation::extrapolate: caloHits");
+
+ //////////////////////////////////////
+ // Start calo extrapolation
+ // First: get entry point into first calo sample
+ //////////////////////////////////////
+  ATH_MSG_INFO("FastCaloSimCaloExtrapolation::extrapolate:*** Get calo surface ***");
+  get_calo_surface(result,hitVector);
+  ATH_MSG_INFO("FastCaloSimCaloExtrapolation::extrapolate:*** Do extrapolation to ID-calo boundary ***");
+  extrapolate_to_ID(result,truth,hitVector);
+  ATH_MSG_INFO("FastCaloSimCaloExtrapolation::extrapolate:*** Do extrapolation ***");
+  extrapolate(result,truth,hitVector);
+  ATH_MSG_INFO("FastCaloSimCaloExtrapolation::extrapolate: Truth extrapolation done");
+
+  for(std::vector<Trk::HitInfo>::iterator it = hitVector->begin();it < hitVector->end();++it)  {
+    if((*it).trackParms) {
+      delete (*it).trackParms;
+      (*it).trackParms=0;
+    }  
+  }
+  delete hitVector;
+  ATH_MSG_INFO("Done FastCaloSimCaloExtrapolation::extrapolate");
+}
+
+std::vector<Trk::HitInfo>* FastCaloSimCaloExtrapolation::caloHits(const TFCSTruthState* truth) const
+{
+  // Start calo extrapolation
+  ATH_MSG_INFO ("[ fastCaloSim transport ] processing particle "<<truth->pdgid() );
+
+  std::vector<Trk::HitInfo>* hitVector =  new std::vector<Trk::HitInfo>;   
+
+  int     pdgId    = truth->pdgid(); 
+  double  charge   = HepPDT::ParticleID(pdgId).charge();
+
+  // particle Hypothesis for the extrapolation
+
+  Trk::ParticleHypothesis pHypothesis = m_pdgToParticleHypothesis.convert(pdgId,charge);
+
+  ATH_MSG_INFO ("particle hypothesis "<< pHypothesis );
+
+  // geantinos not handled by PdgToParticleHypothesis - fix there
+  if ( pdgId == 999 ) pHypothesis = Trk::geantino;
+
+  Amg::Vector3D pos = Amg::Vector3D( truth->vertex().X(), truth->vertex().Y(), truth->vertex().Z()); 
+
+  Amg::Vector3D mom(truth->X(),truth->Y(),truth->Z());
+
+  ATH_MSG_INFO( "[ fastCaloSim transport ] starting transport from position eta="<<pos.eta()<<" phi="<<pos.phi()<<" d="<<pos.mag()<<" pT="<<mom.perp() );
+
+  // input parameters : curvilinear parameters
+  Trk::CurvilinearParameters inputPar(pos,mom,charge);
+
+  // stable vs. unstable check : ADAPT for FASTCALOSIM 
+  //double freepath = ( !m_particleDecayHelper.empty()) ? m_particleDecayHelper->freePath(isp) : - 1.; 
+  double freepath = -1.;
+  //ATH_MSG_VERBOSE( "[ fatras transport ] Particle free path : " << freepath);
+  // path limit -> time limit  ( TODO : extract life-time directly from decay helper )
+  double tDec = freepath > 0. ? freepath : -1.;
+  int decayProc = 0;
+
+  /* uncomment if unstable particles used by FastCaloSim
+  // beta calculated here for further use in validation
+  double mass = m_particleMasses.mass[pHypothesis];
+  double mom = isp.momentum().mag();
+  double beta = mom/sqrt(mom*mom+mass*mass); 
+
+  if ( tDec>0.) {
+    tDec = tDec/beta/CLHEP::c_light + isp.timeStamp();
+    decayProc = 201;                
+  }
+  */
+
+  Trk::TimeLimit timeLim(tDec,0.,decayProc);        // TODO: set vertex time info
+  
+  // prompt decay ( uncomment if unstable particles used )
+  //if ( freepath>0. && freepath<0.01 ) {
+  //  if (!m_particleDecayHelper.empty()) {
+  //    ATH_MSG_VERBOSE( "[ fatras transport ] Decay is triggered for input particle.");
+  //    m_particleDecayHelper->decay(isp);
+  //  }
+  //  return 0;
+  //}
+
+  // presample interactions - ADAPT FOR FASTCALOSIM
+  Trk::PathLimit pathLim(-1.,0);
+  //if (absPdg!=999 && pHypothesis<99) pathLim = m_samplingTool->sampleProcess(mom,isp.charge(),pHypothesis);
+     
+  Trk::GeometrySignature nextGeoID=Trk::Calo; 
+
+  // first extrapolation to reach the ID boundary
+
+  ATH_MSG_INFO( "[ fastCaloSim transport ] before calo entrance ");
+
+  // get CaloEntrance if not done already
+  if (!m_caloEntrance) {
+    m_caloEntrance = m_extrapolator->trackingGeometry()->trackingVolume(m_caloEntranceName);
+    if (!m_caloEntrance)  ATH_MSG_INFO("CaloEntrance not found ");
+     else ATH_MSG_INFO("CaloEntrance found ");
+  }
+
+  ATH_MSG_INFO( "[ fastCaloSim transport ] after calo entrance ");
+  
+  const Trk::TrackParameters* caloEntry = 0;
+
+  if (m_caloEntrance && m_caloEntrance->inside(pos,0.001) &&
+      !m_extrapolator->trackingGeometry()->atVolumeBoundary(pos,m_caloEntrance,0.001)) {
+
+    std::vector<Trk::HitInfo>*     dummyHitVector = 0;   
+    if ( charge==0 ) {
+    
+      caloEntry = m_extrapolator->transportNeutralsWithPathLimit(inputPar,pathLim,timeLim,
+				        Trk::alongMomentum,pHypothesis,dummyHitVector,nextGeoID,m_caloEntrance);  
+ 
+    } else {
+          
+      caloEntry = m_extrapolator->extrapolateWithPathLimit(inputPar,pathLim,timeLim,
+					Trk::alongMomentum,pHypothesis,dummyHitVector,nextGeoID,m_caloEntrance);
+    }
+  } else caloEntry=&inputPar;
+
+  ATH_MSG_INFO( "[ fastCaloSim transport ] after calo caloEntry ");
+
+  if ( caloEntry ) {
+
+    const Trk::TrackParameters* eParameters = 0;
+
+    // save Calo entry hit (fallback info)
+    hitVector->push_back(Trk::HitInfo(caloEntry->clone(),timeLim.time,nextGeoID,0.));  
+
+    ATH_MSG_DEBUG( "[ fastCaloSim transport ] starting Calo transport from position eta="<<caloEntry->position().eta()<<" phi="<<caloEntry->position().phi()<<" d="<<caloEntry->position().mag() );
+    
+    if ( charge==0 ) {
+    
+      eParameters = m_extrapolator->transportNeutralsWithPathLimit(*caloEntry,pathLim,timeLim,
+					      Trk::alongMomentum,pHypothesis,hitVector,nextGeoID);  
+    } else {
+      
+      eParameters = m_extrapolator->extrapolateWithPathLimit(*caloEntry,pathLim,timeLim,
+					      Trk::alongMomentum,pHypothesis,hitVector,nextGeoID);   
+    }
+
+    // save Calo exit hit (fallback info)
+    if (eParameters) hitVector->push_back(Trk::HitInfo(eParameters,timeLim.time,nextGeoID,0.)); 
+  
+    //delete eParameters;   // HitInfo took ownership
+
+  } 
+   
+  if(msgLvl(MSG::DEBUG)) {
+    std::vector<Trk::HitInfo>::iterator it = hitVector->begin();
+    while (it < hitVector->end() )  {
+      int sample=(*it).detID;
+      Amg::Vector3D hitPos = (*it).trackParms->position();
+      ATH_MSG_DEBUG(" HIT: layer="<<sample<<" sample="<<sample-3000<<" eta="<<hitPos.eta()<<" phi="<<hitPos.phi()<<" d="<<hitPos.mag());
+      it++;
+    }
+  }  
+
+  return hitVector;
+}
+
+//#######################################################################
+void FastCaloSimCaloExtrapolation::extrapolate(TFCSExtrapolationState& result,const TFCSTruthState* truth,std::vector<Trk::HitInfo>* hitVector)
+{
+ ATH_MSG_DEBUG("Start extrapolate()");
+
+ double ptruth_eta=truth->Eta();
+ double ptruth_phi=truth->Phi();
+ double ptruth_pt =truth->Pt();
+ double ptruth_p  =truth->P();
+ int    pdgid     =truth->pdgid();
+ 
+ //////////////////////////////////////
+ // Start calo extrapolation
+ //////////////////////////////////////
+ 
+ std::vector< std::vector<double> > eta_safe(3);
+ std::vector< std::vector<double> > phi_safe(3);
+ std::vector< std::vector<double> > r_safe(3);
+ std::vector< std::vector<double> > z_safe(3);
+ for(int subpos=SUBPOS_MID;subpos<=SUBPOS_EXT;++subpos) {
+   eta_safe[subpos].resize(CaloCell_ID_FCS::MaxSample,-999.0);
+  	phi_safe[subpos].resize(CaloCell_ID_FCS::MaxSample,-999.0);
+  	r_safe[subpos].resize(CaloCell_ID_FCS::MaxSample,-999.0);
+  	z_safe[subpos].resize(CaloCell_ID_FCS::MaxSample,-999.0);
+ }
+
+ // only continue if inside the calo
+ if( fabs(result.CaloSurface_eta())<6 )
+ {
+   // now try to extrpolate to all calo layers, that contain energy
+   ATH_MSG_DEBUG("Calo position for particle id "<<pdgid<<", trutheta= " << ptruth_eta <<", truthphi= "<<ptruth_phi<<", truthp="<<ptruth_p<<", truthpt="<<ptruth_pt);
+   for(int sample=CaloCell_ID_FCS::FirstSample;sample<CaloCell_ID_FCS::MaxSample;++sample) {
+     for(int subpos=SUBPOS_MID;subpos<=SUBPOS_EXT;++subpos) {
+       if(get_calo_etaphi(result,hitVector,sample,subpos)) {
+         ATH_MSG_DEBUG( "Result in sample "<<sample<<"."<<subpos<<": eta="<<result.eta(sample,subpos)<<" phi="<<result.phi(sample,subpos)<<" r="<<result.r(sample,subpos)<<" z="<<result.z(sample,subpos)<<" (ok="<<result.OK(sample,subpos)<<")");
+       }
+       else {
+         ATH_MSG_DEBUG( "Extrapolation to sample "<<sample<<" failed (ok="<<result.OK(sample,subpos)<<")");
+       }  
+      }
+    }
+ } //inside calo
+
+ ATH_MSG_DEBUG("End extrapolate()");
+}
+
+void FastCaloSimCaloExtrapolation::extrapolate_to_ID(TFCSExtrapolationState& result,const TFCSTruthState* /*truth*/,std::vector<Trk::HitInfo>* hitVector)
+{
+ ATH_MSG_DEBUG("Start extrapolate_to_ID()");
+
+ Amg::Vector3D hitpos(0,0,0);
+ Amg::Vector3D hitmom(0,0,0);
+ if(rz_cylinder_get_calo_etaphi(hitVector,m_CaloBoundaryR,m_CaloBoundaryZ,hitpos,hitmom)) {
+   ATH_MSG_DEBUG("BOUNDARY ID-CALO eta="<<hitpos.eta()<<" phi="<<hitpos.phi()<<" r="<<hitpos.perp()<<" z="<<hitpos[Amg::z]<<" theta="<<hitpos.theta()<<" ; momentum eta="<<hitmom.eta()<<" phi="<<hitmom.phi()<<" theta="<<hitmom.theta());
+   result.set_IDCaloBoundary_eta(hitpos.eta());
+   result.set_IDCaloBoundary_phi(hitpos.phi());
+   result.set_IDCaloBoundary_r(hitpos.perp());
+   result.set_IDCaloBoundary_z(hitpos[Amg::z]);
+ } else {
+   ATH_MSG_DEBUG("Extrapolation to IDCaloBoundary failed");
+   result.set_IDCaloBoundary_eta(-999.);
+   result.set_IDCaloBoundary_phi(-999.);
+   result.set_IDCaloBoundary_r(0);
+   result.set_IDCaloBoundary_z(0);
+ }
+
+ TVector3 vec(hitpos[Amg::x],hitpos[Amg::y],hitpos[Amg::z]);
+ 
+ //get the tangentvector on this interaction point:
+ //GlobalMomentum* mom=params_on_surface_ID->TrackParameters::momentum().unit() ;
+ //Trk::GlobalMomentum* trackmom=params_on_surface_ID->Trk::TrackParameters::momentum();
+ if(hitmom.mag()>0) {
+   //angle between vec and trackmom:
+   TVector3 Trackmom(hitmom[Amg::x],hitmom[Amg::y],hitmom[Amg::z]);
+   double angle3D=Trackmom.Angle(vec); //isn't this the same as TVector3 vec?
+   ATH_MSG_DEBUG("    3D ANGLE "<<angle3D);
+
+   double angleEta=vec.Theta()-Trackmom.Theta();
+   ATH_MSG_DEBUG("    ANGLE dTHEA"<<angleEta);
+   
+   result.set_IDCaloBoundary_AngleEta(angleEta);
+   result.set_IDCaloBoundary_Angle3D(angle3D);
+ } else {
+   result.set_IDCaloBoundary_AngleEta(-999.);
+   result.set_IDCaloBoundary_Angle3D(-999.);
+ }
+ ATH_MSG_DEBUG("End extrapolate_to_ID()");
+} //extrapolate_to_ID
+
+bool FastCaloSimCaloExtrapolation::get_calo_surface(TFCSExtrapolationState& result,std::vector<Trk::HitInfo>* hitVector)
+{
+  ATH_MSG_DEBUG("Start get_calo_surface()");
+  result.set_CaloSurface_sample(CaloCell_ID_FCS::noSample);
+  result.set_CaloSurface_eta(-999);
+  result.set_CaloSurface_phi(-999);
+  result.set_CaloSurface_r(0);
+  result.set_CaloSurface_z(0);
+  double min_calo_surf_dist=1000;
+
+  for(unsigned int i=0;i<m_surfacelist.size();++i) {
+    int sample=m_surfacelist[i];
+    std::vector<Trk::HitInfo>::iterator it = hitVector->begin();
+    while (it != hitVector->end() && it->detID != (3000+sample) )  { it++;} 
+    if(it==hitVector->end()) continue;
+    Amg::Vector3D hitPos = (*it).trackParms->position();
+    
+    //double offset = 0.;
+    double etaCalo = hitPos.eta();
+
+    msg(MSG::DEBUG)<<"test: entrance to calo surface : sample="<<sample<<" eta="<<etaCalo;
+
+    if (fabs(etaCalo)<900) {
+      double phiCalo = hitPos.phi();
+      double distsamp =deta(sample,etaCalo);
+
+      msg(MSG::DEBUG)<<" phi="<<phiCalo<<" dist="<<distsamp;
+      if(distsamp<min_calo_surf_dist && min_calo_surf_dist>=0) {
+        //hitVector is ordered in r, so if first surface was hit, keep it
+        result.set_CaloSurface_sample(sample);
+        result.set_CaloSurface_eta(etaCalo);
+        result.set_CaloSurface_phi(phiCalo);
+        double rcalo=rent(sample,etaCalo);
+        double zcalo=zent(sample,etaCalo);
+        result.set_CaloSurface_r(rcalo);
+        result.set_CaloSurface_z(zcalo);
+        min_calo_surf_dist=distsamp;
+        msg(MSG::DEBUG)<<" r="<<rcalo<<" z="<<zcalo;
+        if(distsamp<0) {
+          msg(MSG::DEBUG)<<endreq;
+          break;
+        }  
+      }
+      msg(MSG::DEBUG)<<endreq;
+    } else {
+      msg(MSG::DEBUG)<<": eta > 900, not using this"<<endreq;
+    }
+  }
+
+  if(result.CaloSurface_sample()==CaloCell_ID_FCS::noSample) {
+    // first intersection with sensitive calo layer
+    std::vector<Trk::HitInfo>::iterator it = hitVector->begin();
+    while ( it < hitVector->end() && (*it).detID != 3 ) { it++;}   // to be updated 
+    if (it==hitVector->end())   {  // no calo intersection, abort
+      return false;
+    }
+    Amg::Vector3D surface_hitPos = (*it).trackParms->position();
+
+    result.set_CaloSurface_eta(surface_hitPos.eta());
+    result.set_CaloSurface_phi(surface_hitPos.phi());
+    result.set_CaloSurface_r(surface_hitPos.perp());
+    result.set_CaloSurface_z(surface_hitPos[Amg::z]);
+
+    double pT=(*it).trackParms->momentum().perp();
+    if(TMath::Abs(result.CaloSurface_eta())>4.9 || pT<500 || (TMath::Abs(result.CaloSurface_eta())>4 && pT<1000) ) {
+      ATH_MSG_DEBUG("only entrance to calo entrance layer found, no surface : eta="<<result.CaloSurface_eta()<<" phi="<<result.CaloSurface_phi()<<" r="<<result.CaloSurface_r()<<" z="<<result.CaloSurface_z()<<" pT="<<pT);
+    } else {  
+      ATH_MSG_WARNING("only entrance to calo entrance layer found, no surface : eta="<<result.CaloSurface_eta()<<" phi="<<result.CaloSurface_phi()<<" r="<<result.CaloSurface_r()<<" z="<<result.CaloSurface_z()<<" pT="<<pT);
+    }  
+  } else {
+    ATH_MSG_DEBUG("entrance to calo surface : sample="<<result.CaloSurface_sample()<<" eta="<<result.CaloSurface_eta()<<" phi="<<result.CaloSurface_phi()<<" r="<<result.CaloSurface_r()<<" z="<<result.CaloSurface_z()<<" deta="<<min_calo_surf_dist);
+  }
+  
+  ATH_MSG_DEBUG("End get_calo_surface()");
+  return true;
+}
+
+//UPDATED
+bool FastCaloSimCaloExtrapolation::get_calo_etaphi(TFCSExtrapolationState& result,std::vector<Trk::HitInfo>* hitVector, int sample,int subpos)  
+{
+  result.set_OK(sample,subpos,false);
+  result.set_eta(sample,subpos,result.CaloSurface_eta());
+  result.set_phi(sample,subpos,result.CaloSurface_phi());
+  result.set_r(sample,subpos,rpos(sample,result.CaloSurface_eta(),subpos));
+  result.set_z(sample,subpos,zpos(sample,result.CaloSurface_eta(),subpos));
+  double distsamp =deta(sample,result.CaloSurface_eta());
+  double lrzpos =rzpos(sample,result.CaloSurface_eta(),subpos);
+  double hitdist=0;
+  bool best_found=false;
+  double best_target=0;
+
+  std::vector<Trk::HitInfo>::iterator it = hitVector->begin();
+  while ( it!= hitVector->end() && it->detID != (3000+sample) ) { it++;}
+  //while ((*it).detID != (3000+sample) && it < hitVector->end() )  it++;
+  
+  if (it!=hitVector->end()) {
+    Amg::Vector3D hitPos1 = (*it).trackParms->position();
+    int sid1=(*it).detID;
+    int sid2=-1;
+    Amg::Vector3D hitPos;
+    Amg::Vector3D hitPos2;
+    
+    std::vector<Trk::HitInfo>::iterator itnext = it;
+    ++itnext;
+    if(itnext!=hitVector->end()) {
+      hitPos2 = (*itnext).trackParms->position();
+      sid2=(*itnext).detID;
+      double eta_avg=0.5*(hitPos1.eta()+hitPos2.eta());
+      double t;
+      if(isCaloBarrel(sample))
+      {
+        double r=rpos(sample,eta_avg,subpos);
+        double r1=hitPos1.perp();
+        double r2=hitPos2.perp();
+        t=(r-r1)/(r2-r1);
+        best_target=r;
+      }
+      else
+      {
+        double z=zpos(sample,eta_avg,subpos);
+        double z1=hitPos1[Amg::z];
+        double z2=hitPos2[Amg::z];
+        t=(z-z1)/(z2-z1);
+        best_target=z;
+      }
+      hitPos=t*hitPos2+(1-t)*hitPos1;
+    }
+    else
+    	{
+      hitPos=hitPos1;
+      hitPos2=hitPos1;
+    }
+    double etaCalo = hitPos.eta();
+    double phiCalo = hitPos.phi();
+    result.set_OK(sample,subpos,true);
+    result.set_eta(sample,subpos,etaCalo);
+    result.set_phi(sample,subpos,phiCalo);
+    result.set_r(sample,subpos,hitPos.perp());
+    result.set_z(sample,subpos,hitPos[Amg::z]);
+    hitdist=hitPos.mag();
+    lrzpos=rzpos(sample,etaCalo,subpos);
+    distsamp=deta(sample,etaCalo);
+    best_found=true;
+    ATH_MSG_DEBUG(" extrapol with layer hit: id="<<sid1<<" -> "<<sid2<<
+                  " target r/z="<<best_target<<
+                  " r1="<<hitPos1.perp()<<" z1="<<hitPos1[Amg::z]<<" r2="<<hitPos2.perp()<<" z2="<<hitPos2[Amg::z]<<
+                  " re="<<result.r(sample,subpos)<<" ze="<<result.z(sample,subpos)
+                  );
+  } 
+  if(!best_found) {
+    it = hitVector->begin();
+    double best_dist=0.5;
+    bool best_inside=false;
+    int best_id1,best_id2;
+    Amg::Vector3D best_hitPos=(*it).trackParms->position();
+    while (it < hitVector->end()-1 ) {
+      Amg::Vector3D hitPos1 = (*it).trackParms->position();
+      int sid1=(*it).detID;
+      it++;
+      Amg::Vector3D hitPos2 = (*it).trackParms->position();
+      int sid2=(*it).detID;
+      double eta_avg=0.5*(hitPos1.eta()+hitPos2.eta());
+      double t;
+      double tmp_target=0;
+      if(isCaloBarrel(sample)) {
+        double r=rpos(sample,eta_avg,subpos);
+        double r1=hitPos1.perp();
+        double r2=hitPos2.perp();
+        t=(r-r1)/(r2-r1);
+        tmp_target=r;
+      } else {
+        double z=zpos(sample,eta_avg,subpos);
+        double z1=hitPos1[Amg::z];
+        double z2=hitPos2[Amg::z];
+        t=(z-z1)/(z2-z1);
+        tmp_target=z;
+      }
+      Amg::Vector3D hitPos=t*hitPos2+(1-t)*hitPos1;
+      double dist=TMath::Min(TMath::Abs(t-0),TMath::Abs(t-1));
+      bool inside=false;
+      if(t>=0 && t<=1) inside=true;
+      if(!best_found || inside) {
+        if(!best_inside || dist<best_dist) {
+          best_dist=dist;
+          best_hitPos=hitPos;
+          best_inside=inside;
+          best_found=true;
+          best_id1=sid1;
+          best_id2=sid2;
+          best_target=tmp_target;
+        }
+      } else {
+        if(!best_inside && dist<best_dist) {
+          best_dist=dist;
+          best_hitPos=hitPos;
+          best_inside=inside;
+          best_found=true;
+          best_id1=sid1;
+          best_id2=sid2;
+          best_target=tmp_target;
+        }
+      }
+      ATH_MSG_VERBOSE(" extrapol without layer hit: id="<<sid1<<" -> "<<sid2<<" dist="<<dist<<" mindist="<<best_dist<<
+                    " t="<<t<<" best_inside="<<best_inside<<" target r/z="<<tmp_target<<
+                    " r1="<<hitPos1.perp()<<" z1="<<hitPos1[Amg::z]<<" r2="<<hitPos2.perp()<<" z2="<<hitPos2[Amg::z]<<
+                    " re="<<hitPos.perp()<<" ze="<<hitPos[Amg::z]<<
+                    " rb="<<best_hitPos.perp()<<" zb="<<best_hitPos[Amg::z]
+                    );
+      if(best_found) {
+        double etaCalo = best_hitPos.eta();
+        result.set_OK(sample,subpos,true);
+        result.set_eta(sample,subpos,etaCalo);
+        result.set_phi(sample,subpos,best_hitPos.phi());
+        result.set_r(sample,subpos,best_hitPos.perp());
+        result.set_z(sample,subpos,best_hitPos[Amg::z]);
+
+        hitdist=best_hitPos.mag();
+        lrzpos=rzpos(sample,etaCalo,subpos);
+        distsamp=deta(sample,etaCalo);
+      }              
+    } 
+    if(best_found) {
+      ATH_MSG_DEBUG(" extrapol without layer hit: id="<<best_id1<<" -> "<<best_id2<<" mindist="<<best_dist<<
+                    " best_inside="<<best_inside<<" target r/z="<<best_target<<
+                    " rb="<<best_hitPos.perp()<<" zb="<<best_hitPos[Amg::z]
+                    );
+    }                  
+  }
+  
+  if(isCaloBarrel(sample)) lrzpos*=cosh(result.eta(sample,subpos));
+   else                    lrzpos= fabs(lrzpos/tanh(result.eta(sample,subpos)));
+
+  result.set_d(sample,subpos,lrzpos);
+  result.set_detaBorder(sample,subpos,distsamp);
+
+  if(msgLvl(MSG::DEBUG)) {
+    msg(MSG::DEBUG)<<"  Final par TTC sample "<<sample<<" subpos="<<subpos;
+    if(result.OK(sample,subpos)) msg()<<" (good)";
+     else msg()<<" (bad)";
+    msg()<<" eta=" << result.eta(sample,subpos) << "   phi=" << result.phi(sample,subpos) <<" dCalo="<<result.d(sample,subpos)<<" dist(hit)="<<hitdist<< endreq;
+  } 
+ 
+  return result.OK(sample,subpos);
+}
+
+//UPDATED
+bool FastCaloSimCaloExtrapolation::rz_cylinder_get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector, double cylR, double cylZ, Amg::Vector3D& pos, Amg::Vector3D& mom)  
+{
+  bool best_found=false;
+  double best_dist=10000;
+  bool best_inside=false;
+  int best_id1,best_id2;
+
+  std::vector<Trk::HitInfo>::iterator it = hitVector->begin();
+  Amg::Vector3D best_hitPos=(*it).trackParms->position();
+  for(int rz=0;rz<=1;++rz) {
+    it = hitVector->begin();
+    while (it < hitVector->end()-1 ) {
+      Amg::Vector3D hitPos1 = (*it).trackParms->position();
+      Amg::Vector3D hitMom1 = (*it).trackParms->momentum();
+      int sid1=(*it).detID;
+      it++;
+      Amg::Vector3D hitPos2 = (*it).trackParms->position();
+      Amg::Vector3D hitMom2 = (*it).trackParms->momentum();
+      int sid2=(*it).detID;
+
+      double t;
+      if(rz==1) {
+        double r=cylR;
+        double r1=hitPos1.perp();
+        double r2=hitPos2.perp();
+        t=(r-r1)/(r2-r1);
+      } else {
+        double z=cylZ;
+        double z1=hitPos1[Amg::z];
+        double z2=hitPos2[Amg::z];
+        t=(z-z1)/(z2-z1);
+      }
+      Amg::Vector3D hitPos=t*hitPos2+(1-t)*hitPos1;
+
+      double dist=hitPos.mag();
+      bool inside=false;
+      if(t>=-0.001 && t<=1.001) inside=true;
+      
+      if(!best_found || inside) {
+        if(!best_inside || dist<best_dist) {
+          best_dist=dist;
+          best_hitPos=hitPos;
+          best_inside=inside;
+          best_found=true;
+          best_id1=sid1;
+          best_id2=sid2;
+          mom=t*hitMom2+(1-t)*hitMom1;
+        }
+      } else {
+        if(!best_inside && dist<best_dist) {
+          best_dist=dist;
+          best_hitPos=hitPos;
+          best_inside=inside;
+          best_found=true;
+          best_id1=sid1;
+          best_id2=sid2;
+          mom=t*hitMom2+(1-t)*hitMom1;
+        }
+      }
+      ATH_MSG_DEBUG(" extrapol without layer hit: id="<<sid1<<" -> "<<sid2<<" dist="<<dist<<" bestdist="<<best_dist<<
+                    " t="<<t<<" inside="<<inside<<" best_inside="<<best_inside<<
+                    " r1="<<hitPos1.perp()<<" z1="<<hitPos1[Amg::z]<<" r2="<<hitPos2.perp()<<" z2="<<hitPos2[Amg::z]<<
+                    " re="<<hitPos.perp()<<" ze="<<hitPos[Amg::z]<<
+                    " rb="<<best_hitPos.perp()<<" zb="<<best_hitPos[Amg::z]
+                    );
+    }
+  }   
+  
+  if(best_found) {
+    ATH_MSG_DEBUG(" extrapol to r="<<cylR<<" z="<<cylZ<<": id="<<best_id1<<" -> "<<best_id2<<" dist="<<best_dist<<
+                  " best_inside="<<best_inside<<
+                  " rb="<<best_hitPos.perp()<<" zb="<<best_hitPos[Amg::z]
+                  );
+  }                  
+  pos=best_hitPos;
+
+  return best_found;
+}
+
+
 bool FastCaloSimCaloExtrapolation::isCaloBarrel(int sample) const
 {
   return GetCaloGeometry()->isCaloBarrel(sample);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.h
similarity index 64%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.h
index d63263385aaa01e37271b9bb58646c4452efa239..07edc5a390f77eea5fc20f2f0516ee0fb6b95e4a 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.h
@@ -9,16 +9,20 @@
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "GaudiKernel/ToolHandle.h"
 
-namespace Trk {
+namespace Trk
+{
   class TrackingVolume;
 }
+
 #include "TrkExInterfaces/ITimedExtrapolator.h" 
+#include "TrkEventPrimitives/PdgToParticleHypothesis.h"
 
 class ICaloSurfaceBuilder;
 class ICaloSurfaceHelper;
 class ICaloCoordinateTool;
 
-namespace HepPDT {
+namespace HepPDT
+{
   class ParticleDataTable;
 }  
 
@@ -28,8 +32,9 @@ namespace HepPDT {
 
 class IFastCaloSimGeometryHelper;
 
-
-class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExtrapolation {
+class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExtrapolation
+{
+ 
  public:
    FastCaloSimCaloExtrapolation( const std::string& t, const std::string& n, const IInterface* p );
    ~FastCaloSimCaloExtrapolation();
@@ -38,8 +43,20 @@ class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExt
    virtual StatusCode finalize();
 
    IFastCaloSimGeometryHelper* GetCaloGeometry() const {return &(*m_CaloGeometryHelper);};
-
+   enum SUBPOS { SUBPOS_MID = TFCSExtrapolationState::SUBPOS_MID, SUBPOS_ENT = TFCSExtrapolationState::SUBPOS_ENT, SUBPOS_EXT = TFCSExtrapolationState::SUBPOS_EXT}; //MID=middle, ENT=entrance, EXT=exit of cal layer
+	 
+	 virtual void extrapolate(TFCSExtrapolationState& result,const TFCSTruthState* truth);
+	
  protected:
+
+   // extrapolation through Calo
+   std::vector<Trk::HitInfo>* caloHits(const TFCSTruthState* truth) const;
+   void extrapolate(TFCSExtrapolationState& result,const TFCSTruthState* truth,std::vector<Trk::HitInfo>* hitVector);
+   void extrapolate_to_ID(TFCSExtrapolationState& result,const TFCSTruthState* truth,std::vector<Trk::HitInfo>* hitVector);
+   bool get_calo_etaphi(TFCSExtrapolationState& result,std::vector<Trk::HitInfo>* hitVector,int sample,int subpos=SUBPOS_MID);
+   bool get_calo_surface(TFCSExtrapolationState& result,std::vector<Trk::HitInfo>* hitVector);
+   bool rz_cylinder_get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector, double cylR, double cylZ, Amg::Vector3D& pos, Amg::Vector3D& mom);  
+
    bool   isCaloBarrel(int sample) const;
    double deta(int sample,double eta) const;
    void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const;
@@ -62,16 +79,21 @@ class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExt
    double m_CaloBoundaryZ;
    double m_calomargin;
 
-   /** The new Extrapolator setup */
+   std::vector< int > m_surfacelist;
+
+   // The new Extrapolator setup
    ToolHandle<Trk::ITimedExtrapolator> m_extrapolator;          
    ToolHandle<ICaloSurfaceHelper>      m_caloSurfaceHelper;
    mutable const Trk::TrackingVolume*  m_caloEntrance;
    std::string                         m_caloEntranceName; 
 
-   /** The FastCaloSimGeometryHelper tool */
+   Trk::PdgToParticleHypothesis        m_pdgToParticleHypothesis;
+
+   // The FastCaloSimGeometryHelper tool
    ToolHandle<IFastCaloSimGeometryHelper> m_CaloGeometryHelper;
 };
 
 #endif // FastCaloSimCaloExtrapolation_H
 
 
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimGeometryHelper.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimGeometryHelper.cxx
index ed12f4446725d9a7b494dc4eab78edadb02d2098..c73d8dd00ce52eb32724345dfb93e2cf18fede72 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimGeometryHelper.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimGeometryHelper.cxx
@@ -3,7 +3,8 @@
 */
 
 #include "FastCaloSimGeometryHelper.h"
-#include "CaloDetDescr/CaloDetDescrElement.h"
+//#include "CaloDetDescr/CaloDetDescrElement.h"
+#include "ISF_FastCaloSimParametrization/CaloDetDescrElement.h"
 #include "CaloDetDescr/CaloDetDescrManager.h"
 #include "GeoModelInterfaces/IGeoModelSvc.h"
 
@@ -75,15 +76,15 @@ bool FastCaloSimGeometryHelper::LoadGeometryFromCaloDDM()
 {
   ATH_MSG_INFO("Start LoadGeometryFromCaloDDM()");
   int jentry=0;
-  for(CaloDetDescrManager::calo_element_const_iterator calo_iter=m_caloMgr->element_begin();calo_iter<m_caloMgr->element_end();++calo_iter) {
-    const CaloDetDescrElement* pcell=*calo_iter;
-    addcell(pcell);
-
-    if(jentry%10000==0) {
-      ATH_MSG_DEBUG("Load calo cell "<<jentry<<" : "<<pcell->getSampling()<<", "<<pcell->identify());
-    }
-    ++jentry;
-  }
+  //for(CaloDetDescrManager::calo_element_const_iterator calo_iter=m_caloMgr->element_begin();calo_iter<m_caloMgr->element_end();++calo_iter) {
+    //const CaloDetDescrElement* pcell=*calo_iter;
+    //addcell(pcell);
+
+    //if(jentry%10000==0) {
+      //ATH_MSG_DEBUG("Load calo cell "<<jentry<<" : "<<pcell->getSampling()<<", "<<pcell->identify());
+    //}
+    //++jentry;
+  //}
 
   bool ok=PostProcessGeometry();
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx
index 73598a8543ef119597bf14cd3cd7b5290da3b122..7822a5a3f3e9ecb62daf55385f6a227c6f035c05 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx
@@ -3,6 +3,8 @@
 */
 
 #include "ISF_FastCaloSimParametrization/ISF_HitAnalysis.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
 
 // Section of includes for LAr calo tests
 #include "LArSimEvent/LArHitContainer.h"
@@ -173,6 +175,8 @@ ISF_HitAnalysis::ISF_HitAnalysis(const std::string& name, ISvcLocator* pSvcLocat
   declareProperty("MetadataTreeName", m_metadataTreeName); 
   declareProperty("NTruthParticles", m_NtruthParticles=1, "Number of truth particles saved from the truth collection, -1 to save all");
 
+  declareProperty("FastCaloSimCaloExtrapolation",   m_FastCaloSimCaloExtrapolation );
+
   //###########################
   //declareProperty("ExtrapolatorName",               m_extrapolatorName );
   //declareProperty("ExtrapolatorInstanceName",       m_extrapolatorInstanceName );
@@ -411,6 +415,13 @@ StatusCode ISF_HitAnalysis::initialize() {
     return StatusCode::FAILURE;
   }
 
+  // Get FastCaloSimCaloExtrapolation
+  if (m_FastCaloSimCaloExtrapolation.retrieve().isFailure()) {
+    ATH_MSG_ERROR("FastCaloSimCaloExtrapolation not found ");
+    return StatusCode::FAILURE;
+  }
+
+
   // Grab the Ntuple and histogramming service for the tree
   sc = service("THistSvc",m_thistSvc);
   if (sc.isFailure()) {
@@ -806,6 +817,11 @@ StatusCode ISF_HitAnalysis::execute() {
 
 		  if (particleIndex>loopEnd) break; //enough particles
 		  
+    //UPDATE EXTRAPOLATION WITH ALGTOOL
+	  TFCSTruthState truth((*it)->momentum().px(),(*it)->momentum().py(),(*it)->momentum().pz(),(*it)->momentum().e(),(*it)->pdg_id());
+	  TFCSExtrapolationState result;
+	  m_FastCaloSimCaloExtrapolation->extrapolate(result,&truth);
+
     //UPDATE EXTRAPOLATION
     std::vector<Trk::HitInfo>* hitVector = caloHits(*(*it));
 
@@ -825,6 +841,8 @@ StatusCode ISF_HitAnalysis::execute() {
 		  HepMC::GenVertex* pvtx = (*it)->production_vertex();
 		  if (pvtx)
 		    {
+		      truth.set_vertex(pvtx->position().x(),pvtx->position().y(),pvtx->position().z(),pvtx->position().t());
+
 		      m_truth_vtxbarcode->push_back(pvtx->barcode());
 		      double radius2=(pvtx->position().x()*pvtx->position().x())+(pvtx->position().y()*pvtx->position().y());
 		      ATH_MSG_VERBOSE("particle "<<particleIndex<<" Mom: "<<(*it)->momentum().e()<<"|"<<(*it)->momentum().px()<<"|"<<(*it)->momentum().py()<<"|"<<(*it)->momentum().pz()<<" vertex_x "<<pvtx->position().x()<<" y "<<pvtx->position().y()<<" z "<<pvtx->position().z()<<" r2 "<<radius2<<" VertexBarcode: "<<pvtx->barcode()<<" ParticleBarcode:"<<(*it)->barcode()<<" status: "<<(*it)->status());
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/components/ISF_FastCaloSimParametrization_entries.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/components/ISF_FastCaloSimParametrization_entries.cxx
index 9f3977ee384f06cf6da11bd45e5a04a8e18cdea8..ac38e502342898a477c2db1d60302655833c1deb 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/components/ISF_FastCaloSimParametrization_entries.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/components/ISF_FastCaloSimParametrization_entries.cxx
@@ -4,8 +4,10 @@
 #include "ISF_FastCaloSimParametrization/NativeFastCaloSimSvc.h"
 
 #include "../FastCaloSimGeometryHelper.h"
+#include "../FastCaloSimCaloExtrapolation.h"
 
 DECLARE_TOOL_FACTORY( FastCaloSimGeometryHelper )
+DECLARE_TOOL_FACTORY( FastCaloSimCaloExtrapolation )
 
 DECLARE_ALGORITHM_FACTORY( FastCaloSimParamAlg )
 DECLARE_ALGORITHM_FACTORY( ISF_HitAnalysis) 
@@ -18,6 +20,7 @@ DECLARE_FACTORY_ENTRIES( ISF_FastCaloSimParametrization ) {
   DECLARE_ALGORITHM( FastCaloSimParamAlg )
   DECLARE_ALGORITHM( ISF_HitAnalysis )
   DECLARE_TOOL( FastCaloSimGeometryHelper )
+  DECLARE_TOOL( FastCaloSimCaloExtrapolation )
 
   DECLARE_NAMESPACE_SERVICE( ISF , NativeFastCaloSimSvc )
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C
index 2be882925c6c2cdf45679e7e4405cca2055d5b62..0467029a4ab8181b9cf12f1ac4a3475970471b69 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C
@@ -7,10 +7,11 @@
 #include "TLatex.h"
 #include "TLine.h"
 #include "TPave.h"
+#include "TPad.h"
 #include "TMarker.h"
 
 
-void ATLASLabel(Double_t x,Double_t y,char* text,Color_t color) 
+void ATLASLabel(Double_t x,Double_t y,const char* text,Color_t color) 
 {
   TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
   l.SetNDC();
@@ -49,7 +50,7 @@ void ATLASLabelOld(Double_t x,Double_t y,bool Preliminary,Color_t color)
 
 
 
-void ATLASVersion(char* version,Double_t x,Double_t y,Color_t color) 
+void ATLASVersion(const char* version,Double_t x,Double_t y,Color_t color) 
 {
 
   if (version) {
@@ -65,60 +66,3 @@ void ATLASVersion(char* version,Double_t x,Double_t y,Color_t color)
   }
 }
 
-
-
-void myText(Double_t x,Double_t y,Color_t color,char *text) 
-{
-  //Double_t tsize=0.05;
-  TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
-  l.SetNDC();
-  l.SetTextColor(color);
-  l.DrawLatex(x,y,text);
-}
- 
-void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,char *text) 
-{
-  Double_t tsize=0.06;
-
-  TLatex l; l.SetTextAlign(12); //l.SetTextSize(tsize); 
-  l.SetNDC();
-  l.DrawLatex(x,y,text);
-
-  Double_t y1=y-0.25*tsize;
-  Double_t y2=y+0.25*tsize;
-  Double_t x2=x-0.3*tsize;
-  Double_t x1=x2-boxsize;
-
-  printf("x1= %f x2= %f y1= %f y2= %f \n",x1,x2,y1,y2);
-
-  TPave *mbox= new TPave(x1,y1,x2,y2,0,"NDC");
-
-  mbox->SetFillColor(mcolor);
-  mbox->SetFillStyle(1001);
-  mbox->Draw();
-
-  TLine mline;
-  mline.SetLineWidth(4);
-  mline.SetLineColor(1);
-  mline.SetLineStyle(1);
-  Double_t y_new=(y1+y2)/2.;
-  mline.DrawLineNDC(x1,y_new,x2,y_new);
-
-}
-
-void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle,char *text) 
-{
-  //  printf("**myMarker: text= %s\ m ",text);
-
-  Double_t tsize=0.06;
-  TMarker *marker = new TMarker(x-(0.4*tsize),y,8);
-  marker->SetMarkerColor(color);  marker->SetNDC();
-  marker->SetMarkerStyle(mstyle);
-  marker->SetMarkerSize(2.0);
-  marker->Draw();
-
-  TLatex l; l.SetTextAlign(12); //l.SetTextSize(tsize); 
-  l.SetNDC();
-  l.DrawLatex(x,y,text);
-}
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.h
index 8dbd1894b51f243ead49bd8602aafc4b760c57a7..ad0415e5b572f6893b1fa04e83e810c44544fbec 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.h
@@ -9,7 +9,7 @@
 // 
 //   Copyright (C) 2010 Atlas Collaboration
 //
-//   $Id$
+//   $Id: AtlasLabels.h, v0.0   Thu 25 Mar 2010 10:34:20 CET $
 
 
 #ifndef __ATLASLABELS_H
@@ -17,16 +17,10 @@
 
 #include "Rtypes.h"
 
-void ATLASLabel(Double_t x,Double_t y,char* text=NULL,Color_t color=1); 
+void ATLASLabel(Double_t x,Double_t y,const char* text=NULL,Color_t color=1); 
 
 void ATLASLabelOld(Double_t x,Double_t y,bool Preliminary=false,Color_t color=1); 
 
-void ATLASVersion(char* version=NULL,Double_t x=0.88,Double_t y=0.975,Color_t color=1); 
-
-void myText(Double_t x,Double_t y,Color_t color,char *text); 
-
-void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,char *text); 
-
-void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle,char *text); 
+void ATLASVersion(const char* version=NULL,Double_t x=0.88,Double_t y=0.975,Color_t color=1); 
 
 #endif // __ATLASLABELS_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h
index b77a679959a02865d32cd13a52bcbac0f1b2fbf3..52eca17ce554c8a93f91dd5404bbf45879d70365 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h
@@ -12,7 +12,7 @@
 // 
 //   Copyright (C) 2010 Atlas Collaboration
 //
-//   $Id$
+//   $Id: AtlasStyle.h, v0.0   Thu 25 Mar 2010 10:34:20 CET $
 
 #ifndef  __ATLASSTYLE_H
 #define __ATLASSTYLE_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C
index 9dcff66d3191f9fbff0d4498c6161c5b36b53770..58cbccee1a8982bbc8195c1f1d638798d5e43729 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C
@@ -209,9 +209,12 @@ void myAddtoBand(TGraphErrors* g1, TGraphAsymmErrors* g2) {
   for (Int_t i=0; i<g1->GetN(); i++) {
     g1->GetPoint(i, x1,y1);
     g2->GetPoint(i, x1,y2);
-
-    if (y1==0) y1=1;
-    if (y2==0) y2=1;
+    
+    if ( y1==0 || y2==0 ) { 
+      std::cerr << "check these points very carefully : myAddtoBand() : point " << i << std::endl;  
+    }
+    //    if (y1==0) y1=1;
+    //    if (y2==0) y2=1;
 
     //    if (i==g1->GetN()-1) x2=x1;
     //    else                 g2->GetPoint(i+1,x2,dum);
@@ -251,16 +254,16 @@ TGraphErrors* TH1TOTGraph(TH1 *h1){
  TGraphErrors* g1= new TGraphErrors();
 
  Double_t x, y, ex, ey;
- for (Int_t i=0; i<h1->GetNbinsX(); i++) {
+ for (Int_t i=1 ; i<=h1->GetNbinsX(); i++) {
    y=h1->GetBinContent(i);
-  ey=h1->GetBinError(i);
+   ey=h1->GetBinError(i);
    x=h1->GetBinCenter(i);
-  ex=h1->GetBinWidth(i);
-
+   ex=h1->GetBinWidth(i);
+   
   //   cout << " x,y = " << x << " " << y << " ex,ey = " << ex << " " << ey << endl;
 
-   g1->SetPoint(i,x,y);
-   g1->SetPointError(i,ex,ey);
+   g1->SetPoint(i-1,x,y);
+   g1->SetPointError(i-1,ex,ey);
 
  }
 
@@ -269,7 +272,7 @@ TGraphErrors* TH1TOTGraph(TH1 *h1){
  return g1;
 }
 
-void myText(Double_t x,Double_t y,Color_t color,char *text) {
+void myText(Double_t x,Double_t y,Color_t color, const char *text) {
 
   //Double_t tsize=0.05;
   TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
@@ -279,7 +282,7 @@ void myText(Double_t x,Double_t y,Color_t color,char *text) {
 }
  
 
-void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,char *text) 
+void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,const char *text) 
 {
 
   Double_t tsize=0.06;
@@ -311,7 +314,7 @@ void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,char *text)
 }
 
 
-void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle,char *text,Float_t msize) 
+void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle, const char *text,Float_t msize) 
 {
   Double_t tsize=0.06;
   TMarker *marker = new TMarker(x-(0.4*tsize),y,8);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h
index fb4346f98fb6ecfe721ea34cc0644a44bb40f7d5..5305a36284dc2ed2186642bdb98b8fb08ecda079 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h
@@ -10,7 +10,7 @@
 // 
 //   Copyright (C) 2010 Atlas Collaboration
 //
-//   $Id$
+//   $Id: AtlasUtils.h, v0.0   Thu 25 Mar 2010 10:34:20 CET $
 
 
 #ifndef __ATLASUTILS_H
@@ -31,10 +31,10 @@ void myAddtoBand(TGraphErrors* g1, TGraphAsymmErrors* g2);
 
 TGraphErrors* TH1TOTGraph(TH1 *h1);
 
-void myText(Double_t x,Double_t y,Color_t color,char *text);
+void myText(Double_t x,Double_t y,Color_t color,const char *text);
 
-void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,char *text);
+void myBoxText(Double_t x, Double_t y,Double_t boxsize,Int_t mcolor,const char *text);
 
-void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle,char *text,Float_t msize=2.); 
+void myMarkerText(Double_t x,Double_t y,Int_t color,Int_t mstyle,const char *text,Float_t msize=2.); 
 
 #endif // __ATLASUTILS_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.cxx
index 84d84f2379786bb98a7d2a70ea86bd417b72d3e2..a1c38db61ff2855baa9a6bed2b52d1cd8b2e262e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.cxx
@@ -6,6 +6,10 @@
 #include <TTree.h>
 #include <TFile.h>
 #include "CaloDetDescr/CaloDetDescrElement.h"
+#include <fstream>
+#include <sstream>
+#include <TGraph.h>
+#include "TH2D.h"
 
 using namespace std;
 
@@ -27,7 +31,7 @@ bool CaloGeometryFromFile::LoadGeometryFromFile(TString filename,TString treenam
 
   TTree* fChain = tree;
   
-  CaloDetDescrElement cell;
+  CaloGeoDetDescrElement cell;
   
   // List of branches
   TBranch        *b_identifier;   //!
@@ -79,25 +83,220 @@ bool CaloGeometryFromFile::LoadGeometryFromFile(TString filename,TString treenam
     if (ientry < 0) break;
     fChain->GetEntry(jentry);
     
-    CaloDetDescrElement* pcell=new CaloDetDescrElement(cell);
+    CaloGeoDetDescrElement* pcell=new CaloGeoDetDescrElement(cell);
+    int sampling = pcell->getSampling();
+    if(sampling >20) continue;
     addcell(pcell);
 
-    if(jentry%25000==0) {
+    //if(jentry%25000==0) {
+    if(jentry==nentries-1) {
       //cout<<jentry<<" : "<<cell.getSampling()<<", "<<cell.identify()<<endl;
-/*
-      cout<<"all : "<<m_cells.size()<<endl;
-      for(int i=0;i<MAX_SAMPLING;++i) {
-        cout<<"  cells sampling "<<i<<" : "<<m_cells_in_sampling[i].size()<<" cells";
-        cout<<", "<<m_cells_in_regions[i].size()<<" lookup map(s)"<<endl;
-      } 
-*/      
+
+      
+      
       
       //if(jentry>5) break;
     }
   }
-
+	//cout<<"all : "<<m_cells.size()<<endl;
+  Long64_t max(0);
+  Long64_t min_id=m_cells_in_sampling[0].begin()->first;
+  for(int i=0;i<21;++i) {
+		//cout<<"  cells sampling "<<i<<" : "<<m_cells_in_sampling[i].size()<<" cells";
+		//cout<<", "<<m_cells_in_regions[i].size()<<" lookup map(s)"<<endl;
+		for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+			//cout << it->second->getSampling() << " " << it->first << endl;
+			if(min_id/10 >=  it->first){
+				//cout << "Warning: Identifiers are not in increasing order!!!!" << endl;
+				//cout << min_id << " " << it->first << endl;
+				
+			}
+			if(min_id > it->first)min_id = it->first;
+		}
+	}
+	//cout << "Min id for samplings < 21: " << min_id << endl;
   delete f;
-
+	//return true;
   return PostProcessGeometry();
 }
 
+
+bool CaloGeometryFromFile::LoadFCalGeometryFromFiles(TString filename1,TString filename2,TString filename3){
+	
+	vector<ifstream*> electrodes(3);
+  
+  electrodes[0]=new ifstream(filename1);
+  electrodes[1]=new ifstream(filename2);
+  electrodes[2]=new ifstream(filename3);
+	
+	
+	int	thisTubeId;
+  int    thisTubeI;
+	int    thisTubeJ;
+	//int    thisTubeID;
+	int    thisTubeMod;
+	double thisTubeX;
+	double thisTubeY;
+	TString tubeName;
+	
+	int second_column;
+	string seventh_column;
+	string eight_column;
+	int ninth_column;
+
+	
+	
+	
+	
+	int i;
+	for(int imodule=1;imodule<=3;imodule++){
+		
+		i=0;
+		//while(i<50){
+		while(1){
+		
+		  //cout << electrodes[imodule-1]->eof() << endl;
+			(*electrodes[imodule-1]) >> tubeName;
+			if(electrodes[imodule-1]->eof())break;
+			(*electrodes[imodule-1]) >> thisTubeId; // ?????
+			(*electrodes[imodule-1]) >> thisTubeI;
+			(*electrodes[imodule-1]) >> thisTubeJ;
+			(*electrodes[imodule-1]) >> thisTubeX;
+			(*electrodes[imodule-1]) >> thisTubeY;
+			(*electrodes[imodule-1]) >> seventh_column;
+			(*electrodes[imodule-1]) >> eight_column;
+			(*electrodes[imodule-1]) >> ninth_column;
+			
+			tubeName.ReplaceAll("'","");
+			string tubeNamestring=tubeName.Data();
+			
+			std::istringstream tileStream1(std::string(tubeNamestring,1,1));
+		  std::istringstream tileStream2(std::string(tubeNamestring,3,2));
+		  std::istringstream tileStream3(std::string(tubeNamestring,6,3));
+		  int a1=0,a2=0,a3=0;
+		  if (tileStream1) tileStream1 >> a1;
+		  if (tileStream2) tileStream2 >> a2;
+		  if (tileStream3) tileStream3 >> a3;
+			
+			unsigned int tileName= (a3 << 16) + a2;
+			stringstream s;
+			
+			
+			m_FCal_ChannelMap.add_tube(tubeNamestring, imodule, thisTubeId, thisTubeI,thisTubeJ, thisTubeX, thisTubeY,seventh_column);
+			
+			
+			
+			//cout << "FCal electrodes: " << tubeName << " " << second_column << " " << thisTubeI << " " << thisTubeJ << " " << thisTubeX << " " << thisTubeY << " " << seventh_column << " " << eight_column << " " << ninth_column << endl;
+			//cout << tileStream1.str() << " " << tileStream2.str() << " " << tileStream3.str() << endl;
+			//cout << a1 << " " << a2 << " " << a3 << " " << tileName << endl;
+			i++;
+		}
+	}
+	m_FCal_ChannelMap.finish(); // Creates maps
+	
+	Long64_t phi_index,eta_index;
+	float x,y,dx,dy;
+	long id;
+	//auto it =m_cells_in_sampling[20].rbegin();
+	//it--;
+	//Long64_t identify=it->first;
+	//for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+	//	
+	//}
+	long mask1[]{0x34,0x34,0x35};
+	long mask2[]{0x36,0x36,0x37};
+	
+	for(int imap=1;imap<=3;imap++){
+		for(auto it=m_FCal_ChannelMap.begin(imap);it!=m_FCal_ChannelMap.end(imap);it++){
+			phi_index = it->first & 0xffff;
+			eta_index = it->first >> 16;
+			CaloGeoDetDescrElement *DDE =new CaloGeoDetDescrElement; // side C
+			CaloGeoDetDescrElement *DDE2 =new CaloGeoDetDescrElement; // side A
+			x=it->second.x();
+			y=it->second.y();
+			m_FCal_ChannelMap.tileSize(imap, eta_index, phi_index,dx,dy);
+			//if(imap==2) eta_index+=100;
+			//if(imap==3) eta_index+=200;
+			//cout << imap << " " << eta_index << " " << phi_index << " " <<  it->first << " " << (eta_index << 16) + phi_index << endl;
+			
+			DDE->m_calosample=imap+20;
+			DDE->m_x=x;
+			DDE->m_y=y;
+			DDE->m_x_raw=x;
+			DDE->m_y_raw=y;
+			DDE->m_dx=dx;
+			DDE->m_dy=dy;
+			
+			DDE2->m_calosample=imap+20;
+			DDE2->m_x=x;
+			DDE2->m_y=y;
+			DDE2->m_x_raw=x;
+			DDE2->m_y_raw=y;
+			DDE2->m_dx=dx;
+			DDE2->m_dy=dy;
+			
+			id=(mask1[imap-1]<<12) + (eta_index << 5) +2*phi_index;
+			if(imap==2) id+= (8<<8);
+			DDE->m_identify=(id << 44);
+			//DDE->m_identify=(id << 12);
+			//cout << DDE->identify() << endl;
+			addcell(DDE);
+			id=(mask2[imap-1]<<12) + (eta_index << 5) +2*phi_index;
+			if(imap==2) id+= (8<<8);
+			DDE2->m_identify=(id << 44);
+						//DDE->m_identify=(id << 12);
+			addcell(DDE2);
+		}
+	
+	}
+	auto it =m_cells_in_sampling[0].begin();
+	//it--;
+	Long64_t identify=it->first;
+	//cout << "min identifier from sampling < 21: " << identify << endl;
+	
+	for(int i=21;i<MAX_SAMPLING;++i) {
+        //cout<<"  cells sampling "<<i<<" : "<<m_cells_in_sampling[i].size()<<" cells";
+        //cout<<", "<<m_cells_in_regions[i].size()<<" lookup map(s)"<<endl;
+        for(auto it=m_cells_in_sampling[i].begin(); it!=m_cells_in_sampling[i].end();it++){
+					//cout << it->second->getSampling() << " " << it->first << endl;
+				}
+        
+  }
+	return true;
+}
+
+void CaloGeometryFromFile::DrawFCalGraph(int isam,int color){
+	
+	stringstream ss;
+	ss << "FCal" << isam - 20 << endl;
+	TString name = ss.str().c_str();
+	
+	const int size=m_cells_in_sampling[isam].size();
+	double x[size];
+	double y[size];
+	const CaloGeoDetDescrElement* cell;
+	int i=0;
+	for(auto it=m_cells_in_sampling[isam].begin();it!=m_cells_in_sampling[isam].end();it++){
+		x[i]=it->second->x();
+		y[i]=it->second->y();
+		i++;
+	}
+	// cout << size << endl;
+	//TH2D* h = new TH2D("","",10,-0.5,0.5,10,-0.5,0.5);
+	//h->SetStats(0);
+	//h->Draw();
+	TGraph* graph = new TGraph(size,x,y);
+	graph->SetLineColor(color);
+	graph->SetTitle(name);
+	graph->SetMarkerStyle(21);
+	graph->SetMarkerColor(color);
+	graph->SetMarkerSize(0.5);
+	graph->GetXaxis()->SetTitle("x");
+	graph->GetYaxis()->SetTitle("y");
+	
+	graph->Draw("AP");
+
+	
+	
+}	
+		
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.h
index eb87c14820944231ef3c0504e2e4859ed5ff7baf..fe387c317bad940eda9c9baa12edc970d3b39f8b 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloGeometryFromFile.h
@@ -13,6 +13,8 @@ public :
    virtual ~CaloGeometryFromFile();
    
    virtual bool LoadGeometryFromFile(TString filename,TString treename);
+   virtual bool LoadFCalGeometryFromFiles(TString filename1,TString filename2,TString filename3);
+   void DrawFCalGraph(int isam,int color);
 };
 
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CopyParam2File.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CopyParam2File.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4d7c8125d37319d03bf34555f33c6c12b56445d9
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CopyParam2File.cxx
@@ -0,0 +1,177 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+  * Prerequisites:
+  *
+  * -) 
+  *
+  * $ root -l -b -q 'CopyParam2File.cxx("shape.pdgid_211.en_50000.eta_020.root", "EnergyParam", 211, 50000, 0.20)'
+  * 
+ */
+#include "TROOT.h"
+#include "TRint.h"
+#include "TKey.h"
+#include "TFile.h"
+#include "TSystem.h"
+#include "TTree.h"
+#include <string>
+
+// build string sparam.<pdgid>.<energy>.<eta>.<pca#>.<layer#>
+std::string doSParam(std::string pstr, std::string kstr) {
+  std::string delim1 = "layer";
+  std::string delim2 = "_";
+  std::string delim3 = "pca";
+  size_t l_startpos = kstr.find(delim1)+delim1.length();
+  size_t l_endpos = kstr.find_last_of(delim2)-(kstr.find(delim1)+delim1.length());
+  size_t p_startpos = kstr.find(delim3)+delim3.length();
+  std::string lNum = kstr.substr(l_startpos, l_endpos);
+  std::string pNum = kstr.substr(p_startpos,std::string::npos);
+  return pstr.append(".pca_"+pNum+".layer_"+lNum);
+}
+
+// build string eparam.<pdgid>.<energy>.<eta>.<pca#>.<
+std::string doEParam(std::string pstr, std::string kstr, std::string dirstr) {
+  std::string lNum;
+  std::string retstr = "";
+  // bin/pca common amongst all
+  std::string delim1 = "bin";
+  std::string delim2 = "/";
+  size_t p_startpos = dirstr.find(delim1)+delim1.length();
+  size_t p_endpos = dirstr.find_last_of(delim2)-(dirstr.find(delim1)+delim1.length());
+  std::string pNum = dirstr.substr(p_startpos, p_endpos);
+  pstr.append(".pca_"+pNum);
+  // check if we are in a pca dir
+  if (dirstr.find("pca") != std::string::npos) {
+    retstr = pstr+"."+kstr;
+  }
+  // ...in a layer dir?
+  else if (dirstr.find("layer") != std::string::npos) {
+    size_t l_startpos = dirstr.find("layer")+std::string("layer").length();
+    retstr = pstr+".layer_"+dirstr.substr(l_startpos, std::string::npos);
+  }
+  // ...must be a `totalE`!
+  else if (dirstr.find("totalE") != std::string::npos) {
+    retstr = pstr+".totalE";
+  }
+  // Nope -- we don't know where we are!
+  else {
+    std::cout << "ERROR: where are we? (Not a `layer` or `pca`, that's for sure!)" << std::endl;
+    exit(1);
+  }
+
+  std::cout << "\tretstr: " << retstr << std::endl;
+  return retstr;
+}
+
+void copyDir(TDirectory* src, std::string param_str) {
+  // Copy src dir to dest
+  src->ls();
+  TDirectory* savdir = gDirectory;
+  TDirectory* adir = savdir;
+  adir->cd();
+  // loop on all entries in src
+  TKey* key;
+  TIter nextkey(src->GetListOfKeys());
+  while ((key = (TKey*) nextkey())) {
+    const char *classname = key->GetClassName();
+    TClass *cl = gROOT->GetClass(classname);
+    if (!cl) continue;
+    if (cl->InheritsFrom("TDirectory")) {
+//      adir = savdir->mkdir(key->GetName());
+      src->cd(key->GetName());
+      TDirectory *subdir = gDirectory;
+      adir->cd();
+      copyDir(subdir, param_str);
+      adir->cd();
+    } else if (cl->InheritsFrom("TTree")) {
+      TTree *T = (TTree*)src->Get(key->GetName());
+      adir->cd();
+      TTree *newT = (TTree*)T->CloneTree();
+      newT->Write();
+    } else {
+      src->cd();
+      TObject *obj = key->ReadObj();
+      adir->cd();
+      std::string complete_param_str;
+      if (param_str.substr(0,1) == "s") complete_param_str = doSParam(param_str, std::string(key->GetName()));
+      else if (param_str.substr(0,1) == "e") complete_param_str = doEParam(param_str, std::string(key->GetName()), std::string(src->GetPath()));
+      obj->Write(complete_param_str.c_str(),TObject::kWriteDelete);
+      delete obj;
+    }
+  }
+  adir->SaveSelf(kTRUE);
+  savdir->cd();
+}
+
+void copyFile(const char* fname, std::string param_str) {
+  TDirectory* target = gDirectory;
+  TFile* fsrc = TFile::Open(fname);
+  if (!fsrc || fsrc->IsZombie()) {
+    printf("Cannot open source file: %s", fname);
+    target->cd();
+    return;
+  }
+  // Copy dir from src to dest
+  target->cd("/");
+  copyDir(fsrc, param_str);
+  delete fsrc;
+  target->cd();
+}
+
+void 
+CopyParam2File(std::string src_str, std::string param_type, unsigned int pdgid, unsigned int energy, float eta, std::string dest_str = "FCSParams.root") {
+  // ROOT-aware
+  TLorentzVector* t;
+  gROOT->LoadMacro("../20.20.X-VAL/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/IntArray.cxx+");
+  gROOT->LoadMacro("../20.20.X-VAL/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx+");
+  gROOT->LoadMacro("../20.20.X-VAL/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionRegression.cxx+");
+  gROOT->LoadMacro("../20.20.X-VAL/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionRegressionTF.cxx+");
+  gROOT->LoadMacro("../20.20.X-VAL/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionHistogram.cxx+");
+
+  // Destination (where to write to)
+  TFile* fdest = TFile::Open(dest_str.c_str(), "UPDATE");
+  if (!fdest || fdest->IsZombie()) {
+    printf("Cannot open destination file: %s (it doesn't exist?)", dest_str.c_str());
+    printf("Creating file...");
+    fdest = TFile::Open(dest_str.c_str(), "CREATE");
+    // Check if the new file creation was a success; if not, exit with an error.
+    if (!fdest || fdest->IsZombie()) {
+      printf("Cannot create destination file: %s (something went wrong)", dest_str.c_str());
+      return;
+    }
+  }
+
+  std::string s_param_prefix;
+  char param_prefix[100];
+
+  if (param_type == "EnergyParam") {
+    s_param_prefix = "eparam";
+  }
+  else if (param_type == "ShapeParam") {
+    s_param_prefix = "sparam";
+  }
+  else {
+    std::cout << "Invalid param_type. Valid param_type arguments are EnergyParam and ShapeParam." << std::endl;
+    exit(1);
+  }
+
+  // Get rid of the '.' in `eta`
+  std::ostringstream ss_eta;
+  ss_eta << fixed << setprecision(2) << eta;
+  std::string s_eta(ss_eta.str());
+  s_eta.erase(1,1);
+
+  // Construct complete param prefix
+  s_param_prefix.append(".pdgid_"+std::to_string(pdgid)+".en_"+std::to_string(energy)+".eta_"+s_eta);
+
+  // Copy src
+  copyFile(src_str.c_str(), s_param_prefix);
+
+  // cleanup
+  fdest->Close();
+  delete fdest;
+  return;
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/TestFCalIdentifiers.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/TestFCalIdentifiers.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ff464ecf552041ad3321988dc843c410c397d992
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/TestFCalIdentifiers.cxx
@@ -0,0 +1,155 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FCS_Cell.h"
+#include "../ISF_FastCaloSimParametrization/MeanAndRMS.h"
+#include "Identifier/Identifier.h"
+#include "CaloDetDescr/CaloDetDescrElement.h"
+#include "CaloGeometryFromFile.h"
+#include "CaloHitAna.h"
+#include "../ISF_FastCaloSimParametrization/CaloGeometry.h"
+#include "../ISF_FastCaloSimParametrization/FCAL_ChannelMap.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TString.h"
+#include <string>
+#include <sstream>
+#include <iostream>
+#include "TSystem.h"
+#include "TString.h"
+#include "TFile.h"
+#include <stdlib.h>
+#include "TLorentzVector.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TH1F.h"
+#include "TH2F.h"
+#include <vector>
+#include "TCanvas.h"
+//#include "MakeBins.C"
+using namespace std;
+
+void TestFCalIdentifiers(TString sampling="Sampling_0"){
+
+  CaloGeometryFromFile* geo=new CaloGeometryFromFile();
+  geo->LoadGeometryFromFile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSim/ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
+  geo->LoadFCalGeometryFromFiles("FCal1-electrodes.sorted.HV.09Nov2007.dat","FCal2-electrodes.sorted.HV.April2011.dat","FCal3-electrodes.sorted.HV.09Nov2007.dat");
+  
+  
+  FCAL_ChannelMap* channelMap =geo->GetFCAL_ChannelMap();
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  //TFile *inputFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/LArShift020715/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+  
+  //  TFile *inputFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/NTUP_110216/ISF_HitAnalysis_Zach1_merged.root");
+	
+	TFile *inputFile = TFile::Open("/eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000001.matched_output.root");
+	//TFile *inputFile = TFile::Open("/eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root");
+
+  TTree *inputTree = ( TTree* ) inputFile->Get( "FCS_ParametrizationInput" );
+
+  FCS_matchedcellvector *vec=0; //this need to be set to 0!
+  inputTree->SetBranchAddress(sampling,&vec);
+
+
+  std::cout << "Sampling is " << sampling << std::endl;
+
+  Int_t nEvt = inputTree->GetEntries();
+  std::cout << "nEvt " << nEvt << std::endl;
+  
+ // nEvt = 1000;
+  
+  stringstream ssIdentifier;
+  
+  for (Int_t ientry=0; ientry<nEvt; ientry++){
+    
+    inputTree->GetEntry(ientry);   
+    if(ientry%100 == 0)  
+      std::cout << "Processing event # " << ientry << std::endl;
+
+    double weight = 1.0;
+    //cout << (*vec).size() << endl;
+    //loop over cells in sampling
+    for (UInt_t j=0; j<(*vec).size(); j++){
+      
+      Float_t cell_E = 0.0;
+      cell_E = ((FCS_matchedcell)(*vec)[j]).cell.energy;
+      Long64_t cell_ID = 0;
+      cell_ID =  ((FCS_matchedcell)(*vec)[j]).cell.cell_identifier;
+			
+			cout << cell_ID << hex << " 0x"<< cell_ID << endl;
+     // cout << cell_E << endl;
+      
+      //now I use the geomery lookup tool to get the cell eta/phi
+     // const CaloDetDescrElement* cell;
+      Identifier cellid(cell_ID);
+      //cell=geo->getDDE(cellid); //This is working also for the FCal
+      
+      //loop over hits in the cell
+      for (unsigned int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
+	
+				//now I check what is the hit position
+				float x = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_x;
+				float y = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_y;
+				float z = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
+				float t = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_time;	
+				TLorentzVector *hitVec = new TLorentzVector(x, y, z, t);
+				const CaloDetDescrElement* foundCell;
+				int hitSampling =((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling; 
+				
+				//cout << hitSampling << " " << x << " " << y << endl;
+				
+				if(hitSampling<21)foundCell=geo->getDDE(hitSampling,hitVec->Eta(),hitVec->Phi());
+				else if(hitSampling<24)foundCell=geo->getFCalDDE(hitSampling,x,y,z);
+				else {
+					cout << endl << "Warning: Found hit with sampling > 23 !!!!!!!!!!!!!!" << endl << endl;
+					foundCell =0;
+				}
+				
+				
+				int ieta,iphi;
+				
+				//cout << "Hit position: " << "x: " << x << " y: " << y << " eta: " << hitVec->Eta() << " phi: " << hitVec->Phi() <<  endl;
+				
+				
+				
+				if (foundCell){// && cell){
+					channelMap->getTileID(hitSampling - 20,x,y,ieta,iphi);
+					ssIdentifier.str("");
+					
+					int zSide = 2;
+					ssIdentifier << 4          // LArCalorimeter
+             << 3          // LArFCAL
+             << zSide      // EndCap
+             << hitSampling   // FCal Module # 
+             << (ieta << 16)+iphi;  
+					
+					//cout << foundCell->x() << " " << foundCell->y()  << endl;
+					//cout << abs(foundCell->x() - x) << " " << abs(foundCell->y() - y) << endl;
+				  if( z > 0) cout << "Side A " << hex << foundCell->identify()  <<" " << cell_ID <<" " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].cell_identifier << dec << " " << cell_ID <<" " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].cell_identifier <<" " <<  ieta << " " << iphi << " " << (ieta << 16)+iphi << endl;
+				  else cout << "Side C " << hex << foundCell->identify()  <<" " << cell_ID << " " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].cell_identifier << dec<< " " << cell_ID <<" " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].cell_identifier << " " <<  ieta << " " << iphi << " " << (ieta << 16)+iphi << endl;
+				 // cout << cell_ID << " " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].identifier << " " << ((FCS_matchedcell)(*vec)[j]).hit[ihit].cell_identifier << " " << ((FCS_matchedcell)(*vec)[j]).g4hit[ihit].identifier << " " << ((FCS_matchedcell)(*vec)[j]).g4hit[ihit].cell_identifier << endl;
+				 
+				  
+				} //end if cell ok
+				else cout << "Cell not found!" << endl;
+      } //end loop over hits
+    } //end loop on cells   
+  } //end loop on events
+  
+  
+
+
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara.C
new file mode 100644
index 0000000000000000000000000000000000000000..133b6bb2c38499bf38e9b2e83362675f1f1fbfaf
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara.C
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TSystem.h"
+#include "TROOT.h"
+#include <iostream>
+
+#include "TLorentzVector.h"
+#include "TMatrixD.h"
+
+void init_epara();
+
+void init_epara()
+{
+ 
+ cout<<"hello"<<endl;
+ 
+ TLorentzVector *t;
+ TMatrixD *m;
+ 
+ gInterpreter->AddIncludePath("..");
+ gInterpreter->AddIncludePath("../epara");
+ gInterpreter->AddIncludePath("../../ISF_FastCaloSimEvent");
+ 
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/IntArray.cxx+");
+ gROOT->LoadMacro("../Root/TreeReader.cxx+");
+ gROOT->LoadMacro("../epara/firstPCA.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionRegression.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionRegressionTF.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionHistogram.cxx+");
+ gROOT->LoadMacro("../epara/TFCSFunction.cxx+");
+ gROOT->LoadMacro("../epara/TFCS1DRegression.cxx+");
+ gROOT->LoadMacro("../epara/secondPCA.cxx+");
+ 
+ /*
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSExtrapolationState.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSTruthState.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSSimulationState.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSParametrization.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSEnergyParametrization.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx+");
+ gROOT->LoadMacro("../Root/EnergyParametrizationValidation.cxx+");
+ */
+ 
+ cout<<"init done"<<endl;
+ 
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara_validation.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara_validation.C
new file mode 100644
index 0000000000000000000000000000000000000000..1b9514c4470d9a8757873832715ce7e504f3b4aa
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_epara_validation.C
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TSystem.h"
+#include "TROOT.h"
+#include <iostream>
+
+#include "TLorentzVector.h"
+#include "TMatrixD.h"
+
+void init_epara_validation();
+
+void init_epara_validation()
+{
+ 
+ cout<<"hello"<<endl;
+ 
+ TLorentzVector *t;
+ TMatrixD *m;
+ 
+ gInterpreter->AddIncludePath("..");
+ gInterpreter->AddIncludePath("../../ISF_FastCaloSimEvent");
+
+ gROOT->LoadMacro("../Root/TreeReader.cxx+");
+ 
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionRegression.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionRegressionTF.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCS1DFunctionHistogram.cxx+");
+ 
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/IntArray.cxx+");
+ 
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSExtrapolationState.cxx+");
+ 
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSTruthState.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSSimulationState.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSParametrization.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSEnergyParametrization.cxx+");
+ gROOT->LoadMacro("../../ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx+");
+ gROOT->LoadMacro("../Root/EnergyParametrizationValidation.cxx+");
+ 
+ cout<<"init done"<<endl;
+ 
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_geo.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_geo.C
new file mode 100644
index 0000000000000000000000000000000000000000..f3c901f1832518ea4813c8cc53fe54dc54b88349
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_geo.C
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TSystem.h"
+#include "TROOT.h"
+#include <iostream>
+
+#include "../ISF_FastCaloSimParametrization/MeanAndRMS.h"
+#include "Identifier/Identifier.h"
+#include "CaloDetDescr/CaloDetDescrElement.h"
+
+
+void init_geo();
+
+void init_geo()
+{
+ 
+ cout<<"init geometry test tool"<<endl;
+
+ gInterpreter->AddIncludePath("..");
+ gInterpreter->AddIncludePath("../../ISF_FastCaloSimEvent");
+
+ gROOT->LoadMacro("CaloSampling.cxx+");
+ gROOT->LoadMacro("../src/CaloGeometry.cxx+");
+ gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
+ gROOT->LoadMacro("../src/FCAL_ChannelMap.cxx+");
+ cout<<"init geometry done"<<endl;
+ cout << "running run_geo.C" << endl;
+ 
+ gROOT->ProcessLine(".x run_geo.C");
+ 
+ 
+ 
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_shapepara.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_shapepara.C
new file mode 100644
index 0000000000000000000000000000000000000000..2c36d9fee5f9d01614250c62efaa0aaba184a0be
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/init_shapepara.C
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TSystem.h"
+#include "TROOT.h"
+
+#include <iostream>
+
+using namespace std;
+
+void init_shapepara(bool);
+
+void init_shapepara(bool isStandAlone) {
+
+
+    if (!isStandAlone) {
+        // * load required macros
+
+        cout << " ** including paths and loading macros ...." << endl;
+
+        gInterpreter->AddIncludePath("..");
+        gInterpreter->AddIncludePath("../shapepara");
+        gInterpreter->AddIncludePath("../../ISF_FastCaloSimEvent");
+        gInterpreter->AddIncludePath("./");
+
+
+        gROOT->LoadMacro("CaloSampling.cxx+");
+        gROOT->LoadMacro("../src/CaloGeometry.cxx+");
+        gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
+        gROOT->LoadMacro("../src/FCAL_ChannelMap.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeThinning.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeStudy.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeBinning.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapePlotting.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeRegression.cxx+");
+
+    } else if (isStandAlone) {
+
+
+        cout << " ** configuring for standalone running ...." << endl;
+
+        gInterpreter->AddIncludePath("..");
+        gInterpreter->AddIncludePath("../shapepara");
+        gInterpreter->AddIncludePath("./");
+
+
+        gROOT->LoadMacro("../shapepara/ShowerShapeStudy.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeBinning.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapePlotting.cxx+");
+        gROOT->LoadMacro("../shapepara/ShowerShapeRegression.cxx+");
+
+
+    }
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA.cpp b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA.cpp
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA.cpp
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA.cpp
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_ToySimulation.cpp b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_ToySimulation.cpp
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_ToySimulation.cpp
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_ToySimulation.cpp
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Transformation.cpp b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Transformation.cpp
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Transformation.cpp
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Transformation.cpp
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Transformation.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Transformation.h
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Transformation.h
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Transformation.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Validation.cpp b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Validation.cpp
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/PCA_Validation.cpp
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/old_stuff/PCA_Validation.cpp
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C
index a8fdb65e7d51e62d55eb92f7f4f2a41c8ef3f899..6e7a21f315caec0f2dd1a06c3e9f078fc5be0155 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C
@@ -2,9 +2,14 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
+#include "AtlasStyle.C"
+#include "AtlasUtils.C"
+
 void rootlogon()
 {
   // Load ATLAS style
-  gROOT->LoadMacro("AtlasStyle.C");
   SetAtlasStyle();
+  gROOT->SetStyle("ATLAS");
+  gROOT->ForceStyle();
+ 
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C
deleted file mode 100644
index 3910d43f3dcdc165af8adbf6c73e66def450da9a..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-{
-
- //!!!remember to source the hacked tmva!!!
- //export LD_LIBRARY_PATH=/afs/cern.ch/user/s/schaarsc/public/fastcalo/trash/tests/mywork/TMVA-v4.2.0/lib:${LD_LIBRARY_PATH}
- //to do: migrate to root6, where this hack is implemented
-
- gSystem->AddIncludePath(" -I.. ");
- gROOT->LoadMacro("../Root/IntArray.cxx+");
- gROOT->LoadMacro("../Root/TreeReader.cxx+");
- gROOT->LoadMacro("../Root/firstPCA.cxx+");
- gROOT->LoadMacro("../Root/TFCS1DFunction.cxx+");
- gROOT->LoadMacro("../Root/TFCS1DFunctionRegression.cxx+");
- gROOT->LoadMacro("../Root/TFCS1DFunctionRegressionTF.cxx+");
- gROOT->LoadMacro("../Root/TFCS1DFunctionHistogram.cxx+");
- gROOT->LoadMacro("../Root/TFCSFunction.cxx+");
- gROOT->LoadMacro("../Root/secondPCA.cxx+");
- 
- string label;
- vector<string> input;
- 
- //label="pions";
- //input.push_back("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/NTUP_090315/ISF_HitAnalysis_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.matched.pool.root");
-  
- label="s2864";
- input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/*.root");
- 
- //label="s2865";
- //input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/*.root");
- 
- cout<<"*** Preparing to run on "<<label<<" ***"<<endl;
- TChain* mychain= new TChain("FCS_ParametrizationInput");
- for(int i=0;i<input.size();i++)
- {
- 	cout<<"input: "<<input[i]<<endl;
-  mychain->Add(input[i].c_str());
- }
- cout<<"TChain entries: "<<mychain->GetEntries()<<endl;
- 
- system(("mkdir /afs/cern.ch/user/s/schaarsc/public/fastcalo/pca/tools/output/"+label).c_str());
- string pca1_outfilename="/afs/cern.ch/user/s/schaarsc/public/fastcalo/pca/tools/output/"+label+"/firstPCA.root";
- string pca2_outfilename="/afs/cern.ch/user/s/schaarsc/public/fastcalo/pca/tools/output/"+label+"/secondPCA.root";
- 
- firstPCA *myfirstPCA=new firstPCA(mychain,pca1_outfilename);
- myfirstPCA->set_cumulativehistobins(5000);
- myfirstPCA->set_edepositcut(0.001);
- myfirstPCA->set_etacut(0.2,0.25);
- myfirstPCA->apply_etacut(0); //this flag is for the old files, which are already sliced in eta
- myfirstPCA->set_pcabinning(5,1);
- myfirstPCA->run();
- 
- secondPCA* mysecondPCA=new secondPCA(pca1_outfilename,pca2_outfilename);
- mysecondPCA->set_PCAbin(0); //all bins
- mysecondPCA->set_storeDetails(0);
- mysecondPCA->set_cumulativehistobins(5000);
- mysecondPCA->set_cut_maxdeviation_regression(5);
- mysecondPCA->set_cut_maxdeviation_smartrebin(5);
- mysecondPCA->set_Ntoys(1000);
- mysecondPCA->set_neurons_iteration(2,10);
- mysecondPCA->set_skip_regression(1);
- mysecondPCA->run();
- 
- //add validation class
- 
- 
-}
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runTestFCalIdentifiers.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runTestFCalIdentifiers.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..108f3d999bdb1e5c9f1f313d3ffe7064c6a5ccc9
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runTestFCalIdentifiers.cxx
@@ -0,0 +1,22 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+{
+  gStyle->SetOptStat(0);
+
+  gSystem->AddIncludePath(" -I.. ");
+
+  gROOT->LoadMacro("../ISF_FastCaloSimParametrization/MeanAndRMS.h+");
+  gROOT->LoadMacro("Identifier/Identifier.h+");
+  gROOT->LoadMacro("CaloDetDescr/CaloDetDescrElement.h+");
+  gROOT->LoadMacro("CaloSampling.cxx+");
+  gROOT->LoadMacro("../src/CaloGeometry.cxx+");
+  gROOT->LoadMacro("../src/FCAL_ChannelMap.cxx+");
+  gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
+  
+  gROOT->LoadMacro("TestFCalIdentifiers.cxx+");
+  TestFCalIdentifiers("Sampling_21");
+ 
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx
index a645854233bc180f08d933360cfb65f5a316ce08..140bf49fbf026d59df4d90874771e7f43fba4210 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx
@@ -13,6 +13,7 @@
   gROOT->LoadMacro("Identifier/Identifier.h+");
   gROOT->LoadMacro("CaloDetDescr/CaloDetDescrElement.h+");
   gROOT->LoadMacro("CaloSampling.cxx+");
+  gROOT->LoadMacro("../src/FCAL_ChannelMap.cxx+");
   gROOT->LoadMacro("../src/CaloGeometry.cxx+");
   gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
     
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx
index 56cdbca3e99d7e944e3b8740d2cbf59b2296055e..f2748b71d8a45502e37c3e2c0a74fd99e64bc9e8 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx
@@ -11,16 +11,17 @@
   gROOT->LoadMacro("Identifier/Identifier.h+");
   gROOT->LoadMacro("CaloDetDescr/CaloDetDescrElement.h+");
   gROOT->LoadMacro("CaloSampling.cxx+");
+  gROOT->LoadMacro("../src/FCAL_ChannelMap.cxx+");
   gROOT->LoadMacro("../src/CaloGeometry.cxx+");
   gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
   
   gROOT->LoadMacro("wiggle_closure_inputs.cxx+");
-  wiggle_closure_inputs("Sampling_0");
-  wiggle_closure_inputs("Sampling_1");
-  wiggle_closure_inputs("Sampling_2");
-  wiggle_closure_inputs("Sampling_3");
-  wiggle_closure_inputs("Sampling_12");
-  wiggle_closure_inputs("Sampling_13");
-  wiggle_closure_inputs("Sampling_14");
-
+  //wiggle_closure_inputs("Sampling_0");
+  //wiggle_closure_inputs("Sampling_1");
+  //wiggle_closure_inputs("Sampling_2");
+  //wiggle_closure_inputs("Sampling_3");
+  //wiggle_closure_inputs("Sampling_12");
+  //wiggle_closure_inputs("Sampling_13");
+	//wiggle_closure_inputs("Sampling_14");
+		wiggle_closure_inputs("Sampling_21");
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara.C
new file mode 100644
index 0000000000000000000000000000000000000000..82c98f1692852824f927de4a257488bf6c90b5b4
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara.C
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TChain.h"
+#include <iostream>
+
+
+void run_epara();
+
+void run_epara()
+{
+ 
+ 
+ //how to run in root 6.08 on lxplus7:
+ //source setup_root608.sh
+ //.x init_epara.C+
+ //.x run_epara.C
+ 
+ string label;
+ vector<string> input;
+ 
+ label="pions";
+ input.push_back("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/NTUP_090315/ISF_HitAnalysis_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.matched.pool.root");
+  
+ //label="s2864";
+ //input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/*.root");
+ 
+ //label="s2865";
+ //input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/*.root");
+ 
+ cout<<"*** Preparing to run on "<<label<<" ***"<<endl;
+ TChain* mychain= new TChain("FCS_ParametrizationInput");
+ for(int i=0;i<input.size();i++)
+ {
+ 	cout<<"input: "<<input[i]<<endl;
+  mychain->Add(input[i].c_str());
+ }
+ cout<<"TChain entries: "<<mychain->GetEntries()<<endl;
+  
+ system(("mkdir /afs/cern.ch/user/s/schaarsc/public/fastcalo/epara_storage/"+label).c_str());
+ string pca1_outfilename="/afs/cern.ch/user/s/schaarsc/public/fastcalo/epara_storage/"+label+"/firstPCA.root";
+ string pca2_outfilename="/afs/cern.ch/user/s/schaarsc/public/fastcalo/epara_storage/"+label+"/secondPCA.root";
+ 
+ firstPCA *myfirstPCA=new firstPCA(mychain,pca1_outfilename);
+ myfirstPCA->set_cumulativehistobins(5000);
+ myfirstPCA->set_edepositcut(0.001);
+ myfirstPCA->apply_etacut(0); //this flag is for the old files, which are already sliced in eta
+ myfirstPCA->set_etacut(0.2,0.25);
+ myfirstPCA->set_pcabinning(5,1);
+ myfirstPCA->run();
+ 
+ cout<<"1st pca done"<<endl;
+ 
+ secondPCA* mysecondPCA=new secondPCA(pca1_outfilename,pca2_outfilename);
+ mysecondPCA->set_PCAbin(0);
+ mysecondPCA->set_storeDetails(0);
+ mysecondPCA->set_cumulativehistobins(1000);
+ mysecondPCA->set_cut_maxdeviation_regression(5);
+ mysecondPCA->set_cut_maxdeviation_smartrebin(5);
+ mysecondPCA->set_Ntoys(5000);
+ mysecondPCA->set_neurons_iteration(2,16); //2,6
+ mysecondPCA->set_skip_regression(0);
+ mysecondPCA->run();
+ 
+ 
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara_validation.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara_validation.C
new file mode 100644
index 0000000000000000000000000000000000000000..6316b5dd4c6114cd41759d2301fa37105b3f4bbf
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_epara_validation.C
@@ -0,0 +1,301 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+TH1* get_cumul(TH1* hist);
+void run_epara_validation();
+
+//.x init_epara_validation.C+
+//.x run_epara_validation.C
+
+void run_epara_validation()
+{
+ 	
+ 	//parametrization input files:
+ 	
+  string sample="pions";
+  //string samplename="pions_s2864";
+  //string samplename="pions_s2865";
+    
+ 	string dirname ="/afs/cern.ch/user/s/schaarsc/public/fastcalo/epara_storage";
+  
+  system("mkdir eparavalidation");
+  system(("mkdir eparavalidation/"+sample).c_str());
+  /*
+  int setbin=-1;
+  cout<<"PCA bin (-1 if random)? "<<endl;
+  cin>>setbin;
+  */
+  //Prepare the Histograms
+  cout<<"Preparing validation histograms"<<endl;
+  TFile* file1=TFile::Open(Form("%s/%s/firstPCA.root",dirname.c_str(),sample.c_str()));
+  TH2I* h_layer=(TH2I*)file1->Get("h_layer");
+  int pcabins=h_layer->GetNbinsX();
+  vector<int> layerNr;
+  for(int i=1;i<=h_layer->GetNbinsY();i++)
+  {
+ 	 if(h_layer->GetBinContent(1,i)==1) 
+ 	  layerNr.push_back(h_layer->GetYaxis()->GetBinCenter(i));
+  }
+  vector<string> layer;
+  for(unsigned int l=0;l<layerNr.size();l++)
+   layer.push_back(Form("layer%i",layerNr[l]));
+  layer.push_back("totalE");
+  
+  for(unsigned int l=0;l<layer.size();l++)
+   cout<<"l "<<l<<" "<<layer[l]<<endl;
+  
+  int nbins=100;
+  TH1D* h_input[layer.size()+2];
+  TH1D* h_output[layer.size()+2];
+  for(unsigned int l=0;l<layerNr.size();l++)
+  {
+   h_input[l]=new TH1D(Form("h_input_%s",layer[l].c_str()),Form("h_input_%s",layer[l].c_str()),nbins,0,1);
+   h_output[l]=new TH1D(Form("h_output_%s",layer[l].c_str()),Form("h_output_%s",layer[l].c_str()),nbins,0,1);
+  }
+  //Total E
+  TTree* InputTree = (TTree*)file1->Get("tree_1stPCA");
+  TreeReader* read_inputTree = new TreeReader();
+  read_inputTree->SetTree(InputTree);
+
+  double minE=InputTree->GetMinimum("energy_totalE");
+  double maxE=InputTree->GetMaximum("energy_totalE");
+  cout<<"************************"<<endl;
+  cout<<"minE "<<minE<<" maxE "<<maxE<<endl;
+  h_input[layerNr.size()] =new TH1D("h_input_totalE","h_input_totalE",nbins,minE,maxE);
+  h_output[layerNr.size()]=new TH1D("h_output_totalE","h_output_totalE",nbins,minE,maxE);
+  //Fractions:
+  h_input[layer.size()]   =new TH1D("h_input_sumfractions_elmag","h_input_sumfractions_elmag",nbins,-1,2);
+  h_output[layer.size()]  =new TH1D("h_output_sumfractions_elmag","h_output_sumfractions_elmag",nbins,-1,2);
+  h_input[layer.size()+1] =new TH1D("h_input_sumfractions_had","h_input_sumfractions_had",nbins,-1,2);
+  h_output[layer.size()+1]=new TH1D("h_output_sumfractions_had","h_output_sumfractions_had",nbins,-1,2);
+  
+  //Fill the Input Histograms:
+  vector<int> elmag; //0-8
+  for(int e=0;e<=8;e++) elmag.push_back(e);
+  vector<int> had;   //9-24
+  for(int h=9;h<25;h++) had.push_back(h);
+  
+  cout<<"Now fill input histograms"<<endl;
+  for(int event=0;event<read_inputTree->GetEntries();event++)
+  {
+   read_inputTree->GetEntry(event);
+   //if(setbin<0 || (setbin>=1 && read_inputTree->GetVariable("firstPCAbin")==setbin))
+   //{
+   double sum_fraction_elmag=0.0;
+   double sum_fraction_had=0.0;
+   double data = read_inputTree->GetVariable("energy_totalE");
+   h_input[layerNr.size()]->Fill(data);
+   for(unsigned int l=0;l<layerNr.size();l++)
+   {
+   	double data = read_inputTree->GetVariable(Form("energy_%s",layer[l].c_str()));
+   	h_input[l]->Fill(data);
+   	
+   	int is_elmag,is_had;
+   	is_elmag=is_had=0;
+    
+    for(int e=0;e<elmag.size();e++)
+    { 	  if(elmag[e]==layerNr[l]) is_elmag=1;   }
+    for(int h=0;h<had.size();h++)
+    { 	  if(had[h]==layerNr[l]) is_had=1;   }
+    if(is_elmag) sum_fraction_elmag+=data;
+    if(is_had)   sum_fraction_had+=data;
+   }
+   h_input[layerNr.size()+1]->Fill(sum_fraction_elmag);
+   h_input[layerNr.size()+2]->Fill(sum_fraction_had);
+   //}
+  }
+  
+  TH1D* h_randombin=new TH1D("h_randombin","h_randombin",pcabins,-0.5,pcabins-0.5);
+  
+   
+  TFCSPCAEnergyParametrization etest("etest","etest");
+  TFile* file2 = TFile::Open("/afs/cern.ch/atlas/groups/Simulation/FastCaloSimV2/FCSParams.root");
+  cout<<"pca bins before load "<<etest.n_pcabins()<<endl;
+  etest.loadInputs(file2);
+  cout<<"number of pca bins after load "<<etest.n_pcabins()<<" , number from firstPCA file: "<<pcabins<<endl;
+  file2->Close();
+  delete file2;
+
+  //Run the loop:
+  int ntoys=1000;
+  TRandom3* Random=new TRandom3();
+  Random->SetSeed(0);
+  const TFCSTruthState* truth=new TFCSTruthState();
+  const TFCSExtrapolationState* extrapol=new TFCSExtrapolationState();
+  for(int i=0;i<ntoys;i++)
+  {
+   //if(i%100==0) 
+   	cout<<"Now run simulation for Toy "<<i<<endl;
+   
+   int randombin=0;
+   double uniform=Random->Uniform(1);
+   for(int n=0;n<pcabins;n++)
+   {
+    if(uniform>n*1.0/(double)pcabins && uniform<(n+1.)*1.0/(double)pcabins)
+     randombin=n+1;
+   }
+   h_randombin->Fill(randombin);
+         
+   TFCSSimulationState simulstate;
+   simulstate.set_Ebin(randombin);
+   
+   etest.simulate(simulstate, truth, extrapol);
+   
+   //fill the Histograms:
+   double sum_fraction_elmag=0.0;
+   double sum_fraction_had=0.0;
+   
+   for(int s=0;s<30;s++) //30 is a dummy number, sth big
+   {
+   	int is_elmag,is_had;
+   	is_elmag=is_had=0;
+   	for(unsigned int l=0;l<layerNr.size();l++)
+    {
+     if(s==layerNr[l])
+     {
+   	  h_output[l]->Fill(simulstate.Efrac(s));
+      for(int e=0;e<elmag.size();e++)
+      { 	  if(elmag[e]==layerNr[l]) is_elmag=1;   }
+      for(int h=0;h<had.size();h++)
+      { 	  if(had[h]==layerNr[l]) is_had=1;   }
+      if(is_elmag) sum_fraction_elmag+=simulstate.Efrac(s);
+      if(is_had)   sum_fraction_had+=simulstate.Efrac(s);
+     }
+    }
+   }
+   h_output[layerNr.size()]->Fill(simulstate.E());
+   h_output[layerNr.size()+1]->Fill(sum_fraction_elmag);
+   h_output[layerNr.size()+2]->Fill(sum_fraction_had);
+   
+  } //loop over toys
+  
+  
+  cout<<"Now making validation plots"<<endl;
+  
+  vector<string> name;
+  vector<string> title;
+  for(unsigned int l=0;l<layer.size()-1;l++)
+  {
+   name.push_back(layer[l].c_str());
+   title.push_back(Form("E fraction in Layer %i",layerNr[l]));
+  }
+  name.push_back("totalE");
+  name.push_back("sumfraction_elmag");
+  name.push_back("sumfraction_had");
+  title.push_back("total E [MeV]");
+  title.push_back("Sum of E fractions in elmag. layers");
+  title.push_back("Sum of E fractions in had. layers");
+  
+  for(unsigned int l=0;l<layer.size()+2;l++)
+  {
+   //TCanvas* can=new TCanvas(Form("can_%i",l),Form("can_%i",l),0,0,1600,600);
+   TCanvas* can=new TCanvas("can","can",0,0,1600,600);
+   can->Divide(3,1);
+   can->cd(1); //linear scale
+   double min,max,rmin,rmax;
+
+   int use_autozoom=1;
+   TH1D* h_output_lin;
+   TH1D* h_input_lin;
+   if(use_autozoom)
+   {
+    EnergyParametrizationValidation::autozoom(h_input[l],min,max,rmin,rmax);
+    h_output_lin=EnergyParametrizationValidation::refill(h_output[l],min,max,rmin,rmax);  h_output_lin->SetName("h_output_lin");
+    h_input_lin=EnergyParametrizationValidation::refill(h_input[l],min,max,rmin,rmax); h_input_lin->SetName("h_input_lin");
+   }
+   else
+   {
+   	h_output_lin=(TH1D*)h_output[l]->Clone("h_output_lin");
+   	h_input_lin=(TH1D*)h_input[l]->Clone("h_input_lin");
+   }
+   
+   double kolmo=h_input[l]->KolmogorovTest(h_output[l]);
+   double chi2=h_input[l]->Chi2Test(h_output[l],"UW");
+
+   h_input_lin->SetMarkerSize(1.0);
+   h_input_lin->SetLineWidth(1);
+   h_output_lin->SetLineWidth(1);
+   h_output_lin->SetFillColor(7);
+   
+   h_output_lin->Scale(h_input[l]->Integral()/h_output_lin->Integral());
+   h_input_lin->Draw("e");
+   h_input_lin->GetXaxis()->SetNdivisions(504,kFALSE);
+   double ymax=h_input_lin->GetBinContent(h_input_lin->GetMaximumBin());
+   h_input_lin->GetYaxis()->SetRangeUser(0,ymax*1.4);
+   h_input_lin->GetYaxis()->SetTitle("Linear");
+   h_input_lin->GetXaxis()->SetTitle(title[l].c_str());
+   h_output_lin->Draw("histsame");
+   h_input_lin->Draw("esame");
+   
+   TLegend* leg=new TLegend(0.65,0.82,0.99,0.93);
+   leg->SetBorderSize(0);
+   leg->SetFillStyle(0);
+   leg->SetHeader(Form("KS: %.2f, Chi2: %.2f",kolmo,chi2));
+   leg->AddEntry(h_output_lin,"Parametrisation","f");
+   leg->AddEntry(h_input_lin,"G4 Input","lpe");
+   leg->Draw();
+  
+   can->cd(2);
+   TH1D* h_output_log=(TH1D*)h_output_lin->Clone("h_output_log");
+   TH1D* h_input_log=(TH1D*)h_input_lin->Clone("h_input_log");
+   h_input_log->Draw("e");
+   h_input_log->GetYaxis()->SetRangeUser(0.1,ymax*5.0);
+   h_input_log->GetYaxis()->SetTitle("Log");
+   h_output_log->Draw("histsame");
+   h_input_log->Draw("esame");
+   can->cd(2)->SetLogy();
+   TLegend* leg2=new TLegend(0.65,0.82,0.99,0.93);
+   leg2->SetBorderSize(0);
+   leg2->SetFillStyle(0);
+   leg2->SetHeader(Form("KS: %.2f, Chi2: %.2f",kolmo,chi2));
+   leg2->AddEntry(h_output_lin,"Parametrisation","f");
+   leg2->AddEntry(h_input_lin,"G4 Input","lpe");
+   leg2->Draw();
+   
+   can->cd(3);
+   TH1D* h_output_cumul=(TH1D*)get_cumul(h_output_lin); h_output_cumul->SetName("h_output_cumul");
+   TH1D* h_input_cumul =(TH1D*)get_cumul(h_input_lin);  h_input_cumul->SetName("h_input_cumul");
+   double sf=h_input_cumul->GetBinContent(h_input_cumul->GetNbinsX());
+   h_output_cumul->Scale(1.0/sf);
+   h_input_cumul->Scale(1.0/sf);
+   h_input_cumul->Draw("e");
+   h_input_cumul->GetYaxis()->SetRangeUser(0,1.2);
+   h_input_cumul->GetYaxis()->SetTitle("Cumulative");
+   h_output_cumul->Draw("histsame");
+   h_input_cumul->Draw("esame");
+   TLegend* leg3=new TLegend(0.19,0.82,0.53,0.93);
+   leg3->SetBorderSize(0);
+   leg3->SetFillStyle(0);
+   leg3->SetHeader(Form("KS: %.2f, Chi2: %.2f",kolmo,chi2));
+   leg3->AddEntry(h_output_lin,"Parametrisation","f");
+   leg3->AddEntry(h_input_lin,"G4 Input","lpe");
+   leg3->Draw();
+   
+   can->cd(1)->RedrawAxis();
+   can->cd(2)->RedrawAxis();
+   can->cd(3)->RedrawAxis();
+   
+   can->Print(Form("eparavalidation/%s/%s.pdf",sample.c_str(),name[l].c_str()));
+   
+   delete can;
+   
+  } //for layer
+  
+  
+}
+
+
+TH1* get_cumul(TH1* hist)
+{
+  TH1D* h_cumul=(TH1D*)hist->Clone("h_cumul");
+  double sum=0;
+  for(int b=1;b<=h_cumul->GetNbinsX();b++)
+  {
+    sum+=hist->GetBinContent(b);
+    h_cumul->SetBinContent(b,sum);
+  }
+  return h_cumul; 
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_geo.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_geo.C
new file mode 100644
index 0000000000000000000000000000000000000000..b6ec56c5da96317077e3b30b0ca2ab45eaa44ca6
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_geo.C
@@ -0,0 +1,193 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TChain.h"
+#include <iostream>
+#include "TGraph.h"
+
+void run_geo();
+
+void run_geo()
+{
+  
+ //how to run in root 6 on lxplus:
+ //.x init_geo.C+
+ //.x run_geo.C
+ 
+ // Warning: cell lookup in the FCal is not working yet!
+ CaloGeometryFromFile* geo=new CaloGeometryFromFile();
+ geo->SetDoGraphs(1);
+ geo->LoadGeometryFromFile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSim/ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
+ geo->LoadFCalGeometryFromFiles("FCal1-electrodes.sorted.HV.09Nov2007.dat","FCal2-electrodes.sorted.HV.April2011.dat","FCal3-electrodes.sorted.HV.09Nov2007.dat");
+  //CaloGeometry::m_debug_identity=3179554531063103488;
+	//geo->Validate();
+ 
+ 
+  const CaloGeoDetDescrElement* cell;
+  cell=geo->getDDE(2,0.24,0.24); //This is not working yet for the FCal!!!
+  //cout<<"Found cell id="<<cell->identify()<<" sample="<<cell->getSampling()<<" eta="<<cell->eta()<<" phi="<<cell->phi()<<endl;
+  
+  unsigned long long cellid64(3179554531063103488);
+  Identifier cellid(cellid64);
+  cell=geo->getDDE(cellid); //This is working also for the FCal
+  
+  cout<<"Found cell id="<<cell->identify()<<" sample="<<cell->getSampling()<<" eta="<<cell->eta()<<" phi="<<cell->phi()<<endl;
+  
+  /*TCanvas* canvas = new TCanvas("Calo_layout","Calo layout");
+  TH2D* hcalolayout=new TH2D("hcalolayout","hcalolayout",50,-7000,7000,50,0,4000);
+  hcalolayout->Draw();
+  hcalolayout->SetStats(0);
+  
+  for(int i=0;i<24;++i) {
+    double eta=0.2;
+    double mineta,maxeta;
+    geo->minmaxeta(i,eta,mineta,maxeta);
+    cout<<geo->SamplingName(i)<<" : mineta="<<mineta<<" maxeta="<<maxeta<<endl;
+    if(mineta<eta && maxeta>eta) {
+      double avgeta=eta;
+      cout<<"  r="<<geo->rent(i,avgeta)<<" -> "<<geo->rmid(i,avgeta)<<" -> "<<geo->rext(i,avgeta)<<endl;
+    }  
+    geo->GetGraph(i)->Draw("Psame");
+  }
+  
+  geo->DrawGeoForPhi0();
+  canvas->SaveAs("Calorimeter.png");*/
+  
+  TCanvas* canvas = new TCanvas("FCal1_xy","FCal1_xy");
+  geo->DrawFCalGraph(21,1);
+	canvas->SaveAs("FCal1Geometry.png");
+	TCanvas* canvas2 = new TCanvas("FCal2_xy","FCal2_xy");
+  geo->DrawFCalGraph(22,1);
+	canvas2->SaveAs("FCal2Geometry.png");
+	TCanvas* canvas3 = new TCanvas("FCal3_xy","FCal3_xy");
+  geo->DrawFCalGraph(23,1);
+	canvas3->SaveAs("FCal3Geometry.png");
+  
+  
+  
+  
+  vector<ifstream*> electrodes(3);
+  
+  electrodes[0]=new ifstream("FCal1-electrodes.sorted.HV.09Nov2007.dat");
+  electrodes[1]=new ifstream("FCal2-electrodes.sorted.HV.April2011.dat");
+  electrodes[2]=new ifstream("FCal3-electrodes.sorted.HV.09Nov2007.dat");
+  
+  
+  
+  int	thisTubeId;
+  int    thisTubeI;
+	int    thisTubeJ;
+	//int    thisTubeID;
+	int    thisTubeMod;
+	double thisTubeX;
+	double thisTubeY;
+	TString tubeName;
+	
+	int second_column;
+	string seventh_column;
+	string eight_column;
+	int ninth_column;
+	
+	FCAL_ChannelMap *cmap = new FCAL_ChannelMap(0);
+	
+	
+	
+	
+	int i;
+	for(int imodule=1;imodule<=3;imodule++){
+		
+		i=0;
+		//while(i<50){
+		while(1){
+		
+		  //cout << electrodes[imodule-1]->eof() << endl;
+			(*electrodes[imodule-1]) >> tubeName;
+			if(electrodes[imodule-1]->eof())break;
+			(*electrodes[imodule-1]) >> thisTubeId; // ?????
+			(*electrodes[imodule-1]) >> thisTubeI;
+			(*electrodes[imodule-1]) >> thisTubeJ;
+			(*electrodes[imodule-1]) >> thisTubeX;
+			(*electrodes[imodule-1]) >> thisTubeY;
+			(*electrodes[imodule-1]) >> seventh_column;
+			(*electrodes[imodule-1]) >> eight_column;
+			(*electrodes[imodule-1]) >> ninth_column;
+			
+			tubeName.ReplaceAll("'","");
+			string tubeNamestring=tubeName.Data();
+			
+			std::istringstream tileStream1(std::string(tubeNamestring,1,1));
+		  std::istringstream tileStream2(std::string(tubeNamestring,3,2));
+		  std::istringstream tileStream3(std::string(tubeNamestring,6,3));
+		  int a1=0,a2=0,a3=0;
+		  if (tileStream1) tileStream1 >> a1;
+		  if (tileStream2) tileStream2 >> a2;
+		  if (tileStream3) tileStream3 >> a3;
+			
+			unsigned int tileName= (a3 << 16) + a2;
+			stringstream s;
+			
+			
+			cmap->add_tube(tubeNamestring, imodule, thisTubeId, thisTubeI,thisTubeJ, thisTubeX, thisTubeY,seventh_column);
+			
+			
+			
+			//cout << "FCal electrodes: " << tubeName << " " << second_column << " " << thisTubeI << " " << thisTubeJ << " " << thisTubeX << " " << thisTubeY << " " << seventh_column << " " << eight_column << " " << ninth_column << endl;
+			//cout << tileStream1.str() << " " << tileStream2.str() << " " << tileStream3.str() << endl;
+			//cout << a1 << " " << a2 << " " << a3 << " " << tileName << endl;
+			i++;
+		}
+	}
+	cmap->finish(); // Creates maps
+	 
+	cmap->print_tubemap(1);
+  cmap->print_tubemap(2);
+  cmap->print_tubemap(3);
+  
+  int eta_index,phi_index;
+  Long64_t eta_index64,phi_index64;
+  double x=130;
+  double y=180;
+  
+  
+  const CaloGeoDetDescrElement* mcell=0;
+  const CaloGeoDetDescrElement* mcell2=0;
+  
+  cout << endl;
+  cout << "Looking for tile corresponding to [x,y] = [" <<  x << "," << y << "]" << endl;
+  
+  for(int imap=1;imap<=3;imap++){
+  
+		cout << "Looking for tile in module " << imap << endl;
+	  if(!cmap->getTileID(imap,x,y,eta_index,phi_index)){
+			cout << "Not found" << endl;continue;
+		}
+	  cout << "Tile found" << endl;
+	 
+	 cout << "Tile Id " << (eta_index << 16) + phi_index << endl;
+		cout << "eta index: " << eta_index << endl;
+		cout << "phi index: " << phi_index << endl;
+		cout << "Tile position: [x,y] = [" <<  cmap->x(imap,eta_index,phi_index) << "," << cmap->y(imap,eta_index,phi_index) << "]" << endl;
+		mcell=geo->getFCalDDE(imap+20,x,y,-1);
+		cout << "Tile position for calogeometry: [x,y] = [" <<  mcell->x() << "," << mcell->y() << "]" << endl;
+		
+		Identifier identifier= mcell->identify();
+		/*eta_index64=eta_index;
+		phi_index64=phi_index;
+		if (imap==2) eta_index64+=100;
+		if (imap==3) eta_index64+=200;
+		cout << identifier << " " << (eta_index64 << 16) + phi_index64 << endl;
+		
+		
+		
+		mcell2=geo->getDDE((eta_index64 << 16) + phi_index64);
+		cout << "Tile position for calogeometry using identifier: [x,y] = [" <<  mcell2->x() << "," << mcell2->y() << "]" << endl;*/
+	
+	
+	
+	}
+	
+ 
+}
+
+ 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapepara.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapepara.C
new file mode 100644
index 0000000000000000000000000000000000000000..0436281d9f8ac612402d3c7325860ba149b48a11
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapepara.C
@@ -0,0 +1,381 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**********************************************************************************
+* Generates TTree and shower shape distributions for input of the NN regression
+* Single particle Geant4 events used as the input of this macro.
+* To run:
+* > .x init_shapepara.C+(0/1) 0 for lxplus 1 for local
+* > .x run_shapepara.C("thin"/"bin"/"fit"/"plot")
+* <a.hasib@cern.ch>
+*********************************************************************************/
+#include "TChain.h"
+#include "TFile.h"
+#include "TTree.h"
+
+#include <iostream>
+#include <stdlib.h>
+
+
+using namespace std;
+
+void run_shapepara(int layer, int binpca);
+
+
+void run_shapepara(int layer, int binpca)
+{
+// * set the input parameters -----------------------------------------------------------------------------
+
+   string particle = "el_1mm"; // pion, el_1mm, el_opt, photon
+   float  energy   = 50;     // in GeV
+   float  etamin   = 0.20;
+   float  etamax   = 0.25;
+
+
+   int   calolayer   = layer;
+   int   PCAbin      = binpca;
+   int   nbinsR      = 20;
+   int   nbinsAlpha  = 8;
+   float mincalosize = -1000;     //whaaat are thooose?
+   float tolerance   = .00001;    // for empty bin check
+
+
+
+   // * regression parameters
+   int neurons = 12;
+
+
+   // * Create topDir and fileName strings
+
+   std::string topDir   = "../../run/output/shape_para/";
+   std::string fileName = particle + "_" + std::to_string(energy) + "GeV" + "_eta_" + std::to_string(etamin) + "_" + std::to_string(etamax) + "_layer" + std::to_string(calolayer) + "_PCAbin" + std::to_string(PCAbin);
+
+
+
+   // * Create output directory
+
+   system(("mkdir -p " + topDir + particle).c_str());
+
+   //----------------------------------------------------------------------------------------------------------------
+
+   // * set what you want to run
+   //
+
+
+   bool doThinning, doBinning, doRegression, doPlotting;
+
+   // if (action.compare("thin") == 0)
+   // {
+   //    doThinning   = true;
+   //    doBinning    = false;
+   //    doRegression = false;
+   //    doPlotting   = false;
+   // }
+   // else if (action.compare("bin") == 0)
+   // {
+   //    doThinning   = false;
+   //    doBinning    = true;
+   //    doRegression = false;
+   //    doPlotting   = false;
+   // }
+   // else if (action.compare("fit") == 0)
+   // {
+   //    doThinning   = false;
+   //    doBinning    = false;
+   //    doRegression = true;
+   //    doPlotting   = false;
+   // }
+   // else if (action.compare("plot") == 0)
+   // {
+   //    doThinning   = false;
+   //    doBinning    = false;
+   //    doRegression = false;
+   //    doPlotting   = true;
+   // }
+
+   doThinning   = true;
+   doBinning    = false;
+   doRegression = false;
+   doPlotting   = false;
+
+   // * Run ShowerShapeBinning...
+   if (doThinning)
+   {
+      // * configure particle type and input samples
+
+      cout << " ** configure particle type and input samples ...." << endl;
+
+      vector < string > input;      // vector of input samples.
+      vector < string > pca;        // vector of input pca files
+
+
+
+      if (particle == "pion")
+      {
+         // * input sample
+         input.push_back("/afs/cern.ch/work/a/ahasib/FastCaloSim/old/StandAlone/ISF_FastCaloSimParametrization_WorkingBranch/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+
+         // * PCA file
+         pca.push_back("/afs/cern.ch/user/a/ahasib/WorkDir/FastCaloSim/ISF_FastCaloSim/PCAs/pion/firstPCA.root");
+      }
+      else if (particle == "el_1mm")
+      {
+         // * input sample
+
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000001.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000002.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000003.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000004.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000005.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000006.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000007.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000008.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000009.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000010.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000011.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000012.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000013.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000014.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000015.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000016.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000017.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000018.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000019.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000020.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2865_r7736.w0_162706_matched_output.root/user.fladias.8834800._000021.matched_output.root");
+
+         // * PCA file
+
+         pca.push_back("/afs/cern.ch/user/a/ahasib/WorkDir/FastCaloSim/ISF_FastCaloSim/PCAs/electron/firstPCA_el_s2865.root");
+      }
+      else if (particle == "el_opt")
+      {
+         // * optimized merge samples
+
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000001.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000002.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000003.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000004.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000005.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000006.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000007.matched_output.root");
+         input.push_back("root://eosatlas//eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000008.matched_output.root");
+
+
+         // * PCA file
+
+         pca.push_back("/afs/cern.ch/user/a/ahasib/WorkDir/FastCaloSim/ISF_FastCaloSim/PCAs/electron/firstPCA_el_s2864.root");
+      }
+      else if (particle == "photon")
+      {
+         // * input sample
+         input.push_back("/afs/cern.ch/work/a/ahasib/FastCaloSim/old/StandAlone/ISF_FastCaloSimParametrization_WorkingBranch/photon/ISF_HitAnalysis_evgen_calo__22_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+
+         // * PCA file
+         pca.push_back("/afs/cern.ch/user/a/ahasib/WorkDir/FastCaloSim/ISF_FastCaloSim/PCAs/photon/firstPCA.root");
+      }
+      else
+      {
+         cout << "Error:: Particle type not configured! Exiting..." << endl;
+         exit(EXIT_FAILURE);
+      }
+
+
+      // * add the input files in TChain
+
+      TChain *mychain = new TChain("FCS_ParametrizationInput");
+
+      for (auto i : input)
+      {
+         mychain->Add(i.c_str());
+      }
+
+      cout << " * Prepare to run on: " << particle << " with entries = " << mychain->GetEntries() << endl;
+
+      TFile *PCAfile = TFile::Open((pca.at(0)).c_str());           //for the 1st pca file
+
+      if (!PCAfile)
+      {
+         cout << "Error:: Cannot locate the PCA file..." << endl;
+         exit(EXIT_FAILURE);
+      }
+
+      TTree *TPCA = (TTree *)PCAfile->Get("tree_1stPCA");
+
+      if (!TPCA)
+      {
+         cout << "Error:: Cannot locate the PCA TTree..." << endl;
+         exit(EXIT_FAILURE);
+      }
+
+      cout << " * Using PCA file = " << (pca.at(0)).c_str() << " with entries = " << TPCA->GetEntries() << endl;
+
+      // * Set the required parameter values
+
+      ShowerShapeThinning *shapeThin = new ShowerShapeThinning(mychain, TPCA);
+
+      shapeThin->set_calolayer(calolayer);
+      shapeThin->set_PCAbin(PCAbin);
+      shapeThin->set_nbinsR(nbinsR);
+      shapeThin->set_nbinsAlpha(nbinsAlpha);
+      shapeThin->set_mincalosize(mincalosize);
+      shapeThin->set_particle(particle);
+      shapeThin->set_energy(energy);
+      shapeThin->set_eta(etamin, etamax);
+      shapeThin->set_tolerance(tolerance);
+      shapeThin->set_topDir(topDir);
+      shapeThin->set_fileName(fileName);
+
+
+
+      // * file to save hits
+      // std::string fileallPCA = particle + "_" + std::to_string(energy) + "GeV" + "_eta_" + std::to_string(etamin) + "_" + std::to_string(etamax) + "_layer" + std::to_string(calolayer);
+
+      std::string HitsFile = topDir + particle + "/Hits_" + fileName + ".root";
+      shapeThin->set_hitsNtupleName(HitsFile);
+
+      std::string HitsAlphaDrFile = topDir + particle + "/HitsAlphaDr_" + fileName + ".root";
+
+
+      // * check to see it the hits ntuple exits
+      std::ifstream hitsfile(HitsFile);
+      std::ifstream hitsalphadrfile(HitsAlphaDrFile);
+
+      bool force = false;
+
+      if (!hitsfile or force)
+      {
+         cout << " * HitsNtuple doesn't exits. Creating from input samples...." << endl;
+         TFile *hitsFile = new TFile(HitsFile.c_str(), "recreate");
+
+         shapeThin->CreateHitsNtuple(hitsFile);
+      }
+      else if (hitsfile)
+      {
+         cout << " * HitsNtuple already exits!! Using it to CreateHitsAlphaDrNtuple()...." << endl;
+         shapeThin->CreateHitsAlphaDrNtuple(HitsFile);
+         //shapeThin->InvesitageShowerCenter(HitsFile);
+         // shapeThin->FindShowerCenter();
+         cout << " * Finished creating HitsAlphaDrNtuple..." << endl;
+      }
+      else
+      {
+         cout << " Choose a method to run ...." << endl;
+         exit(EXIT_FAILURE);
+      }
+   }
+   else if (doBinning)
+   {
+      std::string HitsAlphaDrFile = topDir + particle + "/HitsAlphaDr_" + fileName + ".root";
+      std::ifstream hitsalphadrfile(HitsAlphaDrFile);
+
+      if (!hitsalphadrfile)
+      {
+         cout << " HitsAlphaDr root file is missing ...." << endl;
+         exit(EXIT_FAILURE);
+      }
+
+      ShowerShapeBinning *shapeBin = new ShowerShapeBinning();
+
+      shapeBin->set_calolayer(calolayer);
+      shapeBin->set_PCAbin(PCAbin);
+      shapeBin->set_nbinsR(nbinsR);
+      shapeBin->set_nbinsAlpha(nbinsAlpha);
+      shapeBin->set_mincalosize(mincalosize);
+      shapeBin->set_particle(particle);
+      shapeBin->set_energy(energy);
+      shapeBin->set_eta(etamin, etamax);
+      shapeBin->set_tolerance(tolerance);
+      shapeBin->set_topDir(topDir);
+      shapeBin->set_fileName(fileName);
+
+
+      cout << " * HitsAlphaDrNtuple already exits!! Using it to RunBinning()..." << endl;
+      shapeBin->RunBinning();
+      cout << " * Creating TTree to be used as input of NN....." << endl;
+      shapeBin->CreateNNinput();
+      cout << " * NNinput file is saved in the directory = " << topDir.c_str() << endl;
+   }
+   else if (doRegression)
+   {
+      // * NN regression ....
+
+      cout << " * Running NN regression ..." << endl;
+
+      std::string NNinputName  = topDir + particle + "/NNinput_nbinsR" + std::to_string(nbinsR) + "_" + fileName + ".root";
+      std::string NNoutputName = topDir + particle + "/NNoutput_neurons" + std::to_string(neurons) + "_nbinsR" + std::to_string(nbinsR) + fileName + ".root";
+
+      ShowerShapeRegression *shapeRegression = new ShowerShapeRegression();
+
+      shapeRegression->set_calolayer(calolayer);
+      shapeRegression->set_PCAbin(PCAbin);
+      shapeRegression->set_nbinsR(nbinsR);
+      shapeRegression->set_particle(particle);
+      shapeRegression->set_energy(energy);
+      shapeRegression->set_eta(etamin, etamax);
+      shapeRegression->set_topDir(topDir);
+      shapeRegression->set_fileName(fileName);
+      shapeRegression->set_NNinputName(NNinputName);
+      shapeRegression->set_NNoutputName(NNoutputName);
+      shapeRegression->set_neurons(neurons);
+
+      std::vector < string > targetVarVec;
+
+      //targetVarVec.push_back("Hits");
+      //targetVarVec.push_back("Energy");
+      //targetVarVec.push_back("EnergyDensity");
+      //targetVarVec.push_back("LnEnergy");
+      targetVarVec.push_back("LnEnergyDensity");
+      shapeRegression->Run(targetVarVec);
+   }
+   else if (doPlotting)
+   {
+      // * plotting stuff...
+      cout << " * Running plotting macro ...." << endl;
+
+      // * create a plots directory
+
+      system(("mkdir -p " + topDir + particle + "/plots_nbinsR" + std::to_string(nbinsR) + "_neuron" + std::to_string(neurons) + "/").c_str());
+      std::string outputDirName = topDir + particle + "/plots_nbinsR" + std::to_string(nbinsR) + "_neuron" + std::to_string(neurons) + "/";
+      std::string NNinputName   = topDir + particle + "/NNinput_nbinsR" + std::to_string(nbinsR) + "_" + fileName + ".root";
+      std::string NNoutputName  = topDir + particle + "/NNoutput_neurons" + std::to_string(neurons) + "_nbinsR" + std::to_string(nbinsR) + fileName + ".root";
+
+
+
+      ShowerShapePlotting *shapePlot = new ShowerShapePlotting();
+
+      shapePlot->set_calolayer(calolayer);
+      shapePlot->set_PCAbin(PCAbin);
+      shapePlot->set_nbinsR(nbinsR);
+      shapePlot->set_particle(particle);
+      shapePlot->set_energy(energy);
+      shapePlot->set_eta(etamin, etamax);
+      shapePlot->set_topDir(topDir);
+      shapePlot->set_fileName(fileName);
+      shapePlot->set_outputDirName(outputDirName);
+      shapePlot->set_NNinputName(NNinputName);
+      shapePlot->set_NNoutputName(NNoutputName);
+      shapePlot->set_neurons(neurons);
+
+
+      // * plotting methods
+
+      std::vector < string > histVec;
+      histVec.push_back("hHits");
+      histVec.push_back("hEnergy");
+      histVec.push_back("hEnergyDensity");
+      histVec.push_back("hLnEnergy");
+      histVec.push_back("hLnEnergyDensity");
+
+      shapePlot->PlotEnergyDensityGradient();
+      shapePlot->PlotPolar(histVec, false);
+      shapePlot->CreateValidationPlot();
+      shapePlot->CreateHTML(histVec);
+   }
+   else
+   {
+      cout << " Choose .x run_shapepara.C(0) to run ShowerShapeBinning or .x run_shapepara(1) to run ShowerShapePlotting" << endl;
+      exit(EXIT_FAILURE);
+   }
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapeparaLocal.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapeparaLocal.C
new file mode 100644
index 0000000000000000000000000000000000000000..fc40ef06613612b691cbb5ca3b9fdafba3ebcbf5
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/run_shapeparaLocal.C
@@ -0,0 +1,267 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**********************************************************************************
+ * Generates TTree and shower shape distributions for input of the NN regression
+ * Single particle Geant4 events used as the input of this macro.
+ * To run:
+ * > .x init_shapepara.C+(1)
+ * > .x run_shapeparaLocal.C("thin"/"bin"/"fit"/"plot")
+ * <a.hasib@cern.ch>
+ *********************************************************************************/
+#include "TChain.h"
+#include "TFile.h"
+#include "TTree.h"
+
+#include <iostream>
+#include <stdlib.h>
+
+
+using namespace std;
+
+void run_shapeparaLocal(string action);
+
+
+void run_shapeparaLocal(string action)
+{
+   // * set the input parameters -----------------------------------------------------------------------------
+
+   string particle = "el_1mm"; // pion, el_1mm, el_opt, photon
+   float  energy   = 50;     // in GeV
+   float  etamin   = 0.20;
+   float  etamax   = 0.25;
+
+
+   int   calolayer   = 12;
+   int   PCAbin      = 5;
+   int   nbinsR      = 20;
+   int   nbinsAlpha  = 8;
+   float mincalosize = -1000;     //whaaat are thooose?
+   float tolerance   = .00000001; // for empty bin check
+
+
+
+   // * regression parameters
+   int neurons = 6;
+
+
+
+   // * Create topDir and fileName strings
+
+   std::string topDir   = "../../run/output/shape_para/";
+   std::string fileName = particle + "_" + std::to_string(energy) + "GeV" + "_eta_" + std::to_string(etamin) + "_" + std::to_string(etamax) + "_layer" + std::to_string(calolayer) + "_PCAbin" + std::to_string(PCAbin);
+
+
+
+   // * Create output directory
+
+   system(("mkdir -p " + topDir + particle).c_str());
+
+   //----------------------------------------------------------------------------------------------------------------
+
+   // * set what you want to run
+
+   bool doThinning, doStudy, doBinning, doRegression, doPlotting;
+
+   if (action.compare("thin") == 0)
+   {
+      doThinning   = true;
+      doStudy      = false;
+      doBinning    = false;
+      doRegression = false;
+      doPlotting   = false;
+   }
+   else if (action.compare("study") == 0)
+   {
+      doThinning   = false;
+      doStudy      = true;
+      doBinning    = false;
+      doRegression = false;
+      doPlotting   = false;
+   }
+   else if (action.compare("bin") == 0)
+   {
+      doThinning   = false;
+      doStudy      = false;
+      doBinning    = true;
+      doRegression = false;
+      doPlotting   = false;
+   }
+   else if (action.compare("fit") == 0)
+   {
+      doThinning   = false;
+      doStudy      = false;
+      doBinning    = false;
+      doRegression = true;
+      doPlotting   = false;
+   }
+   else if (action.compare("plot") == 0)
+   {
+      doThinning   = false;
+      doStudy      = false;
+      doBinning    = false;
+      doRegression = false;
+      doPlotting   = true;
+   }
+
+
+
+   // * Run ShowerShapeBinning...
+   if (doThinning)
+   {
+      // * configure particle type and input samples
+
+      cout << " Running on local machine. Cannot run ShowerShapeThinning  ...." << endl;
+      exit(EXIT_FAILURE);
+   }
+   else if (doStudy)
+   {
+      // std::string fileallPCA = particle + "_" + std::to_string(energy) + "GeV" + "_eta_" + std::to_string(etamin) + "_" + std::to_string(etamax) + "_layer" + std::to_string(calolayer);
+
+      std::string HitsFile = topDir + particle + "/Hits_" + fileName + ".root";
+
+      ShowerShapeStudy *shapeStudy = new ShowerShapeStudy();
+
+      shapeStudy->set_calolayer(calolayer);
+      shapeStudy->set_PCAbin(PCAbin);
+      shapeStudy->set_nbinsR(nbinsR);
+      shapeStudy->set_nbinsAlpha(nbinsAlpha);
+      shapeStudy->set_mincalosize(mincalosize);
+      shapeStudy->set_particle(particle);
+      shapeStudy->set_energy(energy);
+      shapeStudy->set_eta(etamin, etamax);
+      shapeStudy->set_tolerance(tolerance);
+      shapeStudy->set_topDir(topDir);
+      shapeStudy->set_fileName(fileName);
+      shapeStudy->set_hitsNtupleName(HitsFile);
+
+      shapeStudy->InvesitageShowerCenter(HitsFile);
+      //shapeStudy->EachParticleShower();
+   }
+   else if (doBinning)
+   {
+      std::string HitsAlphaDrFile = topDir + particle + "/HitsAlphaDr_" + fileName + ".root";
+      std::ifstream hitsalphadrfile(HitsAlphaDrFile);
+
+      // std::string fileallPCA = particle + "_" + std::to_string(energy) + "GeV" + "_eta_" + std::to_string(etamin) + "_" + std::to_string(etamax) + "_layer" + std::to_string(calolayer);
+      std::string HitsFile = topDir + particle + "/Hits_" + fileName + ".root";
+
+
+      ShowerShapeBinning *shapeBin = new ShowerShapeBinning();
+
+      shapeBin->set_calolayer(calolayer);
+      shapeBin->set_PCAbin(PCAbin);
+      shapeBin->set_nbinsR(nbinsR);
+      shapeBin->set_nbinsAlpha(nbinsAlpha);
+      shapeBin->set_mincalosize(mincalosize);
+      shapeBin->set_particle(particle);
+      shapeBin->set_energy(energy);
+      shapeBin->set_eta(etamin, etamax);
+      shapeBin->set_tolerance(tolerance);
+      shapeBin->set_topDir(topDir);
+      shapeBin->set_fileName(fileName);
+
+      if (!hitsalphadrfile)
+      {
+         cout << " HitsAlphaDr root file is missing ....Creating..." << endl;
+         shapeBin->CreateHitsAlphaDrNtuple(HitsFile);
+         cout << " Created HitsAlphaDrNtuple at " << HitsAlphaDrFile << endl;
+      }
+      else
+      {
+         cout << " * HitsAlphaDrNtuple already exits!! Using it to RunBinning()..." << endl;
+         shapeBin->RunBinning();
+         cout << " * Creating TTree to be used as input of NN....." << endl;
+         shapeBin->CreateNNinput();
+         cout << " * NNinput file is saved in the directory = " << topDir.c_str() << endl;
+      }
+   }
+   else if (doRegression)
+   {
+      // * NN regression ....
+
+      cout << " * Running NN regression ..." << endl;
+
+      std::string NNinputName  = topDir + particle + "/NNinput_"/*nbinsR" + std::to_string(nbinsR) + "_"*/ + fileName + ".root";
+      std::string NNoutputName = topDir + particle + "/NNoutput_neurons" + std::to_string(neurons) + "_nbinsR" + std::to_string(nbinsR) + fileName + ".root";
+
+      ShowerShapeRegression *shapeRegression = new ShowerShapeRegression();
+
+      shapeRegression->set_calolayer(calolayer);
+      shapeRegression->set_PCAbin(PCAbin);
+      shapeRegression->set_nbinsR(nbinsR);
+      shapeRegression->set_particle(particle);
+      shapeRegression->set_energy(energy);
+      shapeRegression->set_eta(etamin, etamax);
+      shapeRegression->set_topDir(topDir);
+      shapeRegression->set_fileName(fileName);
+      shapeRegression->set_NNinputName(NNinputName);
+      shapeRegression->set_NNoutputName(NNoutputName);
+      shapeRegression->set_neurons(neurons);
+
+      std::vector < string > targetVarVec;
+
+      //targetVarVec.push_back("Hits");
+      // targetVarVec.push_back("Energy");
+      //targetVarVec.push_back("EnergyDensity");
+      //targetVarVec.push_back("LnEnergy");
+      //targetVarVec.push_back("LnEnergyDensity");
+      targetVarVec.push_back("EnergyNorm");
+      shapeRegression->Run(targetVarVec);
+   }
+   else if (doPlotting)
+   {
+      // * plotting stuff...
+      cout << " * Running plotting macro ...." << endl;
+
+      // * create a plots directory
+      system(("mkdir -p " + topDir + particle + "/plots"/*_nbinsR" + std::to_string(nbinsR)*/ + "_layer" + std::to_string(calolayer) + "_pca" + std::to_string(PCAbin) + "/").c_str());
+
+
+      system(("mkdir -p " + topDir + particle + "/plot_books/").c_str());
+
+      std::string outputDirName = topDir + particle + "/plots"/*_nbinsR" + std::to_string(nbinsR)*/ + "_layer" + std::to_string(calolayer) + "_pca" + std::to_string(PCAbin) + "/";
+
+      std::string NNinputName  = topDir + particle + "/NNinput_"/*nbinsR" + std::to_string(nbinsR) + "_"*/ + fileName + ".root";
+      std::string NNoutputName = topDir + particle + "/NNoutput_neurons" + std::to_string(neurons) + "_nbinsR" + std::to_string(nbinsR) + fileName + ".root";
+
+
+      ShowerShapePlotting *shapePlot = new ShowerShapePlotting();
+
+      shapePlot->set_calolayer(calolayer);
+      shapePlot->set_PCAbin(PCAbin);
+      shapePlot->set_nbinsR(nbinsR);
+      shapePlot->set_particle(particle);
+      shapePlot->set_energy(energy);
+      shapePlot->set_eta(etamin, etamax);
+      shapePlot->set_topDir(topDir);
+      shapePlot->set_fileName(fileName);
+      shapePlot->set_outputDirName(outputDirName);
+      shapePlot->set_NNinputName(NNinputName);
+      shapePlot->set_NNoutputName(NNoutputName);
+      shapePlot->set_neurons(neurons);
+
+
+      // * plotting methods
+
+      std::vector < string > histVec;
+      //histVec.push_back("hHits");
+      // histVec.push_back("hEnergy");
+      histVec.push_back("hEnergyDensity");
+      //histVec.push_back("hLnEnergy");
+      //histVec.push_back("hLnEnergyDensity");
+      // histVec.push_back("hEnergyNorm");
+
+      shapePlot->PlotEnergyDensityGradient();
+      shapePlot->PlotPolar(histVec, false);
+      shapePlot->CreateValidationPlot();
+      // shapePlot->CreateHTML(histVec);
+      shapePlot->CreatePlotBook(histVec);
+   }
+   else
+   {
+      cout << " Choose .x run_shapepara.C(0) to run ShowerShapeBinning or .x run_shapepara(1) to run ShowerShapePlotting" << endl;
+      exit(EXIT_FAILURE);
+   }
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root6.sh b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root6.sh
new file mode 100644
index 0000000000000000000000000000000000000000..227c5d5c0077b7c85c90c2d8c58b3e49cf3ce8a2
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root6.sh
@@ -0,0 +1,3 @@
+source /afs/cern.ch/sw/lcg/app/releases/ROOT/6.06.06/x86_64-slc6-gcc49-opt/root/bin/thisroot.sh
+source /afs/cern.ch/sw/lcg/contrib/gcc/4.9/x86_64-slc6/setup.sh
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root608.sh b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root608.sh
new file mode 100644
index 0000000000000000000000000000000000000000..91851508673911ec1bac4ebdfb085886d0b46ef5
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_root608.sh
@@ -0,0 +1,2 @@
+source /cvmfs/sft.cern.ch/lcg/app/releases/ROOT/6.08.00/x86_64-centos7-gcc48-opt/root/bin/thisroot.sh
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/setup.sh b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_shape.sh
similarity index 100%
rename from Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/setup.sh
rename to Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/setup_shape.sh
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx
index afa63f02a02bd8d4a3cc9087a32f550a5be73a58..0ff5d455140460ca312ca9a76e2fa266a9e29f1b 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx
@@ -40,9 +40,11 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
   
   //load geometry finder
   CaloGeometryFromFile* geo=new CaloGeometryFromFile();
-  geo->LoadGeometryFromFile("ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
+  geo->LoadGeometryFromFile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSim/ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
+  geo->LoadFCalGeometryFromFiles("FCal1-electrodes.sorted.HV.09Nov2007.dat","FCal2-electrodes.sorted.HV.April2011.dat","FCal3-electrodes.sorted.HV.09Nov2007.dat");
   
-  TFile *originalFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/LArShift020715/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+  //TFile *originalFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/LArShift020715/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+  TFile *originalFile = TFile::Open("/eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000001.matched_output.root");
   
   TFile *PCAfile = TFile::Open("firstPCA_pions_flavia.root");
   
@@ -233,7 +235,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
       
       Long64_t myID = it->first;
 
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(myID);
       cell=geo->getDDE(cellid);
       
@@ -251,7 +253,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
       
       Long64_t myID = it->first;
 
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(myID);
       cell=geo->getDDE(cellid);
       
@@ -267,7 +269,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
       
       Long64_t myID = it->first;
 
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(myID);
       cell=geo->getDDE(cellid);
       
@@ -322,9 +324,11 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
 	float z = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
 	float t = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_time;	
 	TLorentzVector *hitVec = new TLorentzVector(x, y, z, t);
-	const CaloDetDescrElement* someCell;
-	someCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
-
+	int hitSampling=((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling;
+	const CaloGeoDetDescrElement* someCell;
+	if(hitSampling<21)someCell=geo->getDDE(hitSampling,hitVec->Eta(),hitVec->Phi());
+	else if (hitSampling<24)someCell=geo->getFCalDDE(hitSampling,x,y,z);
+	else someCell=0;
 	Long64_t someCellID = someCell->identify();
 	
 	if (Eoriginal.find(someCellID) != Eoriginal.end()){
@@ -359,7 +363,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
       random1->SetSeed(0);
       
       //now I use the geomery lookup tool to get the cell eta/phi
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(cell_ID);
       cell=geo->getDDE(cellid); //This is working also for the FCal
       
@@ -372,8 +376,11 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
 	float z = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
 	float t = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_time;	
 	TLorentzVector *hitVec = new TLorentzVector(x, y, z, t);
-	const CaloDetDescrElement* initCell;
-	initCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
+	int hitSampling=((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling;
+	const CaloGeoDetDescrElement* initCell;
+	if(hitSampling<21)initCell=geo->getDDE(hitSampling,hitVec->Eta(),hitVec->Phi());
+	else if (hitSampling<24)initCell=geo->getFCalDDE(hitSampling,x,y,z);
+	else initCell=0;
 	
 	if (initCell && cell){	  
 	  float efficiencyEta = ( (2.0*(hitVec->Eta()-initCell->eta()))/initCell->deta());
@@ -405,8 +412,10 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
 	  else
 	    wigglePhi = (eff_phi->GetBinCenter(chosenBin+2))/2; 
 	  
-	  const CaloDetDescrElement* foundCell;
-	  foundCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),(hitVec->Phi())-(wigglePhi*initCell->dphi()));
+	  const CaloGeoDetDescrElement* foundCell;
+	  if(hitSampling<21)foundCell=geo->getDDE(hitSampling,hitVec->Eta(),(hitVec->Phi())-(wigglePhi*initCell->dphi()));
+	  else if (hitSampling<24)foundCell=geo->getFCalDDE(hitSampling,x,y,z);
+		else foundCell=0;
 
 	  //deposit energy in specific cell
 	  Long64_t foundCellID = foundCell->identify();
@@ -433,7 +442,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
     for ( std::map<Long64_t, double>::iterator it2 = Eclosure.begin(); it2!=Eclosure.end(); it2++) {
       
       Long64_t myID = it2->first;
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(myID);
       cell=geo->getDDE(cellid);
       
@@ -464,7 +473,7 @@ void wiggleClosureAndComparison(TString sampling="Sampling_0"){
 
       Long64_t myID = it->first;
       
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(myID);
       cell=geo->getDDE(cellid);
       
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggle_closure_inputs.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggle_closure_inputs.cxx
index e9f26fddaa2d7b32b969393a1f103c8c99536e5b..64491914f1b23435f0035748e3e7c8bdcb2eeb12 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggle_closure_inputs.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggle_closure_inputs.cxx
@@ -32,10 +32,12 @@ using namespace std;
 void wiggle_closure_inputs(TString sampling="Sampling_0"){
 
   CaloGeometryFromFile* geo=new CaloGeometryFromFile();
-  geo->LoadGeometryFromFile("ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
-  
-  TFile *inputFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/LArShift020715/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
+  geo->LoadGeometryFromFile("/afs/cern.ch/atlas/groups/Simulation/FastCaloSim/ATLAS-GEO-20-00-01.root","ATLAS-GEO-20-00-01");
+  geo->LoadFCalGeometryFromFiles("FCal1-electrodes.sorted.HV.09Nov2007.dat","FCal2-electrodes.sorted.HV.April2011.dat","FCal3-electrodes.sorted.HV.09Nov2007.dat");
   
+  TFile *inputFile = TFile::Open("/eos/atlas/user/s/schaarsc/FCS/user.fladias.428137.FastCalo_pid11_E65536_etam35_35_zv_m100.e4001_s2864_r7736.w0_162706_matched_output.root/user.fladias.8834798._000001.matched_output.root");
+ 
+	// TFile *inputFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/LArShift020715/ISF_HitAnalysis6_evgen_calo__211_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.merged.pool.root");
   //  TFile *inputFile = TFile::Open("root://eosatlas//eos/atlas/user/z/zhubacek/FastCaloSim/NTUP_110216/ISF_HitAnalysis_Zach1_merged.root");
 
   TTree *inputTree = ( TTree* ) inputFile->Get( "FCS_ParametrizationInput" );
@@ -76,32 +78,50 @@ void wiggle_closure_inputs(TString sampling="Sampling_0"){
       cell_ID = ((FCS_matchedcell)(*vec)[j]).cell.cell_identifier;
 
       //now I use the geomery lookup tool to get the cell eta/phi
-      const CaloDetDescrElement* cell;
+      const CaloGeoDetDescrElement* cell;
       Identifier cellid(cell_ID);
       cell=geo->getDDE(cellid); //This is working also for the FCal
       
       //loop over hits in the cell
-      for (int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
+      for (unsigned int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
 	
 	//now I check what is the hit position
 	float x = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_x;
 	float y = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_y;
 	float z = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
-	float t = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_time;	
+	float t = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_time;
+	int hitSampling =((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling;
+	
 	TLorentzVector *hitVec = new TLorentzVector(x, y, z, t);
-	const CaloDetDescrElement* foundCell;
-	foundCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
+	const CaloGeoDetDescrElement* foundCell;
+	if(hitSampling<21)foundCell=geo->getDDE(hitSampling,hitVec->Eta(),hitVec->Phi());
+	else if(hitSampling<24)foundCell=geo->getFCalDDE(hitSampling,x,y,z);
+	else {
+		cout << endl << "Warning: Found hit with sampling > 23 !!!!!!!!!!!!!!" << endl << endl;
+		foundCell =0;
+	}
 	
 	if (foundCell){// && cell){
-	  
-	  eff_tot_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()),weight);	  
-	  eff_tot_count_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()));
-	  
-	  if (foundCell->identify() == cell->identify()){
-	    
-	    eff_corr_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()),weight);
-	    eff_corr_count_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()));
-	  }
+	  if(hitSampling<21){
+		  eff_tot_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()),weight);	  
+		  eff_tot_count_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()));
+		  
+		  if (foundCell->identify() == cell->identify()){
+		    
+		    eff_corr_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()),weight);
+		    eff_corr_count_phi->Fill(((2*(hitVec->Phi()-foundCell->phi()))/foundCell->dphi()));
+		  }
+		}
+		else if(hitSampling<24){
+		  eff_tot_phi->Fill(((2*(x-foundCell->x()))/foundCell->dx()),weight);	  
+		  eff_tot_count_phi->Fill(((2*(x-foundCell->x()))/foundCell->dx()));
+		  
+		  if (foundCell->identify() == cell->identify()){
+		    
+		    eff_corr_phi->Fill(((2*(x-foundCell->x()))/foundCell->dx()),weight);
+		    eff_corr_count_phi->Fill(((2*(x-foundCell->x()))/foundCell->dx()));
+		  }
+		}
 	  
 	} //end if cell ok
       } //end loop over hits