From 3d0e0163328a64dfffbeec3e7b66ea4288982fea Mon Sep 17 00:00:00 2001
From: Michael Duehrssen <michael.duehrssen@cern.ch>
Date: Sat, 24 Feb 2018 16:17:01 +0100
Subject: [PATCH] Addition of simulation chain elements to select
 parametrizations based on PDGID, eta dn energy.

Former-commit-id: cdf70a0a4ba13440c969b86a1106733909cf486b
---
 .../ISF_FastCaloSimEvent/CMakeLists.txt       |   9 +
 .../ISF_FastCaloSimEvent/LinkDef.h            |  18 ++
 .../TFCSEnergyBinParametrization.h            |  53 ++++++
 .../ISF_FastCaloSimEvent/TFCSInitWithEkin.h   |  36 ++++
 .../TFCSLateralShapeParametrization.h         |   7 +-
 .../TFCSLateralShapeParametrizationHitBase.h  |  19 +-
 .../TFCSLateralShapeParametrizationHitChain.h |  16 +-
 .../TFCSPCAEnergyParametrization.h            |   2 +
 .../TFCSParametrization.h                     |  42 +++--
 .../TFCSParametrizationAbsEtaSelectChain.h    |  31 ++++
 .../TFCSParametrizationBase.h                 |  33 +++-
 .../TFCSParametrizationBinnedChain.h          |  51 ++++++
 .../TFCSParametrizationChain.h                |  24 ++-
 .../TFCSParametrizationEbinChain.h            |  30 ++++
 .../TFCSParametrizationEkinSelectChain.h      |  38 ++++
 .../TFCSParametrizationEtaSelectChain.h       |  37 ++++
 .../TFCSParametrizationFloatSelectChain.h     |  39 ++++
 .../TFCSParametrizationPDGIDSelectChain.h     |  30 ++++
 .../src/TFCSEnergyBinParametrization.cxx      | 122 +++++++++++++
 .../TFCSHistoLateralShapeParametrization.cxx  |   6 +-
 .../src/TFCSHitCellMapping.cxx                |   8 +-
 .../src/TFCSHitCellMappingWiggleEMB.cxx       |   4 +-
 .../src/TFCSInitWithEkin.cxx                  |  24 +++
 .../src/TFCSLateralShapeParametrization.cxx   |  17 +-
 ...TFCSLateralShapeParametrizationHitBase.cxx |  22 +--
 ...FCSLateralShapeParametrizationHitChain.cxx |  68 +++----
 ...eralShapeParametrizationHitNumberFromE.cxx |  13 +-
 .../src/TFCSPCAEnergyParametrization.cxx      |   9 +-
 .../src/TFCSParametrization.cxx               |  27 +++
 .../TFCSParametrizationAbsEtaSelectChain.cxx  | 102 +++++++++++
 .../src/TFCSParametrizationBase.cxx           |  43 +++--
 .../src/TFCSParametrizationBinnedChain.cxx    | 166 ++++++++++++++++++
 .../src/TFCSParametrizationChain.cxx          |  98 +++++++++--
 .../src/TFCSParametrizationEbinChain.cxx      |  72 ++++++++
 .../TFCSParametrizationEkinSelectChain.cxx    | 121 +++++++++++++
 .../src/TFCSParametrizationEtaSelectChain.cxx | 121 +++++++++++++
 .../TFCSParametrizationFloatSelectChain.cxx   | 107 +++++++++++
 .../TFCSParametrizationPDGIDSelectChain.cxx   |  90 ++++++++++
 38 files changed, 1622 insertions(+), 133 deletions(-)
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSInitWithEkin.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyBinParametrization.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSInitWithEkin.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationAbsEtaSelectChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBinnedChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEbinChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEkinSelectChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEtaSelectChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationFloatSelectChain.cxx
 create mode 100644 Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationPDGIDSelectChain.cxx

diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt
index af52921653329..a354d62884591 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt
@@ -33,9 +33,18 @@ atlas_add_root_dictionary( ISF_FastCaloSimEvent _dictSource
                            ISF_FastCaloSimEvent/TFCS1DFunctionRegressionTF.h 
                            ISF_FastCaloSimEvent/TFCSParametrizationBase.h 
                            ISF_FastCaloSimEvent/TFCSParametrization.h 
+                           ISF_FastCaloSimEvent/TFCSInitWithEkin.h
                            ISF_FastCaloSimEvent/TFCSParametrizationChain.h 
+                           ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h
+                           ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h
                            ISF_FastCaloSimEvent/TFCSEnergyParametrization.h 
                            ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h 
+                           ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h
                            ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h
                            ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h
                            ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h
index 64098efdd0234..8a7d8815c0b27 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h
@@ -11,10 +11,19 @@
 
 #include "ISF_FastCaloSimEvent/TFCSParametrizationBase.h"
 #include "ISF_FastCaloSimEvent/TFCSParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSInitWithEkin.h"
 #include "ISF_FastCaloSimEvent/TFCSParametrizationChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h"
 
 #include "ISF_FastCaloSimEvent/TFCSEnergyParametrization.h"
 #include "ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h"
 
 #include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h"
 #include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h"
@@ -38,10 +47,19 @@
 
 #pragma link C++ class TFCSParametrizationBase+;
 #pragma link C++ class TFCSParametrization+;
+#pragma link C++ class TFCSInitWithEkin+;
 #pragma link C++ class TFCSParametrizationChain+;
+#pragma link C++ class TFCSParametrizationBinnedChain+;
+#pragma link C++ class TFCSParametrizationFloatSelectChain+;
+#pragma link C++ class TFCSParametrizationPDGIDSelectChain+;
+#pragma link C++ class TFCSParametrizationEbinChain+;
+#pragma link C++ class TFCSParametrizationEkinSelectChain+;
+#pragma link C++ class TFCSParametrizationEtaSelectChain+;
+#pragma link C++ class TFCSParametrizationAbsEtaSelectChain+;
 
 #pragma link C++ class TFCSEnergyParametrization+;
 #pragma link C++ class TFCSPCAEnergyParametrization+;
+#pragma link C++ class TFCSEnergyBinParametrization+;
 
 #pragma link C++ class TFCSLateralShapeParametrization+;
 #pragma link C++ class TFCSLateralShapeParametrizationHitBase+;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h
new file mode 100644
index 0000000000000..a7a1445d13f16
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSEnergyBinParametrization_h
+#define ISF_FASTCALOSIMEVENT_TFCSEnergyBinParametrization_h
+
+#include "ISF_FastCaloSimEvent/TFCSEnergyParametrization.h"
+#include<map>
+#include<vector>
+
+class TFCSEnergyBinParametrization:public TFCSEnergyParametrization
+{
+ public:
+  TFCSEnergyBinParametrization(const char* name=nullptr, const char* title=nullptr);
+
+  virtual void set_pdgid(int id);
+  virtual void set_pdgid(const std::set< int > &ids);
+  virtual void add_pdgid(int id);
+  virtual void clear_pdgid();
+  
+  virtual int n_bins() const {return m_number_of_Ekin_bins;};
+
+  /// current convention is to start Ekin_bin counting at 1, to be updated to start counting with 0
+  void set_number_of_Ekin_bins(int n_Ekin_bin) {m_number_of_Ekin_bins=n_Ekin_bin;resize();};
+
+  /// set_pdgid_Ekin_bin_probability(): format of probability should be a vector of float with probability values, 
+  /// e.g. for equal probability of 5 Ekin bins specify a vector with {0,1,1,1,1,1} or {0,0.2,0.2,0.2,0.2,0.2}
+  /// This would give a probability of 0 for Ekin_bin=0 and a probability of 20% for 1<=Ekin_bin<=5
+  /// the function will normalize probabilities automatically, if the sum of values is not 1
+  /// current convention is to start Ekin_bin counting at 1, to be updated to start counting with 0
+  virtual void set_pdgid_Ekin_bin_probability(int id,std::vector< float > prob);
+  
+  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
+
+  virtual bool is_match_Ekin_bin(int Ekin_bin) const;
+  
+  void Print(Option_t *option = "") const;
+ private:
+  int m_number_of_Ekin_bins;
+  std::map< int, std::vector< float > > m_pdgid_Ebin_probability;
+  
+  void resize();
+  
+  ClassDef(TFCSEnergyBinParametrization,1)  //TFCSEnergyBinParametrization
+ 
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSEnergyBinParametrization+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSInitWithEkin.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSInitWithEkin.h
new file mode 100644
index 0000000000000..5e73b4abb3546
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSInitWithEkin.h
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSInitWithEkin_h
+#define ISF_FASTCALOSIMEVENT_TFCSInitWithEkin_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationBase.h"
+
+class TFCSInitWithEkin:public TFCSParametrizationBase {
+public:
+  TFCSInitWithEkin(const char* name=nullptr, const char* title=nullptr);
+
+  virtual bool is_match_Ekin(float /*Ekin*/) const {return true;};
+  virtual bool is_match_eta(float /*eta*/) const {return true;};
+
+  virtual bool is_match_Ekin_bin(int /*Ekin_bin*/) const {return true;};
+  virtual bool is_match_calosample(int /*calosample*/) const {return true;};
+
+  virtual bool is_match_all_Ekin() const {return true;};
+  virtual bool is_match_all_eta() const {return true;};
+  virtual bool is_match_all_Ekin_bin() const {return true;};
+  virtual bool is_match_all_calosample() const {return true;};
+
+  // Initialize simulstate with the kinetic energy Ekin from truth
+  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
+private:
+
+  ClassDef(TFCSInitWithEkin,1)  //TFCSInitWithEkin
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSInitWithEkin+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h
index 86be81f47bf52..743523ec8d8e7 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h
@@ -11,8 +11,11 @@ class TFCSLateralShapeParametrization:public TFCSParametrization {
 public:
   TFCSLateralShapeParametrization(const char* name=nullptr, const char* title=nullptr);
 
-  bool is_match_Ekin_bin(int Ekin_bin) const {return Ekin_bin==m_Ekin_bin;};
+  bool is_match_Ekin_bin(int bin) const {if(Ekin_bin()==-1) return true;return bin==Ekin_bin();};
   bool is_match_calosample(int calosample) const {return calosample==m_calosample;};
+
+  virtual bool is_match_all_Ekin_bin() const {if(Ekin_bin()==-1) return true;return false;};
+  virtual bool is_match_all_calosample() const {return false;};
   
   int Ekin_bin() const {return m_Ekin_bin;};
   void set_Ekin_bin(int bin);
@@ -20,6 +23,8 @@ public:
   int calosample() const {return m_calosample;};
   void set_calosample(int cs);
 
+  virtual void set_pdgid_Ekin_eta_Ekin_bin_calosample(const TFCSLateralShapeParametrization& ref);
+  
   void Print(Option_t *option = "") const;
 private:
   int m_Ekin_bin;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h
index 0c37c2cfdc7ed..6902d747776e8 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h
@@ -5,24 +5,15 @@
 #ifndef TFCSLateralShapeParametrizationHitBase_h
 #define TFCSLateralShapeParametrizationHitBase_h
 
-#include "ISF_FastCaloSimEvent/TFCSParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h"
 
 class CaloGeometry;
 
-class TFCSLateralShapeParametrizationHitBase:public TFCSParametrization {
+class TFCSLateralShapeParametrizationHitBase:public TFCSLateralShapeParametrization {
 public:
   TFCSLateralShapeParametrizationHitBase(const char* name=nullptr, const char* title=nullptr);
 
-  bool is_match_Ekin_bin(int Ekin_bin) const {return Ekin_bin==m_Ekin_bin;};
-  bool is_match_calosample(int calosample) const {return calosample==m_calosample;};
-  
-  int Ekin_bin() const {return m_Ekin_bin;};
-  void set_Ekin_bin(int bin);
-
-  int calosample() const {return m_calosample;};
-  void set_calosample(int cs);
-
-  /// Call get_number_of_hits() only once per shower simulation, as it could be build with random numbers and give different results each time
+  // Call get_number_of_hits() only once per shower simulation, as it could be build with random numbers and give different results each time
   virtual int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const;
 
   class Hit
@@ -43,11 +34,7 @@ public:
   /// the hit should be mapped into a cell and this cell recorded in simulstate. 
   /// All hits/cells should be resacled such that their final sum is simulstate->E(sample)
   virtual void simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
-
-  void Print(Option_t *option = "") const;
 private:
-  int m_Ekin_bin;
-  int m_calosample;
 
   ClassDef(TFCSLateralShapeParametrizationHitBase,1)  //TFCSLateralShapeParametrizationHitBase
 };
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h
index 99e5a059e4f08..c101ba418a291 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h
@@ -17,9 +17,11 @@ public:
   virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
 
   virtual void set_geometry(ICaloGeometry* geo);
-  
+
   typedef std::vector< TFCSLateralShapeParametrizationHitBase* > Chain_t;
-  Chain_t::size_type size() const {return m_chain.size();};
+  virtual unsigned int size() const {return m_chain.size();};
+  virtual const TFCSParametrizationBase* operator[](unsigned int ind) const {return m_chain[ind];};
+  virtual TFCSParametrizationBase* operator[](unsigned int ind) {return m_chain[ind];};
   const Chain_t& chain() const {return m_chain;};
   Chain_t& chain() {return m_chain;};
   void push_back( const Chain_t::value_type& value ) {m_chain.push_back(value);};
@@ -30,6 +32,16 @@ public:
   virtual int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const;
 
   void Print(Option_t *option = "") const;
+
+#if defined(__FastCaloSimStandAlone__)
+  /// Update outputlevel
+  virtual void setLevel(int level,bool recursive=false) {
+    TFCSLateralShapeParametrization::setLevel(level,recursive);
+    if(recursive) if(m_number_of_hits_simul) m_number_of_hits_simul->setLevel(level,recursive);
+  }
+#endif
+
+
 private:
   Chain_t m_chain;
   TFCSLateralShapeParametrizationHitBase* m_number_of_hits_simul;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h
index 99ae7c731f8df..9b0d01007eae5 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSPCAEnergyParametrization.h
@@ -27,6 +27,8 @@ class TFCSPCAEnergyParametrization:public TFCSEnergyParametrization
 
   virtual bool is_match_Ekin_bin(int Ekin_bin) const;
   virtual bool is_match_calosample(int calosample) const;
+  virtual bool is_match_all_Ekin_bin() const {return true;};
+  virtual bool is_match_all_calosample() const {return false;};
   
   void P2X(TVectorD*, TVectorD* , TMatrixD* , int, double* , double* , int);
   void loadInputs(TFile* file);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrization.h
index 44b62a39180b7..b35ca50c2decc 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrization.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrization.h
@@ -12,10 +12,15 @@ public:
   TFCSParametrization(const char* name=nullptr, const char* title=nullptr);
   void clear();
 
-  virtual bool is_match_pdgid(int id) const {return m_pdgid.find(id)!=m_pdgid.end();};
+  virtual bool is_match_pdgid(int id) const {return TestBit(kMatchAllPDGID) || 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);};
 
+  virtual bool is_match_all_Ekin() const {return Ekin_min()==init_Ekin_min && Ekin_max()==init_Ekin_max;};
+  virtual bool is_match_all_eta() const {return eta_min()==init_eta_min && eta_max()==init_eta_max;};
+  virtual bool is_match_all_Ekin_bin() const {return true;};
+  virtual bool is_match_all_calosample() const {return true;};
+
   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;};
@@ -24,17 +29,30 @@ public:
   double eta_min() const {return m_eta_min;};
   double eta_max() const {return m_eta_max;};
 
-  void set_pdgid(int id);
-  void set_pdgid(const std::set< int > &ids);
-  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);
+  virtual void set_pdgid(int id);
+  virtual void set_pdgid(const std::set< int > &ids);
+  virtual void add_pdgid(int id);
+  virtual void clear_pdgid();
+
+  virtual void set_Ekin_nominal(double min);
+  virtual void set_Ekin_min(double min);
+  virtual void set_Ekin_max(double max);
+  virtual void set_eta_nominal(double min);
+  virtual void set_eta_min(double min);
+  virtual void set_eta_max(double max);
+  
+  virtual void set_Ekin(const TFCSParametrizationBase& ref);
+  virtual void set_eta(const TFCSParametrizationBase& ref);
+  virtual void set_Ekin_eta(const TFCSParametrizationBase& ref);
+  virtual void set_pdgid_Ekin_eta(const TFCSParametrizationBase& ref);
+
+protected:
+  const double init_Ekin_nominal=0;
+  const double init_Ekin_min=0;
+  const double init_Ekin_max=14000000;
+  const double init_eta_nominal=0;
+  const double init_eta_min=-100;
+  const double init_eta_max=100;
 
 private:
   std::set< int > m_pdgid;
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h
new file mode 100644
index 0000000000000..553a729dc114a
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationAbsEtaSelectChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationAbsEtaSelectChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h"
+
+class TFCSParametrizationAbsEtaSelectChain:public TFCSParametrizationEtaSelectChain {
+public:
+  TFCSParametrizationAbsEtaSelectChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationEtaSelectChain(name,title) {};
+  TFCSParametrizationAbsEtaSelectChain(const TFCSParametrizationAbsEtaSelectChain& ref):TFCSParametrizationEtaSelectChain(ref) {};
+
+  //selects on |extrapol->IDCaloBoundary_eta()|
+  //return -1 if outside range
+  virtual int get_bin(TFCSSimulationState&,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const;
+  virtual const std::string get_bin_text(int bin) const;
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,TFCSTruthState* truth=nullptr, TFCSExtrapolationState* extrapol=nullptr);
+
+private:
+
+  ClassDef(TFCSParametrizationAbsEtaSelectChain,1)  //TFCSParametrizationAbsEtaSelectChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationAbsEtaSelectChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h
index afb8d7106c4e3..799b1a8477a42 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h
@@ -66,14 +66,25 @@ class TFCSParametrizationBase:public TNamed {
 public:
   TFCSParametrizationBase(const char* name=nullptr, const char* title=nullptr);
 
-  virtual bool is_match_pdgid(int /*id*/) const {return false;};
+  enum FCSStatusBits {
+     /// Set this bit in the TObject bit field if valid for all PDGID
+     kMatchAllPDGID = BIT(14)
+  };
+
+  virtual bool is_match_pdgid(int /*id*/) const {return TestBit(kMatchAllPDGID);};
   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 bool is_match_all_pdgid() const {return TestBit(kMatchAllPDGID);};
+  virtual bool is_match_all_Ekin() const {return false;};
+  virtual bool is_match_all_eta() const {return false;};
+  virtual bool is_match_all_Ekin_bin() const {return false;};
+  virtual bool is_match_all_calosample() const {return false;};
+
+  virtual const std::set< int > &pdgid() const {return s_no_pdgid;};
   virtual double Ekin_nominal() const {return 0;};
   virtual double Ekin_min() const {return 0;};
   virtual double Ekin_max() const {return 0;};
@@ -81,11 +92,20 @@ public:
   virtual double eta_min() const {return 100;};
   virtual double eta_max() const {return 100;};
 
-  virtual void set_geometry(ICaloGeometry*) {};
+  virtual void set_match_all_pdgid() {SetBit(kMatchAllPDGID);};
+  virtual void reset_match_all_pdgid() {ResetBit(kMatchAllPDGID);};
+
+  virtual void set_geometry(ICaloGeometry* geo);
+  
+  ///Some derived classes have daughter instances of TFCSParametrizationBase objects
+  /// The size() and operator[] methods give general access to these daughters
+  virtual unsigned int size() const {return 0;};
+  virtual const TFCSParametrizationBase* operator[](unsigned int /*ind*/) const {return nullptr;};
+  virtual TFCSParametrizationBase* operator[](unsigned int /*ind*/) {return nullptr;};
 
   // 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!)
+  // Simulate cells for shape simulation
   virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
 
   void Print(Option_t *option = "") const;
@@ -93,10 +113,11 @@ public:
 #if defined(__FastCaloSimStandAlone__)
 public:
   /// Update outputlevel
-  void setLevel(int level) {
+  virtual void setLevel(int level,bool recursive=false) {
     level = (level >= MSG::NUM_LEVELS) ?
       MSG::ALWAYS : (level<MSG::NIL) ? MSG::NIL : level;
     m_level = MSG::Level(level);
+    if(recursive) for(unsigned int i=0;i<size();++i) (*this)[i]->setLevel(m_level,recursive);
   }
   /// Retrieve output level
   MSG::Level level() const {return m_level;}
@@ -128,7 +149,7 @@ private:
 #endif  
   
 private:
-  static std::set< int > m_no_pdgid;
+  static std::set< int > s_no_pdgid;
 
   ClassDef(TFCSParametrizationBase,1)  //TFCSParametrizationBase
 };
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h
new file mode 100644
index 0000000000000..b6a6adbb164f7
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationBinnedChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationBinnedChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationChain.h"
+
+class TFCSParametrizationBinnedChain:public TFCSParametrizationChain {
+public:
+  TFCSParametrizationBinnedChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationChain(name,title),m_bin_start(1,0) {};
+  TFCSParametrizationBinnedChain(const TFCSParametrizationBinnedChain& ref):TFCSParametrizationChain(ref),m_bin_start(ref.m_bin_start) {};
+
+  virtual void push_before_first_bin(TFCSParametrizationBase* param);
+  virtual void push_back_in_bin(TFCSParametrizationBase* param, unsigned int bin);
+  
+  virtual unsigned int get_number_of_bins() const {return m_bin_start.size()-1;};
+
+  ///this method should determine in derived classes which bin to simulate, so that the simulate method 
+  ///can call the appropriate TFCSParametrizationBase simulations
+  ///return -1 if no bin matches
+  virtual int get_bin(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const;
+  virtual const std::string get_variable_text(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState*) const;
+  ///print the range of a bin; for bin -1, print the allowed range
+  virtual const std::string get_bin_text(int bin) const;
+
+  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
+
+  void Print(Option_t *option = "") const;
+  
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,const TFCSTruthState* truth=nullptr, const TFCSExtrapolationState* extrapol=nullptr);
+
+protected:
+  /// Contains the index where the TFCSParametrizationBase* instances to run for a given bin start. 
+  /// The last entry of the vector correponds to the index from where on TFCSParametrizationBase* objects 
+  /// should be run again for all bins. 
+  /// This way one can loop over some instances for all bins, then only specific ones for one bin 
+  /// and at the end again over some for all bins
+  std::vector< unsigned int > m_bin_start;
+
+private:
+
+  ClassDef(TFCSParametrizationBinnedChain,1)  //TFCSParametrizationBinnedChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationBinnedChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationChain.h
index 9f3be0dcb7a73..78eb717a7d31c 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationChain.h
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationChain.h
@@ -13,23 +13,35 @@ public:
   TFCSParametrizationChain(const TFCSParametrizationChain& ref):TFCSParametrization(ref.GetName(),ref.GetTitle()),m_chain(ref.chain()) {};
 
   typedef std::vector< TFCSParametrizationBase* > Chain_t;
-  Chain_t::size_type size() const {return m_chain.size();};
+  virtual unsigned int size() const {return m_chain.size();};
+  virtual const TFCSParametrizationBase* operator[](unsigned int ind) const {return m_chain[ind];};
+  virtual TFCSParametrizationBase* operator[](unsigned int ind) {return m_chain[ind];};
   const Chain_t& chain() const {return m_chain;};
   Chain_t& chain() {return m_chain;};
   void push_back(const Chain_t::value_type& param) {m_chain.push_back(param);recalc();};
 
-  virtual void set_geometry(ICaloGeometry* geo);
-  
   virtual bool is_match_Ekin_bin(int Ekin_bin) const;
   virtual bool is_match_calosample(int calosample) const;
 
   virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
 
   void Print(Option_t *option = "") const;
-private:
-  Chain_t m_chain;
+protected:
+  void recalc_pdgid_intersect();
+  void recalc_pdgid_union();
+
+  void recalc_Ekin_intersect();
+  void recalc_eta_intersect();
+  void recalc_Ekin_eta_intersect();
+
+  void recalc_Ekin_union();
+  void recalc_eta_union();
+  void recalc_Ekin_eta_union();
   
-  void recalc();
+  ///Default is to call recalc_pdgid_intersect() and recalc_Ekin_eta_intersect()
+  virtual void recalc();
+private:  
+  Chain_t m_chain;
 
   ClassDef(TFCSParametrizationChain,1)  //TFCSParametrizationChain
 };
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h
new file mode 100644
index 0000000000000..15aef2976fadc
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationEbinChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationEbinChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+
+class TFCSParametrizationEbinChain:public TFCSParametrizationBinnedChain {
+public:
+  TFCSParametrizationEbinChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationBinnedChain(name,title) {};
+  TFCSParametrizationEbinChain(const TFCSParametrizationEbinChain& ref):TFCSParametrizationBinnedChain(ref) {};
+
+  /// current convention is to start Ebin counting at 1, to be updated to start counting with 0
+  virtual int get_bin(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const {return simulstate.Ebin();};
+  virtual const std::string get_variable_text(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const;
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,const TFCSTruthState* truth=nullptr, const TFCSExtrapolationState* extrapol=nullptr);
+private:
+
+  ClassDef(TFCSParametrizationEbinChain,1)  //TFCSParametrizationEbinChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationEbinChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h
new file mode 100644
index 0000000000000..74a8a809ca1e6
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationEkinSelectChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationEkinSelectChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+
+class TFCSParametrizationEkinSelectChain:public TFCSParametrizationFloatSelectChain {
+public:
+  TFCSParametrizationEkinSelectChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationFloatSelectChain(name,title) {};
+  TFCSParametrizationEkinSelectChain(const TFCSParametrizationEkinSelectChain& ref):TFCSParametrizationFloatSelectChain(ref) {};
+
+  using TFCSParametrizationFloatSelectChain::push_back_in_bin;
+  virtual void push_back_in_bin(TFCSParametrizationBase* param);
+  //selects on truth->Ekin()
+  //return -1 if outside range
+  virtual int get_bin(TFCSSimulationState&,const TFCSTruthState* truth, const TFCSExtrapolationState*) const;
+  virtual const std::string get_variable_text(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const;
+  virtual const std::string get_bin_text(int bin) const;
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,TFCSTruthState* truth=nullptr, const TFCSExtrapolationState* extrapol=nullptr);
+
+protected:
+  void recalc();
+
+private:
+
+  ClassDef(TFCSParametrizationEkinSelectChain,1)  //TFCSParametrizationEkinSelectChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationEkinSelectChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h
new file mode 100644
index 0000000000000..577e28759c6ac
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationEtaSelectChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationEtaSelectChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h"
+
+class TFCSParametrizationEtaSelectChain:public TFCSParametrizationFloatSelectChain {
+public:
+  TFCSParametrizationEtaSelectChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationFloatSelectChain(name,title) {};
+  TFCSParametrizationEtaSelectChain(const TFCSParametrizationEtaSelectChain& ref):TFCSParametrizationFloatSelectChain(ref) {};
+
+  using TFCSParametrizationFloatSelectChain::push_back_in_bin;
+  virtual void push_back_in_bin(TFCSParametrizationBase* param);
+  //selects on extrapol->IDCaloBoundary_eta()
+  //return -1 if outside range
+  virtual int get_bin(TFCSSimulationState&,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const;
+  virtual const std::string get_variable_text(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const;
+  virtual const std::string get_bin_text(int bin) const;
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,TFCSTruthState* truth=nullptr, TFCSExtrapolationState* extrapol=nullptr);
+
+protected:
+  void recalc();
+
+private:
+
+  ClassDef(TFCSParametrizationEtaSelectChain,1)  //TFCSParametrizationEtaSelectChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationEtaSelectChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h
new file mode 100644
index 0000000000000..844944e67a0fb
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationFloatSelectChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationFloatSelectChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h"
+
+class TFCSParametrizationFloatSelectChain:public TFCSParametrizationBinnedChain {
+public:
+  TFCSParametrizationFloatSelectChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationBinnedChain(name,title),m_bin_low_edge(1,0) {};
+  TFCSParametrizationFloatSelectChain(const TFCSParametrizationFloatSelectChain& ref):TFCSParametrizationBinnedChain(ref),m_bin_low_edge(1,0) {};
+
+  virtual int push_back_in_bin(TFCSParametrizationBase* param, float low, float up);
+  ///Should not be used unless the bin boundaries are already defined!
+  virtual void push_back_in_bin(TFCSParametrizationBase* param, unsigned int bin);
+
+  //return -1 if outside range
+  int val_to_bin(float val) const;
+
+  virtual double get_bin_low_edge(int bin) const {return m_bin_low_edge[bin];};
+  virtual double get_bin_up_edge(int bin) const {return m_bin_low_edge[bin+1];};
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,TFCSTruthState* truth=nullptr, const TFCSExtrapolationState* extrapol=nullptr);
+
+protected:
+  std::vector< float > m_bin_low_edge;
+
+private:
+
+  ClassDef(TFCSParametrizationFloatSelectChain,1)  //TFCSParametrizationFloatSelectChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationFloatSelectChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h
new file mode 100644
index 0000000000000..88492fe86b607
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_FASTCALOSIMEVENT_TFCSParametrizationPDGIDSelectChain_h
+#define ISF_FASTCALOSIMEVENT_TFCSParametrizationPDGIDSelectChain_h
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationChain.h"
+
+class TFCSParametrizationPDGIDSelectChain:public TFCSParametrizationChain {
+public:
+  TFCSParametrizationPDGIDSelectChain(const char* name=nullptr, const char* title=nullptr):TFCSParametrizationChain(name,title) {};
+  TFCSParametrizationPDGIDSelectChain(const TFCSParametrizationPDGIDSelectChain& ref):TFCSParametrizationChain(ref) {};
+
+  virtual void simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol);
+
+  static void unit_test(TFCSSimulationState* simulstate=nullptr,TFCSTruthState* truth=nullptr,TFCSExtrapolationState* extrapol=nullptr);
+protected:
+  virtual void recalc();
+
+private:
+
+  ClassDef(TFCSParametrizationPDGIDSelectChain,1)  //TFCSParametrizationPDGIDSelectChain
+};
+
+#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__)
+#pragma link C++ class TFCSParametrizationPDGIDSelectChain+;
+#endif
+
+#endif
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyBinParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyBinParametrization.cxx
new file mode 100644
index 0000000000000..b41f83869d3ec
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyBinParametrization.cxx
@@ -0,0 +1,122 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSEnergyBinParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "TMath.h"
+#include "TRandom.h"
+
+//=============================================
+//======= TFCSSelectEnergyBin =========
+//=============================================
+
+TFCSEnergyBinParametrization::TFCSEnergyBinParametrization(const char* name, const char* title):TFCSEnergyParametrization(name,title)
+{
+  m_number_of_Ekin_bins=1;
+}
+
+bool TFCSEnergyBinParametrization::is_match_Ekin_bin(int Ekin_bin) const 
+{
+  if(Ekin_bin>=1 && Ekin_bin<=n_bins()) return true;
+  return false;
+}
+
+void TFCSEnergyBinParametrization::resize()
+{
+  for (std::set<int>::iterator itid=pdgid().begin(); itid!=pdgid().end(); ++itid) {
+	  ATH_MSG_VERBOSE("PDGid="<<*itid<<" resize to "<<n_bins()+1);
+    m_pdgid_Ebin_probability[*itid].resize(n_bins()+1);
+  }
+  for (auto it=m_pdgid_Ebin_probability.begin(); it!=m_pdgid_Ebin_probability.end(); ++it) {
+    if(!is_match_pdgid(it->first)) {
+      m_pdgid_Ebin_probability.erase(it);
+      it=m_pdgid_Ebin_probability.begin();
+    }
+  }    
+}
+
+void TFCSEnergyBinParametrization::set_pdgid(int id)
+{
+  TFCSEnergyParametrization::set_pdgid(id);
+  resize();
+}
+
+void TFCSEnergyBinParametrization::set_pdgid(const std::set< int > &ids)
+{
+  TFCSEnergyParametrization::set_pdgid(ids);
+  resize();
+}
+
+void TFCSEnergyBinParametrization::add_pdgid(int id)
+{
+  TFCSEnergyParametrization::add_pdgid(id);
+  resize();
+}
+
+void TFCSEnergyBinParametrization::clear_pdgid()
+{
+  TFCSEnergyParametrization::clear_pdgid();
+  resize();
+}
+
+void TFCSEnergyBinParametrization::set_pdgid_Ekin_bin_probability(int id,std::vector< float > prob)
+{
+  set_pdgid(id);
+  if(prob.size()!=m_pdgid_Ebin_probability[id].size()) {
+    ATH_MSG_ERROR("TFCSEnergyBinParametrization::set_pdgid_Ekin_bin_probability(): size of vectors does not match! in.size()="<<prob.size()<<" instance="<<m_pdgid_Ebin_probability[id].size());
+    return;
+  }
+  float ptot=0;
+  for(int iEbin=0;iEbin<=n_bins();++iEbin) ptot+=prob[iEbin];
+  float p=0;
+  for(int iEbin=0;iEbin<=n_bins();++iEbin) {
+    p+=prob[iEbin]/ptot;
+    m_pdgid_Ebin_probability[id][iEbin]=p;
+  }
+}
+  
+void TFCSEnergyBinParametrization::Print(Option_t *option) const
+{
+  TString opt(option);
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
+  TFCSEnergyParametrization::Print(option);
+  if(longprint) {
+    for (std::set<int>::iterator it=pdgid().begin(); it!=pdgid().end(); ++it) {
+      ATH_MSG(INFO) <<optprint<< "  PDGID="<< *it<<" : ";
+      float p=0;
+      for(int iEbin=0;iEbin<=n_bins();++iEbin) {
+        if(iEbin>0) std::cout <<", ";
+        auto mapit=m_pdgid_Ebin_probability.find(*it);
+        msg() <<"b"<<iEbin<<"="<<(mapit->second[iEbin]-p)/mapit->second.back()*100<<"%";
+        p=mapit->second[iEbin];
+      }
+      msg() <<endmsg;
+    }  
+  }  
+}
+
+void TFCSEnergyBinParametrization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* /*extrapol*/)
+{
+  int pdgid=truth->pdgid();
+  if(!is_match_pdgid(pdgid)) {
+    ATH_MSG_ERROR("TFCSEnergyBinParametrization::simulate(): cannot simulate pdgid="<<pdgid);
+    return;
+  }
+  float searchRand=gRandom->Rndm();
+  int chosenBin=TMath::BinarySearch(n_bins()+1, m_pdgid_Ebin_probability[pdgid].data(), searchRand)+1;
+  if(chosenBin<1 || chosenBin>n_bins()) {
+    ATH_MSG_ERROR("TFCSEnergyBinParametrization::simulate(): cannot simulate bin="<<chosenBin);
+    if(msgLvl(MSG::ERROR)) {
+      ATH_MSG(ERROR)<<"in "<<GetName()<<": E="<<simulstate.E()<<" Ebin="<<chosenBin<<" rnd="<<searchRand<<" array=";
+      for(int iEbin=0;iEbin<=n_bins();++iEbin) msg()<<m_pdgid_Ebin_probability[pdgid][iEbin]<<" ";
+      msg()<<std::endl;
+    }  
+    return;
+  }
+  simulstate.set_Ebin(chosenBin);
+  ATH_MSG_DEBUG("Ebin="<<chosenBin);
+}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx
index 903c219873b66..8c46013152ca0 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx
@@ -91,8 +91,10 @@ bool TFCSHistoLateralShapeParametrization::Initialize(const char* filepath, cons
 void TFCSHistoLateralShapeParametrization::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   TFCSLateralShapeParametrizationHitBase::Print(option);
 
-  ATH_MSG_INFO(opt <<"  Histo: "<<m_hist->GetName()<<" : "<<m_hist->GetTitle()<<" ptr="<<m_hist);
+  if(longprint) ATH_MSG_INFO(optprint <<"  Histo: "<<m_hist->GetName()<<" : "<<m_hist->GetTitle()<<" ptr="<<m_hist);
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMapping.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMapping.cxx
index 316e0390f6208..bd66e0925dca6 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMapping.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMapping.cxx
@@ -14,12 +14,14 @@ TFCSHitCellMapping::TFCSHitCellMapping(const char* name, const char* title, ICal
   TFCSLateralShapeParametrizationHitBase(name,title),
   m_geo(geo)
 {
+  set_match_all_pdgid();
 }
 
 void TFCSHitCellMapping::simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/)
 {
   int cs=calosample();
   const CaloDetDescrElement* cellele=m_geo->getDDE(cs,hit.eta(),hit.phi());
+  ATH_MSG_DEBUG("HIT: cellele="<<cellele<<" E="<<hit.E()<<" cs="<<cs<<" eta="<<hit.eta()<<" phi="<<hit.phi());
   if(cellele) {
     simulstate.deposit(cellele,hit.E());
   } else {
@@ -30,8 +32,10 @@ void TFCSHitCellMapping::simulate_hit(Hit& hit,TFCSSimulationState& simulstate,c
 void TFCSHitCellMapping::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   TFCSLateralShapeParametrizationHitBase::Print(option);
 
-  ATH_MSG_INFO(opt <<"  geo="<<m_geo);
+  if(longprint) ATH_MSG_INFO(optprint <<"  geo="<<m_geo);
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggleEMB.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggleEMB.cxx
index 92fcdb3e7a79a..bee8b904784af 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggleEMB.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggleEMB.cxx
@@ -80,8 +80,10 @@ void TFCSHitCellMappingWiggleEMB::simulate_hit(Hit& hit,TFCSSimulationState& sim
   double wiggle = 0.0;
   if(cs < 4 && cs > 0) wiggle = doWiggle();
 
+  ATH_MSG_DEBUG("HIT: E="<<hit.E()<<" cs="<<cs<<" eta="<<hit.eta()<<" phi="<<hit.phi()<<" wiggle="<<wiggle);
+
   double hit_phi_shifted=hit.phi()-wiggle;
   hit.phi()=TVector2::Phi_mpi_pi(hit_phi_shifted);
-  
+
   TFCSHitCellMapping::simulate_hit(hit,simulstate,truth,extrapol);
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSInitWithEkin.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSInitWithEkin.cxx
new file mode 100644
index 0000000000000..9145226cbbcf6
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSInitWithEkin.cxx
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSInitWithEkin.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+
+//=============================================
+//======= TFCSInitWithEkin =========
+//=============================================
+
+TFCSInitWithEkin::TFCSInitWithEkin(const char* name, const char* title):TFCSParametrizationBase(name,title)
+{
+  set_match_all_pdgid();
+}
+
+void TFCSInitWithEkin::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState*)
+{
+  ATH_MSG_DEBUG("set E to Ekin="<<truth->Ekin());
+  simulstate.set_E(truth->Ekin());
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrization.cxx
index 6bf9af6aca4a4..83d2e7fdb931e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrization.cxx
@@ -23,11 +23,22 @@ void TFCSLateralShapeParametrization::set_calosample(int cs)
   m_calosample=cs;
 }
 
+void TFCSLateralShapeParametrization::set_pdgid_Ekin_eta_Ekin_bin_calosample(const TFCSLateralShapeParametrization& ref)
+{
+  set_calosample(ref.calosample());
+  set_Ekin_bin(ref.Ekin_bin());
+  set_pdgid_Ekin_eta(ref);
+}
+
 void TFCSLateralShapeParametrization::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   TFCSParametrization::Print(option);
-  ATH_MSG_INFO(opt <<"  Ekin_bin="<<Ekin_bin());
-  ATH_MSG_INFO(opt <<"  calosample="<<calosample());
+  if(longprint) {
+    if(Ekin_bin()==-1 ) ATH_MSG_INFO(optprint <<"  Ekin_bin=all ; calosample="<<calosample());
+     else               ATH_MSG_INFO(optprint <<"  Ekin_bin="<<Ekin_bin()<<" ; calosample="<<calosample());
+  }  
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx
index 7807b113bddde..8692fbc5f4dcf 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx
@@ -12,20 +12,10 @@
 //======= TFCSLateralShapeParametrization =========
 //=============================================
 
-TFCSLateralShapeParametrizationHitBase::TFCSLateralShapeParametrizationHitBase(const char* name, const char* title):TFCSParametrization(name,title),m_Ekin_bin(-1),m_calosample(-1)
+TFCSLateralShapeParametrizationHitBase::TFCSLateralShapeParametrizationHitBase(const char* name, const char* title):TFCSLateralShapeParametrization(name,title)
 {
 }
 
-void TFCSLateralShapeParametrizationHitBase::set_Ekin_bin(int bin)
-{
-  m_Ekin_bin=bin;
-}
-
-void TFCSLateralShapeParametrizationHitBase::set_calosample(int cs)
-{
-  m_calosample=cs;
-}
-
 int TFCSLateralShapeParametrizationHitBase::get_number_of_hits(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const
 {
   return -1;
@@ -37,13 +27,3 @@ void TFCSLateralShapeParametrizationHitBase::simulate_hit(Hit& hit,TFCSSimulatio
   hit.eta()=0.5*( extrapol->eta(cs, CaloSubPos::SUBPOS_ENT) + extrapol->eta(cs, CaloSubPos::SUBPOS_EXT) );
   hit.phi()=0.5*( extrapol->phi(cs, CaloSubPos::SUBPOS_ENT) + extrapol->phi(cs, CaloSubPos::SUBPOS_EXT) );
 }
-
-void TFCSLateralShapeParametrizationHitBase::Print(Option_t *option) const
-{
-  TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
-  TFCSParametrization::Print(option);
-
-  ATH_MSG_INFO(opt <<"  Ekin_bin="<<Ekin_bin());
-  ATH_MSG_INFO(opt <<"  calosample="<<calosample());
-}
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx
index fb16c5681851c..bcfc7d5aceeaf 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx
@@ -17,54 +17,59 @@ TFCSLateralShapeParametrizationHitChain::TFCSLateralShapeParametrizationHitChain
 
 TFCSLateralShapeParametrizationHitChain::TFCSLateralShapeParametrizationHitChain(TFCSLateralShapeParametrizationHitBase* hitsim):TFCSLateralShapeParametrization(TString("hit_chain_")+hitsim->GetName(),TString("hit chain for ")+hitsim->GetTitle()),m_number_of_hits_simul(nullptr)
 {
-  set_calosample(hitsim->calosample());
+  set_pdgid_Ekin_eta_Ekin_bin_calosample(*hitsim);
   
-  set_Ekin_bin(hitsim->Ekin_bin());
-  set_Ekin_nominal(hitsim->Ekin_nominal());
-  set_Ekin_min(hitsim->Ekin_min());
-  set_Ekin_max(hitsim->Ekin_max());
-  
-  set_eta_nominal(hitsim->eta_nominal());
-  set_eta_min(hitsim->eta_min());
-  set_eta_max(hitsim->eta_max());
-
-  set_pdgid(hitsim->pdgid());
-
   m_chain.push_back(hitsim);
 }
 
 void TFCSLateralShapeParametrizationHitChain::set_geometry(ICaloGeometry* geo)
 {
-  for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) hitsim->set_geometry(geo);
+  TFCSLateralShapeParametrization::set_geometry(geo);
+  if(m_number_of_hits_simul) m_number_of_hits_simul->set_geometry(geo);
 }
 
 int TFCSLateralShapeParametrizationHitChain::get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const
 {
   if(m_number_of_hits_simul) {
-    return m_number_of_hits_simul->get_number_of_hits(simulstate,truth,extrapol);
+    int n=m_number_of_hits_simul->get_number_of_hits(simulstate,truth,extrapol);
+    if(n<1) n=1;
+    return n;
   }
   for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) {
     int n=hitsim->get_number_of_hits(simulstate,truth,extrapol);
     //std::cout<<"  "<<hitsim->ClassName()<<":"<<hitsim->GetName()<<" #hits="<<n<<std::endl;
-    if(n>=0) return n;
+    if(n>0) return n;
   } 
-  return -1;
+  return 1;
 }
 
 void TFCSLateralShapeParametrizationHitChain::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
 {
   // Call get_number_of_hits() only once, as it could contain a random number
   int nhit=get_number_of_hits(simulstate,truth,extrapol);
-  //std::cout<<"  "<<ClassName()<<":"<<GetName()<<" E="<<simulstate.E(calosample())<<" #hits="<<nhit<<std::endl;
-
   float Ehit=simulstate.E(calosample())/nhit;
-  for(int i=0;i<nhit;++i) {
-    TFCSLateralShapeParametrizationHitBase::Hit hit; 
-    hit.E()=Ehit;
-    for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) {
-      //std::cout<<"  do "<<hitsim->ClassName()<<":"<<hitsim->GetName()<<" hit="<<i<<std::endl;
-      hitsim->simulate_hit(hit,simulstate,truth,extrapol);
-    } 
+  
+  if(msgLvl(MSG::DEBUG)) {
+    ATH_MSG_DEBUG("E("<<calosample()<<")="<<simulstate.E(calosample())<<" #hits="<<nhit);
+    for(int i=0;i<nhit;++i) {
+      TFCSLateralShapeParametrizationHitBase::Hit hit; 
+      hit.E()=Ehit;
+      for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) {
+        if(i<2) hitsim->setLevel(MSG::DEBUG);
+         else hitsim->setLevel(MSG::INFO);
+        //std::cout<<"  do "<<hitsim->ClassName()<<":"<<hitsim->GetName()<<" hit="<<i<<std::endl;
+        hitsim->simulate_hit(hit,simulstate,truth,extrapol);
+      } 
+    }  
+  } else {
+    for(int i=0;i<nhit;++i) {
+      TFCSLateralShapeParametrizationHitBase::Hit hit; 
+      hit.E()=Ehit;
+      for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) {
+        //std::cout<<"  do "<<hitsim->ClassName()<<":"<<hitsim->GetName()<<" hit="<<i<<std::endl;
+        hitsim->simulate_hit(hit,simulstate,truth,extrapol);
+      } 
+    }  
   }  
 }
 
@@ -72,13 +77,16 @@ void TFCSLateralShapeParametrizationHitChain::Print(Option_t *option) const
 {
   TFCSLateralShapeParametrization::Print(option);
   TString opt(option);
-  if(!opt.IsWhitespace()) opt=option; else opt=opt+"  ";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
+
   if(m_number_of_hits_simul) {
-    ATH_MSG_INFO(opt <<"#hits simulation:");
-    m_number_of_hits_simul->Print(opt);
+    if(longprint) ATH_MSG_INFO(optprint <<"#:Number of hits simulation:");
+    m_number_of_hits_simul->Print(opt+"#:");
   }
-  ATH_MSG_INFO(opt <<"Simulation chain:");
+  if(longprint) ATH_MSG_INFO(optprint <<"- Simulation chain:");
   for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) {
-    hitsim->Print(opt);
+    hitsim->Print(opt+"- ");
   } 
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx
index 8f7385502f9fa..ed0f9047fbc4e 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx
@@ -14,6 +14,7 @@
 TFCSLateralShapeParametrizationHitNumberFromE::TFCSLateralShapeParametrizationHitNumberFromE(const char* name, const char* title,double stochastic,double constant) :
   TFCSLateralShapeParametrizationHitBase(name,title),m_stochastic(stochastic),m_constant(constant)
 {
+  set_match_all_pdgid();
 }
 
 int TFCSLateralShapeParametrizationHitNumberFromE::get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const
@@ -22,16 +23,20 @@ int TFCSLateralShapeParametrizationHitNumberFromE::get_number_of_hits(TFCSSimula
   double energy=simulstate.E(cs);
 
   double sigma_stochastic=m_stochastic/sqrt(energy/1000.0);
-  int hits = 1.0 / (sigma_stochastic*sigma_stochastic + m_constant*m_constant);
+  int hits = gRandom->Poisson(1.0 / (sigma_stochastic*sigma_stochastic + m_constant*m_constant));
 
-  return gRandom->Poisson(hits);
+  ATH_MSG_DEBUG("#hits="<<hits);
+  
+  return hits;
 }
 
 void TFCSLateralShapeParametrizationHitNumberFromE::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   TFCSLateralShapeParametrizationHitBase::Print(option);
 
-  ATH_MSG_INFO(opt <<"  stochastic="<<m_stochastic<<" constant="<<m_constant);
+  if(longprint) ATH_MSG_INFO(optprint <<"  stochastic="<<m_stochastic<<" constant="<<m_constant);
 }
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx
index aeea4844e6055..dc111f5ae897c 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSPCAEnergyParametrization.cxx
@@ -42,11 +42,13 @@ bool TFCSPCAEnergyParametrization::is_match_calosample(int calosample) const
 void TFCSPCAEnergyParametrization::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   TFCSEnergyParametrization::Print(option);
   
-  if(msgLvl(MSG::INFO)) {
-    ATH_MSG(INFO) << opt <<"  #bins="<<m_numberpcabins<<", layers=";
+  if(longprint) {
+    ATH_MSG(INFO) << optprint <<"  #bins="<<m_numberpcabins<<", layers=";
     for(unsigned int i=0;i<m_RelevantLayers.size();i++) {
       if(i>0) msg()<<", ";
       msg()<<m_RelevantLayers[i];
@@ -139,6 +141,7 @@ void TFCSPCAEnergyParametrization::simulate(TFCSSimulationState& simulstate,cons
 
   double total_energy=simdata[layer.size()-1];
   simulstate.set_E(total_energy);
+  ATH_MSG_DEBUG("set E to total_energy="<<total_energy);
 
   for(int s=0;s<CaloCell_ID_FCS::MaxSample;s++)
     {
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrization.cxx
index 0f004682d0a58..52501c8bbf291 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrization.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrization.cxx
@@ -74,3 +74,30 @@ void TFCSParametrization::set_eta_max(double max)
 {
   m_eta_max=max;
 }
+
+void TFCSParametrization::set_Ekin(const TFCSParametrizationBase& ref)
+{
+  set_Ekin_nominal(ref.Ekin_nominal());
+  set_Ekin_min(ref.Ekin_min());
+  set_Ekin_max(ref.Ekin_max());
+}
+
+void TFCSParametrization::set_eta(const TFCSParametrizationBase& ref)
+{
+  set_eta_nominal(ref.eta_nominal());
+  set_eta_min(ref.eta_min());
+  set_eta_max(ref.eta_max());
+}
+
+void TFCSParametrization::set_Ekin_eta(const TFCSParametrizationBase& ref)
+{
+  set_Ekin(ref);
+  set_eta(ref);
+}
+
+void TFCSParametrization::set_pdgid_Ekin_eta(const TFCSParametrizationBase& ref)
+{
+  set_Ekin_eta(ref);
+  set_pdgid(ref.pdgid());
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationAbsEtaSelectChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationAbsEtaSelectChain.cxx
new file mode 100644
index 0000000000000..bec8817fbb618
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationAbsEtaSelectChain.cxx
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationAbsEtaSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationAbsEtaSelectChain =========
+//=============================================
+
+int TFCSParametrizationAbsEtaSelectChain::get_bin(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState* extrapol) const
+{
+  return val_to_bin(TMath::Abs(extrapol->IDCaloBoundary_eta()));
+}
+
+const std::string TFCSParametrizationAbsEtaSelectChain::get_bin_text(int bin) const
+{
+  if(bin==-1 || bin>=(int)get_number_of_bins()) {
+    return std::string(Form("bin=%d not in [%2.2f<=|eta|<%2.2f)",bin,m_bin_low_edge[0],m_bin_low_edge[get_number_of_bins()]));
+  }  
+  return std::string(Form("bin=%d, %2.2f<=|eta|<%2.2f",bin,m_bin_low_edge[bin],m_bin_low_edge[bin+1]));
+}
+
+void TFCSParametrizationAbsEtaSelectChain::unit_test(TFCSSimulationState* simulstate,TFCSTruthState* truth, TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationAbsEtaSelectChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  TFCSParametrization* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  param->set_eta_nominal(2);
+  param->set_eta_min(2);
+  param->set_eta_max(3);
+  chain.push_before_first_bin(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  param->set_eta_nominal(2);
+  param->set_eta_min(2);
+  param->set_eta_max(3);
+  chain.push_back(param);
+
+  const int n_params=5;
+  for(int i=2;i<n_params;++i) {
+    param=new TFCSParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_eta_nominal(i*i+0.1);
+    param->set_eta_min(i*i);
+    param->set_eta_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+  for(int i=n_params;i>=1;--i) {
+    param=new TFCSParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_eta_nominal(i*i+0.1);
+    param->set_eta_min(i*i);
+    param->set_eta_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with eta=0.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(0.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=-1.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(-1.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=2.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(2.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=4.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(4.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=-4.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(-4.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=100      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(100);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx
index 365b96d19b9f2..d406a5a257464 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBase.cxx
@@ -9,7 +9,7 @@
 //======= TFCSParametrizationBase =========
 //=============================================
 
-std::set< int > TFCSParametrizationBase::m_no_pdgid;
+std::set< int > TFCSParametrizationBase::s_no_pdgid;
 
 #ifndef __FastCaloSimStandAlone__
 //Initialize only in constructor to make sure the needed services are ready
@@ -27,26 +27,47 @@ TFCSParametrizationBase::TFCSParametrizationBase(const char* name, const char* t
 }
 #endif
 
+void TFCSParametrizationBase::set_geometry(ICaloGeometry* geo)
+{
+  for(unsigned int i=0;i<size();++i) (*this)[i]->set_geometry(geo);
+}
+
 void TFCSParametrizationBase::simulate(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/)
 {
+  ATH_MSG_ERROR("now in TFCSParametrizationBase::simulate(). This should normally not happen");
 }
 
 void TFCSParametrizationBase::Print(Option_t *option) const
 {
   TString opt(option);
-  if(!opt.IsWhitespace()) opt="";
-  ATH_MSG_INFO(opt<<'"'<< GetTitle() <<'"'<<" ("<<IsA()->GetName()<<"*)"<<this);
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
   
-  if(msgLvl(MSG::INFO)) {
-    ATH_MSG(INFO) << opt <<"  PDGID: ";
-    for (std::set<int>::iterator it=pdgid().begin(); it!=pdgid().end(); ++it) {
-      if(it!=pdgid().begin()) msg() << ", ";
-      msg() << *it;
+  if(longprint) {
+    ATH_MSG_INFO(optprint<<GetTitle()<<" ("<<IsA()->GetName()<<"*)"<<this);
+    ATH_MSG(INFO) << optprint <<"  PDGID: ";
+    if(is_match_all_pdgid()) {
+      msg() << "all";
+    } else {
+      for (std::set<int>::iterator it=pdgid().begin(); it!=pdgid().end(); ++it) {
+        if(it!=pdgid().begin()) msg() << ", ";
+        msg() << *it;
+      }  
+    }
+    if(is_match_all_Ekin()) {
+      msg()<<" ; Ekin=all";
+    } else {
+      msg()<<" ; Ekin="<<Ekin_nominal()<<" ["<<Ekin_min()<<" , "<<Ekin_max()<<") MeV";
+    }  
+    if(is_match_all_eta()) {
+      msg()<<" ; eta=all";
+    } else {
+      msg()<<" ; eta="<<eta_nominal()<<" ["<<eta_min()<<" , "<<eta_max()<<")";
     }  
     msg() << endmsg;
+  } else {
+    ATH_MSG_INFO(optprint<<GetTitle());
   }
-  
-  ATH_MSG_INFO(opt <<"  Ekin="<<Ekin_nominal()<<" MeV, range "<<Ekin_min()<<" MeV < Ekin < "<<Ekin_max()<<" MeV");
-  ATH_MSG_INFO(opt <<"  eta="<<eta_nominal()<<", range "<<eta_min()<<" < eta < "<<eta_max());
 }
 
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBinnedChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBinnedChain.cxx
new file mode 100644
index 0000000000000..44964fcfc2e0c
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationBinnedChain.cxx
@@ -0,0 +1,166 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationBinnedChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <algorithm>
+#include <iterator>
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationBinnedChain =========
+//=============================================
+
+void TFCSParametrizationBinnedChain::push_before_first_bin(TFCSParametrizationBase* param) 
+{
+  if(m_bin_start[0]==size()) {
+    chain().push_back(param);
+  } else {  
+    Chain_t::iterator it(&chain()[m_bin_start[0]]);
+    chain().insert(it,param);
+  }  
+  for(auto& ele:m_bin_start) ele++;
+  recalc();
+}
+
+void TFCSParametrizationBinnedChain::push_back_in_bin(TFCSParametrizationBase* param, unsigned int bin) 
+{
+  if(m_bin_start.size()<=bin+1) {
+    m_bin_start.resize(bin+2,m_bin_start.back());
+    m_bin_start.shrink_to_fit();
+  }  
+  if(m_bin_start[bin+1]==size()) {
+    chain().push_back(param);
+  } else {  
+    Chain_t::iterator it(&chain()[m_bin_start[bin+1]]);
+    chain().insert(it,param);
+  }  
+  for(unsigned int ibin=bin+1;ibin<m_bin_start.size();++ibin) m_bin_start[ibin]++;
+  recalc();
+}
+
+int TFCSParametrizationBinnedChain::get_bin(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState*) const
+{
+  return 0;
+}
+
+const std::string TFCSParametrizationBinnedChain::get_variable_text(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState*) const
+{
+  return std::string("NO VARIABLE DEFINED");
+}
+
+const std::string TFCSParametrizationBinnedChain::get_bin_text(int bin) const
+{
+  return std::string(Form("bin %d",bin));
+}
+
+void TFCSParametrizationBinnedChain::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
+{
+  for(unsigned int ichain=0;ichain<m_bin_start[0];++ichain) {
+    ATH_MSG_DEBUG("now run for all bins: "<<chain()[ichain]->GetName());
+    chain()[ichain]->simulate(simulstate,truth,extrapol);
+  }
+  if(get_number_of_bins()>0) {
+    int bin=get_bin(simulstate,truth,extrapol);
+    if(bin>=0 && bin<(int)get_number_of_bins()) {
+      for(unsigned int ichain=m_bin_start[bin];ichain<m_bin_start[bin+1];++ichain) {
+        ATH_MSG_DEBUG("for "<<get_variable_text(simulstate,truth,extrapol)<<" run "<<get_bin_text(bin)<<": "<<chain()[ichain]->GetName());
+        chain()[ichain]->simulate(simulstate,truth,extrapol);
+      }
+    } else {
+      ATH_MSG_WARNING("for "<<get_variable_text(simulstate,truth,extrapol)<<": "<<get_bin_text(bin));
+    }
+  } else {
+    ATH_MSG_WARNING("no bins defined, is this intended?");
+  }  
+  for(unsigned int ichain=m_bin_start.back();ichain<size();++ichain) {
+    ATH_MSG_DEBUG("now run for all bins: "<<chain()[ichain]->GetName());
+    chain()[ichain]->simulate(simulstate,truth,extrapol);
+  }
+}
+
+void TFCSParametrizationBinnedChain::Print(Option_t *option) const
+{
+  TFCSParametrization::Print(option);
+  TString opt(option);
+  bool shortprint=opt.Index("short")>=0;
+  bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  TString optprint=opt;optprint.ReplaceAll("short","");
+
+  TString prefix="- ";
+  for(unsigned int ichain=0;ichain<size();++ichain) {
+    if(ichain==0) {
+      prefix="- ";
+      if(longprint) ATH_MSG_INFO(optprint<<prefix<<"Run for all bins");
+    }  
+    for(unsigned int ibin=0;ibin<get_number_of_bins();++ibin) {
+      if(ichain==m_bin_start[ibin]) {
+        prefix=Form("%-2d",ibin);
+        if(longprint) ATH_MSG_INFO(optprint<<prefix<<"Run for "<<get_bin_text(ibin));
+      }  
+    }  
+    if(ichain==m_bin_start.back()) {
+      prefix="- ";
+      if(longprint) ATH_MSG_INFO(optprint<<prefix<<"Run for all bins");
+    }  
+    chain()[ichain]->Print(opt+prefix);
+  }
+}
+
+void TFCSParametrizationBinnedChain::unit_test(TFCSSimulationState* simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationBinnedChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with empty chain ===="<<std::endl;
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+
+  TFCSParametrizationBase* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate only begin/end all ===="<<std::endl;
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+
+  for(int i=0;i<3;++i) {
+    TFCSParametrizationBase* param=new TFCSParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    chain.push_back_in_bin(param,i);
+  }
+
+  for(int i=3;i>0;--i) {
+    TFCSParametrizationBase* param=new TFCSParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    chain.push_back_in_bin(param,i);
+  }
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with full chain  ===="<<std::endl;
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationChain.cxx
index 6f31be4023f93..a680ddf8f7810 100644
--- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationChain.cxx
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationChain.cxx
@@ -10,16 +10,9 @@
 //======= TFCSParametrizationChain =========
 //=============================================
 
-void TFCSParametrizationChain::recalc()
+void TFCSParametrizationChain::recalc_pdgid_intersect()
 {
-  clear();
-  if(m_chain.size()==0) return;
-
   set_pdgid(m_chain[0]->pdgid());
-  set_Ekin_min(m_chain[0]->Ekin_min());
-  set_Ekin_max(m_chain[0]->Ekin_max());
-  set_eta_min(m_chain[0]->eta_min());
-  set_eta_max(m_chain[0]->eta_max());
   
   for(auto param: m_chain) {
     std::set< int > tmp;
@@ -28,19 +21,96 @@ void TFCSParametrizationChain::recalc()
                           param->pdgid().begin(), param->pdgid().end(),
                           std::inserter(tmp,tmp.begin()));  
     set_pdgid(tmp);
+  }
+}
+
+void TFCSParametrizationChain::recalc_pdgid_union()
+{
+  set_pdgid(chain()[0]->pdgid());
+  
+  for(auto param: chain()) {
+    std::set< int > tmp;
+ 
+    std::set_union(pdgid().begin(), pdgid().end(),
+                   param->pdgid().begin(), param->pdgid().end(),
+                   std::inserter(tmp,tmp.begin()));  
+    set_pdgid(tmp);
+  }
+}
+
+void TFCSParametrizationChain::recalc_Ekin_intersect()
+{
+  set_Ekin(*m_chain[0]);
+  
+  for(auto param: m_chain) {
     if(param->Ekin_min()>Ekin_min()) set_Ekin_min(param->Ekin_min());
     if(param->Ekin_max()<Ekin_max()) set_Ekin_max(param->Ekin_max());
+    if(Ekin_nominal()<Ekin_min() || Ekin_nominal()>Ekin_max()) set_Ekin_nominal(param->Ekin_nominal());
+  }
+
+  if(Ekin_nominal()<Ekin_min() || Ekin_nominal()>Ekin_max()) set_Ekin_nominal(0.5*(Ekin_min()+Ekin_max()));
+}
+
+void TFCSParametrizationChain::recalc_eta_intersect()
+{
+  set_eta(*m_chain[0]);
+  
+  for(auto param: m_chain) {
     if(param->eta_min()>eta_min()) set_eta_min(param->eta_min());
     if(param->eta_max()<eta_max()) set_eta_max(param->eta_max());
+    if(eta_nominal()<eta_min() || eta_nominal()>eta_max()) set_eta_nominal(param->eta_nominal());
   }
 
-  set_Ekin_nominal(0.5*(Ekin_min()+Ekin_max()));
-  set_eta_nominal(0.5*(eta_min()+eta_max()));
+  if(eta_nominal()<eta_min() || eta_nominal()>eta_max()) set_eta_nominal(0.5*(eta_min()+eta_max()));
 }
 
-void TFCSParametrizationChain::set_geometry(ICaloGeometry* geo)
+void TFCSParametrizationChain::recalc_Ekin_eta_intersect()
 {
-  for(auto param : m_chain) param->set_geometry(geo);
+  recalc_Ekin_intersect();
+  recalc_eta_intersect();
+}
+
+void TFCSParametrizationChain::recalc_Ekin_union()
+{
+  set_Ekin(*m_chain[0]);
+  
+  for(auto param: m_chain) {
+    if(param->Ekin_min()<Ekin_min()) set_Ekin_min(param->Ekin_min());
+    if(param->Ekin_max()>Ekin_max()) set_Ekin_max(param->Ekin_max());
+    if(Ekin_nominal()<Ekin_min() || Ekin_nominal()>Ekin_max()) set_Ekin_nominal(param->Ekin_nominal());
+  }
+
+  if(Ekin_nominal()<Ekin_min() || Ekin_nominal()>Ekin_max()) set_Ekin_nominal(0.5*(Ekin_min()+Ekin_max()));
+}
+
+void TFCSParametrizationChain::recalc_eta_union()
+{
+  set_eta(*m_chain[0]);
+  
+  for(auto param: m_chain) {
+    if(param->eta_min()<eta_min()) set_eta_min(param->eta_min());
+    if(param->eta_max()>eta_max()) set_eta_max(param->eta_max());
+    if(eta_nominal()<eta_min() || eta_nominal()>eta_max()) set_eta_nominal(param->eta_nominal());
+  }
+
+  if(eta_nominal()<eta_min() || eta_nominal()>eta_max()) set_eta_nominal(0.5*(eta_min()+eta_max()));
+}
+
+void TFCSParametrizationChain::recalc_Ekin_eta_union()
+{
+  recalc_Ekin_union();
+  recalc_eta_union();
+}
+
+void TFCSParametrizationChain::recalc()
+{
+  clear();
+  if(m_chain.size()==0) return;
+  
+  recalc_pdgid_intersect();
+  recalc_Ekin_eta_intersect();
+  
+  m_chain.shrink_to_fit();
 }
 
 bool TFCSParametrizationChain::is_match_Ekin_bin(int Ekin_bin) const
@@ -66,7 +136,9 @@ void TFCSParametrizationChain::Print(Option_t *option) const
 {
   TFCSParametrization::Print(option);
   TString opt(option);
-  if(!opt.IsWhitespace()) opt=option; else opt=opt+"  ";
+  //bool shortprint=opt.Index("short")>=0;
+  //bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
+  opt=opt+"- ";
 
   for(auto param: m_chain) {
     param->Print(opt);
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEbinChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEbinChain.cxx
new file mode 100644
index 0000000000000..33c4a8001d641
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEbinChain.cxx
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEbinChain.h"
+#include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrization.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationEbinChain =========
+//=============================================
+
+const std::string TFCSParametrizationEbinChain::get_variable_text(TFCSSimulationState& simulstate,const TFCSTruthState*, const TFCSExtrapolationState*) const
+{
+  return std::string(Form("Ebin=%d",simulstate.Ebin()));
+}
+
+void TFCSParametrizationEbinChain::unit_test(TFCSSimulationState* simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationEbinChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  TFCSParametrizationBase* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+
+  for(int i=0;i<3;++i) {
+    TFCSLateralShapeParametrization* param=new TFCSLateralShapeParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_Ekin_bin(i);
+    chain.push_back_in_bin(param,i);
+  }
+
+  for(int i=3;i>0;--i) {
+    TFCSLateralShapeParametrization* param=new TFCSLateralShapeParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_Ekin_bin(i);
+    chain.push_back_in_bin(param,i);
+  }
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with Ebin=0      ===="<<std::endl;
+  simulstate->set_Ebin(0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with Ebin=1      ===="<<std::endl;
+  simulstate->set_Ebin(1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with Ebin=2      ===="<<std::endl;
+  simulstate->set_Ebin(2);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEkinSelectChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEkinSelectChain.cxx
new file mode 100644
index 0000000000000..0c52b16a0f65c
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEkinSelectChain.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEkinSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationEkinSelectChain =========
+//=============================================
+
+void TFCSParametrizationEkinSelectChain::recalc()
+{
+  clear();
+  if(size()==0) return;
+  
+  recalc_pdgid_intersect();
+  recalc_Ekin_union();
+  recalc_eta_intersect();
+  
+  chain().shrink_to_fit();
+}
+
+void TFCSParametrizationEkinSelectChain::push_back_in_bin(TFCSParametrizationBase* param) 
+{
+  push_back_in_bin(param,param->Ekin_min(),param->Ekin_max());
+}
+
+int TFCSParametrizationEkinSelectChain::get_bin(TFCSSimulationState&,const TFCSTruthState* truth, const TFCSExtrapolationState*) const
+{
+  return val_to_bin(truth->Ekin());
+}
+
+const std::string TFCSParametrizationEkinSelectChain::get_variable_text(TFCSSimulationState&,const TFCSTruthState* truth, const TFCSExtrapolationState*) const
+{
+  return std::string(Form("Ekin=%1.1f",truth->Ekin()));
+}
+
+const std::string TFCSParametrizationEkinSelectChain::get_bin_text(int bin) const
+{
+  if(bin==-1 || bin>=(int)get_number_of_bins()) {
+    return std::string(Form("bin=%d not in [%1.1f<=Ekin<%1.1f)",bin,m_bin_low_edge[0],m_bin_low_edge[get_number_of_bins()]));
+  }  
+  return std::string(Form("bin=%d, %1.1f<=Ekin<%1.1f",bin,m_bin_low_edge[bin],m_bin_low_edge[bin+1]));
+}
+
+void TFCSParametrizationEkinSelectChain::unit_test(TFCSSimulationState* simulstate,TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationEkinSelectChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  TFCSParametrization* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  param->set_Ekin_nominal(2);
+  param->set_Ekin_min(2);
+  param->set_Ekin_max(5);
+  chain.push_before_first_bin(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  param->set_Ekin_nominal(2);
+  param->set_Ekin_min(2);
+  param->set_Ekin_max(5);
+  chain.push_back(param);
+
+  const int n_params=5;
+  for(int i=2;i<n_params;++i) {
+    param=new TFCSParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_Ekin_nominal(i*i+0.1);
+    param->set_Ekin_min(i*i);
+    param->set_Ekin_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+  for(int i=n_params;i>=1;--i) {
+    param=new TFCSParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_Ekin_nominal(i*i+0.1);
+    param->set_Ekin_min(i*i);
+    param->set_Ekin_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with E=0.3      ===="<<std::endl;
+  truth->SetPtEtaPhiM(0.3,0,0,0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with E=1.0      ===="<<std::endl;
+  truth->SetPtEtaPhiM(1,0,0,0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with E=1.3      ===="<<std::endl;
+  truth->SetPtEtaPhiM(1.3,0,0,0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with E=4.3      ===="<<std::endl;
+  truth->SetPtEtaPhiM(4.3,0,0,0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with E=100      ===="<<std::endl;
+  truth->SetPtEtaPhiM(100,0,0,0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEtaSelectChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEtaSelectChain.cxx
new file mode 100644
index 0000000000000..73fe3a2d9da28
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationEtaSelectChain.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationEtaSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationEtaSelectChain =========
+//=============================================
+
+void TFCSParametrizationEtaSelectChain::recalc()
+{
+  clear();
+  if(size()==0) return;
+  
+  recalc_pdgid_intersect();
+  recalc_Ekin_intersect();
+  recalc_eta_union();
+  
+  chain().shrink_to_fit();
+}
+
+void TFCSParametrizationEtaSelectChain::push_back_in_bin(TFCSParametrizationBase* param) 
+{
+  push_back_in_bin(param,param->eta_min(),param->eta_max());
+}
+
+int TFCSParametrizationEtaSelectChain::get_bin(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState* extrapol) const
+{
+  return val_to_bin(extrapol->IDCaloBoundary_eta());
+}
+
+const std::string TFCSParametrizationEtaSelectChain::get_variable_text(TFCSSimulationState&,const TFCSTruthState*, const TFCSExtrapolationState* extrapol) const
+{
+  return std::string(Form("eta=%2.2f",extrapol->IDCaloBoundary_eta()));
+}
+
+const std::string TFCSParametrizationEtaSelectChain::get_bin_text(int bin) const
+{
+  if(bin==-1 || bin>=(int)get_number_of_bins()) {
+    return std::string(Form("bin=%d not in [%2.2f<=eta<%2.2f)",bin,m_bin_low_edge[0],m_bin_low_edge[get_number_of_bins()]));
+  }  
+  return std::string(Form("bin=%d, %2.2f<=eta<%2.2f",bin,m_bin_low_edge[bin],m_bin_low_edge[bin+1]));
+}
+
+void TFCSParametrizationEtaSelectChain::unit_test(TFCSSimulationState* simulstate,TFCSTruthState* truth, TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationEtaSelectChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  TFCSParametrization* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  param->set_eta_nominal(2);
+  param->set_eta_min(2);
+  param->set_eta_max(3);
+  chain.push_before_first_bin(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  param->set_eta_nominal(2);
+  param->set_eta_min(2);
+  param->set_eta_max(3);
+  chain.push_back(param);
+
+  const int n_params=5;
+  for(int i=2;i<n_params;++i) {
+    param=new TFCSParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_eta_nominal(i*i+0.1);
+    param->set_eta_min(i*i);
+    param->set_eta_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+  for(int i=n_params;i>=1;--i) {
+    param=new TFCSParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_eta_nominal(i*i+0.1);
+    param->set_eta_min(i*i);
+    param->set_eta_max((i+1)*(i+1));
+    chain.push_back_in_bin(param);
+  }
+
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  chain.push_before_first_bin(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with eta=0.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(0.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=1.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(1.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=2.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(2.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=4.1      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(4.1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with eta=100      ===="<<std::endl;
+  extrapol->set_IDCaloBoundary_eta(100);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationFloatSelectChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationFloatSelectChain.cxx
new file mode 100644
index 0000000000000..904f425bd0020
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationFloatSelectChain.cxx
@@ -0,0 +1,107 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationFloatSelectChain.h"
+#include <algorithm>
+#include <iterator>
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationFloatSelectChain =========
+//=============================================
+
+int TFCSParametrizationFloatSelectChain::push_back_in_bin(TFCSParametrizationBase* param, float low, float up)
+{
+  if(up<low) {
+    //can't handle wrong order of bounds
+    ATH_MSG_ERROR("Cannot add "<<param->GetName()<<": range ["<<low<<","<<up<<") not well defined");
+    return -1;
+  }
+  if(get_number_of_bins()==0) {
+    //special case of adding the first bin
+    push_back_in_bin(param,0);
+    m_bin_low_edge[0]=low;
+    m_bin_low_edge[1]=up;
+    return 0;
+  }
+  int ilow=val_to_bin(low);
+  int iup=val_to_bin(up);
+  if(ilow<0 && iup<0 && m_bin_low_edge[get_number_of_bins()]==low) {
+    //special case of adding bin at the end of existing bins
+    int endbin=get_number_of_bins();
+    push_back_in_bin(param,endbin);
+    m_bin_low_edge[endbin]=low;
+    m_bin_low_edge[endbin+1]=up;
+    return endbin;
+  }
+
+  if(ilow<0 && iup<0) {
+    //can't handle disjunct ranges
+    ATH_MSG_ERROR("Cannot add "<<param->GetName()<<": range ["<<low<<","<<up<<") which is outside existing range ["<<m_bin_low_edge[0]<<","<<m_bin_low_edge[get_number_of_bins()]<<")");
+    return -1;
+  }
+
+  if(iup>=0 && ilow>=0 && iup-ilow==1 && m_bin_low_edge[ilow]==low && m_bin_low_edge[iup]==up) {
+    //Case of adding to an existing bin
+    push_back_in_bin(param,ilow);
+    return ilow;
+  }
+
+  if(ilow<0 && iup==0 && m_bin_low_edge[iup]==up) {
+    //Case of adding a new first bin before existing bins
+    int newbin=iup;
+    int oldsize=m_bin_start.size();
+    m_bin_start.resize(oldsize+1,m_bin_start.back());
+    m_bin_start.shrink_to_fit();
+    m_bin_low_edge.resize(oldsize+1,m_bin_low_edge.back());
+    m_bin_low_edge.shrink_to_fit();
+    for(int i=oldsize;i>newbin;--i) {
+      m_bin_start[i]=m_bin_start[i-1];
+      m_bin_low_edge[i]=m_bin_low_edge[i-1];
+    }
+    m_bin_low_edge[newbin]=low;
+    m_bin_low_edge[newbin+1]=up;
+    push_back_in_bin(param,newbin);
+    return newbin;
+  }
+
+  ATH_MSG_ERROR("Cannot add "<<param->GetName()<<": range ["<<low<<","<<up<<") covers more than one bin in existing range ["<<m_bin_low_edge[0]<<","<<m_bin_low_edge[get_number_of_bins()]<<") or splits an existing bin");
+  return -1;
+}
+
+void TFCSParametrizationFloatSelectChain::push_back_in_bin(TFCSParametrizationBase* param, unsigned int bin) 
+{
+  TFCSParametrizationBinnedChain::push_back_in_bin(param,bin);
+  if(m_bin_low_edge.size()<m_bin_start.size()) {
+    m_bin_low_edge.resize(m_bin_start.size(),m_bin_low_edge.back());
+    m_bin_low_edge.shrink_to_fit();
+  }  
+}
+
+int TFCSParametrizationFloatSelectChain::val_to_bin(float val) const
+{
+  if(val<m_bin_low_edge[0]) {
+    ATH_MSG_VERBOSE("val_to_bin("<<val<<")=-1: "<<val<<" < "<<m_bin_low_edge[0]);
+    return -1;
+  }  
+  if(val>=m_bin_low_edge[get_number_of_bins()]) {
+    ATH_MSG_VERBOSE("val_to_bin("<<val<<")=-1: "<<val<<" >= "<<m_bin_low_edge[get_number_of_bins()]);
+    return -1;
+  }  
+  
+  auto it = std::upper_bound(m_bin_low_edge.begin(),m_bin_low_edge.end(),val);
+  int dist=std::distance(m_bin_low_edge.begin(),it)-1;
+  ATH_MSG_VERBOSE("val_to_bin("<<val<<")="<<dist);
+  return dist;
+}
+
+void TFCSParametrizationFloatSelectChain::unit_test(TFCSSimulationState*,TFCSTruthState*, const TFCSExtrapolationState*)
+{
+  std::cout<<"=================================================================="<<std::endl;
+  std::cout<<"= Please call TFCSParametrizationEkinSelectChain::unit_test(...) ="<<std::endl;
+  std::cout<<"= or          TFCSParametrizationEtaSelectChain ::unit_test(...) ="<<std::endl;
+  std::cout<<"=================================================================="<<std::endl<<std::endl;
+}
+
+
diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationPDGIDSelectChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationPDGIDSelectChain.cxx
new file mode 100644
index 0000000000000..c1b3bb66875bf
--- /dev/null
+++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSParametrizationPDGIDSelectChain.cxx
@@ -0,0 +1,90 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ISF_FastCaloSimEvent/TFCSParametrizationPDGIDSelectChain.h"
+#include "ISF_FastCaloSimEvent/TFCSSimulationState.h"
+#include "ISF_FastCaloSimEvent/TFCSTruthState.h"
+#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h"
+#include <iostream>
+
+//=============================================
+//======= TFCSParametrizationPDGIDSelectChain =========
+//=============================================
+
+void TFCSParametrizationPDGIDSelectChain::recalc()
+{
+  clear();
+  if(size()==0) return;
+  
+  recalc_pdgid_union();
+  recalc_Ekin_eta_intersect();
+  
+  chain().shrink_to_fit();
+}
+
+void TFCSParametrizationPDGIDSelectChain::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol)
+{
+  for(auto param: chain()) {
+    if(param->is_match_pdgid(truth->pdgid())) {
+      ATH_MSG_DEBUG("pdgid="<<truth->pdgid()<<", now run: "<<param->GetName());
+      param->simulate(simulstate,truth,extrapol);
+    }  
+  }
+}
+
+void TFCSParametrizationPDGIDSelectChain::unit_test(TFCSSimulationState* simulstate,TFCSTruthState* truth,TFCSExtrapolationState* extrapol)
+{
+  if(!simulstate) simulstate=new TFCSSimulationState();
+  if(!truth) truth=new TFCSTruthState();
+  if(!extrapol) extrapol=new TFCSExtrapolationState();
+
+  TFCSParametrizationPDGIDSelectChain chain("chain","chain");
+  chain.setLevel(MSG::DEBUG);
+
+  TFCSParametrization* param;
+  param=new TFCSParametrization("A begin all","A begin all");
+  param->setLevel(MSG::DEBUG);
+  param->set_pdgid(0);
+  chain.push_back(param);
+  param=new TFCSParametrization("A end all","A end all");
+  param->setLevel(MSG::DEBUG);
+  param->set_pdgid(0);
+  chain.push_back(param);
+
+  for(int i=0;i<3;++i) {
+    param=new TFCSParametrization(Form("A%d",i),Form("A %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_pdgid(i);
+    chain.push_back(param);
+  }
+
+  for(int i=3;i>0;--i) {
+    param=new TFCSParametrization(Form("B%d",i),Form("B %d",i));
+    param->setLevel(MSG::DEBUG);
+    param->set_pdgid(i);
+    chain.push_back(param);
+  }
+  param=new TFCSParametrization("B end all","B end all");
+  param->setLevel(MSG::DEBUG);
+  param->set_pdgid(1);
+  chain.push_back(param);
+  param=new TFCSParametrization("B begin all","B begin all");
+  param->setLevel(MSG::DEBUG);
+  param->set_pdgid(1);
+  chain.push_back(param);
+  
+  std::cout<<"====         Chain setup       ===="<<std::endl;
+  chain.Print();
+  std::cout<<"==== Simulate with pdgid=0      ===="<<std::endl;
+  truth->set_pdgid(0);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with pdgid=1      ===="<<std::endl;
+  truth->set_pdgid(1);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==== Simulate with pdgid=2      ===="<<std::endl;
+  truth->set_pdgid(2);
+  chain.simulate(*simulstate,truth,extrapol);
+  std::cout<<"==================================="<<std::endl<<std::endl;
+}
+
-- 
GitLab