diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
index 21b613fd50f2bdda32f565a2ba3591605ff65d13..b0472bf527872a3bbf471d307c4a20572c71a098 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt
@@ -18,6 +18,7 @@ atlas_depends_on_subdirs( PUBLIC
                           LArCalorimeter/LArElecCalib
                           Simulation/Barcode/BarcodeInterfaces
                           Simulation/ISF/ISF_Core/ISF_Interfaces
+                          Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent
                           Tracking/TrkEvent/TrkEventPrimitives
                           Tracking/TrkEvent/TrkParameters
                           Tracking/TrkExtrapolation/TrkExInterfaces
@@ -33,7 +34,6 @@ atlas_depends_on_subdirs( PUBLIC
                           Generators/GeneratorObjects
                           LArCalorimeter/LArSimEvent
                           Simulation/ISF/ISF_Core/ISF_Event
-                          Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent
                           Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimInterfaces
                           TileCalorimeter/TileConditions
                           TileCalorimeter/TileDetDescr
@@ -55,7 +55,7 @@ find_package( XercesC )
 # Component(s) in the package:
 atlas_add_root_dictionary( ISF_FastCaloSimParametrizationLib
                            ISF_FastCaloSimParametrizationLibDictSource
-                           ROOT_HEADERS ISF_FastCaloSimParametrization/MeanAndRMS.h ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h ISF_FastCaloSimParametrization/TFCSParametrizationBase.h ISF_FastCaloSimParametrization/TFCSParametrization.h ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h ISF_FastCaloSimParametrization/TFCSPCAEnergyParametrization.h ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSExtrapolationState.h ISF_FastCaloSimParametrization/TFCSTruthState.h ISF_FastCaloSimParametrization/TFCSSimulationState.h ISF_FastCaloSimParametrization/TFCS1DFunction.h ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h ISF_FastCaloSimParametrization/TFCSFunction.h ISF_FastCaloSimParametrization/TreeReader.h ISF_FastCaloSimParametrization/firstPCA.h ISF_FastCaloSimParametrization/secondPCA.h Root/LinkDef.h
+                           ROOT_HEADERS ISF_FastCaloSimParametrization/MeanAndRMS.h ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.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
                            EXTERNAL_PACKAGES  ROOT HepPDT XercesC CLHEP HepMC Geant4 )
 
 atlas_add_library( ISF_FastCaloSimParametrizationLib
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 594d01b729bdd3c1112e58ac42af886a93c64b72..e60dfa2bc6f07fe440ee777cdab8c6ae469b3a10 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/CaloGeometry.h
@@ -21,183 +21,174 @@ class TGraphErrors;
 
 typedef std::map< Identifier , const CaloDetDescrElement* > t_cellmap;
 typedef std::map< double , const CaloDetDescrElement* > t_eta_cellmap;
-   
+
 class CaloGeometryLookup {
-public:
-   CaloGeometryLookup(int ind=0);
-   virtual ~CaloGeometryLookup();
-   
-   bool IsCompatible(const CaloDetDescrElement* cell);
-   void add(const CaloDetDescrElement* 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;};
-   void post_process();
-   bool has_overlap(CaloGeometryLookup* ref);
-   void merge_into_ref(CaloGeometryLookup* ref);
-   //void CalculateTransformation();
-   
-   float mineta() const {return m_mineta;};
-   float maxeta() const {return m_maxeta;};
-   float minphi() const {return m_minphi;};
-   float maxphi() const {return m_maxphi;};
-   
-   float mineta_raw() const {return m_mineta_raw;};
-   float maxeta_raw() const {return m_maxeta_raw;};
-   float minphi_raw() const {return m_minphi_raw;};
-   float maxphi_raw() const {return m_maxphi_raw;};
-   
-   float minx() const {return m_mineta;};
-   float maxx() const {return m_maxeta;};
-   float miny() const {return m_minphi;};
-   float maxy() const {return m_maxphi;};
-   
-   float minx_raw() const {return m_mineta_raw;};
-   float maxx_raw() const {return m_maxeta_raw;};
-   float miny_raw() const {return m_minphi_raw;};
-   float maxy_raw() const {return m_maxphi_raw;};
-   
-   const MeanAndRMS& deta() {return m_deta;};
-   const MeanAndRMS& dphi() {return m_dphi;};
-   float mindeta() {return m_mindeta;};
-   float mindphi() {return m_mindphi;};
-   const MeanAndRMS& dx() {return m_deta;};
-   const MeanAndRMS& dy() {return m_dphi;};
-   float mindx() {return m_mindeta;};
-   float mindy() {return m_mindphi;};
-
-   const MeanAndRMS& eta_correction() {return m_eta_correction;};
-   const MeanAndRMS& phi_correction() {return m_phi_correction;};
-   const MeanAndRMS& x_correction() {return m_eta_correction;};
-   const MeanAndRMS& y_correction() {return m_phi_correction;};
-   
-   int cell_grid_eta() const {return m_cell_grid_eta;};
-   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);
-
-protected:
-   float neta_double() {return (maxeta_raw()-mineta_raw())/deta().mean();};
-   float nphi_double() {return (maxphi_raw()-minphi_raw())/dphi().mean();};
-   Int_t neta() {return TMath::Nint( neta_double() );};
-   Int_t nphi() {return TMath::Nint( nphi_double() );};
-
-   //FCal is not sufficiently regular to use submaps with regular mapping
-   float nx_double() {return (maxx_raw()-minx_raw())/mindx();};
-   float ny_double() {return (maxy_raw()-miny_raw())/mindy();};
-   Int_t nx() {return TMath::Nint(TMath::Ceil( nx_double() ));};
-   Int_t ny() {return TMath::Nint(TMath::Ceil( ny_double() ));};
-   
-   float m_xy_grid_adjustment_factor;
-
-   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);
-
-   int m_index;
-   t_cellmap m_cells;
-   std::vector< std::vector< const CaloDetDescrElement* > > 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;
-   float m_mineta_correction,m_maxeta_correction,m_minphi_correction,m_maxphi_correction;
-   
-   MeanAndRMS m_deta,m_dphi,m_eta_correction,m_phi_correction;
-   float m_mindeta,m_mindphi;
-   float m_deta_double,m_dphi_double;
+  public:
+    CaloGeometryLookup(int ind=0);
+    virtual ~CaloGeometryLookup();
+
+    bool IsCompatible(const CaloDetDescrElement* cell);
+    void add(const CaloDetDescrElement* 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;};
+    void post_process();
+    bool has_overlap(CaloGeometryLookup* ref);
+    void merge_into_ref(CaloGeometryLookup* ref);
+    //void CalculateTransformation();
+
+    float mineta() const {return m_mineta;};
+    float maxeta() const {return m_maxeta;};
+    float minphi() const {return m_minphi;};
+    float maxphi() const {return m_maxphi;};
+
+    float mineta_raw() const {return m_mineta_raw;};
+    float maxeta_raw() const {return m_maxeta_raw;};
+    float minphi_raw() const {return m_minphi_raw;};
+    float maxphi_raw() const {return m_maxphi_raw;};
+
+    float minx() const {return m_mineta;};
+    float maxx() const {return m_maxeta;};
+    float miny() const {return m_minphi;};
+    float maxy() const {return m_maxphi;};
+
+    float minx_raw() const {return m_mineta_raw;};
+    float maxx_raw() const {return m_maxeta_raw;};
+    float miny_raw() const {return m_minphi_raw;};
+    float maxy_raw() const {return m_maxphi_raw;};
+
+    const MeanAndRMS& deta() {return m_deta;};
+    const MeanAndRMS& dphi() {return m_dphi;};
+    float mindeta() {return m_mindeta;};
+    float mindphi() {return m_mindphi;};
+    const MeanAndRMS& dx() {return m_deta;};
+    const MeanAndRMS& dy() {return m_dphi;};
+    float mindx() {return m_mindeta;};
+    float mindy() {return m_mindphi;};
+
+    const MeanAndRMS& eta_correction() {return m_eta_correction;};
+    const MeanAndRMS& phi_correction() {return m_phi_correction;};
+    const MeanAndRMS& x_correction() {return m_eta_correction;};
+    const MeanAndRMS& y_correction() {return m_phi_correction;};
+
+    int cell_grid_eta() const {return m_cell_grid_eta;};
+    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);
+
+  protected:
+    float neta_double() {return (maxeta_raw()-mineta_raw())/deta().mean();};
+    float nphi_double() {return (maxphi_raw()-minphi_raw())/dphi().mean();};
+    Int_t neta() {return TMath::Nint( neta_double() );};
+    Int_t nphi() {return TMath::Nint( nphi_double() );};
+
+    //FCal is not sufficiently regular to use submaps with regular mapping
+    float nx_double() {return (maxx_raw()-minx_raw())/mindx();};
+    float ny_double() {return (maxy_raw()-miny_raw())/mindy();};
+    Int_t nx() {return TMath::Nint(TMath::Ceil( nx_double() ));};
+    Int_t ny() {return TMath::Nint(TMath::Ceil( ny_double() ));};
+
+    float m_xy_grid_adjustment_factor;
+
+    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);
+
+    int m_index;
+    t_cellmap m_cells;
+    std::vector< std::vector< const CaloDetDescrElement* > > 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;
+    float m_mineta_correction,m_maxeta_correction,m_minphi_correction,m_maxphi_correction;
+
+    MeanAndRMS m_deta,m_dphi,m_eta_correction,m_phi_correction;
+    float m_mindeta,m_mindphi;
+    float m_deta_double,m_dphi_double;
 };
 
 class CaloGeometry : virtual public ICaloGeometry {
-public :
-   static const int MAX_SAMPLING;
-   
-   static Identifier m_debug_identify;
-   static bool m_debug;
-   
-   CaloGeometry();
-   virtual ~CaloGeometry();
-   
-   virtual bool PostProcessGeometry();
-
-   virtual void Validate();
-
-   virtual const CaloDetDescrElement* getDDE(Identifier identify);
-   
-   virtual const CaloDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0);
-   
-   double deta(int sample,double eta) const;
-   void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const;
-   double rzmid(int sample,double eta) const;
-   double rzent(int sample,double eta) const;
-   double rzext(int sample,double eta) const;
-   double rmid(int sample,double eta) const;
-   double rent(int sample,double eta) const;
-   double rext(int sample,double eta) const;
-   double zmid(int sample,double eta) const;
-   double zent(int sample,double eta) const;
-   double zext(int sample,double eta) const;
-   //enum SUBPOS { SUBPOS_MID = 0, SUBPOS_ENT = 1, SUBPOS_EXT = 2}; //MID=middle, ENT=entrance, EXT=exit of cal layer
-   double rpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double zpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double rzpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   bool   isCaloBarrel(int sample) const {return m_isCaloBarrel[sample];};
-   static std::string SamplingName(int sample);
-   
-   TGraphErrors* GetGraph(unsigned int sample) const {return m_graph_layers[sample];};
-   void SetDoGraphs(bool dographs=true) {m_dographs=dographs;};
-   bool DoGraphs() const {return m_dographs;};
-
-   TCanvas* DrawGeoForPhi0();
-   
-protected:
-   virtual void addcell(const CaloDetDescrElement* cell);
-   
-   virtual void post_process(int layer);
-
-   virtual void PrintMapInfo(int i, int j);
-   
-   virtual void InitRZmaps();
-   
-   t_cellmap m_cells;
-   std::vector< t_cellmap > m_cells_in_sampling;
-   std::vector< t_eta_cellmap > m_cells_in_sampling_for_phi0;
-   std::vector< std::vector< CaloGeometryLookup* > > m_cells_in_regions;
-
-   std::vector< bool > m_isCaloBarrel;
-   std::vector< double > m_min_eta_sample[2]; //[side][calosample]
-   std::vector< double > m_max_eta_sample[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_rmid_map[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_zmid_map[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_rent_map[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_zent_map[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_rext_map[2]; //[side][calosample]
-   std::vector< FSmap< double , double > > m_zext_map[2]; //[side][calosample]
-   
-   bool m_dographs;
-   std::vector< TGraphErrors* > m_graph_layers;
-   
-/*
-   double  m_min_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
-   double  m_max_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_rmid_map[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_zmid_map[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_rent_map[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_zent_map[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_rext_map[2][MAX_SAMPLING]; //[side][calosample]
-   FSmap< double , double > m_zext_map[2][MAX_SAMPLING]; //[side][calosample]
-*/
+  public :
+    static const int MAX_SAMPLING;
+
+    static Identifier m_debug_identify;
+    static bool m_debug;
+
+    CaloGeometry();
+    virtual ~CaloGeometry();
+
+    virtual bool PostProcessGeometry();
+
+    virtual void Validate();
+
+    virtual const CaloDetDescrElement* getDDE(Identifier identify);
+
+    virtual const CaloDetDescrElement* getDDE(int sampling,float eta,float phi,float* distance=0,int* steps=0);
+
+    double deta(int sample,double eta) const;
+    void   minmaxeta(int sample,double eta,double& mineta,double& maxeta) const;
+    double rzmid(int sample,double eta) const;
+    double rzent(int sample,double eta) const;
+    double rzext(int sample,double eta) const;
+    double rmid(int sample,double eta) const;
+    double rent(int sample,double eta) const;
+    double rext(int sample,double eta) const;
+    double zmid(int sample,double eta) const;
+    double zent(int sample,double eta) const;
+    double zext(int sample,double eta) const;
+    double rpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+    double zpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+    double rzpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+    bool   isCaloBarrel(int sample) const {return m_isCaloBarrel[sample];};
+    static std::string SamplingName(int sample);
+
+    TGraphErrors* GetGraph(unsigned int sample) const {return m_graph_layers[sample];};
+    void SetDoGraphs(bool dographs=true) {m_dographs=dographs;};
+    bool DoGraphs() const {return m_dographs;};
+
+    TCanvas* DrawGeoForPhi0();
+
+  protected:
+    virtual void addcell(const CaloDetDescrElement* cell);
+
+    virtual void post_process(int layer);
+
+    virtual void PrintMapInfo(int i, int j);
+
+    virtual void InitRZmaps();
+
+    t_cellmap m_cells;
+    std::vector< t_cellmap > m_cells_in_sampling;
+    std::vector< t_eta_cellmap > m_cells_in_sampling_for_phi0;
+    std::vector< std::vector< CaloGeometryLookup* > > m_cells_in_regions;
+
+    std::vector< bool > m_isCaloBarrel;
+    std::vector< double > m_min_eta_sample[2]; //[side][calosample]
+    std::vector< double > m_max_eta_sample[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_rmid_map[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_zmid_map[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_rent_map[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_zent_map[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_rext_map[2]; //[side][calosample]
+    std::vector< FSmap< double , double > > m_zext_map[2]; //[side][calosample]
+
+    bool m_dographs;
+    std::vector< TGraphErrors* > m_graph_layers;
+
+    /*
+       double  m_min_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
+       double  m_max_eta_sample[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_rmid_map[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_zmid_map[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_rent_map[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_zent_map[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_rext_map[2][MAX_SAMPLING]; //[side][calosample]
+       FSmap< double , double > m_zext_map[2][MAX_SAMPLING]; //[side][calosample]
+       */
 };
 
-#if defined(__MAKECINT__)
-#ifndef CaloGeometryFromFile_h
-#pragma link C++ class CaloGeometryLookup;
-#pragma link C++ class CaloGeometry;
-#pragma link C++ class ICaloGeometry;
-#endif
-#endif
-
 #endif
 
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/DetailedShapeBinning.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/DetailedShapeBinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..981ccbd3d0b29c4ffa32a04449ac4c76d510e724
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/DetailedShapeBinning.h
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef DetailedShapeBinning_h
+#define DetailedShapeBinning_h
+
+class DetailedShapeBinning
+{
+  public:
+  	
+    DetailedShapeBinning();
+    virtual ~DetailedShapeBinning() {}
+
+    bool run(bool,bool,TChain*, int, float, std::string, int, std::string, std::string, float&,float&, float&, float&, float&, float&, vector<float>);
+    
+    bool fill(bool,TTree*, int, Float_t*, int, Float_t*, float, std::string, float,TH1F&,TH1F&,float,bool,std::string,float&,float&,float&,float&,float&,vector<int>,bool,std::string,vector<float>);
+    void unitsmm(float, float&, float&, float, float);
+    void getcellgeom(float, float, float, float&,float&, float&, float&, float&);
+    std::vector<float> fVecBin(TH1F*, int, bool);
+    bool checkgradient(std::string,TH1F&, std::string, std::string,bool);
+    bool checkgranularity(float, float, float, float, float, float, Float_t*, int, float&);
+    void fillValidationPlot(float, float, bool, bool, std::string, std::string);
+
+
+  private:
+
+  ClassDef(DetailedShapeBinning,1);
+  
+};
+#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
new file mode 100644
index 0000000000000000000000000000000000000000..b7c5aa2ac9d0556410f9ef4ce2f561f08e04ce96
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TFCSSimulationState_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);
+    static TH1D* refill(TH1D* h_in,double min, double max, double rmin, double rmax);
+
+  private:
+  ClassDef(EnergyParametrizationValidation,1)
+};
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h
index 1e13b81b58be9425e76bd943e709721f9df5231b..d63263385aaa01e37271b9bb58646c4452efa239 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h
@@ -22,9 +22,9 @@ namespace HepPDT {
   class ParticleDataTable;
 }  
 
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
 #include "ISF_FastCaloSimParametrization/IFastCaloSimCaloExtrapolation.h"
-#include "ISF_FastCaloSimParametrization/TFCSExtrapolationState.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
 
 class IFastCaloSimGeometryHelper;
 
@@ -39,8 +39,6 @@ class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExt
 
    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
-
  protected:
    bool   isCaloBarrel(int sample) const;
    double deta(int sample,double eta) const;
@@ -54,9 +52,9 @@ class FastCaloSimCaloExtrapolation:public AthAlgTool, public IFastCaloSimCaloExt
    double zmid(int sample,double eta) const;
    double zent(int sample,double eta) const;
    double zext(int sample,double eta) const;
-   double rpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double zpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double rzpos(int sample,double eta,int subpos=SUBPOS_MID) const;
+   double rpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+   double zpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+   double rzpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
    
    HepPDT::ParticleDataTable*     m_particleDataTable;
    
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h
deleted file mode 100755
index 006e00553e44899124d3743afb5587f5ba5561ca..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef FastCaloSim_CaloCell_ID_h
-#define FastCaloSim_CaloCell_ID_h
-
-#include "CaloGeoHelpers/CaloSampling.h"
-
-namespace CaloCell_ID_FCS {
-  enum CaloSample_FCS {
-    FirstSample=CaloSampling::PreSamplerB,
-    PreSamplerB=CaloSampling::PreSamplerB, EMB1=CaloSampling::EMB1, EMB2=CaloSampling::EMB2, EMB3=CaloSampling::EMB3,       // LAr barrel
-    PreSamplerE=CaloSampling::PreSamplerE, EME1=CaloSampling::EME1, EME2=CaloSampling::EME2, EME3=CaloSampling::EME3,       // LAr EM endcap
-    HEC0=CaloSampling::HEC0, HEC1=CaloSampling::HEC1, HEC2=CaloSampling::HEC2, HEC3=CaloSampling::HEC3,      // Hadronic end cap cal.
-    TileBar0=CaloSampling::TileBar0, TileBar1=CaloSampling::TileBar1, TileBar2=CaloSampling::TileBar2,      // Tile barrel
-    TileGap1=CaloSampling::TileGap1, TileGap2=CaloSampling::TileGap2, TileGap3=CaloSampling::TileGap3,      // Tile gap (ITC & scint)
-    TileExt0=CaloSampling::TileExt0, TileExt1=CaloSampling::TileExt1, TileExt2=CaloSampling::TileExt2,      // Tile extended barrel
-    FCAL0=CaloSampling::FCAL0, FCAL1=CaloSampling::FCAL1, FCAL2=CaloSampling::FCAL2,                        // Forward EM endcap
-
-    // Beware of MiniFCAL! We don't have it, so different numbers after FCAL2
-    
-    LastSample = CaloSampling::FCAL2,
-    MaxSample = LastSample+1,
-    noSample = -1
-  };
-  typedef CaloSample_FCS CaloSample;
-}
-#endif
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FitDetailedShape.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FitDetailedShape.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6a89f50a460e6cd97eba885090889685b10949d
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/FitDetailedShape.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FitDetailedShape_h
+#define FitDetailedShape_h
+
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+#include "TTree.h"
+
+class FitDetailedShape{
+
+  public:
+  	
+    FitDetailedShape();
+    virtual ~FitDetailedShape() {}
+    void run(std::string,int,std::string,std::string,int,float,bool);
+	  
+  private:
+    
+  ClassDef(FitDetailedShape,2);
+  
+};
+
+#endif
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 9ce690ef0da6a34dc4ce8adfaf9b0a7fff5b93fd..13f304cb5a48ad5e0ac33e2d8c58696d18f8c269 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ICaloGeometry.h
@@ -6,9 +6,9 @@
 #define ICaloGeometry_h
 
 #include "Identifier/Identifier.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 
 class CaloDetDescrElement;
-   
 class ICaloGeometry {
 public :
    virtual bool PostProcessGeometry() = 0;
@@ -30,10 +30,9 @@ public :
    virtual double zmid(int sample,double eta) const = 0;
    virtual double zent(int sample,double eta) const = 0;
    virtual double zext(int sample,double eta) const = 0;
-   enum SUBPOS { SUBPOS_MID = 0, SUBPOS_ENT = 1, SUBPOS_EXT = 2}; //MID=middle, ENT=entrance, EXT=exit of cal layer
-   virtual double rpos(int sample,double eta,int subpos=SUBPOS_MID) const = 0;
-   virtual double zpos(int sample,double eta,int subpos=SUBPOS_MID) const = 0;
-   virtual double rzpos(int sample,double eta,int subpos=SUBPOS_MID) const = 0;
+   virtual double rpos(int sample,double eta,int subpos=CaloSubPos::SUBPOS_MID) const = 0;
+   virtual double zpos(int sample,double eta,int subpos=CaloSubPos::SUBPOS_MID) const = 0;
+   virtual double rzpos(int sample,double eta,int subpos=CaloSubPos::SUBPOS_MID) const = 0;
    virtual bool   isCaloBarrel(int sample) const = 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 a8da75e437546348a8063beea43eed9b75dc1cc7..2d8b54825da701c4326530419128de8cf257d062 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,9 +25,9 @@
 #include "TrkParameters/TrackParameters.h"
 //#####################################
 
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
 #include "ISF_FastCaloSimParametrization/FastCaloSimCaloExtrapolation.h"
 #include "ISF_FastCaloSimParametrization/IFastCaloSimGeometryHelper.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 
 namespace Trk {
   class TrackingVolume;
@@ -77,7 +77,6 @@ class ISF_HitAnalysis : public AthAlgorithm {
    virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS);
    virtual StatusCode updateMetaData(IOVSVC_CALLBACK_ARGS);
 
-   enum SUBPOS { SUBPOS_MID = 0, SUBPOS_ENT = 1, SUBPOS_EXT = 2}; //MID=middle, ENT=entrance, EXT=exit of cal layer
    //bool get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector,CaloCell_ID_FCS::CaloSample sample);
    bool get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector,int sample,int subpos=SUBPOS_MID);
    bool get_calo_surface(std::vector<Trk::HitInfo>* hitVector);
@@ -216,9 +215,9 @@ class ISF_HitAnalysis : public AthAlgorithm {
    double zmid(int sample,double eta) const;
    double zent(int sample,double eta) const;
    double zext(int sample,double eta) const;
-   double rpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double zpos(int sample,double eta,int subpos=SUBPOS_MID) const;
-   double rzpos(int sample,double eta,int subpos=SUBPOS_MID) const;
+   double rpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+   double zpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
+   double rzpos(int sample,double eta,int subpos = CaloSubPos::SUBPOS_MID) const;
    
    bool   m_layerCaloOK[CaloCell_ID_FCS::MaxSample][3];
    double m_letaCalo[CaloCell_ID_FCS::MaxSample][3];
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h
new file mode 100644
index 0000000000000000000000000000000000000000..3488f519b6c5ac7fbe58041dcede2f87f4e1e687
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/IntArray.h
@@ -0,0 +1,9 @@
+/*
+  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/TFCS1DFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunction.h
deleted file mode 100644
index 8abcf1c793ea75d8b5e3359a029e8693f184ec3a..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunction.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCS1DFunction_h
-#define TFCS1DFunction_h
-
-#include "TH1.h"
-#include "TTree.h"
-
-class TFCS1DFunction:public TObject
-{
-  public:
-    TFCS1DFunction();
-    TFCS1DFunction(TH1* hist);
-    
-    virtual void Initialize(TH1* hist);
-    int testHisto(TH1* hist);
-    
-    virtual double rnd_to_fct(double rnd);
-
-    TH1* transform(TH1*);
-    double get_maxdev(TH1* h_input, TH1* h_approx);
-    void tmvaregression_training(int, TTree *regTree, std::string);
-    double get_range_low(TH1* hist);
-    double tmvaregression_application(double, std::string);
-    TH1* get_cumul(TH1* hist);
-
-  private:
- 
- ClassDef(TFCS1DFunction,1)  //TFCS1DFunction
-};
-
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCS1DFunction;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
index dabc35f69c3031354235f0762a2a430459fd3af6..13ccc11f6c4078a3d65684463b689bd37255d1b3 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionHistogram.h
@@ -5,7 +5,7 @@
 #ifndef TFCS1DFunctionHistogram_h
 #define TFCS1DFunctionHistogram_h
 
-#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
 #include "TH1.h"
 #include <vector>
 
@@ -14,29 +14,28 @@ class TFCS1DFunctionHistogram:public TFCS1DFunction
 	
   public:
     TFCS1DFunctionHistogram();
-    TFCS1DFunctionHistogram(TH1* hist);
+    TFCS1DFunctionHistogram(TH1* hist, int,double);
     
-    virtual void Initialize(TH1* hist);
+    void Initialize(TH1* hist, int,double);
     virtual double rnd_to_fct(double rnd);
     
     TH1* vector_to_histo();
-    void smart_rebinning(TH1* hist, double);
+    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:
 
-    std::vector<float> m_HistoBorders;
-    std::vector<float> m_HistoContents;
-  
+    vector<float> m_HistoBorders;
+    vector<float> m_HistoContents;
+    
   ClassDef(TFCS1DFunctionHistogram,1)  //TFCS1DFunctionHistogram
 
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCS1DFunction;
-#pragma link C++ class TFCS1DFunctionHistogram;
-#endif
-
 #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
index 1f50a83e680dd9417ea326e295b4582ea51a50f8..5f92d674d9a86a63fd28a7a83ca5a25d2b02980c 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h
@@ -5,7 +5,8 @@
 #ifndef TFCS1DFunctionRegression_h
 #define TFCS1DFunctionRegression_h
 
-#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
 #include "TTree.h"
 #include "TH1.h"
 #include <vector>
@@ -16,28 +17,22 @@ class TFCS1DFunctionRegression:public TFCS1DFunction
   	
     TFCS1DFunctionRegression();
     TFCS1DFunctionRegression(TH1* hist);
-    TFCS1DFunctionRegression(std::string);
     
     virtual void Initialize(TH1* hist);
-    virtual void Initialize(std::string);
+    void storeRegression(string);
     virtual double rnd_to_fct(double rnd);
-
-  private:
     
-    std::vector<std::vector<double> > m_fWeightMatrix0to1;
-    std::vector<std::vector<double> > m_fWeightMatrix1to2;
+  //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
   
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCS1DFunction;
-#pragma link C++ class TFCS1DFunctionRegression;
-#endif
-
 #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
new file mode 100644
index 0000000000000000000000000000000000000000..82eb784956f39ae623286184c47df95eeb6f15cd
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS1DFunctionRegressionTF.h
@@ -0,0 +1,33 @@
+/*
+  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;
+		
+  ClassDef(TFCS1DFunctionRegressionTF,1)
+  
+};
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunction.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc243737ef1b7f1cb19c849631e6220227ec73ba
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunction.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TFCS2DFunction_h
+#define TFCS2DFunction_h
+
+
+#include "TTree.h"
+#include "TH2.h"
+
+class TFCS2DFunction:public TObject
+{
+  public:
+    TFCS2DFunction();
+    TFCS2DFunction(std::string);
+    
+    void Initialize(std::string);
+    int fitShape(std::string, std::string, std::string, std::string, std::string, int,float,bool);
+    
+    void tmvaregression_training(int,std::string, std::string, std::string, int,bool);
+    std::vector<float> tmvaregression_application(Float_t, Float_t, std::string, int);
+    void plotpolar(TH2F*, TH2F*, std::string, std::string, std::string,int,float,bool);
+
+
+  private:
+ 
+ ClassDef(TFCS2DFunction,1)  //TFCS2DFunction
+};
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3682f7f919a7b0f7cd771a3065d26fcd6be2cc2
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TFCS2DFunctionRegression_h
+#define TFCS2DFunctionRegression_h
+
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+#include "TTree.h"
+#include "TH1.h"
+#include <vector>
+
+class TFCS2DFunctionRegression:public TFCS2DFunction
+{
+  public:
+  	
+    TFCS2DFunctionRegression();
+    TFCS2DFunctionRegression(TH1* hist);
+    
+    void Initialize(TH1* hist);
+    void storeRegression(string,int);
+    double rnd_to_fct(std::vector<double>,int);
+    
+  private:
+    
+    vector<vector<double> > m_fWeightMatrix0to1;
+    vector<vector<double> > m_fWeightMatrix1to2;
+    
+    double regression_value(std::vector<double> vuniform,int);
+    void get_weights(std::string,int);
+    void validate(int,std::string,int);
+		  
+  ClassDef(TFCS2DFunctionRegression,1)  //TFCS1DFunctionRegression
+  
+};
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2Function.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2Function.h
new file mode 100644
index 0000000000000000000000000000000000000000..11e004e460ac9cbe282344ece5850c560c23a1b7
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCS2Function.h
@@ -0,0 +1,19 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TFCS2Function_h
+#define TFCS2Function_h
+
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+
+class TFCS2Function {
+  public:
+  static TFCS2DFunction* Create(std::string, int, std::string, std::string, int, float,bool);
+  virtual ~TFCS2Function() {}
+  private:
+
+  ClassDef(TFCS2Function,1)  //TFCS2Function
+};
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h
deleted file mode 100644
index cc566b3265d3016ef28ce1512aae10566ba7f1b5..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSEnergyParametrization_h
-#define TFCSEnergyParametrization_h
-
-#include "ISF_FastCaloSimParametrization/TFCSParametrization.h"
-
-class TFCSEnergyParametrization:public TFCSParametrization {
-public:
-  TFCSEnergyParametrization(const char* name=0, const char* title=0);
-
-  virtual bool is_match_Ekin_bin(int /*Ekin_bin*/) const {return true;};
-  virtual bool is_match_calosample(int /*calosample*/) const {return true;};
-  
-  // return number of energy parametrization bins
-  virtual int n_bins() {return 0;};
-  
-private:
-
-  ClassDef(TFCSEnergyParametrization,1)  //TFCSEnergyParametrization
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSEnergyParametrization;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSExtrapolationState.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSExtrapolationState.h
deleted file mode 100644
index 386d663f71f3a2fec04453eed8e67d259609be20..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSExtrapolationState.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSExtrapolationState_h
-#define TFCSExtrapolationState_h
-
-#include <TObject.h>
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
-
-class TFCSExtrapolationState:public TObject {
-  public:
-    TFCSExtrapolationState();
-
-    void clear();
-    
-    enum SUBPOS { SUBPOS_MID = 0, SUBPOS_ENT = 1, SUBPOS_EXT = 2}; //MID=middle, ENT=entrance, EXT=exit of cal layer
-
-    void set_OK (int layer,int subpos,bool   val) {m_CaloOK[layer][subpos]=val;};
-    void set_eta(int layer,int subpos,double val) {m_etaCalo[layer][subpos]=val;};
-    void set_phi(int layer,int subpos,double val) {m_phiCalo[layer][subpos]=val;};
-    void set_r  (int layer,int subpos,double val) {m_rCalo[layer][subpos]=val;};
-    void set_z  (int layer,int subpos,double val) {m_zCalo[layer][subpos]=val;};
-    void set_d  (int layer,int subpos,double val) {m_dCalo[layer][subpos]=val;};
-    void set_detaBorder(int layer,int subpos,double val) {m_distetaCaloBorder[layer][subpos]=val;};
-    void set_IDCaloBoundary_eta(double val) {m_IDCaloBoundary_eta=val;};
-    void set_IDCaloBoundary_phi(double val) {m_IDCaloBoundary_phi=val;};
-    void set_IDCaloBoundary_r(double val) {m_IDCaloBoundary_r=val;};
-    void set_IDCaloBoundary_z(double val) {m_IDCaloBoundary_z=val;};
-
-    bool   OK(int layer,int subpos) const {return m_CaloOK[layer][subpos];};
-    double eta(int layer,int subpos) const {return m_etaCalo[layer][subpos];};
-    double phi(int layer,int subpos) const {return m_phiCalo[layer][subpos];};
-    double r(int layer,int subpos) const {return m_rCalo[layer][subpos];};
-    double z(int layer,int subpos) const {return m_zCalo[layer][subpos];};
-    double d(int layer,int subpos) const {return m_dCalo[layer][subpos];};
-    double detaBorder(int layer,int subpos) const {return m_distetaCaloBorder[layer][subpos];};
-
-    double IDCaloBoundary_eta() const {return m_IDCaloBoundary_eta;};
-    double IDCaloBoundary_phi() const {return m_IDCaloBoundary_phi;};
-    double IDCaloBoundary_r() const {return m_IDCaloBoundary_r;};
-    double IDCaloBoundary_z() const {return m_IDCaloBoundary_z;};
-
-  private:
-    bool   m_CaloOK[CaloCell_ID_FCS::MaxSample][3];
-    double m_etaCalo[CaloCell_ID_FCS::MaxSample][3];
-    double m_phiCalo[CaloCell_ID_FCS::MaxSample][3];
-    double m_rCalo[CaloCell_ID_FCS::MaxSample][3];
-    double m_zCalo[CaloCell_ID_FCS::MaxSample][3];
-    double m_dCalo[CaloCell_ID_FCS::MaxSample][3];
-    double m_distetaCaloBorder[CaloCell_ID_FCS::MaxSample][3];
-    
-    double m_IDCaloBoundary_eta;
-    double m_IDCaloBoundary_phi;
-    double m_IDCaloBoundary_r;
-    double m_IDCaloBoundary_z;
-
-  ClassDef(TFCSExtrapolationState,1)  //TFCSExtrapolationState
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSExtrapolationState;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h
index 8ac72230d546904fe50a094a60eb1d2a404f440e..996ae2c4908ffad73c35156f4d65891e80d41375 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSFunction.h
@@ -5,19 +5,18 @@
 #ifndef TFCSFunction_h
 #define TFCSFunction_h
 
-#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
 
-class TFCSFunction {
+class TFCSFunction
+{
   public:
-    static TFCS1DFunction* Create(TH1* hist);
+    TFCSFunction();
     virtual ~TFCSFunction() {}
+    static TFCS1DFunction* Create(TH1* hist,int,int,int,double,double,int);
   private:
 
-  ClassDef(TFCSFunction,1)  //TFCSFunction
+  ClassDef(TFCSFunction,1)
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSFunction;
-#endif
-
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h
index fc0217544261e25e3570c2170d688d713f1a2cb5..db902724af5f1da008567c09a39285ce7ed01a7e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h
@@ -5,7 +5,7 @@
 #ifndef TFCSLateralShapeParametrization_h
 #define TFCSLateralShapeParametrization_h
 
-#include "ISF_FastCaloSimParametrization/TFCSParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrization.h"
 
 class TFCSLateralShapeParametrization:public TFCSParametrization {
 public:
@@ -33,8 +33,4 @@ private:
   ClassDef(TFCSLateralShapeParametrization,1)  //TFCSLateralShapeParametrization
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSLateralShapeParametrization;
-#endif
-
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h
index 47e4f6ab37947a5fc3c32d637886b14b1f5914f1..e38c9bbead0a6604b5d30a4fd99fdba9d9a93a42 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h
@@ -21,8 +21,4 @@ private:
   ClassDef(TFCSNNLateralShapeParametrization,1)  //TFCSNNLateralShapeParametrization
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSNNLateralShapeParametrization;
-#endif
-
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSPCAEnergyParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSPCAEnergyParametrization.h
deleted file mode 100644
index 0c951cf24f92cff39775879c11f4b4d2e4fe3635..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSPCAEnergyParametrization.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSPCAEnergyParametrization_h
-#define TFCSPCAEnergyParametrization_h
-
-#include "ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h"
-#include "TMatrixD.h"
-#include "TVectorD.h"
-#include "TFile.h"
-
-class TFCSPCAEnergyParametrization:public TFCSEnergyParametrization
-{
- public:
-  TFCSPCAEnergyParametrization(const char* name=0, const char* title=0);
-  
-  // energies in calo layers should be returned in simulstate
-  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
-  
-  //int n_bins() {return 0;};
-  // CHANGE: return number of energy parametrization bins
-  int n_bins() {return m_EigenVectors.size();};
-  void P2X(int gNVariables, TMatrixD *EigenVectors,TVectorD *MeanValues, TVectorD *SigmaValues, double *p, double *x, int nTest); 
-  void loadInputs(TFile* file);
-  
- private:
-  // PCA Matrix and NN mapping information should be stored as private member variables here
-  
-  std::vector<TMatrixD*> m_EigenVectors;
-  std::vector<TVectorD*> m_MeanValues;
-  std::vector<TVectorD*> m_SigmaValues;
-  std::vector<TVectorD*> m_RelevantLayers;
-  std::vector<TVectorD*> m_Gauss_means;
-  std::vector<TVectorD*> m_Gauss_rms;
-  
-  
-  
-  ClassDef(TFCSPCAEnergyParametrization,1)  //TFCSPCAEnergyParametrization
- 
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSPCAEnergyParametrization;
-#endif
-
-#endif
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrization.h
deleted file mode 100644
index c35008ee569fd1fc42b4acde289ba9e3ed55bac0..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrization.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSParametrization_h
-#define TFCSParametrization_h
-
-#include "ISF_FastCaloSimParametrization/TFCSParametrizationBase.h"
-
-class TFCSParametrization:public TFCSParametrizationBase {
-public:
-  TFCSParametrization(const char* name=0, const char* title=0);
-  
-  virtual bool is_match_pdgid(int id) const {return m_pdgid.find(id)!=m_pdgid.end();};
-  virtual bool is_match_Ekin(float Ekin) const {return (Ekin>=m_Ekin_min) && (Ekin<m_Ekin_max);};
-  virtual bool is_match_eta(float eta) const {return (eta>=m_eta_min) && (eta<m_eta_max);};
-
-  const std::set< int > &pdgid() const {return m_pdgid;};
-  double Ekin_nominal() const {return m_Ekin_nominal;};
-  double Ekin_min() const {return m_Ekin_min;};
-  double Ekin_max() const {return m_Ekin_max;};
-  double eta_nominal() const {return m_eta_nominal;};
-  double eta_min() const {return m_eta_min;};
-  double eta_max() const {return m_eta_max;};
-  
-  void set_pdgid(int id);
-  void add_pdgid(int id);
-  void clear_pdgid();
-  
-  void set_Ekin_nominal(double min);
-  void set_Ekin_min(double min);
-  void set_Ekin_max(double max);
-  void set_eta_nominal(double min);
-  void set_eta_min(double min);
-  void set_eta_max(double max);
-  
-private:
-  std::set< int > m_pdgid;
-  double m_Ekin_nominal,m_Ekin_min,m_Ekin_max;
-  double m_eta_nominal,m_eta_min,m_eta_max;
-
-  ClassDef(TFCSParametrization,1)  //TFCSParametrization
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSParametrization;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrizationBase.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrizationBase.h
deleted file mode 100644
index 332c0986e4d2dfef4ad8fac0f5486f408a053796..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSParametrizationBase.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSParametrizationBase_h
-#define TFCSParametrizationBase_h
-
-#include <TNamed.h>
-#include <set>
-#include "ISF_FastCaloSimParametrization/TFCSSimulationState.h"
-#include "ISF_FastCaloSimParametrization/TFCSTruthState.h"
-#include "ISF_FastCaloSimParametrization/TFCSExtrapolationState.h"
-
-class TFCSParametrizationBase:public TNamed {
-public:
-  TFCSParametrizationBase(const char* name=0, const char* title=0);
-  
-  virtual bool is_match_pdgid(int /*id*/) const {return false;};
-  virtual bool is_match_Ekin(float /*Ekin*/) const {return false;};
-  virtual bool is_match_eta(float /*eta*/) const {return false;};
-
-  virtual bool is_match_Ekin_bin(int /*Ekin_bin*/) const {return false;};
-  virtual bool is_match_calosample(int /*calosample*/) const {return false;};
-
-  virtual const std::set< int > &pdgid() const {return m_no_pdgid;};
-  virtual double Ekin_nominal() const {return 0;};
-  virtual double Ekin_min() const {return 0;};
-  virtual double Ekin_max() const {return 0;};
-  virtual double eta_nominal() const {return 100;};
-  virtual double eta_min() const {return 100;};
-  virtual double eta_max() const {return 100;};
-
-  // Do some simulation. Result should be returned in simulstate
-  // Simulate all energies in calo layers for energy parametrizations
-  // Simulate one HIT for later shape parametrizations (TO BE DISCUSSED!)
-  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
-
-  void Print(Option_t *option = "") const;
-private:
-  static std::set< int > m_no_pdgid;
-
-  ClassDef(TFCSParametrizationBase,1)  //TFCSParametrizationBase
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSParametrizationBase;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h
index ca4f804423409c81c545a3d04ef87926e37b7722..fe3eda69b9d5173e3cfad60a67992a0c7bb710bd 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h
@@ -28,40 +28,36 @@ public:
   bool Initialize(float input_sigma_x, float input_sigma_y)
   {
         // Setup random numbers
-        rnd = new TRandom3();
-        rnd->SetSeed(0);
+        m_rnd = new TRandom3();
+        m_rnd->SetSeed(0);
 
-        sigma_x = input_sigma_x;
-        sigma_y = input_sigma_y;
+        m_sigmaX = input_sigma_x;
+        m_sigmaY = input_sigma_y;
         return true;
   };
 
   void getHitXY(double &x, double &y);
 
-  float getSigma_x(){return sigma_x;};
-  float getSigma_y(){return sigma_y;};
+  float getSigma_x(){return m_sigmaX;};
+  float getSigma_y(){return m_sigmaY;};
   
 
 
 private:
   // simple shape information should be stored as private member variables here
 
-  float sigma_x;
-  float sigma_y;
+  float m_sigmaX;
+  float m_sigmaY;
 
   //float sigma2_x;
   //float sigma2_y;
 
   //float gaus_ratio;
 
-  TRandom3 *rnd;
+  TRandom3 *m_rnd;
 
 
   ClassDef(TFCSSimpleLateralShapeParametrization,1)  //TFCSSimpleLateralShapeParametrization
 };
 
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSSimpleLateralShapeParametrization;
-#endif
-
 #endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimulationState.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimulationState.h
deleted file mode 100644
index e9860e3eaf851e381729bba3eb9097cef1c0d865..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSSimulationState.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSSimulationState_h
-#define TFCSSimulationState_h
-
-#include <TObject.h>
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
-
-class TFCSSimulationState:public TObject
-{
-  public:
-    TFCSSimulationState();
-    
-    bool   is_valid() const {return m_Ebin>=0;};
-    double E() const {return m_Etot;};
-    double E(int sample) const {return m_E[sample];};
-    int    Ebin() const {return m_Ebin;};
-    
-    void set_Ebin(int bin) {m_Ebin=bin;};
-    void add_E(int sample,double Esample) {m_E[sample]+=Esample;m_Etot+=Esample;};
-    
-    //empty function so far
-    //not sure if we should keep the function here or rather write a deposit_cell function or similar
-    virtual void deposit_HIT(int sample,double hit_eta,double hit_phi,double hit_weight);
-
-    void clear();
-  private:
-    int    m_Ebin;
-    double m_Etot;
-    double m_E[CaloCell_ID_FCS::MaxSample];
-
-  ClassDef(TFCSSimulationState,1)  //TFCSSimulationState
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSSimulationState;
-#endif
-
-#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSTruthState.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSTruthState.h
deleted file mode 100644
index 9666139dbecc952fbbe3912364c2a39b5a7ce7d9..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TFCSTruthState.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TFCSTruthState_h
-#define TFCSTruthState_h
-
-#include <TLorentzVector.h>
-
-class TFCSTruthState:public TLorentzVector {
-  public:
-    TFCSTruthState();
-    TFCSTruthState(Double_t x, Double_t y, Double_t z, Double_t t, int pdgid);
-    
-    void set_pdgid(int val) {m_pdgid=val;};
-    void set_vertex(const TLorentzVector& val) {m_vertex=val;};
-    void set_vertex(Double_t x, Double_t y, Double_t z, Double_t t=0) {m_vertex.SetXYZT(x,y,z,t);};
-    
-    int    pdgid() const {return m_pdgid;};
-    double Ekin() const {return E()-M();};
-    const TLorentzVector& vertex() const {return m_vertex;};
-  private:
-    int m_pdgid;
-    TLorentzVector m_vertex;
-
-  ClassDef(TFCSTruthState,1)  //TFCSTruthState
-};
-
-#if defined(__MAKECINT__)
-#pragma link C++ class TFCSTruthState;
-#endif
-
-#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 f18953a2396ec97249911dd71cb2eccdcfd8b3cb..9b9e3396a3b1111d524afc3002d12e65089623dd 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/TreeReader.h
@@ -2,8 +2,8 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef TREEREADER_H
-#define TREEREADER_H
+#ifndef TreeReader_h
+#define TreeReader_h
 
 //////////////////////////////////////////////////
 //
@@ -31,10 +31,10 @@ class TreeReader //: public TTreeFormulaManager
  private:
 
   TTree* m_tree;
-  int              m_currentEntry; 			// current ntuple entry stored in buffer
-  int              m_entries;      			// total number of entries
-  bool             m_isChain;
-  int              m_currentTree;
+  int    m_currentEntry; 			// current ntuple entry stored in buffer
+  int    m_entries;      			// total number of entries
+  bool   m_isChain;
+  int    m_currentTree;
   std::map<std::string, TTreeFormula*>     m_formulae;	// known formulae
 
  public:
@@ -43,12 +43,13 @@ class TreeReader //: public TTreeFormulaManager
   TreeReader(TTree* n);       // ctor with ntuple
   virtual ~TreeReader();      // dtor
 
-  void SetTree(TTree* n);       //
+  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);
-  int      GetEntries()             { return m_entries ; }
-  TTree*   GetTree()                { return m_tree    ; }
-  void Restart()                    {m_currentEntry = -1;}
+  int    GetEntries()             { return m_entries ; }
+  TTree* GetTree()                { return m_tree    ; }
+  void   Restart()                    {m_currentEntry = -1;}
+
   ClassDef(TreeReader,0);  // Integrate this class into ROOT (must be the last member)
 };
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h
index 8ab21c2b5561adb363534e4a4263d37d677859f7..8ac9fde492877e73008d5a5293d8f2be3514285e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/firstPCA.h
@@ -4,35 +4,44 @@
 
 #ifndef firstPCA_h
 #define firstPCA_h
-
-
-
+#include "TChain.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
 
 class firstPCA
 {
   public:
   	
+    firstPCA(TChain*, string);
     firstPCA();
     virtual ~firstPCA() {}
-    std::string run(std::string, std::string, int, int, int, double);
-    std::vector<int> get_relevantlayers(TreeReader*, double);
-    std::vector<TH1D*> get_histos_data(std::vector<int> layerNr, std::vector<std::string> layer, TreeReader*, TTree*, int);
-    std::vector<TH1D*> get_cumul_data(std::vector<std::string> layer, std::vector<TH1D*>);
+    void run();
+    vector<TH1D*> get_relevantlayers_inputs(vector<int> &, TreeReader*);
+    vector<TH1D*> get_cumul_histos(vector<string> layer, vector<TH1D*>);
     static double get_cumulant(double x, TH1D* h);
     void quantiles(TH1D* h, int nq, double* xq, double* yq);
-				
-  private:
+
+    void set_cumulativehistobins(int);
+    void set_edepositcut(double);
+    void set_etacut(double,double);
+    void apply_etacut(int);
+    void set_pcabinning(int,int);
     
+  private:
+  	
+  	int    m_debuglevel;
+  	double m_cut_eta_low;
+  	double m_cut_eta_high;
+  	int    m_apply_etacut;
+  	int    m_nbins1;
+  	int    m_nbins2;
+  	int    m_numberfinebins;
+  	double m_edepositcut;
+  	string m_outfilename;
+  	TChain* m_chain;
+  	
   ClassDef(firstPCA,1);
   
 };
 
-
-#if defined(__MAKECINT__)
-#pragma link C++ class firstPCA;
-#endif
-
-
 #endif
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h
index 41c232443067fa0eb1169421582607f96d04ee63..6c6f354678f08602c7602367bca3bd5de49efa85 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/secondPCA.h
@@ -5,34 +5,45 @@
 #ifndef secondPCA_h
 #define secondPCA_h
 
-//#include "TH1D.h"
-//#include "TPrincipal.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
 #include "ISF_FastCaloSimParametrization/firstPCA.h"
-//#include "TTree.h"
+//#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
 
 class secondPCA:public firstPCA
 {
   public:
   	
-    secondPCA();
-    virtual ~secondPCA() {}
-    void run(std::string,std::string,int,int,int);
-    std::vector<int> getLayerBins(TFile* file, int &bins);
-		void do_pca(std::vector<std::string> layer, int bin, TreeReader* read_inputTree, TTree* InputTree, int, TFile*, double* samplings);
-    static std::vector<TH1D*> get_histos_data(std::vector<std::string> layer, TreeReader*, TTree*, int);
-	
+    secondPCA(string,string);
+    //virtual ~secondPCA();
+    void run();
+    vector<int> getLayerBins(TFile* file, int &bins);
+		void do_pca(vector<string>, int, TreeReader*, int*);
+    vector<TH1D*> get_histos_data(vector<string> layer, TreeReader*);
+	  double get_lowerBound(TH1D* h_cumulative);
+	  
+	  void set_cumulativehistobins(int);
+	  void set_storeDetails(int);
+	  void set_skip_regression(int);
+    void set_PCAbin(int);
+    void set_cut_maxdeviation_regression(double val);
+    void set_cut_maxdeviation_smartrebin(double val);
+    void set_Ntoys(int val);
+    void set_neurons_iteration(int start,int end);
+	  
   private:
     
+    int m_numberfinebins;
+    int m_storeDetails;
+    int m_PCAbin;
+    int m_skip_regression;
+    string m_outfilename,m_firstpcafilename;
+    int m_neurons_start,m_neurons_end,m_ntoys;
+    double m_maxdev_regression,m_maxdev_smartrebin;
+    
   ClassDef(secondPCA,2);
   
 };
 
-
-#if defined(__MAKECINT__)
-#pragma link C++ class secondPCA;
-#endif
-
-
 #endif
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/DetailedShapeBinning.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/DetailedShapeBinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ed6c7d5b5058b3efd5b0be52bb3307a2e88c0f02
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/DetailedShapeBinning.cxx
@@ -0,0 +1,978 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+using namespace std;
+
+#include "TMatrixD.h"
+#include "TVectorD.h"
+#include "TH1.h"
+#include "TFile.h"
+#include "TROOT.h"
+#include "TSystem.h"
+#include "TApplication.h"
+#include "TTree.h"
+#include "TStyle.h"
+#include "TSystem.h"
+#include "TH2D.h"
+#include "TLine.h"
+#include "TPrincipal.h"
+#include "TBranch.h"
+#include "TChain.h"
+#include "TMath.h"
+#include "TLatex.h"
+#include "TCanvas.h"
+#include "TBrowser.h"
+#include "ISF_FastCaloSimParametrization/DetailedShapeBinning.h"
+#include "tools/CaloGeometryFromFile.cxx"
+#include "tools/FCS_Cell.h"
+#include "TLorentzVector.h"
+#include <sstream>
+
+#include <iostream>
+#include <fstream>
+
+DetailedShapeBinning::DetailedShapeBinning()
+{
+}
+
+bool DetailedShapeBinning::run(bool doNNHit, bool ismatched, TChain* T, int nRBinsMAX, float layer, string particle, int PCAbin, string /*labeltitle*/, string labeloutput, float& /*mincalosize*/, float& cell_deta, float& cell_dphi, float& cellr, float& cellz, float& celleta, vector<float> etaslice)
+{
+
+  // input file 
+  //cout<<"--- Open input file "<<inputfile<<endl;
+  //TFile* file = TFile::Open(inputfile.c_str());
+  //if(!file) cout<<"ERROR: Inputfile could not be opened"<<endl;
+  //string mytrees="";
+  //if(ismatched && !doNNHit)  mytrees = "FCS_ParametrizationInput";
+  //if(!ismatched && !doNNHit) mytrees = "ISF_HitAnalysis/CaloHitAna";
+  //if(doNNHit) mytrees = "NNSimHit";
+  //TTree* T = (TTree*)file->Get(mytrees.c_str());
+
+  cout << "Number of events : " << T->GetEntries() << std::endl;
+
+  // output file 
+  string outFile = "output/DetailedShape_"+labeloutput+".root";
+  if(doNNHit) outFile = "output/DetailedShape_"+labeloutput+"_NNHits.root";
+
+  // Pi/8 rotation to contain the calo crack within a bin
+  float AlphaMin = TMath::Pi()/8.;
+  float AlphaMax = 2*TMath::Pi()+AlphaMin;
+  float Rmax = 10000 ; //random value 
+
+  TH1F* halpha = new TH1F("halpha","halpha",630000,AlphaMin,AlphaMax) ;
+  TH1F* hr = new TH1F("hr","hr",75000000,0,Rmax);
+  //Float_t xdummy[3];
+  //xdummy[0]=0;
+  //xdummy[1]=1;
+  //xdummy[2]=2;
+
+  float tolerance = 0.00000001; // for empty bin check
+  std::cout << "---Tolerance : "<< tolerance << std::endl;
+
+  // float cellr=0;
+  // float cellz=0;
+  // float celleta=0;
+  // float cell_deta=0;
+  // float cell_dphi=0;
+
+  // PCA file 
+  string myPCAfile = "output/firstPCA_w0_160406_5mmMergebins1st5_bins2nd1.root";
+  if(particle=="pi")
+    myPCAfile = "output/firstPCA_pions.root";
+
+  if(particle=="e")
+    //myPCAfile = "output/firstPCA_electrons.root";
+    myPCAfile = "/afs/cern.ch/user/s/schaarsc/public/fastcalo/pca/tools/output/s2864/firstPCA.root";
+
+  if(particle=="gamma")
+    myPCAfile = "output/firstPCA_photons.root";
+
+  std::cout << "--- Open PCA file : " << myPCAfile << std::endl;
+  TFile* FPCA           = TFile::Open(myPCAfile.c_str());
+
+  TTree* TPCA; 
+  if(particle=="e")   TPCA           = (TTree*)FPCA->Get("tree_1stPCA");
+  if(particle=="pi")  TPCA           = (TTree*)FPCA->Get("firstPCA");
+
+  vector<int> vbinPCA;
+
+  if(particle=="e"){
+    Int_t firstPCAbin = 1 ;
+    TPCA->SetBranchAddress("firstPCAbin",&firstPCAbin);
+    for(Int_t i=0;i<TPCA->GetEntries();i++){
+      TPCA->GetEntry(i);
+      vbinPCA.push_back(firstPCAbin);
+    }
+  }
+
+  if(particle=="pi"){
+    Int_t bin = 0 ; 
+    TPCA->SetBranchAddress("bin",&bin);
+    for(Int_t i=0;i<TPCA->GetEntries();i++){
+      TPCA->GetEntry(i);
+      vbinPCA.push_back(bin);
+    }
+  }
+
+  //Fill initial histos for binning: halpha, hr
+  //bool temp = fill(doNNHit,T,3,xdummy,3,xdummy,layer,particle,PCAbin,halpha,hr,tolerance,false,outFile,cellr,cellz,celleta,cell_deta,cell_dphi,vbinPCA,ismatched,labeloutput,etaslice);
+
+  // Alpha binning
+  cout << "--- Alpha calculation" << std::endl;
+  int nAlphaBins           = 8 ; 
+  int nAlphaboundaries     = nAlphaBins + 1 ;
+  vector<float> vAlphaBins = fVecBin(halpha,nAlphaBins,false);
+
+  Float_t AlphaBins[nAlphaboundaries];
+  for(Int_t i=0;i<nAlphaboundaries;i++){
+    AlphaBins[i] = vAlphaBins.at(i) ;
+    std::cout << "BIN ALPHA : " << i << "  " << AlphaBins[i] << std::endl;
+  }
+
+  // R binning - iterative
+  cout << "--- R calculation" << std::endl;
+  float nRBins    = 0 ;
+  int incr        = 0 ; 
+  bool isEmptyBin = true ; 
+  //float rgran     = 0 ; 
+
+  while(isEmptyBin)
+  {
+    nRBins               = nRBinsMAX-incr ;
+    int nRboundaries     = nRBins+1;
+    cout << "Test " << nRBins << " r bins" << std::endl;
+
+    vector<float> vRBins = fVecBin(hr,nRBins,true) ;
+
+    // try to fusion up to the 5 last bins
+    for(Int_t fusionindex=1;fusionindex<5;fusionindex++){
+
+      if(fusionindex>1) nRboundaries = nRboundaries-1;
+      Float_t RBins[nRboundaries];
+      for(Int_t i=0;i<nRboundaries;i++){
+        RBins[i] = vRBins.at(i) ;
+        if(fusionindex>1){// start fusioning bins
+          RBins[nRboundaries-1] = vRBins.at(vRBins.size()-1);
+        }
+      }
+
+      isEmptyBin = fill(doNNHit,T,nAlphaboundaries,AlphaBins,nRboundaries,RBins,layer,particle,PCAbin,*halpha,*hr,tolerance,true,outFile,cellr,cellz,celleta,cell_deta,cell_dphi,vbinPCA,ismatched,labeloutput,etaslice);
+      //rgran = (RBins[3]-RBins[0]) ;
+      TH1F hGradient(("hGradient_"+labeloutput).c_str(),"hGradient",nRBins,RBins) ;
+
+      if(!isEmptyBin){
+        // final R bins
+        if(fusionindex>1) cout << "Fusion of last bins : " << fusionindex << ", total R bins : " << nRboundaries-1 <<  std::endl;
+        for(Int_t i=0;i<nRboundaries;i++){
+          std::cout << "BIN R : " << i << "  " << RBins[i] << std::endl;
+        }
+
+        // check gradient
+        std::cout << "--- CHECKING GRADIENT" << std::endl;
+        //bool gradientOK = checkgradient(outFile,hGradient,labeloutput,labeltitle,doNNHit);
+
+        // check granularity
+        std::cout << "--- CHECKING GRANULARITY" << std::endl;
+        //bool granularityOK = checkgranularity(cell_deta,cell_dphi,cellr,cellz,celleta,rgran,AlphaBins,nAlphaBins,mincalosize);
+
+        // validation plots 
+        std::cout << "--- Validation plots" << std::endl;
+        //fillValidationPlot(layer,PCAbin,gradientOK,granularityOK,particle,labeloutput);
+
+        break;
+      }//checks and validation plots
+    }//fusion index
+    incr++;
+  }//while empty bin
+
+  return 0;
+}
+
+bool DetailedShapeBinning::fill(bool doNNHit,TTree* T, int nxbinsAlpha, Float_t *xbinsAlpha, int nybinsR, Float_t *ybinsR, float layer, string /*particle*/, float PCAbin, TH1F& halpha, TH1F& hr, float tolerance, bool testBinning, string outFile, float& cellr, float& cellz, float& celleta, float& cell_deta, float& cell_dphi, vector<int> vbinPCA, bool ismatched,string labeloutput, vector<float> etaslice)
+{
+
+  TH1::SetDefaultSumw2(kTRUE);
+
+  bool isEmptyBin = false;
+
+  std::ostringstream os;
+  os<<layer;
+  TString layerS = "Sampling_"+os.str();
+
+  // for matched ntuples 
+  FCS_matchedcellvector *vec=0;
+  std::vector<FCS_truth> *truth=0;
+
+  std::vector<float>* TruthPx = 0;
+  std::vector<float>* TruthPy = 0;
+  std::vector<float>* TruthPz = 0;
+  std::vector<float>* TruthE  = 0;
+
+  if(ismatched && !doNNHit)
+  {
+    T->SetBranchAddress(layerS,&vec);
+    T->SetBranchAddress("TruthCollection",&truth);
+    T->SetBranchAddress("TruthPx",&TruthPx);
+    T->SetBranchAddress("TruthPy",&TruthPy);
+    T->SetBranchAddress("TruthPz",&TruthPz);
+    T->SetBranchAddress("TruthE" ,&TruthE);
+  }
+
+  // for unmatched ntuples 
+  std::vector<float>* HitE = 0;
+  std::vector<float>* HitX=0;
+  std::vector<float>* HitY=0;
+  std::vector<float>* HitZ = 0;
+  vector< vector<double> >* TTC_entrance_eta = 0 ;
+  vector< vector<double> >* TTC_entrance_phi = 0 ;
+  vector< vector<double> >* TTC_entrance_r = 0 ;
+  std::vector<int>* HitSampling =0;
+  TBranch* bHitE = 0 ;
+  TBranch* bHitX = 0 ;
+  TBranch* bHitY = 0 ;
+  TBranch* bHitZ = 0 ;
+  TBranch* bTTC_entrance_eta = 0 ;
+  TBranch* bTTC_entrance_phi = 0 ;
+  TBranch* bTTC_entrance_r = 0 ;
+  TBranch* bHitSampling = 0 ;
+
+  if(!ismatched  && !doNNHit)
+  {
+    std::cout << "BEFORE BRANCH" << std::endl;
+    bHitE = T->GetBranch("HitE");
+    bHitE->SetAddress(&HitE);
+    bHitX = T->GetBranch("HitX");
+    bHitX->SetAddress(&HitX);
+    bHitY = T->GetBranch("HitY");
+    bHitY->SetAddress(&HitY);
+    bHitZ = T->GetBranch("HitZ");
+    bHitZ->SetAddress(&HitZ);
+    bTTC_entrance_eta = T->GetBranch("TTC_entrance_eta");
+    bTTC_entrance_eta->SetAddress(&TTC_entrance_eta);
+    bTTC_entrance_phi = T->GetBranch("TTC_entrance_phi");
+    bTTC_entrance_phi->SetAddress(&TTC_entrance_phi);
+    bTTC_entrance_r = T->GetBranch("TTC_entrance_r");
+    bTTC_entrance_r->SetAddress(&TTC_entrance_r);
+    bHitSampling = T->GetBranch("HitSampling");
+    bHitSampling->SetAddress(&HitSampling);
+    std::cout <<"AFTER BRANCH" << std::endl;
+  }
+
+  TBranch* bNNHitR = 0 ;
+  TBranch* bNNHitAlpha = 0 ;
+  TBranch* bNNHitLNEfrac = 0 ;
+  Float_t NNHitR = 0 ; 
+  Float_t NNHitAlpha = 0 ; 
+  Float_t NNHitLNEfrac = 0 ; 
+
+  if(doNNHit){
+    bNNHitR = T->GetBranch("NNHitR");
+    bNNHitR->SetAddress(&NNHitR);
+    bNNHitAlpha = T->GetBranch("NNHitAlpha");
+    bNNHitAlpha->SetAddress(&NNHitAlpha);
+    bNNHitLNEfrac = T->GetBranch("NNHitLNEfrac");
+    bNNHitLNEfrac->SetAddress(&NNHitLNEfrac);
+  }
+
+  // histograms ##############
+
+  vector<TH2F*> halphadrEvec;
+  // needed for the empty bin check
+  TH2F* hEnergyDensity = new TH2F("hEnergyDensity","hEnergyDensity",nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR) ;
+  TH2F* hEnergy = new TH2F("hEnergy","hEnergy",nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR) ;
+  TH2F* hNNHit  = new TH2F("hNNHit","hNNHit",nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR) ;
+
+  // needed to compare with the NN fit output
+  TH2F* hLNEnergy = new TH2F("hLNEnergy","hLNEnergy",nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR) ;
+  TH2F* hLNEnergyDensity = new TH2F("hLNEnergyDensity","hLNEnergyDensity",nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR) ;
+
+  // cell position ###########
+
+  float etacentre=0;
+  float phicentre=0;
+  int nhits=0;
+  float eta = 0 ; 
+  float phi = 0 ; 
+
+  ofstream ofML;
+  ofML.open(("output/MLHits_"+labeloutput+".txt").c_str());
+
+  int i_pcafile=-1;
+  if(!testBinning && !doNNHit)
+  {
+    int nsel=0;
+    //for(int i=0;i<T->GetEntries();i++)
+    for(int i=0;i<2000;i++)
+    {
+      if(i%200==0) std::cout << "Event: " << i << std::endl;
+      T->GetEntry(i);
+      if(ismatched)
+      {
+        TLorentzVector TruthTLV;
+        TruthTLV.SetPxPyPzE(TruthPx->at(0),TruthPy->at(0),TruthPz->at(0),TruthE->at(0));
+        float TruthEta=TruthTLV.Eta();
+        if(fabs(TruthEta)>etaslice.at(1) || fabs(TruthEta)<etaslice.at(0)) continue;
+        i_pcafile++;
+        if(vbinPCA.at(i_pcafile)!=PCAbin) continue;
+        for (UInt_t j=0; j<(*vec).size(); j++)
+        {
+          for (unsigned int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++)
+          {
+            float posx   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_x;
+            float posy   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_y;
+            float posz   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
+            TVector3 * pos         = new TVector3(posx,posy,posz);	  
+            eta              = pos->PseudoRapidity() ;
+            phi              = pos->Phi() ;
+            etacentre+=eta;
+            phicentre+=phi;
+            nhits++;
+          }
+        }
+      }
+      if(!ismatched)
+      {
+        bHitX->GetEntry(i);
+        bHitY->GetEntry(i);
+        bHitZ->GetEntry(i);
+        bHitSampling->GetEntry(i);
+        for(unsigned int j=0;j<HitX->size();j++)
+        {
+          float layer_id = HitSampling->at(j) ;
+          if(layer_id != layer) continue ;
+          TVector3 * pos         = new TVector3(HitX->at(j), HitY->at(j), HitZ->at(j)) ;
+          eta              = pos->PseudoRapidity() ;
+          phi              = pos->Phi() ;
+          etacentre+=eta;
+          phicentre+=phi;
+          nhits++;
+        }
+      }//end unmatched ntuple
+      nsel++;
+    }
+
+    std::cout << "Number of selected events : " << nsel << std::endl;
+
+    if (nhits > 0) {
+      etacentre=etacentre/nhits;
+      phicentre=phicentre/nhits;
+    } else {
+      std::cout << "DetailedShapeBinning() nhits==0; unable to divide etacentre,phicentre!";
+    }
+    //std::cout << "ETA,PHI CENTRES : " << etacentre << " " << phicentre << "  " << nhits << std::endl;
+
+    getcellgeom(layer,etacentre,phicentre,cellr,cellz,celleta,cell_deta,cell_dphi);
+    std::cout << "--- CELL POSITION (r,z,eta,deta,dphi) : " << cellr << "  " << cellz << "  " << celleta << " " <<  cell_deta << " " << cell_dphi << std::endl;
+  }
+
+  // loop on events ##########
+
+  i_pcafile=-1;
+  //for(int i=0;i<T->GetEntries();i++)  
+  for(int i=0;i<2000;i++)  
+  {
+    std::vector<float> vMLalpha;
+    std::vector<float> vMLr;
+    std::vector<float> vMLE;
+
+    if(i%200==0) std::cout << "Entry 2nd loop : " << i << std::endl;
+
+    if(ismatched || doNNHit)
+    {
+      T->GetEntry(i);
+    }
+
+    if(ismatched && !doNNHit)
+    {    
+      // Cut on eta of particle 
+      TLorentzVector TruthTLV;
+      TruthTLV.SetPxPyPzE(TruthPx->at(0),TruthPy->at(0),TruthPz->at(0),TruthE->at(0));
+      float TruthEta=TruthTLV.Eta();
+      if(fabs(TruthEta)>etaslice.at(1) || fabs(TruthEta)<etaslice.at(0)) continue;
+      i_pcafile++;
+    }
+
+
+    // veto on PCA bin 
+    if(!doNNHit && (i_pcafile >=0))
+      if(vbinPCA.at(i_pcafile)!=PCAbin) continue; 
+
+    if(!ismatched && !doNNHit){
+      bHitX->GetEntry(i);
+      bHitY->GetEntry(i);
+      bHitZ->GetEntry(i);
+      bHitE->GetEntry(i);
+      bHitSampling->GetEntry(i);
+      bTTC_entrance_r->GetEntry(i);
+      bTTC_entrance_eta->GetEntry(i);
+      bTTC_entrance_phi->GetEntry(i);
+    }
+
+    // histos to cumulate energy
+    if(testBinning && !doNNHit)
+    {
+      cout<<"TESTBIN 1"<<endl;
+      std::ostringstream histname;
+      histname << "halphadrEvec_";
+      histname << i;
+      TH2F* hnew = new TH2F(histname.str().c_str(),histname.str().c_str(),nxbinsAlpha-1,xbinsAlpha,nybinsR-1,ybinsR);
+      halphadrEvec.push_back(hnew);
+    }
+
+
+    if(doNNHit){
+      float alpha = NNHitAlpha;
+      float d_r   = NNHitR;
+      float LNenergy= NNHitLNEfrac;
+      float energy = TMath::Exp(LNenergy); // GERALDINE - IS THAT OK ? 
+      if(testBinning){
+        hLNEnergy->Fill(alpha,d_r,LNenergy);
+        hEnergy->Fill(alpha,d_r,energy);
+        hNNHit->Fill(alpha,d_r,1);
+      }
+      halpha.Fill(alpha);
+      float myweight;
+      if(energy>1)
+        myweight = energy;
+      else
+        myweight = 1 ;
+      hr.Fill(d_r,myweight);
+
+    }
+
+    if(!ismatched && !doNNHit)
+    {
+      //loop on hits
+      for(unsigned int j=0;j<HitX->size();j++){ 
+
+        // veto on layer
+        float layer_id = HitSampling->at(j) ;
+        if(layer_id != layer)
+          continue ;
+
+        float energy           = HitE->at(j); 
+        TVector3 * pos         = new TVector3(HitX->at(j), HitY->at(j), HitZ->at(j)) ;  
+        float eta              = pos->PseudoRapidity() ;
+        //float phi              = pos->Phi() ;
+        float eta_correction   = (TTC_entrance_eta->at(0)).at(layer_id) ;
+        float d_eta            = eta - eta_correction ;
+
+        float myy = (TTC_entrance_r->at(0)).at(layer_id) * TMath::Sin((TTC_entrance_phi->at(0)).at(layer_id)); 
+        float myx = (TTC_entrance_r->at(0)).at(layer_id) * TMath::Cos((TTC_entrance_phi->at(0)).at(layer_id)); 
+
+        TVector2 * myv2= new TVector2(myx,myy);
+        TVector2 * myv3= new TVector2(pos->X(),pos->Y());
+        float d_phi = myv3->DeltaPhi(*myv2) ;
+
+        // changes in mm 
+        unitsmm(eta,d_eta,d_phi,cellr,cellz);
+
+        float d_r   = TMath::Sqrt(d_phi*d_phi + d_eta*d_eta);
+
+        float alpha = TMath::ATan2(d_phi,d_eta);
+        if(alpha<(TMath::Pi()/8.))
+          alpha = 2*TMath::Pi()+alpha ;
+
+        if(testBinning)
+        {
+          cout<<"TESTBIN 2"<<endl;
+          halphadrEvec.at(i)->Fill(alpha,d_r,energy);
+        }
+        halpha.Fill(alpha);
+        float myweight;
+        if(energy>1)
+          myweight = energy;
+        else
+          myweight = 1 ;
+        hr.Fill(d_r,myweight);
+
+        vMLr.push_back(d_r);
+        vMLalpha.push_back(alpha);
+        vMLE.push_back(energy);
+      }
+    }// end unmatched 
+    if(ismatched && !doNNHit)
+    {
+
+      // loop on cells 
+      for (UInt_t j=0; j<(*vec).size(); j++){
+        // loop on hits
+        for (unsigned int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
+
+          // r and alpha calculation
+          float energy = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy;
+          float posx   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_x;
+          float posy   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_y;
+          float posz   = ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_z;
+          TVector3 * pos         = new TVector3(posx,posy,posz) ;  
+
+          float eta              = pos->PseudoRapidity() ;
+          //float phi              = pos->Phi() ;
+          float eta_correction   = (*truth)[0].TTC_entrance_eta[0];
+          float d_eta            = eta - eta_correction ;
+
+          float myy = ((*truth)[0].TTC_entrance_r[0]) * TMath::Sin((*truth)[0].TTC_entrance_phi[0]);
+          float myx = ((*truth)[0].TTC_entrance_r[0]) * TMath::Cos((*truth)[0].TTC_entrance_phi[0]);
+
+          TVector2 * myv2= new TVector2(myx,myy);
+          TVector2 * myv3= new TVector2(pos->X(),pos->Y());
+          float d_phi = myv3->DeltaPhi(*myv2) ;
+
+          // change in mm 
+          unitsmm(eta,d_eta,d_phi,cellr,cellz);
+
+          float d_r   = TMath::Sqrt(d_phi*d_phi + d_eta*d_eta);
+
+          float alpha = TMath::ATan2(d_phi,d_eta);
+          if(alpha<(TMath::Pi()/8.)) 
+            alpha = 2*TMath::Pi()+alpha ;
+
+          if(testBinning)
+          {
+            cout<<"TESTBIN 3"<<endl;
+            halphadrEvec.at(i)->Fill(alpha,d_r,energy);
+            cout<<"TESTBIN 3 done"<<endl;
+          }
+          halpha.Fill(alpha);
+          float myweight;
+          if(energy>1)
+            myweight = energy;
+          else
+            myweight = 1 ;
+          hr.Fill(d_r,myweight);
+
+          if(fabs(eta)>=etaslice.at(0) && fabs(eta)<=etaslice.at(1)){
+            vMLr.push_back(d_r);
+            vMLalpha.push_back(alpha);
+            vMLE.push_back(energy);
+          }
+          //std::cout << d_r << " " << alpha << " " << energy << std::endl; // GILLES 
+        }// loop on cells
+      }// loop on hits
+    }// end matched ntuple
+
+    if(testBinning && !doNNHit)
+    {
+      cout<<"TESTBIN 4"<<endl;
+      //float MLint = halphadrEvec.at(i)->Integral();
+      if(halphadrEvec.at(i)->Integral()>0){
+        halphadrEvec.at(i)->Scale(1./halphadrEvec.at(i)->Integral());
+      }
+      hEnergy->Add(halphadrEvec.at(i));
+
+      for(unsigned int w=0;w<vMLr.size();w++){
+        ofML << vMLr.at(w) << " " << vMLalpha.at(w) << " " << vMLE.at(w) << std::endl;
+      }
+    }
+  }// loop on events
+
+  cout<<"loop done"<<endl;
+
+  ofML.close();
+
+  if(doNNHit)
+  {
+    hLNEnergy->Divide(hNNHit);
+    hEnergy->Divide(hNNHit);
+  }
+
+  if(testBinning)
+  {
+    TH2F* hAllnorm = (TH2F*) hEnergy->Clone("hAllnorm");
+    hAllnorm->Scale(1./hAllnorm->Integral());
+
+    TFile* f2 = new TFile(outFile.c_str(),"recreate");
+
+    // output variables for NN fit of the shower shape 
+    TTree* T2 = new TTree("NNfit","NNfit");
+    //float   fAlphaBinCenter=0;
+    //float   fRBinCenter=0;
+    //float   fenergyLN=0;
+    //float   fenergydensityLN=0;
+    //TBranch *b0 ;
+    //b0 =T2->Branch("alpha", &fAlphaBinCenter);
+    //TBranch *b1;
+    //b1 =T2->Branch("r", &fRBinCenter);
+    //TBranch *b2;
+    //b2 =T2->Branch("energydensityLN", &fenergydensityLN);
+    //TBranch *b22;
+    //b22 =T2->Branch("energyLN", &fenergyLN);
+
+
+    // output variables for NN fit of E(alpha,r) generation
+    TTree* T3 = new TTree("NNinv","NNinv");
+    //float   fWeight=0;
+    //float   fbina=0;
+    //float   fbinrLN=0;
+    //float   fprobr=0;
+    //float   fprobalpha=0;
+
+    //TBranch *b3;
+    //b3=T3->Branch("probr", &fprobr);
+    //TBranch *b4;
+    //b4=T3->Branch("probalpha", &fprobalpha);
+    //TBranch *b5;
+    //b5=T3->Branch("bina",&fbina);
+    //TBranch *b6;
+    //b6=T3->Branch("binrLN",&fbinrLN);
+    //TBranch *b7;
+    //b7=T3->Branch("Weight",&fWeight);
+
+    // loop on the histogram to fill tree variables & normalize per bin area 
+    // starts on purpose at i=0 for the bin boundary case for probr and proba
+    for(Int_t i=0;i<hEnergy->GetNbinsX()+1;i++){
+
+      float xbinmin = hEnergy->GetXaxis()->GetBinLowEdge(i) ;
+      float xbinmax = hEnergy->GetXaxis()->GetBinUpEdge(i) ;
+
+      // starts on purpse at j=0 for the bin boundary case 
+      for(Int_t j=0;j<hEnergy->GetNbinsY()+1;j++){
+
+        float ybinmax = hEnergy->GetYaxis()->GetBinUpEdge(j);
+        float ybinmin = hEnergy->GetYaxis()->GetBinLowEdge(j);
+
+        float area = TMath::Pi() * (ybinmax*ybinmax - ybinmin*ybinmin) * ((xbinmax - xbinmin)/(2*TMath::Pi())) ;
+
+        if(i>0 && j>0){
+          if(!doNNHit){
+            hEnergyDensity->SetBinContent(i,j,hEnergy->GetBinContent(i,j)/area);
+            //std::cout << "ENERGY DENSITY : " << hEnergy->GetBinContent(i,j)/area << std::endl;
+            hLNEnergyDensity->SetBinContent(i,j,TMath::Log(hEnergyDensity->GetBinContent(i,j)));
+            hLNEnergy->SetBinContent(i,j,TMath::Log(hEnergy->GetBinContent(i,j)));
+            if(hEnergyDensity->GetBinContent(i,j)<tolerance){
+              std::cout << "EMPTY BIN : " << i << " " << j << "  " << hEnergyDensity->GetBinContent(i,j) << std::endl;
+              isEmptyBin = true;
+              return isEmptyBin;
+            }
+            // variables for NN fit 
+            //fAlphaBinCenter          = hEnergyDensity->GetXaxis()->GetBinCenter(i);
+            //fRBinCenter              = hEnergyDensity->GetYaxis()->GetBinCenter(j);
+            //fenergyLN                = TMath::Log(hEnergy->GetBinContent(i,j));
+            //fenergydensityLN         = TMath::Log(hEnergyDensity->GetBinContent(i,j));
+          }
+          if(doNNHit){
+            float toleranceLN = TMath::Log(tolerance);
+            hLNEnergyDensity->SetBinContent(i,j,(TMath::Exp(hLNEnergy->GetBinContent(i,j))/area));
+            if(hLNEnergy->GetBinContent(i,j)<toleranceLN && doNNHit){
+              std::cout << "EMPTY BIN FOR NN HIT : " << i << " " << j << "  " << hLNEnergy->GetBinContent(i,j) << std::endl;
+              isEmptyBin = true;
+              return isEmptyBin;
+            }
+            // variables for NN fit 
+            //fAlphaBinCenter          = hLNEnergy->GetXaxis()->GetBinCenter(i); 
+            //fRBinCenter              = hLNEnergy->GetYaxis()->GetBinCenter(j); 
+            //fenergyLN                = hLNEnergy->GetBinContent(i,j);  
+            //fenergydensityLN         = hLNEnergyDensity->GetBinContent(i,j);
+          }
+          T2->Fill();
+        }
+
+        // variables for NN inv fit - starts at i,j=0 because of using the bin boundaries (not the centres)
+        //fbina = xbinsAlpha[i];
+        //fbinrLN=TMath::Log(ybinsR[j]);
+        //if(j==0) fbinrLN=TMath::Log(ybinsR[1])-1.;
+
+        // r probability calculation
+        //if(j==0) fprobr    = 0 ;
+        //if(j>0)  fprobr    = hAllnorm->Integral(1,hAllnorm->GetNbinsX(),1,j);
+
+        // alpha probability calculation
+        //float totalpha = 0 ; 
+
+        //if(i==0) fprobalpha= 0 ;
+        //if(j==0){
+          //totalpha = hAllnorm->Integral(1,hAllnorm->GetNbinsX(),1,1);
+          //if(i>0) fprobalpha = hAllnorm->Integral(1,i,1,1)/totalpha ;
+        //}
+        //if(i>0 && j>0){
+          //totalpha   = hAllnorm->Integral(1,hAllnorm->GetNbinsX(),j,j);
+          //fprobalpha = hAllnorm->Integral(1,i,j,j)/totalpha ;
+        //}
+
+        // weight 
+        if(j==0) area = 1./15.;
+        else if(j==hAllnorm->GetNbinsY()) area = 1.;
+        //fWeight = area;
+
+        T3->Fill();
+      }
+    }
+
+    TObjArray Hlist(0);
+    Hlist.Add(hEnergyDensity);
+    Hlist.Add(hLNEnergyDensity);
+    Hlist.Add(hEnergy);
+    Hlist.Add(hLNEnergy);
+    hr.Rebin(100);
+    Hlist.Add(&hr);
+    Hlist.Write();
+
+    T2->Write();
+    T2->Reset();
+    T3->Write();
+    T3->Reset();
+    f2->Close();
+
+
+  }//testBinning
+
+  delete(hEnergyDensity);
+  delete(hEnergy);
+  delete(hNNHit);
+  delete(hLNEnergyDensity);
+  delete(hLNEnergy);
+
+  return isEmptyBin; 
+
+} //fill()
+
+
+void DetailedShapeBinning::unitsmm(float eta, float& d_eta, float& d_phi, float cellr, float cellz){
+
+  float phi_dist2r = 1.0 ;
+  float dist000    = TMath::Sqrt(cellr*cellr + cellz*cellz);
+
+  float eta_jakobi = TMath::Abs(2.0*TMath::Exp(-eta)/(1.0+TMath::Exp(-2*eta)));
+  d_eta       = d_eta * eta_jakobi * dist000 ;
+  d_phi       = d_phi * cellr      * phi_dist2r ;
+
+
+}
+
+
+void DetailedShapeBinning::getcellgeom(float layer, float etacentre, float phicentre, float& cellr, float& cellz, float& /*celleta*/, float& cell_deta, float& cell_dphi){
+
+  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 CaloDetDescrElement* cell;
+  cell=geo->getDDE(layer, etacentre, phicentre);
+
+  cellr      = cell->r();
+  cellz      = cell->z();
+  cell_dphi   = cell->dphi();
+  cell_deta   = cell->deta();
+
+}
+
+vector<float> DetailedShapeBinning::fVecBin(TH1F* myh, int nBins, bool doR){
+
+  vector<float> vbin;
+  float PerBinValue    = myh->Integral()/nBins ;
+
+  // first bin boundary
+  if(doR)  vbin.push_back(0) ;
+  else     vbin.push_back(TMath::Pi()/8.);
+
+  float mybincumul = 0 ;
+  for(Int_t g=1;g<myh->GetNbinsX()+1;g++){
+    if(mybincumul<PerBinValue){
+      mybincumul = mybincumul + myh->GetBinContent(g) ;
+    }
+    if(mybincumul>=PerBinValue){
+      vbin.push_back(myh->GetBinLowEdge(g)+myh->GetBinWidth(g)) ;
+      mybincumul = 0 ;
+    }
+  }
+
+  int nRmax = myh->FindLastBinAbove(0);
+  float Rmax= myh->GetBinLowEdge(nRmax)+myh->GetBinWidth(nRmax);
+  //if(doR) std::cout << "Rmax : " << Rmax << std::endl;
+
+  // last bin boundary
+  if(doR) vbin.push_back(Rmax);
+  else    vbin.push_back(2*TMath::Pi()+TMath::Pi()/8.);
+
+  return vbin ;
+}
+
+bool DetailedShapeBinning::checkgradient(string outfile, TH1F& hGradient, string labeloutput, string labeltitle, bool doNNHit){
+
+  TFile* file =TFile::Open(outfile.c_str());
+  TH2F* hist  = (TH2F*)file->Get("hEnergyDensity");
+  if(doNNHit)
+    hist  = (TH2F*)file->Get("hLNEnergy");
+
+  bool isStatFluc = true;
+
+  for(Int_t j=2;j<hist->GetNbinsY();j++){
+
+    float relvar1 = 0 ; 
+    float relvar2 = 0 ; 
+    float errGradient = 0 ; 
+
+    for(Int_t i=1;i<hist->GetNbinsX()+1;i++){
+      if(!doNNHit){
+        relvar1    += (TMath::Log(hist->GetBinContent(i,j))  -TMath::Log(hist->GetBinContent(i,j-1)));///TMath::Log(hist->GetBinContent(i,j-1));
+        relvar2    += (TMath::Log(hist->GetBinContent(i,j+1))-TMath::Log(hist->GetBinContent(i,j)));///TMath::Log(hist->GetBinContent(i,j));
+        errGradient += (TMath::Log(hist->GetBinError(i,j))  -TMath::Log(hist->GetBinError(i,j-1)));
+      }
+      if(doNNHit){
+        relvar1    += (hist->GetBinContent(i,j)-hist->GetBinContent(i,j-1));
+        relvar2    += (hist->GetBinContent(i,j+1)-hist->GetBinContent(i,j));
+        errGradient += (hist->GetBinError(i,j)-hist->GetBinError(i,j-1));
+      }
+    }
+    relvar1 = relvar1/hist->GetNbinsX();
+    relvar2 = relvar2/hist->GetNbinsX(); 
+
+    hGradient.Fill(hist->GetYaxis()->GetBinCenter(j),relvar1);
+    hGradient.SetBinError(j,errGradient);
+
+    // gradient tolerances
+    float gradtol = 0 ; 
+    if(j<int(hist->GetNbinsY()/3.))
+      gradtol = 0.1 ;
+    if(j>=int(hist->GetNbinsY()/3.) && j<2*(int(hist->GetNbinsY()/3.)))
+      gradtol = 0.3 ;
+    if(j>=2*(int(hist->GetNbinsY()/3.)))
+      gradtol = 0.8 ;
+
+    if(fabs(relvar1)>gradtol && fabs(relvar2)>gradtol){
+      isStatFluc = false;
+      std::cout << "GRADIENT PROBLEM (biny,relvar1,relvar2): " << j << " " << relvar1 << "  " << relvar2 << std::endl;
+    }
+  }  
+
+  TCanvas c0("c0","Gradient",10,10,900,800);
+  c0.SetRightMargin(0.13);
+  hGradient.SetMarkerStyle(20);
+  hGradient.GetYaxis()->SetRangeUser(-1,0);
+  hGradient.GetYaxis()->SetTitle("log(#rho_{E}) variation");
+  hGradient.GetXaxis()->SetTitle("r [mm]");
+  hGradient.Draw("P");
+  c0.Update();
+
+  int nzoom1 = int((hGradient.GetNbinsX())/3.*2.)-1;
+  int nzoom2 = int((hGradient.GetNbinsX())/3.)-1;
+
+  std::cout << "ZOOM VALUES : " << nzoom1 << " " << nzoom2 << std::endl;
+
+  float Rzoom2 = hGradient.GetXaxis()->GetBinLowEdge(nzoom2);
+  float Rzoom1 = hGradient.GetXaxis()->GetBinLowEdge(nzoom1);
+  float Rzoom0 = hGradient.GetXaxis()->GetBinLowEdge(hGradient.GetNbinsX()) + hGradient.GetXaxis()->GetBinWidth(hGradient.GetNbinsX());
+
+  TLine lg1p(0,-0.1,Rzoom2,-0.1);
+  lg1p.SetLineWidth(2);
+  lg1p.SetLineColor(kBlue);
+  lg1p.Draw();
+  TLine lg2(Rzoom2,-0.1,Rzoom2,-0.3);
+  lg2.SetLineWidth(2);
+  lg2.SetLineStyle(7);
+  lg2.SetLineColor(kBlue);
+  lg2.Draw();
+  TLine lg2p(Rzoom2,-0.3,Rzoom1,-0.3);
+  lg2p.SetLineWidth(2);
+  lg2p.SetLineColor(kBlue);
+  lg2p.Draw();
+  TLine lg3(Rzoom1,-0.3,Rzoom1,-0.8);
+  lg3.SetLineWidth(2);
+  lg3.SetLineStyle(7);
+  lg3.SetLineColor(kBlue);
+  lg3.Draw();
+  TLine lg3p(Rzoom1,-0.8,Rzoom0,-0.8);
+  lg3p.SetLineWidth(2);
+  lg3p.SetLineColor(kBlue);
+  lg3p.Draw();
+
+  TLatex l;
+  l.DrawLatex(0,0.01,(labeltitle).c_str());
+  TLatex l2;
+  l2.DrawLatex(-1,-1.15,"ATLAS Simulation Preliminary");
+
+  c0.SetLogx();
+  c0.SetRightMargin(0.13);
+  c0.Update();
+  c0.SaveAs(("output/gradient_"+labeloutput+".pdf").c_str());
+
+  return isStatFluc;
+}
+
+bool DetailedShapeBinning::checkgranularity(float cell_deta, float cell_dphi, float cellr, float cellz, float cell_eta,float rgran, Float_t* AlphaBins, int nAlphaBins, float& mincellgran){
+
+  cout << "--- Delta(r) [mm] of 3 first bins : " << rgran << std::endl;
+
+  bool isGoodGranularity = true;
+  unitsmm(cell_eta,cell_deta,cell_dphi,cellr,cellz);
+
+  mincellgran   = TMath::Min(cell_deta,cell_dphi);
+  cout << "--- Cell geometry in mm : " << cell_deta << " " << cell_dphi << std::endl;
+  //double mygranres = -1000 ; 
+
+  std::vector<double> va;
+  for(Int_t i=0;i<nAlphaBins;i++){
+    va.push_back(AlphaBins[i+1]-AlphaBins[i]);
+  }
+
+  double alphaMAX = *std::max_element(va.begin(),va.end());
+  double alphaMIN = *std::min_element(va.begin(),va.end());
+
+  double etaMAX   = TMath::Sqrt( (rgran*rgran)/(1+pow(TMath::Tan(alphaMAX),2)) );
+  double phiMAX   = fabs(etaMAX * TMath::Tan(alphaMAX));
+
+  double etaMIN   = TMath::Sqrt( (rgran*rgran)/(1+pow(TMath::Tan(alphaMIN),2)) );
+  double phiMIN   = fabs(etaMIN * TMath::Tan(alphaMIN));
+
+  double minparamgran = 0 ;
+  if(mincellgran==cell_deta)
+    minparamgran = TMath::Max(etaMIN,etaMAX) ;
+  if(mincellgran==cell_dphi)
+    minparamgran = TMath::Max(phiMIN,phiMAX) ;
+
+  if(mincellgran<minparamgran){
+    isGoodGranularity = false ;
+    //mygranres = minparamgran-mincellgran;
+
+    std::cout << "GRANULARITY PROBLEM " << std::endl;
+    std::cout << "CELL MINIMUM GRANULARITY ETA/PHI: " << cell_deta << "  " << cell_dphi << "  " << mincellgran << std::endl;
+    std::cout << "ETA MIN,MAX FROM PARAM : [" << etaMIN << "," << etaMAX << "]" << std::endl;
+    std::cout << "PHI MIN,MAX FROM PARAM : [" << phiMIN << "," << phiMAX << "]" << std::endl;
+    std::cout << "MAXIMUM VALUE FOR PARAM : " << minparamgran << std::endl;
+  }
+  if(mincellgran>=minparamgran){
+    std::cout << "Granularity OK : " << minparamgran << " < " << mincellgran << std::endl;
+  }
+
+
+  return isGoodGranularity;
+}
+
+void DetailedShapeBinning::fillValidationPlot(float layer,float PCAbin,bool gradientOK, bool granularityOK, string particle, string labeloutput){
+
+  gStyle->SetPalette(1);
+
+  TH2F* htest = new TH2F("htest","htest",10,-0.5,9.5,14,0.5,14.5);
+  htest->GetXaxis()->SetTitle("PCA bin");
+  htest->GetYaxis()->SetTitle("Calorimeter layer");
+
+  if(granularityOK && gradientOK)
+    htest->Fill(PCAbin,layer,1);
+  if(granularityOK && !gradientOK)
+    htest->Fill(PCAbin,layer,2);
+  if(!granularityOK && gradientOK)
+    htest->Fill(PCAbin,layer,3);
+  if(!granularityOK && !gradientOK)
+    htest->Fill(PCAbin,layer,4);
+
+  TCanvas ctest("ctest","dr versus alpha",10,10,900,800);
+  htest->Draw("COLZ");
+
+  TLatex l;
+  l.SetTextSize(0.03);
+  l.DrawLatex(-2,-1,"1= all OK ; 2= bad gradient ; 3= bad granularity");
+  l.DrawLatex(-2,-2,"4= bad gradient & granularity");
+  TLatex l2;
+  string sparticle="";
+  if(particle=="pi")
+    sparticle="50 GeV pions";
+  if(particle=="e")
+    sparticle="50 GeV electrons";
+  if(particle=="gamma")
+    sparticle="50 GeV photons";
+  l2.DrawLatex(0,14.5,sparticle.c_str());
+
+  ctest.SetRightMargin(0.13);
+  ctest.Update();
+  ctest.SaveAs(("output/validation_"+labeloutput+".pdf").c_str());
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e088e3e3523b0decc004fb07e338a5cec8c54f3b
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/EnergyParametrizationValidation.cxx
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TH1D.h"
+#include "TFile.h"
+#include "TROOT.h"
+#include "TSystem.h"
+#include "TApplication.h"
+#include "TTree.h"
+#include "TSystem.h"
+#include "TMath.h"
+#include "ISF_FastCaloSimParametrization/EnergyParametrizationValidation.h"
+
+#include <iostream>
+
+using namespace std;
+
+void EnergyParametrizationValidation::autozoom(TH1D* h1, TH1D* /*h2*/, 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)
+  {
+   min1=h1->GetBinCenter(b);
+   break;
+  }
+ }
+ for(int b=h1->GetNbinsX();b>=1;b--)
+ {
+  if(h1->GetBinContent(b)>0)
+  {
+   max1=h1->GetBinCenter(b);
+   break;
+  }
+ }
+ 
+ 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);
+ 
+}
+
+TH1D* EnergyParametrizationValidation::refill(TH1D* h_in,double min, double max, double rmin, double rmax)
+{
+ 
+ //int debug=0;
+ 
+ int Nbins;
+ int bins=0;
+ for(int b=h_in->FindBin(min);b<=h_in->FindBin(max);b++)
+  bins++;
+ 
+ if(bins<=120)
+ {
+ 	//no rebinning
+ 	Nbins=bins;
+ }
+ else
+ {
+ 	int tries=0;
+ 	int rebin=2;
+  
+ 	while(tries<1000)
+ 	{
+ 	 if((10000%rebin)==0)
+ 	 {
+ 	 	TH1D* h_clone=(TH1D*)h_in->Clone("h_clone");
+ 	  h_clone->Rebin(rebin);
+ 	  Nbins=0;
+ 	  for(int b=h_clone->FindBin(min);b<=h_clone->FindBin(max);b++)
+     Nbins++;
+    if(Nbins<120 && Nbins>50)
+    {
+     h_in->Rebin(rebin);
+     cout<<"*decide for rebin="<<rebin<<"*"<<endl;
+     break;
+    }
+   }
+   rebin++;
+   tries++;
+  }
+  if(tries>=1000)
+  {
+   cout<<" ********** GIVE UP ********** "<<endl;
+ 	 h_in->Rebin((double)bins/100.0);
+ 	 Nbins=0;
+ 	 for(int b=h_in->FindBin(min);b<=h_in->FindBin(max);b++)
+    Nbins++;
+  }
+ }
+ 
+ //if(debug) cout<<"---> NBINS "<<Nbins<<endl;
+
+ int start=h_in->FindBin(min)-1;
+ 
+ //if(debug) cout<<"AFTER rebin ->underflow "<<h_in->GetBinContent(0)<<" startbin "<<start<<" minimum "<<min<<endl;
+ 
+ TH1D* h_out=new TH1D("h_out","h_out",Nbins,rmin,rmax);
+ for(int b=1;b<=h_out->GetNbinsX();b++)
+ {
+ 	h_out->SetBinContent(b,h_in->GetBinContent(start+b));
+ 	h_out->SetBinError(b,h_in->GetBinError(start+b));
+ }
+
+ //if(debug) cout<<"AFTER refill ->underflow "<<h_out->GetBinContent(0)<<" startbin "<<start<<" minimum "<<min<<endl;
+
+ return h_out;
+ 
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/FitDetailedShape.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/FitDetailedShape.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2c9010289e3568034197a99d1b254eb0d87f7e20
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/FitDetailedShape.cxx
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TMatrixF.h"
+#include "TMatrixD.h"
+#include "TMatrixDSym.h"
+#include "TMatrixDSymEigen.h"
+#include "TVectorF.h"
+#include "TH1D.h"
+#include "TFile.h"
+#include "TROOT.h"
+#include "TSystem.h"
+#include "TApplication.h"
+#include "TTree.h"
+#include "TSystem.h"
+#include "TH2D.h"
+#include "TPrincipal.h"
+#include "TMath.h"
+#include "TBrowser.h"
+#include "ISF_FastCaloSimParametrization/FitDetailedShape.h"
+#include "ISF_FastCaloSimParametrization/TFCS2Function.h"
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+FitDetailedShape::FitDetailedShape()
+{
+ 
+}
+
+void FitDetailedShape::run(string inputfile, int /*verbose_level*/, string /*thisname*/, string /*labelout*/, int /*mycase*/, float /*calosize*/, bool /*doNNHit*/)
+{
+ 
+ //Open inputfile:
+ cout<<endl;
+ cout<<"****************"<<endl;
+ cout<<" Fit detailed shape "<<endl;
+ cout<<"****************"<<endl;
+ cout<<endl;
+ cout<<"--- Open input file "<<inputfile<<endl;
+ TFile* file=TFile::Open(inputfile.c_str());
+ if(!file) cout<<"ERROR: Inputfile could not be opened"<<endl;
+  
+ //TFCS2DFunction* fct=TFCS2Function::Create(inputfile,verbose_level,thisname,labelout, mycase, calosize,doNNHit);
+ 
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2298acdeb1092567af4e6b0e3d194a7184f22b62
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/IntArray.cxx
@@ -0,0 +1,4 @@
+/*
+  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 1115e8cfba6668a454bf939a1ba1a4d5c047f00c..634915782fe0d266888a99ecc198905356872f50 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/LinkDef.h
@@ -3,25 +3,28 @@
 */
 
 #ifdef __CINT__
-//#pragma link C++ class CaloSampling+;
-#pragma link C++ class TFCSExtrapolationState+;
-#pragma link C++ class TFCSTruthState+;
-#pragma link C++ class TFCSSimulationState+;
-#pragma link C++ class TFCSParametrizationBase+;
-#pragma link C++ class TFCSParametrization+;
-#pragma link C++ class TFCSEnergyParametrization+;
-#pragma link C++ class TFCSPCAEnergyParametrization+;
 #pragma link C++ class TFCSLateralShapeParametrization+;
 #pragma link C++ class TFCSNNLateralShapeParametrization+;
 #pragma link C++ class TFCSSimpleLateralShapeParametrization+;
 #pragma link C++ class MeanAndRMS;
-#pragma link C++ class TFCS1DFunction;
 #pragma link C++ class TFCS1DFunctionRegression;
 #pragma link C++ class TFCS1DFunctionHistogram;
 #pragma link C++ class TFCSFunction;
 #pragma link C++ class TreeReader;
 #pragma link C++ class firstPCA;
 #pragma link C++ class secondPCA;
-
+#pragma link C++ class DetailedShowerShape;
+#pragma link C++ class TFCS2DFunction;
+#pragma link C++ class TFCS2Function;
+#pragma link C++ class FitDetailedShape;
+#pragma link C++ class TFCS2DFunctionRegression;
+#pragma link C++ class TFCS1DFunctionRegressionTF;
+#pragma link C++ class DetailedShapeBinning;
+#pragma link C++ class EnergyParametrizationValidation;
+#ifndef CaloGeometryFromFile_h
+#pragma link C++ class CaloGeometryLookup;
+#pragma link C++ class CaloGeometry;
+#pragma link C++ class ICaloGeometry;
+#endif
 #endif
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunction.cxx
deleted file mode 100644
index 57d0f2977a84e4d43cd207682ec4fcff8aee9cf7..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunction.cxx
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
-
-#include "TMVA/Config.h"
-#include "TMVA/Tools.h"
-#include "TMVA/Reader.h"
-#include "TMVA/Factory.h"
-#include "TFile.h"
-
-
-//=============================================
-//======= TFCS1DFunction =========
-//=============================================
-
-TFCS1DFunction::TFCS1DFunction()
-{
-}
-
-TFCS1DFunction::TFCS1DFunction(TH1* hist)
-{
-  Initialize(hist);
-}
-
-void TFCS1DFunction::Initialize(TH1* /*hist*/)
-{
-}
-
-int TFCS1DFunction::testHisto(TH1* hist)
-{
-  
-  //int debug=1;
- 
- //transform the histogram
- TH1* h_transf=transform(hist); h_transf->SetName("h_transf");
- 
- //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);
- 
- std::string weightfilename="testweights";
- TRandom* myRandom=new TRandom3(); myRandom->SetSeed(0);
- int Ntoys=10000;
- 
- int do_iteration=1;
- int do_range=1;
- double maxdev=100;
- int neurons=2;
- 
- double maxdev_cut=5;
- 
- while(maxdev>maxdev_cut && neurons<11)
- {
- 	
-  tmvaregression_training(neurons, tree, weightfilename);
-  
-  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 =tmvaregression_application(random,weightfilename);
- 	 h_output->Fill(value); 	 
-  }
-  
-  TH1* h_cumul=get_cumul(h_output);
-  
-  maxdev=get_maxdev(h_transf,h_cumul);
-  std::cout<<"---> Neurons="<<neurons<<" MAXDEV="<<maxdev<<"%"<<std::endl;
-  neurons++;
-  if(!do_iteration) break;
- }
- 
- int regression_success=1;
- if(maxdev>maxdev_cut) regression_success=0;
- 
- 
- int status=0;
- if(regression_success)
- {
-     std::cout<<"Regression successful. Weights are stored."<<std::endl;
-     status=1;
- }
-	
- 
- if(!regression_success)
- {
-     std::cout<<"Regression failed. Histogram is stored."<<std::endl;
-     status=2;
- } //!success
- 
- return status;
- 
-}
-
-double TFCS1DFunction::rnd_to_fct(double /*rnd*/)
-{
-  return 0;
-}
-
-
-double TFCS1DFunction::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;
-}
-
-void TFCS1DFunction::tmvaregression_training(int neurons, TTree *regTree, 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;
- 
- 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;
-  }
- }
- 
- TString outfileName("TMVAReg.root");
- TFile* outputFile = TFile::Open( outfileName, "RECREATE" );
- TMVA::Factory *factory = new TMVA::Factory( "TMVARegression", outputFile, "!V:!Silent:Color:DrawProgressBar" );
- TString dirname=Form("%s/",weightfile.c_str());
- (TMVA::gConfig().GetIONames()).fWeightFileDir = dirname;
- factory->AddVariable( "y", "y", 'F' );
- factory->AddTarget( "x" );
- //TFile *input(0);
- Double_t regWeight  = 1.0;   
- 
- factory->AddRegressionTree( regTree, regWeight );
- TCut mycut = "";
- factory->PrepareTrainingAndTestTree( mycut,"nTrain_Regression=0:nTest_Regression=0:SplitMode=Random:NormMode=NumEvents:!V" );
- 
- if(Use["MLP"])
-  //factory->BookMethod( TMVA::Types::kMLP, "MLP", Form("!H:!V:VarTransform=Norm:NeuronType=tanh:NCycles=20000:HiddenLayers=%i:TestRate=6:TrainingMethod=BFGS:Sampling=0.3:SamplingEpoch=0.8:ConvergenceImprove=1e-6:ConvergenceTests=15:!UseRegulator",neurons) );
-  factory->BookMethod( TMVA::Types::kMLP, "MLP", Form("!H:!V:NeuronType=tanh: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;  
- 
-}
-
-
-TH1* TFCS1DFunction::transform(TH1* h_input)
-{
- 
- bool do_transform=false;
- double xmin=h_input->GetXaxis()->GetXmin();
- double xmax=h_input->GetXaxis()->GetXmax();
- if(xmin<0 || xmax>1) do_transform=true;
- 
- TH1D* h_out = nullptr;
- 
- 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));
- }
- if(!do_transform)
- {
- 	h_out=(TH1D*)h_input->Clone("h_out");
- }
- return h_out;
- 
-}
-
-
-double TFCS1DFunction::get_maxdev(TH1* h_input, TH1* h_approx)
-{
- double maxdev=0.0;
- 
- //normalize the histos to the same area:
- //be careful when binning is different!!!!!
- double integral_input=h_input->Integral();
- double integral_approx=0.0;
- for(int b=1;b<=h_input->GetNbinsX();b++)
- {
- 	integral_approx+=h_approx->GetBinContent(h_approx->FindBin(h_input->GetBinCenter(b)));
- }
- h_approx->Scale(integral_input/integral_approx);
-  
- double ymax=h_approx->GetBinContent(h_approx->GetNbinsX());
- for(int i=1;i<=h_input->GetNbinsX();i++)
- {
-  double val=fabs(h_approx->GetBinContent(h_approx->FindBin(h_input->GetBinCenter(i)))-h_input->GetBinContent(i))/ymax;
-  if(val>maxdev) maxdev=val;
- }
- return maxdev*100.0;
- 
-}
-
-
-double TFCS1DFunction::tmvaregression_application(double uniform, std::string weightfile)
-{
- 
- using namespace TMVA;
- 
- 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;
-    return 0;
-   }
-   Use[regMethod] = 1;
-  }
- }
- 
- // --------------------------------------------------------------------------------------------------
- 
- TMVA::Reader *reader = new TMVA::Reader( "!Color:Silent");    
- 
- Float_t y=uniform;
- reader->AddVariable( "y", &y );
- 
- TString dir    = Form("%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 weightfile = dir + prefix + "_" + TString(it->first) + ".weights.xml";
-   reader->BookMVA( methodName, weightfile ); 
-  }
- }
- 
- Float_t val = (reader->EvaluateRegression("MLP method"))[0];
- delete reader;
- return val;
- 
-}
-
-
-TH1* TFCS1DFunction::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; 
-}
-
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCS1DFunction)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx
index 8280a944cf5f95795f1ef41c74bed5fa4cf3ce70..e7eac1231f69bba27674cffb24f4af52574b5862 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionHistogram.cxx
@@ -2,12 +2,11 @@
   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>
 
-using namespace std;
-
 //=============================================
 //======= TFCSFunctionRegression =========
 //=============================================
@@ -16,180 +15,349 @@ TFCS1DFunctionHistogram::TFCS1DFunctionHistogram()
 {
 }
 
-TFCS1DFunctionHistogram::TFCS1DFunctionHistogram(TH1* hist)
+TFCS1DFunctionHistogram::TFCS1DFunctionHistogram(TH1* hist, int verbose, double cut_maxdev)
 {
-  Initialize(hist);
+  Initialize(hist, verbose,cut_maxdev);
 }
 
-void TFCS1DFunctionHistogram::Initialize(TH1* hist)
+void TFCS1DFunctionHistogram::Initialize(TH1* hist, int verbose,double cut_maxdev)
 {
-	
- //smart rebinning
-	
- int do_histo_iteration=1;
- double maxdev=100;
- int iter=0; //0
- while(maxdev>5 && do_histo_iteration && iter<=10)
- {
-  smart_rebinning(hist,1.0-iter*0.1);
-  TH1* h_rebinned=vector_to_histo();
-  maxdev=get_maxdev(hist,h_rebinned);
-  delete h_rebinned;
-  cout<<"Histo Iteration "<<iter<<" maxdev "<<maxdev<<endl;
-  iter++;
- }
-  
- //m_histo=(TH1*)hist->Clone("m_histo");
-  
+
+  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();
-  */
-  
-}
+     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);
- }
- return histoVals;
- 
+
+  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);
- 
- return value;
- 
+
+  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;
+  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;
- 
+
+  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());
+
 }
 
-void TFCS1DFunctionHistogram::smart_rebinning(TH1* hist, double change /*in percent*/ )
+TH1D* TFCS1DFunctionHistogram::smart_rebin(TH1D* h_input, double change)
 {
- 
- int debug=0;
- 
- //do the rebin and save the bins in a vector
- vector<double> content;
- vector<double> binborder;
- 
- binborder.push_back(hist->GetXaxis()->GetXmin());
- 
- change=change/100.0;
- double sum=0;
- int count=0;
- for(int b=1;b<hist->GetNbinsX();b++)
- {
-  double thisBin=hist->GetBinContent(b);
-  double nextBin=hist->GetBinContent(b+1);
-  if(debug) cout<<"b "<<b<<" begin, thisBin "<<thisBin<<" nextBin "<<nextBin<<" sum "<<sum<<endl;
-  if(fabs(nextBin/thisBin-1.0)>=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++)
   {
-   sum+=thisBin;
-   count++;
- 	 binborder.push_back(hist->GetBinCenter(b)+0.5*hist->GetBinWidth(b));
- 	 //divide the sum by the number of summed bins:
- 	 content.push_back(sum/(double)count);
-   //Reset the sum:
-   sum=0;
-   count=0;
+    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++;
+    }
   }
-  if(fabs(nextBin/thisBin-1.0)<change)
+  //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:
   {
-   //do not add this bin to the new vector of bins, but add to the sum
-   sum+=thisBin;
-   count++;
+    content.push_back(h_input->GetBinContent(h_input->GetNbinsX()));
   }
- }
- //last bin is special:
- binborder.push_back(hist->GetXaxis()->GetXmax());
- if(count==0) //that means the previous-to-last bin was written out, so simpy add the last one:
- {
-  content.push_back(hist->GetBinContent(hist->GetNbinsX()));
- }
- if(count>0)
- {
- 	sum+=hist->GetBinContent(hist->GetNbinsX());
- 	count++;
- 	content.push_back(sum/(double)count);
- }
- 
- //safe into the member variables:
- 
- m_HistoContents.clear();
- m_HistoBorders.clear();
- 
- for(unsigned int i=0;i<content.size();i++)
-  m_HistoContents.push_back((float)content[i]);
- for(unsigned int i=0;i<binborder.size();i++)
-  m_HistoBorders.push_back((float)binborder[i]);
- 
-}
+  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 value=sample_from_histovalues(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 ===========
 //=============================================
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx
index 9d52458fe5153056e972c2c9692d426963cc0c94..3d477f8e7448758f33699c7318388216efedd34e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegression.cxx
@@ -2,6 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
+using namespace std;
 #include "ISF_FastCaloSimParametrization/TFCS1DFunctionRegression.h"
 
 #include "TMVA/Config.h"
@@ -11,26 +12,16 @@
 #include "TRandom3.h"
 #include "TFile.h"
 #include "TString.h"
+#include "TMath.h"
+
 #include "TMVA/IMethod.h"
 #include "TMVA/MethodMLP.h"
-#include "TMath.h"
 
 
 //=============================================
 //======= TFCS1DFunctionRegression =========
 //=============================================
 
-using namespace std;
-
-namespace {
-class MethodMLPNetworkGetter
-  : public TMVA::MethodMLP
-{
-public:
-  using TMVA::MethodMLP::fNetwork;
-};
-}
-
 TFCS1DFunctionRegression::TFCS1DFunctionRegression()
 {
 }
@@ -38,25 +29,17 @@ TFCS1DFunctionRegression::TFCS1DFunctionRegression()
 TFCS1DFunctionRegression::TFCS1DFunctionRegression(TH1* hist)
 {
 	
-	cout<<"IN TFCS1DFunctionRegression"<<endl;
   Initialize(hist);
   
 }
 
-TFCS1DFunctionRegression::TFCS1DFunctionRegression(string weightfilename)
-{
-	
-	cout<<"IN TFCS1DFunctionRegression"<<endl;
-  Initialize(weightfilename);
-  
-}
 
 void TFCS1DFunctionRegression::Initialize(TH1* /*hist*/)
 {
  //not needed
 }
 
-void TFCS1DFunctionRegression::Initialize(string weightfilename)
+void TFCS1DFunctionRegression::storeRegression(string weightfilename)
 {
   
 	get_weights(weightfilename);
@@ -73,7 +56,8 @@ 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<<"Validating the regression value:"<<endl;
+ cout<<endl;
+ cout<<"--- Validating the regression value:"<<endl;
  for(int i=0;i<Ntoys;i++)
  {
   double random=myRandom->Uniform(1);
@@ -83,10 +67,11 @@ void TFCS1DFunctionRegression::validate(int Ntoys,string weightfilename)
 }
 
 
+void TFCS1DFunctionRegression::get_weights(string /*weightfile*/)
+{
 
+/*
 
-void TFCS1DFunctionRegression::get_weights(string weightfile)
-{
  using namespace TMVA;
  int debug=1;
  
@@ -142,13 +127,12 @@ void TFCS1DFunctionRegression::get_weights(string weightfile)
  
  TMVA::IMethod* m=reader->FindMVA("MLP method");
  TMVA::MethodMLP *mlp = dynamic_cast<TMVA::MethodMLP*>(m);
- TObjArray* Network=reinterpret_cast<MethodMLPNetworkGetter*>(mlp)->fNetwork;
- 
+ 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();
- if(fLayers!=3) cout<<"!!!!!!!!!! fLayers is not 3 !!!!!!!!!"<<endl;
  
  for(int a=0;a<((TObjArray*)Network->At(1))->GetEntriesFast();a++)
  {
@@ -171,11 +155,11 @@ void TFCS1DFunctionRegression::get_weights(string weightfile)
  Int_t numNeurons = curLayer->GetEntriesFast();
  for (Int_t n = 0; n < numNeurons; n++)
  {  
-  TNeuron* neuron = (TNeuron*)curLayer->At(n);
+  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
   int numSynapses = neuron->NumPostLinks();
   for (int s = 0; s < numSynapses; s++)
   {
-   TSynapse* synapse = neuron->PostLinkAt(s);  
+   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
    m_fWeightMatrix0to1[s][n]=synapse->GetWeight();
    if(debug) cout<<"fWeightMatrix0to1["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
   }
@@ -185,17 +169,19 @@ void TFCS1DFunctionRegression::get_weights(string weightfile)
  numNeurons = curLayer->GetEntriesFast();
  for (Int_t n = 0; n < numNeurons; n++)
  {  
-  TNeuron* neuron = (TNeuron*)curLayer->At(n);
+  TMVA::TNeuron* neuron = (TMVA::TNeuron*)curLayer->At(n);
   int numSynapses = neuron->NumPostLinks();
   for (int s = 0; s < numSynapses; s++)
   {
-   TSynapse* synapse = neuron->PostLinkAt(s);  
+   TMVA::TSynapse* synapse = neuron->PostLinkAt(s);  
    m_fWeightMatrix1to2[s][n]=synapse->GetWeight();
    if(debug) cout<<"fWeightMatrix1to2["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
   }
  }
  
  delete reader;
+
+*/
  
 }
 
@@ -264,6 +250,7 @@ double TFCS1DFunctionRegression::rnd_to_fct(double rnd)
   
 }
 
+
 //=============================================
 //========== ROOT persistency stuff ===========
 //=============================================
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9636c85a5d61fa61797587c3dee0b049a170e4cb
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS1DFunctionRegressionTF.cxx
@@ -0,0 +1,56 @@
+/*
+  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/TFCS2DFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2710b48023ee6de745ee00d03086269ff4b61d09
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunction.cxx
@@ -0,0 +1,637 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+
+#include "TMVA/Config.h"
+#include "TMVA/Tools.h"
+#include "TMVA/Reader.h"
+#include "TMVA/Factory.h"
+#include "TFile.h"
+#include "TH2.h"
+#include "TMVA/DataLoader.h"
+
+#include "TRandom1.h"
+#include "TRandom.h"
+#include "TRandom3.h"
+#include "TCanvas.h"
+#include "TStyle.h"
+#include "TColor.h"
+#include "TLatex.h"
+#include "TMath.h"
+
+using namespace std;
+
+//=============================================
+//======= TFCS2DFunction =========
+//=============================================
+
+TFCS2DFunction::TFCS2DFunction()
+{
+}
+
+TFCS2DFunction::TFCS2DFunction(string inputfile)
+{
+  Initialize(inputfile);
+}
+
+void TFCS2DFunction::Initialize(string /*inputfile*/)
+{
+}
+
+int TFCS2DFunction::fitShape(string inputfile, string weightfilename, string outfilename, string labeltitle, string labeloutput, int mycase, float calosize, bool doNNHit)
+{
+
+  //int debug=1;
+  
+  TRandom1* myRandom =new TRandom1(); myRandom->SetSeed(0);
+  TRandom1* myRandom2=new TRandom1(); myRandom2->SetSeed(1000);
+  int Ntoys1=50000;
+  int Ntoys2=50000;
+
+ //int do_iteration = 1;
+ //int do_range     = 1;
+ //double maxdev    = 100;
+ int neurons      = 4;
+ 
+ //double maxdev_cut=5; //5!!
+  	
+ tmvaregression_training(neurons,inputfile, weightfilename, outfilename, mycase,doNNHit);
+
+ TFile* file=TFile::Open(inputfile.c_str());
+ if(file) cout << "opening : " << inputfile << std::endl;
+ if(!file) {
+   cout<<"ERROR: Inputfile could not be opened; exiting."<<endl;
+   return -1;
+ }
+ string sh = "";
+ if(mycase==1 && !doNNHit) sh = "hLNEnergyDensity";
+ if(mycase==1 && doNNHit)  sh = "hLNEnergy";
+ if(mycase==2) sh = "hEnergy";
+ TH2F* histo = (TH2F*)file->Get(sh.c_str());
+ std::cout << "TEMP : " << histo->GetNbinsX() << std::endl;
+
+ // Test regression at bin centres 
+ if(mycase==1){
+
+   // Test at the centres
+   cout << "Testing the regression at the bin centres" << std::endl;
+   TH2F* h_output=(TH2F*)histo->Clone("h_output");
+   h_output->Reset();
+   
+   for(int i=1;i<histo->GetNbinsX()+1;i++){
+     double alpha = histo->GetXaxis()->GetBinCenter(i);
+     for(int j=1;j<histo->GetNbinsY()+1;j++){
+       double r = histo->GetYaxis()->GetBinCenter(j);
+       // boundaries for zooms
+       std::vector<float> value = tmvaregression_application(alpha,r,weightfilename,mycase);
+       h_output->SetBinContent(i,j,value.at(0));
+     }
+   }
+   plotpolar(histo,h_output,labeltitle,labeloutput,"bincentre",mycase,calosize,doNNHit);
+   
+   // Test with random numbers 
+   
+   cout << "Testing the regression with " << Ntoys1 << " toys" << endl;
+   TH2F* h_output2=(TH2F*)histo->Clone("h_output2");
+   h_output2->Reset();
+   TH2F* h_norm=(TH2F*)histo->Clone("h_norm");
+   h_norm->Reset();
+
+
+   // file containing the events simulated by the NN fit result!
+   if(doNNHit){
+     string outFile = "output/NNHit_"+labeloutput+".root";
+     TFile* fsim = new TFile(outFile.c_str(),"recreate");
+     TTree* Tsim = new TTree("NNSimHit","NNSimHit");
+     float   fNNHitAlpha=0;
+     float   fNNHitR=0;
+     float   fNNHitLNEfrac=0;
+     //TBranch *b0 ;
+     //b0 =Tsim->Branch("NNHitAlpha", &fNNHitAlpha);
+     //TBranch *b1;
+     //b1 =Tsim->Branch("NNHitR", &fNNHitR);
+     //TBranch *b2;
+     //b2 =Tsim->Branch("NNHitLNEfrac", &fNNHitLNEfrac);
+     
+     gRandom = new TRandom3(0);
+     TH1F* hrRandom = (TH1F*)file->Get("hr");
+     if(!hrRandom) std::cout << "there is a problem with loading the histo" << std::endl;
+     hrRandom->Rebin(10);
+     
+     for(int i=0;i<Ntoys1;i++){
+       fNNHitAlpha  = TMath::Pi()/8.+ 2*myRandom->Uniform(0,1)*TMath::Pi();
+       //fNNHitR      = histo->GetYaxis()->GetBinLowEdge(1)
+       //+myRandom2->Uniform(0,1)*(histo->GetYaxis()->GetBinLowEdge(histo->GetNbinsY())+histo->GetYaxis()->GetBinWidth(histo->GetNbinsY())
+       //				 -histo->GetYaxis()->GetBinLowEdge(0));
+       fNNHitR = hrRandom->GetRandom();
+       std::vector<float> value   = tmvaregression_application(fNNHitAlpha,fNNHitR,weightfilename,mycase);
+       fNNHitLNEfrac=value.at(0);
+       h_output2->Fill(fNNHitAlpha,fNNHitR,fNNHitLNEfrac);
+       h_norm->Fill(fNNHitAlpha,fNNHitR,1.);
+       Tsim->Fill();
+     }
+     h_output2->Divide(h_norm);
+     plotpolar(histo,h_output2,labeltitle,labeloutput,"random",mycase,calosize,doNNHit);
+     Tsim->Write();
+     Tsim->Reset();
+     fsim->Close();
+   }
+ }
+
+ // Test regression with random numbers
+ if(mycase==2){
+   cout<<"Testing the regression with "<<Ntoys2<<" toys"<<endl;
+
+   // Need to define a histogram with LN(r) boundaries first 
+   int nalpha = histo->GetNbinsX()+1;
+   int nr     = histo->GetNbinsY()+1;
+   Float_t valpha[nalpha];
+   Float_t vLNr[nr];
+   
+   for(Int_t i=1;i<nalpha;i++){
+     valpha[i-1] = histo->GetXaxis()->GetBinLowEdge(i);
+     if(i==nalpha-1)
+       valpha[i] = histo->GetXaxis()->GetBinLowEdge(i)+histo->GetXaxis()->GetBinWidth(i);
+   }
+   for(Int_t j=1;j<nr;j++){
+     vLNr[j-1] = TMath::Log(histo->GetYaxis()->GetBinLowEdge(j));
+     if(j==1)
+       vLNr[j-1] = TMath::Log(histo->GetYaxis()->GetBinLowEdge(2))-1.; 
+     if(j==nr-1)
+       vLNr[j] = TMath::Log(histo->GetYaxis()->GetBinLowEdge(j)+histo->GetYaxis()->GetBinWidth(j));
+   }
+   TH2F* h_output2=new TH2F("h_output2","h_output2",nalpha-1,valpha,nr-1,vLNr);
+
+   for(int i=0;i<Ntoys2;i++)
+     {
+       double random  = myRandom->Uniform(0,1);
+       double random2 = myRandom2->Uniform(0,1);
+       
+       std::vector<float> value   = tmvaregression_application(random,random2,weightfilename,mycase); 
+       h_output2->Fill(value.at(0),value.at(1)); 	 
+     }
+   // Change back LN(r)->r for plotting
+   TH2F* h_output3=(TH2F*)histo->Clone("h_output3");
+   h_output3->Reset();
+   for(Int_t j=1;j<h_output2->GetNbinsX()+1;j++){
+     for(Int_t i=1;i<h_output2->GetNbinsY()+1;i++){
+       h_output3->SetBinContent(j,i,h_output2->GetBinContent(j,i));
+       h_output3->SetBinError(j,i,h_output2->GetBinError(j,i));
+     }
+   }
+   plotpolar(histo,h_output3,labeltitle,labeloutput,"random",mycase,calosize,doNNHit);
+ }//end mycase==2
+
+ //int regression_success=1;
+ //if(maxdev>maxdev_cut) regression_success=0;
+
+ int status=0;
+ /*if(regression_success)
+   {
+     cout<<"Regression successful. Weights are stored."<<endl;
+     status=1;
+   }
+ if(!regression_success)
+   {
+     cout<<"Regression failed. Histogram is stored."<<endl;
+     status=3;
+   } //!success*/
+ return status;
+ 
+}
+
+void TFCS2DFunction::tmvaregression_training(int neurons, string inputfile, string weightfile, string outfilename, int mycase, bool doNNHit)
+{
+ using namespace TMVA;
+
+ TFile* file=TFile::Open(inputfile.c_str());
+ if(!file) {
+   cout<<"ERROR: Inputfile could not be opened; exiting."<<endl;
+   return;
+ }
+ string stree = "";
+ if(mycase==1) 
+   stree = "NNfit";
+ if(mycase==2) 
+   stree = "NNinv";
+
+ TTree* regTree = (TTree*)file->Get(stree.c_str());
+
+ 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;
+  }
+ }
+ 
+// TString outfileName("TMVAReg.root");
+ TFile* outputFile = TFile::Open( outfilename.c_str(), "RECREATE" );
+ TMVA::Factory *factory = new TMVA::Factory( "TMVARegression", outputFile, "!V:!Silent:Color:DrawProgressBar" );
+ 	
+ TMVA::DataLoader *dl=new TMVA::DataLoader("dl");
+ 	
+ TString dirname=Form("%s/",weightfile.c_str());
+
+ if(Use["MLP"])
+  factory->BookMethod(dl, TMVA::Types::kMLP, "MLP", Form("!H:!V:VarTransform=Norm:NeuronType=tanh:NCycles=20000:HiddenLayers=%i:TestRate=6:TrainingMethod=BFGS:Sampling=0.3:SamplingEpoch=0.8:ConvergenceImprove=1e-6:ConvergenceTests=15:!UseRegulator",neurons) ); 
+
+ (TMVA::gConfig().GetIONames()).fWeightFileDir = dirname;
+ if(mycase==1)
+ {
+  dl->AddVariable("alpha","alpha",'F');
+  dl->AddVariable("r","r",'F');
+  if(!doNNHit)
+   dl->AddTarget("energydensityLN");
+  if(doNNHit)
+  dl->AddTarget("energyLN");
+ }
+ if(mycase==2)
+ {
+  dl->AddVariable("probalpha","probalpha",'F');
+  dl->AddVariable("probr","probr",'F');
+  dl->AddTarget("bina");
+  dl->AddTarget("binrLN");
+ }
+
+ dl->AddSignalTree( regTree, 1.0, "Training" );
+ dl->AddSignalTree( regTree, 1.0, "Test" );
+
+ // 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;  
+ 
+}
+
+
+vector<float> TFCS2DFunction::tmvaregression_application(Float_t x, Float_t y, string weightfile, int mycase)
+{
+ 
+ using namespace TMVA;
+
+ vector<float> vval ;
+ 
+ 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;
+    return vval;
+   }
+   Use[regMethod] = 1;
+  }
+ }
+ 
+ // --------------------------------------------------------------------------------------------------
+ 
+ TMVA::Reader *reader = new TMVA::Reader( "!Color:Silent");    
+ 
+
+ //Float_t r=uniform;
+ Float_t r = y; 
+ Float_t alpha = x ; 
+ Float_t probr = y ; 
+ Float_t probalpha = x ; 
+
+ if(mycase==1){
+   reader->AddVariable( "alpha", &alpha );
+   reader->AddVariable( "r", &r );
+ }
+ if(mycase==2){
+   reader->AddVariable( "probalpha", &probalpha );
+   reader->AddVariable( "probr", &probr );
+ }
+
+ TString dir    = Form("%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 weightfile2 = dir + prefix + "_" + TString(it->first) + ".weights.xml";
+   reader->BookMVA( methodName, weightfile2 ); 
+  }
+ }
+ 
+ Float_t val  = (reader->EvaluateRegression("MLP method"))[0];
+ Float_t val2 = 0 ; 
+ if(mycase==2) 
+   val2 = (reader->EvaluateRegression("MLP method"))[1];
+
+ vval.push_back(val);
+ if(mycase==2)
+   vval.push_back(val2);
+
+ delete reader;
+ return vval;
+ 
+}
+
+void TFCS2DFunction::plotpolar(TH2F* href, TH2F* hout, string labeltitle, string labeloutput, string method, int mycase, float calosize, bool doNNHit){
+
+  gStyle->SetOptStat(0);
+  
+  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);
+
+  // LOOP ON THE 3 ZOOMS
+  for(int i=1;i<4;i++){
+
+    float zoom = 1000 ; 
+    string szoom = "";
+
+    if(i==1){
+      zoom  = href->GetYaxis()->GetBinLowEdge(href->GetNbinsY())+href->GetYaxis()->GetBinWidth(href->GetNbinsY()); 
+      szoom = "zoom0";
+    }
+    if(i==2){
+      int nzoom1=int((href->GetNbinsY())/3.*2.)-1;
+      zoom  = href->GetYaxis()->GetBinLowEdge(nzoom1); 
+      szoom = "zoom1" ; 
+    }
+    if(i==3){
+      int nzoom2 = int((href->GetNbinsY())/3.)-1;
+      zoom  = href->GetYaxis()->GetBinLowEdge(nzoom2);
+      szoom = "zoom2" ; 
+    }
+    
+    std::cout << "NOW DOING FOR ZOOM = " << zoom << std::endl;
+    Float_t myr[3];
+    myr[0]=-zoom;
+    myr[1]=0;
+    myr[2]= zoom;
+    TH2F* hdummy = new TH2F("hdummy","hdummy",2,myr,2,myr);
+    hdummy->GetYaxis()->SetRangeUser(-float(zoom),float(zoom));
+    hdummy->GetXaxis()->SetRangeUser(-float(zoom),float(zoom));
+    hdummy->GetXaxis()->SetTitle("x [mm]");
+    hdummy->GetYaxis()->SetTitle("y [mm]");
+
+    href->SetContour(ncontours);
+    //if(mycase==2) href->Scale(1./href->Integral());
+    href->GetYaxis()->SetRangeUser(-float(zoom),float(zoom));
+    href->GetZaxis()->SetLabelSize(0.03);
+    if(mycase==1 && !doNNHit) href->GetZaxis()->SetTitle("log(E/mm^{2})");
+    if(mycase==1 && doNNHit) href->GetZaxis()->SetTitle("log(E)");
+    if(mycase==2) href->GetZaxis()->SetTitle("norm. E [MeV]");
+    href->GetZaxis()->SetTitleSize(0.04);
+    href->GetZaxis()->SetTitleOffset(1.);
+
+    hout->SetContour(ncontours);
+    //if(mycase==2) hout->Scale(1./hout->Integral());
+    hout->GetYaxis()->SetRangeUser(-float(zoom),float(zoom));
+    hout->GetZaxis()->SetLabelSize(0.03);
+    if(mycase==1 && !doNNHit) hout->GetZaxis()->SetTitle("log(E/mm^{2})");
+    if(mycase==1 && doNNHit) hout->GetZaxis()->SetTitle("log(E)");
+    if(mycase==2) hout->GetZaxis()->SetTitle("norm. E [MeV]");
+    hout->GetZaxis()->SetTitleSize(0.04);
+    hout->GetZaxis()->SetTitleOffset(1.);
+
+    // ratio plot
+    TH2F* hratio = (TH2F*) hout->Clone("hratio");
+    hratio->Divide(href);
+
+    TLatex l;
+    TLatex l2;
+    TLatex l3;
+    TLatex l4;
+
+    TCanvas* c1 = new TCanvas("c1","c1",10,10,900,800);
+    c1->SetRightMargin(0.13);
+    hdummy->Draw("COLZ");
+    href->Draw("COLZ POL SAME");
+    l.DrawLatex(-1.3*zoom,-1.3*zoom,"ATLAS");
+    l2.DrawLatex(-0.9*zoom,-1.3*zoom,"Simulation Preliminary");
+    l3.DrawLatex(-zoom,1.02*zoom,(labeltitle+", NN input").c_str());    
+    l4.DrawLatex(-0.95*zoom,0.85*zoom,szoom.c_str());
+    if(!doNNHit) c1->SaveAs(("output/NNinput_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+    if( doNNHit) c1->SaveAs(("output/NNinput_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+    TCanvas* c2 =new TCanvas("c2","c2",10,10,900,800);
+    c2->SetRightMargin(0.13);
+    hdummy->Draw("COLZ");
+    float myZmax = href->GetMaximum();
+    float myZmin = href->GetMinimum();
+    hout->SetMaximum(myZmax);
+    hout->SetMinimum(myZmin);
+    hout->Draw("COLZ POL SAME");
+    l.DrawLatex(-1.3*zoom,-1.3*zoom,"ATLAS");
+    l2.DrawLatex(-0.9*zoom,-1.3*zoom,"Simulation Preliminary");
+    l3.DrawLatex(-zoom,1.02*zoom,(labeltitle+", NN output").c_str());
+    l4.DrawLatex(-0.95*zoom,0.85*zoom,szoom.c_str());
+    if(!doNNHit) c2->SaveAs(("output/NNoutput_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+    if( doNNHit) c2->SaveAs(("output/NNoutput_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+    TCanvas* c3 =new TCanvas("c3","c3",10,10,900,800);
+    c3->SetRightMargin(0.13);
+    //c3->SetLogz();
+    hdummy->Draw("COLZ");
+    hratio->SetMinimum(0);
+    hratio->SetMaximum(3);
+    hratio->Draw("COLZ POL SAME");
+    l.DrawLatex(-1.3*zoom,-1.3*zoom,"ATLAS");
+    l2.DrawLatex(-0.9*zoom,-1.3*zoom,"Simulation Preliminary");
+    l3.DrawLatex(-zoom,1.02*zoom,(labeltitle+", ratio").c_str());
+    l4.DrawLatex(-0.95*zoom,0.85*zoom,szoom.c_str());
+    if(!doNNHit) c3->SaveAs(("output/NNratio_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+    if( doNNHit) c3->SaveAs(("output/NNratio_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+    // projections
+    if(i==1){ // only for zoom0 case
+
+      int nR = href->GetNbinsY()+1;
+      Float_t* vR = new Float_t[nR];
+      for(Int_t i=1;i<hratio->GetNbinsY()+1;i++){
+	vR[i-1]=hratio->GetYaxis()->GetBinLowEdge(i);
+	if(i==hratio->GetNbinsY()){
+	  vR[i] = hratio->GetYaxis()->GetBinLowEdge(i)+hratio->GetYaxis()->GetBinWidth(i);
+	}
+      }
+      TH1D* hratio1Dr     = new TH1D("hratio1Dr","hratio1Dr",nR-1,vR);
+      
+      for(Int_t j=1;j<hratio->GetNbinsY()+1;j++){
+	float myrcumul = 0 ; 
+	for(Int_t i=1;i<hratio->GetNbinsX()+1;i++){
+	  myrcumul += hratio->GetBinContent(i,j);
+	}
+	hratio1Dr->SetBinContent(j,myrcumul/hratio->GetNbinsX());
+      }
+      
+      int nA = href->GetNbinsX()+1;
+      Float_t* vA = new Float_t[nA];
+      for(Int_t i=1;i<hratio->GetNbinsX()+1;i++){
+	vA[i-1]=hratio->GetXaxis()->GetBinLowEdge(i);
+	if(i==hratio->GetNbinsX()){
+	  vA[i] = hratio->GetXaxis()->GetBinLowEdge(i)+hratio->GetXaxis()->GetBinWidth(i);
+	}
+      }
+      TH1D* hratio1Dalpha  = new TH1D("hratio1Dalpha","hratio1Dalpha",nA-1,vA);
+      for(Int_t i=1;i<hratio->GetNbinsX()+1;i++){
+	float myalphacumul = 0 ;
+	for(Int_t j=1;j<hratio->GetNbinsY()+1;j++){
+	  myalphacumul += hratio->GetBinContent(i,j);
+	}
+	hratio1Dalpha->SetBinContent(i,myalphacumul/hratio->GetNbinsY());
+      }
+      
+      TCanvas* c4 =new TCanvas("c4","c4",10,10,900,800);
+      c4->SetRightMargin(0.13);
+      hratio1Dalpha->GetXaxis()->SetTitle("#alpha");
+      hratio1Dalpha->GetYaxis()->SetTitle("NN output / NN input");
+      hratio1Dalpha->GetYaxis()->SetRangeUser(0,2);
+      hratio1Dalpha->Draw();
+      l.DrawLatex(0,-0.3,"ATLAS Simulation Preliminary");
+      l3.DrawLatex(0,2.03,(labeltitle+", ratio").c_str());
+      l4.DrawLatex(2,1.85,szoom.c_str());
+      if(!doNNHit) c4->SaveAs(("output/NNratioAlpha_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+      if( doNNHit) c4->SaveAs(("output/NNratioAlpha_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+      TCanvas* c5 =new TCanvas("c5","c5",10,10,900,800);
+      c5->SetRightMargin(0.13);
+      c5->SetLogx();
+      hratio1Dr->GetXaxis()->SetTitle("r [mm]");
+      hratio1Dr->GetYaxis()->SetTitle("NN output / NN input");
+      hratio1Dr->GetXaxis()->SetRangeUser(-float(zoom),float(zoom));
+      hratio1Dr->GetYaxis()->SetRangeUser(0,2);
+      hratio1Dr->Draw();
+      l.DrawLatex(0,-0.3,"ATLAS Simulation Preliminary");
+      l3.DrawLatex(0,2.03,(labeltitle+", ratio").c_str());
+      l4.DrawLatex(2,1.85,szoom.c_str());
+      if(!doNNHit) c5->SaveAs(("output/NNratioR_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+      if( doNNHit) c5->SaveAs(("output/NNratioR_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+      // rebin r with respect to the calorimeter geometry
+      float newRboundary = 0 ; 
+      float newbincontent = 0 ; 
+      std::vector<float> vnewRboundary;
+      std::vector<float> vnewbincontent;
+      int n = 1 ;
+      int nmergedbins=0;
+      vnewRboundary.push_back(hratio1Dr->GetBinLowEdge(1));
+      for(Int_t i=1;i<hratio1Dr->GetNbinsX()+1;i++){
+	newRboundary     = hratio1Dr->GetBinLowEdge(i)+hratio1Dr->GetBinWidth(i);
+	newbincontent   += hratio1Dr->GetBinContent(i);
+	nmergedbins++;
+	if(newRboundary>n*calosize){
+	  vnewbincontent.push_back(newbincontent/nmergedbins);
+	  vnewRboundary.push_back(newRboundary);
+	  n++;
+	  nmergedbins=0;
+	  newbincontent=0;
+	}
+      }
+      int nnewRboundary = vnewRboundary.size();
+      Float_t vnewRboundary1[nnewRboundary];
+      for(unsigned int j=0;j<vnewRboundary.size();j++){
+	vnewRboundary1[j] = vnewRboundary.at(j);
+      }
+      TH1F* hratio1DrBIN = new TH1F("hratio1DrBIN","hratio1DrBIN",nnewRboundary-1,vnewRboundary1);
+      
+      for(unsigned int k=0;k<vnewbincontent.size();k++){
+	hratio1DrBIN->SetBinContent(k+1,vnewbincontent.at(k));
+      }
+      std::ostringstream scalosize;
+      scalosize << calosize ; 
+      
+      if(calosize==-1000)
+	std::cout << "There is a problem with determining the size of the calo cell! " << std::endl;
+      TCanvas* c6 =new TCanvas("c6","c6",10,10,900,800);
+      c6->SetRightMargin(0.13);
+      hratio1DrBIN->GetXaxis()->SetRangeUser(-float(zoom),float(zoom));
+      hratio1DrBIN->GetXaxis()->SetTitle("r [mm]");
+      hratio1DrBIN->GetYaxis()->SetTitle("NN output / NN input");
+      hratio1DrBIN->GetXaxis()->SetRangeUser(-float(zoom),float(zoom));
+      hratio1DrBIN->GetYaxis()->SetRangeUser(0,2);
+      hratio1DrBIN->Draw();
+      c6->SetLogx();
+      l.DrawLatex(-0,-0.3,"ATLAS Simulation Preliminary");
+      l3.DrawLatex(0,2.03,(labeltitle+", ratio").c_str());
+      string scalo = szoom+" ,rebin of "+scalosize.str()+" mm";
+      l4.DrawLatex(calosize,1.85,scalo.c_str());
+      if(!doNNHit) c6->SaveAs(("output/NNratioR_rebincalo_"+labeloutput+"_"+szoom+"_"+method+".pdf").c_str());
+      if( doNNHit) c6->SaveAs(("output/NNratioR_rebincalo_"+labeloutput+"_"+szoom+"_"+method+"_NNHit.pdf").c_str());
+
+      delete hratio1DrBIN;
+      delete hratio1Dr;
+      delete hratio1Dalpha;
+      delete c4;
+      delete c5;
+      delete c6;
+    }
+
+    delete hdummy;
+    delete c1;
+    delete c2;
+    delete c3;
+  }
+
+}
+
+//=============================================
+//========== ROOT persistency stuff ===========
+//=============================================
+
+ClassImp(TFCS2DFunction)
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunctionRegression.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunctionRegression.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e6b27e5217bb9bb2211df7e536eeae7f4a151581
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2DFunctionRegression.cxx
@@ -0,0 +1,282 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+using namespace std;
+
+#include "ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.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 "TMVA/IMethod.h"
+#include "TMVA/MethodMLP.h"
+#define private public
+#define protected public
+#include "TMath.h"
+
+
+//=============================================
+//======= TFCS2DFunctionRegression =========
+//=============================================
+
+TFCS2DFunctionRegression::TFCS2DFunctionRegression()
+{
+}
+
+TFCS2DFunctionRegression::TFCS2DFunctionRegression(TH1* hist)
+{
+	
+  Initialize(hist);
+  
+}
+
+
+void TFCS2DFunctionRegression::Initialize(TH1* /*hist*/)
+{
+ //not needed
+}
+
+void TFCS2DFunctionRegression::storeRegression(string weightfilename,int mycase)
+{
+  
+  get_weights(weightfilename,mycase);
+  
+  //for testing - DOES NOT WORK FOR TRANSFORMED VARARIABLES (VarTransform=Norm)
+  //validate(10,weightfilename,mycase);
+  
+}
+
+
+void TFCS2DFunctionRegression::validate(int Ntoys,string weightfilename,int mycase)
+{
+ 
+ TRandom* myRandom1=new TRandom3();
+ TRandom* myRandom2=new TRandom3();
+
+ myRandom1->SetSeed( 0 );
+ myRandom2->SetSeed( 1000 );
+
+
+ //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++)
+ {
+   std::vector<double> vuniform;
+   float random1 = myRandom1->Uniform(1);
+   float random2 = myRandom2->Uniform(1);
+   vuniform.push_back(random1);
+   vuniform.push_back(random2);
+   
+   if(mycase==1) cout <<"myvalue "<< regression_value(vuniform, mycase) <<" TMVA value "<<(tmvaregression_application(random1,random2,weightfilename,mycase)).at(0)<<endl;
+   if(mycase==2) cout <<"myvalue "<< regression_value(vuniform, mycase) <<" TMVA value "<<(tmvaregression_application(random1,random2,weightfilename,mycase)).at(0)<< "  " << (tmvaregression_application(random1,random2,weightfilename,mycase)).at(1) << endl;
+ }
+ 
+}
+
+
+void TFCS2DFunctionRegression::get_weights(string /*weightfile*/,int /*mycase*/)
+{
+
+/*
+ 
+ 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 r=0.5; //just a dummy
+ Float_t alpha=0.5;
+ Float_t probr=0.5;
+ Float_t probalpha=0.5;
+ if(mycase==1){
+   reader->AddVariable( "alpha", &alpha );
+   reader->AddVariable( "r", &r );
+ } 
+ if(mycase==2){
+   reader->AddVariable( "probalpha", &probalpha );
+   reader->AddVariable( "probr", &probr );
+ }
+
+ 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;
+ //mlp->MakeClass("mlpcode.C");
+
+ int num_neurons_input=((TObjArray*)Network->At(1))->GetEntriesFast()-1;
+ if(debug) cout<<"num_neurons_input "<<num_neurons_input<<endl;
+ 
+ int fLayers = Network->GetEntriesFast();
+ if(fLayers!=3) cout<<"!!!!!!!!!! fLayers is not 3 !!!!!!!!!"<<endl;
+ 
+ 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++)
+ {  
+  TNeuron* neuron = (TNeuron*)curLayer->At(n);
+  int numSynapses = neuron->NumPostLinks();
+  for (int s = 0; s < numSynapses; s++)
+  {
+   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++)
+ {  
+  TNeuron* neuron = (TNeuron*)curLayer->At(n);
+  int numSynapses = neuron->NumPostLinks();
+  for (int s = 0; s < numSynapses; s++)
+  {
+   TSynapse* synapse = neuron->PostLinkAt(s);  
+   m_fWeightMatrix1to2[s][n]=synapse->GetWeight();
+   if(debug) cout<<"fWeightMatrix1to2["<<s<<"]["<<n<<"] "<<synapse->GetWeight()<<endl;
+  }
+ }
+ 
+ delete reader;
+ */
+
+}
+
+double TFCS2DFunctionRegression::regression_value(vector<double> vuniform, int mycase)
+{
+
+ int n_neurons=m_fWeightMatrix0to1.size();
+ 
+ int fLayers=3;
+ vector<int> fLayerSize;
+ fLayerSize.push_back(3);
+ fLayerSize.push_back(n_neurons);
+ fLayerSize.push_back(mycase);
+ 
+
+ 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]=vuniform[i];
+ }
+
+ // 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] = TMath::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];
+  }
+ }
+ 
+ return fWeights[2][0];
+ 
+}
+
+
+double TFCS2DFunctionRegression::rnd_to_fct(std::vector<double> vrdn, int mycase)
+{
+  
+  double value=regression_value(vrdn,mycase);
+  return value;
+  
+}
+
+
+//=============================================
+//========== ROOT persistency stuff ===========
+//=============================================
+
+ClassImp(TFCS2DFunctionRegression)
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2Function.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2Function.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7c25a67d7134ca5ceaba56a4649c2e1e6b80f531
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCS2Function.cxx
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+using namespace std;
+#include "ISF_FastCaloSimParametrization/TFCS2Function.h"
+#include "ISF_FastCaloSimParametrization/TFCS2DFunction.h"
+#include "ISF_FastCaloSimParametrization/TFCS2DFunctionRegression.h"
+#include "TRandom1.h"
+#include <sstream>  
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ftw.h>
+
+//=============================================
+//======= TFCSFunction =========
+//=============================================
+
+TFCS2DFunction* TFCS2Function::Create(string inputfile, int verbose_level, string label, string labelout, int mycase, float calosize, bool doNNHit)
+{
+  // 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 TFCS2DFunctionRegression
+  // 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";
+  TFCS2DFunction* fct=new TFCS2DFunction(inputfile);
+  int status=fct->fitShape(inputfile,xmlweightfilename, outfilename, label, labelout, mycase,calosize,doNNHit);
+  if(verbose_level==1) cout<<"--- fitShape status="<<status<<endl;
+
+  TFCS2DFunctionRegression* freg;
+  if(status==1)
+  {
+    if(verbose_level==1) cout<<"Regression"<<endl;
+    freg=new TFCS2DFunctionRegression();
+    freg->storeRegression(xmlweightfilename,mycase);
+    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)
+  {
+    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 0;
+  }
+  if(status==0)
+  {
+    cout<<"something went wrong :("<<endl;
+    return 0;	
+  }
+
+  return 0 ;  
+}
+
+
+//=============================================
+//========== ROOT persistency stuff ===========
+//=============================================
+
+ClassImp(TFCS2Function)
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSEnergyParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSEnergyParametrization.cxx
deleted file mode 100644
index b497e0cdb55c1a295a804923fc9030fadbd9a192..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSEnergyParametrization.cxx
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSEnergyParametrization.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
-
-//=============================================
-//======= TFCSEnergyParametrization =========
-//=============================================
-
-TFCSEnergyParametrization::TFCSEnergyParametrization(const char* name, const char* title):TFCSParametrization(name,title)
-{
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSEnergyParametrization)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSExtrapolationState.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSExtrapolationState.cxx
deleted file mode 100644
index 017b9763c965afc4175b4eb213ea726dc5aa3e8d..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSExtrapolationState.cxx
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSExtrapolationState.h"
-
-//=============================================
-//======= TFCSExtrapolationState =========
-//=============================================
-
-TFCSExtrapolationState::TFCSExtrapolationState()
-{
-  clear();
-}
-
-void TFCSExtrapolationState::clear()
-{
-  for(int i=0;i<CaloCell_ID_FCS::MaxSample;++i) {
-    for(int j=0;j<3;++j) {
-      m_CaloOK[i][j]=false;
-      m_etaCalo[i][j]=-999;
-      m_phiCalo[i][j]=-999;
-      m_rCalo[i][j]=0;
-      m_zCalo[i][j]=0;
-      m_dCalo[i][j]=0;
-      m_distetaCaloBorder[i][j]=0;
-    }
-  }
-  
-  m_IDCaloBoundary_eta=-999;
-  m_IDCaloBoundary_phi=-999;
-  m_IDCaloBoundary_r=0;
-  m_IDCaloBoundary_z=0;
-}
-
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSExtrapolationState)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx
index ce281f6e2edc3bfcb8018ab068ef825feeef5e17..44f9472f8813bff3610d12242c5c2064a184b45b 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSFunction.cxx
@@ -2,38 +2,139 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
+using namespace std;
 #include "ISF_FastCaloSimParametrization/TFCSFunction.h"
-#include "ISF_FastCaloSimParametrization/TFCS1DFunction.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 =========
 //=============================================
 
-TFCS1DFunction* TFCSFunction::Create(TH1* hist)
+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. 
  
- // For now dummy implementation always using TFCS1DFunctionHistogram
-
+ 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);
-#if 0
- int status=fct->testHisto(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)
-  TFCS1DFunctionRegression* freg=new TFCS1DFunctionRegression(hist);
+ {
+ 	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)
-  TFCS1DFunctionHistogram* fhis=new TFCS1DFunctionHistogram(hist);
-#endif
-  
- return fct;
+ {
+ 	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 ===========
 //=============================================
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSLateralShapeParametrization.cxx
index 2746c84ea82947b1c91ea28c2866ef2d88206222..783fd7c04f11271cee243c71de979cc2364de32b 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSLateralShapeParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSLateralShapeParametrization.cxx
@@ -3,7 +3,7 @@
 */
 
 #include "ISF_FastCaloSimParametrization/TFCSLateralShapeParametrization.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 #include <iostream>
 
 //=============================================
@@ -27,8 +27,8 @@ void TFCSLateralShapeParametrization::set_calosample(int cs)
 void TFCSLateralShapeParametrization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* extrapol)
 {
   int cs=calosample();
-  double hit_eta=0.5*( extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_EXT) );
-  double hit_phi=0.5*( extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_EXT) );
+  double hit_eta=0.5*( extrapol->eta(cs, CaloSubPos::SUBPOS_ENT) + extrapol->eta(cs, CaloSubPos::SUBPOS_EXT) );
+  double hit_phi=0.5*( extrapol->phi(cs, CaloSubPos::SUBPOS_ENT) + extrapol->phi(cs, CaloSubPos::SUBPOS_EXT) );
   double hit_weight=1;
 
   simulstate.deposit_HIT(cs,hit_eta,hit_phi,hit_weight);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSNNLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSNNLateralShapeParametrization.cxx
index 70a25dc6f80627a5b7f411600643619b590cf806..0fd04dca8d7f6c225f2e0be51e17abf6a48274c2 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSNNLateralShapeParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSNNLateralShapeParametrization.cxx
@@ -3,7 +3,7 @@
 */
 
 #include "ISF_FastCaloSimParametrization/TFCSNNLateralShapeParametrization.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 
 //=============================================
 //======= TFCSLateralShapeParametrization =========
@@ -16,8 +16,8 @@ TFCSNNLateralShapeParametrization::TFCSNNLateralShapeParametrization(const char*
 void TFCSNNLateralShapeParametrization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* extrapol)
 {
   int cs=calosample();
-  double hit_eta=0.5*( extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_EXT) );
-  double hit_phi=0.5*( extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_EXT) );
+  double hit_eta=0.5*( extrapol->eta(cs, CaloSubPos::SUBPOS_ENT) + extrapol->eta(cs, CaloSubPos::SUBPOS_EXT) );
+  double hit_phi=0.5*( extrapol->phi(cs, CaloSubPos::SUBPOS_ENT) + extrapol->phi(cs, CaloSubPos::SUBPOS_EXT) );
   double hit_weight=1;
 
   simulstate.deposit_HIT(cs,hit_eta,hit_phi,hit_weight);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSPCAEnergyParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSPCAEnergyParametrization.cxx
deleted file mode 100644
index e6bd2d24a7f49d65363ed430d3e7f5e2b57e167c..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSPCAEnergyParametrization.cxx
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSPCAEnergyParametrization.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
-
-#include "TFile.h"
-#include <iostream>
-#include "TKey.h"
-#include "TClass.h"
-#include "TRandom3.h"
-
-//=============================================
-//======= TFCSPCAEnergyParametrization =========
-//=============================================
-
-TFCSPCAEnergyParametrization::TFCSPCAEnergyParametrization(const char* name, const char* title):TFCSEnergyParametrization(name,title)
-{
-}
-
-void TFCSPCAEnergyParametrization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* /*extrapol*/)
-{
- 
- int thisbin=simulstate.Ebin();
- std::cout<<"--- Simulation of bin "<<thisbin<<std::endl;
-  
- for(unsigned int i=0;i<CaloCell_ID_FCS::MaxSample;++i)
-  simulstate.add_E(i,truth->Ekin()/CaloCell_ID_FCS::MaxSample);
- 
- TRandom3* Random3=new TRandom3();
- Random3->SetSeed(0);
- 
- //get relevant layers for that bin
- std::vector<std::string> layer;
- std::vector<int> layerNr;
- double* samplings=m_RelevantLayers[thisbin]->GetMatrixArray();
- for(int i=0;i<m_RelevantLayers[thisbin]->GetNrows();i++)
-  layerNr.push_back(samplings[i]);
- for(unsigned int i=0;i<layerNr.size();i++)
- {
-     std::string thislayer="layer"+layerNr[i];
-  layer.push_back(thislayer);
- }
- layer.push_back("totalE");
- 
- double output_data[layer.size()];
- double input_data[layer.size()];
- 
- double* gauss_means=m_Gauss_means[thisbin]->GetMatrixArray();
- double* gauss_rms=m_Gauss_rms[thisbin]->GetMatrixArray();
- 
- for(unsigned int l=0;l<layer.size();l++)
- {
-  double mean=gauss_means[l];
-  double rms =gauss_rms[l];
-  double gauszz=Random3->Gaus(mean,rms);
-  input_data[l]=gauszz;
- }
-  
- P2X(layer.size(), m_EigenVectors[thisbin], m_MeanValues[thisbin], m_SigmaValues[thisbin], input_data, output_data, layer.size());
- 
- std::cout<<"--- Inverse Regression"<<std::endl;
- //double simdata_uniform[layer.size()];
- //double simdata[layer.size()];
- //double total_fraction; //this is needed for the rescaling in the next step
- /*
- for(int l=0;l<layer.size();l++)
- {
-  simdata_uniform[l]=(TMath::Erf(output_data[l]/1.414213562)+1)/2.f;
-  
-  if(do_range)
-  {
-   if(Simulated_Uniform2[l]<range_low[l][randombin])
-    Simulated_Uniform2[l]=range_low[l][randombin];
-  }
-  
-  //simdata[l] = regression_application(simdata_uniform[l],thisbin,label,layer[l]);
-  if(simdata[l]<0) simdata[l]=0;
-  if(layer[l]!="totalE" && simdata[l]>1) simdata[l]=1;  
-  if(layer[l]!="totalE") total_fraction+=simdata[l];
- }
- */
- 
-}
-
-
-void TFCSPCAEnergyParametrization::P2X(int gNVariables, TMatrixD *EigenVectors,TVectorD *MeanValues, TVectorD *SigmaValues, double *p, double *x, int nTest)
-{
- 
- double* gEigenVectors = EigenVectors->GetMatrixArray();
- double* gMeanValues = MeanValues->GetMatrixArray();
- double* gSigmaValues = SigmaValues->GetMatrixArray();
- 
- for(int i = 0; i < gNVariables; i++)
- {
-  x[i] = gMeanValues[i];
-  for(int j = 0; j < nTest; j++)
-   x[i] += p[j] * gSigmaValues[i] * gEigenVectors[i *  gNVariables + j];       
- }
- 
-}
-
-
-void TFCSPCAEnergyParametrization::loadInputs(TFile* file)
-{
- 
- TIter next(file->GetListOfKeys());
- TKey *key;
- while ((key = (TKey*)next()))
- {
-  TDirectory* bindir=(TDirectory*)key->ReadObj();
-  
-  bindir->cd();
-  TMatrixD* EigenVectors = (TMatrixD*)bindir->Get("EigenVectors");
-  TVectorD* MeanValues   =(TVectorD*)bindir->Get("MeanValues");
-  TVectorD* SigmaValues  =(TVectorD*)bindir->Get("Sigmas");
-  TVectorD* RelevantLayers  =(TVectorD*)bindir->Get("RelevantLayers");
-  TVectorD* Gauss_means  =(TVectorD*)bindir->Get("Gauss_means");
-  TVectorD* Gauss_rms  =(TVectorD*)bindir->Get("Gauss_rms");
-  
-  m_RelevantLayers.push_back(RelevantLayers);
-  m_EigenVectors.push_back(EigenVectors);
-  m_MeanValues.push_back(MeanValues);
-  m_SigmaValues.push_back(SigmaValues);
-  m_Gauss_means.push_back(Gauss_means);
-  m_Gauss_rms.push_back(Gauss_rms); 
- }
- 
- 
- 
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSPCAEnergyParametrization)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrization.cxx
deleted file mode 100644
index 74c16cbc392869832465f248c89c3f9f35752f85..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrization.cxx
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSParametrization.h"
-
-//=============================================
-//======= TFCSParametrization =========
-//=============================================
-
-TFCSParametrization::TFCSParametrization(const char* name, const char* title):TFCSParametrizationBase(name,title),m_Ekin_nominal(0),m_Ekin_min(0),m_Ekin_max(0),m_eta_nominal(100),m_eta_min(100),m_eta_max(100)
-{
-}
-
-void TFCSParametrization::set_pdgid(int id)
-{
-  m_pdgid.clear();
-  m_pdgid.insert(id);
-}
-
-void TFCSParametrization::add_pdgid(int id)
-{
-  m_pdgid.insert(id);
-}
-
-void TFCSParametrization::clear_pdgid()
-{
-  m_pdgid.clear();
-}
-
-void TFCSParametrization::set_Ekin_nominal(double nominal)
-{
-  m_Ekin_nominal=nominal;
-}
-
-void TFCSParametrization::set_Ekin_min(double min)
-{
-  m_Ekin_min=min;
-}
-
-void TFCSParametrization::set_Ekin_max(double max)
-{
-  m_Ekin_max=max;
-}
-
-
-void TFCSParametrization::set_eta_nominal(double nominal)
-{
-  m_eta_nominal=nominal;
-}
-
-void TFCSParametrization::set_eta_min(double min)
-{
-  m_eta_min=min;
-}
-
-void TFCSParametrization::set_eta_max(double max)
-{
-  m_eta_max=max;
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSParametrization)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrizationBase.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrizationBase.cxx
deleted file mode 100644
index 939e568993966b0f440db4051389a954a2c66ceb..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSParametrizationBase.cxx
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSParametrizationBase.h"
-#include <iostream>
-
-//=============================================
-//======= TFCSParametrizationBase =========
-//=============================================
-
-std::set< int > TFCSParametrizationBase::m_no_pdgid;
-
-TFCSParametrizationBase::TFCSParametrizationBase(const char* name, const char* title):TNamed(name,title)
-{
-}
-
-void TFCSParametrizationBase::simulate(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/)
-{
-}
-
-void TFCSParametrizationBase::Print(Option_t *option) const
-{
-  TNamed::Print(option);
-
-  std::cout <<"  PDGID: ";
-  for (std::set<int>::iterator it=pdgid().begin(); it!=pdgid().end(); ++it) std::cout << *it << ", ";
-  std::cout << std::endl;
-  
-  std::cout <<"  Ekin="<<Ekin_nominal()<<" MeV, range "<<Ekin_min()<<" MeV < Ekin < "<<Ekin_max()<<" MeV"<<std::endl;
-  std::cout <<"  eta="<<eta_nominal()<<", range "<<eta_min()<<" < eta < "<<eta_max()<<std::endl;
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSParametrizationBase)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimpleLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimpleLateralShapeParametrization.cxx
index 6a4470cbfb1e1e06ab93e7e0cf3d0cf310448c02..9419132bc29ed02b9caaea554e15a8290e7bbe0d 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimpleLateralShapeParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimpleLateralShapeParametrization.cxx
@@ -3,17 +3,19 @@
 */
 
 #include "ISF_FastCaloSimParametrization/TFCSSimpleLateralShapeParametrization.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 
 //=============================================
 //======= TFCSLateralShapeParametrization =========
 //=============================================
 
-TFCSSimpleLateralShapeParametrization::TFCSSimpleLateralShapeParametrization(const char* name, const char* title):TFCSLateralShapeParametrization(name,title)
+TFCSSimpleLateralShapeParametrization::TFCSSimpleLateralShapeParametrization(const char* name, const char* title) :
+  TFCSLateralShapeParametrization(name,title),
+  m_rnd(0)
 {
 
-    sigma_x = 0;
-    sigma_y = 0;
+    m_sigmaX = 0;
+    m_sigmaY = 0;
 
     //sigma2_x = 0;
     //sigma2_y = 0;
@@ -23,8 +25,8 @@ TFCSSimpleLateralShapeParametrization::TFCSSimpleLateralShapeParametrization(con
 void TFCSSimpleLateralShapeParametrization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* extrapol)
 {
   int cs=calosample();
-  double hit_eta=0.5*( extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->eta(cs,TFCSExtrapolationState::SUBPOS_EXT) );
-  double hit_phi=0.5*( extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_ENT) + extrapol->phi(cs,TFCSExtrapolationState::SUBPOS_EXT) );
+  double hit_eta=0.5*( extrapol->eta(cs, CaloSubPos::SUBPOS_ENT) + extrapol->eta(cs, CaloSubPos::SUBPOS_EXT) );
+  double hit_phi=0.5*( extrapol->phi(cs, CaloSubPos::SUBPOS_ENT) + extrapol->phi(cs, CaloSubPos::SUBPOS_EXT) );
   double hit_weight=1;
 
   double x, y;
@@ -44,8 +46,8 @@ void TFCSSimpleLateralShapeParametrization::simulate(TFCSSimulationState& simuls
 bool TFCSSimpleLateralShapeParametrization::Initialize(const char* filepath, const char* histname)
 {
     // Setup random numbers
-    rnd = new TRandom3();
-    rnd->SetSeed(0);
+    m_rnd = new TRandom3();
+    m_rnd->SetSeed(0);
 
 
     // input file with histogram to fit
@@ -109,8 +111,8 @@ bool TFCSSimpleLateralShapeParametrization::Initialize(const char* filepath, con
     //out->Close();
 
     // Finally set sigma
-    sigma_x = fitx->GetParameter(2);
-    sigma_y = fity->GetParameter(2);
+    m_sigmaX = fitx->GetParameter(2);
+    m_sigmaY = fity->GetParameter(2);
 
 
     // clean up
@@ -128,8 +130,8 @@ void TFCSSimpleLateralShapeParametrization::getHitXY(double &x, double &y)
 {
 
 
-    x = rnd->Gaus(0, sigma_x);
-    y = rnd->Gaus(0, sigma_y);
+    x = m_rnd->Gaus(0, m_sigmaX);
+    y = m_rnd->Gaus(0, m_sigmaY);
 
 }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimulationState.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimulationState.cxx
deleted file mode 100644
index 6c4e75976029976dc5277096cdb03c7294bd9223..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSSimulationState.cxx
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSSimulationState.h"
-
-//=============================================
-//======= TFCSSimulationState =========
-//=============================================
-
-
-TFCSSimulationState::TFCSSimulationState()
-{
-  clear();
-}
-
-void TFCSSimulationState::clear()
-{
-  m_Ebin=-1;
-  m_Etot=0;
-  for(int i=0;i<CaloCell_ID_FCS::MaxSample;++i) {
-    m_E[i]=0;
-  }
-}
-
-void TFCSSimulationState::deposit_HIT(int /*sample*/, double /*hit_eta*/, double /*hit_phi*/, double /*hit_weight*/)
-{
-
-    /* deposit a hit */
-
-
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSSimulationState)
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSTruthState.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSTruthState.cxx
deleted file mode 100644
index a74981943fff15aa103261105726dced04acd419..0000000000000000000000000000000000000000
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TFCSTruthState.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ISF_FastCaloSimParametrization/TFCSTruthState.h"
-
-//=============================================
-//======= TFCSTruthState =========
-//=============================================
-
-TFCSTruthState::TFCSTruthState():TLorentzVector(),m_pdgid(0),m_vertex(0,0,0,0)
-{
-}
-
-TFCSTruthState::TFCSTruthState(Double_t x, Double_t y, Double_t z, Double_t t, int pdgid):TLorentzVector(x,y,z,t),m_vertex(0,0,0,0)
-{
-  m_pdgid=pdgid;
-}
-
-//=============================================
-//========== ROOT persistency stuff ===========
-//=============================================
-
-ClassImp(TFCSTruthState)
-
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
index 871f2dcf204f03551141c38d88262f2925ef8eaa..c6c5956e8b617a00789f89ea9e7438b39cf429e2 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/TreeReader.cxx
@@ -29,7 +29,8 @@ TreeReader::TreeReader()
   //============================================================
 {
   // Default constructor.
-  
+  m_isChain = false;
+  m_currentTree = -1;
   m_tree = 0;
   m_currentEntry = -1;
   m_entries = -1;
@@ -40,6 +41,7 @@ TreeReader::TreeReader(TTree* n)
   //============================================================
 {
   // Constructor.
+  m_tree = 0;
   m_entries = -1;
   SetTree(n);
 }
@@ -56,14 +58,15 @@ TreeReader::~TreeReader()
 void TreeReader::SetTree(TTree* n)
   //============================================================
 {
+  // check for null pointer BEFORE trying to use it
+  if(!n) return;
   // Set tree.
-  m_tree = n ;
+  m_tree = n;
   m_currentEntry = -1;
   m_formulae.clear();
   m_formulae["__DUMMY__"] = new TTreeFormula("__DUMMY__","0",m_tree);  
-  m_isChain = n->IsA() == TClass::GetClass("TChain");
+  m_isChain = (n->IsA() == TClass::GetClass("TChain"));
   m_currentTree = 0;
-  if(!n) return;
   m_entries = (int) m_tree->GetEntries();
 }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx
index 08594cde8447a58be784d099509073493671c014..b1b5f6876e314041af9af8c20707bf66e500c1bb 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/firstPCA.cxx
@@ -2,6 +2,8 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
+using namespace std;
+
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "TH1D.h"
@@ -17,461 +19,579 @@
 #include "TBrowser.h"
 #include "ISF_FastCaloSimParametrization/firstPCA.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
+#include "TLorentzVector.h"
+#include "TChain.h"
 
 #include <iostream>
 
-using namespace std;
-
 firstPCA::firstPCA()
 {
+  //default parameters:
+  m_numberfinebins=5000;
+  m_edepositcut=0.001;
+  m_cut_eta_low=-100;
+  m_cut_eta_high=100;
+  m_nbins1=5;
+  m_nbins2=1;
+  m_debuglevel=0;
+  m_apply_etacut=1;
+  
+  m_outfilename="";
+  m_chain = 0;
 }
 
-string firstPCA::run(string inputfile, string label, int nbins1, int nbins2, int numberfinebins, double cut_edeposit)
+firstPCA::firstPCA(TChain* chain,string outfilename)
 {
- 
- int debug=0;
- 
- //Open inputfile:
- cout<<"--- Open input file "<<inputfile<<endl;
- TFile* file=TFile::Open(inputfile.c_str());
- if(!file) cout<<"ERROR: Inputfile could not be opened"<<endl;
- 
- cout<<"--- Init the TreeReader"<<endl;
- TTree* InputTree = (TTree*)file->Get("FCS_ParametrizationInput");
- TreeReader* read_inputTree = new TreeReader();
- read_inputTree->SetTree(InputTree);
- 
- cout<<"--- Get relevant layers"<<endl;
- vector<int> layerNr=get_relevantlayers(read_inputTree, cut_edeposit);
- vector<string> layer;
- for(unsigned int l=0;l<layerNr.size();l++)
-  layer.push_back(Form("layer%i",layerNr[l]));
- layer.push_back("totalE");
- 
- cout<<"--- Obtain data histograms and Cumulative Distributions from the input"<<endl;
- vector<TH1D*> histos_data=get_histos_data(layerNr, layer, read_inputTree, InputTree, numberfinebins);
- vector<TH1D*> cumul_data =get_cumul_data(layer, histos_data);
- 
- cout<<"--- Now define the TPrincipal"<<endl;
- TPrincipal* principal = new TPrincipal(layer.size(),"ND");  //ND means normalize cov matrix and store data
- 
- TTree *T_Gauss = new TTree("T_Gauss","T_Gauss");
- double* data_Gauss = new double[layer.size()];
- int eventNumber;
- for(unsigned int l=0;l<layer.size();l++)
- {
-  T_Gauss->Branch(Form("data_Gauss_%s",layer[l].c_str()),&data_Gauss[l],Form("data_Gauss_%s/D",layer[l].c_str()));
-  T_Gauss->Branch("eventNumber",&eventNumber,"eventNumber/I");
- }
- 
- cout<<"--- Uniformization/Gaussianization"<<endl;
- for(int event=0;event<read_inputTree->GetEntries();event++)
- {
-  read_inputTree->GetEntry(event);
-  eventNumber=event;
+  //default parameters:
+  m_numberfinebins=5000;
+  m_edepositcut=0.001;
+  m_cut_eta_low=-100;
+  m_cut_eta_high=100;
+  m_nbins1=5;
+  m_nbins2=1;
+  m_debuglevel=0;
+
+  m_outfilename=outfilename;
+  m_chain=chain;
+
+}
+
+void firstPCA::apply_etacut(int flag)
+{
+ m_apply_etacut=flag;
+}
+
+void firstPCA::set_cumulativehistobins(int bins)
+{
+  m_numberfinebins=bins;
+}
+
+void firstPCA::set_edepositcut(double cut)
+{
+  m_edepositcut=cut;
+}
+
+void firstPCA::set_etacut(double cut_low, double cut_high)
+{
+  m_cut_eta_low=cut_low;
+  m_cut_eta_high=cut_high;
+}
+
+void firstPCA::set_pcabinning(int bin1,int bin2)
+{
+  m_nbins1=bin1;
+  m_nbins2=bin2;
+}
+
+void firstPCA::run()
+{
+  cout<<endl;
+  cout<<"****************"<<endl;
+  cout<<"     1st PCA"<<endl;
+  cout<<"****************"<<endl;
+  cout<<endl;
+  cout<<"Now running firstPCA with the following parameters:"<<endl;
+  cout<<"  Energy deposit cut: "<<m_edepositcut<<endl;
+  cout<<"  PCA binning: 1st compo "<<m_nbins1<<", 2nd compo "<<m_nbins2<<endl;
+  cout<<"  Number of bins in the cumulative histograms "<<m_numberfinebins<<endl;
+  cout<<"  Eta cut: "<<m_cut_eta_low<<" "<<m_cut_eta_high<<endl;
+  cout<<"  Apply eta cut: "<<m_apply_etacut<<endl;
+  cout<<endl;
+  if(m_debuglevel) cout<<"initialize input tree reader"<<endl;
+  TreeReader* read_inputTree = new TreeReader();
+  read_inputTree->SetTree(m_chain);
+
+  vector<int> layerNr;
+  cout<<"--- Get relevant layers and Input Histograms"<<endl;
+  vector<TH1D*> histos_data=get_relevantlayers_inputs(layerNr,read_inputTree);
+
+  vector<string> layer;
+  for(unsigned int l=0;l<layerNr.size();l++)
+    layer.push_back(Form("layer%i",layerNr[l]));
+  layer.push_back("totalE");
+
+  vector<TH1D*> cumul_data =get_cumul_histos(layer, histos_data);
+
+  cout<<"--- Now define the TPrincipal"<<endl;
+  TPrincipal* principal = new TPrincipal(layer.size(),"ND");  //ND means normalize cov matrix and store data
+
+  TTree *T_Gauss = new TTree("T_Gauss","T_Gauss");
+  double* data_Gauss = new double[layer.size()];
+  int eventNumber;
   for(unsigned int l=0;l<layer.size();l++)
   {
-    double data/*,data_uniform*/;
-   
-   if(l==layer.size()-1)
-   	data = read_inputTree->GetVariable("total_cell_energy");
-   else
-    data = read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/read_inputTree->GetVariable("total_cell_energy");
-   
-   //Uniformization
-   double cumulant = get_cumulant(data,cumul_data[l]);
-   cumulant = TMath::Min(cumulant,1.-10e-10);
-   cumulant = TMath::Max(cumulant,0.+10e-10);
-   //data_uniform = cumulant;
-   
-   //Gaussianization
-   double maxErfInvArgRange = 0.99999999;
-   double arg = 2.0*cumulant - 1.0;
-   arg = TMath::Min(+maxErfInvArgRange,arg);
-   arg = TMath::Max(-maxErfInvArgRange,arg);
-   data_Gauss[l] = 1.414213562*TMath::ErfInverse(arg);
-   
-  } //for layers
-  
-  //Add this datapoint to the PCA
-  principal->AddRow(data_Gauss);
-  T_Gauss->Fill();
-  
- } //event loop
- 
- cout<<"--- MakePrincipals()"<<endl;
- principal->MakePrincipals();
- 
- cout<<"--- PCA Results"<<endl;
- principal->Print("MSE");
- 
- cout<<"--- PCA application and binning of first principal component"<<endl;
- 
- TreeReader* tree_Gauss = new TreeReader();
- tree_Gauss->SetTree(T_Gauss);
- int entries_Gauss = tree_Gauss->GetEntries();
- 
- int Bin_1stPC1=0;
- int Bin_1stPC2=0;
- 
- TH1D* hPCA_first_component = new TH1D("hPCA_first_component","hPCA_first_component",10000,-20,20);
- 
- for(int event=0;event<entries_Gauss;event++)
- {
-  tree_Gauss->GetEntry(event);
-  
-  double* data_PCA = new double[layer.size()];
-  double* input_data = new double[layer.size()];
- 	
-  for (unsigned int l=0;l<layer.size(); l++)
-   input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
-  
-  principal->X2P(input_data,data_PCA);  
-  hPCA_first_component->Fill(data_PCA[0]);
-  
- }
- 
- cout<<"--- Binning 1st Principal Component" <<endl;
- double xq[nbins1]; double yq[nbins1];
- 
- //2D binning:
- quantiles( hPCA_first_component, nbins1, xq , yq );
- for (int m = 0; m < nbins1 ; m++)
- {
-	int a=1;
- 	if(m>0) a=hPCA_first_component->FindBin(yq[m-1]);
- 	int b=hPCA_first_component->FindBin(yq[m]);
- 	cout<<"Quantiles "<<m+1<<"  "<<xq[m]<<" "<<yq[m]<<" -> Events "<<hPCA_first_component->Integral(a,b-1)<<endl;
- }
- 
- TH1D* h_compo1[nbins1];
- for(int m=0;m<nbins1;m++)
-  h_compo1[m]=new TH1D(Form("h_compo1_bin%i",m),Form("h_compo1_bin%i",m),20000,-20,20);
- 
- cout<<"--- PCA application and binning 2nd principal component"<<endl;
- for(int event=0;event<entries_Gauss;event++)
- {
-  tree_Gauss->GetEntry(event);
-  double* data_PCA = new double[layer.size()];
-  double* input_data = new double[layer.size()];
-
-  for (unsigned int l=0;l<layer.size();l++)
-   input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
-  
-  principal->X2P(input_data,data_PCA);
-  
-  int firstbin=-42;
-  //Binning 1st PC
-  for (int m = 0 ; m < nbins1 ; m++)
+    T_Gauss->Branch(Form("data_Gauss_%s",layer[l].c_str()),&data_Gauss[l],Form("data_Gauss_%s/D",layer[l].c_str()));
+    T_Gauss->Branch("eventNumber",&eventNumber,"eventNumber/I");
+  }
+
+  cout<<"--- Uniformization/Gaussianization"<<endl;
+  for(int event=0;event<read_inputTree->GetEntries();event++)
+  {
+    read_inputTree->GetEntry(event);
+    eventNumber=event;
+
+    double E  = read_inputTree->GetVariable("TruthE");
+    double px = read_inputTree->GetVariable("TruthPx");
+    double py = read_inputTree->GetVariable("TruthPy");
+    double pz = read_inputTree->GetVariable("TruthPz");
+
+    TLorentzVector tlv;  tlv.SetPxPyPzE(px,py,pz,E);
+    bool pass_eta=0;
+    if(!m_apply_etacut) pass_eta=1;
+    if(m_apply_etacut)  pass_eta=(fabs(tlv.Eta())>m_cut_eta_low && fabs(tlv.Eta())<m_cut_eta_high);
+    if(pass_eta)
+    {
+      double total_e=read_inputTree->GetVariable("total_cell_energy");
+      for(unsigned int l=0;l<layer.size();l++)
+      {
+        double data = 0.;
+        //double data_uniform;
+
+        if(l==layer.size()-1)
+          data = total_e;
+        else
+          data = read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/total_e;
+
+        //Uniformization
+        double cumulant = get_cumulant(data,cumul_data[l]);
+        cumulant = TMath::Min(cumulant,1.-10e-10);
+        cumulant = TMath::Max(cumulant,0.+10e-10);
+        //data_uniform = cumulant;
+
+        //Gaussianization
+        double maxErfInvArgRange = 0.99999999;
+        double arg = 2.0*cumulant - 1.0;
+        arg = TMath::Min(+maxErfInvArgRange,arg);
+        arg = TMath::Max(-maxErfInvArgRange,arg);
+        data_Gauss[l] = 1.414213562*TMath::ErfInverse(arg);
+
+      } //for layers
+
+      //Add this datapoint to the PCA
+      principal->AddRow(data_Gauss);
+      T_Gauss->Fill();
+
+    } //pass eta
+    if(event%2000==0) cout<<event<<" from "<<read_inputTree->GetEntries()<<" done "<<endl;
+  } //event loop
+
+  cout<<"--- MakePrincipals()"<<endl;
+  principal->MakePrincipals();
+
+  cout<<"--- PCA Results"<<endl;
+  principal->Print("MSE");
+
+  cout<<"--- PCA application and binning of first principal component"<<endl;
+
+  TreeReader* tree_Gauss = new TreeReader();
+  tree_Gauss->SetTree(T_Gauss);
+
+  int Bin_1stPC1=0;
+  int Bin_1stPC2=0;
+
+  TH1D* hPCA_first_component = new TH1D("hPCA_first_component","hPCA_first_component",10000,-20,20);
+
+  for(int event=0;event<tree_Gauss->GetEntries();event++)
   {
-   if( m==0 && data_PCA[0] <= yq[0])
-    firstbin = 0;
-   if(m > 0 && data_PCA[0] > yq[m-1] && data_PCA[0] <= yq[m])
-    firstbin = m;
+    tree_Gauss->GetEntry(event);
+
+    double* data_PCA = new double[layer.size()];
+    double* input_data = new double[layer.size()];
+
+    for (unsigned int l=0;l<layer.size(); l++)
+      input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
+
+    principal->X2P(input_data,data_PCA);  
+    hPCA_first_component->Fill(data_PCA[0]); 
   }
-  
-  h_compo1[firstbin]->Fill(data_PCA[1]);
-  
- }
 
- std::vector<std::vector<double> > yq2d (nbins1, std::vector<double>(nbins2));
- 
- for(int m=0;m<nbins1;m++)
- {
- 	if(debug) cout<<"now do m "<<m<<endl;
-  double xq2[nbins2]; double yq2[nbins2];
-  quantiles( h_compo1[m], nbins2, xq2 , yq2);
-  if(debug) cout<<"1stPCA bin# "<<m<<" Events "<<h_compo1[m]->Integral()<<endl;
-  for (int u = 0; u < nbins2 ; u++)
+  cout<<"--- Binning 1st Principal Component" <<endl;
+  double xq[m_nbins1]; double yq[m_nbins1];
+
+  //2D binning:
+  quantiles( hPCA_first_component, m_nbins1, xq , yq );
+  for (int m = 0; m < m_nbins1 ; m++)
   {
-   int a=0;
- 	 if(u>0) a=h_compo1[m]->FindBin(yq2[u-1]);
- 	 int b=h_compo1[m]->FindBin(yq2[u]);
-   cout<<"Quantile # "<<u<<"  "<<xq2[u]<<" "<<yq2[u]<<" -> Events "<<h_compo1[m]->Integral(a,b-1)<<endl;
+    int a=1;
+    if(m>0) a=hPCA_first_component->FindBin(yq[m-1]);
+    int b=hPCA_first_component->FindBin(yq[m]);
+    cout<<"Quantiles "<<m+1<<"  "<<xq[m]<<" "<<yq[m]<<" -> Events "<<hPCA_first_component->Integral(a,b-1)<<endl;
   }
-  
-  for(int u=0;u<nbins2;u++)
-   yq2d[m][u]=yq2[u];
- }
- 
- cout<<"--- Fill a tree that has the bin information"<<endl;
- int firstPCAbin;
- double* data = new double[layer.size()];
- TTree* tree_1stPCA=new TTree(Form("tree_1stPCA"),Form("tree_1stPCA"));
- tree_1stPCA->Branch("firstPCAbin",&firstPCAbin,"firstPCAbin/I");
- for(unsigned int l=0;l<layer.size();l++)
-  tree_1stPCA->Branch(Form("energy_%s",layer[l].c_str()),&data[l],Form("energy_%s/D",layer[l].c_str()));
- 
- for(int event=0;event<entries_Gauss;event++)
- {
-  tree_Gauss->GetEntry(event);
-  double* data_PCA = new double[layer.size()];
-  double* input_data = new double[layer.size()];
-  int eventNumber=tree_Gauss->GetVariable("eventNumber");
-  
-  for(unsigned int l=0; l<layer.size();l++)
-   input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
-  
-  //PCA Application
-  principal->X2P(input_data,data_PCA);
-  
-  //Binning 1st and 2nd PC
-  for(int m = 0 ; m < nbins1 ; m++)
+
+  std::vector<TH1D*> h_compo1;
+  for(int m=0;m<m_nbins1;m++)
+    h_compo1.push_back(new TH1D(Form("h_compo1_bin%i",m),Form("h_compo1_bin%i",m),20000,-20,20));
+
+  cout<<"--- PCA application and binning 2nd principal component"<<endl;
+  for(int event=0;event<tree_Gauss->GetEntries();event++)
   {
-   if(m==0 && data_PCA[0]<=yq[m])
-   {
-    Bin_1stPC1 = 0;
-    for(int u=0;u<nbins2;u++)
+    tree_Gauss->GetEntry(event);
+    double* data_PCA = new double[layer.size()];
+    double* input_data = new double[layer.size()];
+
+    for (unsigned int l=0;l<layer.size();l++)
+      input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
+
+    principal->X2P(input_data,data_PCA);
+
+    int firstbin=-42;
+    //Binning 1st PC
+    for(int m = 0 ; m < m_nbins1 ; m++)
     {
-     if(u==0 && data_PCA[1]<=yq2d[0][u])
-      Bin_1stPC2 = 0;
-     if(u>0 && data_PCA[1]>yq2d[0][u-1] && data_PCA[1]<=yq2d[0][u])
-      Bin_1stPC2 = u;
+      if(m==0 && data_PCA[0] <= yq[0])
+        firstbin = 0;
+      if(m > 0 && data_PCA[0] > yq[m-1] && data_PCA[0] <= yq[m])
+        firstbin = m;
+    }
+
+    if (firstbin >= 0) h_compo1[firstbin]->Fill(data_PCA[1]);
+
+  }
+
+  // non-standard
+  //double yq2d[m_nbins1][m_nbins2];
+  std::vector<std::vector<double> > yq2d (m_nbins1, std::vector<double>(m_nbins2));
+
+  for(int m=0;m<m_nbins1;m++)
+  {
+    if(m_debuglevel) cout<<"now do m "<<m<<endl;
+    double xq2[m_nbins2]; double yq2[m_nbins2];
+    quantiles( h_compo1[m], m_nbins2, xq2 , yq2);
+    if(m_debuglevel) {
+      cout<<"1stPCA bin# "<<m<<" Events "<<h_compo1[m]->Integral()<<endl;
     }
-   }
-   if(m>0 && data_PCA[0]>yq[m-1] && data_PCA[0]<=yq[m])
-   {
-    Bin_1stPC1 = m;
-    for(int u=0;u<nbins2;u++)
+
+    for (int u = 0; u < m_nbins2 ; u++)
     {
-     if(u==0 && data_PCA[1]<=yq2d[m][u])
-      Bin_1stPC2 = 0;
-     if(u>0 && data_PCA[1]>yq2d[m][u-1] && data_PCA[1]<=yq2d[m][u])
-      Bin_1stPC2 = u;
+      int a=0;
+      if(u>0) a=h_compo1[m]->FindBin(yq2[u-1]);
+      int b=h_compo1[m]->FindBin(yq2[u]);
+      cout<<"Quantile # "<<u<<"  "<<xq2[u]<<" "<<yq2[u]<<" -> Events "<<h_compo1[m]->Integral(a,b-1)<<endl;
     }
-   }   
+
+    for(int u=0;u<m_nbins2;u++)
+      yq2d[m][u]=yq2[u];
   }
-  
-  firstPCAbin=Bin_1stPC1+nbins1*Bin_1stPC2;
-    
-  //find the energy fractions and total energy for that given event
-  read_inputTree->GetEntry(eventNumber);
+
+  // cleanup
+  for (auto it = h_compo1.begin(); it != h_compo1.end(); ++it)
+    delete *it;
+  h_compo1.clear();
+
+  cout<<"--- Fill a tree that has the bin information"<<endl;
+  int firstPCAbin;
+  double* data = new double[layer.size()];
+  TTree* tree_1stPCA=new TTree(Form("tree_1stPCA"),Form("tree_1stPCA"));
+  tree_1stPCA->Branch("firstPCAbin",&firstPCAbin,"firstPCAbin/I");
   for(unsigned int l=0;l<layer.size();l++)
+    tree_1stPCA->Branch(Form("energy_%s",layer[l].c_str()),&data[l],Form("energy_%s/D",layer[l].c_str()));
+
+  for(int event=0;event<tree_Gauss->GetEntries();event++)
   {
-   if(l==layer.size()-1)
-   	data[l] = read_inputTree->GetVariable("total_cell_energy");
-   else
-    data[l] = read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/read_inputTree->GetVariable("total_cell_energy");
-  }
-  
-  tree_1stPCA->Fill();
-  
- } //for events in gauss
- 
- //add a histogram that holds the relevant layer:
- 
- int totalbins=nbins1*nbins2;
- 
- TH2I* h_layer=new TH2I("h_layer","h_layer",totalbins,-0.5,totalbins-0.5,25,-0.5,24.5);
- h_layer->GetXaxis()->SetTitle("PCA bin");
- h_layer->GetYaxis()->SetTitle("Layer");
- for(int b=0;b<totalbins;b++)
- {
-  for(int l=0;l<25;l++)
+    tree_Gauss->GetEntry(event);
+    double* data_PCA = new double[layer.size()];
+    double* input_data = new double[layer.size()];
+    int eventNumber=tree_Gauss->GetVariable("eventNumber");
+
+    for(unsigned int l=0; l<layer.size();l++)
+      input_data[l] = tree_Gauss->GetVariable(Form("data_Gauss_%s",layer[l].c_str()));
+
+    //PCA Application
+    principal->X2P(input_data,data_PCA);
+
+    //Binning 1st and 2nd PC
+    for(int m = 0 ; m < m_nbins1 ; m++)
+    {
+      if(m==0 && data_PCA[0]<=yq[m])
+      {
+        Bin_1stPC1 = 0;
+        for(int u=0;u<m_nbins2;u++)
+        {
+          if(u==0 && data_PCA[1]<=yq2d[0][u])
+            Bin_1stPC2 = 0;
+          if(u>0 && data_PCA[1]>yq2d[0][u-1] && data_PCA[1]<=yq2d[0][u])
+            Bin_1stPC2 = u;
+        }
+      }
+      if(m>0 && data_PCA[0]>yq[m-1] && data_PCA[0]<=yq[m])
+      {
+        Bin_1stPC1 = m;
+        for(int u=0;u<m_nbins2;u++)
+        {
+          if(u==0 && data_PCA[1]<=yq2d[m][u])
+            Bin_1stPC2 = 0;
+          if(u>0 && data_PCA[1]>yq2d[m][u-1] && data_PCA[1]<=yq2d[m][u])
+            Bin_1stPC2 = u;
+        }
+      }   
+    }
+
+    firstPCAbin=Bin_1stPC1+m_nbins1*Bin_1stPC2+1;
+
+    //find the energy fractions and total energy for that given event
+    read_inputTree->GetEntry(eventNumber);
+    for(unsigned int l=0;l<layer.size();l++)
+    {
+      if(l==layer.size()-1)
+        data[l] = read_inputTree->GetVariable("total_cell_energy");
+      else
+        data[l] = read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/read_inputTree->GetVariable("total_cell_energy");
+    }
+
+    tree_1stPCA->Fill();
+
+  } //for events in gauss
+
+  //add a histogram that holds the relevant layer:
+
+  int totalbins=m_nbins1*m_nbins2;
+
+  TH2I* h_layer=new TH2I("h_layer","h_layer",totalbins,0.5,totalbins+0.5,25,-0.5,24.5);
+  h_layer->GetXaxis()->SetTitle("PCA bin");
+  h_layer->GetYaxis()->SetTitle("Layer");
+  for(int b=0;b<totalbins;b++)
   {
-   int is_relevant=0;
-   for(unsigned int i=0;i<layerNr.size();i++)
-   {
-   	if(l==layerNr[i]) is_relevant=1;
-   }
-   h_layer->SetBinContent(b+1,l+1,is_relevant);
+    for(int l=0;l<25;l++)
+    {
+      int is_relevant=0;
+      for(unsigned int i=0;i<layerNr.size();i++)
+      {
+        if(l==layerNr[i]) is_relevant=1;
+      }
+      h_layer->SetBinContent(b+1,l+1,is_relevant);
+    }
   }
- }
- 
- //Output file:
- TFile* output=new TFile(Form("output/firstPCA_%s_nbins1st%i_nbins2nd%i.root",label.c_str(),nbins1,nbins2),"RECREATE");
- output->Add(h_layer);
- output->Add(tree_1stPCA);
- output->Write();
- 
- cout<<"1st PCA is done. Output file: "<<output->GetName()<<endl;
- 
- return output->GetName();
- 
-} //run()
 
-vector<TH1D*> firstPCA::get_cumul_data(vector<string> layer, vector<TH1D*> histos_data)
+  TFile* output=new TFile(m_outfilename.c_str(),"RECREATE");
+  output->Add(h_layer);
+  output->Add(tree_1stPCA);
+  output->Write();
+
+  cout<<"1st PCA is done. Output file: "<<m_outfilename<<endl;
+
+  // cleanup
+  delete read_inputTree;
+  delete tree_Gauss;
+
+} // run
+
+vector<TH1D*> firstPCA::get_cumul_histos(vector<string> layer, vector<TH1D*> histos)
 {
- 
- vector<TH1D*> cumul;
- 
- for(unsigned int i=0;i<histos_data.size();i++)
- {
- 	TH1D* h_cumul=(TH1D*)histos_data[i]->Clone(Form("h_cumul_%s",layer[i].c_str()));
- 	for (int b=1; b<=h_cumul->GetNbinsX(); b++)
+
+  vector<TH1D*> cumul;
+
+  for(unsigned int i=0;i<histos.size();i++)
   {
-   h_cumul->SetBinContent(b,histos_data[i]->Integral(1,b));
+    TH1D* h_cumul=(TH1D*)histos[i]->Clone(Form("h_cumul_%s",layer[i].c_str()));
+    for (int b=1; b<=h_cumul->GetNbinsX(); b++)
+    {
+      h_cumul->SetBinContent(b,histos[i]->Integral(1,b));
+      h_cumul->SetBinError(b,0);
+    }
+    cumul.push_back(h_cumul);
   }
-  cumul.push_back(h_cumul);
- }
 
- return cumul;
- 
+  return cumul;
+
 }
 
-vector<TH1D*> firstPCA::get_histos_data(vector<int> layerNr, vector<string> layer, TreeReader* read_inputTree, TTree* InputTree, int numberfinebins)
+vector<TH1D*> firstPCA::get_relevantlayers_inputs(vector<int> &layerNr, TreeReader* read_inputTree)
 {
- 
- vector<TH1D*> data;
- 
- //get the maxima per layer:
- vector<double> MaxInputs;
- for(unsigned int l=0;l<layerNr.size();l++) MaxInputs.push_back(0.0);
- 
- for(int event=0;event<read_inputTree->GetEntries();event++)
- {
- 	read_inputTree->GetEntry(event);
-  for(unsigned int l=0;l<layerNr.size();l++)
+
+  int NLAYER=25;
+
+  vector<TH1D*>  data;
+  vector<double> MaxInputs;
+  vector<double> MinInputs;
+
+  double max_e=0.0;
+  double min_e=100000000;
+
+  vector<double> sum_efraction;
+  for(int l=0;l<NLAYER;l++)
   {
-   double efraction = read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/read_inputTree->GetVariable("total_cell_energy");
-   if(efraction>MaxInputs[l])
-    MaxInputs[l]=efraction;
+    sum_efraction.push_back(0.0);
+    MaxInputs.push_back(0.0);
+    MinInputs.push_back(1000000.0);
   }
- }
- 
- for(unsigned int l=0; l<layer.size(); l++)
- {
- 	TH1D* h_data;
-  if(l==layer.size()-1)  //Total energy
+
+  int N_pass_eta=0;
+  for(int event=0;event<read_inputTree->GetEntries();event++ )
   {
-   h_data=new TH1D(Form("h_data_%s",layer[l].c_str()),Form("h_data_%s",layer[l].c_str()),numberfinebins,InputTree->GetMinimum("total_cell_energy"),InputTree->GetMaximum("total_cell_energy"));
-   for(int event=0;event<read_inputTree->GetEntries();event++)
-   {
     read_inputTree->GetEntry(event);
-    h_data->Fill(read_inputTree->GetVariable("total_cell_energy"));
-   }
+    double E  = read_inputTree->GetVariable("TruthE");
+    double px = read_inputTree->GetVariable("TruthPx");
+    double py = read_inputTree->GetVariable("TruthPy");
+    double pz = read_inputTree->GetVariable("TruthPz");
+    TLorentzVector tlv; tlv.SetPxPyPzE(px,py,pz,E);
+    bool pass_eta=0;
+    if(!m_apply_etacut) pass_eta=1;
+    if(m_apply_etacut)  pass_eta=(fabs(tlv.Eta())>m_cut_eta_low && fabs(tlv.Eta())<m_cut_eta_high);
+    if(pass_eta)
+    {
+      N_pass_eta++;
+      double total_e=read_inputTree->GetVariable("total_cell_energy");
+      for(int l=0;l<NLAYER;l++)
+      {
+        double efraction = read_inputTree->GetVariable(Form("cell_energy[%d]",l))/total_e;
+        sum_efraction[l] += efraction;
+        if(efraction>MaxInputs[l]) MaxInputs[l]=efraction;
+        if(efraction<MinInputs[l]) MinInputs[l]=efraction;
+        if(total_e>max_e) max_e=total_e;
+        if(total_e<min_e) min_e=total_e;
+      }
+    }
+    if(event%2000==0) cout<<event<<" from "<<read_inputTree->GetEntries()<<" done"<<endl;
   }
-  else  //Efraction Per Layer
+
+  cout<<"rel. layer"<<endl;
+
+  for(int l=0;l<NLAYER;l++)
   {
-   h_data = new TH1D(Form("h_data_%s",layer[l].c_str()),Form("h_data_%s",layer[l].c_str()),numberfinebins,0,MaxInputs[l]);
-   for(int event=0;event<read_inputTree->GetEntries();event++ )
-   {
-    read_inputTree->GetEntry(event);
-    h_data->Fill( read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/read_inputTree->GetVariable("total_cell_energy") );
-   }
+    if(N_pass_eta>0)
+    {
+      if(sum_efraction[l]/N_pass_eta>=m_edepositcut)
+      {
+        layerNr.push_back(l);
+        cout<<"Layer "  <<l <<" is relevant! sum_efraction= "<<sum_efraction[l]<<" sum/entries= "<<sum_efraction[l]/N_pass_eta<<endl;
+      }
+    }
   }
-  
-  h_data->Sumw2();
-  h_data->Scale(1.0/h_data->Integral());
-  data.push_back(h_data);
- } //for layer
- 
- return data;
- 
-}
 
+  for(unsigned int k=0;k<layerNr.size();k++)
+    cout<<"Relevant "<<layerNr[k]<<endl;
 
-vector<int> firstPCA::get_relevantlayers(TreeReader* read_inputTree, double cut_edeposit)
-{
- 
- double sum_efraction[25];
- for(int i=0;i<25;i++) sum_efraction[i]=0.0;
- 
- for(int event=0;event<read_inputTree->GetEntries();event++ )
- {
-  read_inputTree->GetEntry(event);
-  for (int j=0 ; j<25 ; j++)
+  cout<<"init data histos"<<endl;
+
+  for(int l=0;l<NLAYER;l++)
   {
-   double efraction = read_inputTree->GetVariable(Form("cell_energy[%d]",j))/read_inputTree->GetVariable("total_cell_energy");
-   sum_efraction[j] += efraction;
+    int is_rel=0;
+    for(unsigned int k=0;k<layerNr.size();k++)
+    {
+      if(l==layerNr[k])
+        is_rel=1;
+    }
+    if(is_rel)
+    {
+      TH1D* h_data=new TH1D(Form("h_data_layer%i",l),Form("h_data_layer%i",l),m_numberfinebins,MinInputs[l],MaxInputs[l]);
+      h_data->Sumw2();
+      data.push_back(h_data);
+    }
   }
- }
- 
- vector<int> Relevant_Layers;
- for (int i=0; i<25 ; i++)
- {
-  if(sum_efraction[i]/read_inputTree->GetEntries() >= cut_edeposit)
+  TH1D* h_data_total=new TH1D("h_data_totalE","h_data_totalE",m_numberfinebins,min_e,max_e);
+  data.push_back(h_data_total);
+
+  cout<<"fill data histos"<<endl;
+
+  for(int event=0;event<read_inputTree->GetEntries();event++)
   {
-   Relevant_Layers.push_back(i);
-   cout<<"Layer "  <<i <<" is relevant! sum_efraction= "<<sum_efraction[i]<<" sum/entries= "<<sum_efraction[i]/read_inputTree->GetEntries()<<endl;
+    read_inputTree->GetEntry(event);
+    TLorentzVector tlv;  tlv.SetPxPyPzE(read_inputTree->GetVariable("TruthPx"),read_inputTree->GetVariable("TruthPy"),read_inputTree->GetVariable("TruthPz"),read_inputTree->GetVariable("TruthE"));
+    bool pass_eta=0;
+    if(!m_apply_etacut) pass_eta=1;
+    if(m_apply_etacut)  pass_eta=(fabs(tlv.Eta())>m_cut_eta_low && fabs(tlv.Eta())<m_cut_eta_high);
+    if(pass_eta)
+    {
+      double total_e=read_inputTree->GetVariable("total_cell_energy");
+      ((TH1D*)data[data.size()-1])->Fill(total_e);
+      for(unsigned int l=0;l<layerNr.size();l++)
+      {
+        ((TH1D*)data[l])->Fill(read_inputTree->GetVariable(Form("cell_energy[%d]",layerNr[l]))/total_e);
+      }
+    }
+    if(event%2000==0) cout<<event<<" from "<<read_inputTree->GetEntries()<<" done"<<endl;
   }
- }
   
- return Relevant_Layers;
+  for(unsigned int l=0;l<data.size();l++)
+  {
+    ((TH1D*)data[l])->Scale(1.0/data[l]->Integral());
+  }
   
+  return data;
+ 
 }
 
 
-
 double firstPCA::get_cumulant(double x, TH1D* h)
 {
-    
-    //Cumulant "à la TMVA"
-    
-    int nbin = h->GetNbinsX();
-    int bin = h->FindBin(x);
-    bin = TMath::Max(bin,1);
-    bin = TMath::Min(bin,h->GetNbinsX());
-    
-    
-    double AvNuEvPerBin;
-    double Tampon = 0 ;
-    for (int i=1; i<=nbin; i++) {
-        Tampon += h->GetBinContent(i);
-    }
-    
-    AvNuEvPerBin = Tampon/nbin;
-    
-    double cumulant;
-    double x0, x1, y0, y1;
-    double total = h->GetNbinsX()*AvNuEvPerBin;
-    double supmin = 0.5/total;
-    
-    x0 = h->GetBinLowEdge(TMath::Max(bin,1));
-    x1 = h->GetBinLowEdge(TMath::Min(bin,h->GetNbinsX())+1);
-    
-    y0 = h->GetBinContent(TMath::Max(bin-1,0)); // Y0 = F(x0); Y0 >= 0
-    y1 = h->GetBinContent(TMath::Min(bin, h->GetNbinsX()+1));  // Y1 = F(x1);  Y1 <= 1
-    
-    //Zero bin
-    if (bin == 0) {
-        y0 = supmin;
-        y1 = supmin;
-    }
-    if (bin == 1) {
-        y0 = supmin;
-    }
-    if (bin > h->GetNbinsX()) {
-        y0 = 1.-supmin;
-        y1 = 1.-supmin;
-    }
-    if (bin == h->GetNbinsX()) {
-        y1 = 1.-supmin;
-    }
-    
-    ////////////////////////
-    
-    if (x0 == x1) {
-        cumulant = y1;
-    } else {
-        cumulant = y0 + (y1-y0)*(x-x0)/(x1-x0);
-    }
-    
-    if (x <= h->GetBinLowEdge(1)){
-        cumulant = supmin;
-    }
-    if (x >= h->GetBinLowEdge(h->GetNbinsX()+1)){
-        cumulant = 1-supmin;
-    }
-    
-    return cumulant;
-    
+
+  //Cumulant "à la TMVA"
+
+  int nbin = h->GetNbinsX();
+  int bin = h->FindBin(x);
+  bin = TMath::Max(bin,1);
+  bin = TMath::Min(bin,h->GetNbinsX());
+
+
+  double AvNuEvPerBin;
+  double Tampon = 0 ;
+  for (int i=1; i<=nbin; i++) {
+    Tampon += h->GetBinContent(i);
+  }
+
+  AvNuEvPerBin = Tampon/nbin;
+
+  double cumulant;
+  double x0, x1, y0, y1;
+  double total = h->GetNbinsX()*AvNuEvPerBin;
+  double supmin = 0.5/total;
+
+  x0 = h->GetBinLowEdge(TMath::Max(bin,1));
+  x1 = h->GetBinLowEdge(TMath::Min(bin,h->GetNbinsX())+1);
+
+  y0 = h->GetBinContent(TMath::Max(bin-1,0)); // Y0 = F(x0); Y0 >= 0
+  y1 = h->GetBinContent(TMath::Min(bin, h->GetNbinsX()+1));  // Y1 = F(x1);  Y1 <= 1
+
+  //Zero bin
+  if (bin == 0) {
+    y0 = supmin;
+    y1 = supmin;
+  }
+  if (bin == 1) {
+    y0 = supmin;
+  }
+  if (bin > h->GetNbinsX()) {
+    y0 = 1.-supmin;
+    y1 = 1.-supmin;
+  }
+  if (bin == h->GetNbinsX()) {
+    y1 = 1.-supmin;
+  }
+
+  ////////////////////////
+
+  if (x0 == x1) {
+    cumulant = y1;
+  } else {
+    cumulant = y0 + (y1-y0)*(x-x0)/(x1-x0);
+  }
+
+  if (x <= h->GetBinLowEdge(1)){
+    cumulant = supmin;
+  }
+  if (x >= h->GetBinLowEdge(h->GetNbinsX()+1)){
+    cumulant = 1-supmin;
+  }
+
+  return cumulant;
+
 }
 
 
 void firstPCA::quantiles(TH1D* h, int nq, double* xq, double* yq)
 {
-    
-    //Function for quantiles
-    // h Input histo
-    // nq number of quantiles
-    // xq position where to compute the quantiles in [0,1]
-    // yq array to contain the quantiles
-    
-    for (int i=0;i<nq;i++)
-    {
-      xq[i] = double(i+1)/nq;
-      h->GetQuantiles(nq,yq,xq);
-    }
-    
+
+  //Function for quantiles
+  // h Input histo
+  // nq number of quantiles
+  // xq position where to compute the quantiles in [0,1]
+  // yq array to contain the quantiles
+
+  for (int i=0;i<nq;i++)
+  {
+    xq[i] = double(i+1)/nq;
+    h->GetQuantiles(nq,yq,xq);
+  }
+
 }
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx
index 66e2372fb7eb45496fe6e8069c24f47c069e51ae..85b1cc5ce3e760cac0cd873a9548485f74cb67fa 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/Root/secondPCA.cxx
@@ -2,8 +2,12 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
+using namespace std;
+#include "TMatrixF.h"
 #include "TMatrixD.h"
-#include "TVectorD.h"
+#include "TMatrixDSym.h"
+#include "TMatrixDSymEigen.h"
+#include "TVectorF.h"
 #include "TH1D.h"
 #include "TFile.h"
 #include "TROOT.h"
@@ -18,72 +22,157 @@
 #include "ISF_FastCaloSimParametrization/secondPCA.h"
 #include "ISF_FastCaloSimParametrization/firstPCA.h"
 #include "ISF_FastCaloSimParametrization/TreeReader.h"
+#include "ISF_FastCaloSimParametrization/TFCSFunction.h"
+#include "ISF_FastCaloSimEvent/TFCS1DFunction.h"
+//#include "ISF_FastCaloSimParametrization/TFCS1DFunction.h"
+#include "ISF_FastCaloSimParametrization/IntArray.h"
 
 #include <iostream>
+#include <sstream>
 
-using namespace std;
+secondPCA::secondPCA(string firstpcafilename, string outfilename)
+{
+ m_firstpcafilename=firstpcafilename;
+ m_outfilename=outfilename;
+ 
+ m_numberfinebins   =5000;
+ m_storeDetails     =0;
+ m_PCAbin           =-1; //-1 means all bins
+ m_skip_regression  =0;
+ m_neurons_start    =2;
+ m_neurons_end      =8;
+ m_ntoys            =1000;
+ m_maxdev_regression=5;
+ m_maxdev_smartrebin=5;
+}
 
-secondPCA::secondPCA()
+void secondPCA::set_cut_maxdeviation_regression(double val)
 {
- 
+ m_maxdev_regression=val;
 }
 
-void secondPCA::run(string inputfile, string label, int nbins1, int nbins2, int numberfinebins)
+void secondPCA::set_cut_maxdeviation_smartrebin(double val)
+{
+ m_maxdev_smartrebin=val;
+}
+
+void secondPCA::set_Ntoys(int val)
+{
+ m_ntoys=val;
+}
+
+void secondPCA::set_neurons_iteration(int start,int end)
+{
+ m_neurons_start=start;
+ m_neurons_end=end;
+}
+
+void secondPCA::set_storeDetails(int flag)
+{
+ m_storeDetails=flag;
+}
+
+void secondPCA::set_cumulativehistobins(int bins)
+{
+ m_numberfinebins=bins;
+}
+
+void secondPCA::set_PCAbin(int bin)
+{
+ m_PCAbin=bin;
+}
+
+void secondPCA::set_skip_regression(int flag)
+{
+ m_skip_regression=flag;
+}
+
+void secondPCA::run()
 {
  
  //Open inputfile:
+ TFile* inputfile=TFile::Open(m_firstpcafilename.c_str(),"READ");
+ if(!inputfile) {
+   cout<<"ERROR: Inputfile could not be opened"<<endl;
+   // I don't think we can continue...
+   return;
+ }
+ 
+ int nbins; int nbins0=1;
+ vector<int> layerNr=getLayerBins(inputfile, nbins);
+ //if a specific PCA bin was set,check if this is available, and set nbins to that
+ if(m_PCAbin>0)
+ {
+ 	if(m_PCAbin<=nbins)
+ 	{
+ 	 nbins =m_PCAbin;
+ 	 nbins0=m_PCAbin;
+ 	 string binlabel=Form("_bin%i",m_PCAbin);
+   m_outfilename=m_outfilename+binlabel;
+ 	}
+ 	else cout<<"ERROR: The PCA bin you set is not available"<<endl;
+ }
+ 
+ vector<string> layer;
+ for(unsigned int l=0;l<layerNr.size();l++)
+  layer.push_back(Form("layer%i",layerNr[l]));
+ layer.push_back("totalE");
+ 
+ int* samplings=new int[layerNr.size()];
+ for(unsigned int i=0;i<layerNr.size();i++)
+  samplings[i]=layerNr[i];
+ 
  cout<<endl;
  cout<<"****************"<<endl;
  cout<<"     2nd PCA"<<endl;
  cout<<"****************"<<endl;
  cout<<endl;
- cout<<"--- Open input file "<<inputfile<<endl;
- TFile* file=TFile::Open(inputfile.c_str());
- if(!file) cout<<"ERROR: Inputfile could not be opened"<<endl;
- 
+ cout<<"Now running 2nd PCA with the following parameters:"<<endl;
+ cout<<"   Input file (1st PCA): "<<m_firstpcafilename<<endl;
+ cout<<"   Number of bins of the cumulative histos: "<<m_numberfinebins<<endl;
+ cout<<"   storeDetails: "<<m_storeDetails<<endl;
+ cout<<"   PCA bin number(s): ";
+ for(int b=nbins0;b<=nbins;b++) cout<<b<<" "; cout<<endl;
+ cout<<"   skip regression: "<<m_skip_regression<<endl;
+ cout<<"   Regression test toys:" <<m_ntoys<<endl;
+ cout<<"   Neurons in the regression iteration:" <<m_neurons_start<<" - "<<m_neurons_end<<endl;
+ cout<<"   Maximal deviation of approximated histogram (regression):  "<<m_maxdev_regression<<"%"<<endl;
+ cout<<"   Maximal deviation of approximated histogram (smart-rebin): "<<m_maxdev_smartrebin<<"%"<<endl;
+ cout<<endl;
  cout<<"--- Init the TreeReader"<<endl;
- TTree* InputTree = (TTree*)file->Get("tree_1stPCA");
+ TTree* InputTree = (TTree*)inputfile->Get("tree_1stPCA");
  TreeReader* read_inputTree = new TreeReader();
  read_inputTree->SetTree(InputTree);
  
- int nbins;
- vector<int> layerNr=getLayerBins(file, nbins);
- cout<<"Bins: "<<nbins<<endl;
- 
- 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<<layer[l]<<endl;
-
- double* samplings=new double[layerNr.size()];
- for(unsigned int i=0;i<layerNr.size();i++)
+ TFile* output=new TFile(m_outfilename.c_str(),"RECREATE");
+ for(int b=nbins0;b<=nbins;b++)
  {
-  samplings[i]=layerNr[i];
-//  cout<<"i "<<i<<" samplings "<<samplings[i]<<endl;
+  output->mkdir(Form("bin%i",b));
+  output->mkdir(Form("bin%i/pca",b));
+	for(unsigned int l=0;l<layer.size();l++)
+   output->mkdir(Form("bin%i/%s",b,layer[l].c_str()));
  }
- 
- TFile* output=new TFile(Form("output/secondPCA_%s_nbins1st%i_nbins2nd%i.root",label.c_str(),nbins1,nbins2),"RECREATE");
- for(int b=0;b<nbins;b++)
+ output->Write();
+ output->Close();
+
+ for(int b=nbins0;b<=nbins;b++)
  {
   cout<<"--- now performing 2nd PCA in bin "<<b<<endl;
-  do_pca(layer, b, read_inputTree, InputTree, numberfinebins, output, samplings);
+  do_pca(layer, b, read_inputTree, samplings);
  }
- output->Write();
  
- cout<<"2nd PCA outputfile: "<<output->GetName()<<endl;
+ cout<<"2nd PCA is done. Output: "<<m_outfilename<<endl;
+
+ // cleanup
+ delete read_inputTree;
+ delete[] samplings;
  
 }
 
-void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree, TTree* InputTree, int numberfinebins, TFile* output, double *samplings)
+void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree, int* samplings)
 {
  
- TDirectory *cdbin = (TFile*)output->mkdir(Form("bin%i",bin));
- cdbin->cd();
- 
- //make a tree that holds only the events for that bin
+ //make a tree that holds only the events for that 
  TTree* bintree=new TTree("bintree","bintree");
  double* data=new double[layer.size()];
  for(unsigned int l=0;l<layer.size();l++)
@@ -104,10 +193,10 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
  TreeReader* read_bintree = new TreeReader();
  read_bintree->SetTree(bintree);
  
- vector<TH1D*> histos_data=get_histos_data(layer, read_bintree, InputTree, numberfinebins);
- vector<TH1D*> cumul_data=get_cumul_data(layer, histos_data);
+ vector<TH1D*> histos_data=get_histos_data(layer, read_bintree);
+ vector<TH1D*> cumul_data =get_cumul_histos(layer, histos_data);
  
- TPrincipal* principal = new TPrincipal(layer.size(),"ND");
+ TPrincipal* principal = new TPrincipal(layer.size(),"ND"); //ND means normalize cov matrix and store data
  TTree* T_Gauss=new TTree("T_Gauss","T_Gauss");
  double* data_Gauss=new double[layer.size()];
  for(unsigned int l=0;l<layer.size();l++)
@@ -161,11 +250,12 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
    if(data_PCA[l]<data_PCA_min[l]) data_PCA_min[l]=data_PCA[l];
   }
  }
+
  //fill histograms
- TH1D* h_data_PCA[layer.size()];
+ std::vector<TH1D*> h_data_PCA;
  for(unsigned int l=0;l<layer.size();l++)
  {
- 	h_data_PCA[l]=new TH1D(Form("h_data_PCA_%s",layer[l].c_str()),Form("h_data_PCA_%s",layer[l].c_str()),1000,data_PCA_min[l],data_PCA_max[l]);
+ 	h_data_PCA.push_back(new TH1D(Form("h_data_PCA_%s",layer[l].c_str()),Form("h_data_PCA_%s",layer[l].c_str()),1000,data_PCA_min[l],data_PCA_max[l]));
  }
  for(int event=0;event<reader_treeGauss->GetEntries();event++)
  {
@@ -184,35 +274,117 @@ void secondPCA::do_pca(vector<string> layer, int bin, TreeReader* read_inputTree
  {
  	gauss_means[l]=h_data_PCA[l]->GetMean();
  	gauss_rms[l]=h_data_PCA[l]->GetRMS();
- 	//cout<<layer[l]<<" mean "<<gauss_means[l]<<" gauss_rms[l] "<<gauss_rms[l]<<endl;
  }
-  
- delete T_Gauss;
+ 
+ if(m_storeDetails)
+ {
+  TFile* output=TFile::Open(m_outfilename.c_str(),"UPDATE");
+  output->cd(Form("bin%i/",bin));
+  for(unsigned int l=0;l<layer.size();l++)
+  {
+   h_data_PCA[l]->Write(Form("h_PCA_component%i",l));
+   histos_data[l]->Write(Form("h_input_%s",layer[l].c_str()));
+   cumul_data[l]->Write(Form("h_cumul_%s",layer[l].c_str()));
+  }
+  output->Write();
+  output->Close();
+ }
+ 
+ // cleanup
  delete bintree;
+ delete read_bintree;
+ delete reader_treeGauss;
+ delete T_Gauss;
+ delete[] data;
+ delete[] data_Gauss;
+ 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++)
+ {
+  lowerBound[l]=get_lowerBound(cumul_data[l]);
+ }
+ 
+ //Save EigenValues/EigenVectors/CovarianceMatrix in the output file
+ IntArray* myArray=new IntArray((int)(layer.size()-1));
+ myArray->Set(layer.size()-1,samplings);
  
- //Save EigenValues/EigenVectors/CovarianceMatrix
- TMatrixD* CovarianceMatrix =(TMatrixD*)principal->GetCovarianceMatrix();
- TVectorD* EigenValues  =(TVectorD*)principal->GetEigenValues();
  TMatrixD* EigenVectors =(TMatrixD*)principal->GetEigenVectors();
- TVectorD* MeanValues   =(TVectorD*)principal->GetMeanValues();
- TVectorD* SigmaValues  =(TVectorD*)principal->GetSigmas();
- TVectorD* Layers=new TVectorD((int)(layer.size()-1),samplings); 
- TVectorD* Gauss_means=new TVectorD((int)(layer.size()-1),gauss_means); 
- TVectorD* Gauss_rms  =new TVectorD((int)(layer.size()-1),gauss_rms); 
- 
- CovarianceMatrix->Write("CovarianceMatrix");
- EigenValues ->Write("EigenValues");
+ TMatrixD* CovarianceMatrix =(TMatrixD*)principal->GetCovarianceMatrix();
+ TMatrixDSym *symCov=new TMatrixDSym();
+ symCov->Use(CovarianceMatrix->GetNrows(),CovarianceMatrix->GetMatrixArray());  //symCov to be stored!
+ 
+ TVectorD* MeanValues  =(TVectorD*)principal->GetMeanValues();
+ TVectorD* SigmaValues =(TVectorD*)principal->GetSigmas();
+ TVectorD* Gauss_means =new TVectorD((int)(layer.size()),gauss_means); 
+ TVectorD* Gauss_rms   =new TVectorD((int)(layer.size()),gauss_rms); 
+ TVectorD* LowerBounds =new TVectorD((int)(layer.size()),lowerBound); 
+ 
+ TFile* output=TFile::Open(m_outfilename.c_str(),"UPDATE");
+ output->cd(Form("bin%i/pca",bin));
+ symCov->Write("symCov");
  EigenVectors->Write("EigenVectors");
  MeanValues  ->Write("MeanValues");
  SigmaValues ->Write("SigmaValues");
- Layers      ->Write("RelevantLayers");
  Gauss_means ->Write("Gauss_means");
  Gauss_rms   ->Write("Gauss_rms");
+ myArray     ->Write("RelevantLayers");
+ LowerBounds ->Write("LowerBounds");
+ output->Write();
+ output->Close();
  
+ //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;
+  stringstream ss;
+  ss << bin;
+  string binstring = ss.str();
+  TFCS1DFunction* fct=TFCSFunction::Create(cumul_data[l],m_skip_regression,m_neurons_start,m_neurons_end,m_maxdev_regression,m_maxdev_smartrebin,m_ntoys);
+  
+  //Store it:
+  TFile* output=TFile::Open(m_outfilename.c_str(),"UPDATE");
+  output->cd(Form("bin%i/%s/",bin,layer[l].c_str()));
+  fct->Write();
+  output->Write();
+  output->Close();
+  
+ }
+  
 } //do_pca
 
 
-vector<TH1D*> secondPCA::get_histos_data(vector<string> layer, TreeReader* read_bintree, TTree* bintree, int numberfinebins)
+double secondPCA::get_lowerBound(TH1D* h_cumulative)
+{
+ 
+ double range_low=0;
+ int bin_start,bin_end;
+ bin_start=bin_end=-1;
+ 
+ for(int b=1;b<=h_cumulative->GetNbinsX();b++)
+ {
+ 	if(h_cumulative->GetBinContent(b)>0 && bin_start<0)
+ 	{
+ 	 bin_start=b;
+ 	 range_low=(double)(h_cumulative->GetBinContent(b));
+ 	}
+ 	if(h_cumulative->GetBinContent(b)>0.9999999 && bin_end<0)
+ 	{
+ 	 bin_end=b;
+ 	}
+ }
+ 
+ return range_low;
+ 
+}
+
+
+vector<TH1D*> secondPCA::get_histos_data(vector<string> layer, TreeReader* read_bintree)
 {
  
  vector<TH1D*> data;
@@ -221,7 +393,10 @@ vector<TH1D*> secondPCA::get_histos_data(vector<string> layer, TreeReader* read_
  vector<double> MaxInputs;
  for(unsigned int l=0;l<layer.size();l++) MaxInputs.push_back(0.0);
  
- for(int event=0;event<bintree->GetEntries();event++)
+ vector<double> MinInputs;
+ for(unsigned int l=0;l<layer.size();l++) MinInputs.push_back(1000000.0);
+
+ for(int event=0;event<read_bintree->GetEntries();event++)
  {
  	read_bintree->GetEntry(event);
   for(unsigned int l=0;l<layer.size();l++)
@@ -229,13 +404,15 @@ vector<TH1D*> secondPCA::get_histos_data(vector<string> layer, TreeReader* read_
    double val = read_bintree->GetVariable(Form("energy_%s",layer[l].c_str()));
    if(val>MaxInputs[l])
     MaxInputs[l]=val;
+   if(val<MinInputs[l])
+    MinInputs[l]=val;
   }
  }
  
  for(unsigned int l=0; l<layer.size(); l++)
  {
  	TH1D* h_data;
-  h_data = new TH1D(Form("h_data_%s",layer[l].c_str()),Form("h_data_%s",layer[l].c_str()),numberfinebins,0,MaxInputs[l]);
+  h_data = new TH1D(Form("h_data_%s",layer[l].c_str()),Form("h_data_%s",layer[l].c_str()),m_numberfinebins,MinInputs[l],MaxInputs[l]);
   for(int event=0;event<read_bintree->GetEntries();event++)
   {
    read_bintree->GetEntry(event);
@@ -245,6 +422,7 @@ vector<TH1D*> secondPCA::get_histos_data(vector<string> layer, TreeReader* read_
   h_data->Sumw2();
   h_data->Scale(1.0/h_data->Integral());
   data.push_back(h_data);
+  
  } //for layer
  
  return data;
@@ -264,7 +442,6 @@ vector<int> secondPCA::getLayerBins(TFile* file, int &bins)
  	if(h_layer->GetBinContent(1,i)==1) 
  	 layer.push_back(h_layer->GetYaxis()->GetBinCenter(i));
  }
-
  
  bins=h_layer->GetNbinsX();
  
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements
index 34e1c1f846dc56e24d5932b42f91f7a7cdbaabef..4b9a97ad0c1167038a069c646901b2a47e196690 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/cmt/requirements
@@ -24,9 +24,9 @@ use HepPDT                      v*                              LCG_Interfaces
 ######################
 
 use CaloInterface               CaloInterface-*                 Calorimeter
-use CaloGeoHelpers              CaloGeoHelpers-*                Calorimeter
-use BarcodeInterfaces           BarcodeInterfaces-*             Simulation/Barcode
+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
@@ -41,12 +41,12 @@ 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_FastCaloSimEvent        ISF_FastCaloSimEvent-*          Simulation/ISF/ISF_FastCaloSim
 use ISF_FastCaloSimInterfaces   ISF_FastCaloSimInterfaces-*     Simulation/ISF/ISF_FastCaloSim
 
 ####################
@@ -65,16 +65,19 @@ apply_tag ROOTTMVALibs
 apply_tag ROOTTreePlayerLibs
 
 # Create a named installed library
-library ISF_FastCaloSimParametrizationLib "../Root/*.cxx"
+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 FastCaloSim_CaloCell_ID.h TFCSParametrizationBase.h TFCSParametrization.h TFCSEnergyParametrization.h TFCSPCAEnergyParametrization.h TFCSLateralShapeParametrization.h TFCSNNLateralShapeParametrization.h TFCSSimpleLateralShapeParametrization.h TFCSExtrapolationState.h TFCSTruthState.h TFCSSimulationState.h TFCS1DFunction.h TFCS1DFunctionRegression.h TFCS1DFunctionHistogram.h TFCSFunction.h TreeReader.h firstPCA.h secondPCA.h ../Root/LinkDef.h" \ 
+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
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/python/ISF_NativeFastCaloSimJobProperties.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/python/ISF_NativeFastCaloSimJobProperties.py
index 5ba44b4f92452ea26849d7b5c485e4280d760e93..27c63982094d8755852979de1bfd30d4da212cc9 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/python/ISF_NativeFastCaloSimJobProperties.py
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/python/ISF_NativeFastCaloSimJobProperties.py
@@ -10,7 +10,7 @@
 """
 
 __author__ = "KG Tan"
-__version__= "$Revision: 612425 $"
+__version__= "$Revision: 779694 $"
 __doc__    = "ISF_NativeFastCaloSimJobProperties"
 
 __all__    = [ "ISF_NativeFastCaloSimJobProperties" ]
@@ -44,6 +44,11 @@ class CaloCellsName(JobProperty):
     allowedTypes = ['str']
     StoredValue  = 'AllCalo'
 
+class outputFile(JobProperty):
+    statusOn     = False
+    allowedTypes = ['str']
+    StoredValue  = 'ESD_output_test.root'
+
 ##-----------------------------------------------------------------------------
 ## 2nd step
 ## Definition of the InDet flag container
@@ -64,7 +69,7 @@ jobproperties.add_Container(ISF_NativeFastCaloSimJobProperties)
 jobproperties.ISF_NativeFastCaloSimJobProperties.add_JobProperty( NativeFastCaloSimIsActive        )
 jobproperties.ISF_NativeFastCaloSimJobProperties.add_JobProperty( RandomStreamName           )
 jobproperties.ISF_NativeFastCaloSimJobProperties.add_JobProperty( CaloCellsName              )
-
+jobproperties.ISF_NativeFastCaloSimJobProperties.add_JobProperty( outputFile              )
 ##-----------------------------------------------------------------------------
 ## 5th step
 ## short-cut for lazy people
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/setup.sh b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/setup.sh
new file mode 100644
index 0000000000000000000000000000000000000000..efcd73c6ffe7d04e8be81002a3b163052218ce4c
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/setup.sh
@@ -0,0 +1,4 @@
+setupATLAS
+asetup 20.1.0
+svn switch $SVNROOT/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/devbranches/ISF_FastCaloSimParametrization_WorkingBranch
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/prodOptions.ISF_ntuple.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/prodOptions.ISF_ntuple.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad7c74d80f16a1841e2fd074862973cfd890ed9b
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/share/prodOptions.ISF_ntuple.py
@@ -0,0 +1,63 @@
+# production options for running ISF ntuples
+from AthenaCommon.AppMgr import ServiceMgr
+#import AthenaPoolCnvSvc.ReadAthenaPool
+#from PartPropSvc.PartPropSvcConf import PartPropSvc
+#include( "ParticleBuilderOptions/McAOD_PoolCnv_jobOptions.py")
+#include( "EventAthenaPool/EventAthenaPool_joboptions.py" )
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+
+from ISF_FastCaloSimParametrization.ISF_NativeFastCaloSimJobProperties import jobproperties
+from OutputStreamAthenaPool.MultipleStreamManager import MSMgr
+alg = MSMgr.NewRootStream( "StreamNTUP_FastCaloSim", jobproperties.ISF_NativeFastCaloSimJobProperties.outputFile(), "FastCaloSim" )
+
+from ISF_FastCaloSimParametrization.ISF_FastCaloSimParametrizationConf import ISF_HitAnalysis
+alg += ISF_HitAnalysis() 
+
+ISF_HitAnalysis = ISF_HitAnalysis()
+ISF_HitAnalysis.NtupleFileName = 'ISF_HitAnalysis'
+
+##############################
+#ISF_HitAnalysis.CaloBoundaryR = [ 0., 1148., 1148., 0. ]
+#ISF_HitAnalysis.CaloBoundaryZ = [ -3475., -3475., 3475., 3475. ]
+ISF_HitAnalysis.CaloBoundaryR = 1148.0
+ISF_HitAnalysis.CaloBoundaryZ = 3549.5 #before: 3475.0
+ISF_HitAnalysis.CaloMargin=100 #=10cm
+ISF_HitAnalysis.NTruthParticles = 1 # Copy only one truth particle to the ntuples for now
+#ISF_HitAnalysis.OutputLevel = DEBUG
+
+#############################
+##### NEW TRACKING SETUP ####
+#############################
+from TrkExSTEP_Propagator.TrkExSTEP_PropagatorConf import Trk__STEP_Propagator
+niPropagator = Trk__STEP_Propagator()
+niPropagator.MaterialEffects = False 
+ToolSvc+=niPropagator    
+
+from TrkExTools.TimedExtrapolator import TimedExtrapolator
+timedExtrapolator=TimedExtrapolator()
+timedExtrapolator.STEP_Propagator = niPropagator
+timedExtrapolator.ApplyMaterialEffects = False
+ToolSvc+=timedExtrapolator
+
+from CaloTrackingGeometry.CaloTrackingGeometryConf import CaloSurfaceHelper
+caloSurfaceHelper = CaloSurfaceHelper()
+ToolSvc+=caloSurfaceHelper
+
+from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags 
+
+ISF_HitAnalysis.CaloEntrance=TrkDetFlags.InDetContainerName()
+ISF_HitAnalysis.CaloSurfaceHelper=caloSurfaceHelper
+ISF_HitAnalysis.Extrapolator=timedExtrapolator
+
+#############################
+
+from ISF_FastCaloSimParametrization.ISF_FastCaloSimParametrizationConf import FastCaloSimGeometryHelper
+FCSgeoHelper=FastCaloSimGeometryHelper()
+ToolSvc+=FCSgeoHelper
+ISF_HitAnalysis.CaloGeometryHelper=FCSgeoHelper
+
+# Note: don't think I actually need ISF_Geometry as a stream
+# Note: Need to turn ISF_HitAnalysis into a D3PD friendly object
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
index de37734e8a1fc0a0f97e724bb42e45bb88f1753f..5ac7ff959dd9fcf420607736c021cdaac11aacd2 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/CaloGeometry.cxx
@@ -14,7 +14,7 @@
 
 #include "CaloDetDescr/CaloDetDescrElement.h"
 #include "CaloGeoHelpers/CaloSampling.h"
-#include "ISF_FastCaloSimParametrization/FastCaloSim_CaloCell_ID.h"
+#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h"
 //#include "TMVA/Tools.h"
 //#include "TMVA/Factory.h"
 
@@ -207,11 +207,11 @@ void CaloGeometryLookup::post_process()
     m_deta_double=deta();
     m_dphi_double=dphi();
   } else {
-    double rnx=nx_double()-nx();
-    double rny=ny_double()-ny();
-    if(TMath::Abs(rnx)>0.05 || TMath::Abs(rny)>0.05) {
-      cout<<"Grid: Sampling "<<sampling<<"_"<<index()<<": mapping cells into a regular grid, although cells don't fit well"<<endl;
-    }
+    //double rnx=nx_double()-nx();
+    //double rny=ny_double()-ny();
+    //if(TMath::Abs(rnx)>0.05 || TMath::Abs(rny)>0.05) {
+    //  cout<<"Grid: Sampling "<<sampling<<"_"<<index()<<": mapping cells into a regular grid, although cells don't fit well"<<endl;
+    //}
 
     m_cell_grid_eta=TMath::Nint(TMath::Ceil(nx_double()/m_xy_grid_adjustment_factor));
     m_cell_grid_phi=TMath::Nint(TMath::Ceil(ny_double()/m_xy_grid_adjustment_factor));
@@ -262,7 +262,7 @@ 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"<<endl;
 }
 
 float CaloGeometryLookup::calculate_distance_eta_phi(const CaloDetDescrElement* DDE,float eta,float phi,float& dist_eta0,float& dist_phi0)
@@ -516,7 +516,7 @@ void CaloGeometry::PrintMapInfo(int i, int j)
 
 void CaloGeometry::post_process(int sampling)
 {
-  cout<<"post processing sampling "<<sampling<<endl;
+  //cout<<"post processing sampling "<<sampling<<endl;
   bool found_overlap=false;
   for(unsigned int j=0;j<m_cells_in_regions[sampling].size();++j) {
     /*
@@ -1122,8 +1122,8 @@ double CaloGeometry::rpos(int sample,double eta,int subpos) const
   int side=0;
   if(eta>0) side=1;
 
-  if(subpos==SUBPOS_ENT) return m_rent_map[side][sample].find_closest(eta)->second;
-  if(subpos==SUBPOS_EXT) return m_rext_map[side][sample].find_closest(eta)->second;
+  if(subpos==CaloSubPos::SUBPOS_ENT) return m_rent_map[side][sample].find_closest(eta)->second;
+  if(subpos==CaloSubPos::SUBPOS_EXT) return m_rext_map[side][sample].find_closest(eta)->second;
   return m_rmid_map[side][sample].find_closest(eta)->second;
 }
 
@@ -1132,8 +1132,8 @@ double CaloGeometry::zpos(int sample,double eta,int subpos) const
   int side=0;
   if(eta>0) side=1;
 
-  if(subpos==SUBPOS_ENT) return m_zent_map[side][sample].find_closest(eta)->second;
-  if(subpos==SUBPOS_EXT) return m_zext_map[side][sample].find_closest(eta)->second;
+  if(subpos==CaloSubPos::SUBPOS_ENT) return m_zent_map[side][sample].find_closest(eta)->second;
+  if(subpos==CaloSubPos::SUBPOS_EXT) return m_zext_map[side][sample].find_closest(eta)->second;
   return m_zmid_map[side][sample].find_closest(eta)->second;
 }
 
@@ -1143,12 +1143,12 @@ double CaloGeometry::rzpos(int sample,double eta,int subpos) const
   if(eta>0) side=1;
  
   if(isCaloBarrel(sample)) {
-    if(subpos==SUBPOS_ENT) return m_rent_map[side][sample].find_closest(eta)->second;
-    if(subpos==SUBPOS_EXT) return m_rext_map[side][sample].find_closest(eta)->second;
+    if(subpos==CaloSubPos::SUBPOS_ENT) return m_rent_map[side][sample].find_closest(eta)->second;
+    if(subpos==CaloSubPos::SUBPOS_EXT) return m_rext_map[side][sample].find_closest(eta)->second;
     return m_rmid_map[side][sample].find_closest(eta)->second;
   } else {
-    if(subpos==SUBPOS_ENT) return m_zent_map[side][sample].find_closest(eta)->second;
-    if(subpos==SUBPOS_EXT) return m_zext_map[side][sample].find_closest(eta)->second;
+    if(subpos==CaloSubPos::SUBPOS_ENT) return m_zent_map[side][sample].find_closest(eta)->second;
+    if(subpos==CaloSubPos::SUBPOS_EXT) return m_zext_map[side][sample].find_closest(eta)->second;
     return m_zmid_map[side][sample].find_closest(eta)->second;
   }  
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
index f6c32291da4f1ae5a1629d5e5fbdcc7085cf0a17..2e9fe8772b5804c4042bc2fe9f6dd5c3cf298270 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/FastCaloSimCaloExtrapolation.cxx
@@ -11,7 +11,13 @@
 #include "GaudiKernel/IPartPropSvc.h"
 #include "GaudiKernel/ListItem.h"
 
-FastCaloSimCaloExtrapolation::FastCaloSimCaloExtrapolation(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t,n,p),m_CaloBoundaryR(1148.0),m_CaloBoundaryZ(3549.5),m_calomargin(100)
+FastCaloSimCaloExtrapolation::FastCaloSimCaloExtrapolation(const std::string& t, const std::string& n, const IInterface* p) :
+  AthAlgTool(t,n,p),
+  m_CaloBoundaryR(1148.0),
+  m_CaloBoundaryZ(3549.5),
+  m_calomargin(100),
+  m_caloEntrance(0),
+  m_caloEntranceName("")
 {
   declareInterface<IFastCaloSimCaloExtrapolation>(this);
 
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 f5a97b75e6b9c281e76d8cb5b4f52d6d0199c6a7..73598a8543ef119597bf14cd3cd7b5290da3b122 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx
@@ -312,7 +312,7 @@ StatusCode ISF_HitAnalysis::updateMetaData( IOVSVC_CALLBACK_ARGS_P( I, keys ) )
      if( *itr == m_MC_SIM_PARAM ) run_update = true;
      msg() << *itr;
   }
-  msg() << endreq;
+  msg() << endmsg;
   // If that's not the key that we received after all, let's just return
   // silently...
   if( ! run_update ) return StatusCode::SUCCESS;
@@ -1166,7 +1166,7 @@ void ISF_HitAnalysis::extrapolate(const HepMC::GenParticle* part,std::vector<Trk
  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) {
+ for(int subpos=CaloSubPos::SUBPOS_MID;subpos<=CaloSubPos::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);
@@ -1179,7 +1179,7 @@ void ISF_HitAnalysis::extrapolate(const HepMC::GenParticle* part,std::vector<Trk
    // now try to extrpolate to all calo layers, that contain energy
    ATH_MSG_DEBUG("Calo position for particle id "<<m_pdgid<<", trutheta= " << m_ptruth_eta <<", truthphi= "<<m_ptruth_phi<<", truthp="<<m_ptruth_p<<", truthpt="<<m_ptruth_pt);
    for(int sample=CaloCell_ID_FCS::FirstSample;sample<CaloCell_ID_FCS::MaxSample;++sample) {
-     for(int subpos=SUBPOS_MID;subpos<=SUBPOS_EXT;++subpos) {
+     for(int subpos=CaloSubPos::SUBPOS_MID;subpos<=CaloSubPos::SUBPOS_EXT;++subpos) {
        m_letaCalo[sample][subpos]=-12345;
        m_lphiCalo[sample][subpos]=-12345;
        m_lrCalo[sample][subpos]=-12345;
@@ -1200,15 +1200,15 @@ void ISF_HitAnalysis::extrapolate(const HepMC::GenParticle* part,std::vector<Trk
     }
  } //inside calo
  
- m_TTC_back_eta->push_back(eta_safe[SUBPOS_EXT]);
- m_TTC_back_phi->push_back(phi_safe[SUBPOS_EXT]);
- m_TTC_back_r->push_back(r_safe[SUBPOS_EXT]);
- m_TTC_back_z->push_back(z_safe[SUBPOS_EXT]);
+ m_TTC_back_eta->push_back(eta_safe[CaloSubPos::SUBPOS_EXT]);
+ m_TTC_back_phi->push_back(phi_safe[CaloSubPos::SUBPOS_EXT]);
+ m_TTC_back_r->push_back(r_safe[CaloSubPos::SUBPOS_EXT]);
+ m_TTC_back_z->push_back(z_safe[CaloSubPos::SUBPOS_EXT]);
  
- m_TTC_entrance_eta->push_back(eta_safe[SUBPOS_ENT]);
- m_TTC_entrance_phi->push_back(phi_safe[SUBPOS_ENT]);
- m_TTC_entrance_r->push_back(r_safe[SUBPOS_ENT]);
- m_TTC_entrance_z->push_back(z_safe[SUBPOS_ENT]);
+ m_TTC_entrance_eta->push_back(eta_safe[CaloSubPos::SUBPOS_ENT]);
+ m_TTC_entrance_phi->push_back(phi_safe[CaloSubPos::SUBPOS_ENT]);
+ m_TTC_entrance_r->push_back(r_safe[CaloSubPos::SUBPOS_ENT]);
+ m_TTC_entrance_z->push_back(z_safe[CaloSubPos::SUBPOS_ENT]);
 
  ATH_MSG_DEBUG("End extrapolate()");
 }
@@ -1419,7 +1419,7 @@ bool ISF_HitAnalysis::get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector, int
     msg(MSG::DEBUG)<<"  Final par TTC sample "<<sample<<" subpos="<<subpos;
     if(m_layerCaloOK[sample][subpos]) msg()<<" (good)";
      else msg()<<" (bad)";
-    msg()<<" eta=" << m_letaCalo[sample][subpos] << "   phi=" << m_lphiCalo[sample][subpos] <<" m_dCalo="<<m_dCalo[sample][subpos]<<" dist(hit)="<<hitdist<< endreq;
+    msg()<<" eta=" << m_letaCalo[sample][subpos] << "   phi=" << m_lphiCalo[sample][subpos] <<" m_dCalo="<<m_dCalo[sample][subpos]<<" dist(hit)="<<hitdist<< endmsg;
   } 
  
   return m_layerCaloOK[sample][subpos];
@@ -1655,7 +1655,7 @@ bool ISF_HitAnalysis::get_calo_etaphi(std::vector<Trk::HitInfo>* hitVector, Calo
     msg(MSG::DEBUG)<<"  Final par TTC sample "<<(int)sample;
     if(m_layerCaloOK[sample]) msg()<<" (good)";
      else msg()<<" (bad)";
-    msg()<<" eta=" << m_letaCalo[sample] << "   phi=" << m_lphiCalo[sample] <<" m_dCalo="<<m_dCalo[sample]<<" dist(hit)="<<hitdist<< endreq;
+    msg()<<" eta=" << m_letaCalo[sample] << "   phi=" << m_lphiCalo[sample] <<" m_dCalo="<<m_dCalo[sample]<<" dist(hit)="<<hitdist<< endmsg;
   } 
  
   return m_layerCaloOK[sample];
@@ -1701,13 +1701,13 @@ bool ISF_HitAnalysis::get_calo_surface(std::vector<Trk::HitInfo>* hitVector)
         else                    m_d_calo_surf= fabs(m_d_calo_surf/tanh(etaCalo));
         msg(MSG::DEBUG)<<" d="<<m_d_calo_surf;
         if(distsamp<0) {
-          msg(MSG::DEBUG)<<endreq;
+          msg(MSG::DEBUG)<<endmsg;
           break;
         }  
       }
-      msg(MSG::DEBUG)<<endreq;
+      msg(MSG::DEBUG)<<endmsg;
     } else {
-      msg(MSG::DEBUG)<<": eta > 900, not using this"<<endreq;
+      msg(MSG::DEBUG)<<": eta > 900, not using this"<<endmsg;
     }
   }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C
new file mode 100644
index 0000000000000000000000000000000000000000..2be882925c6c2cdf45679e7e4405cca2055d5b62
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.C
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AtlasLabels.h"
+
+#include "TLatex.h"
+#include "TLine.h"
+#include "TPave.h"
+#include "TMarker.h"
+
+
+void ATLASLabel(Double_t x,Double_t y,char* text,Color_t color) 
+{
+  TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
+  l.SetNDC();
+  l.SetTextFont(72);
+  l.SetTextColor(color);
+
+  double delx = 0.115*696*gPad->GetWh()/(472*gPad->GetWw());
+
+  l.DrawLatex(x,y,"ATLAS");
+  if (text) {
+    TLatex p; 
+    p.SetNDC();
+    p.SetTextFont(42);
+    p.SetTextColor(color);
+    p.DrawLatex(x+delx,y,text);
+    //    p.DrawLatex(x,y,"#sqrt{s}=900GeV");
+  }
+}
+
+
+void ATLASLabelOld(Double_t x,Double_t y,bool Preliminary,Color_t color) 
+{
+  TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
+  l.SetNDC();
+  l.SetTextFont(72);
+  l.SetTextColor(color);
+  l.DrawLatex(x,y,"ATLAS");
+  if (Preliminary) {
+    TLatex p; 
+    p.SetNDC();
+    p.SetTextFont(42);
+    p.SetTextColor(color);
+    p.DrawLatex(x+0.115,y,"Preliminary");
+  }
+}
+
+
+
+void ATLASVersion(char* version,Double_t x,Double_t y,Color_t color) 
+{
+
+  if (version) {
+    char versionString[100];
+    sprintf(versionString,"Version %s",version);
+    TLatex l;
+    l.SetTextAlign(22); 
+    l.SetTextSize(0.04); 
+    l.SetNDC();
+    l.SetTextFont(72);
+    l.SetTextColor(color);
+    l.DrawLatex(x,y,versionString);
+  }
+}
+
+
+
+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
new file mode 100644
index 0000000000000000000000000000000000000000..8dbd1894b51f243ead49bd8602aafc4b760c57a7
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasLabels.h
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//
+//   @file    AtlasLabels.h         
+//   
+//   @author M.Sutton
+// 
+//   Copyright (C) 2010 Atlas Collaboration
+//
+//   $Id$
+
+
+#ifndef __ATLASLABELS_H
+#define __ATLASLABELS_H
+
+#include "Rtypes.h"
+
+void ATLASLabel(Double_t x,Double_t y,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); 
+
+#endif // __ATLASLABELS_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.C
new file mode 100644
index 0000000000000000000000000000000000000000..e954a0ac158e8ddcc45edb4e5732097abdf893ff
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.C
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//
+// ATLAS Style, based on a style file from BaBar
+//
+
+#include <iostream>
+
+#include "AtlasStyle.h"
+
+#include "TROOT.h"
+
+void SetAtlasStyle ()
+{
+  static TStyle* atlasStyle = 0;
+  std::cout << "\nApplying ATLAS style settings...\n" << std::endl ;
+  if ( atlasStyle==0 ) atlasStyle = AtlasStyle();
+  gROOT->SetStyle("ATLAS");
+  gROOT->ForceStyle();
+}
+
+TStyle* AtlasStyle() 
+{
+  TStyle *atlasStyle = new TStyle("ATLAS","Atlas style");
+
+  // use plain black on white colors
+  Int_t icol=0; // WHITE
+  atlasStyle->SetFrameBorderMode(icol);
+  atlasStyle->SetFrameFillColor(icol);
+  atlasStyle->SetCanvasBorderMode(icol);
+  atlasStyle->SetCanvasColor(icol);
+  atlasStyle->SetPadBorderMode(icol);
+  atlasStyle->SetPadColor(icol);
+  atlasStyle->SetStatColor(icol);
+  //atlasStyle->SetFillColor(icol); // don't use: white fill color for *all* objects
+
+  // set the paper & margin sizes
+  atlasStyle->SetPaperSize(20,26);
+
+  // set margin sizes
+  atlasStyle->SetPadTopMargin(0.05);
+  atlasStyle->SetPadRightMargin(0.05);
+  atlasStyle->SetPadBottomMargin(0.16);
+  atlasStyle->SetPadLeftMargin(0.16);
+
+  // set title offsets (for axis label)
+  atlasStyle->SetTitleXOffset(1.4);
+  atlasStyle->SetTitleYOffset(1.4);
+
+  // use large fonts
+  //Int_t font=72; // Helvetica italics
+  Int_t font=42; // Helvetica
+  Double_t tsize=0.05;
+  atlasStyle->SetTextFont(font);
+
+  atlasStyle->SetTextSize(tsize);
+  atlasStyle->SetLabelFont(font,"x");
+  atlasStyle->SetTitleFont(font,"x");
+  atlasStyle->SetLabelFont(font,"y");
+  atlasStyle->SetTitleFont(font,"y");
+  atlasStyle->SetLabelFont(font,"z");
+  atlasStyle->SetTitleFont(font,"z");
+  
+  atlasStyle->SetLabelSize(tsize,"x");
+  atlasStyle->SetTitleSize(tsize,"x");
+  atlasStyle->SetLabelSize(tsize,"y");
+  atlasStyle->SetTitleSize(tsize,"y");
+  atlasStyle->SetLabelSize(tsize,"z");
+  atlasStyle->SetTitleSize(tsize,"z");
+
+  // use bold lines and markers
+  atlasStyle->SetMarkerStyle(20);
+  atlasStyle->SetMarkerSize(1.2);
+  atlasStyle->SetHistLineWidth(2.);
+  atlasStyle->SetLineStyleString(2,"[12 12]"); // postscript dashes
+
+  // get rid of X error bars 
+  //atlasStyle->SetErrorX(0.001);
+  // get rid of error bar caps
+  atlasStyle->SetEndErrorSize(0.);
+
+  // do not display any of the standard histogram decorations
+  atlasStyle->SetOptTitle(0);
+  //atlasStyle->SetOptStat(1111);
+  atlasStyle->SetOptStat(0);
+  //atlasStyle->SetOptFit(1111);
+  atlasStyle->SetOptFit(0);
+
+  // put tick marks on top and RHS of plots
+  atlasStyle->SetPadTickX(1);
+  atlasStyle->SetPadTickY(1);
+
+  return atlasStyle;
+
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h
new file mode 100644
index 0000000000000000000000000000000000000000..b77a679959a02865d32cd13a52bcbac0f1b2fbf3
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasStyle.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//
+//   @file    AtlasStyle.h         
+//   
+//            ATLAS Style, based on a style file from BaBar
+//
+//
+//   @author M.Sutton
+// 
+//   Copyright (C) 2010 Atlas Collaboration
+//
+//   $Id$
+
+#ifndef  __ATLASSTYLE_H
+#define __ATLASSTYLE_H
+
+#include "TStyle.h"
+
+void SetAtlasStyle();
+
+TStyle* AtlasStyle(); 
+
+#endif // __ATLASSTYLE_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C
new file mode 100644
index 0000000000000000000000000000000000000000..9dcff66d3191f9fbff0d4498c6161c5b36b53770
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.C
@@ -0,0 +1,327 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include <iostream>
+#include <cmath>
+
+#include "AtlasUtils.h"
+
+#include "TLine.h"
+#include "TLatex.h"
+#include "TMarker.h"
+#include "TPave.h"
+#include "TH1.h"
+
+void ATLAS_LABEL(Double_t x,Double_t y,Color_t color) 
+{
+  TLatex l; //l.SetTextAlign(12); l.SetTextSize(tsize); 
+  l.SetNDC();
+  l.SetTextFont(72);
+  l.SetTextColor(color);
+  l.DrawLatex(x,y,"ATLAS");
+}
+
+TGraphErrors* myTGraphErrorsDivide(TGraphErrors* g1,TGraphErrors* g2) {
+ 
+  const Int_t debug=0; 
+
+  if (!g1) printf("**myTGraphErrorsDivide: g1 does not exist !  \n"); 
+  if (!g2) printf("**myTGraphErrorsDivide: g2 does not exist !  \n"); 
+
+
+  Int_t n1=g1->GetN();
+  Int_t n2=g2->GetN();
+
+  if (n1!=n2) {
+   printf("**myTGraphErrorsDivide: vector do not have same number of entries !  \n"); 
+  }
+
+  TGraphErrors* g3= new TGraphErrors();
+
+  Double_t  x1=0., y1=0., x2=0., y2=0.;
+  Double_t dx1=0.,dy1=0.,       dy2=0.;
+
+  Int_t iv=0;
+  for (Int_t i1=0; i1<n1; i1++) {
+   for (Int_t i2=0; i2<n2; i2++) {
+     //if (debug) printf("**myTGraphErrorsDivide: %d  %d !  \n",i1,i2);
+
+    g1->GetPoint(i1,x1,y1);
+    g2->GetPoint(i2,x2,y2);
+    if (x1!=x2) {
+      //printf("**myTGraphErrorsDivide: %d x1!=x2  %f %f  !  \n",iv,x1,x2);
+    }else{
+      //if (debug) printf("**myTGraphErrorsDivide: %d x1=x2  %f %f  !  \n",iv,x1,x2);
+     dx1  = g1->GetErrorX(i1);
+     if (y1!=0) dy1  = g1->GetErrorY(i1)/y1;
+     if (y2!=0) dy2  = g2->GetErrorY(i2)/y2;
+   
+     if (debug)
+      printf("**myTGraphErrorsDivide: %d x1=%f x2=%f y1=%f y2=%f  \n",iv,x1,x2,y1,y2);
+
+     if (y2!=0.) g3->SetPoint(iv, x1,y1/y2);
+     else        g3->SetPoint(iv, x1,y2);
+   
+     Double_t e=0.;
+     if (y1!=0 && y2!=0) e=std::sqrt(dy1*dy1+dy2*dy2)*(y1/y2); 
+     g3->SetPointError(iv,dx1,e);
+
+
+     if (debug) {
+       //Double_t g3y, g3x,g3e;
+       //g3->GetPoint(iv, g3y,g3x);
+       //g3e=g3->GetErrorY(iv);
+       //printf("%d g3y= %f g3e=%f  \n",iv,g3y,g3e);
+     }
+     iv++;
+    }
+    //    printf("**myTGraphErrorsDivide: ...next  \n");
+   }
+  }  
+  return g3;
+
+}
+
+
+TGraphAsymmErrors* myTGraphErrorsDivide(TGraphAsymmErrors* g1,TGraphAsymmErrors* g2) {
+
+  const Int_t debug=0; 
+
+  TGraphAsymmErrors* g3= new TGraphAsymmErrors();
+  Int_t n1=g1->GetN();
+  Int_t n2=g2->GetN();
+
+  if (n1!=n2) {
+    printf(" vectors do not have same number of entries !  \n");
+   return g3;
+  }
+
+  Double_t   x1=0.,   y1=0., x2=0., y2=0.;
+  Double_t dx1h=0., dx1l=0.;
+  Double_t dy1h=0., dy1l=0.;
+  Double_t dy2h=0., dy2l=0.;
+
+  Double_t* X1 = g1->GetX();
+  Double_t* Y1 = g1->GetY();
+  Double_t* EXhigh1 = g1->GetEXhigh();
+  Double_t* EXlow1 =  g1->GetEXlow();
+  Double_t* EYhigh1 = g1->GetEYhigh();
+  Double_t* EYlow1 =  g1->GetEYlow();
+
+  Double_t* X2 = g2->GetX();
+  Double_t* Y2 = g2->GetY();
+  Double_t* EXhigh2 = g2->GetEXhigh();
+  Double_t* EXlow2 =  g2->GetEXlow();
+  Double_t* EYhigh2 = g2->GetEYhigh();
+  Double_t* EYlow2 =  g2->GetEYlow();
+
+  for (Int_t i=0; i<g1->GetN(); i++) {
+    g1->GetPoint(i,x1,y1);
+    g2->GetPoint(i,x2,y2);
+    dx1h  = EXhigh1[i];
+    dx1l  = EXlow1[i];
+    if (y1!=0.) dy1h  = EYhigh1[i]/y1;
+    else        dy1h  = 0.;
+    if (y2!=0.) dy2h  = EYhigh2[i]/y2;
+    else        dy2h  = 0.;
+    if (y1!=0.) dy1l  = EYlow1 [i]/y1;
+    else        dy1l  = 0.;
+    if (y2!=0.) dy2l  = EYlow2 [i]/y2;
+    else        dy2l  = 0.;
+   
+    //if (debug)
+    //printf("%d x1=%f x2=%f y1=%f y2=%f  \n",i,x1,x2,y1,y2);
+    if (debug)
+      printf("%d dy1=%f %f dy2=%f %f sqrt= %f %f \n",i,dy1l,dy1h,dy2l,dy2h,
+	     std::sqrt(dy1l*dy1l+dy2l*dy2l), std::sqrt(dy1h*dy1h+dy2h*dy2h));
+
+    if (y2!=0.) g3->SetPoint(i, x1,y1/y2);
+    else       g3->SetPoint(i, x1,y2);
+    Double_t el=0.; Double_t eh=0.;
+
+    if (y1!=0. && y2!=0.) el=std::sqrt(dy1l*dy1l+dy2l*dy2l)*(y1/y2);
+    if (y1!=0. && y2!=0.) eh=std::sqrt(dy1h*dy1h+dy2h*dy2h)*(y1/y2);
+
+    if (debug) printf("dx1h=%f  dx1l=%f  el=%f  eh=%f \n",dx1h,dx1l,el,eh);
+    g3->SetPointError(i,dx1h,dx1l,el,eh);
+
+  }  
+  return g3;
+
+}
+
+
+
+TGraphAsymmErrors* myMakeBand(TGraphErrors* g0, TGraphErrors* g1,TGraphErrors* g2) {
+  // default is g0
+    //const Int_t debug=0;
+
+  TGraphAsymmErrors* g3= new TGraphAsymmErrors();
+
+  Double_t  x1=0., y1=0., x2=0., y2=0., y0=0, x3=0.;
+  //Double_t dx1=0.;
+  Double_t dum;
+  for (Int_t i=0; i<g1->GetN(); i++) {
+    g0->GetPoint(i, x1,y0);
+    g1->GetPoint(i, x1,y1);
+    g2->GetPoint(i, x1,y2);
+
+    // if (y1==0) y1=1;
+    //if (y2==0) y2=1;
+
+    if (i==g1->GetN()-1) x2=x1;
+    else                 g2->GetPoint(i+1,x2,dum);
+
+    if (i==0)            x3=x1;
+    else                 g2->GetPoint(i-1,x3,dum);
+
+    Double_t tmp=y2;
+    if (y1<y2) {y2=y1; y1=tmp;}
+    //Double_t y3=1.;
+    Double_t y3=y0;
+    g3->SetPoint(i,x1,y3);
+
+    Double_t binwl=(x1-x3)/2.;
+    Double_t binwh=(x2-x1)/2.;
+    if (binwl==0.)  binwl= binwh;
+    if (binwh==0.)  binwh= binwl;
+    g3->SetPointError(i,binwl,binwh,(y3-y2),(y1-y3));
+
+  }
+  return g3;
+
+}
+
+void myAddtoBand(TGraphErrors* g1, TGraphAsymmErrors* g2) {
+
+  Double_t  x1=0., y1=0.,  y2=0., y0=0;
+  //Double_t dx1=0.;
+  //Double_t dum;
+
+  if (g1->GetN()!=g2->GetN())
+    std::cout << " graphs have not the same # of elements " << std::endl;
+
+  Double_t* EYhigh = g2-> GetEYhigh();
+  Double_t* EYlow  = g2-> GetEYlow();
+
+  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 (i==g1->GetN()-1) x2=x1;
+    //    else                 g2->GetPoint(i+1,x2,dum);
+    //    if (i==0)            x3=x1;
+    //    else                 g2->GetPoint(i-1,x3,dum);
+
+    Double_t eyh=0., eyl=0.;
+    //if (y1<y2) {y2=y1; y1=tmp;}
+    //Double_t y3=1.;
+
+    //printf("%d: y1=%f y2=%f Eyhigh= %f Eylow= %f \n",i,y1,y2,EYhigh[i],EYlow[i]);
+
+    y0=y1-y2;
+    if (y0!=0) {
+     if (y0>0){
+      eyh=EYhigh[i];
+      eyh=std::sqrt(eyh*eyh+y0*y0);
+      //printf("high: %d: y0=%f eyh=%f  \n",i,y0,eyh);
+      g2->SetPointEYhigh(i,eyh);
+     } else {
+      eyl=EYlow[i];
+      eyl=std::sqrt(eyl*eyl+y0*y0);
+      // printf("low: %d: y0=%f eyl=%f  \n",i,y0,eyl);
+      g2->SetPointEYlow (i,eyl);
+     }
+    }
+  }
+  return;
+
+}
+
+TGraphErrors* TH1TOTGraph(TH1 *h1){
+
+
+  if (!h1) std::cout << "TH1TOTGraph: histogram not found !" << std::endl;
+
+ TGraphErrors* g1= new TGraphErrors();
+
+ Double_t x, y, ex, ey;
+ for (Int_t i=0; i<h1->GetNbinsX(); i++) {
+   y=h1->GetBinContent(i);
+  ey=h1->GetBinError(i);
+   x=h1->GetBinCenter(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->Print();
+
+ return g1;
+}
+
+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,Float_t msize) 
+{
+  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(msize);
+  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/AtlasUtils.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb4346f98fb6ecfe721ea34cc0644a44bb40f7d5
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/AtlasUtils.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//
+//   @file    AtlasUtils.h         
+//   
+//
+//   @author M.Sutton
+// 
+//   Copyright (C) 2010 Atlas Collaboration
+//
+//   $Id$
+
+
+#ifndef __ATLASUTILS_H
+#define __ATLASUTILS_H
+
+#include "TGraphErrors.h"
+#include "TGraphAsymmErrors.h"
+
+void ATLAS_LABEL(Double_t x,Double_t y,Color_t color=1); 
+
+TGraphErrors* myTGraphErrorsDivide(TGraphErrors* g1,TGraphErrors* g2);
+
+TGraphAsymmErrors* myTGraphErrorsDivide(TGraphAsymmErrors* g1,TGraphAsymmErrors* g2);
+
+TGraphAsymmErrors* myMakeBand(TGraphErrors* g0, TGraphErrors* g1,TGraphErrors* g2);
+
+void myAddtoBand(TGraphErrors* g1, TGraphAsymmErrors* g2);
+
+TGraphErrors* TH1TOTGraph(TH1 *h1);
+
+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,Float_t msize=2.); 
+
+#endif // __ATLASUTILS_H
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloDetDescr/CaloDetDescrElement.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloDetDescr/CaloDetDescrElement.h
index 67d9d313f470f4fb5f67badee1c1768b529f8562..a41bffa0db237c94270c2efe14fef1f605639005 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloDetDescr/CaloDetDescrElement.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/CaloDetDescr/CaloDetDescrElement.h
@@ -11,7 +11,28 @@ class CaloDetDescrElement
 {
  friend class CaloGeometry;
  public:
-  CaloDetDescrElement() {};
+  CaloDetDescrElement() {
+    m_identify = 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
    */
@@ -79,7 +100,8 @@ class CaloDetDescrElement
 
   Int_t getSampling() const ;
 
- protected:  
+ //ACH protected:  
+ //
   Long64_t m_identify;
   
   Int_t m_calosample;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/ConvertTreeIntoNumPy.py b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/ConvertTreeIntoNumPy.py
new file mode 100644
index 0000000000000000000000000000000000000000..d39f369d667f1e17c0493ba746697504355f7a19
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/ConvertTreeIntoNumPy.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from rootpy.tree import Tree, TreeModel, FloatCol, IntCol
+from rootpy.io import root_open
+from random import gauss
+
+
+f = root_open("test.root", "recreate")
+
+
+# define the model
+#class Event(TreeModel):
+#    x = FloatCol()
+#    y = FloatCol()
+#    z = FloatCol()
+#    i = IntCol()
+#
+#tree = Tree("test", model=Event)
+#
+## fill the tree
+#for i in xrange(100):
+#    tree.x = gauss(.5, 1.)
+#    tree.y = gauss(.3, 2.)
+#    tree.z = gauss(13., 42.)
+#    tree.i = i
+#    tree.fill()
+#tree.write()
+
+# convert tree into a numpy record array
+from root_numpy import tree2rec
+array = tree2rec(tree)
+print array
+print array.x
+print array.i
+print tree.to_array()
+
+f.close()
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/Makefile b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/Makefile
index 952a4e602fe1425f3f033d832b31072fa3b9d763..3cc648f37490f24a5add5d3aa67d35469be2d4a6 100755
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/Makefile
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/Makefile
@@ -1,24 +1,248 @@
-if [  -f FCS_CellDict.cxx ];
-then
- rm FCS_CellDict.cxx
- rm FCS_CellDict.h
-fi
-rootcint FCS_CellDict.cxx -c FCS_Cell.h Linkdef.h
-#compile
-g++ -g -c run.C FCS_CellDict.cxx -I $(root-config --incdir) -I . -fPIC $CPPEXPFLAGS -std=c++11
+######################################################################
+# Project: TMVA - Toolkit for Multivariate Data Analysis             #
+# Code   : Source                                                    #
+###################################################################### 
 
-#link executable
-g++ -g -o CaloHitAna run.o FCS_CellDict.o -L $(root-config --libdir) -lGui -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,$(root-config --libdir) -lm -ldl -fPIC $CPPEXPFLAGS -std=c++11
+SHELL=bash
 
-#this creates a shared library for ROOT (which can be loaded by hand)
-g++ -shared -o FCS_Cell_h.so FCS_CellDict.o -L $(root-config --libdir) -lGui -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,$(root-config --libdir) -lm -ldl -fPIC $CPPEXPFLAGS -std=c++11
+MAKEFLAGS = --no-print-directory -r -s --warn-undefined-variables --debug
 
-#example
-g++ -g -c CaloHitAna2.C -I $(root-config --incdir) -I . -fPIC $CPPEXPFLAGS -std=c++11
+include Makefile.arch
 
-g++ -g -o CaloHitAna2 CaloHitAna2.o FCS_CellDict.o -L $(root-config --libdir) -lGui -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,$(root-config --libdir) -lm -ldl -lstdc++ -fPIC $CPPEXPFLAGS -std=c++11
+# Internal configuration
+PACKAGE=TMVA
+LD_LIBRARY_PATH := $(shell root-config --libdir):$(LD_LIBRARY_PATH)
+OBJDIR    = obj
+DEPDIR    = $(OBJDIR)/dep
+LIBDIR    = lib
+VPATH     = $(OBJDIR)
+INCLUDES += -I./
 
-#another example
-g++ -g -c CaloHitAna3.C FCS_CellDict.cxx -Wall -I $(root-config --incdir) -I . -fPIC $CPPEXPFLAGS -Wall -std=c++11
+DICTL1       := inc/LinkDef1.h
+DICTL2       := inc/LinkDef2.h
+DICTL3       := inc/LinkDef3.h
+DICTL4       := inc/LinkDef4.h
+DICTL        := $(DICTL1) $(DICTL2) $(DICTL3) $(DICTL4)
+DICTS1       := src/$(PACKAGE)_Dict1.C
+DICTS2       := src/$(PACKAGE)_Dict2.C
+DICTS3       := src/$(PACKAGE)_Dict3.C
+DICTS4       := src/$(PACKAGE)_Dict4.C
+DICTS        := $(DICTS1) $(DICTS2) $(DICTS3) $(DICTS4)
+DICTO1       := $(OBJDIR)/$(PACKAGE)_Dict1.o
+DICTO2       := $(OBJDIR)/$(PACKAGE)_Dict2.o
+DICTO3       := $(OBJDIR)/$(PACKAGE)_Dict3.o
+DICTO4       := $(OBJDIR)/$(PACKAGE)_Dict4.o
+DICTO        := $(DICTO1) $(DICTO2) $(DICTO3) $(DICTO4)
+DICTH1       := Configurable.h Event.h Factory.h MethodBase.h MethodCompositeBase.h \
+		MethodANNBase.h MethodTMlpANN.h MethodRuleFit.h MethodCuts.h MethodFisher.h \
+		MethodKNN.h MethodCFMlpANN.h MethodCFMlpANN_Utils.h MethodLikelihood.h \
+		MethodHMatrix.h MethodPDERS.h MethodBDT.h MethodDT.h MethodSVM.h MethodBayesClassifier.h \
+		MethodFDA.h MethodMLP.h MethodBoost.h \
+		MethodPDEFoam.h MethodLD.h MethodCategory.h
+DICTH2       := TSpline2.h TSpline1.h PDF.h BinaryTree.h BinarySearchTreeNode.h BinarySearchTree.h \
+		Timer.h RootFinder.h CrossEntropy.h DecisionTree.h DecisionTreeNode.h MisClassificationError.h \
+		Node.h SdivSqrtSplusB.h SeparationBase.h RegressionVariance.h Tools.h Reader.h \
+		GeneticAlgorithm.h GeneticGenes.h GeneticPopulation.h GeneticRange.h GiniIndex.h \
+		GiniIndexWithLaplace.h SimulatedAnnealing.h QuickMVAProbEstimator.h
+DICTH3       := Config.h KDEKernel.h Interval.h LogInterval.h FitterBase.h MCFitter.h GeneticFitter.h  \
+		SimulatedAnnealingFitter.h MinuitFitter.h MinuitWrapper.h IFitterTarget.h \
+		PDEFoam.h PDEFoamDecisionTree.h PDEFoamDensityBase.h PDEFoamDiscriminantDensity.h \
+		PDEFoamEventDensity.h PDEFoamTargetDensity.h PDEFoamDecisionTreeDensity.h PDEFoamMultiTarget.h \
+		PDEFoamVect.h PDEFoamCell.h PDEFoamDiscriminant.h PDEFoamEvent.h PDEFoamTarget.h \
+		PDEFoamKernelBase.h PDEFoamKernelTrivial.h PDEFoamKernelLinN.h PDEFoamKernelGauss.h \
+		BDTEventWrapper.h CCTreeWrapper.h \
+		CCPruner.h CostComplexityPruneTool.h SVEvent.h OptimizeConfigParameters.h
+DICTH4       := TNeuron.h TSynapse.h TActivationChooser.h TActivation.h TActivationSigmoid.h TActivationIdentity.h \
+		TActivationTanh.h TActivationRadial.h TNeuronInputChooser.h TNeuronInput.h TNeuronInputSum.h \
+		TNeuronInputSqSum.h TNeuronInputAbs.h Types.h Ranking.h RuleFit.h RuleFitAPI.h IMethod.h MsgLogger.h \
+		VariableTransformBase.h VariableIdentityTransform.h VariableDecorrTransform.h VariablePCATransform.h \
+		VariableGaussTransform.h VariableNormalizeTransform.h VariableRearrangeTransform.h
+DICTH1       := $(patsubst %,inc/TMVA/%,$(DICTH1))
+DICTH2       := $(patsubst %,inc/TMVA/%,$(DICTH2))
+DICTH3       := $(patsubst %,inc/TMVA/%,$(DICTH3))
+DICTH4       := $(patsubst %,inc/TMVA/%,$(DICTH4))
+DICTH        := $(DICTH1) $(DICTH2) $(DICTH3) $(DICTH4)
 
-g++ -g -o CaloHitAna3 CaloHitAna3.o FCS_CellDict.o -L $(root-config --libdir) -lGui -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,$(root-config --libdir) -lm -ldl -lstdc++ -fPIC $CPPEXPFLAGS -Wall -std=c++11
+
+SKIPCPPLIST  := 
+SKIPHLIST    := $(DICTHEAD) $(DICTL)
+LIBFILE      := lib/lib$(PACKAGE).a
+SHLIBFILE    := lib$(PACKAGE).$(DllSuf)
+DLLIBFILE    := lib/lib$(PACKAGE).dll
+ROOTMAP      := lib/lib$(PACKAGE).rootmap
+TESTDIR      := test
+UNAME = $(shell uname)
+
+default: shlib linklib
+
+# List of all source files to build
+HLIST   = $(filter-out $(SKIPHLIST),$(wildcard inc/TMVA/*.h))
+CPPLIST = $(filter-out $(SKIPCPPLIST),$(patsubst src/%,%,$(wildcard src/*.$(SrcSuf))))
+
+# List of all object files to build
+OLIST=$(patsubst %.cxx,%.o,$(CPPLIST))
+OLIST=$(CPPLIST:.$(SrcSuf)=.o)
+DEPLIST=$(foreach var,$(CPPLIST:.$(SrcSuf)=.d),$(DEPDIR)/$(var))
+
+# Implicit rule to compile all classes
+sl:
+	if [[ ( ! -e TMVA ) ]]; then \
+		ln -sf inc/TMVA TMVA; \
+	fi
+
+$(OBJDIR)/%.o : src/%.cxx 
+	if [[ ( ! -e TMVA ) ]]; then \
+		ln -sf inc/TMVA TMVA; \
+	fi
+	@printf "Compiling $< ... "
+	@mkdir -p $(OBJDIR)
+	@$(CXX) $(INCLUDES) $(CXXFLAGS) -ggdb -c $< -o $@
+	@echo "Done"
+
+# Rule to make the dictionary
+dict: sl $(DICTO1) $(DICTO2) $(DICTO3) $(DICTO4)
+
+$(DICTS1):  $(DICTH1) $(DICTL1)
+	@echo "Generating dictionary $@" 
+	$(shell root-config --exec-prefix)/bin/rootcint -f $@ -c -p $(INCLUDES) $^
+
+$(DICTS2):  $(DICTH2) $(DICTL2)
+	@echo "Generating dictionary $@" 
+	$(shell root-config --exec-prefix)/bin/rootcint -f $@ -c -p $(INCLUDES) $^
+
+$(DICTS3):  $(DICTH3) $(DICTL3)
+	@echo "Generating dictionary $@" 
+	$(shell root-config --exec-prefix)/bin/rootcint -f $@ -c -p $(INCLUDES) $^
+
+$(DICTS4):  $(DICTH4) $(DICTL4)
+	@echo "Generating dictionary $@" 
+	$(shell root-config --exec-prefix)/bin/rootcint -f $@ -c -p $(INCLUDES) $^
+
+$(DICTO1): $(DICTS1)
+	@echo "Compiling dictionary $<"
+	@mkdir -p $(OBJDIR)
+	@$(CXX) $(INCLUDES) $(CXXFLAGS) -g -c  -o $@ $<
+
+$(DICTO2): $(DICTS2)
+	@echo "Compiling dictionary $<"
+	@mkdir -p $(OBJDIR)
+	@$(CXX) $(INCLUDES) $(CXXFLAGS) -g -c  -o $@ $<
+
+$(DICTO3): $(DICTS3)
+	@echo "Compiling dictionary $<"
+	@mkdir -p $(OBJDIR)
+	@$(CXX) $(INCLUDES) $(CXXFLAGS) -g -c  -o $@ $<
+
+$(DICTO4): $(DICTS4)
+	@echo "Compiling dictionary $<"
+	@mkdir -p $(OBJDIR)
+	@$(CXX) $(INCLUDES) $(CXXFLAGS) -g -c  -o $@ $<
+
+
+
+# Rule to set up a symbolic links to the created shared library
+linklib:
+	if [[ ( ( `root-config --platform` == "macosx" ) && \
+			( ! -e lib/lib$(PACKAGE).1.dylib ) ) || \
+			( ! -e lib/lib$(PACKAGE).1.so ) ]]; then \
+		printf "Setting up soft links to the TMVA library ... "; \
+		ln -sf $(SHLIBFILE) $(LIBDIR)/lib$(PACKAGE).1.so; \
+		if [[ `root-config --platform` == "macosx" ]]; then \
+			ln -sf $(SHLIBFILE) $(LIBDIR)/lib$(PACKAGE).1.dylib; \
+		fi; \
+		echo "Done"; \
+	fi
+
+##############################
+# The dependencies section   
+# - the purpose of the .d files is to keep track of the
+#   header file dependence
+# - this can be achieved using the makedepend command 
+##############################
+# .d tries to pre-process .cc
+ifneq ($(MAKECMDGOALS),clean)
+-include $(DEPLIST)
+endif
+
+$(DEPDIR)/%.d: src/%.$(SrcSuf)
+	@mkdir -p $(DEPDIR)
+	if [[ ( ! -e TMVA ) ]]; then \
+		ln -sf inc/TMVA TMVA; \
+	fi
+	if test -f $< ; then \
+		printf "Building $(@F) ... "; \
+		$(SHELL) -ec '`root-config --exec-prefix`/bin/rmkdepend -f- -Y -w 3000 -- -I./ -- $< 2> /dev/null 1| sed -e "s-src/\(.*\).o\(: .*\)-$(DEPDIR)\/\1.d $(OBJDIR)/\1.o\2-" > $@'; \
+		rm -f $@.bak; \
+		echo "Done"; \
+	fi
+
+# Rule to combine objects into a library
+$(LIBFILE): $(DICTO) $(OLIST)
+	@printf "Making static library $(LIBFILE) ... "
+	@rm -f $(LIBFILE)
+	@ar q $(LIBFILE) $(addprefix $(OBJDIR)/,$(OLIST) $(DICTO)
+	@ranlib $(LIBFILE)
+	@echo "Done"
+
+# Rule to combine objects into a unix shared library
+$(LIBDIR)/$(SHLIBFILE): $(OLIST) $(DICTO)
+	@printf "Building shared library $(LIBDIR)/$(SHLIBFILE) ... "
+	@mkdir -p $(LIBDIR)
+	@rm -f $(LIBDIR)/$(SHLIBFILE)
+	@$(LD) -L$(shell root-config --libdir) $(SOFLAGS) $(addprefix $(OBJDIR)/,$(OLIST)) $(DICTO) -o $(LIBDIR)/$(SHLIBFILE) -lMinuit -lXMLIO
+#	ln -fs $(SHLIBFILE) lib/lib$(PACKAGE).1.so
+	@echo "Done"
+
+# Rule to combine objects into a unix shared library
+$(ROOTMAP): $(DICTL)
+	@printf "Building $(ROOTMAP) ... "
+	@mkdir -p $(LIBDIR)
+	rlibmap -f -o $@ -l lib$(PACKAGE).1.$(DllSuf) -d libMinuit.so libMLP.so libMatrix.so libTree.so libGraf.so libTreePlayer.so libXMLIO.so -c $^
+	@echo "Done"
+
+# Rule to combine objects into a windows shared library
+$(DLLIBFILE): $(OLIST) $(DICTO)
+	@printf "Making dll file $(DLLIBFILE) ... "
+	@rm -f $(DLLIBFILE)
+	$(LD) -Wl,--export-all-symbols -Wl,--export-dynamic -Wl,--enable-auto-import -Wl,-Bdynamic -shared --enable-auto-image-base -Wl,-soname -o $(DLLIBFILE) -Wl,--whole-archive $(addprefix $(OBJDIR)/,$(OLIST) $(patsubst %.$(SrcSuf),%.o,$(DICTFILE))) -Wl,--no-whole-archive -L$(ROOTSYS)/lib -lCore -lCint -lHist -lGraf -lGraf3d -lTree -lRint -lPostscript -lMatrix -lMinuit -lPhysics -lHtml -lXMLIO -lm
+	@echo "Done"
+
+# Useful build targets
+lib: $(LIBFILE) 
+
+shlib: $(LIBDIR)/$(SHLIBFILE) $(ROOTMAP)
+
+winlib: $(DLLIBFILE)
+
+vars:
+	#echo $(patsubst src/%,%,$(wildcard src/*.$(SrcSuf)))
+	echo $(OLIST) $(DICTO)
+
+clean:
+	rm -rf obj
+	rm -rf lib
+	rm -f TMVA 
+	rm -f $(DICTS) $(DICTS:.C=.h)
+	rm -f $(OBJDIR)/*.o
+	rm -f $(DEPDIR)/*.d
+	rm -f $(LIBFILE)
+	rm -f $(LIBDIR)/$(SHLIBFILE)
+	rm -f lib/lib$(PACKAGE).1.so
+	rm -f lib/lib$(PACKAGE).1.dylib
+	rm -f $(ROOTMAP)
+	rm -f $(DLLIBFILE)
+
+distclean:
+	rm -rf obj 
+	rm -f *~
+	rm -f $(DICTFILE) $(DICTHEAD)
+	rm -f $(LIBFILE)
+	rm -f $(LIBDIR)/$(SHLIBFILE	)
+	rm -f lib/lib$(PACKAGE).1.so
+	rm -f lib/lib$(PACKAGE).1.dylib
+	rm -f $(ROOTMAP)
+	rm -f $(DLLIBFILE)
+
+.PHONY : winlib shlib lib default clean
+
+# DO NOT DELETE
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/batchDetailedShape.sh b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/batchDetailedShape.sh
new file mode 100644
index 0000000000000000000000000000000000000000..287f7bef40351a043b6998125c88f1b7b59d527a
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/batchDetailedShape.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#BSUB -q 8nh
+#BSUB -J AF2[1-1]
+#BSUB -o LOGS/out
+#BSUB -e LOGS/err
+#BSUB -g /AF2
+#BSUB ulimit -c 0
+  
+cd /afs/cern.ch/work/c/conti/private/G4FASTCALO/ISF_FastCaloSimParametrization/tools/
+
+RELEASE=20.1.2
+source /afs/cern.ch/atlas/software/dist/AtlasSetup/scripts/asetup.sh $RELEASE
+
+let "s=($LSB_JOBINDEX)"
+echo $s
+
+if [ $s -eq 1 ]; then 
+    root -l -b runDetailedShape.C
+fi
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C
new file mode 100644
index 0000000000000000000000000000000000000000..a8fdb65e7d51e62d55eb92f7f4f2a41c8ef3f899
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/rootlogon.C
@@ -0,0 +1,10 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+void rootlogon()
+{
+  // Load ATLAS style
+  gROOT->LoadMacro("AtlasStyle.C");
+  SetAtlasStyle();
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShape.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShape.C
new file mode 100644
index 0000000000000000000000000000000000000000..ff4168d6f5af6853f75801abeb2bd37c8b40e6db
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShape.C
@@ -0,0 +1,105 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+void runDetailedShape(){
+
+  gSystem->AddIncludePath(" -I.. ");
+  gROOT->LoadMacro("../src/CaloGeometry.cxx+");
+  gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
+  gROOT->LoadMacro("../Root/DetailedShapeBinning.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2DFunction.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2DFunctionRegression.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2Function.cxx+");
+  gROOT->LoadMacro("../Root/FitDetailedShape.cxx+");
+  
+  bool runBinning  = false;
+  bool runNNfit    = true;
+
+  bool runmode1    = true;
+  bool runmode2    = false;
+  bool ismatched   = false;  
+  bool doNNHit     = false;
+
+  string particle="pi";
+  string PID = "11";
+  string sparticle = "e";
+  if(particle=="pi"){
+    sparticle="#pi";
+    PID="211";
+  }
+  if(particle=="gamma"){
+    sparticle="#gamma";
+    PID="22";
+  }
+  
+  string inputfile = "";
+
+  // type of input file you want to run on
+  if(!ismatched) inputfile="/afs/cern.ch/work/c/conti/public/AF2/ISF_HitAnalysis_evgen_calo__"+PID+"_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.pool.root";
+    
+  //string inputfile="root:://eos/atlas/user/c/conti/atlasreadable/AF2/ISF_HitAnalysis_evgen_calo__"+PID+"_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.pool.root";
+
+  if(ismatched){ 
+  //inputfile="/afs/cern.ch/work/c/conti/private/ISF_FastCaloSimParametrization/INPUT/user.zmarshal.8071918._000001.matched_output.root"; 
+    inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/00/24/user.zmarshal.7814824._000001.matched_output.root"; //v1_w2_160301
+    inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/4d/19/user.zmarshal.7805067._000001.matched_output.root"; //v0_w2_160229
+    inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/78/74/user.zmarshal.8071918._000001.matched_output.root"; //w0_160406_5mmMerge
+    inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/44/b4/user.zmarshal.8071920._000001.matched_output.root"; //w0_160406_1mmMerge
+  }
+
+
+  float layer=2;
+  float PCAbin=0;
+  int nybinsR=50;
+  float mincalosize=-1000;
+  
+  ostringstream os;
+  os << layer ;
+  ostringstream os2;
+  os2 << PCAbin ;
+  string labeloutput  = "50GeV_"+particle+"_layer"+os.str()+"_PCAbin"+os2.str();
+  string labeltitle   = "50 GeV "+sparticle+"^{#pm}, layer "+os.str()+", bin(PCA)="+os2.str();
+  
+  float cellr=0;
+  float cellz=0;
+  float celleta=0;
+  float cell_deta=0;
+  float cell_dphi=0;
+
+  // Determine the binning
+  if(runBinning){
+    DetailedShapeBinning* mydetailedshape=new DetailedShapeBinning();
+    bool test = mydetailedshape->run(false,ismatched,inputfile,nybinsR,layer, particle, PCAbin, labeltitle, labeloutput,mincalosize,cell_deta,cell_dphi,cellr,cellz,celleta);
+    // Test cell position
+    std::cout << "CELL POSITION IS : " << cell_deta << " " << cell_dphi << " " << cellr << " " << cellz << " " << celleta << std::endl;
+  }    
+
+  // To perform the NN fit of the shower shape 
+  if(runNNfit){
+    FitDetailedShape* myfit = new FitDetailedShape(); 
+    string outfile = "output/DetailedShape_"+labeloutput+".root";
+
+    if(runmode1){
+      //!doNNHit : Fit shower shape - LN(energy density) 
+      // doNNHit : Fit shower shape - LN(energy) to generate many hits
+      myfit->run(outfile,labeltitle,labeloutput,1,mincalosize,doNNHit);
+      if(doNNHit){
+      	DetailedShapeBinning* mydetailedshape2=new DetailedShapeBinning();
+      	string inputfileNNHit = "output/NNHit_"+labeloutput+".root";
+      	bool test2 = mydetailedshape2->run(true,ismatched,inputfileNNHit,nybinsR,layer, particle, PCAbin, labeltitle, labeloutput,mincalosize,cell_deta,cell_dphi,cellr,cellz,celleta);  
+      }
+    }
+    // Run the second binning
+    if(runmode2){
+      if(doNNHit)
+	outfile = "output/DetailedShape_"+labeloutput+"_NNHits.root";
+      std::cout << "RUNNING WITH FILE : " << outfile << std::endl;
+      myfit->run(outfile,labeltitle,labeloutput,2,mincalosize,doNNHit);
+    }
+  }
+
+  std::cout << "END " <<  std::endl;
+
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShapeGOOD.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShapeGOOD.C
new file mode 100644
index 0000000000000000000000000000000000000000..e8232ea2d90080d77c1747703b6effa5bda6e078
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runDetailedShapeGOOD.C
@@ -0,0 +1,153 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <vector>
+using namespace std;
+
+void runDetailedShapeGOOD(){
+
+  gSystem->AddIncludePath(" -I.. ");
+  gROOT->LoadMacro("../src/CaloGeometry.cxx+");
+  gROOT->LoadMacro("CaloGeometryFromFile.cxx+");
+  gROOT->LoadMacro("../Root/DetailedShapeBinning.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2DFunction.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2DFunctionRegression.cxx+");
+  gROOT->LoadMacro("../Root/TFCS2Function.cxx+");
+  gROOT->LoadMacro("../Root/FitDetailedShape.cxx+");
+  //
+  string particle="e";
+  string PID = "11";
+  string sparticle = "e";
+  if(particle=="pi"){
+    sparticle="#pi";
+    PID="211";
+  }
+  if(particle=="gamma"){
+    sparticle="#gamma";
+    PID="22";
+  }
+  
+  string inputfile = "";
+  
+  
+  bool doNNHit=0; // has to be false for the first iteration !!!
+
+  std::vector<float> etaslice;
+
+  // type of input file you want to run on
+  bool ismatched = 1;
+  
+  if(!ismatched)
+  {
+    TChain* mychain=new TChain("ISF_HitAnalysis/CaloHitAna");
+    if(PID=="211") mychain->Add(("/afs/cern.ch/work/c/conti/public/AF2/ISF_HitAnalysis_evgen_calo__"+PID+"_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.pool.root").c_str());
+    if(PID=="11")  mychain->Add(("/afs/cern.ch/work/c/conti/public/AF2/ISF_HitAnalysis_evgen_calo__"+PID+"_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.pool.root").c_str());
+    //string inputfile="root:://eos/atlas/user/c/conti/atlasreadable/AF2/ISF_HitAnalysis_evgen_calo__"+PID+"_E50000_50000_eta20_25_Evts0-5500_vz_0_origin_calo.standard.pool.root";
+  }
+
+  if(ismatched)
+  { 
+    //inputfile="/afs/cern.ch/work/c/conti/private/ISF_FastCaloSimParametrization/INPUT/user.zmarshal.8071918._000001.matched_output.root"; 
+    //inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/00/24/user.zmarshal.7814824._000001.matched_output.root"; //v1_w2_160301
+    //inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/4d/19/user.zmarshal.7805067._000001.matched_output.root"; //v0_w2_160229
+    // GOOD : inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/78/74/user.zmarshal.8071918._000001.matched_output.root"; //w0_160406_5mmMerge
+    //inputfile="root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/zmarshal/44/b4/user.zmarshal.8071920._000001.matched_output.root"; //w0_160406_1mmMerge
+
+    // Dataset 1 - optimized merging scheme
+    TChain* mychain=new TChain("FCS_ParametrizationInput");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/88/05/user.fladias.8834798._000001.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/cb/ec/user.fladias.8834798._000002.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/d6/d5/user.fladias.8834798._000003.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/b0/a6/user.fladias.8834798._000004.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/6f/4f/user.fladias.8834798._000005.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/5d/6c/user.fladias.8834798._000006.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/e8/71/user.fladias.8834798._000007.matched_output.root");
+    mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/15/9f/user.fladias.8834798._000008.matched_output.root");
+
+    // Dataset 2 - 1mm merging scheme
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/76/8c/user.fladias.8834800._000001.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/25/5c/user.fladias.8834800._000002.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/7c/11/user.fladias.8834800._000003.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/4e/1f/user.fladias.8834800._000004.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/ca/6b/user.fladias.8834800._000005.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/68/51/user.fladias.8834800._000006.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/4d/ea/user.fladias.8834800._000007.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/ed/d9/user.fladias.8834800._000008.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/f7/0e/user.fladias.8834800._000009.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/6e/67/user.fladias.8834800._000010.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/4a/f5/user.fladias.8834800._000011.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/70/a8/user.fladias.8834800._000012.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/96/61/user.fladias.8834800._000013.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/d6/f0/user.fladias.8834800._000014.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/8d/eb/user.fladias.8834800._000015.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/60/f3/user.fladias.8834800._000016.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/07/71/user.fladias.8834800._000017.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/a1/b6/user.fladias.8834800._000018.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/12/2b/user.fladias.8834800._000019.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/0b/bc/user.fladias.8834800._000020.matched_output.root");
+    //mychain->Add("root://eosatlas//eos/atlas/atlasgroupdisk/soft-simul/rucio/user/fladias/13/43/user.fladias.8834800._000021.matched_output.root");
+
+    // whih eta slice to consider 
+    etaslice.push_back(0.20);
+    etaslice.push_back(0.25);
+  }
+
+  float layer=2;
+  int PCAbin=1;
+  int nybinsR=20;
+  float mincalosize=-1000;
+  
+  ostringstream os;
+  os << layer ;
+  ostringstream os2;
+  os2 << PCAbin ;
+  string labeloutput  = "50GeV_"+particle+"_layer"+os.str()+"_PCAbin"+os2.str();
+  string labeltitle   = "50 GeV "+sparticle+"^{#pm}, layer "+os.str()+", bin(PCA)="+os2.str();
+  
+  // geometry
+  float cell_deta=0;
+  float cell_dphi=0;
+  float cellr=0;
+  float cellz=0;
+  float celleta=0;
+
+  //// Determine the binning
+  DetailedShapeBinning* mydetailedshape=new DetailedShapeBinning();
+  bool test = mydetailedshape->run(doNNHit,ismatched,mychain,nybinsR,layer, particle, PCAbin, labeltitle, labeloutput,mincalosize,cell_deta,cell_dphi,cellr,cellz,celleta,etaslice);
+  //
+  ////// To perform the NN fit of the shower shape 
+  float calosize = 15;
+  //string outfile = "output/DetailedShape_"+labeloutput+"_NNHits.root";
+  string outfile = "output/DetailedShape_"+labeloutput+".root";
+  FitDetailedShape* myfit = new FitDetailedShape(); 
+  int mycase = 0 ; 
+  ////
+  //// Fit shower shape 
+  mycase = 1 ; 
+  int verbose_level = 1;
+  myfit->run(outfile,verbose_level,labeltitle,labeloutput,mycase,mincalosize,doNNHit);
+  //// To create the file based on the sim hits
+  //doNNHit = 1 ; 
+  //myfit->run(outfile,verbose_level,labeltitle,labeloutput,mycase,mincalosize,doNNHit);
+  //////// Fit input variables 
+  //mycase = 2 ; 
+  //doNNHit = 0 ; 
+  //myfit->run(outfile,verbose_level,labeltitle,labeloutput,mycase,mincalosize,doNNHit);
+  ////
+
+  // Redo analysis with simulated hits for mycase=2
+  //
+  //doNNHit = 1 ;
+  //inputfile = "/afs/cern.ch/work/c/conti/private/ISF_FastCaloSimParametrization/tools/output/NNHit_50GeV_pi_layer2_PCAbin0.root";
+  //bool test = mydetailedshape->run(doNNHit,ismatched,inputfile,nybinsR,layer, particle, PCAbin, labeltitle, labeloutput,mincalosize,cell_deta,cell_dphi,cellr,cellz,celleta);
+  //
+  //myfit->run(outfile,verbose_level,labeltitle,labeloutput,mycase,mincalosize,doNNHit);
+  //
+  std::cout << "END " <<  std::endl;
+
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C
index f3d4c1a16fba67caf0869faee6e96c285ea3487c..3910d43f3dcdc165af8adbf6c73e66def450da9a 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runPCA.C
@@ -3,33 +3,67 @@
 */
 
 {
-	
+
+ //!!!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 inputfile="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";
- string label="pions";
+ string label;
+ vector<string> input;
  
- int numberfinebins=5000; //for the finely binned cumulative distributions
- double cut_edeposit=0.001;  //to get the relevant layers (sum_efraction/events>cut_edeposit)
+ //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");
  
- int nbinscompo1=5;	// number of bins in the 1st component
- int nbinscompo2=2;	// number of bins in the 2nd component (per bin in the 1st component)
- // total number of bins=nbinscompo1*nbinscompo2
+ //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");
  
- if(nbinscompo2==0)
+ cout<<"*** Preparing to run on "<<label<<" ***"<<endl;
+ TChain* mychain= new TChain("FCS_ParametrizationInput");
+ for(int i=0;i<input.size();i++)
  {
- 	nbinscompo2=1;
- 	cout<<"Setting nbinscompo2 to 1"<<endl;
+ 	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();
  
- firstPCA *myfirstPCA=new firstPCA();
- string PCA1outputname=myfirstPCA->run(inputfile,label,nbinscompo1,nbinscompo2,numberfinebins,cut_edeposit);
+ 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();
  
- secondPCA* mysecondPCA=new secondPCA();
- mysecondPCA->run(PCA1outputname,label,nbinscompo1,nbinscompo2,numberfinebins);
+ //add validation class
  
  
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a645854233bc180f08d933360cfb65f5a316ce08
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosure.cxx
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//void run(TString sampling="Sampling_0"){
+{
+  gStyle->SetOptStat(0);
+  gStyle->SetPalette(1);
+
+  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("CaloGeometryFromFile.cxx+");
+    
+  gROOT->LoadMacro("wiggleClosureAndComparison.cxx+");
+ 
+  wiggleClosureAndComparison("Sampling_1");
+ 
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..56cdbca3e99d7e944e3b8740d2cbf59b2296055e
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/runWiggleClosureInputs.cxx
@@ -0,0 +1,26 @@
+/*
+  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("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");
+
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/testPersistency.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/testPersistency.C
index fcb056a073cd222a02199b8e0b5ae1b0372f54bc..22a10658679cc31102844befbe666ed2f2ae7e1e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/testPersistency.C
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/testPersistency.C
@@ -13,9 +13,13 @@
   {
     gSystem->AddIncludePath(" -I.. ");
 
-    gROOT->LoadMacro("../Root/myMsgLogger.cxx+");
     gROOT->LoadMacro("../ISF_FastCaloSimParametrization/MeanAndRMS.h+");
-/*
+    gROOT->LoadMacro("../Root/IntArray.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/TFCSExtrapolationState.cxx+");
     gROOT->LoadMacro("../Root/TFCSTruthState.cxx+");
     gROOT->LoadMacro("../Root/TFCSSimulationState.cxx+");
@@ -23,95 +27,25 @@
     gROOT->LoadMacro("../Root/TFCSParametrization.cxx+");
     gROOT->LoadMacro("../Root/TFCSEnergyParametrization.cxx+");
     gROOT->LoadMacro("../Root/TFCSPCAEnergyParametrization.cxx+");
-//    gROOT->LoadMacro("../Root/TFCS1DFunctionHistogram.cxx+");
-  //  gROOT->LoadMacro("../Root/TFCS1DFunctionRegression.cxx+");
-    gROOT->LoadMacro("../Root/TFCS1DFunction.cxx+");
-    gROOT->LoadMacro("../Root/TFCSFunction.cxx+");
+/*
     gROOT->LoadMacro("../Root/TFCSLateralShapeParametrization.cxx+");
     gROOT->LoadMacro("../Root/TFCSNNLateralShapeParametrization.cxx+");
     gROOT->LoadMacro("../Root/TFCSSimpleLateralShapeParametrization.cxx+");
 */
-    gROOT->LoadMacro("../Root/TFCS1DFunction.cxx+");
-    gROOT->LoadMacro("../Root/TFCS1DFunctionRegression.cxx+");
-    gROOT->LoadMacro("../Root/TFCS1DFunctionHistogram.cxx+");
-    gROOT->LoadMacro("../Root/TFCSFunction.cxx+");
   }
   
   //test the TFCSFunction:
   
   //that one works well:
-  /*
-  TFile *input=TFile::Open("PCA2_bin0_pions_new_2dbin_10bins.root");
-  TH1D* hist=(TH1D*)input->Get("h_cumulative_total")); hist->SetName("hist");
+  //TFile *input=TFile::Open("PCA2_bin0_pions_new_2dbin_10bins.root");
+  //TH1D* hist=(TH1D*)input->Get("h_cumulative_total")); hist->SetName("hist");
   
   //that one crashes:
-  //TFile *input=TFile::Open("PCA2_bin8_pions_calo_10bins.root");
-  //TH1D* hist=(TH1D*)input->Get("h_cumulative_PCA_3")); hist->SetName("hist");
+  TFile *input=TFile::Open("PCA2_bin8_pions_calo_10bins.root");
+  TH1D* hist=(TH1D*)input->Get("h_cumulative_PCA_3")); hist->SetName("hist");
   
-  TFCS1DFunction* fct=TFCSFunction::Create(hist);
+  TFCS1DFunction* fct=TFCSFunction::Create(hist,0);
   cout<<fct<<endl;
-    
-  //save fct
-  TFile* output=new TFile("test.root","RECREATE");
-  output->Add(fct);
-  output->Write();
-  */
-  
-  /*
-  TFile* file=TFile::Open("output/secondPCA_pions_nbins1st5_nbins2nd2.root");
-  vector<int> layerNr; 
-  TH2I* h_layer=(TH2I*)file->Get("h_layer");
-  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");
-  int pcabins=h_layer->GetNbinsX();
-  //get a random PCA bin:
-  TRandom* Random=new TRandom3();
-  Random->SetSeed(0);
-  double uniform=Random->Uniform(1);
-  int randombin=0;
-  for(int n=0;n<nbins;n++)
-  {
-   if(uniform>n*1.0/(double)pcabins && uniform<(n+1.)*1.0/(double)pcabins)
-   	randombin=n;
-  }
-  stringstream ss;
-  ss << randombin;
-  string randombinstr = ss.str();
-  //for this random bin, store the info of the cumulatives:
-  TIter next(file->GetListOfKeys());
-  TKey *key;
-  while ((key = (TKey*)next()))
-  {
-   TDirectory* bindir=(TDirectory*)key->ReadObj();
-   bindir->cd();
-   string binname="bin"+randombinstr;
-   if(bindir->GetName()==binname)
-   {
-    cdbin->cd();
-    for(unsigned int l=0;l<layer.size();l++)
-    {
-     TH1D* hist=(TH1D*)file->Get(Form("h_cumul_%s",layer[l].c_str())); hist->SetName("hist");
-     TFCS1DFunction* fct=TFCSFunction::Create(hist);
-    }
-   }
-  }
   
-  //perform the simulation:  
-  TFCSPCAEnergyParametrization* etest=new TFCSPCAEnergyParametrization("etest","etest");
-  etest->loadInputs(file);
-  const TFCSTruthState* truth=new TFCSTruthState();
-  const TFCSExtrapolationState* extrapol=new TFCSExtrapolationState();
-  TFCSSimulationState simulstate;
-  simulstate.set_Ebin(randombin);
-  etest->simulate(simulstate, truth, extrapol);
-  */
-   
 }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_DetailedShape.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_DetailedShape.C
new file mode 100644
index 0000000000000000000000000000000000000000..cca3ec3fa36888adc2cb56854929a731e4a6e2d4
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_DetailedShape.C
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+void validate_DetailedShape(){
+
+  gSystem->AddIncludePath(" -I.. ");
+
+  int Ntoys=10000;
+  TRandom1* myRandom =new TRandom1(); myRandom->SetSeed(0);
+  TRandom1* myRandom2=new TRandom1(); myRandom2->SetSeed(1000);
+
+  const TFCSTruthState* truth=new TFCSTruthState();
+  const TFCSExtrapolationState* extrapol=new TFCSExtrapolationState();
+
+  for(int i=0;i<Ntoys;i++)
+    {
+      double random  = myRandom->Uniform(0,1);
+      double random2 = myRandom2->Uniform(0,1);
+
+      if(i%100==0)
+        cout<<"Now run simulation for Toy "<<i<<endl;
+
+      TFCSNNLateralShapeParametrization* shapetest=new TFCSNNLateralShapeParametrization("shapetest","shapetest");
+
+      TFCSSimulationState simulstate;
+      simulstate.set_Ebin(randombin);
+      shapetest->simulate(simulstate, truth, extrapol);
+
+    }
+  
+  std::cout << "END " <<  std::endl;
+
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_Epara.C b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_Epara.C
new file mode 100644
index 0000000000000000000000000000000000000000..b34e2f2778a44ff0de706b099272a660f1d3b3c2
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/validate_Epara.C
@@ -0,0 +1,314 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+{
+  if(1==0)
+  {
+    // Needs athena environment setup and ISF_FastCaloSimParametrization package compiled.
+    // Uses the root interface library created in the compilation of ISF_FastCaloSimParametrization
+    gSystem->Load("libISF_FastCaloSimParametrizationLib.so");
+  }
+  else
+  {
+    gSystem->AddIncludePath(" -I.. ");
+    
+    gROOT->LoadMacro("../Root/IntArray.cxx+");
+    gROOT->LoadMacro("../Root/TreeReader.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/TFCSExtrapolationState.cxx+");
+    gROOT->LoadMacro("../Root/TFCSTruthState.cxx+");
+    gROOT->LoadMacro("../Root/TFCSSimulationState.cxx+");
+    gROOT->LoadMacro("../Root/TFCSParametrizationBase.cxx+");
+    gROOT->LoadMacro("../Root/TFCSParametrization.cxx+");
+    gROOT->LoadMacro("../Root/TFCSEnergyParametrization.cxx+");
+    gROOT->LoadMacro("../Root/TFCSPCAEnergyParametrization.cxx+");
+    gROOT->LoadMacro("../Root/EnergyParametrizationValidation.cxx+");
+/*
+    gROOT->LoadMacro("../Root/TFCSLateralShapeParametrization.cxx+");
+    gROOT->LoadMacro("../Root/TFCSNNLateralShapeParametrization.cxx+");
+    gROOT->LoadMacro("../Root/TFCSSimpleLateralShapeParametrization.cxx+");
+*/
+  }
+  
+  string samplename="pions";
+  //string samplename="pions_s2864";
+  //string samplename="pions_s2865";
+  
+  int setbin=0;
+  cout<<"PCA bin (-1 if random)? "<<endl;
+  cin>>setbin;
+  
+  //Prepare the Histograms
+  cout<<"Preparing validation histograms"<<endl;
+  TFile* file1=TFile::Open(Form("output/firstPCA_%s.root",samplename.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>=0 && 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);
+  
+  //Run the loop:
+  int ntoys=5000;
+  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;
+   
+   double uniform=Random->Uniform(1);
+   int randombin=0;
+   for(int n=0;n<pcabins;n++)
+   {
+    if(uniform>n*1.0/(double)pcabins && uniform<(n+1.)*1.0/(double)pcabins)
+     randombin=n;
+   }
+   if(setbin>=0)
+    randombin=setbin;
+   h_randombin->Fill(randombin);
+   
+   cout<<"call etest"<<endl;
+     
+   TFCSPCAEnergyParametrization* etest=new TFCSPCAEnergyParametrization("etest","etest");
+   TFile* file2;
+   if(setbin!=-1) file2=TFile::Open(Form("output/secondPCA_%s_bin%i.root",samplename.c_str(),randombin));
+   else           file2=TFile::Open(Form("output/secondPCA_%s.root",samplename.c_str()));
+   if(setbin!=-1) etest->loadInputs(file2);
+   else           etest->loadInputs(file2,randombin);
+   file2->Close();
+   delete file2;
+   
+      
+   TFCSSimulationState simulstate;
+   simulstate.set_Ebin(randombin);
+   
+   
+   cout<<"simulate"<<endl;
+   etest->simulate(simulstate, truth, extrapol);
+   delete etest;
+   
+   //fill the Histograms:
+   double sum_fraction_elmag=0.0;
+   double sum_fraction_had=0.0;
+   
+   for(int s=0;s<30;s++)
+   {
+   	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.E(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.E(s);
+      if(is_had)   sum_fraction_had+=simulstate.E(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 make 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],h_output[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(0.1);
+   h_output_lin->SetLineWidth(0.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*)TFCS1DFunction::get_cumul(h_output_lin); h_output_cumul->SetName("h_output_cumul");
+   TH1D* h_input_cumul =(TH1D*)TFCS1DFunction::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();
+   
+   if(setbin>=0)
+    can->Print(Form("plots/%s_%s_bin%i.pdf",samplename.c_str(),name[l].c_str(),setbin));
+   else
+   	can->Print(Form("plots/%s_%s.pdf",samplename.c_str(),name[l].c_str()));
+   can->Close();
+   
+  } //for layer
+  
+  //TCanvas* can=new TCanvas("can","can",0,0,800,600);  h_randombin->Draw();
+  
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..afa63f02a02bd8d4a3cc9087a32f550a5be73a58
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggleClosureAndComparison.cxx
@@ -0,0 +1,663 @@
+/*
+  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 "TFile.h"
+#include "TTree.h"
+#include "TString.h"
+#include "TRandom3.h"
+#include "TRandom.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 "TProfile2D.h"
+#include "TVector2.h"
+#include <vector>
+#include "TCanvas.h"
+#include "TSystem.h"
+#include "TMath.h"
+#include <map>
+
+using namespace std;
+
+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");
+  
+  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 *PCAfile = TFile::Open("firstPCA_pions_flavia.root");
+  
+  TTree *inputTree = ( TTree* ) originalFile->Get( "FCS_ParametrizationInput" );
+  FCS_matchedcellvector *vec=0; //this need to be set to 0!
+  inputTree->SetBranchAddress(sampling,&vec);
+  
+  TTree *PCAtree = ( TTree* ) PCAfile->Get( "firstPCA" );
+  int PCAbin = -99;
+  PCAtree->SetBranchAddress("bin",&PCAbin);  
+  
+  std::vector<FCS_truth> *truth=0; //does this also need to be zero?
+  inputTree->SetBranchAddress("TruthCollection",&truth);
+  
+  //Now instead of loading the file, I make the closure in the same job
+  /* TFile *closureFile = TFile::Open("wiggle_ClosureOutput_"+sampling+".root");
+  TTree *closureTree = ( TTree* ) closureFile->Get( "FCS_ClosureOutput" );
+  vector<FCS_cell> *vect=0; //this need to be set to 0!
+  closureTree->SetBranchAddress(sampling,&vect);
+  */
+
+
+  /////////////////////////////////
+  //     Start of wiggle def     //
+  /////////////////////////////////
+
+  //efficiency inputs from file  
+  TFile *effFile = TFile::Open("wiggle_efficiency_"+sampling+".root");
+  TH1F *eff_phi = ( TH1F* ) effFile->Get( "eff_phi_"+sampling );
+
+  //have to change to get the wiggle derivative instead
+  double eff_int[50]; 
+  eff_int[0] = eff_phi->GetBinContent(1);
+  for (int i=1; i<50; i++){
+    eff_int[i] = eff_int[i-1] + eff_phi->GetBinContent(i+1);
+  }
+  
+  for (int j=0; j<50; j++){
+    cout << eff_int[j] << endl;
+  }
+  
+  /////////////////////////////////
+  //      End of wiggle def      //
+  /////////////////////////////////
+
+ 
+  //Histogram definitions
+  
+  TProfile2D *dEta_dPhi[11];
+  TH2F *dEta_dPhi_N[11];
+  TH2F *dEta_dPhi_res[11];
+  TH2F *dEta_dPhi_N_res[11];
+  
+  TProfile2D *dEta_dPhi_avg_reco[11];
+  TProfile2D *dEta_dPhi_avg_g4[11];
+  TProfile2D *dEta_dPhi_FCS_orig[11];
+  TProfile2D *dEta_dPhi_FCS_matched[11];
+  TProfile2D *dEta_dPhi_FCS_orig_overAvg[11];
+  TProfile2D *dEta_dPhi_FCS_matched_overAvg[11];
+  TH2F *dEta_dPhi_FCS_orig_overAvg_N[11];
+  TH2F *dEta_dPhi_FCS_matched_overAvg_N[11];
+  TProfile2D *subtraction[11];
+
+  //10 is inclusive
+  //0-9 is for each of the PCA bins
+  
+  int nbins_eta;
+  int nbins_phi;
+  
+  if (sampling == "Sampling_1" || sampling == "Sampling_2" || sampling == "Sampling_3"){
+    //cout << "Sampling_2" << endl;
+    //    nbins_eta = 120;
+    // nbins_phi = 120;
+    nbins_eta = 120;
+    nbins_phi = 120;
+  }
+  else if(sampling == "Sampling_12" || sampling == "Sampling_13"){
+    nbins_eta = 12;
+    nbins_phi = 12;
+  }
+  else if(sampling == "Sampling_0"){
+    nbins_eta = 60;
+    nbins_phi = 60;
+  }
+
+  else if(sampling == "Sampling_14"){
+    nbins_eta = 10;
+    nbins_phi = 10;
+  } 
+
+  for (int i=0; i<11; i++){
+    TString layerName=sampling+"_Layer_";
+    layerName+=i;
+    
+    dEta_dPhi[i] = new TProfile2D("closure_dEtadPhi_Layer_"+layerName, "closure_dEtadPhi_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_N[i] = new TH2F("closure_dEtadPhi_N_Layer_"+layerName, "closure_dEtadPhi_N_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    
+    dEta_dPhi_res[i] = new TH2F("closure_dEtadPhi_res_Layer_"+layerName, "closure_dEtadPhi_res_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_N_res[i] = new TH2F("closure_dEtadPhi_N_res_Layer_"+layerName, "closure_dEtadPhi_N_res_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    
+    dEta_dPhi_avg_reco[i] = new TProfile2D("dEta_dPhi_avg_reco_Layer_"+layerName, "dEta_dPhi_avg_reco_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_avg_g4[i] = new TProfile2D("dEta_dPhi_avg_g4_Layer_"+layerName, "dEta_dPhi_avg_g4_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_FCS_orig[i] = new TProfile2D(" dEta_dPhi_FCS_orig_Layer_"+layerName, " dEta_dPhi_FCS_orig_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_FCS_matched[i] = new TProfile2D("dEta_dPhi_FCS_matched_Layer_"+layerName, "dEta_dPhi_FCS_matched_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+
+    dEta_dPhi_FCS_orig_overAvg[i] = new TProfile2D("dEta_dPhi_FCS_orig_overAvg_Layer_"+layerName, "dEta_dPhi_FCS_orig_overAvg_reco_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_FCS_matched_overAvg[i] = new TProfile2D("dEta_dPhi_FCS_matched_overAvg_Layer_"+layerName, "dEta_dPhi_FCS_matched_overAvg_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+
+    dEta_dPhi_FCS_orig_overAvg_N[i] = new TH2F("dEta_dPhi_FCS_orig_overAvg_N_Layer_"+layerName, "dEta_dPhi_FCS_orig_overAvg_N_reco_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+    dEta_dPhi_FCS_matched_overAvg_N[i] = new TH2F("dEta_dPhi_FCS_matched_overAvg_N_Layer_"+layerName, "dEta_dPhi_FCS_matched_overAvg_N_Layer_"+layerName, nbins_eta, -0.5, 0.5, nbins_phi, -0.5, 0.5);
+
+  }
+  //end of histogram definitions
+
+  //define maps to be used in analysis
+  std::map<Long64_t, double> Eoriginal;
+  std::map<Long64_t, double> EoriginalG4;  
+  std::map<Long64_t, double> EoriginalReco;
+  std::map<Long64_t, double> Eclosure;
+  //end of maps definition
+
+  std::cout << "Sampling is " << sampling << std::endl;
+
+  Int_t nEvt = inputTree->GetEntries();
+  std::cout << "nEvt " << nEvt << std::endl;
+
+  Int_t nEvtPCA = PCAtree->GetEntries();
+  std::cout << "nEvt3 " << nEvtPCA << std::endl;
+
+  //start event loop
+  for (Int_t ientry=0; ientry<nEvt; ientry++){
+    
+    inputTree->GetEntry(ientry);   
+    if(ientry%100 == 0)  
+      std::cout << "Processing event # " << ientry << std::endl;
+
+    PCAtree->GetEntry(ientry);
+    //cout << "PCAbin " << PCAbin << endl;
+    //cout << "PCAevtN " << PCAevtN << endl;
+    //cout << endl;
+
+    //clean the maps before the start of the event
+    Eoriginal.clear();
+    EoriginalG4.clear();
+    EoriginalReco.clear();
+    Eclosure.clear();
+ 
+    //variables to store, for this event
+    double sum_energy_hit = 0.0;
+    double sum_energy_g4hit = 0.0;
+    double trEta = 0.0;
+    double trPhi = 0.0;
+    //cout << "TTC_entrance_eta " << (*truth)[0].TTC_entrance_eta.size() << " " << (*truth)[0].TTC_entrance_eta[0] << endl; 
+    //cout << "TTC_entrance_phi " << (*truth)[0].TTC_entrance_phi.size() << " " << (*truth)[0].TTC_entrance_phi[0] << endl; 
+    //cout << endl;
+    trEta = (*truth)[0].TTC_entrance_eta[0];
+    trPhi = (*truth)[0].TTC_entrance_phi[0];
+    
+    //loop over cells in sampling to sum its energy on the layer
+    for (UInt_t j=0; j<(*vec).size(); j++){    
+      sum_energy_hit = 0.0;
+      sum_energy_g4hit = 0.0;
+
+      //loop over hits in each cell to find the sum of the hit energies in the layer
+      for (int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
+        sum_energy_hit = sum_energy_hit + ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy;
+      }
+
+      for (int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).g4hit.size(); ihit++){
+        sum_energy_g4hit = sum_energy_g4hit + ((FCS_matchedcell)(*vec)[j]).g4hit[ihit].hit_energy;
+      }
+
+      //now I have the hit energy in a given cell, and I store it in a map
+      //cout << endl;
+      //cout << ((FCS_matchedcell)(*vec)[j]).cell.cell_identifier << endl;
+      //cout << sum_energy_hit << endl;
+      Eoriginal.insert(std::pair<Long64_t, double>(((FCS_matchedcell)(*vec)[j]).cell.cell_identifier, sum_energy_hit));
+      EoriginalReco.insert(std::pair<Long64_t, double>(((FCS_matchedcell)(*vec)[j]).cell.cell_identifier, ((FCS_matchedcell)(*vec)[j]).cell.energy));
+      EoriginalG4.insert(std::pair<Long64_t, double>(((FCS_matchedcell)(*vec)[j]).cell.cell_identifier, sum_energy_g4hit));
+    } //end of loop over cells of originalTree
+    ///////////////////////
+     
+
+
+
+    //NOW make the average shower shapes by looping over all maps
+    for ( std::map<Long64_t, double>::iterator it = Eoriginal.begin(); it!=Eoriginal.end(); it++) {
+      
+      Long64_t myID = it->first;
+
+      const CaloDetDescrElement* cell;
+      Identifier cellid(myID);
+      cell=geo->getDDE(cellid);
+      
+      double dEta = trEta - cell->eta();
+      double dPhi = TVector2::Phi_mpi_pi(trPhi - cell->phi());
+
+      dEta_dPhi_FCS_orig[10]->Fill(dEta, dPhi, (it->second));
+      dEta_dPhi_FCS_orig[PCAbin]->Fill(dEta, dPhi, (it->second));
+        
+    }
+
+
+
+    for ( std::map<Long64_t, double>::iterator it = EoriginalReco.begin(); it!=EoriginalReco.end(); it++) {
+      
+      Long64_t myID = it->first;
+
+      const CaloDetDescrElement* cell;
+      Identifier cellid(myID);
+      cell=geo->getDDE(cellid);
+      
+      double dEta = trEta - cell->eta();
+      double dPhi = TVector2::Phi_mpi_pi(trPhi - cell->phi());
+
+      dEta_dPhi_avg_reco[10]->Fill(dEta, dPhi, (it->second));
+      dEta_dPhi_avg_reco[PCAbin]->Fill(dEta, dPhi, (it->second));
+        
+    }
+
+    for ( std::map<Long64_t, double>::iterator it = EoriginalG4.begin(); it!=EoriginalG4.end(); it++) {
+      
+      Long64_t myID = it->first;
+
+      const CaloDetDescrElement* cell;
+      Identifier cellid(myID);
+      cell=geo->getDDE(cellid);
+      
+      double dEta = trEta - cell->eta();
+      double dPhi = TVector2::Phi_mpi_pi(trPhi - cell->phi());
+
+      dEta_dPhi_avg_g4[10]->Fill(dEta, dPhi, (it->second));
+      dEta_dPhi_avg_g4[PCAbin]->Fill(dEta, dPhi, (it->second));
+        
+    }
+
+  } //end of event loop
+  
+
+
+
+  //  TH2F * cl_ratio = (TH2F*)dEta_dPhi[0]->Clone("cl_ratio_"+sampling);
+  //cl_ratio->Divide(dEta_dPhi_N[0]);
+  //cl_ratio->GetXaxis()->SetTitle("d#eta");
+  //cl_ratio->GetYaxis()->SetTitle("d#phi");
+  //cl_ratio->Draw("colz");
+
+  //Now I have to run over events again to get the ratio to the average 
+  for (Int_t ientry=0; ientry<nEvt; ientry++){
+    
+    inputTree->GetEntry(ientry);   
+    if(ientry%100 == 0)  
+      std::cout << "Processing event # " << ientry << std::endl;
+    PCAtree->GetEntry(ientry);
+
+    Eoriginal.clear();
+    EoriginalG4.clear();
+    EoriginalReco.clear();
+    Eclosure.clear();
+
+    double trEta = 0.0;
+    double trPhi = 0.0;
+
+    trEta = (*truth)[0].TTC_entrance_eta[0];
+    trPhi = (*truth)[0].TTC_entrance_phi[0];
+
+    double sum_energy_hit = 0.0; 
+
+    for (UInt_t j=0; j<(*vec).size(); j++){    
+      // sum_energy_hit = 0.0;
+      //loop over hits and assigning energy to cells
+      for (int ihit=0; ihit<((FCS_matchedcell)(*vec)[j]).hit.size(); ihit++){
+	// sum_energy_hit = sum_energy_hit + ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy;
+	//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* someCell;
+	someCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
+
+	Long64_t someCellID = someCell->identify();
+	
+	if (Eoriginal.find(someCellID) != Eoriginal.end()){
+	  std::map<Long64_t, double>::iterator someit = Eoriginal.find(someCellID);
+	  someit->second+=((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy;
+	} //end cells exist
+	
+	else {
+	  Eoriginal.insert(std::pair<Long64_t, double>(someCellID, ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy));
+	}//end of else creating new cell	
+      } //end hit loop
+      
+      //Eoriginal.insert(std::pair<Long64_t, double>(((FCS_matchedcell)(*vec)[j]).cell.cell_identifier, sum_energy_hit));
+    }//loop over cells
+
+    
+    
+
+    ///////////////////////////////////
+    //    Wiggle assignment start    //
+    ///////////////////////////////////
+   
+    
+    //loop over cells in sampling
+    for (UInt_t j=0; j<(*vec).size(); j++){
+      
+      Long64_t cell_ID = 0;
+      cell_ID = ((FCS_matchedcell)(*vec)[j]).cell.cell_identifier;
+      
+      //set random numbers
+      TRandom3 *random1 = new TRandom3();
+      random1->SetSeed(0);
+      
+      //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 (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* initCell;
+	initCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
+	
+	if (initCell && cell){	  
+	  float efficiencyEta = ( (2.0*(hitVec->Eta()-initCell->eta()))/initCell->deta());
+	  float efficiencyPhi = ( (2.0*(hitVec->Phi()-initCell->phi()))/initCell->dphi());
+	  
+	  double searchRand = random1->Rndm(0);
+	  //cout << searchRand << endl;
+	  int chosenBin = (Int_t) TMath::BinarySearch(50, eff_int, searchRand);
+	  //cout << chosenBin << endl; 
+	  //cout << "x axis value:  " << eff_phi->GetBinCenter(chosenBin+2) << endl; 
+	  //cout << endl;
+	  //double wigglePhi = (eff_phi->GetBinCenter(chosenBin+2))/2;
+	  double wigglePhi = 0.0;
+	  //change the wiggle for the derivative
+	  if (sampling=="Sampling_1"){
+	    if (efficiencyPhi>0.76){
+	      //cout << "plus yoo" << endl;
+	      //wigglePhi = (0.24*searchRand);
+	      wigglePhi = (eff_phi->GetBinCenter(chosenBin+2))/2;
+	    }
+	    else if (efficiencyPhi<-0.76){
+	      //cout << "minus yoo" << endl;
+	      //wigglePhi = -(0.24*searchRand);
+	      wigglePhi = (eff_phi->GetBinCenter(chosenBin+2))/2;
+	    }/// FAD FAD FAD ///
+	    else
+	      wigglePhi = 0.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()));
+
+	  //deposit energy in specific cell
+	  Long64_t foundCellID = foundCell->identify();
+	  if (Eclosure.find(foundCellID) != Eclosure.end()){
+	    std::map<Long64_t, double>::iterator it = Eclosure.find(foundCellID);
+	    // found cell iD: foundCell->identify()
+	    it->second+=((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy;
+	  } //end cells exist
+	  else {
+	    //create the cell --> OK assigned probabilistically although not really in terms of cell IDs
+	    Eclosure.insert(std::pair<Long64_t, double>(foundCellID, ((FCS_matchedcell)(*vec)[j]).hit[ihit].hit_energy));
+	  }//end of else creating new cell
+	} //end if cell ok
+      } //end loop over hits
+      
+    } //end loop on cells
+
+
+    ///////////////////////////////////
+    //     Wiggle assignment end     //
+    ///////////////////////////////////
+
+    //now I iterate over my closure file and fill the plots
+    for ( std::map<Long64_t, double>::iterator it2 = Eclosure.begin(); it2!=Eclosure.end(); it2++) {
+      
+      Long64_t myID = it2->first;
+      const CaloDetDescrElement* cell;
+      Identifier cellid(myID);
+      cell=geo->getDDE(cellid);
+      
+      double dEta = trEta - cell->eta();
+      double dPhi = TVector2::Phi_mpi_pi(trPhi - cell->phi());
+
+      Int_t binReco = dEta_dPhi_avg_reco[10]->FindBin(dEta, dPhi);
+      double eReco = dEta_dPhi_avg_reco[10]->GetBinContent(binReco);
+      Int_t binG4 = dEta_dPhi_avg_g4[10]->FindBin(dEta, dPhi);
+      double eG4 = dEta_dPhi_avg_g4[10]->GetBinContent(binG4);
+
+      Int_t binRecoPCA = dEta_dPhi_avg_reco[PCAbin]->FindBin(dEta, dPhi);
+      double eRecoPCA = dEta_dPhi_avg_reco[PCAbin]->GetBinContent(binRecoPCA);
+      Int_t binG4PCA = dEta_dPhi_avg_g4[PCAbin]->FindBin(dEta, dPhi);
+      double eG4PCA = dEta_dPhi_avg_g4[PCAbin]->GetBinContent(binG4PCA);
+
+
+      dEta_dPhi_FCS_matched_overAvg[10]->Fill(dEta, dPhi, it2->second/eReco);
+      dEta_dPhi_FCS_matched_overAvg[PCAbin]->Fill(dEta, dPhi, it2->second/eRecoPCA);
+
+      dEta_dPhi_FCS_matched_overAvg_N[10]->Fill(dEta, dPhi);
+      dEta_dPhi_FCS_matched_overAvg_N[PCAbin]->Fill(dEta, dPhi);
+
+
+    }
+
+    for (std::map<Long64_t, double>::iterator it = Eoriginal.begin(); it!=Eoriginal.end(); it++){
+
+      Long64_t myID = it->first;
+      
+      const CaloDetDescrElement* cell;
+      Identifier cellid(myID);
+      cell=geo->getDDE(cellid);
+      
+      double dEta = trEta - cell->eta();
+      double dPhi = TVector2::Phi_mpi_pi(trPhi - cell->phi());
+
+      Int_t binReco = dEta_dPhi_avg_reco[10]->FindBin(dEta, dPhi);
+      double eReco = dEta_dPhi_avg_reco[10]->GetBinContent(binReco);
+      Int_t binG4 = dEta_dPhi_avg_g4[10]->FindBin(dEta, dPhi);
+      double eG4 = dEta_dPhi_avg_g4[10]->GetBinContent(binG4);
+
+      Int_t binRecoPCA = dEta_dPhi_avg_reco[PCAbin]->FindBin(dEta, dPhi);
+      double eRecoPCA = dEta_dPhi_avg_reco[PCAbin]->GetBinContent(binRecoPCA);
+      Int_t binG4PCA = dEta_dPhi_avg_g4[PCAbin]->FindBin(dEta, dPhi);
+      double eG4PCA = dEta_dPhi_avg_g4[PCAbin]->GetBinContent(binG4PCA);
+
+      dEta_dPhi_FCS_orig_overAvg[10]->Fill(dEta, dPhi, it->second/eReco);
+      dEta_dPhi_FCS_orig_overAvg[PCAbin]->Fill(dEta, dPhi, it->second/eRecoPCA);
+ 
+      dEta_dPhi_FCS_orig_overAvg_N[10]->Fill(dEta, dPhi);
+      dEta_dPhi_FCS_orig_overAvg_N[PCAbin]->Fill(dEta, dPhi);
+
+
+    }
+    
+
+  }//end new event loop
+
+  
+  
+  //now print it all
+  TCanvas *c1 = new TCanvas();
+  c1->SetLogz();
+  c1->Divide(1,2);
+  c1->cd(1);
+  dEta_dPhi[0]->Draw("colz");
+  c1->cd(2);
+  dEta_dPhi_N[0]->Draw("colz");  
+
+  c1->Print("wiggle_plots_ClosureTest"+sampling+".pdf(");
+
+
+  TCanvas *c4 = new TCanvas();
+  c4->Divide(1,2);
+  c4->cd(1);
+  dEta_dPhi_res[0]->Draw("colz");
+  c4->cd(2);
+  dEta_dPhi_N_res[0]->Draw("colz");  
+
+  c4->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+
+  TCanvas *c2[11];
+  TCanvas *c3[11];
+
+  TCanvas *cc2[11];
+  TCanvas *cc3[11];
+
+  TCanvas *ccc2[11];
+  TCanvas *ccc3[11];
+
+  TCanvas *ccc4[11];
+  TCanvas *ccc5[11];
+  TCanvas *ccc6[11];
+
+  for (int i=0; i<11; i++){
+    //    c2[i]= new TCanvas();
+    c2[i] = new TCanvas("c2"+i,"c2"+i,2);
+
+    c2[i]->Divide(2,2);
+    c2[i]->cd(1);
+    dEta_dPhi_avg_reco[i]->Draw("colz");
+    c2[i]->cd(2);
+    dEta_dPhi_avg_g4[i]->Draw("colz");
+    c2[i]->cd(3);
+    dEta_dPhi_FCS_orig[i]->Draw("colz");
+    c2[i]->cd(4);
+    dEta_dPhi_FCS_matched[i]->Draw("colz");
+
+    c2[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+
+    //c3[i]= new TCanvas();
+    c3[i] = new TCanvas("c3"+i,"c3"+i,2);
+
+    c3[i]->Divide(2,2);
+    c3[i]->cd(1);
+    dEta_dPhi_avg_reco[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_avg_reco[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_avg_reco[i]->Draw("colz");
+    c3[i]->cd(2);
+    dEta_dPhi_avg_g4[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_avg_g4[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_avg_g4[i]->Draw("colz");
+    c3[i]->cd(3);
+    dEta_dPhi_FCS_orig[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_orig[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_orig[i]->Draw("colz");
+    c3[i]->cd(4);
+    dEta_dPhi_FCS_matched[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_matched[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_matched[i]->Draw("colz");
+
+    c3[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+    //cc2[i] = new TCanvas();
+    cc2[i] = new TCanvas("cc22"+i,"cc22"+i,2);
+
+
+    //cc2[i]->Divide(2,1);
+    //cc2[i]->cd(1);
+    
+    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    // to make bins zero if less than 10 entries
+    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    /*
+    for (int ki=1; ki<nbins_eta+1; ki++){
+      for (int j=1; j<nbins_phi+1; j++){
+
+	if (dEta_dPhi_FCS_matched_overAvg_N[10]->GetBinContent(dEta_dPhi_FCS_matched_overAvg_N[10]->GetBin(ki,j)) < 10){	  
+	  dEta_dPhi_FCS_matched_overAvg[10]->SetBinContent(dEta_dPhi_FCS_matched_overAvg[10]->GetBin(ki,j), 0.0);
+	}
+
+	if (dEta_dPhi_FCS_orig_overAvg_N[10]->GetBinContent(dEta_dPhi_FCS_orig_overAvg_N[10]->GetBin(ki,j)) < 10){	  
+	  dEta_dPhi_FCS_orig_overAvg[10]->SetBinContent(dEta_dPhi_FCS_orig_overAvg[10]->GetBin(ki,j), 0.0);
+	}
+
+
+
+      }
+      }*/
+    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    
+    //cc2[i]->SetLogz();
+    //dEta_dPhi_FCS_orig_overAvg[i]->GetZaxis()->SetRangeUser(0.1,10);
+    //dEta_dPhi_FCS_orig_overAvg[i]->Rebin2D(nrebin);
+    dEta_dPhi_FCS_orig_overAvg[i]->Draw("colz");
+
+
+
+    //ccc2[i] = new TCanvas();
+    ccc2[i] = new TCanvas("cc2"+i,"cc2"+i,2);
+
+    //ccc2[i]->SetLogz();
+    //dEta_dPhi_FCS_matched_overAvg[i]->GetZaxis()->SetRangeUser(0.1,10);
+    //dEta_dPhi_FCS_matched_overAvg[i]->Rebin2D(nrebin);
+    dEta_dPhi_FCS_matched_overAvg[i]->Draw("colz");
+
+
+    cc2[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+    ccc2[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+    //   ccc3[i] = new TCanvas();
+    ccc3[i] = new TCanvas("cc3"+i,"cc3"+i,2);
+
+    subtraction[i] = (TProfile2D*)dEta_dPhi_FCS_orig_overAvg[i]->Clone("subtraction_"+sampling);
+    subtraction[i]->Add(dEta_dPhi_FCS_matched_overAvg[i],-1);
+    subtraction[i]->Draw("colz");
+
+    ccc3[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+
+    //    ccc4[i] = new TCanvas();
+    ccc4[i] = new TCanvas("cc4"+i,"cc4"+i,2);
+
+    //ccc4[i]->SetLogz();
+    dEta_dPhi_FCS_orig_overAvg[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_orig_overAvg[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_orig_overAvg[i]->GetZaxis()->SetRangeUser(0.5,2.0);
+    dEta_dPhi_FCS_orig_overAvg[i]->Draw("colz");
+    ccc4[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+    //ccc5[i] = new TCanvas();
+    ccc5[i] = new TCanvas("cc5"+i,"cc5"+i,2);
+
+    //ccc5[i]->SetLogz();
+    dEta_dPhi_FCS_matched_overAvg[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_matched_overAvg[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    dEta_dPhi_FCS_matched_overAvg[i]->GetZaxis()->SetRangeUser(0.5,2.0);
+    dEta_dPhi_FCS_matched_overAvg[i]->Draw("colz");
+    ccc5[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+
+    ccc6[i] = new TCanvas("cc6"+i,"cc6"+i,2);
+    subtraction[i]->GetXaxis()->SetRangeUser(-0.1,0.1);
+    subtraction[i]->GetYaxis()->SetRangeUser(-0.1,0.1);
+    subtraction[i]->Draw("colz");
+    if (i==10){
+      ccc6[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf)");
+    }
+    else {
+      ccc6[i]->Print("wiggle_plots_ClosureTest"+sampling+".pdf");
+    }
+
+  } // i loop
+
+} //end of main loop
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
new file mode 100644
index 0000000000000000000000000000000000000000..e9f26fddaa2d7b32b969393a1f103c8c99536e5b
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/wiggle_closure_inputs.cxx
@@ -0,0 +1,160 @@
+/*
+  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 "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 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");
+  
+  //  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" );
+
+  FCS_matchedcellvector *vec=0; //this need to be set to 0!
+  inputTree->SetBranchAddress(sampling,&vec);
+
+  //histograms definition
+  TH1F *eff_tot_phi = new TH1F("eff_tot_phi_"+sampling, "eff_tot_phi_"+sampling, 50, -1, 1);
+  TH1F *eff_corr_phi = new TH1F("eff_corr_phi_"+sampling, "eff_corr_phi_"+sampling, 50, -1, 1);
+  TH1F *eff_tot_count_phi = new TH1F("eff_tot_count_phi_"+sampling, "eff_tot_count_phi_"+sampling, 50, -1, 1);
+  TH1F *eff_corr_count_phi = new TH1F("eff_corr_count_phi_"+sampling, "eff_corr_count_phi_"+sampling, 50, -1, 1);
+  eff_corr_phi->Sumw2();
+  eff_tot_phi->Sumw2();
+  eff_corr_count_phi->Sumw2();
+  eff_tot_count_phi->Sumw2();
+
+
+  std::cout << "Sampling is " << sampling << std::endl;
+
+  Int_t nEvt = inputTree->GetEntries();
+  std::cout << "nEvt " << nEvt << std::endl;
+  
+  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;
+    
+    //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;
+
+      //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 (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;
+	foundCell=geo->getDDE(((FCS_matchedcell)(*vec)[j]).hit[ihit].sampling,hitVec->Eta(),hitVec->Phi());
+	
+	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()));
+	  }
+	  
+	} //end if cell ok
+      } //end loop over hits
+    } //end loop on cells   
+  } //end loop on events
+  
+  
+  /*
+  for (Int_t bin1=1; bin1<301; bin1++){
+    for (Int_t bin2=1; bin2<301; bin2++){
+      if (eff_tot_count_phi->GetBinContent(bin1) < 2){
+	eff_tot_phi->SetBinContent(bin1,0.0);
+	eff_corr_phi->SetBinContent(bin1,0.0);
+      }
+      if (eff_corr_count_phi->GetBinContent(bin1) < 2){
+	eff_tot_phi->SetBinContent(bin1,0.0);
+	eff_corr_phi->SetBinContent(bin1,0.0);
+      }
+      
+      }}*/
+  
+  TCanvas *c1 = new TCanvas();
+  eff_tot_phi->Draw();
+  TCanvas *c2 = new TCanvas();
+  eff_corr_phi->Draw();
+
+  TCanvas *c5 = new TCanvas();
+  TH1F *eff_phi;
+  eff_phi = (TH1F*)eff_corr_phi->Clone("eff_phi_"+sampling);
+  eff_phi->Divide(eff_tot_phi);
+  eff_phi->Scale(1.0/eff_phi->Integral());
+  cout << eff_phi->Integral() << endl;
+  eff_phi->SetTitle("Efficiency of cell assigment");
+  eff_phi->GetXaxis()->SetTitle("2*(#phi_{hit}-#phi_{assigCell})/dphi_{assigCell}");
+  eff_phi->GetYaxis()->SetTitle("Efficiency of cell assignment");
+  eff_phi->Draw();
+  
+  double eff_int[50]; 
+  eff_int[0] = eff_phi->GetBinContent(1);
+  for (int i=1; i<50; i++){
+    eff_int[i] = eff_int[i-1] + eff_phi->GetBinContent(i+1);
+  }
+  
+  for (int j=0; j<50; j++){
+    cout << eff_int[j] << endl;
+  }
+
+  TFile f("wiggle_efficiency_"+sampling+".root", "recreate");
+  eff_phi->Write();
+  //eff_int->Write();
+  f.Close();
+  
+
+
+
+}