diff --git a/PhysicsAnalysis/RingerSelectorTools/CMakeLists.txt b/PhysicsAnalysis/RingerSelectorTools/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fa033d66128487c4a1f5ee0a814b27882cda6801
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/CMakeLists.txt
@@ -0,0 +1,55 @@
+################################################################################
+# Package: RingerSelectorTools
+################################################################################
+
+# Declare the package name:
+atlas_subdir( RingerSelectorTools )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthToolSupport/AsgTools
+                          Control/AthenaKernel
+                          Control/CxxUtils
+                          Event/xAOD/xAODCaloRings
+                          Event/xAOD/xAODEgamma
+                          Event/xAOD/xAODTracking
+                          PhysicsAnalysis/AnalysisCommon/PATCore
+                          PhysicsAnalysis/ElectronPhotonID/ElectronPhotonSelectorTools
+                          PRIVATE
+                          Control/AthContainers
+                          Event/xAOD/xAODBase
+                          GaudiKernel
+                          Tools/PathResolver
+                          Tracking/TrkEvent/TrkTrackSummary )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+
+# tag ROOTBasicLibs was not recognized in automatic conversion in cmt2cmake
+
+# Component(s) in the package:
+atlas_add_library( RingerSelectorToolsLib
+                   Root/*.cxx
+                   Root/procedures/*.cxx
+                   Root/tools/*.cxx
+                   PUBLIC_HEADERS RingerSelectorTools
+                   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
+                   LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} AsgTools AthenaKernel CxxUtils xAODCaloRings xAODEgamma xAODTracking PATCoreLib ElectronPhotonSelectorToolsLib
+                   PRIVATE_LINK_LIBRARIES AthContainers xAODBase GaudiKernel PathResolver TrkTrackSummary )
+
+atlas_add_component( RingerSelectorTools
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} AsgTools AthenaKernel CxxUtils xAODCaloRings xAODEgamma xAODTracking PATCoreLib ElectronPhotonSelectorToolsLib AthContainers xAODBase GaudiKernel PathResolver TrkTrackSummary RingerSelectorToolsLib )
+
+atlas_add_dictionary( RingerSelectorToolsDict
+                      RingerSelectorTools/RingerSelectorToolsDict.h
+                      RingerSelectorTools/selection.xml
+                      INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}
+                      LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} AsgTools AthenaKernel CxxUtils xAODCaloRings xAODEgamma xAODTracking PATCoreLib ElectronPhotonSelectorToolsLib AthContainers xAODBase GaudiKernel PathResolver TrkTrackSummary RingerSelectorToolsLib )
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
+atlas_install_data( data/test )
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/AsgElectronRingerSelector.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/AsgElectronRingerSelector.h
new file mode 100644
index 0000000000000000000000000000000000000000..3fe36544a830abcbd8b833075039b0913897eb90
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/AsgElectronRingerSelector.h
@@ -0,0 +1,449 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: AsgElectronRingerSelector.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_ASGELECTRONCALORINGERSELECTOR_H
+#define RINGERSELECTORTOOLS_ASGELECTRONCALORINGERSELECTOR_H
+
+// STL includes:
+#include <string>
+
+// ROOT includes:
+#include <TFile.h>
+
+#ifndef RINGER_STANDALONE
+// Athena includes
+#include "PATCore/TAccept.h"
+#include "PATCore/TResult.h"
+#include "AsgTools/AsgMetadataTool.h"
+#include "AsgTools/ToolHandle.h"
+#include "ElectronPhotonSelectorTools/IAsgElectronIsEMSelector.h"
+
+// xAOD includes:
+#include "xAODCaloRings/CaloRingsContainer.h" // needed for caloRingsReader_t
+#include "xAODCaloRings/RingSetConfContainerFwd.h"
+
+// Local includes:
+#include "RingerSelectorTools/IAsgElectronRingerSelector.h"
+#include "RingerSelectorTools/ElectronTAccept.h"
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.h"
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+#include "RingerSelectorTools/tools/RingerCommonSelector.h"
+#include "RingerSelectorTools/tools/cxx/mutable.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+
+namespace Ringer {
+
+/*
+ *  TODO List:
+ *    - Add metadata on xAOD file with the AsgSelector configuration.
+ */
+
+/**
+ * @class AsgElectronRingerSelector
+ * @brief Electron selector using Ringer patterns to apply discrimination
+ *
+ * @author Werner Spolidoro Freund <wsfreund@cern.ch>
+ *
+ * Based on AsgElectronIsEMSelector by Jovan Mitrevski (UCSC) 
+ *   and Karsten Koeneke (CERN)
+ *
+ * and Metadata implementation based on xAODConfigTool by
+ *   Attila Krasznahorkay
+ *
+ **/
+class AsgElectronRingerSelector : public asg::AsgMetadataTool,
+                                  virtual public IAsgElectronRingerSelector
+{
+
+  public:
+    /**
+     * @class IOConfStruct
+     * @brief Configuration structure for parameters in file
+     **/
+    struct IOConfStruct {
+      bool useTrackPat;
+      bool useRawTrackPat;
+      //bool useCalStdPat;
+      //bool useRawCalStdPat(false),
+      bool useCaloCommittee;
+      bool useBLOutliers;
+      bool usePIXOutliers;
+      bool useSCTOutliers;
+      bool useTRTOutliers;
+      bool useTRTXenonHits;
+
+      IOConfStruct();
+    };
+
+    // Use ASG_TOOL macro for 2 interface base classes.
+    ASG_TOOL_CLASS2(AsgElectronRingerSelector, 
+                    IAsgElectronRingerSelector, 
+                    IAsgSelectionTool)
+
+  public:
+
+    /** Standard constructor */
+    AsgElectronRingerSelector(std::string myname);
+
+    /** Standard destructor */
+    virtual ~AsgElectronRingerSelector();
+
+    /** Gaudi Service Interface method implementations */
+    virtual StatusCode initialize();
+
+    /** Gaudi Service Interface method implementations */
+    virtual StatusCode finalize();
+
+    /// Main methods for IAsgSelectionTool interface
+    ///@{
+    /**
+     * @brief Set the discrimination configuration file
+     **/
+    void setDiscrFile( const std::string path );
+
+    /**
+     * @brief Set the threshold configuration file
+     **/
+    void setThresFile( const std::string path );
+
+    /**
+     * @brief Set the threshold configuration file
+     **/
+    void setCutMask( const unsigned int cutMask );
+
+    /**
+     * @brief Set the CutIDSelector to be used
+     **/
+    void setCutIDSelector( IAsgElectronIsEMSelector *cutID );
+
+    /**
+     * @brief Set the RingSetConfContainer (MetaData) key
+     **/
+    void setRSMetaName( const std::string name );
+
+    /**
+     * @brief Set whether to cache the meta data and assume it will be the same
+     *        through all the analysis.
+     **/
+    void setCacheMetaData( bool flag );
+
+    /** 
+     * @brief This method will bypass accept to xAOD::Electron if it is possible.
+     **/
+    const Root::TAccept& accept( const xAOD::IParticle* part ) const;
+
+    /** 
+     * @brief Identification procedure is done in this method
+     **/
+    const Root::TAccept& accept( const xAOD::Electron* part ) const;
+
+    /** 
+     * @brief Identification procedure is done in this method
+     **/
+    const Root::TAccept& accept( const xAOD::Egamma* eg ) const;
+
+    /** 
+     * @brief Accept using Electron reference 
+     **/
+    const Root::TAccept& accept( const xAOD::Electron& part ) const;
+    /** 
+     * @brief Accept using IParticle reference 
+     **/
+    const Root::TAccept& accept( const xAOD::IParticle& part ) const;
+
+    /** 
+     * @brief Identification procedure is done in this method
+     **/
+    const Root::TAccept& accept( const xAOD::Egamma& eg ) const;
+    
+    /** 
+     * @brief Method to get the plain TAccept for the last particle.
+     **/
+    const Root::TAccept& getTAccept() const;
+
+    /** Method to get output space representation */
+    const std::vector<float>& getOutputSpace() const;
+
+    /** 
+     * @brief Main execute method
+     **/                                            
+    StatusCode execute(const xAOD::Electron* eg) const;              
+
+    /** 
+     * @brief Execute without tracking information, potentially used by trigger.
+     **/
+    StatusCode execute(const xAOD::Egamma* eg) const;                
+
+    /**
+     * @brief Retrieve configuration on file 
+     **/
+    static void retrieveFileConf(const char* fileName, 
+        IOConfStruct &fileConf);
+
+    /**
+     * @brief Write configuration on file
+     **/
+    static void writeConf(const char* fileName, 
+        IOConfStruct &fileConf);
+
+    /**
+     * @brief Print file configuration
+     **/
+    static void printConf( IOConfStruct &fileConf, 
+        MsgStream *msg, MSG::Level lvl = MSG::DEBUG);
+    ///@}
+
+  protected:
+
+    /** 
+     * @brief Update metadata information held
+     */
+    StatusCode beginInputFile();
+
+    /**
+     * @brief Called when entering a new event
+     *
+     *  NOTE: This doesn't do anything for now
+     **/
+    StatusCode beginEvent();
+
+
+  private:
+
+    /// @name AsgElectronRingerSelector props (python configurables):
+    /// @{
+    
+    /// @brief Conf file in which we will retrieve the discrimination chain
+    std::string m_discrFileName;
+    
+    /// @brief Conf file in which we will retrieve the threshold values
+    std::string m_thresFileName;
+    
+    /// @brief The CutID Tool Handle to run track (if required by config file)
+    ToolHandle<IAsgElectronIsEMSelector> m_cutIDSelector;
+    
+    /// @brief The unsigned mask from which we will set m_cutsToUse (IsEM)
+    unsigned m_cutsMask;
+    
+    /// @brief RingSetConfContainer key in the MetaData StoreGate
+    std::string m_rsMetaName;
+    
+    /// @brief Whether to cache metadata configuration or not
+    bool m_cacheMetaData;
+    /// @}
+
+    /// @name AsgElectronRingerSelector props (non-python configurables):
+    /// @{
+    /// @brief The discriminator chain collection
+    IDiscrWrapperCollection m_discrWrapperCol;
+
+    /// @brief The discriminator chain collection
+    IThresWrapper *m_thresWrapper;
+    
+    /// @brief The Ringer Common Selector which will be run by this AsgSelector:
+    RingerCommonSelector *m_ringSelCommon;
+    
+    /// @brief Hold the track patterns:
+    ATH_RINGER_MUTABLE TrackPatternsHolder *m_trackPat;
+    
+    /// @brief The particles CaloRings decorations reader
+    xAOD::caloRingsReader_t* m_ringsELReader;
+    
+    /// @brief Last particle decision bitmask (the inverse of the IsEM)
+    ATH_RINGER_MUTABLE Root::TAccept m_partDecMsk;
+    
+    /// @brief Last particle accept bitmask (already applying the m_cutsToUse)
+    ATH_RINGER_MUTABLE Root::TAccept m_accept;
+    
+    /// @brief Which subset of decisions to use
+    ElectronTAccept::bitMskWord m_cutsToUse;
+    
+    /// Whether to use CutID track decision
+    bool m_useCutIDDecision;
+    
+    /// Flag to whether metadata is cached or not
+    bool m_metaDataCached;
+    
+    /// Hold pointer into the CaloRingsConfContainer
+    const xAOD::RingSetConfContainer* m_rsConfCont;
+
+    /// Hold the raw configuration collection:
+    xAOD::RingSetConf::RawConfCollection m_rawConfCol;
+
+    /// Cache if configuration info is on inputData
+    bool m_metaIsOnOutput;
+    /// @}
+
+    /// Private methods:
+    /// @{
+
+    /**
+     * @brief Read the configuration file
+     **/
+    StatusCode readConfigFiles();
+
+    /**
+     * @brief Register decision bitmask word
+     **/
+    StatusCode registerDecisionBitMask();
+
+    /**
+     * Set TAccept value
+     **/
+    void fillTAccept() const;
+    /// @}
+};
+
+#else // RINGER_STANDALONE is defined
+class AsgElectronRingerSelector 
+{
+  public:
+    /**
+     * @class IOConfStruct
+     * @brief Configuration structure for parameters in file
+     **/
+    struct IOConfStruct {
+      bool useTrackPat;
+      bool useRawTrackPat;
+      //bool useCalStdPat;
+      //bool useRawCalStdPat(false),
+      bool useCaloCommittee;
+      bool useBLOutliers;
+      bool usePIXOutliers;
+      bool useSCTOutliers;
+      bool useTRTOutliers;
+      bool useTRTXenonHits;
+
+      IOConfStruct();
+    };
+
+    /**
+     * @brief Retrieve configuration on file 
+     **/
+    static void retrieveFileConf(IOConfStruct &fileConf);
+
+    /**
+     * @brief Write configuration on file
+     **/
+    static void writeConf(TFile *file, 
+        IOConfStruct &fileConf);
+
+    /**
+     * @brief Print file configuration
+     **/
+    static void printConf( IOConfStruct &fileConf, 
+        MsgStream *msg, MSG::Level lvl = MSG::DEBUG);
+};
+#endif // ifndef RINGER_STANDALONE
+
+// Inline methods:
+//=============================================================================
+inline
+AsgElectronRingerSelector::IOConfStruct::IOConfStruct()
+  : useTrackPat(false),
+    useRawTrackPat(false),
+    //useCalStdPat,
+    //useRawCalStdPat(false),
+    useCaloCommittee(false),
+    useBLOutliers(false),
+    usePIXOutliers(false),
+    useSCTOutliers(false),
+    useTRTOutliers(false),
+    useTRTXenonHits(false){;}
+
+
+#ifndef RINGER_STANDALONE
+
+//=============================================================================
+inline
+void AsgElectronRingerSelector::setDiscrFile( const std::string path )
+{
+  m_discrFileName = path;
+}
+
+//=============================================================================
+inline
+void AsgElectronRingerSelector::setThresFile( const std::string path )
+{
+  m_thresFileName = path;
+}
+
+//=============================================================================
+inline 
+void AsgElectronRingerSelector::setCutMask( const unsigned int cutMask )
+{
+  m_cutsMask = cutMask;
+}
+
+//=============================================================================
+inline 
+void AsgElectronRingerSelector::setCutIDSelector( 
+      IAsgElectronIsEMSelector *cutID )
+{
+  m_cutIDSelector = ToolHandle<IAsgElectronIsEMSelector>(cutID);
+}
+
+//=============================================================================
+inline
+void AsgElectronRingerSelector::setRSMetaName( const std::string name )
+{
+  m_rsMetaName = name;
+}
+
+//=============================================================================
+inline
+void AsgElectronRingerSelector::setCacheMetaData( bool flag )
+{
+  m_cacheMetaData = flag;
+}
+
+//=============================================================================
+inline
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::Electron& part ) const 
+{
+  return accept (&part);
+}
+
+//=============================================================================
+inline
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::IParticle& part ) const 
+{
+  return accept (&part);
+}
+
+//=============================================================================
+inline
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::Egamma& part ) const 
+{
+  return accept (&part);
+}
+
+//=============================================================================
+inline
+const Root::TAccept& AsgElectronRingerSelector::getTAccept() const 
+{
+  return m_accept;
+}
+
+//=============================================================================
+inline
+const std::vector<float>& AsgElectronRingerSelector::getOutputSpace() const 
+{
+  if ( m_ringSelCommon ){
+    return m_ringSelCommon->getOutputSpace();
+  } else {
+    throw std::runtime_error(std::string("Cannot return outut space "
+          "because RingerCommonSelector was not yet allocated."));
+  }
+}
+
+} // namespace Ringer
+#endif // RINGER_STANDALONE
+
+#endif // RINGERSELECTORTOOLS_ASGELECTRONCALORINGERSELECTOR_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/ElectronTAccept.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/ElectronTAccept.h
new file mode 100644
index 0000000000000000000000000000000000000000..f39b3c19f2e77d47a4e3cd085911aed846b9c407
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/ElectronTAccept.h
@@ -0,0 +1,152 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ElectronTAccept.h 670599 2015-05-28 14:15:35Z wsfreund $
+#ifndef RINGER_STANDALONE
+
+#ifndef RINGERSELECTORTOOLS_ELECTRONTACCEPT_H
+#define RINGERSELECTORTOOLS_ELECTRONTACCEPT_H
+
+// Athena includes:
+#include "PATCore/TAccept.h"
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+
+namespace Ringer {
+
+class BitdefElectron_v1;
+
+/**
+ * @class ElectronTAccept_v1
+ * @brief Get electron defined TAccept and its masks.
+ **/
+class ElectronTAccept_v1 {
+  public:
+    /** 
+     * @brief Bit mask word used
+     *
+     * FIXME: Ask m_nBits to be encapsulated and a similar typedef like this to
+     * be within TAccept 
+     **/
+    typedef std::bitset<m_nBits> bitMskWord;
+
+    // Grant access to m_accept for BitdefElectron_v1
+    friend class BitdefElectron_v1;
+
+    /// Main methods
+    /// @{
+    /**
+     * @brief Retrieve copy of the ElectronTAccept_v1 template
+     **/
+    static unsigned int getAppliedCutMsk(const Requirement cut, 
+        bool withCutIDTrack = false);
+    /**
+     * @brief Retrieve copy of the ElectronTAccept_v1 template
+     **/
+    static Root::TAccept retrieveTAcceptTemplate(){ return m_accept;}
+    /// @}
+
+
+    /// Auxiliar methods
+    /// @{
+    /**
+     * @brief Reset mask so that it doesn't apply any cut (IsEM mask):
+     **/
+    static void resetMsk(bitMskWord& word);
+    /**
+     * @brief Add loose applied cuts to bitmask (IsEM mask):
+     **/
+    static void addLooseAppliedCuts(bitMskWord& word);
+    /**
+     * @brief Add medium applied cuts to bitmask (IsEM mask):
+     **/
+    static void addMediumAppliedCuts(bitMskWord& word);
+    /**
+     * @brief Add tight applied cuts bitmask (IsEM mask):
+     **/
+    static void addTightAppliedCuts(bitMskWord& word);
+    /**
+     * @brief Add CutID Track applied cuts to bitmask (IsEM mask):
+     **/
+    static void addCutIDTrackAppliedCuts(bitMskWord& word);
+    /// @}
+
+  private:
+    /**
+     * @brief Standard ctor (ensure abstract class).
+     **/
+    ElectronTAccept_v1();
+
+    /// The TAccept:
+    static Root::TAccept m_accept;
+};
+
+/**
+ * @class BitdefElectron_v1
+ * @brief Define electron bits (v1)
+ **/
+class BitdefElectron_v1 {
+/*
+ * NOTE:
+ *
+ *  Should new implementation inherit from this? That is, new bits 
+ *  can only be defined for positions that weren't yet defined:
+ *
+ *  Example:
+ *
+ *  \code
+ *  class BitdefElectron_v2 : public BitdefElectron_v2 
+ *  {
+ *    static const int NewBit;
+ *  }
+ *
+ *  \endcode
+ */
+
+  public:
+    /// The decision position set to true when no error occurs:
+    static const int NoErrorBit;
+    /// Whether CutID was run:
+    static const int ExecCutID;
+    /// The decision position of the CutID:
+    static const int CutIDDec;
+    /// The decision position of the Ringer algorithm's discrimation chain:
+    static const int RingerChainDec;
+
+    /// Number of bits:
+    static unsigned NUsedBits() { return m_nUsedBits; }
+
+  private:
+    /**
+     * @brief Declare bit to ElectronTAccept_v1 word
+     **/
+    static int declareBit(
+        const char* cutName,
+        const char* cutDescr)
+    {
+      int bit = ElectronTAccept_v1::m_accept.addCut(cutName,cutDescr);
+      ++m_nUsedBits;
+      return bit;
+    }
+
+    static unsigned m_nUsedBits;
+
+    /**
+     * @brief Standard ctor (ensure abstract class).
+     **/
+    BitdefElectron_v1();
+};
+
+// Definition of the current Electron TAccept version:
+typedef ElectronTAccept_v1 ElectronTAccept;
+// And the Electron Bitdef as well:
+typedef BitdefElectron_v1  BitdefElectron;
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_ELECTRONTACCEPT_H
+
+
+#endif // RINGER_STANDALONE
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/IAsgElectronRingerSelector.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/IAsgElectronRingerSelector.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e120f38ac53adf7bf0eca4f974d3f85a38c916e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/IAsgElectronRingerSelector.h
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IAsgElectronRingerSelector.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_IASGELECTRONRINGERSELECTOR_H
+#define RINGERSELECTORTOOLS_IASGELECTRONRINGERSELECTOR_H
+
+/**
+ * @class IAsgElectronRingerSelector
+ * @brief Interface to select electrons using Ringer information
+ *
+ * @author Werner Freund <wsfreund@cern.ch>
+ * @date   Nov 2014
+ *
+ **/
+
+// STL includes
+#include<vector>
+
+// Include the interfaces
+#include "PATCore/IAsgSelectionTool.h"
+
+// Include the return object and the underlying ROOT tool
+#include "PATCore/TAccept.h"
+
+// Forward declarations:
+#include "xAODEgamma/EgammaFwd.h"
+#include "xAODEgamma/ElectronFwd.h"
+
+class IAsgElectronIsEMSelector;
+
+class IAsgElectronRingerSelector : virtual public IAsgSelectionTool
+{
+
+  ASG_TOOL_INTERFACE(IAsgElectronRingerSelector)
+  
+  public:
+
+  /** Virtual Destructor */
+  virtual ~IAsgElectronRingerSelector() {};
+
+  /** The main accept method: using the generic interface */
+  virtual const Root::TAccept& accept( const xAOD::IParticle* part ) const = 0;
+
+  /** The main accept method: the actual cuts are applied here */
+  virtual const Root::TAccept& accept( const xAOD::Electron* part ) const = 0;
+
+  /** The main accept method: using the generic interface */
+  virtual const Root::TAccept& accept( const xAOD::IParticle& part ) const = 0;
+
+  /** The main accept method: the actual cuts are applied here */
+  virtual const Root::TAccept& accept( const xAOD::Electron& part ) const = 0;
+  
+  /** The basic Ringer selector tool execution */
+  virtual StatusCode execute(const xAOD::Electron* eg) const = 0;
+
+  /** The Ringer selector tool execution for HLT */
+  virtual StatusCode execute(const xAOD::Egamma* eg) const = 0;
+
+  /** Get last executed TAccept answer */
+  virtual const Root::TAccept& getTAccept() const = 0;
+  
+  /** Get last executed TResult value */
+  virtual const std::vector<float>& getOutputSpace() const = 0;
+
+  /**
+   * @brief Set the discrimination configuration file
+   **/
+  virtual void setDiscrFile( const std::string path ) = 0;
+
+  /**
+   * @brief Set the threshold configuration file
+   **/
+  virtual void setThresFile( const std::string path ) = 0;
+
+  /**
+   * @brief Set the threshold configuration file
+   **/
+  virtual void setCutMask( const unsigned int cutMask ) = 0;
+
+  /**
+   * @brief Set the CutIDSelector to be used
+   **/
+  virtual void setCutIDSelector( IAsgElectronIsEMSelector *cutID ) = 0;
+
+  /**
+   * @brief Set the RingSetConfContainer (MetaData) key
+   **/
+  virtual void setRSMetaName( const std::string name ) = 0;
+
+};
+
+
+#endif // RINGERSELECTORTOOLS_IASGELECTRONRINGERSELECTOR_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDefs.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..710261eee5c495175125c23080f8a8b781649e3e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDefs.h
@@ -0,0 +1,190 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerSelectorToolsDefs.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDEFS_H
+#define RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDEFS_H
+
+/**
+ *
+ * WARNING: Do not change the order of the enumerations for backward files
+ * compatibility!!
+ *
+ * This means that if a new value is needed, add it to the end (before the Nxxx
+ * enumeration) of the enumeration, instead of adding it to any place in the
+ * enumeration.
+ *
+ * After adding a enumeration type, also add it to the methods in the
+ * RingerSelectorToolsDefs.cxx file.
+ *
+ **/
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+
+/**                                                                                        
+ * @brief the possible procedure longitudinal segmentation types.
+ *
+ * - NoSegmentation stands for a unique representation for all data. This may
+ *   mean that the procedure: 
+ *
+ *    o is not applied for a pattern segment;
+ *
+ *    o has a specialized implemented approach that works in distinct depths of
+ *    the segmented information.
+ *
+ *    o cannot be applied in a segmentation approach. This is the case whenever
+ *    the procedure is not applied in the first layer or if the procedure is
+ *    the application of a threshold. In another words, only the first
+ *    PreProcessor and the first discriminator may have access to segmented
+ *    information, the later only if its pre-processing chain does not affect
+ *    the output segmentation.
+ *
+ * - TrackCalSegmentation will segmentate track (if information
+ *   available) from calorimeter.
+ *
+ * - TrackCalPatTypeSegmentation will segmentate track (if information
+ *   available) from calorimeter, the latter also being segmented between the
+ *   standard calorimeter patterns and rings.
+ *
+ * - TrackCalJointSections will segmentate track (if information available)
+ *   from calorimeter. Besides, the calorimeter information will be segmentated
+ *   through CalJointSections (see xAODCaloRings/CaloRingsDefs.h).
+ *
+ * - TrackCalJointLayers will segmentate track (if information available) from
+ *   calorimeter. Besides, the calorimeter information will be segmentated
+ *   through CalJointLayers (see xAODCaloRings/CaloRingsDefs.h).
+ *
+ * If adding a new value on this enumeration, add it to the numberOfSegments
+ * function on RingerSelectorToolsDefs.cxx
+ **/
+enum SegmentationType { 
+  NoSegmentation = 0,
+  TrackCalSegmentation,
+  TrackCalPatTypeSegmentation,
+  TrackCalJointSections,
+  TrackCalJointLayers,
+  NSegmentations
+};
+
+/** 
+ * @brief Specify eta position dependency 
+ *
+ * This specifies whether the discriminator will operate only for a small
+ * (bin) eta region or will operate for the full analysis region (generally the
+ * ATLAS precision region).
+ *
+ **/
+enum EtaDependency {
+  EtaIndependent = 0,
+  EtaDependent,
+  NEtaDependencies
+};
+
+/** 
+ * @brief Specify et position dependency 
+ *
+ * This specifies whether the discriminator will operate only for a small
+ * (bin) Et region or will operate for the full analysis region (generally the
+ * ATLAS precision region).
+ *
+ **/
+enum EtDependency {
+  EtIndependent = 0,
+  EtDependent,
+  NEtDependencies
+};
+
+/** 
+ * @brief the cut requirement 
+ **/
+enum Requirement {
+  Loose_CutID_Pd = 0, // Same detection probability as CutID Loose
+  Medium_CutID_Pd,    // Same detection probability as CutID Medium
+  Tight_CutID_Pd,     // Same detection probability as CutID Tight
+  Loose_CutID_Pf,     // Same false alarm probability as CutID Loose
+  Medium_CutID_Pf,    // Same false alarm probability as CutID Medium
+  Tight_CutID_Pf,     // Same false alarm probability as CutID Tight
+  Loose_LH_Pd,        // Same detection probability as LH Loose
+  Medium_LH_Pd,       // Same detection probability as LH Medium
+  Tight_LH_Pd,        // Same detection probability as LH Tight
+  Loose_LH_Pf,        // Same false alarm probability as LH Loose
+  Medium_LH_Pf,       // Same false alarm probability as LH Medium
+  Tight_LH_Pf,        // Same false alarm probability as LH Tight
+  Medium_MaxSP,       // Maximum SP-product
+  Loose,              // Same as LooseCutIDPd
+  Medium,             // Same as MediumSP
+  Tight,              // Same as TightCutIDPf
+  NoCut,              // Run to retrieve discriminators output, but no cut is applied
+  NRequirements       // Number of Requirements available
+};
+
+/**
+ * Return number of segments for segment of type @name e.
+ **/
+unsigned numberOfSegments(const SegmentationType e);
+
+/**
+ * Return Ringer enumeration of type T identifying string type:
+ **/
+template<typename T>
+T getType(const char* cStr);
+
+/**
+ * Specialization for SegmentationType
+ **/
+template<>
+SegmentationType getType(const char* cStr);
+
+/**
+ * Specialization for EtaDependency
+ **/
+template<>
+EtaDependency getType(const char* cStr);
+
+/**
+ * Specialization for EtDependency
+ **/
+template<>
+EtDependency getType(const char* cStr);
+
+/**
+ * Specialization for Requirement
+ **/
+template<>
+Requirement getType(const char* cStr);
+
+// Explicit instantiate the templates functions to avoid multiple definition
+template SegmentationType getType(const char *);
+template EtaDependency getType(const char *);
+template EtDependency getType(const char *);
+template Requirement getType(const char *);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(SegmentationType e);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(EtaDependency e);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(EtDependency e);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(Requirement e);
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDEFS_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDict.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2d3d0b983a24ce37fb63ba8ecc7e10046bd0415
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/RingerSelectorToolsDict.h
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerSelectorToolsDict.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDICT_H
+#define RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDICT_H
+
+#include <vector>
+
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+
+// These are only available if we are not in a standalone environment.
+#ifndef RINGER_STANDALONE
+#include "RingerSelectorTools/tools/RingerCommonSelector.h"
+#include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#endif
+
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/RingerIOVarDepObj.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.h"
+
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+#include "RingerSelectorTools/procedures/Types.h"
+
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.h"
+
+#include "RingerSelectorTools/procedures/Normalizations.h"
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+#include "RingerSelectorTools/procedures/Thresholds.h"
+
+/*
+#define RINGER_DECLARE_VARDEP_T(name, inst_name) \
+  name< Ringer::EtaDependent   , Ringer::EtDependent   > inst_name ## _etaDep_etDep; \
+  name< Ringer::EtaDependent   , Ringer::EtIndependent > inst_name ## _etaDep_etIndep; \
+  name< Ringer::EtaIndependent , Ringer::EtDependent   > inst_name ## _etaIndep_etDep; \
+  name< Ringer::EtaIndependent , Ringer::EtIndependent > inst_name ## _etaIndep_etIndep;
+*/
+
+#define _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, segType, inst_name) \
+  Ringer::RingerProcedureWrapper< type, Ringer::EtaDependent,     Ringer::EtDependent,    segType > inst_name ## _etaDep_etDep; \
+  Ringer::RingerProcedureWrapper< type, Ringer::EtaIndependent,   Ringer::EtDependent,    segType > inst_name ## _etaIndep_etDep; \
+  Ringer::RingerProcedureWrapper< type, Ringer::EtaDependent,     Ringer::EtIndependent,  segType > inst_name ## _etaDep_etIndep; \
+  Ringer::RingerProcedureWrapper< type, Ringer::EtaIndependent,   Ringer::EtIndependent,  segType > inst_name ## _etaIndep_etIndep; 
+
+#define RINGER_DECLARE_ONLYALLCALO_WRAPPER_T(type, inst_name) \
+  _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::NoSegmentation, inst_name ## _allCalo )
+
+#define RINGER_DECLARE_ALLSEGTYPES_WRAPPER_T(type, inst_name) \
+  _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::NoSegmentation, inst_name ## _allCalo ) \
+  _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::TrackCalSegmentation, inst_name ## _trackCalSeg ) \
+  /*_RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::TrackCalPatTypeSegmentation, inst_name ## _trackCalSeg )*/ \
+  _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::TrackCalJointSections, inst_name ## _jSec ) \
+  _RINGER_DECLARE_WRAPPER_T_WITH_SEG_TYPE_(type, Ringer::TrackCalJointLayers, inst_name ## _jLay )
+
+template void Ringer::IOHelperFcns::readVar<Ringer::EtaDependency,unsigned>(TDirectory*, const char*, Ringer::EtaDependency&);
+template void Ringer::IOHelperFcns::readVar<Ringer::EtDependency,unsigned>(TDirectory*, const char*, Ringer::EtDependency&);
+template void Ringer::IOHelperFcns::readVar<Ringer::SegmentationType,unsigned>(TDirectory*, const char*, Ringer::SegmentationType&);
+template void Ringer::IOHelperFcns::readVar<Ringer::PreProcessing::Type::PreProcessorTypes,unsigned>(TDirectory*, const char*, Ringer::PreProcessing::Type::PreProcessorTypes&);
+template void Ringer::IOHelperFcns::readVar<Ringer::Discrimination::Type::DiscriminatorTypes,unsigned>(TDirectory*, const char*, Ringer::Discrimination::Type::DiscriminatorTypes&);
+template void Ringer::IOHelperFcns::readVar<Ringer::Discrimination::Type::ThresholdTypes,unsigned>(TDirectory*, const char*, Ringer::Discrimination::Type::ThresholdTypes&);
+template void Ringer::IOHelperFcns::readVar(TDirectory*, const char*, unsigned&);
+template void Ringer::IOHelperFcns::readVar(TDirectory*, const char*, float&);
+//-------------- For now, we also include the write variable methods
+template void Ringer::IOHelperFcns::writeVar<const Ringer::EtaDependency,const unsigned>(TDirectory*, const char*, const Ringer::EtaDependency&);
+template void Ringer::IOHelperFcns::writeVar<const Ringer::EtDependency,const unsigned>(TDirectory*, const char*, const Ringer::EtDependency&);
+template void Ringer::IOHelperFcns::writeVar<const Ringer::SegmentationType,const unsigned>(TDirectory*, const char*, const Ringer::SegmentationType&);
+template void Ringer::IOHelperFcns::writeVar<const Ringer::PreProcessing::Type::PreProcessorTypes,const unsigned>(TDirectory*, const char*, const Ringer::PreProcessing::Type::PreProcessorTypes&);
+template void Ringer::IOHelperFcns::writeVar<const Ringer::Discrimination::Type::DiscriminatorTypes,const unsigned>(TDirectory*, const char*, const Ringer::Discrimination::Type::DiscriminatorTypes&);
+template void Ringer::IOHelperFcns::writeVar<const Ringer::Discrimination::Type::ThresholdTypes,const unsigned>(TDirectory*, const char*, const Ringer::Discrimination::Type::ThresholdTypes&);
+template void Ringer::IOHelperFcns::writeVar(TDirectory*, const char*, unsigned&);
+template void Ringer::IOHelperFcns::writeVar(TDirectory*, const char*, float&);
+//---------------------------------------------------------------------
+
+namespace RingerSelectorToolsDict {
+
+struct dict {
+
+  //std::vector<long long>             m_vecLongLong;
+  //std::vector<unsigned long long>    m_vecULongLong;
+  //std::vector<unsigned long>    m_vecULong;
+  //std::vector<Ringer::EtaDependency>    m_vecEtaDep;
+  std::vector<Ringer::PreProcessing::Norm::Norm1VarDep*>    m_vecNorm1;
+  std::vector<std::vector<Ringer::PreProcessing::Norm::Norm1VarDep*> >    m_vecVecNorm1;
+
+  std::vector<Ringer::Discrimination::NNFeedForwardVarDep*>    m_vecNN;
+  std::vector<std::vector<Ringer::Discrimination::NNFeedForwardVarDep*> >  m_vecVecNN;
+
+  //Ringer::RingerProcedureWrapper<Ringer::PreProcessing::Norm1VarDep, 
+  //                               Ringer::EtaIndependent,
+  //                               Ringer::EtIndependent,
+  //                               Ringer::NoSegmentation> discrDummy;
+
+  /// Wrappers
+  /// @{
+  // Add all interface wrappers:
+  RINGER_DECLARE_ALLSEGTYPES_WRAPPER_T(Ringer::PreProcessing::IPreProcessorVarDep, iwrap_ipp)
+  RINGER_DECLARE_ALLSEGTYPES_WRAPPER_T(Ringer::Discrimination::IDiscriminatorVarDep, iwrap_idiscr)
+  //RINGER_DECLARE_ONLYALLCALO_WRAPPER_T(Ringer::Discrimination::IThresholdVarDep, iwrap_ithres)
+  // Now we add some the specialized procedure wrappers:
+  // Norm1:
+  RINGER_DECLARE_ONLYALLCALO_WRAPPER_T(Ringer::PreProcessing::Norm::Norm1VarDep, norm1)
+  // NNFeedForward:
+  RINGER_DECLARE_ONLYALLCALO_WRAPPER_T(Ringer::Discrimination::NNFeedForwardVarDep, nnff)
+  // UniqueThreshold
+  RINGER_DECLARE_ONLYALLCALO_WRAPPER_T(Ringer::Discrimination::UniqueThresholdVarDep, uniqueThres)
+  /// @}
+
+};
+
+} // private namespace
+
+
+#ifdef G__DICTIONARY   // ROOT6 dictionary compilation
+#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)
+// MN:  pull in the Ringer enums and variables for ROOT6 on dictionary library loading
+#include "TInterpreter.h"
+namespace Ringer {
+   struct DeclareHeader {
+     DeclareHeader() {
+        gInterpreter->Declare("#include \"RingerSelectorTools/RingerSelectorToolsDefs.h\"");
+        gInterpreter->Declare("#include \"RingerSelectorTools/procedures/Types.h\"");
+        gInterpreter->Declare("#include \"RingerSelectorTools/tools/IOHelperFcns.h\"");
+     }
+   } declareHeader;
+}
+#endif
+#endif
+
+#endif // RINGERSELECTORTOOLS_RINGERSELECTORTOOLSDICT_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/IRingerProcedure.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/IRingerProcedure.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3fad5933140e73723f6935bc23a3b594646d0a7
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/IRingerProcedure.h
@@ -0,0 +1,402 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IRingerProcedure.h 694257 2015-09-10 22:45:27Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_IPROCEDURE_H
+#define RINGERSELECTORTOOLS_PROCEDURES_IPROCEDURE_H
+
+// STL includes:
+#include <vector>
+
+// Root includes:
+#include <TDirectory.h>
+//#include <TClass.h>
+
+// Local includes:
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/IRedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/StaticAssert.h"
+#include "RingerSelectorTools/tools/cxx/is_base_of.h"
+#include "RingerSelectorTools/tools/cxx/conditional.h"
+#include "RingerSelectorTools/tools/cxx/enable_if.h"
+
+#ifndef INCLUDE_HEADER_ONLY
+#define INCLUDE_HEADER_ONLY
+#endif // INCLUDE_HEADER_ONLY
+#include "RingerSelectorTools/procedures/Types.h"
+#undef INCLUDE_HEADER_ONLY
+
+/**
+ * Define ringer interface default methods
+ *
+ * It defines static template member type, that can be used to retrieve
+ * procedure type as an enumeration type. In order for this to work, make sure
+ * to add the enumeration value on Types.h file and add it properly to the
+ * conversion string<->enumeration function in the Types.cxx file.
+ *
+ * Beware that it changes scope inside class to public.
+ *  
+ **/
+#define RINGER_DEFINE_INTERFACE(self)                                          \
+                                                                               \
+  public:                                                                      \
+                                                                               \
+    template <typename T = const char*>                                        \
+    static T procType();                                                       \
+                                                                               \
+    virtual const char* name() const = 0;                                      \
+                                                                               \
+    virtual void print(MSG::Level lvl) const = 0;
+
+/**
+ * Define Ringer interface procedure type methods.
+ **/
+#define RINGER_DEFINE_INTERFACE_DEFAULT_METHODS(self)                          \
+                                                                               \
+  template<>                                                                   \
+  inline                                                                       \
+  const char* self::procType()                                                 \
+  {                                                                            \
+    return #self;                                                              \
+  }                                                                            \
+                                                                               \
+  template<>                                                                   \
+  inline                                                                       \
+  Ringer::RingerProcedureType<self>::procEnum_t self::procType()               \
+  {                                                                            \
+    return Ringer::getType<                                                    \
+        Ringer::RingerProcedureType<self>::procEnum_t>(#self);                 \
+  }
+
+#define __RINGER_DEFINE_PROCEDURE_STANDARD_METHODS__(self)                     \
+                                                                               \
+    virtual const char* name() const                                           \
+      ATH_RINGER_OVERRIDE;
+
+/**
+ * Use this macro when procedure has member properties
+ **/
+#define RINGER_DEFINE_PROCEDURE(self)                                          \
+                                                                               \
+  public:                                                                      \
+    __RINGER_DEFINE_PROCEDURE_STANDARD_METHODS__(self)                         \
+                                                                               \
+    virtual void print(MSG::Level lvl) const                                   \
+      ATH_RINGER_OVERRIDE;
+
+/**
+ * Use this macro when procedure hasn't member properties 
+ **/
+#define RINGER_DEFINE_NOMEMBER_PROCEDURE(self)                                 \
+                                                                               \
+  public:                                                                      \
+    __RINGER_DEFINE_PROCEDURE_STANDARD_METHODS__(self)                         \
+                                                                               \
+    virtual void print(MSG::Level lvl) const                                   \
+      ATH_RINGER_OVERRIDE                                                      \
+    {                                                                          \
+      if ( !this->isStreamAvailable() ) {                                      \
+        std::cerr << "Cannot print " << this->name() << ", stream unavailable" \
+          << std::endl;                                                        \
+      }                                                                        \
+      if ( this->level() > lvl ) {                                             \
+        return;                                                                \
+      }                                                                        \
+      ATH_MSG_LVL(lvl, "Procedure hasn't any property.");                      \
+    }
+/// @}
+
+/**
+ * This macro should be defined for every Ringer Procedure defined after the
+ * class is defined, within same scope and translation unit where it is
+ * defined.
+ *
+ * You will have to define the procedure print method yourself.
+ **/
+#define RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS(self)                          \
+                                                                               \
+  /*RINGER_DEFINE_INTERFACE_DEFAULT_METHODS(self)*/                            \
+                                                                               \
+  inline                                                                       \
+  const char* self::name() const                                               \
+  {                                                                            \
+    return this->procType<const char*>();                                      \
+  }
+
+
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+// Declare interface base for all Ringer procedure types:
+//
+/**
+ * @class IRingerProcedure
+ * @brief The base interface for all Ringer procedures.
+ *
+ * Note: Every Ringer Procedure redirects message stream
+ **/
+class IRingerProcedure : virtual public IRedirectMsgStream { 
+  public:
+    /**
+     * @brief Write Ringer procedure to configuration directory
+     **/
+    virtual void write(TDirectory *configDir, const char*idxStr = "") 
+        const = 0;
+
+    /** Ensures virtual dtor for all inherited classes */
+    virtual ~IRingerProcedure(){;}
+
+  protected: 
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IRingerProcedure,0)
+};
+
+// Forward declare base procedure types:
+namespace PreProcessing {
+  class IPreProcessor;
+  class IPreProcessorVarDep;
+}
+
+namespace Discrimination {
+  class IDiscriminator;
+  class IDiscriminatorVarDep;
+  class IThreshold;
+  class IThresholdVarDep;
+}
+
+/**
+ * @class RingerProcedureType
+ * @brief Check Ringer Procedure type.
+ *
+ * Only available to this translation unit.
+ *
+ *  - Use RingerProcedure<Procedure>::is_pre_processor to get if procedure is
+ * of pre-processing type
+ *
+ *  - Use RingerProcedure<Procedure>::is_discriminator to get if procedure is
+ * of discriminator type
+ *
+ *  - Use RingerProcedure<Procedure>::is_threshold to get if procedure is
+ * of threshold type
+ **/
+template<typename procedure_t > 
+struct RingerProcedureType {
+
+  RINGER_STATIC_ASSERT( (Ringer::is_base_of<IRingerProcedure,procedure_t>::value),
+      "Requested to check Ringer procedure type from class that is not a IRingerProcedure.");
+
+  // Determine which procedure type it is:
+#if RINGER_USE_NEW_CPP_FEATURES || defined(FORCE_RINGER_PROCEDURE_TYPE_CONST_EXPR)
+  static constexpr bool is_pre_processor =
+    Ringer::is_base_of<PreProcessing::IPreProcessor,procedure_t>::value;
+  static constexpr bool is_discriminator =
+    Ringer::is_base_of<Discrimination::IDiscriminator,procedure_t>::value;
+  static constexpr bool is_threshold = 
+    Ringer::is_base_of<Discrimination::IThreshold,procedure_t>::value;
+
+  RINGER_STATIC_ASSERT( ( is_pre_processor || is_discriminator || is_threshold ), 
+      "Couldn't find a procedure type.");
+
+  // Determine which enumType it should have been declared
+  typedef typename Ringer::conditional< is_pre_processor, 
+    preProcEnum_t,  // true, it is_pre_processor
+      typename Ringer::conditional< is_discriminator, 
+    discrEnum_t, // true, it is discriminator
+      thresEnum_t >::type >::type procEnum_t;
+
+  // Boolean to determine whether this procedure inherits from VariableDependency
+  static constexpr bool inherits_from_var_dep = Ringer::is_base_of< VariableDependency, 
+                                                             procedure_t>::value;
+
+  // Determine which interface this Ringer procedure inherits from
+  typedef typename Ringer::conditional< is_pre_processor, 
+    // true, it is_pre_processor
+    typename Ringer::conditional< inherits_from_var_dep,
+        PreProcessing::IPreProcessorVarDep, PreProcessing::IPreProcessor>::type, 
+    // not pre_processor, check if is_discriminator
+    typename Ringer::conditional< is_discriminator, 
+      // true, it is_discriminator
+      typename Ringer::conditional< inherits_from_var_dep,
+          Discrimination::IDiscriminatorVarDep, Discrimination::IDiscriminator>::type, 
+      // otherwise it has to be threshold
+      typename Ringer::conditional< inherits_from_var_dep,
+          Discrimination::IThresholdVarDep, Discrimination::IThreshold>::type   
+    >::type 
+  >::type baseInterface_t;
+
+#else
+  static const bool is_pre_processor;
+  static const bool is_discriminator;
+  static const bool is_threshold;
+#endif
+};
+
+/**
+ * @brief RingerProcedureType specialization to ensure that procedure_t is not
+ *        a pointer
+ **/ 
+template<typename procedure_t >
+struct RingerProcedureType<procedure_t*> : public RingerProcedureType<procedure_t>{ };
+
+/** 
+ * @brief Namespace dedicated for Ringer pre-processing utilities 
+ **/
+namespace PreProcessing {
+
+/**
+ * @brief PreProcessing interface to be inherited by PreProcessing procedures.
+ **/
+class IPreProcessor : virtual public IRingerProcedure 
+{
+
+  RINGER_DEFINE_INTERFACE( IPreProcessor )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IPreProcessor& operator=(IPreProcessor&&);
+  public:
+    /**
+     * @brief Execute transform @name inputSpace to a new space representation.
+     **/
+    virtual void execute(std::vector<float> &inputSpace) const = 0;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IPreProcessor,0)
+};
+
+/**
+ * @brief PreProcessor interface to be used by Ringer Wrapper.
+ **/
+class IPreProcessorVarDep : public virtual VariableDependency,
+                            public virtual IPreProcessor
+{
+
+  RINGER_DEFINE_INTERFACE( IPreProcessorVarDep )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IPreProcessorVarDep& operator=(IPreProcessorVarDep&&);
+  public:
+    //IPreProcessorVarDep(){;}
+
+    // This is needed for parsing wrapper
+    static IPreProcessorVarDep* read(TDirectory *){ return nullptr;}
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IPreProcessorVarDep,0)
+};
+
+} // namespace PreProcessor
+
+/** 
+ * @brief Namespace dedicated for Ringer Discrimination utilities 
+ **/
+namespace Discrimination {
+
+/**
+ * @brief Discriminator interface to be inherited by discrimination procedures.
+ **/
+class IDiscriminator : virtual public IRingerProcedure 
+{
+
+  RINGER_DEFINE_INTERFACE( IDiscriminator )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IDiscriminator& operator=(IDiscriminator&&);
+  public:
+    virtual void execute(const std::vector<float> &input, 
+        std::vector<float> &output) const = 0;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IDiscriminator,0)
+};
+
+/**
+ * @brief Discriminator interface to be used by Ringer Wrapper.
+ **/
+class IDiscriminatorVarDep : public virtual VariableDependency,
+                             public virtual IDiscriminator
+{
+
+  RINGER_DEFINE_INTERFACE( IDiscriminatorVarDep )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IDiscriminatorVarDep& operator=(IDiscriminatorVarDep&&);
+  public:
+    //IDiscriminatorVarDep(){;}
+
+    // This prototype is needed for parsing wrapper
+    static IDiscriminatorVarDep* read(TDirectory *){ return nullptr;}
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IDiscriminatorVarDep,0)
+};
+
+/**
+ * @brief Threshold interface to be inherited by thresholding procedures.
+ **/
+class IThreshold : virtual public IRingerProcedure
+{
+
+  RINGER_DEFINE_INTERFACE( IThreshold )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IThreshold& operator=(IThreshold&&);
+  public:
+    /**
+     * @brief Execute threshold for input and retrieve throw output.
+     **/
+    virtual void execute(const std::vector<float> &input,
+            std::vector<bool> &output) const = 0;
+    
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IThreshold,0)
+};
+
+/**
+ * @brief Threshold interface to be used by Ringer Wrapper.
+ **/
+class IThresholdVarDep : public virtual VariableDependency,
+                         public virtual IThreshold
+{
+
+  RINGER_DEFINE_INTERFACE( IThresholdVarDep )
+
+  protected:
+    /** Note: https://sft.its.cern.ch/jira/browse/CFHEP-87 */
+    IThresholdVarDep& operator=(IThresholdVarDep&&);
+  public:
+    //IThresholdVarDep(){;}
+    
+    // This prototype is needed for parsing wrapper
+    static IThresholdVarDep* read(TDirectory *){ return nullptr;}
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(IThresholdVarDep,0)
+};
+
+} // namespace Discrimination
+
+// Declare procedure type member functions
+namespace PreProcessing {
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IPreProcessor )
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IPreProcessorVarDep )
+} // namespace PreProcessing
+namespace Discrimination {
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IThreshold )
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IThresholdVarDep )
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IDiscriminator )
+RINGER_DEFINE_INTERFACE_DEFAULT_METHODS( IDiscriminatorVarDep )
+} // namespace Discrimination
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_IPROCEDURE_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/NeuralNetwork.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/NeuralNetwork.h
new file mode 100644
index 0000000000000000000000000000000000000000..632faf5fcbc2b8b94f3308943561381e695445a1
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/NeuralNetwork.h
@@ -0,0 +1,150 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: NeuralNetwork.h 693248 2015-09-04 17:52:57Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_NEURALNETWORK_H
+#define RINGERSELECTORTOOLS_PROCEDURES_NEURALNETWORK_H
+
+//#undef NDEBUG
+
+// STL includes:
+#include <vector>
+
+// Local includes:
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+
+// Local tool includes:
+#include "RingerSelectorTools/tools/RingerIOVarDepObj.h"
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+
+namespace Ringer {
+
+
+namespace Discrimination {
+
+/**
+ *  @class NNFeedForward
+ *  @brief Provides Neural Network FeedForward
+ *
+ *  @author: Dhiana Deva Cavalcanti Rocha <dhiana.deva@gmail.com> (LPS/UFRJ)
+ *  @author: Werner S. Freund <wsfreund@cern.ch> (LPS/UFRJ)
+ *                (revised implementation)
+ *
+ *  @date: Jan 2015
+ **/
+class NNFeedForward : virtual public IDiscriminator, 
+                      public RedirectMsgStream
+{
+
+  RINGER_IO_VARDEP_BASE( NNFeedForward )
+
+  public:
+    /**
+     * @brief Main ctor
+     **/
+    NNFeedForward(const std::vector<unsigned int> &nodes, 
+       const std::vector<float> &weights, 
+       const std::vector<float> &bias);
+
+    NNFeedForward(): m_nLayers(0),
+                     m_wM(nullptr),
+                     m_bM(nullptr),
+                     m_mM(nullptr){;}
+    /**
+     * @brief Propagates input through neural network
+     **/
+    virtual void execute(const std::vector<float> &input,
+        std::vector<float> &output) const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    void changeArchiteture(const std::vector<unsigned int> &nodes, 
+        const std::vector<float> &weights, 
+        const std::vector<float> &bias);
+
+    /**
+     * @brief Main dtor
+     **/
+    ~NNFeedForward();
+
+  protected:
+    /**
+     * Release bias memory
+     **/
+    void releaseBias();
+
+    /**
+     * Release weights memory
+     **/
+    void releaseWeights();
+
+    /**
+     * Release multiplication matrix memory
+     **/
+    void releaseMMatrix();
+
+    /**
+     * Get m_wM and m_bM on std::vector unique dimension representation:
+     **/
+    void getWeigthsAndBias(std::vector<float> &weights,
+        std::vector<float> &bias) const;
+
+  private:
+
+    /// @brief Neural network nodes size description
+    std::vector<unsigned int> m_nodes;
+    /// @brief Neural network number of layers
+    size_t m_nLayers;
+    /// @brief Neural network weights
+    float ***m_wM;
+    /// @brief Neural network bias
+    float **m_bM;
+    /// @brief Temporary multiplication matrix
+    float **m_mM;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(NNFeedForward,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( NNFeedForward )
+
+/**
+ *  @class NNFeedForwardVarDep
+ *  @brief Provides Neural Network FeedForward mechanism.
+ *
+ *  @author: Werner S. Freund <wsfreund@cern.ch> (LPS/UFRJ)
+ *  @author: Dhiana Deva Cavalcanti Rocha <dhiana.deva@gmail.com> (LPS/UFRJ)
+ *
+ *  @date: Jan 2015
+ **/
+class NNFeedForwardVarDep : virtual public IDiscriminatorVarDep,
+                            public RingerIOVarDepObj < NNFeedForwardVarDep >,
+                            public NNFeedForward
+{
+
+  RINGER_IO_VARDEP_OBJ(NNFeedForwardVarDep, NNFeedForward)
+
+  public:
+
+    /**
+     * Main ctor
+     **/
+    NNFeedForwardVarDep(const std::vector<unsigned int> &nodes, 
+        const std::vector<float> &weights, 
+        const std::vector<float> &bias):
+      NNFeedForward(nodes,weights,bias){;}
+
+    /**
+     * Empty ctor
+     **/
+    NNFeedForwardVarDep(){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(NNFeedForwardVarDep,1)
+};
+
+} // namespace Discrimination
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_NEURALNETWORK_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2ddafc05389206035b4d0768d277c7bcfda2864
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.h
@@ -0,0 +1,428 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Normalizations.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_NORMALIZATIONS_H
+#define RINGERSELECTORTOOLS_PROCEDURES_NORMALIZATIONS_H
+
+//#undef NDEBUG
+
+// STL includes:
+#include <vector>
+#include <stdexcept>
+#include <string>
+#include <cmath>
+#include <iostream>
+
+// Gaudi includes:
+#if !defined(XAOD_STANDALONE) && !defined(RINGER_STANDALONE)
+# include "GaudiKernel/SystemOfUnits.h"
+#endif
+
+
+// Local includes:
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+#include "RingerSelectorTools/tools/RingerIOVarDepObj.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer
+{
+
+/** 
+* @brief Namespace dedicated for Ringer pre-processing utilities 
+**/
+namespace PreProcessing
+{
+
+/** 
+ * @brief Namespace dedicated for Ringer normalization utilities 
+ **/
+namespace Norm {
+
+/// Normalization base classes:
+/// @{
+class Norm1 : virtual public IPreProcessor,
+              public RedirectMsgStream 
+{
+
+  RINGER_IO_VARDEP_BASE_NOMEMBER( Norm1 )
+
+  private:
+    Norm1(Norm1&&);
+
+  public:
+    Norm1(){;}
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(Norm1,1)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( Norm1 )
+
+class Norm2 : public virtual IPreProcessor,
+              public RedirectMsgStream 
+{
+
+  RINGER_IO_VARDEP_BASE_NOMEMBER( Norm2 )
+
+  private:
+    Norm2(Norm2&&);
+
+  public:
+    Norm2(){;}
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(Norm2,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( Norm2 )
+
+class Sqrt : public virtual IPreProcessor,
+             public RedirectMsgStream 
+{
+
+  RINGER_IO_VARDEP_BASE_NOMEMBER( Sqrt )
+
+  private:
+    Sqrt(Sqrt&&);
+
+  public:
+    Sqrt(){};
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(Sqrt,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( Sqrt )
+
+class ConstantValue : public virtual IPreProcessor,
+                      public RedirectMsgStream 
+{
+
+  RINGER_IO_VARDEP_BASE( ConstantValue )
+
+  private:
+    ConstantValue(ConstantValue&&);
+    /// Inverse value of the constant value normalization
+    float m_constantInv; 
+
+  public:
+
+    ConstantValue() 
+      : m_constantInv(1){;}
+    ConstantValue(
+        const float constantValue)
+      : m_constantInv(1/constantValue)
+    {
+      if (!m_constantInv) {
+        throw std::runtime_error(
+            std::string("Initialized ConstantValueVarDep norm with zero constant"));
+      }
+    }
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(ConstantValue,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( ConstantValue )
+
+class Sequential : public virtual IPreProcessor,
+                   public RedirectMsgStream 
+{
+  RINGER_IO_VARDEP_BASE( Sequential )
+
+  private:
+    Sequential(Sequential&&);
+    /// @brief The stop energy threshold for increasing noise
+    float m_stopEnergy;
+    /// @brief The energy threshold for choosing 
+    float m_energyThres;
+
+  public:
+
+    Sequential()
+      : m_stopEnergy(0),
+        m_energyThres(0){;}
+
+    Sequential(
+        const float stopEnergy,
+        const float energyThres)
+      : m_stopEnergy(stopEnergy),
+        m_energyThres(energyThres){;}
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(Sequential,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( Sequential )
+
+class Spherization : public virtual IPreProcessor,
+                     public RedirectMsgStream
+{
+  RINGER_IO_VARDEP_BASE( Spherization )
+
+  private:
+    Spherization(Spherization&&);
+    /// @brief The training sample data mean
+    std::vector<float> m_deslocation;
+    /// @brief The inverse of the training sample data standard deviation
+    std::vector<float> m_normInv;
+    /// Input dimension (transient variable)
+    size_t m_dim;
+  public:
+
+    Spherization()
+        : m_dim(0){;}
+
+    Spherization(
+        const std::vector<float> &dataMean,
+        const std::vector<float> &dataStd);
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(Spherization,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( Spherization )
+
+class MinMax : public virtual IPreProcessor,
+               public RedirectMsgStream
+{
+  RINGER_IO_VARDEP_BASE( MinMax )
+
+  private:
+    MinMax(MinMax&&);
+    /// @brief The training sample data min
+    std::vector<float> m_deslocation;
+    /// @brief The inverse of sample delta(max,min)
+    std::vector<float> m_normInv;
+    /// Input dimension (transient variable)
+    size_t m_dim;
+  public:
+    MinMax()
+      : m_dim(0){;}
+
+    MinMax(
+        const std::vector<float> min,
+        const std::vector<float> max);
+  public:
+
+    virtual void execute(std::vector<float> &inputSpace) const ATH_RINGER_FINAL
+      ATH_RINGER_OVERRIDE;
+
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(MinMax,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( MinMax )
+/// @}
+
+/// @ Usable normalizations:
+/// @{
+/**
+ * @brief Use norm-1 as rings normalization factor
+ **/
+class Norm1VarDep : virtual public IPreProcessorVarDep,
+                    public RingerIOVarDepObj < Norm1VarDep >,
+                    public Norm1
+{ 
+  RINGER_IO_VARDEP_OBJ(Norm1VarDep, Norm1)
+
+  public:
+
+    Norm1VarDep(){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(Norm1VarDep,1)
+};
+
+/**
+ * @brief Use norm-2 as rings normalization factor
+ **/
+class Norm2VarDep : virtual public IPreProcessorVarDep,
+                    public RingerIOVarDepObj < Norm2VarDep >,
+                    public Norm2
+{
+
+  RINGER_IO_VARDEP_OBJ(Norm2VarDep, Norm2)
+
+  public:
+
+    Norm2VarDep(){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(Norm2VarDep,1)
+};
+
+/**
+ * @brief Use SqrtVarDep of norm-1 as rings normalization factor
+ **/
+class SqrtVarDep : virtual public IPreProcessorVarDep,
+                   public RingerIOVarDepObj < SqrtVarDep >,
+                   public Sqrt
+{
+
+  RINGER_IO_VARDEP_OBJ(SqrtVarDep, Sqrt)
+
+  public:
+
+    SqrtVarDep(){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(SqrtVarDep,1)
+};
+
+/**
+ * @brief Use constant value as rings normalization factor
+ **/
+class ConstantValueVarDep : virtual public IPreProcessorVarDep,
+                            public RingerIOVarDepObj < ConstantValueVarDep >,
+                            public ConstantValue
+{
+
+  RINGER_IO_VARDEP_OBJ(ConstantValueVarDep, ConstantValue)
+
+  public:
+
+    ConstantValueVarDep(){;}
+
+    ConstantValueVarDep(const float constantValue)
+      : ConstantValue(constantValue){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(ConstantValueVarDep,1)
+};
+
+/**
+ * @brief Scale rings energy to GeV
+ **/
+class MevToGevVarDep: virtual public IPreProcessorVarDep,
+                      public RingerIOVarDepObj < MevToGevVarDep >,
+                      public ConstantValue
+{
+
+  RINGER_IO_VARDEP_OBJ(MevToGevVarDep, ConstantValue)
+
+  public:
+
+    // Normalization is the inverse of the Units transformation (MeV -> GeV)
+#if !defined(XAOD_STANDALONE) && !defined(RINGER_STANDALONE)
+    MevToGevVarDep()
+      : ConstantValue( (Gaudi::Units::GeV) / (Gaudi::Units::MeV) ){;}
+#else // We suppose that we are working with MeV as reference unit.
+    MevToGevVarDep()
+      : ConstantValue( 1000 / 1 ){;}
+#endif
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(MevToGevVarDep,1)
+};
+
+/**
+ * @brief Use sequential normalization.
+ *
+ * For more information check: 
+ *
+ * https://svnweb.cern.ch/trac/atlasoff/browser/Trigger/TrigHypothesis/TrigMultiVarHypo/trunk/TrigMultiVarHypo/TrigRingerNeuralFex.h#L140
+ **/
+class SequentialVarDep : virtual public IPreProcessorVarDep,
+                         public RingerIOVarDepObj < SequentialVarDep >,
+                         public Sequential
+{
+
+  RINGER_IO_VARDEP_OBJ(SequentialVarDep, Sequential)
+
+  public:
+
+    SequentialVarDep(){;}
+
+    SequentialVarDep(
+        const float stopEnergy,
+        const float energyThres):
+      Sequential(stopEnergy,energyThres){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(SequentialVarDep,1)
+};
+
+/**
+ * @brief Normalize data to have zero mean and unitary standard deviation.
+ **/
+class SpherizationVarDep : virtual public IPreProcessorVarDep,
+                           public RingerIOVarDepObj < SpherizationVarDep >,
+                           public Spherization
+{
+
+  RINGER_IO_VARDEP_OBJ(SpherizationVarDep, Spherization)
+
+  public:
+
+    SpherizationVarDep(){;}
+
+    SpherizationVarDep(
+        const std::vector<float> &dataMean,
+        const std::vector<float> &dataStd):
+      Spherization(dataMean,dataStd){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(SpherizationVarDep,1)
+};
+
+/**
+ * @brief Normalize data to be bounded within [-1,1] range.
+ **/
+class MinMaxVarDep : virtual public IPreProcessorVarDep,
+                     public RingerIOVarDepObj < MinMaxVarDep >,
+                     public MinMax
+{
+  RINGER_IO_VARDEP_OBJ(MinMaxVarDep, MinMax)
+
+  public:
+
+    MinMaxVarDep(){;}
+
+    MinMaxVarDep(
+        const std::vector<float> &min,
+        const std::vector<float> &max):
+      MinMax(min,max){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(MinMaxVarDep,1)
+};
+/// @}
+
+} // Norm namespace;
+} // Pre-processing namespace;
+} // Ringer namespace
+
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_NORMALIZATIONS_H
+
+// Include inline and template declarations:
+#ifndef INCLUDE_HEADER_ONLY // Protect against circular includes
+#include "Normalizations.icc"
+#endif // INCLUDE_HEADER_ONLY
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.icc
new file mode 100644
index 0000000000000000000000000000000000000000..8e0db0f305c9b496f7364dcd2b8807aac3cba1fe
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Normalizations.icc
@@ -0,0 +1,245 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Normalizations.icc 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_NORMALIZATIONS_ICC
+#define RINGERSELECTORTOOLS_NORMALIZATIONS_ICC
+
+#include "Normalizations.h"
+#include <cmath>
+#include <limits>
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer
+{
+
+/** 
+* @brief Namespace dedicated for Ringer pre-processing utilities 
+**/
+namespace PreProcessing
+{
+
+/** 
+ * @brief Namespace dedicated for Ringer normalization utilities 
+ **/
+namespace Norm {
+
+/** 
+ * @brief Helper functions:
+ **/
+namespace {
+
+// =============================================================================
+inline
+float getMax( std::vector<float> &inputSpace ) {
+  float max = std::numeric_limits<float>::min();
+  for ( std::vector<float>::const_iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    if (std::abs(*itr) > max) {
+      max = *itr;
+    }
+  }
+  return std::abs(max);
+}
+
+// =============================================================================
+inline
+float getNorm( std::vector<float> &inputSpace ){
+  float norm = 0;
+  for ( std::vector<float>::const_iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    norm += *itr;
+  }
+  return std::abs(norm);
+}
+
+// =============================================================================
+inline
+float getNorm( std::vector<float> &inputSpace, const unsigned int p ){
+  if ( p == 1) return getNorm(inputSpace);
+  float norm = 0;
+  for ( std::vector<float>::const_iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    norm += std::pow(*itr,p);
+  }
+  return std::abs(std::pow(norm,1/p));
+}
+
+// =============================================================================
+inline
+void applyNorm( std::vector<float> &inputSpace, const float norm ){
+  if (!norm) return;
+  float invNorm = 1/norm;
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    *itr *= invNorm;
+  }
+}
+
+// =============================================================================
+inline
+void applyInvNorm( std::vector<float> &inputSpace, const float invNorm ){
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    *itr *= invNorm;
+  }
+}
+
+// =============================================================================
+inline
+void applyInvNorm( std::vector<float> &inputSpace, 
+    const std::vector<float> &invNorm )
+{
+  std::vector<float>::const_iterator itr2 = invNorm.begin();
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr, ++itr2)
+  {
+    *itr *= *itr2;
+  }
+}
+
+// =============================================================================
+inline
+void applyDeslocation( std::vector<float> &inputSpace, const float deslocation )
+{
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr)
+  {
+    *itr += deslocation;
+  }
+}
+
+// =============================================================================
+inline
+void applyDeslocation( std::vector<float> &inputSpace, 
+    const std::vector<float> deslocation )
+{
+  std::vector<float>::const_iterator itr2 = deslocation.begin();
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr, ++itr2)
+  {
+    *itr += *itr2;
+  }
+}
+
+} // Private namespace
+
+/// Normalization interfaces:
+/// @{
+// =============================================================================
+inline
+void Norm1::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying Norm1. Input space is: " << inputSpace);
+#endif
+  float norm1 = getNorm(inputSpace,1);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Normalization factor is " << norm1 );
+#endif
+  applyNorm(inputSpace,norm1);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+inline
+void Norm2::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying Norm2. Input space is: " << inputSpace);
+#endif
+  float norm2 = getNorm(inputSpace,2);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Normalization factor is " << norm2 );
+#endif
+  applyNorm(inputSpace,norm2);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+inline
+void Sqrt::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying Sqrt. Input space is: " << inputSpace);
+#endif
+  float sqrtNorm = std::sqrt(std::fabs(getNorm(inputSpace,1)));
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Normalization factor is " << sqrtNorm );
+#endif
+  applyNorm(inputSpace,sqrtNorm);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+inline
+void ConstantValue::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying ConstantValue(Value: " << 1/m_constantInv
+      << "). Input space is: " << inputSpace);
+#endif
+  applyInvNorm(inputSpace,m_constantInv);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+inline
+void Spherization::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying Spherization. Input space is: " << inputSpace);
+#endif
+  if ( inputSpace.size() != m_dim ){
+    throw std::runtime_error(std::string( "Input size (") +
+        std::to_string(inputSpace.size()) + ") does not match "
+        " this pre-processing inputSpace dimension size(" +
+        std::to_string(m_dim) + ".");
+  }
+  applyDeslocation(inputSpace,m_deslocation);
+  applyInvNorm(inputSpace,m_normInv);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+inline
+void MinMax::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying MinMax. Input space is: " << inputSpace);
+#endif
+  if ( inputSpace.size() != m_dim ){
+    throw std::runtime_error(std::string( "Input size (") +
+        std::to_string(inputSpace.size()) + ") does not match "
+        " this pre-processing inputSpace dimension size(" +
+        std::to_string(m_dim) + ".");
+  }
+  applyDeslocation(inputSpace,m_deslocation);
+  applyInvNorm(inputSpace,m_normInv);
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+/// @}
+
+} // namespace Norm
+} // namespace Discrimination
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_NORMALIZATIONS_ICC
+// vim: filetype=cpp :
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..04b2efa3622daf63cad4f7587354b4c96076c319
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.h
@@ -0,0 +1,402 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerDiscriminatorWrapper.h 713528 2015-12-09 08:58:44Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_H
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_H
+
+#define RINGER_PROCEDURE_INCLUDE
+#include "RingerProcedureWrapper.h"
+#undef RINGER_PROCEDURE_INCLUDE
+
+//#undef NDEBUG
+
+#define RINGER_DISCRIMINATOR_WRAPPER_INCLUDE
+// We are also dependent on the PreProcessorWrapper, but we want only to define
+// the collection for now:
+#include "RingerPreProcessorWrapper.h"
+#undef RINGER_DISCRIMINATOR_WRAPPER_INCLUDE
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/**
+ * @class IRingerProcedureWrapper
+ * @brief Specialization for Discriminator procedure.
+ **/
+template<>
+class IRingerProcedureWrapper< Discrimination::IDiscriminator > :
+  virtual public IRedirectMsgStream,
+  virtual public IRingerProcedureWrapperBase
+{
+  public:
+    /**
+     * @brief Collection type of Discriminators Wrappers.
+     **/
+    typedef typename std::vector< IRingerProcedureWrapper* > WrapperCollection;
+
+    /// Main methods:
+    ///@{
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Apply discriminator to obtain its output representation
+     *
+     * This method will pass the information within xAOD::CaloRings and
+     * xAOD::TrackParticle to the pre-processors (if any) and
+     * afterwards feed the classifier. If any pointer if set to null, then it
+     * won't pass it into the classifier.  Make sure to feed classifier with
+     * the same information it was adjusted to work with.
+     **/
+    virtual void execute(
+        const DepVarStruct &depVar,
+        const xAOD::CaloRings *clrings,
+        const TrackPatternsHolder *trackPat,
+        std::vector<float> &output) const = 0;
+
+    /**
+     * @brief Set the holden CaloRings raw configuration collection.
+     **/
+    virtual void setRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *crRawConfCol) = 0;
+
+    /**
+     * @brief Get the holden CaloRings raw configuration collection.
+     **/
+    virtual void getRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *&crRawConfCol) const = 0;
+
+    /**
+     * @brief Get segmentation type for this pre-processing
+     **/
+    virtual SegmentationType getSegType() const = 0;
+
+#endif
+
+    /**
+     * @brief Apply discriminator to obtain its output representation
+     *
+     * This method will pass @name input information to the
+     * pre-processors (if any) and afterwards feed the classifier. 
+     *
+     * This overload is only available if SegmentationType is set to 
+     * NoSegmentation (there is no section/layer segmentation
+     * information available on this method).
+     **/
+    virtual void execute(
+        const DepVarStruct &depVar,
+        const std::vector<float> &input,
+        std::vector<float> &output) const = 0;
+    ///@}
+ 
+    /**
+     * @brief Returns this wrapper name
+     **/
+    virtual const char* name() const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE {
+      return wrapName;
+    }
+
+#if RINGER_USE_NEW_CPP_FEATURES
+    static constexpr const char* wrapName = "RingerDiscriminatorWrapper"; 
+#else
+    static const char* wrapName; 
+#endif
+
+    /**
+     * @brief Returns whether it has Pre-Processing Collection Wrapper.
+     **/
+    virtual bool hasPP() const = 0;
+
+    /**
+     * @brief Write all wrappers on discrWrapperCol to TDirectory
+     **/
+    static void writeCol(const WrapperCollection &discrWrapperCol, 
+        const char *fileName);
+
+    /**
+     * @brief Read all discriminator on file at the path and append them to
+     * IPreProcWrapperCollection
+     **/
+    static void read(WrapperCollection &discrWrapperCol, 
+        const char* fileName);
+
+  protected:
+
+    IRingerProcedureWrapper(){;}
+
+};
+
+/**
+ * @brief Facilitate access into Discrimination Wrappers.
+ **/
+typedef IRingerProcedureWrapper< Discrimination::IDiscriminator >
+  IDiscrWrapper;
+
+/**
+ * @brief Facilitate access into Discrimination Wrappers.
+ **/
+typedef IDiscrWrapper::WrapperCollection IDiscrWrapperCollection;
+
+/**
+ * @class RingerProcedureWrapper
+ * @brief Specialization for Discriminator procedure.
+ **/
+template < class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType>
+class RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false> :   // isThreshold
+    public IDiscrWrapper,
+    public RedirectMsgStream
+{
+    RINGER_STATIC_ASSERT(
+        (Ringer::is_base_of<VariableDependency,procedure_t>::value),
+        "RingerProcedureWrapper procedure_t type must have IVariableDependecy inheritance.");
+  public:
+    /// RingerProcedureWrapper for Discrimination procedures typedefs:
+    ///@{
+    /**
+     * @brief typedef to base wrapper
+     **/
+    //typedef typename RingerProcedureWrapper::template
+    //    IRingerProcedureWrapper< Discrimination::IDiscriminator > 
+    //    wrapper_t;
+
+    /**
+     * @brief typedef to the Ringer Interface variable dependency collection
+     *
+     * Collection Dimension: [segType][etBin][etaBin]:
+     *  
+     **/
+    typedef typename std::vector< 
+        std::vector < 
+        std::vector < procedure_t* > >
+      > DiscrDepProcCollection;
+    ///@}
+
+    /// Ctors:
+    ///@{
+    /**
+     * @brief Build RProc Wrapper with no pre-processor
+     **/
+    RingerProcedureWrapper(
+        const DiscrDepProcCollection &discrDepCol):
+      m_ppWrapperCol(IPreProcWrapperCollection(0)),
+      m_discrCol(discrDepCol),
+      m_discr(nullptr),
+      m_rsRawConfCol(nullptr),
+      m_nRings(0)
+    { 
+      checkDiscrCol(); 
+    }
+
+    /**
+     * @brief Build RProc Wrapper with all functionallities
+     **/
+    RingerProcedureWrapper(
+        const IPreProcWrapperCollection &ppCol, 
+        const DiscrDepProcCollection &discrDepCol):
+      m_ppWrapperCol(ppCol),
+      m_discrCol(discrDepCol),
+      m_discr(nullptr),
+      m_rsRawConfCol(nullptr),
+      m_nRings(0)
+    { 
+      checkPPWrapperCol(); 
+      checkDiscrCol(); 
+    }
+    ///@}
+
+    /// Main methods:
+    ///@{
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Apply discriminator to obtain its output representation
+     *
+     * This method will pass the information within xAOD::CaloRings and
+     * xAOD::TrackParticle to the pre-processors (if any) and
+     * afterwards feed the classifier. If any pointer if set to null, then it
+     * won't pass it into the classifier.  Make sure to feed classifier with
+     * the same information it was adjusted to work with.
+     **/
+    virtual void execute(
+        const DepVarStruct &depVar,
+        const xAOD::CaloRings *clrings,
+        const TrackPatternsHolder *trackPat,
+        std::vector<float> &output) const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+#endif
+
+    /**
+     * @brief Apply discriminator to obtain its output representation
+     *
+     * This method will pass @name input information to the
+     * pre-processors (if any) and afterwards feed the classifier. 
+     *
+     * This overload is only available if SegmentationType is set to 
+     * NoSegmentation (there is no section/layer segmentation
+     * information available on this method).
+     **/
+    virtual void execute(
+        const DepVarStruct &depVar,
+        const std::vector<float> &input,
+        std::vector<float> &output) const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+    ///@}
+
+    /// Other utilities:
+    ///@{
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Set the holden CaloRings raw configuration collection.
+     **/
+    virtual void setRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *crRawConfCol) 
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE 
+    {
+      for ( auto &ppWrapper : m_ppWrapperCol ) {
+        ppWrapper->setRawConfCol( crRawConfCol );
+      }
+      m_rsRawConfCol = crRawConfCol;
+      m_nRings = xAOD::RingSetConf::totalNumberOfRings( *crRawConfCol );
+    }
+
+    /**
+     * @brief Get the holden CaloRings raw configuration collection.
+     **/
+    virtual void getRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *&crRawConfCol) const
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE
+    {
+      crRawConfCol = m_rsRawConfCol;
+    }
+#endif
+
+    /**
+     * @brief Get segmentation type for this pre-processor
+     **/
+    virtual SegmentationType getSegType() const 
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE
+    {
+      return static_cast<SegmentationType>(segType);
+    }
+
+
+    /**
+     * @brief Returns whether holden interface collection is empty.
+     **/
+    virtual bool empty() const ATH_RINGER_OVERRIDE { return m_discrCol.empty();}
+
+    /**
+     * @brief Returns whether it has pre-processing Collection Wrapper.
+     **/
+    virtual bool hasPP() const ATH_RINGER_OVERRIDE { return !m_ppWrapperCol.empty();}
+
+    /**
+     * @brief Overloads the setMsgStream from RedirectMsgStream.
+     **/
+    virtual void setMsgStream(MsgStream *msg) const ATH_RINGER_OVERRIDE;
+
+    /**
+     * @brief Write collection to TDirectory
+     **/
+    void write(TDirectory *baseDir, const char *idxStr = "") const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Returns eta dependecy for this wrapper
+     **/
+    EtaDependency etaDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtaDependency>(etaDependency);
+    }
+
+    /**
+     * @brief Returns et dependecy for this wrapper
+     **/
+    EtDependency etDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtDependency>(etDependency);
+    }
+
+    /**
+     * @brief Release all holden pointer memory
+     **/
+    void releaseMemory() ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Get full wrapper name, static method
+     **/
+    static std::string staticFullName();
+
+    /**
+     * @brief Print wrapper content
+     **/
+    void print(MSG::Level lvl = MSG::DEBUG) const ATH_RINGER_OVERRIDE 
+      ATH_RINGER_FINAL;
+
+    /**
+     * @brief Get full wrapper name
+     **/
+    std::string fullName() const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Read collection from TDirectory
+     **/
+    static RingerProcedureWrapper* read(TDirectory *configDir, 
+        unsigned version);
+    ///@}
+
+  private:
+    /// Private methods
+    ///@{
+    /**
+     * @brief Check if input PP Wrapper collection is in good status
+     * (Throws otherwise)
+     **/
+    void checkPPWrapperCol();
+    /**
+     * @brief Check if discriminators interface collection is in good status 
+     * (Throws otherwise)
+     **/
+    void checkDiscrCol(); 
+    ///@}
+
+    /// Properties
+    ///@{
+    /// @brief Discriminator preprocessing collection routines
+    const IPreProcWrapperCollection m_ppWrapperCol;
+    /// @brief holden discriminator collection:
+    DiscrDepProcCollection m_discrCol;
+    /// @brief hold pointer to first collection position:
+    procedure_t *m_discr;
+
+
+#ifndef RINGER_STANDALONE
+    /// @brief contains a pointer into the CaloRings configuration
+    const xAOD::RingSetConf::RawConfCollection *m_rsRawConfCol;
+    /// @short contains the total number of rings in the vectorized
+    ///        representation
+    unsigned m_nRings;
+#endif
+    ///@}
+
+};
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "RingerDiscriminatorWrapper.icc"
+#endif // INCLUDE_HEADER_ONLY
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.icc
new file mode 100644
index 0000000000000000000000000000000000000000..82f6f8c9ae9ae4c5a2cf47ce650f17a3a7587831
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerDiscriminatorWrapper.icc
@@ -0,0 +1,825 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerDiscriminatorWrapper.icc 713528 2015-12-09 08:58:44Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
+
+#include "RingerDiscriminatorWrapper.h"
+#include "RingerProcedureWrapper.icc"
+
+#include "RingerSelectorTools/procedures/Normalizations.h"
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+
+namespace Ringer {
+
+namespace WrapperHelperFcns {
+
+/**
+ * Return the discriminator on dirObj of ppType
+ **/
+inline
+Discrimination::IDiscriminatorVarDep* getDiscr(discrEnum_t discrType, 
+    TDirectory *dirObj )
+{
+  using namespace Discrimination;
+  // For the interface case, we will have to create each pre-processing 
+  // depending on the information written on ppType:
+  switch ( discrType )
+  {
+    case discrEnum_t::NNFeedForward:
+    {
+      return NNFeedForwardVarDep::read( dirObj );
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error( std::string("Cannot read discriminator of ") +
+          "type: " + toStr(discrType) );
+    }
+  }
+}
+} // WrapperHelperFcns
+
+// Import Wrapper Helper functions
+using namespace WrapperHelperFcns;
+
+// =============================================================================
+//            -----------------------------------------
+//            RingerProcedureWrapper for Discriminators
+//            -----------------------------------------
+// =============================================================================
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::releaseMemory()
+{
+  for ( size_t ppColIdx = 0; ppColIdx < m_ppWrapperCol.size(); ++ppColIdx){
+    if (m_ppWrapperCol[ppColIdx]){
+      m_ppWrapperCol[ppColIdx]->releaseMemory();
+    }
+  }
+  for ( size_t segIdx = 0; segIdx < m_discrCol.size() ; ++segIdx){
+    for ( size_t etIdx = 0; etIdx < m_discrCol[segIdx].size() ; ++etIdx){
+      for ( size_t etaIdx = 0; etaIdx < m_discrCol[segIdx][etIdx].size(); 
+          ++etaIdx)
+      {
+        delete m_discrCol[segIdx][etIdx][etaIdx];
+      }
+    }
+  }
+  m_discrCol.clear();
+  m_discr = nullptr;
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::execute(
+    const DepVarStruct &depVar,
+    const xAOD::CaloRings *clrings,
+    const TrackPatternsHolder *trackPat,
+    std::vector<float> &output) const
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying first discrimination layer discriminators.");
+#endif
+
+  // Clear any previous output:
+  output.clear();
+
+  // We will put pre-processing results into this vector:
+  std::vector<float> transformVec;
+
+#ifndef NDEBUG
+    ATH_MSG_DEBUG( "Allocating space on transformVec of size " << 
+      (((clrings)?(m_nRings):0) + 
+      ((trackPat)?TrackPatternsHolder::numberOfPatterns():0)));
+#endif
+
+  // We grant it enougth space to handle worst case:
+  transformVec.reserve( 
+      (clrings)?(m_nRings):(0 + 
+      ((trackPat)?TrackPatternsHolder::numberOfPatterns():0)) 
+    );
+
+  std::vector<float> input = transformVec;
+
+  if ( m_ppWrapperCol.empty() ) {
+    // Otherwise simply push-back information:
+    if (clrings){
+      clrings->exportRingsTo(transformVec);
+    }
+    if (trackPat){
+      trackPat->exportPatternsTo(transformVec);
+    }
+  } else {
+    // FIXME: This does not work with multiple normalizations, we need to
+    // change this to something where the pre-processor will keep the
+    // segmentation information that it will receive and where should it divide
+    // it.
+
+    // If pre-processing available execute it:
+    for ( size_t ppIdx = 0; ppIdx < m_ppWrapperCol.size(); ++ppIdx ){
+      m_ppWrapperCol[ppIdx]->applyPreProcessing(
+          depVar, 
+          clrings, 
+          trackPat, 
+          transformVec);
+    }
+  }
+
+  // Initialize eta and et indexes:
+  size_t etaIdx(0), etIdx(0);
+  // Get the correct idx to be applied:
+  if (etaDependency) {
+    etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
+  }
+  if (etDependency) {
+    etIdx = findEtBin(depVar.et, m_discrCol[0]);
+  }
+
+  size_t cDiscr = 0;
+
+  switch(segType){
+    case SegmentationType::NoSegmentation:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying NonSegmented" 
+          " discriminator at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      input = transformVec;
+      // Apply discrimination to all transformed space:
+      m_discrCol[cDiscr++][etaIdx][etIdx]->execute(input,output);
+      break;
+    }
+    case SegmentationType::TrackCalSegmentation:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal segmented" 
+          " discriminators at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply discrimination to CaloRings as one:
+        getCaloSegmentFromTransformVec( m_nRings,
+            transformVec,
+            input);
+
+        executeSegmentedDiscr(
+            input, 
+            m_discrCol[cDiscr++][etaIdx][etIdx], 
+            output);
+      } else {
+        cDiscr += 1;
+      }
+      if (trackPat){
+        // Apply discrimination to Track separated:
+        getTrackSegmentFromTransformVec(
+            // If the CaloRings is available, then we have to increase the
+            // start index to jump all Calorimeter representations:
+            (clrings)?(m_nRings):0,
+            transformVec,
+            input);
+
+        executeSegmentedDiscr(
+            input, 
+            m_discrCol[cDiscr++][etaIdx][etIdx], 
+            output);
+      } else {
+        cDiscr += 1;
+      }
+      break;
+    }
+    case SegmentationType::TrackCalPatTypeSegmentation:
+    {
+      // TODO Implement this if it is going to be used:
+      throw std::runtime_error(std::string("There is no implementation method "
+            "for ") + toStr(static_cast<SegmentationType>(segType)) );
+    }
+    case SegmentationType::TrackCalJointSections:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal-JointSections segmented" 
+          " discriminators at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply discrimination to each CalJointSection:
+        while ( cDiscr < static_cast<size_t>(
+              CalJointSection::NJointSections) )
+        {
+          getCaloSegmentFromTransformVec( 
+              *m_rsRawConfCol,
+              static_cast<CalJointSection>(cDiscr),
+              transformVec,
+              input);
+
+          executeSegmentedDiscr(
+              input, 
+              m_discrCol[cDiscr++][etaIdx][etIdx], 
+              output);
+        }
+      } else {
+        cDiscr += static_cast<size_t>(CalJointSection::NJointSections);
+      }
+      if (trackPat) {
+        // Apply discrimination to Track separated:
+        getTrackSegmentFromTransformVec(
+            (clrings)?(m_nRings):0,
+            transformVec,
+            input);
+
+        executeSegmentedDiscr(
+            input, 
+            m_discrCol[cDiscr++][etaIdx][etIdx], 
+            output);
+      } else {
+        cDiscr += 1;
+      }
+      break;
+    }
+    case SegmentationType::TrackCalJointLayers:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal-JointLayers segmented" 
+          " discriminators at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply discrimination to each CalJointLayer:
+        while ( cDiscr < static_cast<size_t>(
+              CalJointLayer::NJointLayers) )
+        {
+          getCaloSegmentFromTransformVec(
+              *m_rsRawConfCol,
+              static_cast<CalJointLayer>(cDiscr),
+              transformVec,
+              input);
+
+          executeSegmentedDiscr(
+              input, 
+              m_discrCol[cDiscr++][etaIdx][etIdx], 
+              output);
+        }
+      } else {
+        cDiscr += static_cast<size_t>(CalJointLayer::NJointLayers);
+      }
+      if (trackPat){
+        // Apply discrimination to Track separated:
+        getTrackSegmentFromTransformVec(
+            (clrings)?(m_nRings):0,
+            transformVec,
+            input);
+
+        executeSegmentedDiscr(
+            input, 
+            m_discrCol[cDiscr++][etaIdx][etIdx], 
+            output);
+      } else {
+        cDiscr += 1;
+      }
+      break;
+    }
+  }
+  return;
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::execute(
+    const DepVarStruct &depVar,
+    const std::vector<float> &input,
+    std::vector<float> &output) const
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying internal discrimination layer discriminators.");
+#endif
+
+  // This method only applies for segType NoSegmentation.
+  ensureNoSegmentationOnlyFcn(static_cast<SegmentationType>(segType));
+
+  // Copy input:
+  std::vector<float> inputCopy = input;
+  // First, execute pp wrapper collection:
+  for ( size_t ppIdx = 0; ppIdx < m_ppWrapperCol.size(); ++ppIdx ){
+    m_ppWrapperCol[ppIdx]->applyPreProcessing(depVar,inputCopy);
+  }
+
+  if (!etaDependency && !etDependency){
+    m_discr->execute(inputCopy,output);
+    return;
+  }
+
+  // Initialize eta and et indexes:
+  size_t etaIdx(0), etIdx(0);
+
+  // Get the correct idx to be applied:
+  if (etaDependency){
+    etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
+  }
+  if (etDependency){
+    etIdx = findEtBin(depVar.et, m_discrCol[0]);
+  }
+
+  // Apply it:
+  m_discrCol[0][etaIdx][etIdx]->execute(inputCopy,output);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::checkPPWrapperCol(){
+  if (m_ppWrapperCol.empty()){
+    throw std::runtime_error(std::string(
+          "Attempted to start Discriminator Wrapper with" 
+           " PreProcessing Wrapper collection that is empty.\n"
+           "In this case, do not input PreProcessing" 
+           " Wrapper collection in Discriminator"
+           " Wrapper construction."));
+
+  }
+  for ( size_t ppWrapperIdx = 0; ppWrapperIdx < m_ppWrapperCol.size(); 
+      ++ppWrapperIdx ){
+    if( !m_ppWrapperCol[ppWrapperIdx] || 
+        m_ppWrapperCol[ppWrapperIdx]->empty() ){
+      throw std::runtime_error(std::string(
+            "Attempted to start Discriminator Wrapper with"
+            " PreProcessing Wrapper collection with"
+            " empty PreProcessing Wrapper."));
+    }
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::checkDiscrCol(){
+  try {
+    checkCollection(m_discrCol, 
+        static_cast<EtaDependency>(etaDependency), 
+        static_cast<EtDependency>(etDependency));
+    if (segType && m_discrCol.size() < 2 ){
+      throw std::runtime_error(std::string("Cannot allocate dependency vector "
+            "with size lesser than one when using segmentation dependency."));
+    }
+  } catch ( const std::runtime_error &e ) {
+    throw std::runtime_error(std::string("Couldn't initialize RingerDiscriminationWrapper collection due to: ")
+        + e.what() );
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::setMsgStream(MsgStream *msg) const {
+  // The pre-processors wrapper collection:
+  for ( size_t ppWrapperIdx = 0; ppWrapperIdx < m_ppWrapperCol.size(); ++ppWrapperIdx ){
+    if ( m_ppWrapperCol[ppWrapperIdx] ) {
+      m_ppWrapperCol[ppWrapperIdx]->setMsgStream(msg);
+    }
+  }
+  // The discrimination collection:
+  setCollectionMsgStream(msg,m_discrCol);
+  // Set the wrapper message stream:
+  this->RedirectMsgStream::setMsgStream(msg);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,      // isPreProcessor
+  true,       // isDiscriminator
+  false>      // isThreshold
+::staticFullName() {
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+  std::stringstream ss;
+  ss << "RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((Ringer::is_same<procedure_t,
+                             Discrimination::IDiscriminatorVarDep>::value)?",":
+            "(VarDep),")
+        << toStr(static_cast<EtaDependency>(etaDependency)) << "," 
+        << toStr(static_cast<EtDependency>(etDependency)) << "," 
+        << toStr(static_cast<SegmentationType>(segType)) << ">";
+  return ss.str();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,      // isPreProcessor
+  true,       // isDiscriminator
+  false>      // isThreshold
+::fullName() const {
+  return staticFullName();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,      // isPreProcessor
+  true,       // isDiscriminator
+  false>      // isThreshold
+::print(MSG::Level lvl) const
+{
+  if ( this->isStreamAvailable() ) { 
+    if ( this->level() > lvl ){
+      // Don't waste time to print nothing.
+      return;
+    }
+    this->msg() << lvl << " -------- Printing PreProcesorWrappers -------- " 
+      << endreq;
+    // Print pre-processing collection:
+    for ( size_t ppWrapIdx = 0; ppWrapIdx < m_ppWrapperCol.size(); ++ppWrapIdx )
+    {
+      this->msg() << lvl << "PreProcessingWrapper" 
+        << IOHelperFcns::makeIdxStr(ppWrapIdx) << endreq;
+      m_ppWrapperCol[ppWrapIdx]->print( lvl );
+    }
+    this->msg() << lvl << " --- Finished printing PreProcessorWrappers --- " 
+      << endreq;
+    // Print discriminators
+    std::vector<unsigned> posVec(3);
+    for ( size_t segIdx = 0; segIdx < m_discrCol.size() ; ++segIdx){
+      posVec[0] = segIdx;
+      for ( size_t etIdx = 0; etIdx < m_discrCol[segIdx].size() ; ++etIdx){
+        posVec[1] = etIdx;
+        for ( size_t etaIdx = 0; etaIdx < m_discrCol[segIdx][etIdx].size(); 
+            ++etaIdx)
+        {
+          posVec[2] = etaIdx;
+          this->msg() << lvl << m_discrCol[segIdx][etIdx][etaIdx]->name() <<
+            IOHelperFcns::makeIdxStr(posVec) << " configuration:" << endreq;
+          m_discrCol[segIdx][etIdx][etaIdx]->print(lvl);
+        }
+      }
+    }
+  } else {
+    std::cerr << "Stream is not available, cannot print " << fullName() << "." 
+      << std::endl;
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::write(TDirectory *baseDir, const char *idxStr) const
+{
+
+  // ----------- Template basics ----------
+  // Create configuration directory
+  TDirectory *configDir = IOHelperFcns::makeDir(baseDir, 
+      (std::string(name()) + idxStr).c_str() );
+
+  // Write basic template information:
+  discrEnum_t discrType = procedure_t::template procType<discrEnum_t>();
+  SegmentationType fileSegType = static_cast<SegmentationType>(segType);
+  EtaDependency fileEtaDep = static_cast<EtaDependency>(etaDependency);
+  EtDependency fileEtDep = static_cast<EtDependency>(etDependency);
+  // FIXME Why do I need to use const? Unfortunately if I don't use so, the
+  // compiler won't accept static_casting from discr_Enum_t to unsigned int:
+  // some issue with reference casting.
+  IOHelperFcns::writeVar<const discrEnum_t, const unsigned int>( configDir,
+      "discrType",
+      discrType);
+  IOHelperFcns::writeVar<const SegmentationType, const unsigned int>( configDir, 
+      "segType",
+      fileSegType);
+  IOHelperFcns::writeVar<const EtaDependency, const unsigned int>( configDir,
+      "etaDependency",
+      fileEtaDep);
+  IOHelperFcns::writeVar<const EtDependency, const unsigned int>( configDir,
+      "etDependency",
+      fileEtDep);
+
+  // ----------- Pre-processing chain ----------
+  // Write flag whether there is pre-processing chain for this discriminator:
+  IPreProcWrapper::writeCol(m_ppWrapperCol, configDir);
+
+  // ------------ Discriminators: ---------------
+  // Write size information:
+  unsigned discrSegDepSize = m_discrCol.size();
+  unsigned discrEtDepSize = m_discrCol[0].size();
+  unsigned discrEtaDepSize = m_discrCol[0][0].size();
+  IOHelperFcns::writeVar( configDir,  "discrSegDepSize" , discrSegDepSize );
+  IOHelperFcns::writeVar( configDir,  "discrEtDepSize"  , discrEtDepSize  );
+  IOHelperFcns::writeVar( configDir,  "discrEtaDepSize" , discrEtaDepSize );
+  // Write Discriminator collection
+  std::vector<unsigned int> discrCount(3);
+  for (size_t segIdx = 0; 
+      segIdx < m_discrCol.size(); 
+      ++segIdx)
+  {
+    discrCount[0] = segIdx;
+    for (size_t etIdx = 0; 
+        etIdx < m_discrCol[segIdx].size(); 
+        ++etIdx)
+    {
+      discrCount[1] = etIdx;
+      for (size_t etaIdx = 0; 
+          etaIdx < m_discrCol[segIdx][etIdx].size(); 
+          ++etaIdx)
+      {
+        discrCount[2] = etaIdx;
+        m_discrCol[segIdx][etIdx][etaIdx]->write(
+            configDir,
+            IOHelperFcns::makeIdxStr(discrCount).c_str());
+      }
+    }
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+RingerProcedureWrapper<procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,
+  true,
+  false> *
+RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  false,     // isPreProcessor
+  true,      // isDiscriminator
+  false>     // isThreshold
+::read(TDirectory *configDir, unsigned version)
+{
+
+  using namespace Discrimination;
+
+  IOHelperFcns::checkDir(configDir);
+
+  // ----------- Pre-processing chain ----------
+  // Create empty preprocessing wrapper collection:
+  IPreProcWrapperCollection ppWrapperCol;
+
+  //ATH_MSG_DEBUG("Reading Discrimination Wrapper of type \"" 
+  //    << ppType.Data() 
+  //    << "\" named \"" << configDir->GetName()
+  //    << "\" and dependency : ["
+  //    << toStr(segType) << ","
+  //    << toStr(etaDependency) << "," 
+  //    << toStr(etDependency) << "]");
+
+  // Check if this discriminator has pre-processing:
+  bool hasPP(false);
+  IOHelperFcns::readVar( configDir, "hasPP", hasPP );
+
+  // Fill preprocessing wrapper collection
+  if (hasPP) {
+    IPreProcWrapper::read( ppWrapperCol, configDir, version ); 
+  } else {
+    //ATH_MSG_VERBOSE("This Discrimination Wrapper hasn't pre-processors.");
+  }
+
+  // ----------- Discriminators: ----------
+  // Read discrimination collection size:
+  unsigned discrSegDepSize(0),
+           discrEtDepSize(0),
+           discrEtaDepSize(0);
+  IOHelperFcns::readVar( configDir,  "discrSegDepSize", discrSegDepSize );
+  IOHelperFcns::readVar( configDir,  "discrEtDepSize" , discrEtDepSize  );
+  IOHelperFcns::readVar( configDir,  "discrEtaDepSize", discrEtaDepSize );
+
+  // Allocate discriminator collection with size specified on file
+  DiscrDepProcCollection discrCol( discrSegDepSize,
+      std::vector< std::vector< procedure_t*> >(
+        discrEtDepSize, std::vector< procedure_t*>(
+          discrEtaDepSize, nullptr )));
+
+  // Allocate index position retriever:
+  std::vector<unsigned int> discrIdxVec(3);
+
+  // Retrieve dir list and loop on it:
+  std::shared_ptr<THashList> list(nullptr);
+  if ( !( list = IOHelperFcns::getDirList(configDir) ) ) {
+    std::runtime_error(std::string("Couldn't retrieve directory "
+          "list from wrapper folder"));
+  }
+
+  TIter iter( list.get() );
+  while ( TDirectory* dirObj = static_cast<TDirectory*>(iter()) ) {
+
+    const char* folderName = dirObj->GetName();
+
+    //ATH_MSG_VERBOSE("Scanning directory " << folderName );
+
+    // Filter pre-processing wrapper dirs:
+    if ( IOHelperFcns::startsWith( IRingerProcedureWrapper<
+        PreProcessing::IPreProcessor>::wrapName, folderName) )
+    {
+      // Ok, we don't need to scan this directory, we've handled it before.
+      //ATH_MSG_VERBOSE("Directory is PreProcessorWrapper, continuing.." );
+      continue;
+    }
+    // Get information about the discriminator on the folder:
+    discrEnum_t discrType;
+    EtaDependency fileEtaDep;
+    EtDependency fileEtDep;
+    try {
+      IOHelperFcns::readVar<discrEnum_t, unsigned int>(dirObj, 
+          "procType", 
+          discrType);
+      IOHelperFcns::readVar<EtaDependency, unsigned int>(dirObj, 
+          "etaDependency", 
+          fileEtaDep);
+      IOHelperFcns::readVar<EtDependency, unsigned int>(dirObj, 
+          "etDependency", 
+          fileEtDep);
+    } catch (const std::runtime_error &e){
+      throw std::runtime_error(std::string("Couldn't get discriminator type "
+            "while") + "reading folder: " + folderName + ". Reason: "
+          + e.what() );
+    }
+    // Check if holden information dependency information is ok:
+    if ( fileEtaDep != etaDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtaDep) + " whereas Wrapper is " + toStr(static_cast<EtaDependency>(etaDependency)) + ".");
+    }
+    if ( fileEtDep != etDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtDep) + " whereas Wrapper is " + toStr(static_cast<EtDependency>(etDependency)) + ".");
+    }
+    // Retrieve position indexes where we shall retrieve this discriminator
+    IOHelperFcns::getIdxVecFromStr( folderName, discrIdxVec );
+
+    // Check if everything is ok on indexes retrived:
+    if ( discrIdxVec.size() < 3 ||
+        discrIdxVec[0] >= discrSegDepSize ||
+        discrIdxVec[1] >= discrEtDepSize  ||
+        discrIdxVec[2] >= discrEtaDepSize )
+    {
+      throw std::runtime_error(std::string("There is something wrong with ")
+            + "folder idxStr: " + folderName + ". Got idxStr " + 
+            IOHelperFcns::makeIdxStr(discrIdxVec) + ". Maximum discrimination "
+            "collection size is : " + std::to_string(discrSegDepSize) + "," +
+            std::to_string(discrEtDepSize) + "," + std::to_string(discrEtaDepSize));
+    }
+
+    // Get a reference to the pointer (done only to reduce typing):
+    procedure_t *&thisDiscr = discrCol[discrIdxVec[0]]
+                                      [discrIdxVec[1]]
+                                      [discrIdxVec[2]];
+
+    // Check which procedure_t this discrimination wrapper holds. 
+    if ( Ringer::is_same<procedure_t, IDiscriminatorVarDep >::value )
+    {
+      // If the procedure_t is not the Discriminator interface, code will
+      // never get here. We only use the interpret cast so that the compiler
+      // doesn't complain about type casting.
+      thisDiscr = reinterpret_cast<procedure_t*>( getDiscr(discrType, dirObj) );
+    } else {
+      // Here it's easier, we already know the type that is written in the file,
+      // so all we need to do is loop over it and retrieve the discriminator.
+      discrEnum_t wrapperDiscrType = procedure_t::template procType<discrEnum_t>();
+      if ( discrType != wrapperDiscrType ){
+        throw std::runtime_error( std::string("There is a discriminator of type ") +
+            toStr(discrType) + " whereas this wrapper can only hold discriminators " 
+            "of type " + toStr(wrapperDiscrType));
+      }
+      thisDiscr = procedure_t::read( dirObj );
+    }
+    // ATH_MSG_VERBOSE("Successfully read directory " << folderName);
+  }
+
+  // Create Discrimination wrapper:
+  RingerProcedureWrapper *newWrapper = nullptr;
+  if (ppWrapperCol.empty()) {
+    newWrapper = new RingerProcedureWrapper(discrCol);
+  } else {
+    newWrapper = new RingerProcedureWrapper(ppWrapperCol, discrCol);
+  }
+
+  return newWrapper;
+
+}
+/// @}
+
+} // Namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..9bf329a30624b659f5b4f4a361401559e0f0a466
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.h
@@ -0,0 +1,343 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerPreProcessorWrapper.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_H
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_H
+
+#define RINGER_PROCEDURE_INCLUDE
+#include "RingerProcedureWrapper.h"
+#undef RINGER_PROCEDURE_INCLUDE
+
+//#undef NDEBUG
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/**
+ * @class IRingerProcedureWrapper
+ * @brief Specialization for PreProcessor procedure.
+ **/
+template<>
+class IRingerProcedureWrapper< PreProcessing::IPreProcessor > : 
+  virtual public IRedirectMsgStream,
+  virtual public IRingerProcedureWrapperBase
+{
+  public:
+    /**
+     * @brief Collection type of PreProcessor Wrappers.
+     **/
+    typedef typename std::vector< IRingerProcedureWrapper* > WrapperCollection;
+
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Apply PP to transform input space into a new representation
+     *
+     * This method will pass the information within xAOD::CaloRings and
+     * xAOD::TrackParticle to the pre-processors. If any pointer if set to
+     * null, then it won't pass this information. Make sure to feed
+     * pre-processors with the same information it was adjusted to work with.
+     **/
+    virtual void applyPreProcessing(
+        const DepVarStruct &depVar,
+        const xAOD::CaloRings *clrings,
+        const TrackPatternsHolder *trackPat,
+        std::vector<float> &transformVec) const = 0;
+
+    /**
+     * @brief Set the holden CaloRings raw configuration collection.
+     **/
+    virtual void setRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *crRawConfCol) = 0;
+
+    /**
+     * @brief Get the holden CaloRings raw configuration collection.
+     **/
+    virtual void getRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *&crRawConfCol) const = 0;
+
+    /**
+     * @brief Get segmentation type for this pre-processing
+     **/
+    virtual SegmentationType getSegType() const = 0;
+#endif
+
+    /**
+     * @brief Apply PP to transform input space into a new representation.
+     *
+     * This method directly uses transformVec as input and transforms it into
+     * the new representation.
+     **/
+    virtual void applyPreProcessing(
+        const DepVarStruct &depVar, 
+        std::vector<float> &transformVec) const = 0;
+
+    /**
+     * @brief Returns this wrapper name
+     **/
+    virtual const char* name() const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE {
+      return wrapName;
+    }
+
+    /**
+     * @brief Write all wrappers on ppWrapperCol to TDirectory
+     **/
+    static void writeCol(const WrapperCollection &ppWrapperCol, 
+        TDirectory *configDir);
+
+    /**
+     * @brief Read all pre-processing on configDir and append them to
+     * IPreProcWrapperCollection
+     **/
+    static void read(WrapperCollection &ppWrapperCol, 
+        TDirectory *configDir, 
+        unsigned version);
+
+#if RINGER_USE_NEW_CPP_FEATURES
+    static constexpr const char* wrapName = "RingerPreProcessorWrapper"; 
+#else
+    static const char* wrapName; 
+#endif
+
+    /** Ensure virtual destructor */
+    virtual ~IRingerProcedureWrapper(){;}
+
+  protected:
+    IRingerProcedureWrapper(){;}
+
+};
+
+/**
+ * @brief Facilitate access into Threshold Wrappers.
+ **/
+typedef IRingerProcedureWrapper< PreProcessing::IPreProcessor > IPreProcWrapper;
+/**
+ * @brief Facilitate access into Threshold Wrappers collection.
+ **/
+typedef IPreProcWrapper::WrapperCollection IPreProcWrapperCollection;
+
+/**
+ * @class RingerProcedureWrapper
+ * @brief Specialization for PreProcessing procedure.
+ **/
+template < class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType>
+class RingerProcedureWrapper<
+  procedure_t, 
+  etaDependency,
+  etDependency,
+  segType,
+  true,    // isPreProcessor
+  false,   // isDiscriminator
+  false> : // isThreshold
+    public IPreProcWrapper,
+    public RedirectMsgStream
+{
+    RINGER_STATIC_ASSERT(
+        (Ringer::is_base_of<VariableDependency,procedure_t>::value),
+        "RingerProcedureWrapper procedure_t type must have IVariableDependecy inheritance.");
+  public:
+    /// RingerProcedureWrapper for Threshold procedures typedefs:
+    ///@{
+    /**
+     * @brief typedef to the Ringer Interface variable dependency collection
+     *
+     * Vector Dimension: [segType][etBin][etaBin]:
+     **/
+    typedef typename std::vector < 
+        std::vector < 
+        std::vector < procedure_t* > >
+      > PPDepProcCollection;
+    ///@}
+
+    /// Ctors:
+    ///@{
+    /**
+     * @brief Build RProc Wrapper 
+     **/
+    RingerProcedureWrapper(
+        const PPDepProcCollection &ppDepCol):
+      m_ppCol(ppDepCol),
+      m_pp(nullptr),
+      m_rsRawConfCol(nullptr),
+      m_nRings(0)
+    { 
+      checkPPCol(); 
+      m_pp = m_ppCol[0][0][0];
+    }
+    ///@}
+
+    /// Main Methods:
+    ///@{
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Apply PP to transform input space into a new representation
+     *
+     * This method will pass the information within xAOD::CaloRings and
+     * xAOD::TrackParticle to the pre-processors. If any pointer if set to
+     * null, then it won't pass this information. Make sure to feed
+     * pre-processors with the same information it was adjusted to work with.
+     **/
+    virtual void applyPreProcessing(
+        const DepVarStruct &depVar,
+        const xAOD::CaloRings *clrings,
+        const TrackPatternsHolder *trackPat,
+        std::vector<float> &transformVec) const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE;
+
+#endif
+
+    /**
+     * @brief Apply PP to transform input space into a new representation.
+     *
+     * This method directly uses transformVec as input and transforms it into
+     * the new representation.
+     **/
+    virtual void applyPreProcessing(
+        const DepVarStruct &depVar, 
+        std::vector<float> &transformVec) const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE;
+    /// @}
+
+    /// Other utilities
+    /// @{
+#ifndef RINGER_STANDALONE
+    /**
+     * @brief Set the holden CaloRings raw configuration collection.
+     **/
+    virtual void setRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *crRawConfCol) 
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE 
+    {
+      m_rsRawConfCol = crRawConfCol;
+      m_nRings = xAOD::RingSetConf::totalNumberOfRings( *crRawConfCol );
+    }
+
+    /**
+     * @brief Get the holden CaloRings raw configuration collection.
+     **/
+    virtual void getRawConfCol(
+        const xAOD::RingSetConf::RawConfCollection *&crRawConfCol) const
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE
+    {
+      crRawConfCol = m_rsRawConfCol;
+    }
+#endif
+
+    /**
+     * @brief Get segmentation type for this pre-processor
+     **/
+    virtual SegmentationType getSegType() const 
+      ATH_RINGER_FINAL ATH_RINGER_OVERRIDE
+    {
+      return static_cast<SegmentationType>(segType);
+    }
+
+    /**
+     * @brief Returns whether holden interface collection is empty.
+     **/
+    virtual bool empty() const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE 
+    { 
+      return m_ppCol.empty();
+    }
+
+    /**
+     * @brief Returns eta dependecy for this wrapper
+     **/
+    EtaDependency etaDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtaDependency>(etaDependency);
+    }
+
+    /**
+     * @brief Returns et dependecy for this wrapper
+     **/
+    EtDependency etDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtDependency>(etDependency);
+    }
+
+    /**
+     * @brief Release all holden pointer memory
+     **/
+    void releaseMemory() ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+
+    /**
+     * @brief Overloads the setMsgStream from RedirectMsgStream.
+     **/
+    virtual void setMsgStream(MsgStream *msg) const ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL;
+
+    /**
+     * @brief Get full wrapper name, static method
+     **/
+    static std::string staticFullName();
+
+    /**
+     * @brief Get full wrapper name
+     **/
+    std::string fullName() const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Print wrapper content
+     **/
+    void print(MSG::Level lvl = MSG::DEBUG) const ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL;
+
+    /**
+     * @brief Write collection to TDirectory
+     **/
+    void write(TDirectory *baseDir, const char *idxStr = "") const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Read collection from TDirectory
+     **/
+    static RingerProcedureWrapper* read(TDirectory *configDir, 
+        unsigned version);
+    ///@}
+
+  private:
+    /// Private Methods:
+    ///@{
+    /**
+     * @brief Check if pre-processing interface collection is in good status 
+     * (Throws otherwise)
+     **/
+    void checkPPCol(); 
+    ///@}
+
+    /// Private Properties:
+    ///@{
+    /// @brief holden pre-processing collection:
+    PPDepProcCollection m_ppCol;
+    /// Hold pointer to the first position on the collection
+    procedure_t *m_pp;
+
+#ifndef RINGER_STANDALONE
+    /// @brief contains a pointer into the CaloRings configuration:
+    const xAOD::RingSetConf::RawConfCollection *m_rsRawConfCol;
+    /// @short contains the total number of rings in the vectorized
+    ///        representation
+    unsigned m_nRings;
+#endif
+    ///@}
+ 
+};
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#ifndef RINGER_DISCRIMINATOR_WRAPPER_INCLUDE
+#include "RingerPreProcessorWrapper.icc"
+#endif // RINGER_DISCRIMINATOR_WRAPPER_INCLUDE
+#endif // INCLUDE_HEADER_ONLY
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.icc
new file mode 100644
index 0000000000000000000000000000000000000000..8defdbe1a618aefbd1fb0e1803c97e497c87f81c
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerPreProcessorWrapper.icc
@@ -0,0 +1,709 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerPreProcessorWrapper.icc 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_ICC
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_ICC
+
+#include "RingerPreProcessorWrapper.h"
+#include "RingerProcedureWrapper.icc"
+
+#include "Normalizations.h"
+
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+
+#undef NDEBUG
+
+namespace Ringer {
+
+namespace WrapperHelperFcns {
+
+/**
+ * Return the pre-processing on dirObj of ppType
+ **/
+inline
+PreProcessing::IPreProcessorVarDep* getPP(preProcEnum_t ppType, 
+    TDirectory *dirObj )
+{
+  using namespace PreProcessing;
+  // For the interface case, we will have to create each pre-processing 
+  // depending on the information written on ppType:
+  switch ( ppType )
+  {
+    case preProcEnum_t::Norm1:
+    {
+      return Norm::Norm1VarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::Norm2:
+    {
+      return Norm::Norm2VarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::Sqrt:
+    {
+      return Norm::SqrtVarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::ConstantValue:
+    {
+      return Norm::ConstantValueVarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::Sequential:
+    {
+      return Norm::SequentialVarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::Spherization:
+    {
+      return Norm::SpherizationVarDep::read( dirObj );
+      break;
+    }
+    case preProcEnum_t::MinMax:
+    {
+      return Norm::MinMaxVarDep::read( dirObj );
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error( std::string("Cannot read preprocessor of ") +
+          "type: " + toStr(ppType) );
+    }
+  }
+}
+} // private namespace 
+
+
+// Import Wrapper Helper functions
+using namespace WrapperHelperFcns;
+
+// =============================================================================
+//            ----------------------------------------
+//            RingerProcedureWrapper for PreProcessors
+//            ----------------------------------------
+// =============================================================================
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,      // isPreProcessor
+  false,     // isDiscriminator
+  false>     // isThreshold
+::releaseMemory()
+{
+  for ( size_t segIdx = 0; segIdx < m_ppCol.size() ; ++segIdx){
+    for ( size_t etIdx = 0; etIdx < m_ppCol[segIdx].size() ; ++etIdx){
+      for ( size_t etaIdx = 0; etaIdx < m_ppCol[segIdx][etIdx].size(); 
+          ++etaIdx)
+      {
+        delete m_ppCol[segIdx][etIdx][etaIdx];
+      }
+    }
+  }
+  m_ppCol.clear();
+  m_pp = nullptr;
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,
+  false,
+  false >
+::applyPreProcessing(
+    const DepVarStruct &depVar,
+    std::vector<float> &transformVec) const
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying internal layer pre-processing.");
+#endif
+
+  // This method only applies for segType NoSegmentation.
+  ensureNoSegmentationOnlyFcn(static_cast<SegmentationType>(segType));
+
+  // If not dependent, simply run for the first position in the vector:
+  if ( !etaDependency && !etDependency ){
+    m_pp->execute(transformVec);
+    return;
+  }
+
+  // Initialize eta and et indexes:
+  size_t etaIdx(0), etIdx(0);
+  // Get the correct pp to be applied:
+  if (etaDependency == EtaDependency::EtaDependent){
+    etaIdx = findEtaBin(depVar.eta, m_ppCol[0]);
+  }
+
+  if (etDependency == EtDependency::EtDependent){
+    etIdx = findEtBin(depVar.et, m_ppCol[0]);
+  }
+
+#ifndef NDEBUG
+  ATH_MSG_VERBOSE("Applying pre-processing at etaIdx (" 
+      << etaIdx << ") and etIdx (" << etIdx << ").");
+#endif
+
+  // Apply it:
+  m_ppCol[0][etIdx][etaIdx]->execute(transformVec);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,
+  false,
+  false >
+::applyPreProcessing(
+    const DepVarStruct &depVar,
+    const xAOD::CaloRings *clrings,
+    const TrackPatternsHolder *trackPat,
+    std::vector<float> &transformVec) const
+{
+
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying first discrimination layer pre-processing.");
+#endif
+
+  // Erase any previous information
+  transformVec.clear();
+
+  // Initialize eta and et indexes:
+  size_t etaIdx(0), etIdx(0);
+  // Get the correct idx to be applied:
+  if ( etaDependency == EtaDependency::EtaDependent ) {
+    etaIdx = findEtaBin(depVar.eta, m_ppCol[0]);
+  }
+  if ( etDependency == EtDependency::EtDependent ) {
+    etIdx = findEtBin(depVar.et, m_ppCol[0]);
+  }
+  size_t cPreProc = 0;
+
+  switch(segType){
+    case SegmentationType::NoSegmentation:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying NonSegmented pre-processing at etaIdx (" 
+          << etaIdx << ") and etIdx (" << etIdx << ").");
+#endif
+      if (clrings){
+        clrings->exportRingsTo(transformVec);
+      }
+      if (trackPat){
+        trackPat->exportPatternsTo(transformVec);
+      }
+      // Apply pre-processing to all transformVec:
+      m_ppCol[cPreProc++][etaIdx][etIdx]->execute(transformVec);
+      break;
+    }
+    case SegmentationType::TrackCalSegmentation:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal segmented pre-processing "
+          " at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply pre-processing to CaloRings as one:
+        clrings->exportRingsTo(transformVec);
+        executeSegmentedPP(
+            transformVec,
+            m_ppCol[cPreProc++][etaIdx][etIdx], 
+            transformVec);
+      } else {
+        cPreProc += 1;
+      }
+      if (trackPat){
+        transformVec.clear();
+        // Apply pre-processing to track patterns separated:
+        trackPat->exportPatternsTo(transformVec);
+        executeSegmentedPP(
+            transformVec,
+            m_ppCol[cPreProc++][etaIdx][etIdx], 
+            transformVec);
+      } else {
+        cPreProc += 1;
+      }
+      break;
+    }
+    case SegmentationType::TrackCalPatTypeSegmentation:
+    {
+      // TODO Implement this if it is going to be used:
+      throw std::runtime_error(std::string("There is no implementation method "
+            "for ") + toStr(static_cast<SegmentationType>(segType)) );
+    }
+    case SegmentationType::TrackCalJointSections:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal-JointSections segmented" 
+          " pre-processing at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply pre-processing to each CalJointSection:
+        while ( cPreProc < static_cast<size_t>(
+              CalJointSection::NJointSections) )
+        {
+          transformVec.clear();
+          clrings->exportRingsTo( transformVec, 
+              *m_rsRawConfCol,
+              static_cast<CalJointSection>(cPreProc));
+
+          executeSegmentedPP(
+              transformVec,
+              m_ppCol[cPreProc++][etaIdx][etIdx], 
+              transformVec);
+        }
+      } else {
+        cPreProc += static_cast<size_t>(CalJointSection::NJointSections);
+      }
+      if (trackPat){
+        transformVec.clear();
+        // Apply pre-processing to track patterns separated:
+        trackPat->exportPatternsTo(transformVec);
+        executeSegmentedPP(
+            transformVec,
+            m_ppCol[cPreProc++][etaIdx][etIdx], 
+            transformVec);
+      } else {
+        cPreProc += 1;
+      }
+      break;
+    }
+    case SegmentationType::TrackCalJointLayers:
+    {
+#ifndef NDEBUG
+      ATH_MSG_VERBOSE("Applying Track/Cal-JointLayers segmented" 
+          " pre-processing at etaIdx (" << etaIdx << ") and etIdx (" 
+          << etIdx << ").");
+#endif
+      if (clrings){
+        // Apply pre-processing to each CalJointLayer:
+        while ( cPreProc < static_cast<size_t>(
+              CalJointLayer::NJointLayers) )
+        {
+          transformVec.clear();
+          clrings->exportRingsTo(
+              transformVec, 
+              *m_rsRawConfCol,
+              static_cast<CalJointLayer>(cPreProc));
+
+          executeSegmentedPP(
+              transformVec,
+              m_ppCol[cPreProc++][etaIdx][etIdx], 
+              transformVec);
+        }
+      } else {
+        cPreProc += static_cast<size_t>(CalJointLayer::NJointLayers);
+      }
+      if (trackPat){
+        transformVec.clear();
+        // Apply pre-processing to track Patterns separated:
+        trackPat->exportPatternsTo(transformVec);
+        executeSegmentedPP(
+            transformVec,
+            m_ppCol[cPreProc++][etaIdx][etIdx], 
+            transformVec);
+      } else {
+        cPreProc += 1;
+      }
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error(std::string("There is no implementation method "
+            "for ") + toStr(static_cast<SegmentationType>(segType)) );
+    }
+  }
+  return;
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,      // isPreProcessor
+  false,     // isDiscriminator
+  false>     // isThreshold
+::checkPPCol(){
+  try {
+    checkCollection(m_ppCol, 
+        static_cast<EtaDependency>(etaDependency), 
+        static_cast<EtDependency>(etDependency));
+    if ( m_ppCol.size() != numberOfSegments(static_cast<SegmentationType>(segType))){
+      throw std::runtime_error(std::string("Cannot allocate segment ") +
+            "dependent vector of type " + toStr(static_cast<SegmentationType>(segType)) + " with size "
+            "different from " + std::to_string(numberOfSegments(static_cast<SegmentationType>(segType))) + 
+            ". Current size is " + std::to_string(m_ppCol.size()) + ".");
+    }
+  } catch ( const std::runtime_error &e ) {
+    throw std::runtime_error(std::string("Couldn't initialize RingerPreProcessorWrapper due to: ")
+        + e.what() );
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,      // isPreProcessing
+  false,     // isDiscriminator
+  false>     // isThreshold
+::setMsgStream(MsgStream *msg) const {
+  // Propagate this stream into collection:
+  setCollectionMsgStream(msg,m_ppCol);
+  // Set stream to self
+  this->RedirectMsgStream::setMsgStream(msg);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,       // isPreProcessor
+  false,      // isDiscriminator
+  false>      // isThreshold
+::staticFullName() {
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+  std::stringstream ss;
+  ss << "RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((Ringer::is_same<procedure_t, 
+              PreProcessing::IPreProcessorVarDep>::value)?",":"(VarDep),")
+        << toStr(static_cast<EtaDependency>(etaDependency)) << "," 
+        << toStr(static_cast<EtDependency>(etDependency)) << "," 
+        << toStr(static_cast<SegmentationType>(segType)) << ">";
+  return ss.str();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,       // isPreProcessor
+  false,      // isDiscriminator
+  false>      // isThreshold
+::fullName() const {
+  return staticFullName();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,       // isPreProcessor
+  false,      // isDiscriminator
+  false>      // isThreshold
+::print(MSG::Level lvl) const
+{
+  if ( this->isStreamAvailable() ) { 
+    if ( this->level() > lvl ){
+      // Don't waste time print nothing.
+      return;
+    }
+    std::vector<unsigned> posVec(3);
+    this->msg() << lvl << fullName() << " contents: "<<  endreq;
+    for ( size_t segIdx = 0; segIdx < m_ppCol.size() ; ++segIdx){
+      posVec[0] = segIdx;
+      for ( size_t etIdx = 0; etIdx < m_ppCol[segIdx].size() ; ++etIdx){
+        posVec[1] = etIdx;
+        for ( size_t etaIdx = 0; etaIdx < m_ppCol[segIdx][etIdx].size(); 
+            ++etaIdx)
+        {
+          posVec[2] = etaIdx;
+          this->msg() << lvl << m_ppCol[segIdx][etIdx][etaIdx]->name() <<
+            IOHelperFcns::makeIdxStr(posVec) << " configuration:" << endreq;
+          m_ppCol[segIdx][etIdx][etaIdx]->print(lvl);
+        }
+      }
+    }
+  } else {
+    std::cerr << "Stream is not available, cannot print " <<
+      fullName() << "." << std::endl;
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,       // isPreProcessor
+  false,      // isDiscriminator
+  false>      // isThreshold
+::write(TDirectory *baseDir, const char *idxStr) const
+{
+  // ----------- Template basics ----------
+  // Create configuration directory
+  TDirectory *configDir = IOHelperFcns::makeDir(baseDir, 
+      (std::string(this->name()) + idxStr).c_str() );
+
+  // Write basic template information:
+  preProcEnum_t ppType = procedure_t::template procType<preProcEnum_t>();
+  SegmentationType fileSegType = static_cast<SegmentationType>(segType);
+  EtaDependency fileEtaDep = static_cast<EtaDependency>(etaDependency);
+  EtDependency fileEtDep = static_cast<EtDependency>(etDependency);
+  // FIXME Why do I need to use const? Unfortunately if I don't use so, the
+  // compiler won't accept static_casting from discr_Enum_t to unsigned int:
+  // some issue with reference casting.
+  IOHelperFcns::writeVar<const preProcEnum_t, const unsigned int>( configDir,
+      "ppType",
+      ppType);
+  IOHelperFcns::writeVar<const SegmentationType, const unsigned int>( configDir, 
+      "segType",
+      fileSegType);
+  IOHelperFcns::writeVar<const EtaDependency, const unsigned int>( configDir,
+      "etaDependency",
+      fileEtaDep);
+  IOHelperFcns::writeVar<const EtDependency, const unsigned int>( configDir,
+      "etDependency",
+      fileEtDep);
+
+  // Write size information:
+  unsigned ppSegDepSize = m_ppCol.size();
+  unsigned ppEtDepSize =  m_ppCol[0].size();
+  unsigned ppEtaDepSize = m_ppCol[0][0].size();
+  IOHelperFcns::writeVar( configDir,  "ppSegDepSize" , ppSegDepSize );
+  IOHelperFcns::writeVar( configDir,  "ppEtDepSize"  , ppEtDepSize  );
+  IOHelperFcns::writeVar( configDir,  "ppEtaDepSize" , ppEtaDepSize );
+
+  // Write PreProcessors Collection
+  std::vector<unsigned int> ppCount(3);
+  for (size_t segIdx = 0; 
+      segIdx < m_ppCol.size(); 
+      ++segIdx)
+  {
+    ppCount[0] = segIdx;
+    for (size_t etIdx = 0; 
+        etIdx < m_ppCol[segIdx].size(); 
+        ++etIdx)
+    {
+      ppCount[1] = etIdx;
+      for (size_t etaIdx = 0; 
+          etaIdx < m_ppCol[segIdx][etIdx].size(); 
+          ++etaIdx)
+      {
+        ppCount[2] = etaIdx;
+        m_ppCol[segIdx][etIdx][etaIdx]->write(
+            configDir,
+            IOHelperFcns::makeIdxStr(ppCount).c_str());
+      }
+    }
+  }
+}
+
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency,
+  /*SegmentationType*/int segType
+>
+RingerProcedureWrapper<procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,
+  false,
+  false> *
+RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  segType,
+  true,      // isPreProcessor
+  false,     // isDiscriminator
+  false>     // isThreshold
+::read(TDirectory *configDir, unsigned /*version*/)
+{
+  using namespace PreProcessing;
+
+  IOHelperFcns::checkDir(configDir);
+
+  // ----------- PreProcesings: ----------
+  // Read pre-processing collection size:
+  unsigned ppSegDepSize(0),
+           ppEtDepSize(0),
+           ppEtaDepSize(0);
+  IOHelperFcns::readVar( configDir,  "ppSegDepSize", ppSegDepSize );
+  IOHelperFcns::readVar( configDir,  "ppEtDepSize" , ppEtDepSize  );
+  IOHelperFcns::readVar( configDir,  "ppEtaDepSize", ppEtaDepSize );
+
+  // Allocate pre-processing collection with size specified on file
+  PPDepProcCollection ppCol( ppSegDepSize,
+      std::vector< std::vector< procedure_t*> >(
+        ppEtDepSize, std::vector< procedure_t*>(
+          ppEtaDepSize, nullptr )));
+
+  // Allocate index position retriever:
+  std::vector<unsigned int> ppIdxVec(3);
+
+  // Retrieve dir list and loop on it:
+  std::shared_ptr<THashList> list(nullptr);
+  if ( !( list = IOHelperFcns::getDirList(configDir) ) ) {
+    std::runtime_error(std::string("Couldn't retrieve directory "
+          "list from wrapper folder"));
+  }
+
+  TIter iter( list.get() );
+  while ( TDirectory* dirObj = static_cast<TDirectory*>(iter()) ) {
+
+    const char* folderName = dirObj->GetName();
+
+    //ATH_MSG_VERBOSE("Scanning directory " << folderName );
+
+    // Get information about the pre-processing on the folder:
+    preProcEnum_t ppType;
+    EtaDependency fileEtaDep;
+    EtDependency fileEtDep;
+    try {
+      IOHelperFcns::readVar<preProcEnum_t, unsigned int>(dirObj, 
+          "procType", 
+          ppType);
+      IOHelperFcns::readVar<EtaDependency, unsigned int>(dirObj, 
+          "etaDependency", 
+          fileEtaDep);
+      IOHelperFcns::readVar<EtDependency, unsigned int>(dirObj, 
+          "etDependency", 
+          fileEtDep);
+    } catch (const std::runtime_error &e){
+      throw std::runtime_error(std::string("Couldn't get pre-processing type "
+            "while") + "reading folder: " + folderName + ". Reason: "
+          + e.what() );
+    }
+    // Check if holden information dependency information is ok:
+    if ( fileEtaDep != etaDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtaDep) + " whereas Wrapper is " + toStr(static_cast<EtaDependency>(etaDependency)) + ".");
+    }
+    if ( fileEtDep != etDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtDep) + " whereas Wrapper is " + toStr(static_cast<EtDependency>(etDependency)) + ".");
+    }
+    // Retrieve position indexes where we shall retrieve this pre-processing 
+    IOHelperFcns::getIdxVecFromStr( folderName, ppIdxVec );
+
+    // Check if everything is ok on indexes retrived:
+    if ( ppIdxVec.size() < 3 ||
+        ppIdxVec[0] >= ppSegDepSize ||
+        ppIdxVec[1] >= ppEtDepSize  ||
+        ppIdxVec[2] >= ppEtaDepSize )
+    {
+      throw std::runtime_error(std::string("There is something wrong with ")
+            + "folder idxStr: " + folderName + ". Got idxStr " + 
+            IOHelperFcns::makeIdxStr(ppIdxVec) + ". Maximum pre-processing "
+            "collection size is : " + std::to_string(ppSegDepSize) + "," +
+            std::to_string(ppEtDepSize) + "," + std::to_string(ppEtaDepSize));
+    }
+
+    // Get a reference to the pointer (only used to reduce typing):
+    procedure_t *&thisPP = ppCol[ppIdxVec[0]]
+                                [ppIdxVec[1]]
+                                [ppIdxVec[2]];
+
+    // Check which procedure_t this pre-processing wrapper holds. 
+    if ( Ringer::is_same<procedure_t, IPreProcessorVarDep >::value )
+    {
+      // If the procedure_t is not the PreProcessor interface, code will
+      // never get here. We only use the interpret cast so that the compiler
+      // doesn't complain about type casting.
+      thisPP = reinterpret_cast<procedure_t*>( getPP(ppType, dirObj) );
+    } else {
+      // Here it's easier, we already know the type that is written in the file,
+      // so all we need to do is loop over it and retrieve the discriminator.
+      preProcEnum_t wrapperPPType = procedure_t::template procType<preProcEnum_t>();
+      if ( ppType != wrapperPPType ){
+        throw std::runtime_error( std::string("There is a pre-processing of type ") +
+            toStr(ppType) + " whereas this wrapper can only hold pre-processings " 
+            "of type " + toStr(wrapperPPType));
+      }
+      thisPP = procedure_t::read( dirObj );
+    }
+    // ATH_MSG_VERBOSE("Successfully read directory " << folderName);
+  }
+
+  // Create and return PreProcessors wrapper:
+  return new RingerProcedureWrapper(ppCol);
+
+}
+
+
+} // Namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERPREPROCESSORWRAPPER_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..271ad2d05aea6789d320058d74a5dee13e7714c7
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.h
@@ -0,0 +1,192 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerProcedureWrapper.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_H
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_H
+
+// STL includes:
+#include <vector>
+
+#ifndef RINGER_STANDALONE
+// xAOD includes:
+# include "xAODCaloRings/CaloRings.h"
+# include "xAODCaloRings/RingSetConf.h"
+# include "xAODTracking/TrackParticleFwd.h"
+#endif
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+#include "RingerSelectorTools/tools/cxx/is_same.h"
+#include "RingerSelectorTools/tools/cxx/StaticAssert.h"
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+
+#ifndef INCLUDE_HEADER_ONLY // Avoid circular includes
+#define INCLUDE_HEADER_ONLY
+#endif // INCLUDE_HEADER_ONLY
+#include "RingerSelectorTools/procedures/Types.h"
+#undef INCLUDE_HEADER_ONLY
+
+/*
+ * TODO List
+ *
+ * - Maybe we want to put PreProcessor Wrapper into the RingerCommonSelector
+ *   and add to the Discriminator Wrapper a post-processing wrapper. This would 
+ *   make implementation much more flexible.
+ *
+ * - We also need to deal with the pattern space segmentation being different
+ *   from input space, previous topic would help this to be implemented, but we
+ *   also would need to add the segmentation representation into the Discrimators.
+ *   This means that we might want to change the configuration classes into
+ *   segmentation representation, which is what really we need.
+ *
+ * - The PreProcessings can be propagated into a Processing space, to merge it 
+ *   with the PostProcessings. They might be applied as both, that is, they
+ *   will inherit from both interfaces, and we might want to apply the direct
+ *   transformation, but also the inverse transformation (if it exists), that
+ *   would lead the transform space into the original space.
+ *
+ * - Check why decoration cannot be read within root file using kBranchAccess.
+ *
+ * - The RingerProcedureWrapper can be divided into base templates to have its
+ *   members created only for those cases where it is dependent. For instance,
+ *   the collection shouldn't be dependent on seg, eta and et, but only on
+ *   procedure_t template. This is also true for some methods, that shouldn't
+ *   be created dependent on segment information, or even eta/et dependency.
+ */
+
+/* 
+ * FIXME List:
+ *
+ * - Can't apply more than one PreProcessing Wrapper when on the first
+ *   discrimination layer.
+ *
+ */
+
+namespace Ringer {
+
+/**
+ * @class IRingerProcedureWrapperBase
+ * @brief Used as base for all IRingerProcedureWrapper template specializations
+ **/
+class IRingerProcedureWrapperBase {
+  public:
+    /**
+     * @brief Returns whether holden interface collection is empty.
+     **/
+    virtual bool empty() const = 0;
+
+    /**
+     * @brief Write collection to TDirectory
+     **/
+    virtual void write(TDirectory *baseDir, const char *idxStr = "") const = 0;
+
+    /**
+     * @brief Retrieve RingerProcedureWrapper name
+     **/
+    virtual const char* name() const = 0;
+
+    /**
+     * @brief Returns eta dependecy for this wrapper
+     **/
+    virtual EtaDependency etaDep() const = 0;
+
+    /**
+     * @brief Returns et dependecy for this wrapper
+     **/
+    virtual EtDependency etDep() const = 0;
+
+    /**
+     * @brief Release all pointed memory holden by wrapper
+     **/
+    virtual void releaseMemory() = 0;
+
+    /**
+     * @brief Get full wrapper name
+     **/
+    virtual std::string fullName() const = 0;
+
+    /**
+     * @brief Print wrapper content
+     **/
+    virtual void print(MSG::Level lvl = MSG::DEBUG) const = 0;
+
+    /**
+     * Ensure virtual destructor
+     **/
+    virtual ~IRingerProcedureWrapperBase(){;}
+
+};
+
+/**
+ * Reduce verbosity 
+ **/
+typedef IRingerProcedureWrapperBase IProcWrapperBase;
+
+/**
+ * Collection of interface base
+ **/
+typedef std::vector<IProcWrapperBase> IProcWrapperBaseCollection;
+
+/**
+ * @class IRingerProcedureWrapper
+ * @brief Primary Template for Ringer Interface Wrapper (not implemented)
+ *
+ * We implement specializations for each Ringer procedure type
+ **/
+template< typename procedure_t >
+class IRingerProcedureWrapper;
+
+/**
+ * @class ProcedureHolder
+ * @brief Hold procedure dependent procedure vector
+ *
+ * TODO Implement this
+ **/
+//template<typename procedure_t>
+//class ProcedureHolder;
+
+
+/**
+ * @class RingerProcedureWrapper
+ * @brief Primary Template for Ringer Interface Wrapper (not implemented).
+ *
+ * There is a bool template for determining the procedure specialization type:
+ * it must not be explicitely declared.
+ *
+ * We implement specializations for each procedure type on dedicated files. 
+ **/
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency = EtaIndependent,
+  /*EtDependency*/int etDependency = EtIndependent,
+  /*SegmentationType*/int segType = NoSegmentation,
+  // Below template parameters are not supposed to be set directly by user:
+  bool isPreProcessor = RingerProcedureType< procedure_t >::is_pre_processor,
+  bool isDiscriminator = RingerProcedureType< procedure_t >::is_discriminator,
+  bool isThreshold     = RingerProcedureType< procedure_t >::is_threshold 
+>
+class RingerProcedureWrapper; 
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#ifndef RINGER_PROCEDURE_INCLUDE // When included a specialized procedure type
+// in place of RingerProcedureWrapper it is needed to do this because
+// the procedure wrapper undefines INCLUDE_HEADER_ONLY macro when including
+// Types.h. This can be avoided if we don't force including all other procedure
+// types wrappers, but it is wanted to make sure that when a procedure type wrapper
+// is included, every other procedure is also included so that the template
+// specializations are always available independent on how you include it.
+#include "RingerProcedureWrapper.icc"
+#endif // RINGER_PROCEDURE_INCLUDE
+#endif // INCLUDE_HEADER_ONLY
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.icc
new file mode 100644
index 0000000000000000000000000000000000000000..08dce1e518cefa1a87659c8e11b787a9908cd13c
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerProcedureWrapper.icc
@@ -0,0 +1,441 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerProcedureWrapper.icc 689837 2015-08-17 17:22:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_ICC
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_ICC
+
+#undef NDEBUG
+
+// STL includes:
+#include <vector>
+#include <stdexcept>
+
+// Local includes:
+#include "RingerProcedureWrapper.h"
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.h"
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+namespace WrapperHelperFcns {
+
+// =============================================================================
+/**
+ * @brief Returns eta bin number which is within region.
+ *
+ * Vector Dimension: [etBin][etaBin]:
+ **/
+template<class vecType>
+size_t findEtaBin( const float eta, 
+  const typename std::vector< std::vector < 
+      vecType*
+    > 
+  > &varDepCol )
+{
+  std::vector< vecType* > firstRow = varDepCol[0];
+  for (size_t idx = 0; idx < firstRow.size(); ++idx){
+    if (firstRow[idx]->isWithinEtaRange(eta)){
+      return idx;
+    }
+  }
+  throw std::runtime_error(std::string( "eta ")  +
+      std::to_string(eta) + " is not inside Ringer Procedure range.");
+}
+
+// =============================================================================
+/**
+ * @brief Returns Et bin number which is within region.
+ *
+ * Vector Dimension: [etBin][etaBin]:
+ **/
+template<class vecType>
+size_t findEtBin( const float et, 
+    const std::vector< 
+      std::vector < 
+          vecType*
+        > 
+      > &varDepCol )
+{
+  for (size_t idx = 0; idx < varDepCol.size(); ++idx){
+    if ( varDepCol[idx][0]->isWithinEtRange(et) ){
+      return idx;
+    }
+  }
+  throw std::runtime_error(std::string( "Et ")  +
+      std::to_string(et) + " is not inside Ringer Procedure range.");
+}
+
+// =============================================================================
+template < typename vecType >
+void checkCollection( const std::vector< std::vector<vecType*> > &vec, 
+    EtaDependency etaDependency, EtDependency etDependency )
+{
+  if (vec.empty()){
+    throw std::runtime_error(std::string(
+          "Dependency collection cannot be empty."));
+  }
+  if ( !static_cast<bool>(etDependency) && (vec.size() != 1) ) {
+    throw std::runtime_error(std::string(
+          "Cannot have EtIndependent vector with size different from unit."));
+  }
+  for ( size_t etIdx = 0; etIdx < vec.size() ; ++etIdx){
+    size_t etaSize = vec[etIdx].size();
+    if ( !etaSize ){
+      throw std::runtime_error(std::string(
+          "Dependency collection cannot have an empty vector."));
+    }
+    if ( !static_cast<bool>(etaDependency) && (etaSize != 1) ) {
+      throw std::runtime_error(std::string(
+            "Cannot have EtaIndependent vector with size "
+            "different from unit."));
+    }
+    for ( size_t etaIdx = 0; etaIdx < etaSize; ++etaIdx){
+      if( !vec[etIdx][etaIdx] ){
+        throw std::runtime_error(std::string(
+            "Dependency collection holden object is invalid."));
+      }
+      if ( etaDependency != vec[etIdx][etaIdx]->etaDep() ){
+        if ( etDependency != vec[etIdx][etaIdx]->etDep() ){
+          throw std::runtime_error(std::string(
+                "Wrong eta and Et dependency. EtaDependency should be ") + 
+              toStr(etaDependency) + " and is " + 
+              toStr(vec[etIdx][etaIdx]->etaDep()) + ", as well as EtDependency "
+              "should be " + toStr(etDependency) + " and is " +
+              toStr(vec[etIdx][etaIdx]->etDep()) + "." );
+        } else {
+          throw std::runtime_error(std::string(
+                "Wrong eta dependency. EtaDependency should be ") + 
+              toStr(etaDependency) + " and is " + 
+              toStr(vec[etIdx][etaIdx]->etaDep()) + "." );
+        }
+      }
+      if ( etDependency != vec[etIdx][etaIdx]->etDep() ){
+        throw std::runtime_error(std::string(
+              "Wrong Et dependency. EtDependency should be ") + 
+            toStr(etDependency) + " and is " + 
+            toStr(vec[etIdx][etaIdx]->etDep()) + "." );
+      }
+    }
+  }
+}
+
+// =============================================================================
+template < typename vecType >
+void checkCollection( 
+    const std::vector< std::vector< std::vector<vecType*> > > &vec,
+    EtaDependency etaDependency, EtDependency etDependency)
+{
+  if (vec.empty()){
+    throw std::runtime_error(std::string(
+          "Dependency collection cannot be empty."));
+  }
+  for ( size_t segIdx = 0; segIdx < vec.size(); ++segIdx){
+    size_t etSize = vec[segIdx].size();
+    if (!etSize){
+      throw std::runtime_error(std::string(
+          "Dependency collection cannot have an" 
+          " empty vector<vector>."));
+    }
+    checkCollection(vec[segIdx], etaDependency, etDependency);
+  }
+}
+
+// =============================================================================
+template < typename vecType >
+void setCollectionMsgStream(
+    MsgStream *stream, 
+    const std::vector< std::vector<vecType*> > &vec )
+{
+  for ( size_t etIdx = 0; etIdx < vec.size() ; ++etIdx){
+    size_t etaSize = vec[etIdx].size();
+    for ( size_t etaIdx = 0; etaIdx < etaSize; ++etaIdx){
+      vec[etIdx][etaIdx]->setMsgStream(stream);
+    }
+  }
+}
+
+// =============================================================================
+template < typename vecType >
+void setCollectionMsgStream(
+    MsgStream *stream, 
+    const std::vector< std::vector< std::vector<vecType*> > > &vec )
+{
+  for ( size_t segIdx = 0; segIdx < vec.size(); ++segIdx) {
+    setCollectionMsgStream(stream,vec[segIdx]);
+  }
+}
+
+// =============================================================================
+/**
+ * @brief Ensure that segType is NoSegmentation, otherwise throws runtime_error
+ **/
+inline
+void ensureNoSegmentationOnlyFcn(const SegmentationType segType)
+{
+  // XXX This shouldn't be a runtime_error, but it seems I would need to
+  // implement a RingerProcedureWrapper for each segType (check if this
+  // hypothesis is true), which would demand more time that I afford.
+  if (segType != SegmentationType::NoSegmentation ){
+    throw std::runtime_error(std::string(
+          "Cannot use this method for other" 
+          " SegmentationType then NoSegmentation."));
+  }
+}
+
+// =============================================================================
+/**
+ * @brief Insert toBeCopied vector values to newHolder end
+ **/
+inline
+void insertVecToVecEnd(
+    const std::vector<float> &toBeCopied,
+    std::vector<float> &newHolder)
+{
+  newHolder.insert(newHolder.end(), toBeCopied.begin(), toBeCopied.end());
+}
+
+// =============================================================================
+/**
+ * @brief Execute segmented pre-processor unified routine
+ **/
+inline
+void executeSegmentedPP(
+  std::vector<float> &input, 
+  const PreProcessing::IPreProcessor *proc, 
+  std::vector<float> &transformVec)
+{
+  // Transform input:
+  proc->execute(input);
+  // Concatenate it to global transformation vector:
+  insertVecToVecEnd(input, transformVec);
+  // Clear input vector:
+  input.clear();
+}
+
+// =============================================================================
+/**
+ * @brief Execute segmented discriminator unified routine
+ **/
+inline
+void executeSegmentedDiscr(
+  std::vector<float> &input, 
+  const Discrimination::IDiscriminator *discr, 
+  std::vector<float> &output)
+{
+  // Get this procedure output into another vector:
+  std::vector<float> localOutput;
+  localOutput.reserve(output.capacity());
+  // Execute on it:
+  discr->execute(input,localOutput);
+  // Concatenate it to global output vec:
+  insertVecToVecEnd(localOutput, output);
+  // Clear input vector:
+  input.clear();
+}
+
+// =============================================================================
+/**
+ * @brief Get Calorimeter segment from transformVec
+ **/
+inline
+void getCaloSegmentFromTransformVec(
+    const unsigned nRings,
+    const std::vector<float> &transformVec,
+    std::vector<float> &transformVecSegment)
+{
+  transformVecSegment.clear();
+  for ( size_t idx = 0; idx < nRings; ++idx )
+  {
+    transformVecSegment.push_back(transformVec[idx]);
+  }
+}
+
+// =============================================================================
+/**
+ * @brief Get Calorimeter segment from transformVec
+ **/
+template<typename segment_t>
+inline
+void getCaloSegmentFromTransformVec(
+    const xAOD::RingSetConf::RawConfCollection &rawConfCol,
+    const segment_t segment,
+    const std::vector<float> &transformVec,
+    std::vector<float> &transformVecSegment)
+{
+
+  transformVecSegment.clear();
+
+  // Get the start and end indexes from the required segment:
+  unsigned startIdx(0), endIdx(0);
+  xAOD::RingSetConf::getEdges(rawConfCol,segment,startIdx,endIdx);
+
+  for (unsigned idx = startIdx; idx < endIdx; ++idx ) {
+    transformVecSegment.push_back(transformVec[idx]);
+  }
+}
+
+// =============================================================================
+/**
+ * @brief Get Track segment from transformVec
+ **/
+inline
+void getTrackSegmentFromTransformVec(
+    const unsigned nRings,
+    const std::vector<float> &transformVec,
+    std::vector<float> &transformVecSegment)
+{
+  transformVecSegment.clear();
+  for ( size_t idx = nRings; idx < transformVec.size(); ++idx ) {
+    transformVecSegment.push_back(transformVec[idx]);
+  }
+}
+
+
+// =============================================================================
+/**
+ * These macros can be used if we want to declare a specific type wrapper, so
+ * that it can have it dedicated compiled code. Although its wrapper calling
+ * method will be determined during runtime (it is holded though its
+ * interface), it will have its code specifically compiled for this type. This
+ * means that it execute its collection methods through statically determined
+ * methods are can also benefit of inline methods.
+ *
+ * However, it shouldn't be used for every type created, as it will increase
+ * compile time and library size.
+ *
+ * Besides, there is no garantee that there will be speed gain or that it won't
+ * be negligible.
+ *
+ * If you use the READ_ALL_DEP_WRAPPER macro, it will declare all possible
+ * dependent types for that class: you should pass this wrapper the variables
+ * that are read on the file. 
+ *
+ * Instead using the READ_ALL_DEP_WRAPPER, when you need to declare only one
+ * specific template type for reading, you can otherwise use READ_WRAPPER. In
+ * this case, the passing parameters are not variables, but rather the template
+ * values.
+ *
+ * If you want to declare all eta/et dependent cases for a procedure type,
+ * you can use the READ_ETA_ET_DEP_WRAPPER, where it defines for the etaDep and
+ * etDep variables all possible variations. The segType however must be a
+ * value determined at compile time.
+ *
+ * Otherwise you want to declare segment dependent cases, which are not eta/et
+ * dependent, use READ_SEG_DEP_WRAPPER inserting segType as the variable and
+ * eta/et as compile time values, such as EtaIndependent and EtIndependent.
+ **/
+#define READ_WRAPPER(vec, wrapType, segType, etaDep, etDep, configDir, version) \
+  vec.push_back( Ringer::RingerProcedureWrapper<wrapType,                       \
+      etaDep, etDep, segType >::read(configDir,version) );     
+
+// =============================================================================
+#define READ_ETA_DEP_WRAPPER(vec, wrapType, segType, etaDep, etDep,            \
+    configDir, version)                                                        \
+  switch( etaDep )                                                             \
+  {                                                                            \
+    case Ringer::EtaDependent:                                                 \
+      READ_WRAPPER(vec, wrapType, segType, Ringer::EtaDependent, etDep,        \
+          configDir, version)                                                  \
+      break;                                                                   \
+    case Ringer::EtaIndependent:                                               \
+      READ_WRAPPER(vec, wrapType, segType, Ringer::EtaIndependent, etDep,      \
+          configDir, version)                                                  \
+      break;                                                                   \
+    default:                                                                   \
+      throw std::runtime_error(std::string("Unknown Eta dependency."));        \
+  }
+
+// =============================================================================
+#define READ_SEG_DEP_WRAPPER(vec, wrapType, segType, etaDep, etDep, configDir, \
+    version)                                                                   \
+  switch( segType )                                                            \
+  {                                                                            \
+    case Ringer::NoSegmentation:                                               \
+      READ_WRAPPER(vec, wrapType, Ringer::NoSegmentation, etaDep, etDep,       \
+          configDir, version)                                                  \
+      break;                                                                   \
+    case Ringer::TrackCalPatTypeSegmentation:                                  \
+      READ_WRAPPER(vec, wrapType, Ringer::TrackCalPatTypeSegmentation, etaDep, \
+          etDep, configDir, version)                                           \
+      break;                                                                   \
+    case Ringer::TrackCalSegmentation:                                         \
+      READ_WRAPPER(vec, wrapType, Ringer::TrackCalSegmentation, etaDep, etDep, \
+          configDir, version)                                                  \
+      break;                                                                   \
+    case Ringer::TrackCalJointLayers:                                          \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType, Ringer::TrackCalJointLayers,      \
+          etaDep, etDep, configDir, version)                                   \
+      break;                                                                   \
+    case Ringer::TrackCalJointSections:                                        \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType, Ringer::TrackCalJointSections,    \
+          etaDep, etDep, configDir, version)                                   \
+    default:                                                                   \
+      throw std::runtime_error(std::string("Unknown segmentation type"));      \
+  }
+
+// =============================================================================
+#define READ_ETA_ET_DEP_WRAPPER(vec, wrapType, segType, etaDep, etDep,         \
+    configDir, version)                                                        \
+  switch( etDep )                                                              \
+  {                                                                            \
+    case Ringer::EtDependent:                                                  \
+      READ_ETA_DEP_WRAPPER(vec, wrapType, segType, etaDep, Ringer::EtDependent,\
+          configDir, version)                                                  \
+      break;                                                                   \
+    case Ringer::EtIndependent:                                                \
+      READ_ETA_DEP_WRAPPER(vec, wrapType, segType, etaDep,                     \
+          Ringer::EtIndependent, configDir, version)                           \
+      break;                                                                   \
+    default:                                                                   \
+      throw std::runtime_error(std::string("Unknown Et dependency."));         \
+  }
+
+// =============================================================================
+#define READ_ALL_DEP_WRAPPER(vec, wrapType, segType, etaDep, etDep,            \
+    configDir, version )                                                       \
+  switch( segType )                                                            \
+  {                                                                            \
+    case Ringer::NoSegmentation:                                               \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType, Ringer::NoSegmentation, etaDep,   \
+          etDep, configDir, version )                                          \
+      break;                                                                   \
+    case Ringer::TrackCalPatTypeSegmentation:                                  \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType,                                   \
+          Ringer::TrackCalPatTypeSegmentation,                                 \
+          etaDep, etDep, configDir, version )                                  \
+      break;                                                                   \
+    case Ringer::TrackCalSegmentation:                                         \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType,                                   \
+          Ringer::TrackCalSegmentation, etaDep,                                \
+          etDep, configDir, version )                                          \
+      break;                                                                   \
+    case Ringer::TrackCalJointLayers:                                          \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType,                                   \
+          Ringer::TrackCalJointLayers, etaDep,                                 \
+          etDep, configDir, version)                                           \
+      break;                                                                   \
+    case Ringer::TrackCalJointSections:                                        \
+      READ_ETA_ET_DEP_WRAPPER(vec, wrapType,                                   \
+          Ringer::TrackCalJointSections, etaDep,                               \
+          etDep, configDir, version)                                           \
+    default:                                                                   \
+      throw std::runtime_error(std::string("Unknown segmentation type"));      \
+  }
+
+
+} // WrapperUtils namespace
+
+} // Ringer namespace
+
+#include "RingerSelectorTools/procedures/RingerPreProcessorWrapper.icc"
+#include "RingerSelectorTools/procedures/RingerDiscriminatorWrapper.icc"
+#include "RingerSelectorTools/procedures/RingerThresholdWrapper.icc"
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERPROCEDUREWRAPPER_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbe3ebba815732aec5b321f276f3fb4b6ef5754e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.h
@@ -0,0 +1,241 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerThresholdWrapper.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_H
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_H
+
+#define RINGER_PROCEDURE_INCLUDE
+#include "RingerProcedureWrapper.h"
+#undef RINGER_PROCEDURE_INCLUDE
+
+//#undef NDEBUG
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/**
+ * @class IRingerProcedureWrapper
+ * @brief Specialization for Threshold procedure.
+ **/
+template<>
+class IRingerProcedureWrapper< Discrimination::IThreshold > : 
+  virtual public IRedirectMsgStream,
+  virtual public IRingerProcedureWrapperBase
+{
+  public:
+    /**
+     * @brief Collection type of PreProcessor Wrappers.
+     **/
+    typedef typename std::vector< IRingerProcedureWrapper* > WrapperCollection;
+
+    /**
+     * @brief Apply threshold to obtain a decision.
+     **/
+    virtual void getOutput(
+        const DepVarStruct &depVar,
+        const std::vector<float> &discrOutput,
+        std::vector<bool> &decision) const = 0;
+
+    /**
+     * @brief Returns whether holden interface collection is empty.
+     **/
+    virtual bool empty() const ATH_RINGER_OVERRIDE = 0;
+
+    /**
+     * @brief Returns this wrapper name
+     **/
+    virtual const char* name() const ATH_RINGER_FINAL ATH_RINGER_OVERRIDE {
+      return wrapName;
+    }
+
+#if RINGER_USE_NEW_CPP_FEATURES
+    static constexpr const char* wrapName = "RingerThresholdWrapper"; 
+#else
+    static const char* wrapName; 
+#endif
+
+    /** Ensure virtual destructor */
+    virtual ~IRingerProcedureWrapper(){;}
+
+    /**
+     * Write wrapper to file.
+     **/
+    static void writeWrapper(const IRingerProcedureWrapper *thresWrapper, 
+        const char *fileName);
+    
+    /**
+     * Read wrapper from file.
+     **/
+    static void read(IRingerProcedureWrapper *&thresWrapper, 
+        const char* fileName);
+
+  protected:
+    IRingerProcedureWrapper(){;}
+
+};
+
+/**
+ * @brief Facilitate access into Threshold Wrappers.
+ **/
+typedef IRingerProcedureWrapper< Discrimination::IThreshold > IThresWrapper;
+/**
+ * @brief Facilitate access into Threshold Wrappers collection.
+ **/
+typedef IThresWrapper::WrapperCollection IThresWrapperCollection;
+
+/**
+ * @class RingerProcedureWrapper
+ * @brief Specialization for Threshold procedure.
+ **/
+template < class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency>
+class RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation, // Threshold is always unique for
+    // all layers, as it is applied for the discriminator output space.
+  false,    // isPreProcessor
+  false,    // isDiscriminator
+  true> :   // isThreshold
+    public IThresWrapper,
+    public RedirectMsgStream
+{
+    RINGER_STATIC_ASSERT(
+        (Ringer::is_base_of<VariableDependency,procedure_t>::value),
+        "RingerProcedureWrapper procedure_t type must have IVariableDependecy inheritance.");
+  public:
+    /// RingerProcedureWrapper for Threshold procedures typedefs:
+    ///@{
+    /**
+     * @brief typedef to the Ringer Interface variable dependency collection
+     *
+     * Collection Dimension: [etBin][etaBin]:
+     *  
+     **/
+    typedef typename std::vector < 
+        std::vector < procedure_t* > 
+      > ThresDepProcCollection;
+    ///@}
+
+    /// Ctors:
+    ///@{
+    /**
+     * @brief Build RProc Wrapper 
+     **/
+    RingerProcedureWrapper(
+        const ThresDepProcCollection &thresDepCol):
+      m_thresCol(thresDepCol)
+    { 
+      checkThresCol(); 
+      m_thres = m_thresCol[0][0];
+    }
+    ///@}
+
+    /// Main methods:
+    /// @{
+    /**
+     * @brief Apply threshold to obtain a decision.
+     **/
+    virtual void getOutput(
+        const DepVarStruct &depVar,
+        const std::vector<float> &discrOutput,
+        std::vector<bool> &decision) const ATH_RINGER_OVERRIDE;
+    /// @}
+
+
+    /// Other utilities
+    /// @{
+    /**
+     * @brief Returns whether holden interface collection is empty.
+     **/
+    virtual bool empty() const ATH_RINGER_OVERRIDE { return m_thresCol.empty();}
+
+    /**
+     * @brief Overloads the setMsgStream from RedirectMsgStream.
+     **/
+    virtual void setMsgStream(MsgStream *msg) const ATH_RINGER_OVERRIDE;
+
+    /**
+     * @brief Release all holden pointer memory
+     **/
+    void releaseMemory() ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Returns eta dependecy for this wrapper
+     **/
+    EtaDependency etaDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtaDependency>(etaDependency);
+    }
+
+    /**
+     * @brief Returns et dependecy for this wrapper
+     **/
+    EtDependency etDep() const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL
+    {
+      return static_cast<EtDependency>(etDependency);
+    }
+
+    /**
+     * @brief Get full wrapper name, static method
+     **/
+    static std::string staticFullName();
+
+    /**
+     * @brief Get full wrapper name
+     **/
+    std::string fullName() const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Print wrapper content
+     **/
+    void print(MSG::Level lvl = MSG::DEBUG) const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Write wrapper to TDirectory
+     **/
+    void write(TDirectory *baseDir, const char *idxStr = "") const
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /**
+     * @brief Read wrapper from TDirectory
+     **/
+    static RingerProcedureWrapper* read(TDirectory *configDir, 
+        unsigned version);
+    ///@}
+
+  private:
+    /// Private Methods:
+    ///@{
+    /**
+     * @brief Check if threshold interface collection is in good status 
+     * (Throws otherwise)
+     **/
+    void checkThresCol(); 
+    ///@}
+
+    /// Private Properties:
+    ///@{
+    /// @brief holden threshold collection:
+    ThresDepProcCollection m_thresCol;
+    /// @brief Hold pointer to first threshold from collection
+    /// Used when it has no variable dependency.
+    procedure_t* m_thres;
+    ///@}
+};
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "RingerThresholdWrapper.icc"
+#endif // INCLUDE_HEADER_ONLY
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.icc
new file mode 100644
index 0000000000000000000000000000000000000000..8628d7ae0a277efa811c00e587a7ce6a1fa0a25e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/RingerThresholdWrapper.icc
@@ -0,0 +1,456 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerThresholdWrapper.icc 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_ICC
+#define RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_ICC
+
+#include "RingerThresholdWrapper.h"
+#include "RingerProcedureWrapper.icc"
+
+#include "RingerSelectorTools/tools/cxx/is_same.h"
+
+#include "RingerSelectorTools/procedures/Thresholds.h"
+
+namespace Ringer {
+
+namespace WrapperHelperFcns {
+
+/**
+ * Return the threshold on dirObj of thresType
+ **/
+inline
+Discrimination::IThresholdVarDep* getThres(thresEnum_t thresType, 
+    TDirectory *dirObj )
+{
+  using namespace Discrimination;
+  // For the interface case, we will have to create each threshold
+  // depending on the information written on thresType:
+  switch ( thresType )
+  {
+    case thresEnum_t::UniqueThreshold:
+    {
+      return UniqueThresholdVarDep::read( dirObj );
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error( std::string("Cannot read threshold of ") +
+          "type: " + toStr(thresType) );
+    }
+  }
+}
+} // private namespace 
+
+
+// Import Wrapper Helper functions
+using namespace WrapperHelperFcns;
+
+// =============================================================================
+//            -------------------------------------
+//            RingerProcedureWrapper for Thresholds
+//            -------------------------------------
+// =============================================================================
+
+/**/
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,
+  false,
+  true >
+::releaseMemory()
+{
+  for ( size_t etIdx = 0; etIdx < m_thresCol.size() ; ++etIdx){
+    for ( size_t etaIdx = 0; etaIdx < m_thresCol[etIdx].size(); ++etaIdx)
+    {
+      delete m_thresCol[etIdx][etaIdx];
+    }
+  }
+  m_thresCol.clear();
+  m_thres = nullptr;
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,
+  false,
+  true >
+::getOutput(
+    const DepVarStruct &depVar,
+    const std::vector<float> &discrOutput,
+    std::vector<bool> &decision) const
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Running getOutput.");
+#endif
+
+  // If no dependency, simply use threshold and return
+  if ( !etaDependency && !etDependency ){
+    m_thres->execute(discrOutput,decision);
+    return;
+  }
+
+  // Initialize eta and et indexes:
+  size_t etaIdx(0), etIdx(0);
+  // Get the correct pp to be applied:
+  if (etaDependency){
+    etaIdx = findEtaBin(depVar.eta, m_thresCol);
+  }
+  if (etDependency){
+    etIdx = findEtBin(depVar.et, m_thresCol);
+  }
+#ifndef NDEBUG
+  ATH_MSG_VERBOSE("Applying threshold at etaIdx (" << 
+      etaIdx << ") and etIdx (" << etIdx << ").");
+#endif
+  // Apply it:
+  m_thresCol[etIdx][etaIdx]->execute(discrOutput,decision);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>       // isThreshold
+::checkThresCol(){
+  try {
+    checkCollection(m_thresCol, 
+        static_cast<EtaDependency>(etaDependency), 
+        static_cast<EtDependency>(etDependency));
+  } catch ( const std::runtime_error &e ) {
+    throw std::runtime_error(std::string("Couldn't initialize RingerThresholdWrapper due to: ")
+        + e.what() );
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>       // isThreshold
+::setMsgStream(MsgStream *msg) const {
+  // Propagate this stream into collection:
+  setCollectionMsgStream(msg,m_thresCol);
+  // Set stream to self
+  this->RedirectMsgStream::setMsgStream(msg);
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>       // isThreshold
+::staticFullName() {
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+  std::stringstream ss;
+  ss << "RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((Ringer::is_same<procedure_t,Discrimination::IThresholdVarDep>::value)?",":"(VarDep),")
+        << toStr(static_cast<EtaDependency>(etaDependency)) << "," 
+        << toStr(static_cast<EtDependency>(etDependency)) << "," 
+        << toStr(NoSegmentation) << ">";
+  return ss.str();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+std::string RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>       // isThreshold
+::fullName() const {
+  return staticFullName();
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>       // isThreshold
+::print(MSG::Level lvl) const
+{
+  if ( this->isStreamAvailable() ) { 
+    if ( this->level() > lvl ){
+      // Dont waste time printing nothing
+      return;
+    }
+    this->msg() << lvl << fullName() << " contents: "<<  endreq;
+    std::vector<unsigned> posVec(2);
+    for ( unsigned etIdx = 0; etIdx < m_thresCol.size() ; ++etIdx){
+      posVec[0] = etIdx;
+      for ( unsigned etaIdx = 0; etaIdx < m_thresCol[etIdx].size(); ++etaIdx)
+      {
+        posVec[1] = etaIdx;
+        this->msg() << lvl << m_thresCol[etIdx][etaIdx]->name() << 
+          IOHelperFcns::makeIdxStr(posVec) << " configuration:" << endreq;
+        m_thresCol[etIdx][etaIdx]->print(lvl);
+      }
+    }
+  } else {
+    std::cerr << "Stream is not available, cannot print " <<
+      fullName() << "." << std::endl;
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+void RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>      // isThreshold
+::write(TDirectory *baseDir, const char *idxStr) const
+{
+  // ----------- Template basics ----------
+  // Create configuration directory
+  TDirectory *configDir = IOHelperFcns::makeDir(baseDir, 
+      (std::string(this->name()) + idxStr).c_str() );
+
+  // Write basic template information:
+  thresEnum_t thresType = procedure_t::template procType<thresEnum_t>();
+  EtaDependency fileEtaDep = static_cast<EtaDependency>(etaDependency);
+  EtDependency fileEtDep = static_cast<EtDependency>(etDependency);
+  // FIXME Why do I need to use const? Unfortunately if I don't use so, the
+  // compiler won't accept static_casting from discr_Enum_t to unsigned int:
+  // some issue with reference casting.
+  IOHelperFcns::writeVar<const thresEnum_t, const unsigned int>( configDir,
+      "thresType",
+      thresType);
+  IOHelperFcns::writeVar<const EtaDependency, const unsigned int>( configDir,
+      "etaDependency",
+      fileEtaDep);
+  IOHelperFcns::writeVar<const EtDependency, const unsigned int>( configDir,
+      "etDependency",
+      fileEtDep);
+
+  // Write size information:
+  unsigned thresEtDepSize =  m_thresCol.size();
+  unsigned thresEtaDepSize = m_thresCol[0].size();
+  IOHelperFcns::writeVar( configDir,  "thresEtDepSize"  , thresEtDepSize  );
+  IOHelperFcns::writeVar( configDir,  "thresEtaDepSize" , thresEtaDepSize );
+
+  // Write Threshold collection
+  std::vector<unsigned int> thresCount(2);
+  for (size_t etIdx = 0; 
+      etIdx < m_thresCol.size(); 
+      ++etIdx)
+  {
+    thresCount[0] = etIdx;
+    for (size_t etaIdx = 0; 
+        etaIdx < m_thresCol[etIdx].size(); 
+        ++etaIdx)
+    {
+      thresCount[1] = etaIdx;
+      m_thresCol[etIdx][etaIdx]->write(
+          configDir,
+          IOHelperFcns::makeIdxStr(thresCount).c_str());
+    }
+  }
+}
+
+// =============================================================================
+template < 
+  class procedure_t,
+  /*EtaDependency*/int etaDependency,
+  /*EtDependency*/int etDependency
+>
+RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,
+  false,
+  true> *
+RingerProcedureWrapper<
+  procedure_t,
+  etaDependency,
+  etDependency,
+  SegmentationType::NoSegmentation,
+  false,      // isPreProcessor
+  false,      // isDiscriminator
+  true>      // isThreshold
+::read(TDirectory *configDir, unsigned /*version*/)
+{
+  using namespace Discrimination;
+
+  IOHelperFcns::checkDir(configDir);
+
+  // ----------- PreProcesings: ----------
+  // Read pre-processing collection size:
+  unsigned thresEtDepSize(0),
+           thresEtaDepSize(0);
+  IOHelperFcns::readVar( configDir,  "thresEtDepSize" , thresEtDepSize  );
+  IOHelperFcns::readVar( configDir,  "thresEtaDepSize", thresEtaDepSize );
+
+  // Allocate pre-processing collection with size specified on file
+  ThresDepProcCollection thresCol( thresEtDepSize, 
+      std::vector< procedure_t*>(
+        thresEtaDepSize, nullptr ));
+
+  // Allocate index position retriever:
+  std::vector<unsigned int> thresIdxVec(2);
+
+  // Retrieve dir list and loop on it:
+  std::shared_ptr<THashList> list(nullptr);
+  if ( !( list = IOHelperFcns::getDirList(configDir) ) ) {
+    std::runtime_error(std::string("Couldn't retrieve directory "
+          "list from wrapper folder"));
+  }
+
+  TIter iter( list.get() );
+  while ( TDirectory* dirObj = static_cast<TDirectory*>(iter()) ) {
+
+    const char* folderName = dirObj->GetName();
+
+    //ATH_MSG_VERBOSE("Scanning directory " << folderName );
+
+    // Get information about the pre-processing on the folder:
+    thresEnum_t thresType;
+    EtaDependency fileEtaDep;
+    EtDependency fileEtDep;
+    try {
+      IOHelperFcns::readVar<thresEnum_t, unsigned int>(dirObj, 
+          "procType", 
+          thresType);
+      IOHelperFcns::readVar<EtaDependency, unsigned int>(dirObj, 
+          "etaDependency", 
+          fileEtaDep);
+      IOHelperFcns::readVar<EtDependency, unsigned int>(dirObj, 
+          "etDependency", 
+          fileEtDep);
+    } catch (const std::runtime_error &e){
+      throw std::runtime_error(std::string("Couldn't get threshold type "
+            "while") + " reading folder: " + folderName + ". Reason: "
+          + e.what() );
+    }
+    // Check if holden information dependency information is ok:
+    if ( fileEtaDep != etaDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtaDep) + " whereas Wrapper is " + toStr(static_cast<EtaDependency>(etaDependency)) + ".");
+    }
+    if ( fileEtDep != etDependency ){
+      throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
+          + toStr(fileEtDep) + " whereas Wrapper is " + toStr(static_cast<EtDependency>(etDependency)) + ".");
+    }
+    // Retrieve position indexes where we shall retrieve this pre-processing 
+    IOHelperFcns::getIdxVecFromStr( folderName, thresIdxVec );
+
+    // Check if everything is ok on indexes retrived:
+    if ( thresIdxVec.size() < 2 ||
+        thresIdxVec[0] >= thresEtDepSize  ||
+        thresIdxVec[1] >= thresEtaDepSize )
+    {
+      throw std::runtime_error(std::string("There is something wrong with ")
+            + "folder idxStr: " + folderName + ". Got idxStr " + 
+            IOHelperFcns::makeIdxStr(thresIdxVec) + ". Maximum threshold "
+            "collection size is : " + std::to_string(thresEtDepSize) + "," 
+            + std::to_string(thresEtaDepSize));
+    }
+
+    // Get a reference to the pointer (only used to reduce typing):
+    procedure_t *&thisThres = thresCol[thresIdxVec[0]]
+                                      [thresIdxVec[1]];
+
+    // Check which procedure_t this pre-processing wrapper holds. 
+    if ( Ringer::is_same<procedure_t, IThresholdVarDep >::value )
+    {
+      // If the procedure_t is not the PreProcessor interface, code will
+      // never get here. We only use the interpret cast so that the compiler
+      // doesn't complain about type casting.
+      thisThres = reinterpret_cast<procedure_t*>( getThres(thresType, dirObj) );
+      // FIXME New compiler version complains to use static_cast, but would it compile on
+      // older versions?
+    } else {
+      // Here it's easier, we already know the type that is written in the file,
+      // so all we need to do is loop over it and retrieve the discriminator.
+      thresEnum_t wrapperThresType = procedure_t::template procType<thresEnum_t>();
+      if ( thresType != wrapperThresType ){
+        throw std::runtime_error( std::string("There is a pre-processing of type ") +
+            toStr(thresType) + " whereas this wrapper can only hold pre-processings " 
+            "of type " + toStr(wrapperThresType));
+      }
+      thisThres = procedure_t::read( dirObj );
+    }
+    // ATH_MSG_VERBOSE("Successfully read directory " << folderName);
+  }
+
+  // Create and return PreProcessors wrapper:
+  return new RingerProcedureWrapper(thresCol);
+
+}
+
+} // Namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERTHRESHOLDWRAPPER_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.h
new file mode 100644
index 0000000000000000000000000000000000000000..ecec51676cc0c94cee8a5dc46c9f57caec3303dd
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.h
@@ -0,0 +1,99 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Thresholds.h 694257 2015-09-10 22:45:27Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_H
+#define RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_H
+
+//#undef NDEBUG
+
+// STL includes:
+#include <vector>
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+
+// Local tools:
+#include "RingerSelectorTools/tools/RingerIOVarDepObj.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/** 
+ * @brief Namespace dedicated for Ringer Discrimination utilities 
+ **/
+namespace Discrimination {
+
+/// Threshold interfaces
+/// @{
+class UniqueThreshold : virtual public IThreshold,
+                          public RedirectMsgStream
+{
+
+  RINGER_IO_VARDEP_BASE(UniqueThreshold)
+
+  private:
+    float m_threshold;
+  protected:
+    UniqueThreshold(const float threshold):m_threshold(threshold){;}
+  public:
+
+    UniqueThreshold():
+      m_threshold(0){;}
+
+    /** Execute threshold */
+    virtual void execute(const std::vector<float> &input,
+        std::vector<bool> &output) const ATH_RINGER_OVERRIDE ATH_RINGER_FINAL;
+
+    /** Ensure virtual dtor */
+    virtual ~UniqueThreshold(){;}
+    /** Define it as a Root TObjebt, disable I/O */
+    //ClassDef(UniqueThreshold,0)
+};
+
+RINGER_DEFINE_PROCEDURE_DEFAULT_METHODS( UniqueThreshold )
+
+/// @}
+
+
+/**
+ * @brief Unique threshold
+ **/
+class UniqueThresholdVarDep : virtual public IThresholdVarDep,
+                              public RingerIOVarDepObj < UniqueThresholdVarDep >,
+                              public UniqueThreshold
+{
+  RINGER_IO_VARDEP_OBJ(UniqueThresholdVarDep, UniqueThreshold)
+  public:
+
+    /** Default ctor (needed by ClassDef) */
+    UniqueThresholdVarDep(){;}
+
+    /** Obj ctor */
+    UniqueThresholdVarDep(const float threshold):
+      UniqueThreshold(threshold){;}
+
+    /** Ensure virtual dtor */
+    virtual ~UniqueThresholdVarDep(){;}
+
+    /** Define it as a Root TObjebt, set version 1 */
+    //ClassDef(UniqueThresholdVarDep,1)
+};
+
+} // namespace Discrimination
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "Thresholds.icc"
+#endif // INCLUDE_HEADER_ONLY
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.icc
new file mode 100644
index 0000000000000000000000000000000000000000..066183aa581c64042a013e2b8a57177f6d4c66a5
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Thresholds.icc
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Thresholds.icc 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_ICC
+#define RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_ICC
+
+#include "Thresholds.h"
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/** 
+ * @brief Namespace dedicated for Ringer Discrimination utilities 
+ **/
+namespace Discrimination {
+
+// =============================================================================
+inline
+void UniqueThreshold::execute(const std::vector<float> &input,
+    std::vector<bool> &output) const 
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying UniqueThreshold (Value: " << m_threshold 
+      << "). Output space is: " << input);
+#endif
+  output.clear();
+  if ( input.empty() ) {
+    throw std::runtime_error(
+        std::string("Entered UniqueDimThreshold.execute" 
+          " with input.size() == 0"));
+  }
+  output.push_back( input[0] > m_threshold );
+#ifndef NDEBUG
+  std::ios_base::fmtflags flags = std::cout.flags();
+  ATH_MSG_DEBUG("Decision is: " << output);
+  // reset previous cout flags
+  std::cout.flags(flags);
+#endif
+}
+
+} // namespace Discrimination
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_PROCEDURES_THRESHOLDS_ICC
+
+// vim: filetype=cpp :
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Types.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Types.h
new file mode 100644
index 0000000000000000000000000000000000000000..6054ef8210bd6d5ec422704fa9d6bfb9e2229fa0
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/procedures/Types.h
@@ -0,0 +1,113 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Types.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef  RINGERSELECTORTOOLS_TOOLS_PROCEDURES_TYPES_H
+#define  RINGERSELECTORTOOLS_TOOLS_PROCEDURES_TYPES_H
+
+// STL includes:
+#include <string>
+#include <stdexcept>
+
+/**
+ *
+ * WARNING: Do not change the order of the enumerations for backward files
+ * compatibility!!
+ *
+ * This means that if a new value is needed, add it to the end of the
+ * enumeration, instead adding it to any place in the enumeration.
+ *
+ * Every time a Ringer Procedure is created, it is needed to add it in this
+ * file: this is necessary to IO. Otherwise it won't even compile.
+ *
+ * After adding a enumeration type, also add it to the methods in the
+ * Types.cxx file.
+ *
+ **/
+
+namespace Ringer {
+
+namespace PreProcessing {
+namespace Type {
+
+enum PreProcessorTypes {
+  IPreProcessorVarDep,
+  IPreProcessor,
+  Norm1,
+  Norm2,
+  Sqrt,
+  ConstantValue,
+  Sequential,
+  Spherization,
+  MinMax
+};
+} // namespace Type
+} // namespace PreProcessing
+
+namespace Discrimination {
+namespace Type {
+
+enum DiscriminatorTypes {
+  IDiscriminatorVarDep,
+  IDiscriminator,
+  NNFeedForward
+};
+
+enum ThresholdTypes {
+  IThresholdVarDep,
+  IThreshold,
+  UniqueThreshold
+};
+} // namespace Type
+} // namespace Discrimination
+
+// We are at Ringer namespace again
+
+typedef PreProcessing::Type::PreProcessorTypes preProcEnum_t;
+typedef Discrimination::Type::DiscriminatorTypes discrEnum_t;
+typedef Discrimination::Type::ThresholdTypes thresEnum_t;
+
+/**
+ * Return Ringer enumeration of type T identifying string type:
+ **/
+template<typename T>
+T getType(const char* cStr);
+
+/**
+ * Specialization for PreProcessorTypes:
+ **/
+template<>
+preProcEnum_t getType(const char* cStr);
+
+/**
+ * Specialization for DiscriminatorTypes:
+ **/
+template<>
+discrEnum_t getType(const char* cStr);
+
+/**
+ * Specialization for ThresholdTypes:
+ **/
+template<>
+thresEnum_t getType(const char* cStr);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(preProcEnum_t e);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(discrEnum_t e);
+
+/**
+ * Transform enumeration types to string
+ **/
+const char* toStr(thresEnum_t t);
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_PROCEDURES_TYPES_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/selection.xml b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..036e6a829f796ce7377e3376f5c6c9d6c5d57318
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/selection.xml
@@ -0,0 +1,71 @@
+<lcgdict>
+
+  <!-- Needed for adding logging capabilities on python (?)-->
+  <!-- Redirect MsgStream dictionary: -->
+  <!--
+  <class name="Ringer::RedirectMsgStream">
+    <field name="m_msg" transient="true" />
+  </class>
+  -->
+
+  <class class="Ringer::VariableDependency" />
+
+  <!-- The multi-tool and some configurables -->
+  <class name="Ringer::AsgElectronRingerSelector" />
+  <class pattern="Ringer::ElectronTAccept*" />
+  <class pattern="Ringer::BitdefElectron*" />
+
+  <!-- The procedures -->
+  <class name="Ringer::PreProcessing::Norm::Norm1VarDep" />
+  <class name="Ringer::Discrimination::NNFeedForwardVarDep" />
+  <class name="Ringer::Discrimination::UniqueThresholdVarDep" />
+
+  <!-- The wrapper templates -->
+  <class name="Ringer::IPreProcWrapper" />
+  <class name="Ringer::IPreProcWrapperCollection" />
+  <class name="Ringer::IDiscrWrapper" />
+  <class name="Ringer::IDiscrWrapperCollection" />
+  <class name="Ringer::IThresWrapper" />
+  <class pattern="Ringer::RingerProcedureWrapper<*" />
+  <!-- Include the templated Ringer vectors-->
+  <class pattern="std::vector<Ringer::*" />
+  <class pattern="std::vector<std::vector<Ringer::*" />
+
+  <!-- Add every enum/fnc within Ringer namespace -->
+  <enum pattern="Ringer::*"/>
+  <function pattern="Ringer::*"/>
+
+  <!-- <class pattern="Ringer::*" /> -->
+
+  <!-- Remove extra Root catch-ups by above patterns that we dont want -->
+  <exclusion>
+    <class pattern="*ROOTDict::*" />
+    <class pattern="*boost_static_assert_typedef*" />
+    <class pattern="Ringer::is_base_of*" />
+    <class pattern="Ringer::is_same*" />
+    <enum  name="Ringer::CalJointSection" />
+    <enum  name="Ringer::CalJointLayer" />
+    <function pattern="Ringer::PreProcessing*"/>
+    <function pattern="Ringer::WrapperHelperFcns*"/>
+    <class pattern="*bitMskWord*" />
+  </exclusion>
+
+  <!--
+  <class name="std::vector<long long>"/>
+  <class name="std::vector<unsigned long long>"/>
+  <class name="std::vector<unsigned long>"/>
+  <class name="std::vector<Ringer::EtaDependency>"/>
+  -->
+
+  <!-- Pool read xAOD::CaloRings_v1  -->
+  <!-- Take a look at https://root.cern.ch/root/html532/io/DataModelEvolution.html
+  <read sourceClass="xAOD::CaloRings_v1" version="[1-]"
+    targetClass="xAOD::CaloRings_v1" source="" 
+    target="m_isRingSetCached" >
+    <![CDATA[
+    m_isRingSetCached = false;
+    ]]>
+  </read>
+  -->
+
+</lcgdict>
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/DeclareBit.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/DeclareBit.h
new file mode 100644
index 0000000000000000000000000000000000000000..a031f6c30f5ea33732eb2e5cce353b7090490241
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/DeclareBit.h
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: DeclareBit.h 693573 2015-09-07 19:15:49Z wsfreund $
+#ifndef RINGER_STANDALONE
+
+#ifndef RINGERSELECTORTOOLS_TOOLS_DECLARE_BIT_H
+#define RINGERSELECTORTOOLS_TOOLS_DECLARE_BIT_H
+
+#include <utility>
+
+#include "RingerSelectorTools/tools/cxx/StaticAssert.h"
+#include "RingerSelectorTools/tools/cxx/stringify.h"
+
+/**
+ * @brief Static counter.
+ *
+ * Made by David Krauss, used with author concent. 
+ *
+ * Counts up to 64, taken from http://stackoverflow.com/a/6174263/1162884
+ **/
+/// @{
+#define COUNTER_READ_CRUMB( TAG, RANK, ACC )                                   \
+  counter_crumb( TAG(), constant_index< RANK >(), constant_index< ACC >() )
+
+#define COUNTER_READ( TAG )                                                    \
+  COUNTER_READ_CRUMB( TAG, 1,                                                  \
+  COUNTER_READ_CRUMB( TAG, 2,                                                  \
+  COUNTER_READ_CRUMB( TAG, 4,                                                  \
+  COUNTER_READ_CRUMB( TAG, 8,                                                  \
+  COUNTER_READ_CRUMB( TAG, 16,                                                 \
+  COUNTER_READ_CRUMB( TAG, 32,                                                 \
+  COUNTER_READ_CRUMB( TAG, 64, 0 ) ) ) ) ) ) )
+ 
+/**
+ * Increment tagged macro
+ **/
+#define COUNTER_INC( TAG )                                                     \
+constant_index< COUNTER_READ( TAG ) + 1 >                                      \
+constexpr counter_crumb( TAG,                                                  \
+  constant_index< ( COUNTER_READ( TAG ) + 1 ) & ~ COUNTER_READ( TAG ) >,       \
+  constant_index< ( COUNTER_READ( TAG ) + 1 ) & COUNTER_READ( TAG ) > )        \
+{                                                                              \
+  return {};                                                                   \
+}
+
+template< std::size_t n >
+struct constant_index : std::integral_constant< std::size_t, n > {};
+
+// =============================================================================
+template< typename id, std::size_t rank, std::size_t acc >
+constexpr constant_index< acc > counter_crumb( id,
+    constant_index< rank >,
+    constant_index< acc > )
+{
+  return {};
+} /* found by ADL via constant_index */
+
+/**
+ * Define counter which will be used by counter_read and counter_inc macros
+ **/
+#define DEFINE_COUNTER( counter )                                             \
+struct counter {};
+ 
+/**
+ * Makes counter_crumb fcn available at the namespace.
+ **/
+#define COUNTER_LINK_NAMESPACE using ::counter_crumb;
+/// @}
+
+/**
+ * This macro is used to declare a TAccept bit with name and decription.
+ * The fourth parameter is a static counter defined using above macros.
+ * Make sure to make the namespace linked with the counter fcn by using
+ * COUNTER_LINK_NAMESPACE inside the namespace.
+ **/
+#define DECLARE_BIT( bitmask, name, description, bit_counter)                 \
+  const int Ringer::bitmask::name =                                           \
+    Ringer::bitmask::declareBit(                                              \
+      #name,                                                                  \
+      description                                                             \
+    );                                                                        \
+                                                                              \
+  RINGER_STATIC_ASSERT( ( COUNTER_READ( bit_counter ) <= 32),                 \
+      "Bit " STRINGIFY(name) " couldn't be added to bitmask "                 \
+      STRINGIFY(bitmask) ": " STRINGIFY(bitmask)                              \
+      " ran out of bits!!");                                                  \
+                                                                              \
+  COUNTER_INC( bit_counter )
+  
+#endif // RINGERSELECTORTOOLS_TOOLS_DECLARE_BIT_H
+
+#endif // RINGER_STANDALONE
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/Exceptions.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/Exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1398773e00b8d121fab4796288350dbd5a3b851
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/Exceptions.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Exceptions.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_EXCEPTIONS_H
+#define RINGERSELECTORTOOLS_TOOLS_EXCEPTIONS_H
+
+// STL includes:
+#include <stdexcept>
+#include <string>
+
+#ifndef INCLUDE_HEADER_ONLY
+#define INCLUDE_HEADER_ONLY // Avoid circular includes
+#endif
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/procedures/Types.h"
+#undef INCLUDE_HEADER_ONLY
+
+namespace Ringer {
+
+namespace Exceptions {
+
+/**
+ * Exception telling user to implement type on this file
+ **/
+class no_such_type : public std::runtime_error {
+  public:
+
+    no_such_type(const char* scope, std::string type = "",
+        std::string file = ""):
+      std::runtime_error(std::string("Could not recognize ") +
+          scope + " :" + type + ". If it should be "
+        "available, add it to file " + file){;}
+
+    no_such_type(preProcEnum_t p,
+        std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "PreProcessorTypes(") + std::to_string(int(p)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+
+    no_such_type(discrEnum_t d,
+        std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "DiscriminatorTypes(") + std::to_string(int(d)) +
+            "). Make sure to add it to file " + file + " and also " 
+            "add it to getType and toStr functions."){;}
+
+    no_such_type(thresEnum_t t,
+        std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "ThresholdTypes(") + std::to_string(int(t)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+
+    no_such_type(SegmentationType e, std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "EtaDependency(") + std::to_string(int(e)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+
+    no_such_type(EtaDependency e, std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "EtaDependency(") + std::to_string(int(e)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+
+    no_such_type(EtDependency e, std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "EtDependency(") + std::to_string(int(e)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+
+    no_such_type(Requirement e, std::string file = ""):
+      std::runtime_error(std::string("Could not recognize "
+            "Requirement(") + std::to_string(int(e)) +
+            "). Make sure to add it to file " + file + 
+            " and also add it to getType and toStr functions."){;}
+};
+
+} // namespace Exceptions
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_EXCEPTIONS_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe9617d0a5c38c3ac3e88c17bbebd42f57cd955d
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.h
@@ -0,0 +1,171 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IOHelperFcns.h 679254 2015-06-30 12:54:50Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_H
+#define RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_H
+
+// STL includes:
+#include <stdexcept>
+#include <string>
+#include <memory>
+
+// ROOT includes:
+#include <TFile.h>
+#include <TList.h>
+#include <THashList.h>
+
+#ifndef INCLUDE_HEADER_ONLY // Avoid circular includes
+#define INCLUDE_HEADER_ONLY
+#endif
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#undef INCLUDE_HEADER_ONLY
+
+namespace Ringer {
+
+namespace IOHelperFcns {
+
+/**
+ * @brief Set varDest to varName key pointer inside TDirectory dir
+ **/
+template <typename ReadingType, typename WrittenType = ReadingType >
+void readVar(TDirectory* dir, const char* varName, ReadingType& varDest);
+
+/**
+ * @brief Write var with name varName at directory dir, raises otherwise.
+ *
+ * It cannot write non-scalar C objects, such as float[] and so on. Use
+ * std::vector<> otherwise. It also needs the root dictionary available 
+ * for the type being writen. Some std::vector types available are:
+ *
+ * std::vector<float>
+ * std::vector<double>
+ * std::vector<unsigned int>
+ *
+ * But their long counterparts seem not possible to be written. 
+ *
+ * For enumeration types, convert them into integers and when reading, convert
+ * them back, i.e.:
+ *
+ * --- Writing ---
+ * EtaDependency etaDependency = EtaIndependent;
+ * writeVar< EtaDependecy, unsigned int>(dir, "etaDep", etaDependency);
+ *
+ * --- Reading ---
+ * EtaDependency etaDependency;
+ * readVar< EtaDependency, unsigned int>(dir, "etaDep", etaDependency);
+ **/
+template <typename InputType, typename WrittenType = InputType >
+void writeVar(TDirectory* dir, const char* varName, InputType& var);
+
+/**
+ * @brief Make index string from index
+ *
+ * If vector contains indexes [1], for instance, then returning string will
+ * be "@(1)".
+ *
+ **/
+std::string makeIdxStr(unsigned int idxV);
+
+/**
+ * @brief Make index string from index vector
+ *
+ * If vector contains indexes [1,2], for instance, then returning string will
+ * be "@(1,2)".
+ *
+ **/
+std::string makeIdxStr(std::vector<unsigned int> &idxV);
+
+/**
+ * @brief Fill vector with indexes contained in string made with makeIdxStr.
+ *
+ * Throws runtime_error if string does not contains string formated as created
+ * by makeIdxStr or if it cannot retrieve n-th index.
+ **/
+void getIdxVecFromStr(const char* cstr, std::vector<unsigned int> &n);
+
+/**
+ * @brief Get n-th index from string containing makeIdxStr.
+ *
+ * Throws runtime_error if string does not contains string formated as created
+ * by makeIdxStr or if it cannot retrieve n-th index.
+ **/
+unsigned int getIdxFromStr(const char* cstr, unsigned int n);
+
+/**
+ * @brief Returns package version as unsigned
+ *
+ * Remove package name and '-' from string, keep only package version
+ * as RingerSelectorTools-10-11-12 would lead into version 101112.
+ *
+ * NOTE: This means that a package cannot have any version number higher
+ * than 99.
+ **/
+unsigned version();
+
+/**
+ * @brief Check if cStr starts with string cStrStart.
+ **/
+bool startsWith(const char *cStrStart, const char *cStr);
+
+/**
+ * @brief Check if TFile is correctly opened.
+ **/
+void checkFile(const TFile& file);
+
+/**
+ * @brief Check if TFile is exists.
+ **/
+bool fileExist(const char* fileName);
+
+/**
+ * @brief Delete file
+ **/
+int deleteFile(const char* fileName);
+
+/**
+ * @brief Check if directory is not pointing into void.
+ *
+ * Throws runtime_error otherwise error occurred
+ **/
+void checkDir(TDirectory* baseDir);
+
+/**
+ * @brief Write package version to directory
+ **/
+void writeVersion(TDirectory* dir);
+
+/**
+ * @brief Creates directory in baseDir with given name.
+ *
+ * Throws runtime_error if error occurred. It also adds to created directory 
+ * the package version in which it was created. This can be written using the
+ * getWrittenVersion function.
+ **/
+TDirectory *makeDir(TDirectory* baseDir, const char *name);
+
+/**
+ * @brief Retrieve TList with directories on directory dir.
+ **/
+std::shared_ptr<THashList> getDirList(TDirectory* dir);
+
+/**
+ * @brief Gets package written version
+ *
+ * It returns the package version in which this directory was written,
+ * otherwise it throws runtime_error.
+ *
+ **/
+unsigned getWrittenVersion(TDirectory *configDir);
+
+} // namespace IOHelperFcns
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "IOHelperFcns.icc"
+#endif // INCLUDE_HEADER_ONLY
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.icc
new file mode 100644
index 0000000000000000000000000000000000000000..2690e4360077548ae2f3246a88e33d289fd216ce
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IOHelperFcns.icc
@@ -0,0 +1,109 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IOHelperFcns.icc 694257 2015-09-10 22:45:27Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_ICC
+#define RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_ICC
+
+// STL includes:
+#include <vector>
+#include <stdexcept>
+#include <string>
+#include <iostream>
+
+// ROOT includes:
+#include <TFile.h>
+#include <TError.h>
+
+// Local includes:
+#include "IOHelperFcns.h"
+#include "RingerSelectorTools/tools/cxx/remove_cv.h"
+#include "RingerSelectorTools/tools/cxx/decay.h"
+
+namespace Ringer {
+
+namespace IOHelperFcns {
+
+// =============================================================================
+template <typename ReadingType, typename WrittenType >
+void readVar(TDirectory* dir, const char* varName, ReadingType& varDest) 
+{
+
+  checkDir(dir);
+
+  if ( dir->FindObjectAny( varName ) != nullptr ) {
+    WrittenType* reader = nullptr;
+    dir->GetObject( varName, reader );
+    if ( reader != nullptr ){
+      // Make raw copy to varDest
+      varDest = static_cast<ReadingType>(*reader);
+    } else {
+      throw std::runtime_error(std::string("Retrieved null pointer while ") +
+          "trying to read " + varName + " at directory named " +
+          dir->GetName() + ".");
+    }
+  } else if ( dir->FindObjectAny( (std::string(varName) + "__Vec__").c_str() ) 
+      != nullptr )
+  {
+    // Remove constant and reference types
+    std::vector< typename Ringer::decay< 
+                 typename Ringer::remove_cv<WrittenType>::type >::type 
+                 >* reader = nullptr;
+    dir->GetObject( (std::string(varName) + "__Vec__" ).c_str(), reader );
+    if ( reader != nullptr ){
+      if ( reader->size() != 1 ){
+        throw std::runtime_error(std::string("Seems that the variable was saved using "
+              "the std::vector type. However, its size is different from 1, "
+              "which indicates that something went wrong."));
+      }
+      // Make raw copy to varDest
+      varDest = static_cast<ReadingType>((*reader)[0]);
+    } else {
+      throw std::runtime_error(std::string("Retrieved null pointer while ") +
+          "trying to read " + varName + "__Vec__ at directory named " +
+          dir->GetName() + ".");
+    }
+  } else {
+    throw std::runtime_error( std::string("Cannot find ") + 
+        varName + " at directory named " +
+        dir->GetName() + "." );
+  }
+}
+
+// =============================================================================
+template <typename InputType, typename WrittenType >
+void writeVar(TDirectory* dir, const char* varName, InputType& var) 
+{
+  // This workaround is just because gcc seems not to be able of creating
+  // std::vector<const type>, so we remove const and reference types.
+  typedef typename Ringer::decay<
+          typename Ringer::remove_cv<WrittenType>::type 
+          >::type NonConstWrittenType;
+  // Create the non constant variable to write:
+  NonConstWrittenType &writtenVar = const_cast<NonConstWrittenType&>(
+                                    static_cast<WrittenType&>(var));
+  // Check if directory is in good status
+  checkDir(dir);
+  Int_t prevMessageLevel = gErrorIgnoreLevel;
+  gErrorIgnoreLevel = kBreak;
+  // Try to write variable directly:
+  if ( !dir->WriteObject( &writtenVar, varName ) ){
+    gErrorIgnoreLevel = prevMessageLevel;
+    // It didn't work, so attempt to write it using std::vector
+    std::vector< NonConstWrittenType > vec(1, writtenVar);
+    if ( !dir->WriteObject( &vec, (std::string(varName) + "__Vec__").c_str() ) )
+    {
+      dir->ls();
+      throw std::runtime_error(std::string("Couldn't write variable ") + 
+          varName );
+    }
+  }
+  gErrorIgnoreLevel = prevMessageLevel;
+}
+
+} // namespace IOHelperFcns
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_IOHELPERFCNS_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IRedirectMsgStream.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IRedirectMsgStream.h
new file mode 100644
index 0000000000000000000000000000000000000000..65a1ec01ca5cf934daff1b96c310a92f26dbe4f9
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/IRedirectMsgStream.h
@@ -0,0 +1,163 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IRedirectMsgStream.h 693573 2015-09-07 19:15:49Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_IREDIRECTMSGSTREAM_H
+#define RINGERSELECTORTOOLS_TOOLS_IREDIRECTMSGSTREAM_H
+
+// We make these declarations here because we can't forward declare enums
+// without C++11 enum class.
+#if !defined(RINGER_STANDALONE)
+// Asg includes:
+# include "AsgTools/MsgStream.h"
+# include "AsgTools/MsgStreamMacros.h"
+# include "xAODCaloRings/tools/PrintHelperFcns.h"
+//#pragma message "ASGTOOL or ASGTOOL_STANDALONE"
+#else
+# include <iostream>
+typedef std::ostream MsgStream;
+namespace MSG {
+
+  // Keep it simple
+  // FIXME This needs to be tested
+  enum Level { 
+    NIL = 0,
+    VERBOSE,
+    DEBUG,
+    INFO,
+    WARNING,
+    ERROR,
+    FATAL,
+    ALWAYS,
+    NUM_LEVELS
+  }
+
+  /**
+   * This is just a workaround for simulating the MsgStream when on standalone
+   * environment.
+   **/
+  static Level currentLevel = INFO;
+
+  /**
+   * Display message level:
+   **/
+  std::ostream& operator<<(std::ostream &stream, const Level lvl){
+    switch (lvl){
+      case VERBOSE:
+        return stream << "VERBOSE:  ";
+        break;
+      case DEBUG:
+        return stream << "DEBUG:    ";
+        break;
+      case INFO:
+        return stream << "INFO:     ";
+        break;
+      case WARNING:
+        return stream << "WARNING:  ";
+        break;
+      case ERROR:
+        return stream << "ERROR:    ";
+        break;
+      case FATAL:
+        return stream << "FATAL:    ";
+        break;
+      otherwise:
+        return stream;
+    }
+  }
+}
+
+# define ATH_MSG_LVL( lvl, xmsg)                                               \
+  do {                                                                         \
+    if ( msgLvl(lvl) ) {                                                       \
+      msg(lvl) << xmsg << std::endl;                                           \
+    }                                                                          \
+  } while( 0 )
+  
+# define ATH_MSG_VERBOSE(xmsg)                                                 \
+  ATH_MSG_LVL( MSG::VERBOSE, xmsg )
+
+# define ATH_MSG_DEBUG(xmsg)                                                   \
+  ATH_MSG_LVL( MSG::DEBUG, xmsg )
+
+# define ATH_MSG_INFO(xmsg)                                                    \
+  ATH_MSG_LVL( MSG::INFO, xmsg )
+
+# define ATH_MSG_WARNING(xmsg)                                                 \
+  ATH_MSG_LVL( MSG::WARNING, xmsg )
+
+# define ATH_MSG_ERROR(xmsg)                                                   \
+  ATH_MSG_LVL( MSG::ERROR, xmsg )
+
+# define ATH_MSG_FATAL(xmsg)                                                   \
+  ATH_MSG_LVL( MSG::FATAL, xmsg )
+
+#define ATH_MSG_LVL_DISP_VAR( lvl, var)                                        \
+  do {                                                                         \
+    if ( msgLvl(lvl) ) {                                                       \
+      msg << #var << ":" << var << endl;                                       \
+    }                                                                          \
+  } while (0)
+
+// =============================================================================
+/// Helper operator for printing the contents of vectors (ostream)
+template <typename T>
+std::ostream& operator<< ( std::ostream& out, const std::vector< T >& vec )
+{
+  // A little prefix:
+  out << "[";
+  // Print the contents:
+  for( size_t i = 0; i < vec.size(); ++i ) {
+     out << vec[ i ];
+     if( i < vec.size() - 1 ) {
+        out << ", ";
+     }
+  }
+  // A little postfix:
+  out << "]";
+  // Return the stream:
+  return out;
+}
+
+// =============================================================================
+/// Helper operator for printing the contents of vector pointers (ostream)
+template <typename T>
+std::ostream& operator<< ( std::ostream& out, const std::vector< T >* vec)      
+{
+  return out.operator<<(*vec);
+}
+#endif // Environment selection
+
+namespace Ringer {
+/**
+ * @class IRedirectMsgStream
+ * @brief Interface for RedirectMsgStream
+ **/
+class IRedirectMsgStream {
+  public:
+    /// Methods:
+    /// @{
+    /// Check whether stream is available
+    virtual bool isStreamAvailable() const = 0;
+
+    /// Returns MsgSteam with its current level
+    virtual MsgStream& msg() const = 0;
+
+    /// Returns MsgSteam with its current level
+    /// It is const member function because m_msg member will be mutable
+    virtual void setMsgStream(MsgStream *msg) const = 0;
+
+    /// Set msg level
+    virtual bool msgLvl(MSG::Level level) const = 0;
+    /// Returns m_msg, otherwise returns
+    virtual MsgStream& msg(MSG::Level level) const = 0;
+
+    virtual ~IRedirectMsgStream(){;}
+    /// @}
+};
+
+} // namespace Ringer
+
+
+#endif // RINGERSELECTORTOOLS_TOOLS_IREDIRECTMSGSTREAM_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RedirectMsgStream.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RedirectMsgStream.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b3fe5617627a00a95ce1ae86e230cd8628ce335
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RedirectMsgStream.h
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RedirectMsgStream.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_REDIRECTMSGSTREAM_H
+#define RINGERSELECTORTOOLS_TOOLS_REDIRECTMSGSTREAM_H
+
+#include <string>
+#include <stdexcept>
+
+// Local includes:
+#include "RingerSelectorTools/tools/IRedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/mutable.h"
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+
+namespace Ringer {
+/**
+ * @class RedirectMsgStream
+ * @brief Redirect Msg Stream to calling AsgSelector
+ *
+ *  We do this so that we can display messages as if we were AsgSelector 
+ * with our algorithms.
+ *
+ *  If we are not running using a AsgSelector, use ostream otherwise.
+ **/
+class RedirectMsgStream : virtual public IRedirectMsgStream {
+  public:
+    /// Methods:
+    /// @{
+    /// Check whether stream is available
+    bool isStreamAvailable() const {
+      return m_msg != nullptr;
+    }
+
+    /// Returns MsgSteam with its current level
+    void setMsgStream(MsgStream *msg) const {
+#if RINGER_USE_NEW_CPP_FEATURES
+      m_msg = msg;
+#else
+      const_cast<RedirectMsgStream*>(this)->m_msg = msg;
+#endif
+    }
+    /// Check if message level is enabled
+    bool msgLvl(MSG::Level level) const { 
+#if !defined(RINGER_STANDALONE)
+      if ( isStreamAvailable() ) {
+        return m_msg->level() <= level; 
+      }
+      return false;
+#else
+      return MSG::currentLevel <= level;
+#endif
+    }
+
+    /// Get msg level
+    MSG::Level level() const {
+#if !defined(RINGER_STANDALONE)
+      if ( isStreamAvailable() )
+        return m_msg->level();
+      else 
+        throw std::runtime_error(std::string("Stream not available"));
+#else
+      return MSG::currentLevel;
+#endif
+    }
+
+  protected:
+    /// Ctors:
+    /// @{
+    /**
+     * @brief Redirects output as if it run by Asg selector. 
+     *
+     *   When no MsgStream available, build one if on Asg environment,
+     * otherwise use std::cout.
+     **/ 
+    RedirectMsgStream(MsgStream *msg):
+      m_msg(msg){;}
+    /**
+     * @brief Redirects output as if it run by Asg selector. 
+     *
+     *   When no MsgStream available, build one if on Asg environment,
+     * otherwise use std::cout.
+     **/ 
+    RedirectMsgStream():
+      m_msg(nullptr){;}
+    /// @}
+    ~RedirectMsgStream(){;}
+
+    /// Properties:
+    /// @{
+    /// The re-directed message stream from AsgSelector
+    ATH_RINGER_MUTABLE MsgStream *m_msg;
+    /// @}
+
+#if !defined(RINGER_STANDALONE)
+    /// Returns MsgSteam with its current level
+    MsgStream& msg() const { 
+      if ( isStreamAvailable() ) {
+        return (*m_msg); 
+      } else {
+        throw std::runtime_error(std::string(
+              "Cannot display message, MsgStream not set."
+              " Make sure to use setMsgStream(MsgStream*) method."));
+      }
+    }
+
+    /// Returns MsgStream and set its level
+    MsgStream& msg(MSG::Level level) const { 
+      if ( isStreamAvailable() ) {
+#if !defined(XAOD_ANALYSIS) && !defined(XAOD_STANDALONE)
+        return m_msg->report(level);
+#else
+        return (*m_msg) << level;
+#endif
+      } else {
+        throw std::runtime_error(std::string(
+              "Cannot display message, MsgStream not set."
+              " Make sure to use setMsgStream(MsgStream*) method."));
+      }
+    }
+
+#else
+    /// Returns MsgSteam with its current level
+    MsgStream& msg() const { 
+      if ( isStreamAvailable() ) {
+        return (*m_msg); 
+      } else {
+        return std::cout;
+      }
+    }
+
+    /// Returns m_msg, otherwise returns
+    MsgStream& msg(MSG::Level level) const { 
+      if ( isStreamAvailable() ) {
+        return (*m_msg) << level; 
+      } else {
+        return std::cout << level;
+      }
+    }
+#endif
+    /// @}
+
+};
+
+} // namespace Ringer
+
+#endif
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerCommonSelector.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerCommonSelector.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7e22c464aa7b48de04efb5e6872e57e70dc178b
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerCommonSelector.h
@@ -0,0 +1,118 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerCommonSelector.h 668868 2015-05-20 20:26:18Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_RINGERCOMMONSELECTOR_H
+#define RINGERSELECTORTOOLS_TOOLS_RINGERCOMMONSELECTOR_H
+
+// Local includes:
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.icc"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+
+// STL includes:
+#include <vector>
+
+// xAOD includes:
+#include "xAODCaloRings/CaloRingsFwd.h"
+#include "xAODTracking/TrackParticleFwd.h"
+
+// ROOT includes:
+#include "PATCore/TAccept.h"
+
+namespace Ringer {
+
+/**
+ *
+ * @class RingerCommonSelecto
+ *
+ **/ 
+class RingerCommonSelector : public RedirectMsgStream
+{
+
+  public:
+    /**
+     * @brief Main ctor
+     **/ 
+    RingerCommonSelector(
+      const Ringer::IDiscrWrapperCollection *discrWrapperCol,
+      const Ringer::IThresWrapper *thresWrapper,
+      Root::TAccept *partDecMsk,
+      const bool useTrackPat,
+      const bool useRawTrackPat,
+      const bool useCaloCommittee);
+    
+    /**
+     * @brief Clear output space representation
+     **/
+    void clear();
+
+    /**
+     * @brief Execute Ringer common selector
+     **/ 
+    StatusCode execute(
+        const DepVarStruct &depVar,
+        const xAOD::CaloRings* clRings,
+        const TrackPatternsHolder *trackPat);
+
+    /**
+     * @brief Get output space
+     **/
+    const std::vector<float> &getOutputSpace() const;
+
+  private:
+
+    /// Properties to be given by AsgSelector:
+    /// @{
+    const Ringer::IDiscrWrapperCollection *m_discrWrapperCol;
+    const Ringer::IThresWrapper *m_thresWrapper;
+    Root::TAccept *m_partDecMsk;
+    const bool m_useTrackPat;
+    const bool m_useRawTrackPat;
+    const bool m_useCaloCommittee;
+    /// @}
+
+    /// Local properties:
+    /// @{
+    /// Pointer to firlastst discrimination layer
+    const IDiscrWrapper *m_fstDiscrLayer;
+    /// Pointer to last discrimination layer
+    const IDiscrWrapper *m_lastDiscrLayer;
+    /// The discrimination wrapper collection size
+    size_t m_discrWrapperColSize;
+    /// Hold discriminators input
+    std::vector<float> m_input; 
+    /// Hold discriminators output
+    std::vector<float> m_output;
+    /// Hold decision
+    std::vector<bool> m_decVec;
+    /** 
+     * @brief Hold track discriminator output
+     *
+     * This vector will be used only in the following special occasion:
+     *   - It is wanted to feed the last classifier with the output from the track
+     *  classifier. In this case, we need 
+     **/ 
+    std::vector<float> m_trackDiscr_output;
+    /// Flag if discrimination approach is non segmented
+    bool m_nonSegmentedDiscr;
+    /// @}
+
+};
+
+//==============================================================================
+inline
+void RingerCommonSelector::clear(){
+  m_output.clear();
+}
+
+//==============================================================================
+inline
+const std::vector<float>& RingerCommonSelector::getOutputSpace() const {
+  return m_output;
+}
+
+} // namespace Ringer
+
+
+#endif // RINGERSELECTORTOOLS_TOOLS_RINGERCOMMONSELECTOR_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.h
new file mode 100644
index 0000000000000000000000000000000000000000..f81032c4eaa1518ee9dd5a3d06d23ad33af44715
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.h
@@ -0,0 +1,236 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerIOVarDepObj.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_H
+#define RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_H
+
+// STL includes:
+#include <string>
+
+// Root includes:
+#include <TFile.h>
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/cxx/StaticAssert.h"
+#include "RingerSelectorTools/tools/cxx/constexpr.h"
+#include "RingerSelectorTools/tools/cxx/is_base_of.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+#include "RingerSelectorTools/tools/cxx/mutable.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+
+/**
+ * @brief Create RingerIOVarDepObj base object prototype methods
+ *
+ * Every time you create a class that use this mechanism, make sure to add it
+ * to "RingerSelectorTools/procedures/Types.h"
+ *
+ *
+ * When you create a class that implements a RingerProcedure and it will be a
+ * writable object, then this object must have defined this macro and
+ * implement the read and write methods as:
+ *
+ * file NewProcedure.h:
+ * /code
+ * class NewProcedure: virtual public IDiscriminator
+ *                     // or virtual public IPreProcessor
+ *                     // or virtual public IThreshold
+ * {
+ *   // Given as example
+ *   float m_var;
+ *
+ *   RINGER_IO_VARDEP_BASE( NewProcedure )
+ *   // ...
+ * }
+ *
+ * RINGER_DEFINE_PROCTYPE_MEMBER_FCN( NewProcedure )
+ *
+ * } // namespace Ringer
+ * /endcode
+ *
+ * file NewProcedure.cxx
+ * /code
+ * namespace Ringer {
+ *
+ * void NewProcedure::read(NewProcedure* newObj,
+ *    TDirectory *configDir,
+ *    unsigned version )
+ * {
+ *   IOHelperFcns::readVar( configDir, "var",  newObj->m_var );
+ * }
+ *
+ * void NewProcedure::write(TDirectory *configDir) const
+ * {
+ *   IOHelperFcns::writeVar(configDir, "var",  m_var  );
+ * }
+ *
+ * void NewProcedure::print(MSG::Level lvl) const
+ * {
+ *   if ( !this->isStreamAvailable() ) {
+ *     std::cerr << "Cannot print NewProcedure, stream unavailable"
+ *       << std::endl;
+ *   }
+ *   if ( this->level() > lvl ) {
+ *     return;
+ *   }
+ *   msg() << lvl << this->name() << " configuration:" << endreq;
+ *   msg() << lvl << "var:" << m_var << endreq;
+ * }
+ *
+ * } // namespace Ringer
+ * /endcode
+ *
+ * If the procedure has no variable, it can use the
+ * RINGER_IO_VARDEP_BASE_NOMEMBER macro instead.
+ *
+ * The previous structure will need also to implement the VariableDependency
+ * class, which will inherit from the RingerIOVarDepObj using the
+ * RINGER_IO_VARDEP_OBJ macro described next.
+ *
+ * /code
+ * class NewProcedureVarDep : virtual public IDiscriminatorVarDep,
+ *                      public RingerIOVarDepObj<NewProcedureVarDep>,
+ *                      public NewProcedure
+ * {
+ *     RINGER_IO_VARDEP_OBJ(NewProcedureVarDep, NewProcedure)
+ *     // ...
+ * }
+ * /endcode
+ **/
+
+#define RINGER_IO_VARDEP_BASE(self)                                            \
+  public:                                                                      \
+                                                                               \
+    RINGER_DEFINE_PROCEDURE(self)                                              \
+                                                                               \
+    static void read(self *newObj,                                             \
+        TDirectory *configDir,                                                 \
+        unsigned version );                                                    \
+                                                                               \
+    virtual void write(TDirectory *configDir, const char* idxStr = "")         \
+      const ATH_RINGER_OVERRIDE;
+
+/**
+ * @brief Same as RINGER_IO_VARDEP_BASE, but when class has no member
+ **/
+#define RINGER_IO_VARDEP_BASE_NOMEMBER(self)                                   \
+  public:                                                                      \
+                                                                               \
+     RINGER_DEFINE_NOMEMBER_PROCEDURE(self)                                    \
+                                                                               \
+    static void read(self *,                                                   \
+        TDirectory *,                                                          \
+        unsigned ) {;}                                                         \
+                                                                               \
+    virtual void write(TDirectory *, const char*) const                        \
+      ATH_RINGER_OVERRIDE {;}
+
+/**
+ * @brief Add necessary information to RingerIOVarDepObj
+ *
+ * When declaring the new procedure variable dependent object, you will need to
+ * add this macro adding to add its base type where you used the
+ * RINGER_IO_VARDEP_BASE macro.
+ *
+ *
+ **/
+#define RINGER_IO_VARDEP_OBJ(self, base)                                       \
+                                                                               \
+  public:                                                                      \
+    typedef base base_t;                                                       \
+                                                                               \
+    using base::procType;                                                      \
+                                                                               \
+    virtual const char* name() const                                           \
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL                                     \
+    {                                                                          \
+      return this->RingerIOVarDepObj<self>::name();                            \
+    }                                                                          \
+                                                                               \
+    void print(MSG::Level lvl) const                                           \
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL                                     \
+    {                                                                          \
+      this->base_t::print(lvl);                                                \
+    }                                                                          \
+                                                                               \
+    virtual void write(TDirectory *baseDir, const char* idxStr = "") const     \
+      ATH_RINGER_OVERRIDE ATH_RINGER_FINAL                                     \
+    {                                                                          \
+      this->RingerIOVarDepObj<self>::write(baseDir, idxStr);                   \
+    }                                                                          \
+                                                                               \
+    static self* read(TDirectory *configDir){                                  \
+      return RingerIOVarDepObj<self>::read(configDir);                         \
+    }                                                                          \
+                                                                               \
+    typedef typename Ringer::template RingerProcedureType<base>::              \
+      baseInterface_t baseInterface_t;                                         \
+                                                                               \
+    using baseInterface_t::procType;
+
+namespace Ringer {
+
+/**
+ * @class RingerIOVarDepObj
+ * @brief Objects that can be recorded/read into/from configuration files.
+ *
+ * Use CRTP mechanism so that we can force static read method to be
+ * implemented.
+ *
+ * The CRTP class will automatically inherit from BaseProcedure and
+ * VariableDependency, the late using etaDependency and etDependency given
+ * values.
+ *
+ * It also implements the final version of the IRingerProcedure write pure
+ * virtual method, which will call both VariableDependency and
+ * the BaseProcedure write methods. It also make sure that the configuration
+ * directory written to Root will be named as:
+ *
+ * "BaseProcedure::type()[VariableDependency::type()]"
+ *
+ **/
+template < class CRTP  >
+class RingerIOVarDepObj : virtual public VariableDependency
+{
+
+  public:
+    /**
+     * Typedef to CRTP type:
+     **/
+    //typedef CRTP crtp_t;
+
+    // Make sure we initialize the variable dependency
+    RingerIOVarDepObj():VariableDependency(){;}
+    
+    /**
+     * Retrieve name for this RingerIOVarDepObj
+     **/
+    const char* name() const;
+
+    /**
+     * @brief Read Ringer procedure from configuration dir
+     **/
+    static CRTP* read(TDirectory *configDir);
+
+    /**
+     * @brief Write Ringer procedure to configuration directory
+     **/
+    void write(TDirectory *baseDir, const char* idxStr="")
+      const;
+
+  private:
+    ATH_RINGER_MUTABLE std::string m_name;
+
+};
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "RingerIOVarDepObj.icc"
+#endif // INCLUDE_HEADER_ONLY
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.icc
new file mode 100644
index 0000000000000000000000000000000000000000..df48ddd2448a69b7c810ffae32d8603930446a8c
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/RingerIOVarDepObj.icc
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerIOVarDepObj.icc 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_ICC
+#define RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_ICC
+
+// STL includes:
+#include <sstream>
+#include <cctype>
+
+// Root includes:
+#include <TFile.h>
+
+// Local includes:
+#include "RingerSelectorTools/tools/RingerIOVarDepObj.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.icc"
+
+namespace Ringer {
+
+// =============================================================================
+template < class CRTP >
+const char* RingerIOVarDepObj<CRTP>::name() const
+{
+  const_cast<std::string&>(m_name) = std::string(CRTP::base_t::procType()) +
+    this->VariableDependency::type();
+  return m_name.c_str();
+}
+
+// =============================================================================
+template < class CRTP >
+CRTP* RingerIOVarDepObj<CRTP>::read(TDirectory *configDir) 
+{
+  CRTP* crtp = new CRTP;
+  try {
+    unsigned v = IOHelperFcns::getWrittenVersion(configDir);
+    CRTP::base_t::read(crtp, configDir, v );
+    VariableDependency::read(crtp, configDir, v );
+    return crtp;
+  } catch ( const std::runtime_error &e){
+    std::cerr << "Couldn't read object of type " 
+      << CRTP::base_t::procType() 
+      << ". Reason: " << e.what() << std::endl;
+    delete crtp;
+    return nullptr;
+  }
+}
+
+// =============================================================================
+template < class CRTP >
+void RingerIOVarDepObj<CRTP>::write(TDirectory *baseDir, const char *idxStr)
+  const
+{
+  typedef typename CRTP::base_t base_t;
+  typedef typename RingerProcedureType<base_t>::procEnum_t
+    procEnum_t;
+  // Create directory where we will add all configurable information:
+  TDirectory* configDir = IOHelperFcns::makeDir( baseDir, 
+      (std::string(this->name()) + std::string(idxStr) ).c_str() );
+  // Write object version:
+  unsigned v = IOHelperFcns::version();
+  IOHelperFcns::writeVar( configDir, "writtenOnPkgVersion", v );
+  // Write object type:
+  procEnum_t procType = base_t::template procType<procEnum_t>();
+  IOHelperFcns::writeVar< const procEnum_t, const unsigned int>( configDir, 
+      "procType", 
+      procType );
+  // Now write BaseProcedure and VariableDependency information on it:
+  static_cast<const CRTP*>(this)->base_t::write(configDir, idxStr);
+  static_cast<const VariableDependency*>(this)->writeDepInfo(configDir);
+}
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_RINGERIOVARDEPOBJ_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/TrackPatternsHolder.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/TrackPatternsHolder.h
new file mode 100644
index 0000000000000000000000000000000000000000..57b1d02b36901844d65c1d6f30211d9e9d14e2df
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/TrackPatternsHolder.h
@@ -0,0 +1,220 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TrackPatternsHolder.h 689837 2015-08-17 17:22:12Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_TRACKPATTERNSHOLDER_H
+#define RINGERSELECTORTOOLS_TOOLS_TRACKPATTERNSHOLDER_H
+
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+
+// STL includes:
+#include <vector>
+#include <cstddef>
+#if RINGER_USE_NEW_CPP_FEATURES
+#include <array>
+#endif
+
+// xAOD framework includes:
+#include "xAODTracking/TrackParticleFwd.h"
+#include "xAODEgamma/ElectronFwd.h"
+
+// Local includes:
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/tools/RedirectMsgStream.h"
+
+namespace Ringer {
+
+/**
+ * @class TrackPatterns
+ * @brief Hold Ringer Track needed patterns.
+ *
+ *  This class will extract the Ringer needed Track patterns from TrackParticle
+ *  and Electron (if available). It is used afterwards to extract this patterns
+ *  into the containers (std::vector<float>) used by the classifiers.
+ **/
+class TrackPatternsHolder : public RedirectMsgStream {
+
+  public:
+
+    /**
+     * @brief Standard ctor:
+     **/
+    TrackPatternsHolder(
+        const bool useBLOutliers,
+        const bool usePIXOutliers,
+        const bool useSCTOutliers,
+        const bool useTRTOutliers,
+        const bool useTRTXenonHits):
+      m_useBLOutliers(useBLOutliers),
+      m_usePIXOutliers(usePIXOutliers),
+      m_useSCTOutliers(useSCTOutliers),
+      m_useTRTOutliers(useTRTOutliers),
+      m_useTRTXenonHits(useTRTXenonHits),
+      m_nBL(0),
+      m_nBLOutliers(0),
+      m_nPi(0),
+      m_nPiOutliers(0),
+      m_nSCT(0),
+      m_nSCTOutliers(0),
+      m_nTRThigh(0),
+      m_nTRThighOutliers(0),
+      m_nTRT(0),
+      m_nTRTOutliers(0),
+      m_nTRTXenonHits(0),
+      m_expectHitInBLayer(0),
+      m_trackd0(0),
+      m_deltaeta(0),
+      m_deltaphi(0),
+      m_ep(0),
+      m_energy(0),
+      m_eta(0){;}
+
+    /**
+     * @brief Extrack Track Patterns from Particles
+     **/
+    void extractPatternsFrom(
+        const xAOD::TrackParticle *track,
+        const xAOD::Electron *el );
+
+    /**
+     * @brief Export Track Patterns to @name vec end
+     *
+     * We apply transformations on the raw patterns extracted to obtain the
+     * true patterns applied. This method must be called after 
+     * extrackPatternsFrom method is called.
+     **/
+    void exportPatternsTo( std::vector<float> &vec ) const;
+
+    /**
+     * @brief Export the number of patterns that will be exported to vector.
+     **/
+    static size_t numberOfPatterns();
+
+  private:
+
+    /// Private properties (configuration):
+    ///@{
+    /// Flag whether to use B-layer outliers:
+    const bool m_useBLOutliers;
+    /// Flag whether to use Pixel outliers:
+    const bool m_usePIXOutliers;
+    /// Flag whether to use SCT outliers:
+    const bool m_useSCTOutliers;
+    /// Flag whether to use TRT outliers:
+    const bool m_useTRTOutliers;
+    /// Flag whether to use TRT Xenon hits:
+    const bool m_useTRTXenonHits;
+    ///@}
+
+    /// Private Properties:
+    ///@{
+    /// Number of B-Layer hits:
+    uint8_t m_nBL;
+    /// Number of B-Layer outliers:
+    uint8_t m_nBLOutliers;
+    /// Number of Pixel hits:
+    uint8_t m_nPi;
+    /// Number of Pixel outliers:
+    uint8_t m_nPiOutliers;
+    /// Number of SCT hits:
+    uint8_t m_nSCT;
+    /// Number of SCT outliers:
+    uint8_t m_nSCTOutliers;
+    /// Number of TRT high threshold hits:
+    uint8_t m_nTRThigh;
+    /// Number of TRT high threshold outliers:
+    uint8_t m_nTRThighOutliers;
+    /// Number of TRT hits:
+    uint8_t m_nTRT;
+    /// Number of TRT outliers:
+    uint8_t m_nTRTOutliers;
+    /// Number of TRT Xenon hits:
+    uint8_t m_nTRTXenonHits;
+    /// Whether to expect hit in BLayer:
+    uint8_t m_expectHitInBLayer;
+    /// Track transverse impact param:
+    float m_trackd0;
+    /// Track Calo deltaEta:
+    float m_deltaeta;
+    /// Track Calo deltaPhi:
+    float m_deltaphi;
+    /// Track Calo e/p:
+    double m_ep;
+
+    /// Cluster energy:
+    double m_energy;
+    /// Cluster eta:
+    double m_eta;
+    ///@}
+
+    /// Static properties:
+    ///@{
+    /// Coefficients to aproximate Number of TRT hits:
+    ///@{
+#if RINGER_USE_NEW_CPP_FEATURES
+    static constexpr double m_a0 = 33.14; 
+    static constexpr double m_b0 = -129.1; 
+    static constexpr double m_c0 = 1455.;
+    static constexpr double m_a1 = 29.42; 
+    static constexpr double m_b1 = 27.93; 
+    static constexpr double m_c1 = -89.96; 
+    static constexpr double m_d1 = 91.51;
+    static constexpr double m_a2 = 196.3; 
+    static constexpr double m_b2 = -403.; 
+    static constexpr double m_c2 = 230.2;
+    static constexpr double m_a3 = -10.59; 
+    static constexpr double m_b3 = 37.29;
+    static constexpr double m_a4 = -640.9; 
+    static constexpr double m_b4 = 1323.; 
+    static constexpr double m_c4 = -851.8; 
+    static constexpr double m_d4 = 180.8;
+    static constexpr double m_a5 = 159.8; 
+    static constexpr double m_b5 = -70.9;
+    static constexpr std::array<float,6> m_cutBinEta_TRT{{
+      0.1, 0.625, 1.07, 1.304, 1.752, 2.0
+    }};
+#else
+    static const double m_a0; 
+    static const double m_b0; 
+    static const double m_c0;
+    static const double m_a1; 
+    static const double m_b1; 
+    static const double m_c1; 
+    static const double m_d1;
+    static const double m_a2; 
+    static const double m_b2; 
+    static const double m_c2;
+    static const double m_a3; 
+    static const double m_b3;
+    static const double m_a4; 
+    static const double m_b4; 
+    static const double m_c4; 
+    static const double m_d4;
+    static const double m_a5; 
+    static const double m_b5;
+    static const std::vector<float> m_cutBinEta_TRT;
+#endif
+    ///@}
+    ///@}
+
+    /// Private Methods:
+    ///@{
+    /** Reset all values */
+    void resetValues();
+    /** get Track TRT variables */
+    void getTRTVar(double &rTRT, double &estHitsTRT) const;
+    ///@}
+
+};
+
+//==============================================================================
+inline
+size_t TrackPatternsHolder::numberOfPatterns()
+{
+  return 10;
+}
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_TRACKPATTERNSHOLDER_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.h
new file mode 100644
index 0000000000000000000000000000000000000000..cfbb6538d63b3f945ff2b9787819cd2472d49a2f
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.h
@@ -0,0 +1,256 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: VariableDependency.h 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef  RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_H
+#define  RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_H
+
+// STL includes:
+#include <stdexcept>
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+// ROOT includes:
+#include <TDirectory.h>
+
+// Local includes:
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+#include "RingerSelectorTools/tools/cxx/constexpr.h"
+#include "RingerSelectorTools/tools/cxx/final.h"
+#include "RingerSelectorTools/tools/cxx/override.h"
+#include "RingerSelectorTools/tools/cxx/mutable.h"
+
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer {
+
+/**
+ * @struct Eta, Et 
+ * @brief Dependency variable structure. 
+ *
+ * Holds all possible dependent variables values.
+ **/
+struct DepVarStruct {
+  const float eta;
+  const float et;
+  DepVarStruct(const float eta, const float et):
+    eta(eta),
+    et(et){;}
+};
+
+//class IVariableDependency
+//{
+//  public:
+//    /**
+//     * Check if depVar is within this procedure range
+//     **/
+//    virtual bool isWithinRange(const DepVarStruct &depVar) const = 0;
+//
+//    /**
+//     * Check if eta is within this procedure eta range
+//     **/
+//    virtual bool isWithinEtaRange(const float eta) const = 0;
+//
+//    /**
+//     * Set this procedure to be eta dependent:
+//     **/
+//    virtual void setEtaDep(const float etaMin, const float etaMax) = 0;
+//
+//    /**
+//     * Check if et is within this procedure et range
+//     **/
+//    virtual bool isWithinEtRange(const float et) const = 0;
+//
+//    /**
+//     * Set this procedure to be et dependent:
+//     **/
+//    virtual void setEtDep(const float etMin, const float etMax) = 0;
+//
+//    /**
+//     * Set this procedure to be et, eta dependent:
+//     **/
+//    virtual void setEtaEtDep(const float etaMin, const float etaMax,
+//        const float etMin, const float etMax) = 0;
+//
+//    virtual ~IVariableDependency(){;}
+//};
+
+/**
+ * @class VariableDependency
+ * @brief Interface for possible Eta and Et variable dependency. 
+ **/
+class VariableDependency /*: virtual public IVariableDependency*/
+{
+  public:
+
+    /**
+     * Ctor for independent 
+     **/
+    VariableDependency()
+      : m_etaDependency(EtaDependency::EtaIndependent),
+        m_etDependency(EtDependency::EtIndependent),
+        m_etaMin(0), m_etaMax(0),
+        m_etMin(0), m_etMax(0),
+        m_type{""}{;}
+
+    /**
+     * Ctor for eta dependent case
+     **/
+    VariableDependency(const float etaMin, const float etaMax,
+        EtaDependency etaDependency)
+      : m_etaDependency(etaDependency),
+        m_etDependency(EtDependency::EtIndependent),
+        m_etaMin(etaMin),
+        m_etaMax(etaMax),
+        m_etMin(0), 
+        m_etMax(0),
+        m_type{""}{;}
+
+    /**
+     * Ctor for et dependent case
+     **/
+    VariableDependency(const float etMin, const float etMax,
+        EtDependency etDependency)
+      : m_etaDependency(EtaDependency::EtaIndependent),
+        m_etDependency(etDependency),
+        m_etMin(etMin),
+        m_etMax(etMax),
+        m_type{""}{;}
+
+    /**
+     * Ctor for et/eta dependent case
+     **/
+    VariableDependency(const float etaMin, const float etaMax,
+        const float etMin, const float etMax)
+      : m_etaDependency(EtaDependency::EtaDependent),
+        m_etDependency(EtDependency::EtDependent),
+        m_etaMin(etaMin),
+        m_etaMax(etaMax),
+        m_etMin(etMin),
+        m_etMax(etMax),
+        m_type{""}{;}
+
+    /**
+     * Check if depVar is within this procedure range
+     **/
+    bool isWithinRange(const DepVarStruct &depVar) const /*ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Check if eta is within this procedure range
+     **/
+    bool isWithinEtaRange(const float eta) const /*ATH_RINGER_OVERRIDE 
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Returns whether it is et dependent
+     **/
+    EtaDependency etaDep() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Get eta min
+     **/
+    float etaMin() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Get eta max
+     **/
+    float etaMax() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Get et min
+     **/
+    float etMin() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Get et max
+     **/
+    float etMax() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Set this procedure to be eta dependent:
+     **/
+    void setEtaDep(const float etaMin, const float etaMax) /*ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Check if et is within this procedure et range
+     **/
+    bool isWithinEtRange(const float et) const /*ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Returns whether it is et dependent
+     **/
+    EtDependency etDep() const /*ATH_RINGER_OVERRIDE ATH_RINGER_FINAL*/;
+
+    /**
+     * Set this procedure to be et dependent
+     **/
+    void setEtDep(const float etMin, const float etMax) /*ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Set this procedure to be et dependent
+     **/
+    void setEtaEtDep(const float etaMin, const float etaMax,
+        const float etMin, const float etMax) /*ATH_RINGER_OVERRIDE
+      ATH_RINGER_FINAL*/;
+
+    /**
+     * Return this variable dependency string
+     *
+     * This is not a virtual method.
+     **/
+    const char* type() const;
+
+    /**
+     * Read variable dependency from directory
+     **/
+    static void read(VariableDependency *varDep, 
+        TDirectory *configDir, 
+        unsigned writtenVersion);
+
+    /**
+     * Write variable dependency to directory
+     *
+     * This is not a virtual method.
+     **/
+    void writeDepInfo(TDirectory *configDir) const;
+
+    /**
+     * Ensure virtual destruction (needed if creating dictionary from this
+     * class)
+     **/
+    virtual ~VariableDependency(){;}
+
+  private:
+
+    /// Whether there is eta dependency
+    EtaDependency m_etaDependency; 
+    /// Whether there is et dependency
+    EtDependency m_etDependency;
+
+    /// Eta bounded region where RingerProcedure may be applied 
+    float m_etaMin, m_etaMax;
+
+    /// Et bounded region where RingerProcedure may be applied 
+    float m_etMin, m_etMax;
+
+    /// The string holder for type:
+    ATH_RINGER_MUTABLE std::string m_type;
+
+};
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_H
+
+#ifndef INCLUDE_HEADER_ONLY // Use to avoid circular includes
+#include "VariableDependency.icc"
+#endif // INCLUDE_HEADER_ONLY
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.icc b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.icc
new file mode 100644
index 0000000000000000000000000000000000000000..17997c3bdc9ad10bf9d863dcb3af6deef98d8186
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/VariableDependency.icc
@@ -0,0 +1,113 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: VariableDependency.icc 689837 2015-08-17 17:22:12Z wsfreund $
+#ifndef  RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_ICC
+#define  RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_ICC
+
+// Local includes:
+#include "RingerSelectorTools/tools/VariableDependency.h"
+
+namespace Ringer {
+
+// =============================================================================
+inline
+bool VariableDependency::isWithinRange(const DepVarStruct &depVar) const 
+{
+  return isWithinEtaRange(depVar.eta) && isWithinEtRange(depVar.et);
+}
+
+// =============================================================================
+inline
+bool VariableDependency::isWithinEtaRange(const float eta) const  
+{
+  if ( static_cast<bool>(m_etaDependency) ){
+    const float eta_abs = std::abs(eta);
+    return ( (eta_abs >= m_etaMin) && (eta_abs < m_etaMax) );
+  } else {
+    return true;
+  }
+}
+
+// =============================================================================
+inline
+EtaDependency VariableDependency::etaDep() const {
+  return m_etaDependency;
+}
+
+// =============================================================================
+inline
+float VariableDependency::etaMin() const
+{
+  return m_etaMin;
+}
+
+// =============================================================================
+inline
+float VariableDependency::etaMax() const
+{
+  return m_etaMax;
+}
+
+// =============================================================================
+inline
+void VariableDependency::setEtaDep(const float etaMin, const float etaMax) 
+{
+  m_etaDependency = EtaDependency::EtaDependent;
+  m_etaMin = etaMin;
+  m_etaMax = etaMax;
+}
+
+// =============================================================================
+inline
+bool VariableDependency::isWithinEtRange(const float et) const 
+{
+  if ( static_cast<bool>(m_etDependency) ) {
+    return ( (et >= m_etMin) && (et < m_etMax) );
+  } else {
+    return true;
+  }
+}
+
+// =============================================================================
+inline
+EtDependency VariableDependency::etDep() const {
+  return m_etDependency;
+}
+
+// =============================================================================
+inline
+float VariableDependency::etMin() const
+{
+  return m_etMin;
+}
+
+// =============================================================================
+inline
+float VariableDependency::etMax() const
+{
+  return m_etMax;
+}
+
+// =============================================================================
+inline
+void VariableDependency::setEtDep(const float etMin, const float etMax) 
+{
+  m_etDependency = EtDependency::EtDependent;
+  m_etMin = etMin;
+  m_etMax = etMax;
+}
+
+// =============================================================================
+inline
+void VariableDependency::setEtaEtDep(const float etaMin, const float etaMax,
+    const float etMin, const float etMax)
+{
+  setEtaDep(etaMin,etaMax);
+  setEtDep(etMin,etMax);
+}
+
+} // namespace Ringer
+
+#endif // RINGERSELECTORTOOLS_TOOLS_VARIABLEDEPENDENCY_ICC
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h
new file mode 100644
index 0000000000000000000000000000000000000000..81dba98859292e6fc9dd5c0648363bd61e5ab8fe
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h
@@ -0,0 +1,19 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerUseNewCppFeatures.h 693573 2015-09-07 19:15:49Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_RINGERUSENEWCPPFEATURES_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_RINGERUSENEWCPPFEATURES_H
+
+#include "RVersion.h"
+
+#ifndef RINGER_STANDALONE
+#include "xAODCaloRings/tools/cxx/RingerUseNewCppFeatures.h"
+#define FORCE_RINGER_PROCEDURE_TYPE_CONST_EXPR
+#else
+# define RINGER_USE_NEW_CPP_FEATURES ((__cplusplus >= 201100) && \
+                                      (ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)) )
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_RINGERUSENEWCPPFEATURES_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/StaticAssert.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/StaticAssert.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1fb4d090f47d5f3ee72e58426fba662dc83dfa5
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/StaticAssert.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: StaticAssert.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_STATICASSERT_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_STATICASSERT_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#undef RINGER_STATIC_ASSERT
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+#define RINGER_STATIC_ASSERT(cond,msg) static_assert(cond,msg)
+#else
+#include "boost/static_assert.hpp"
+#define RINGER_STATIC_ASSERT(cond,msg) BOOST_STATIC_ASSERT_MSG(cond,msg)
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_STATICASSERT_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/add_lvalue_reference.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/add_lvalue_reference.h
new file mode 100644
index 0000000000000000000000000000000000000000..03ac3f3df94de715ba25bf762411b1c507bff52e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/add_lvalue_reference.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: add_lvalue_reference.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_ADD_LVALUE_REFERENCE_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_ADD_LVALUE_REFERENCE_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::add_lvalue_reference;
+} // namespace Ringer
+#else
+#include "boost/type_traits/add_lvalue_reference.hpp" 
+namespace Ringer {
+template < class T>
+class add_lvalue_reference : public boost::add_lvalue_reference<T>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_ADD_LVALUE_REFERENCE_H
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/conditional.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/conditional.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff0ff7b866062db968217b09961d2e1698c73bd4
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/conditional.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: conditional.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_CONDITIONAL_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_CONDITIONAL_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::conditional;
+} // namespace Ringer
+#else
+#include "boost/type_traits/conditional.hpp" 
+namespace Ringer {
+template<bool Cond, class T, class F>
+class conditional : public boost::conditional<Cond,T,F> {};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_CONDITIONAL_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/constexpr.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/constexpr.h
new file mode 100644
index 0000000000000000000000000000000000000000..113f728ba6e7df2b981f5d1bac667b5786a7b361
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/constexpr.h
@@ -0,0 +1,22 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: constexpr.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_CONSTEXPR_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_CONSTEXPR_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#undef ATH_RINGER_CONSTEXPR
+
+//CxxUtils for final
+#if RINGER_USE_NEW_CPP_FEATURES
+# define ATH_RINGER_CONSTEXPR constexpr
+#else
+# define ATH_RINGER_CONSTEXPR 
+#endif
+
+
+#endif  // RINGERSELECTORTOOLS_TOOLS_CXX_CONSTEXPR_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/decay.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/decay.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f44edd84d9dd32888ef43bb6607aef9cdcfc0ed
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/decay.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: decay.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_DECAY_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_DECAY_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::decay;
+} // namespace Ringer
+#else
+#include "boost/type_traits/decay.hpp" 
+namespace Ringer {
+template < class T >
+class decay : public boost::decay<T>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_DECAY_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/enable_if.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/enable_if.h
new file mode 100644
index 0000000000000000000000000000000000000000..2615acdf56bca479b360e9131fa83bac18720816
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/enable_if.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: enable_if.h 693383 2015-09-06 22:08:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_ENABLE_IF_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_ENABLE_IF_H
+
+#include "RingerUseNewCppFeatures.h"
+
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::enable_if;
+} // namespace Ringer
+#else
+#include "CxxUtils/enable_if.h" 
+namespace Ringer {
+template<bool Cond, class T = void>
+class enable_if : public enable_if<Cond,T> {};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_ENABLE_IF_H
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/errorcheck.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/errorcheck.h
new file mode 100644
index 0000000000000000000000000000000000000000..1db42200890d100e8382309bb35d110e9e2bc57b
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/errorcheck.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_ERRORCHECK_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_ERRORCHECK_H
+
+#if !defined(RINGER_STANDALONE) && !defined(XAOD_STANDALONE)
+# include "AthenaKernel/errorcheck.h"
+#else
+# ifndef XAOD_STANDALONE
+#  include <TError.h> // Include ::Error from root
+# endif
+# define PLACE_INFO __FILE__
+# define CHECK( ARG )                                  \
+  do {                                                  \
+      const bool result = ARG;                          \
+    if( ! result ) {                                    \
+      ::Error( PLACE_INFO, "Failed to execute: \"%s\"", \
+  #ARG );                                               \
+        return 1;                                       \
+    }                                                   \
+   } while( false )
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_ERRORCHECK_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/final.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/final.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a5b8e32361da699da69f268a653b01a08309fab
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/final.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: final.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_FINAL_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_FINAL_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#undef ATH_RINGER_FINAL
+
+//CxxUtils for final
+#if RINGER_USE_NEW_CPP_FEATURES
+# define ATH_RINGER_FINAL final
+#else
+# define ATH_RINGER_FINAL  
+#endif
+
+
+#endif  // RINGERSELECTORTOOLS_TOOLS_CXX_FINAL_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_base_of.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_base_of.h
new file mode 100644
index 0000000000000000000000000000000000000000..deb2f648ae7df6a0bfceb4aa88df8e201eaece53
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_base_of.h
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: is_base_of.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_ISBASEOF_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_ISBASEOF_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::is_base_of;
+} // namespace Ringer
+#else
+#include "boost/type_traits/is_base_of.hpp" 
+namespace Ringer {
+template<class Base, class Derived>
+class is_base_of : public boost::is_base_of<Base,Derived> {};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_ISBASEOF_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_enum.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_enum.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fad7cf45fd3fe90daddbef1be279ae79c763ae9
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_enum.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: is_enum.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_IS_ENUM_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_IS_ENUM_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::is_enum;
+} // namespace Ringer
+#else
+#include "boost/type_traits/is_enum.hpp" 
+namespace Ringer {
+template < class T>
+class is_enum : public boost::is_enum<T>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_IS_ENUM_H
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_same.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_same.h
new file mode 100644
index 0000000000000000000000000000000000000000..e08c454a2a342bf150a656df566f544de87d5889
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/is_same.h
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: is_same.h 693383 2015-09-06 22:08:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_ISSAME_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_ISSAME_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::is_same;
+} // namespace Ringer
+#else
+#include "boost/type_traits/is_base_of.hpp" 
+namespace Ringer {
+template < class T, class U>
+class is_same : public boost::is_same<T,U>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_ISSAME_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/mutable.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/mutable.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0a261fd87c1346bc5d58770fb7b1f143b0bf538
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/mutable.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: mutable.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_MUTABLE_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_MUTABLE_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#ifndef RINGER_STANDALONE
+#include "xAODCaloRings/tools/cxx/mutable.h"
+#else
+#if RINGER_USE_NEW_CPP_FEATURES
+# define ATH_RINGER_MUTABLE mutable
+#else
+# define ATH_RINGER_MUTABLE
+#endif
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_MUTABLE_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/override.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/override.h
new file mode 100644
index 0000000000000000000000000000000000000000..be29b538df486b2afb9b4d2ccb788a9264f5f000
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/override.h
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: override.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_OVERRIDE_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_OVERRIDE_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#undef ATH_RINGER_OVERRIDE
+
+//CxxUtils for override
+#if RINGER_USE_NEW_CPP_FEATURES
+# define ATH_RINGER_OVERRIDE override 
+#else
+# define ATH_RINGER_OVERRIDE  
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_OVERRIDE_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_cv.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_cv.h
new file mode 100644
index 0000000000000000000000000000000000000000..3edd406bfd70d173498c6d9e1f99cb440159a54f
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_cv.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: remove_cv.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_CV_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_CV_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::remove_cv;
+} // namespace Ringer
+#else
+#include "boost/type_traits/remove_cv.hpp" 
+namespace Ringer {
+template < class T>
+class remove_cv : public boost::remove_cv<T>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_CV_H
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_pointer.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_pointer.h
new file mode 100644
index 0000000000000000000000000000000000000000..1367fc9205c14518fc5c1606307693c8107ded38
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/remove_pointer.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: remove_pointer.h 667905 2015-05-18 19:07:55Z wsfreund $
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_POINTER_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_POINTER_H
+
+#include "RingerUseNewCppFeatures.h"
+
+#if RINGER_USE_NEW_CPP_FEATURES
+#include<type_traits>
+namespace Ringer {
+using std::remove_pointer;
+} // namespace Ringer
+#else
+#include "boost/type_traits/remove_pointer.hpp" 
+namespace Ringer {
+template < class T>
+class remove_pointer : public boost::remove_pointer<T>{};
+} // namespace Ringer
+#endif
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_REMOVE_POINTER_H
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/stringify.h b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/stringify.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7668d004991dd4f9b1c3a41f1e6646414352181
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/RingerSelectorTools/tools/cxx/stringify.h
@@ -0,0 +1,14 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RINGERSELECTORTOOLS_TOOLS_CXX_STRINGIZE_H
+#define RINGERSELECTORTOOLS_TOOLS_CXX_STRINGIZE_H
+
+// Simple stringify macro
+#define __STRINGIFY(x) #x
+#define STRINGIFY(x) __STRINGIFY(x)
+#define __PASTE(x,y) x##y
+#define PASTE(x) __PASTE(x,y)
+
+#endif // RINGERSELECTORTOOLS_TOOLS_CXX_STRINGIZE_H
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/AsgElectronRingerSelector.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/AsgElectronRingerSelector.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ecfcef500ad65281fe253c00639ec5f912ddf003
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/AsgElectronRingerSelector.cxx
@@ -0,0 +1,833 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: AsgElectronRingerSelector.cxx 713528 2015-12-09 08:58:44Z wsfreund $
+// STL includes:
+#include <string>
+#include <stdexcept>
+#include <iostream>
+#include <limits>
+#include <iostream>
+
+#ifndef RINGER_STANDALONE
+// Athena framework includes:
+# include "AsgTools/AsgTool.h"
+# include "PATCore/TAccept.h"
+# include "PathResolver/PathResolver.h"
+# include "AthContainers/exceptions.h"
+
+// xAOD includes:
+# include "xAODBase/IParticle.h"
+# include "xAODCaloRings/CaloRingsContainer.h"
+# include "xAODCaloRings/CaloRingsAuxContainer.h"
+# include "xAODCaloRings/RingSetConfContainer.h"
+# include "xAODCaloRings/RingSetConfAuxContainer.h" // always include aux container
+# include "xAODCaloRings/CaloRingsDefs.h"
+# include "xAODCaloRings/tools/getCaloRingsDecorator.h"
+# include "xAODCaloRings/RingSetConf.h"
+# include "xAODTracking/TrackParticle.h"
+# include "xAODEgamma/Electron.h"
+#endif // ndef RINGER_STANDALONE
+
+// Local includes:
+#include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#include "RingerSelectorTools/ElectronTAccept.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.h"
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+#include "RingerSelectorTools/tools/IRedirectMsgStream.h"
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+#include "RingerSelectorTools/tools/cxx/errorcheck.h"
+
+// Root framework includes:
+#include <TFile.h>
+
+/*
+ * TODO List:
+ * 
+ * - We need to change getTAccept logic so that it works exactly for egamma
+ *   particle, and then checks if particle is electron. If true, gets track
+ *   information and feed it into the RingerCommonSelector.
+ */
+
+namespace Ringer {
+
+#ifndef RINGER_STANDALONE
+
+namespace {
+
+//==============================================================================
+/**
+ * @brief Get cluster 2EM layer eta and et variables
+ *
+ * NOTE: It isn't being used for now.
+ **/
+//inline
+//void getCluster2EMEtaEt(
+//    const xAOD::CaloCluster *cluster, 
+//    float &eta2, 
+//    float &et)
+//{
+//  eta2 = std::fabs(cluster->etaBE(2));
+//  // We need to hold the dependence variable within this structure:
+//  const double energy =  cluster->e();
+//  if ( eta2 < 999.) {
+//    const double cosheta = std::cosh(eta2);
+//    et = (cosheta != 0.) ? energy /cosheta : 0.;
+//  }
+//}
+
+//==============================================================================
+/**
+ * @brief Check if decision bit is to be used
+ **/
+//inline
+//bool isDecToBeUsed(
+//    const int bitIntHolder, 
+//    const Ringer::ElectronTAccept::bitMskWord &decsToUse)
+//{
+//  return decsToUse.test(bitIntHolder);
+//}
+
+} // End of private namespace
+
+
+//==============================================================================
+// Standard constructor
+//==============================================================================
+AsgElectronRingerSelector::AsgElectronRingerSelector(std::string asgToolName) :
+  AsgMetadataTool(asgToolName),
+  m_thresWrapper(nullptr),
+  m_ringSelCommon(nullptr),
+  m_trackPat(nullptr),
+  m_partDecMsk(Ringer::ElectronTAccept::retrieveTAcceptTemplate()),
+  m_accept(Ringer::ElectronTAccept::retrieveTAcceptTemplate()),
+  m_useCutIDDecision(false),
+  m_metaDataCached(false),
+  m_rsConfCont(nullptr),
+  m_metaIsOnOutput(false) // Check first input
+{
+
+  declareProperty("DiscriminationFileName", m_discrFileName="", 
+      "The configuration file in which we will retrieve the "
+      "discrimination chain.");
+
+  declareProperty("ThresholdFileName", m_thresFileName="", 
+      "The configuration file in which we will retrieve the "
+      "");
+
+  declareProperty("CutsMask", m_cutsMask, 
+      "The required cuts to apply (IsEM Mask)");
+
+  declareProperty("CutIDSelector", m_cutIDSelector, 
+      "The CutID Tool Handle to run track (if required by discrimation "
+      "configuration file)");
+
+  declareProperty("RingSetConfContainerName", m_rsMetaName,
+      "The RingSetConfContainer key in the MetaData StoreGate");
+
+  declareProperty("CacheConfData",m_cacheMetaData = true,
+      "Whether to cache metadata configuration or not");
+
+  m_ringsELReader = xAOD::getCaloRingsReader();
+
+}
+
+//==============================================================================
+// Standard destructor
+//==============================================================================
+AsgElectronRingerSelector::~AsgElectronRingerSelector()
+{
+  // Release discriminator wrapper collection memory:
+  for ( size_t discrColIdx = 0; 
+      discrColIdx < m_discrWrapperCol.size(); 
+      ++discrColIdx ) 
+  {
+    if (m_discrWrapperCol[discrColIdx]) {
+      m_discrWrapperCol[discrColIdx]->releaseMemory();
+    }
+  }
+
+  // Release memory from threshold wrapper:
+  if ( m_thresWrapper ){
+    m_thresWrapper->releaseMemory();
+    delete m_thresWrapper;
+  }
+
+  delete m_ringSelCommon;
+  delete m_trackPat;
+}
+
+//==============================================================================
+// finalize method (called by destructor)
+//==============================================================================
+StatusCode AsgElectronRingerSelector::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
+
+
+//==============================================================================
+// Athena initialize method
+//==============================================================================
+StatusCode AsgElectronRingerSelector::initialize()
+{
+  // Set the unsigned mask into the bitset
+  m_cutsToUse = ElectronTAccept::bitMskWord(m_cutsMask);
+
+  ATH_MSG_DEBUG("Cut mask was set to: " << m_cutsToUse.to_string());
+
+  // Set our configuration:
+  CHECK( readConfigFiles() );
+
+  return StatusCode::SUCCESS;
+}
+
+//==============================================================================
+StatusCode AsgElectronRingerSelector::readConfigFiles()
+{
+
+  // Use colaboration tool to find true path for file:
+  std::string discrFileName = PathResolverFindCalibFile( m_discrFileName );
+  std::string thresFileName = PathResolverFindCalibFile( m_thresFileName );
+
+  if( discrFileName.empty() ) {
+    ATH_MSG_ERROR("Discrimination chain configuration file is not "
+        "available.");
+    return StatusCode::FAILURE;
+  }
+
+  if( thresFileName.empty() ) {
+    ATH_MSG_ERROR("Threshold configuration file is not "
+        "available.");
+    return StatusCode::FAILURE;
+  }
+
+  // Read discrimination wrapper collection
+  IDiscrWrapper::read(m_discrWrapperCol, discrFileName.c_str() );
+
+  ATH_MSG_INFO( "Using DiscriminationFile: " << discrFileName.c_str());
+
+  // Set message stream and print configuration:
+  for ( unsigned discrIdx = 0; 
+      discrIdx < m_discrWrapperCol.size(); 
+      ++discrIdx)
+  {
+    m_discrWrapperCol[discrIdx]->setMsgStream( &(this->msg()));
+    m_discrWrapperCol[discrIdx]->print();
+  }
+
+  // Get configuration for discrimination information flow
+  IOConfStruct fileConf;
+  retrieveFileConf( discrFileName.c_str(), fileConf );
+  printConf( fileConf, &(this->msg()) );
+
+  // Read discrimination wrapper collection
+  IThresWrapper::read(m_thresWrapper, thresFileName.c_str() );
+
+  ATH_MSG_INFO( "Using ThresholdFile: " << thresFileName.c_str());
+
+  // Set message stream and print configuration:
+  m_thresWrapper->setMsgStream( &(this->msg() ));
+  m_thresWrapper->print();
+
+  // Create our discrimination chain selector:
+  m_ringSelCommon = new Ringer::RingerCommonSelector(
+      &m_discrWrapperCol,
+      m_thresWrapper,
+      &m_partDecMsk,
+      fileConf.useTrackPat,
+      fileConf.useRawTrackPat,
+      fileConf.useCaloCommittee);
+
+  // Set RingerCommonSelector message stream:
+  m_ringSelCommon->setMsgStream( &(this->msg()) );
+
+  // Update discrimination wrapper CaloRings configuration
+  if ( !m_rawConfCol.empty() ){
+    for ( auto &discrWrapper : m_discrWrapperCol ) {
+      discrWrapper->setRawConfCol( &m_rawConfCol );
+    }
+    xAOD::RingSetConf::print( m_rawConfCol, msg() );
+  }
+
+  // See if we are using CutID selector and retrieve it if so:
+  if (m_useCutIDDecision) {
+    if ( m_cutIDSelector.retrieve().isFailure() ) {
+      ATH_MSG_FATAL( "Could not get tool: " << m_cutIDSelector );
+      return StatusCode::FAILURE;
+    }
+  }
+
+  // Create track pattern and make it redirect its stream as if it
+  // was AsgElectronRingerSelector:
+  m_trackPat = new Ringer::TrackPatternsHolder( 
+      fileConf.useBLOutliers,
+      fileConf.usePIXOutliers,
+      fileConf.useSCTOutliers,
+      fileConf.useTRTOutliers,
+      fileConf.useTRTXenonHits);
+
+  m_trackPat->setMsgStream( &(this->msg()) );
+
+  return StatusCode::SUCCESS;
+
+}
+
+//=============================================================================
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::IParticle* part ) const
+{
+  ATH_MSG_DEBUG("Entering accept( const IParticle* part )");
+
+  const xAOD::Electron* el = 0;
+  if( part->type()==xAOD::Type::Electron ){
+    el = static_cast<const xAOD::Electron*> (part);
+  } else {
+    ATH_MSG_ERROR("AsgElectronRingerSelector::could not convert argument to accept");
+  }
+
+  return accept(el);
+}
+
+
+// =============================================================================
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::Electron* el) const
+{
+  ATH_MSG_DEBUG("Entering accept( const xAOD::Electron* el)");
+
+  StatusCode sc = execute(el);
+
+  if (sc.isFailure()) {
+    ATH_MSG_ERROR("Error while on particle AsgSelector execution.");
+  }
+
+  return m_accept;
+}
+
+
+// =============================================================================
+const Root::TAccept& AsgElectronRingerSelector::accept( 
+    const xAOD::Egamma* eg ) const
+{
+  ATH_MSG_DEBUG("Entering accept( const xAOD::Egamma* part )");
+
+  StatusCode sc = execute(eg);
+
+  if (sc.isFailure()) {
+    ATH_MSG_ERROR("Error while on particle AsgSelector execution.");
+  }
+
+  return m_accept;
+}
+
+
+// =============================================================================
+StatusCode AsgElectronRingerSelector::execute(
+    const xAOD::Electron* el) const
+{
+
+  ATH_MSG_DEBUG("Entering execute(const xAOD::Electron* el...)");
+
+#if RINGER_USE_NEW_CPP_FEATURES
+  // In this case, we only do this to have a more harmonic code:
+  Root::TAccept &partDecMsk_ref = m_partDecMsk;
+  TrackPatternsHolder *trackPat_ref = m_trackPat;
+#else
+  // Well, since we do not have mutable properties, we need to do this ugly
+  // things...
+  Root::TAccept &partDecMsk_ref = 
+    const_cast<Root::TAccept&>(m_partDecMsk);
+  TrackPatternsHolder *trackPat_ref = 
+    const_cast<TrackPatternsHolder*>(m_trackPat);
+#endif
+
+  // Clear particle decision mask and previous result (set everything as if it
+  // was passed), prepare to refill it:
+  partDecMsk_ref.clear();
+
+  m_ringSelCommon->clear();
+
+  // No error occurred so far, flag it:
+  partDecMsk_ref.setCutResult( 
+      BitdefElectron::NoErrorBit, 
+      true);
+
+  // Set if it was requested to execute CutID:
+  partDecMsk_ref.setCutResult( 
+      BitdefElectron::ExecCutID, 
+      m_useCutIDDecision );
+
+  if (!el){
+    ATH_MSG_ERROR("Invalid electron pointer.");
+
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::NoErrorBit, 
+        false);
+
+    return StatusCode::FAILURE;
+  }
+
+  // First, check if we can retrieve decoration:
+  const xAOD::CaloRingsLinks *caloRingsLinks(nullptr);
+  try {
+    caloRingsLinks = &(m_ringsELReader->operator()(*el));
+  } catch ( const std::exception &e) {
+    ATH_MSG_ERROR("Couldn't retrieve CaloRingsLinks. Reason: " 
+        << e.what());
+  }
+
+  if ( caloRingsLinks->empty() ){
+
+    ATH_MSG_ERROR("Particle does not have CaloRings decoratorion.");
+
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::NoErrorBit, 
+        false);
+
+    return StatusCode::FAILURE;
+  }
+
+  // FIXME The indexing should be an enum, previous test should ensure that the
+  // size is large enought to access index.
+  if ( !caloRingsLinks->at(0).isValid() ){
+    ATH_MSG_DEBUG("Ignoring candidate with invalid ElementLink.");
+
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::NoErrorBit, 
+        false);
+
+    return StatusCode::SUCCESS;
+  }
+
+
+  // For now, we are using only the first cluster 
+  const xAOD::CaloRings *clrings = *(caloRingsLinks->at(0));
+  
+  // Check if everything is ok with CaloRings ElementLink vector:
+  if (caloRingsLinks->empty() || !(clrings) ){
+
+    ATH_MSG_ERROR("There isn't CaloRings Decoration available" 
+        " for input particle." );
+
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::NoErrorBit, 
+        false );
+
+    return StatusCode::FAILURE;
+  }
+
+  // Get track information:
+  const xAOD::TrackParticle *track = el->trackParticle();
+
+  // Fill track pattern holder with new information:
+  trackPat_ref->extractPatternsFrom( track, el );
+
+  // Put cluster calibrated eta/et into DepVarStruct:
+  const xAOD::CaloCluster *cluster = el->caloCluster();
+  const DepVarStruct depVar( cluster->eta(), 
+      cluster->et() );
+
+  // We head now into the RingerChain execution:
+  try {
+    // Execute Ringer Selector Common:
+    if ( m_ringSelCommon->execute(
+          depVar, 
+          clrings, 
+          trackPat_ref).isFailure() )
+    {
+
+      ATH_MSG_ERROR("Error while executing "
+          "RingerCommonSelector.");
+
+      partDecMsk_ref.setCutResult( 
+          BitdefElectron::NoErrorBit, 
+          false);
+
+    }
+  } catch (const std::exception &e ) {
+
+    ATH_MSG_ERROR("Error while executing "
+        "RingerCommonSelector. Reason: " << e.what() );
+
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::NoErrorBit, 
+        false);
+
+  }
+  
+  // Add the CutID track decision bit (if requested):
+  if ( m_useCutIDDecision ) {
+    try {
+      partDecMsk_ref.setCutResult( 
+          BitdefElectron::CutIDDec, 
+          static_cast<bool>(m_cutIDSelector->accept(el)) );
+
+    } catch ( const std::exception &e ) {
+
+      ATH_MSG_ERROR("Error while executing "
+          "AsgElectronRingerSelector. Reason:" << e.what() );
+
+      partDecMsk_ref.setCutResult( 
+          BitdefElectron::NoErrorBit, 
+          false );
+
+      partDecMsk_ref.setCutResult( 
+          BitdefElectron::CutIDDec , 
+          false );
+
+    }
+  } else { 
+
+    // If we do not run it, set track decision to true:
+    partDecMsk_ref.setCutResult( 
+        BitdefElectron::CutIDDec , 
+        true );
+
+  }
+
+  // We have finished, then fill decision mask:
+  fillTAccept();
+
+  // Check if an error occurred, and flag it:
+  if ( partDecMsk_ref.getCutResult( 
+        BitdefElectron::NoErrorBit ) )
+  {
+    return StatusCode::SUCCESS;
+  } else {
+    return StatusCode::FAILURE;
+  }
+}
+
+//==============================================================================
+StatusCode AsgElectronRingerSelector::execute(const xAOD::Egamma* eg) const
+{
+  ATH_MSG_DEBUG("entering execute(const xAOD::Egamma* eg...)");
+
+  if (eg){
+    //size_t cDiscr = 0;
+  } else {
+    ATH_MSG_ERROR("Egamma pointer is null.");
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+//=============================================================================
+// Fill the m_accept from the m_partDecMsk mask using the m_cutsToUse
+//=============================================================================
+void AsgElectronRingerSelector::fillTAccept() const 
+{
+#if RINGER_USE_NEW_CPP_FEATURES
+  // In this case, we only do this to have a more harmonic code:
+  Root::TAccept &accept_ref = m_accept;
+#else
+  // Well, since we do not have mutable properties, we need to do this ugly
+  // things...
+  Root::TAccept &accept_ref = const_cast<Root::TAccept&>(m_accept);
+#endif
+  for (unsigned bit = 0; bit < BitdefElectron::NUsedBits(); ++bit ){
+    // m_partDec mask is set to true if passed cut.
+    // m_cutsToUse is set to true if cut is to be used.
+    accept_ref.setCutResult( bit, 
+        (m_partDecMsk.getCutResult(bit)) || !m_cutsToUse[bit] );
+  }
+}
+
+//==============================================================================
+StatusCode AsgElectronRingerSelector::beginInputFile()
+{
+
+  // Tell the user what's happening:
+  ATH_MSG_DEBUG( "Entered new file, checking if it is needed to " 
+      "update metadata information.");
+
+  if ( m_cacheMetaData && m_metaDataCached ) {
+    ATH_MSG_DEBUG( "Metadata is already cached." );
+    return StatusCode::SUCCESS;
+  }
+
+  // Read the metadata object:
+  m_rsConfCont = nullptr;
+
+  bool failedToRetrieveInInput(false);
+
+  // First we try to obtain configuration on the inputMetaStore. If this does
+  // not work, we try to obtain it on the outputMetaStore.
+#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS)
+  if ( !m_metaIsOnOutput && ( ( m_rsConfCont = inputMetaStore()->
+        tryConstRetrieve< xAOD::RingSetConfContainer >( m_rsMetaName ) )
+      == nullptr ) ) 
+  {
+    if ( !m_metaIsOnOutput ) {
+      failedToRetrieveInInput = true;
+      ATH_MSG_DEBUG("Couldn't retrieve on inputMetaStore, will "
+          "try to retrieve from outputMetaStore.");
+    }
+  } else {
+    ATH_MSG_DEBUG("Retrieved meta from inputMetaStore.");
+  }
+#else
+  if ( !m_metaIsOnOutput && 
+      inputMetaStore()->retrieve( m_rsConfCont, m_rsMetaName ) )
+  {
+    if ( !m_metaIsOnOutput ) {
+      failedToRetrieveInInput = true;
+      ATH_MSG_DEBUG("Couldn't retrieve on inputMetaStore, will "
+          "try to retrieve from outputMetaStore.");
+    }
+  } else {
+    ATH_MSG_DEBUG("Retrieved meta from inputMetaStore.");
+  }
+#endif
+
+  // We also attempt to retrieve on outputMetaStore if inputMetaStore failed:
+  if ( ( m_metaIsOnOutput || failedToRetrieveInInput ) &&
+      outputMetaStore()->retrieve( m_rsConfCont, m_rsMetaName ).isFailure())
+  {
+    // FIXME: This should be done by manually setting the metadata information
+    // if it is not set (if manually set, do not attempt to retrieve on the 
+    // metadata store).
+    ATH_MSG_WARNING( "Couldn't retrieve rings configuration on both "
+        "inputMetaStore and outputMetaStore. Setting default value, "
+        "(which might be wrong)." );
+    m_rawConfCol.clear();
+    m_rawConfCol = { 
+        {8,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::PS,
+          Ringer::CalJointSection::EM,
+          false, false,
+          0, 8,
+        0, 88},
+        {64,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::EM1,
+          Ringer::CalJointSection::EM,
+          false, false,
+          8, 72,
+        0, 88},
+        {8,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::EM2,
+          Ringer::CalJointSection::EM,
+          false, false,
+          72, 80, 
+        0, 88},
+        {8,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::EM3,
+          Ringer::CalJointSection::EM,
+          false, false,
+          80, 88, 
+        0, 88},
+        {4,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::HAD1,
+          Ringer::CalJointSection::HAD,
+          false, false,
+          88, 92, 
+        88, 100},
+        {4,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::HAD2,
+          Ringer::CalJointSection::HAD,
+          false, false,
+          92, 96, 
+        88, 100},
+        {4,
+          std::vector<CaloSampling::CaloSample>(), 0., 0., 0., 0.,
+          Ringer::CalJointLayer::HAD3,
+          Ringer::CalJointSection::HAD,
+          false, false,
+          96, 100,
+        88, 100} };
+    for ( auto &discrWrapper : m_discrWrapperCol ) {
+      discrWrapper->setRawConfCol( &m_rawConfCol );
+    }
+    xAOD::RingSetConf::print( m_rawConfCol, msg() );
+    m_metaDataCached = true;
+  } else {
+    // Flag that meta is on outputMeta rather than the input 
+    if ( failedToRetrieveInInput ){
+      m_metaIsOnOutput = true;
+      ATH_MSG_DEBUG("Retrieved meta from outputMetaStore.");
+    }
+  }
+
+  ATH_MSG_DEBUG("Successfully retrieved store, "
+      "trying to get RawConfiguration Collection.");
+
+  // A little sanity check:
+  if( !m_rsConfCont || m_rsConfCont->empty() ) {
+     ATH_MSG_ERROR( "Metadata " << m_rsMetaName << " is not available on file." );
+     return StatusCode::FAILURE;
+  }
+
+  // Retrieve the raw configuration:
+  xAOD::RingSetConf::getRawConfCol( m_rawConfCol, m_rsConfCont );
+
+  // Sign that it can be cached, if we want to cache it for the whole run:
+  m_metaDataCached = true;
+
+  // Pass its pointer into each wrapper in the discrimination chain:
+  for ( auto &discrWrapper : m_discrWrapperCol ) {
+    discrWrapper->setRawConfCol( &m_rawConfCol );
+  }
+  xAOD::RingSetConf::print( m_rawConfCol, msg() );
+
+  ATH_MSG_DEBUG( "Successfully retrieve configuration info.");
+
+  return StatusCode::SUCCESS;
+}
+
+//==============================================================================
+StatusCode AsgElectronRingerSelector::beginEvent(){
+  // This doesn't do anything for now, return gracefully:
+  return StatusCode::SUCCESS;
+}
+
+#endif // RINGER_STANDALONE
+
+// =============================================================================
+void AsgElectronRingerSelector::retrieveFileConf(const char *fileName, 
+    IOConfStruct &fileConf)
+{
+  // Try to open file and check if nothing wrong happened:
+  TFile file(fileName, "READ");
+  IOHelperFcns::checkFile( file );
+
+  TDirectory* configDir = file.GetDirectory("");
+
+  // When start using a version that this properties MUST be defined
+  // in the file, change the max to the version value and implement
+  // the else routine where it does throw.
+  if ( IOHelperFcns::getWrittenVersion(configDir) 
+      < std::numeric_limits<unsigned int>::max() )
+  {
+    try {
+      IOHelperFcns::readVar( configDir, 
+          "useTrackPat", 
+          fileConf.useTrackPat );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir, 
+          "useRawTrackPat", 
+          fileConf.useRawTrackPat );
+    } catch( std::runtime_error & ){;}
+    //try {
+    //  IOHelperFcns::readVar( configDir,
+    //      "useRawCalStdPat",
+    //      fileConf.useRawCalStdPat );
+    //} catch( std::runtime_error & ){;}
+    //try {
+    //  IOHelperFcns::readVar( configDir,
+    //      "useCalStdPat",
+    //      fileConf.useCaloCommittee );
+    //} catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "useCaloCommittee",
+          fileConf.useCaloCommittee );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "useBLOutliers",
+          fileConf.useBLOutliers );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "usePIXOutliers",
+          fileConf.usePIXOutliers );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "useSCTOutliers",
+          fileConf.useSCTOutliers );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "useTRTOutliers",
+          fileConf.useTRTOutliers );
+    } catch( std::runtime_error & ){;}
+    try {
+      IOHelperFcns::readVar( configDir,
+          "useTRTXenonHits",
+          fileConf.useTRTXenonHits );
+    } catch( std::runtime_error & ){;}
+  } /* else if */
+
+  file.Close();
+  return;
+}
+
+// =============================================================================
+void AsgElectronRingerSelector::writeConf(const char* fileName, 
+    IOConfStruct &fileConf)
+{
+  // Try to open file and check if nothing wrong happened:
+  TFile file(fileName, "UPDATE");
+  IOHelperFcns::checkFile( file );
+
+  TDirectory* configDir = file.GetDirectory("");
+
+  IOHelperFcns::writeVar( configDir, 
+      "useTrackPat", 
+      fileConf.useTrackPat );
+  IOHelperFcns::writeVar( configDir, 
+      "useRawTrackPat", 
+      fileConf.useRawTrackPat );
+  //IOHelperFcns::writeVar( configDir,
+  //    "useRawCalStdPat",
+  //    fileConf.useRawCalStdPat );
+  //IOHelperFcns::writeVar( configDir,
+  //    "useCalStdPat",
+  //    fileConf.useCaloCommittee );
+  IOHelperFcns::writeVar( configDir,
+      "useCaloCommittee",
+      fileConf.useCaloCommittee );
+  IOHelperFcns::writeVar( configDir,
+      "useBLOutliers",
+      fileConf.useBLOutliers );
+  IOHelperFcns::writeVar( configDir,
+      "usePIXOutliers",
+      fileConf.usePIXOutliers );
+  IOHelperFcns::writeVar( configDir,
+      "useSCTOutliers",
+      fileConf.useSCTOutliers );
+  IOHelperFcns::writeVar( configDir,
+      "useTRTOutliers",
+      fileConf.useTRTOutliers );
+  IOHelperFcns::writeVar( configDir,
+      "useTRTXenonHits",
+      fileConf.useTRTXenonHits );
+  file.Close();
+}
+
+// =============================================================================
+void AsgElectronRingerSelector::printConf( IOConfStruct &fileConf, 
+    MsgStream *msg, MSG::Level lvl)
+{
+  if ( msg && msg->level() <= lvl ){
+    auto flags = static_cast<std::ios_base::fmtflags>(msg->flags());
+    (*msg) << lvl << "File configuration is: " << endreq;
+    (*msg) << lvl << std::boolalpha << "useTrackPat: " << fileConf.useTrackPat 
+      << " | useRawTrackPat: " << fileConf.useRawTrackPat 
+      << " | useCaloCommittee: " << fileConf.useCaloCommittee
+      << " | useBLOutliers: " << fileConf.useBLOutliers
+      << " | usePIXOutliers: " << fileConf.usePIXOutliers
+      << " | useSCTOutliers: " << fileConf.useSCTOutliers
+      << " | useTRTOutliers: " << fileConf.useTRTOutliers
+      << " | useTRTXenonHits: " << fileConf.useTRTXenonHits 
+      << endreq;
+    // reset previous cout flags
+    msg->flags(flags);
+  }
+}
+
+
+} // namespace Ringer
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/ElectronTAccept.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/ElectronTAccept.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..196f6f67181fd824dda29973c11eb86f0f059ac5
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/ElectronTAccept.cxx
@@ -0,0 +1,137 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ElectronTAccept.cxx 704615 2015-10-29 18:50:12Z wsfreund $
+#ifndef RINGER_STANDALONE
+
+#include "RingerSelectorTools/ElectronTAccept.h"
+
+#include "RingerSelectorTools/tools/DeclareBit.h"
+
+namespace Ringer {
+
+// link this namespace to the static counter
+COUNTER_LINK_NAMESPACE
+
+// This is the counter which will check if we ran out of bits
+DEFINE_COUNTER( ElectronNBits )
+
+// =============================================================================
+/// Define the ElectronTAcceptHolder_v1 holden TAccept:
+Root::TAccept ElectronTAccept_v1::m_accept("ElectronDecisionMask");
+
+// =============================================================================
+// Define the bit counter:
+unsigned BitdefElectron_v1::m_nUsedBits = 0;
+
+// =============================================================================
+/// Bit set to true when no error occurs:
+DECLARE_BIT(BitdefElectron_v1, NoErrorBit,
+    "Bit destinated to flag error occurrance.",
+    ElectronNBits )
+
+// =============================================================================
+// Bit to flag whether track CutID was run:
+DECLARE_BIT(BitdefElectron_v1, ExecCutID,
+    "Flag whether executed Ringer holden CutID algorithm.",
+    ElectronNBits )
+
+// =============================================================================
+/// The decision position of the CutID:
+DECLARE_BIT(BitdefElectron_v1, CutIDDec,
+    "Ringer holden CutID algorithm decision.",
+    ElectronNBits )
+
+// =============================================================================
+/// The decision position of the Ringer algorithm's discrimation chain:
+DECLARE_BIT(BitdefElectron_v1, RingerChainDec,
+    "Ringer algorithm discrimation chain decision." , 
+    ElectronNBits )
+
+// =============================================================================
+unsigned int ElectronTAccept_v1::getAppliedCutMsk( const Requirement cut, 
+    bool withCutIDTrack)
+{
+  // Create an empty word:
+  ElectronTAccept_v1::bitMskWord word(0);
+
+  switch (cut) {
+    case  Requirement::Loose_CutID_Pd:
+    case  Requirement::Loose_CutID_Pf:
+    case  Requirement::Loose_LH_Pd:
+    case  Requirement::Loose_LH_Pf:
+    case  Requirement::Loose:
+      // Add for all loose configuration their cuts applied:
+      ElectronTAccept_v1::addLooseAppliedCuts(word);
+      break;
+    case  Requirement::Medium_CutID_Pd:
+    case  Requirement::Medium_CutID_Pf:
+    case  Requirement::Medium_LH_Pd:
+    case  Requirement::Medium_LH_Pf:
+    case  Requirement::Medium_MaxSP:
+    case  Requirement::Medium:
+      // Add for all medium configuration their cuts applied:
+      ElectronTAccept_v1::addMediumAppliedCuts(word);
+      break;
+    case  Requirement::Tight_CutID_Pf:
+    case  Requirement::Tight_CutID_Pd:
+    case  Requirement::Tight_LH_Pf:
+    case  Requirement::Tight_LH_Pd:
+    case  Requirement::Tight:
+      // Add for all tight configuration their cuts applied:
+      ElectronTAccept_v1::addTightAppliedCuts(word);
+      break;
+    case  Requirement::NoCut:
+      // Just for safity, reset mask bits:
+      ElectronTAccept_v1::resetMsk(word);
+      break;
+    default:
+      throw std::runtime_error(std::string("Unknown required cut."));
+  }
+  // If we requested to add track cuts, add them:
+  if (withCutIDTrack) {
+    ElectronTAccept_v1::addCutIDTrackAppliedCuts(word);
+  }
+  return word.to_ulong();
+}
+
+// =============================================================================
+void ElectronTAccept_v1::resetMsk(bitMskWord& word)
+{
+  word.reset();
+}
+
+// =============================================================================
+void ElectronTAccept_v1::addLooseAppliedCuts(bitMskWord& word)
+{
+  word.set(BitdefElectron_v1::NoErrorBit);
+  word.set(BitdefElectron_v1::RingerChainDec);
+}
+
+// =============================================================================
+void ElectronTAccept_v1::addMediumAppliedCuts(bitMskWord& word)
+{
+  word.set(BitdefElectron_v1::NoErrorBit);
+  word.set(BitdefElectron_v1::RingerChainDec);
+}
+
+// =============================================================================
+void ElectronTAccept_v1::addTightAppliedCuts(bitMskWord& word)
+{
+  word.set(BitdefElectron_v1::NoErrorBit);
+  word.set(BitdefElectron_v1::RingerChainDec);
+}
+
+// =============================================================================
+void ElectronTAccept_v1::addCutIDTrackAppliedCuts(
+    bitMskWord& word)
+{
+  word.set(BitdefElectron_v1::ExecCutID);
+  word.set(BitdefElectron_v1::CutIDDec);
+}
+
+} // namespace Ringer
+
+#endif
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/RingerSelectorToolsDefs.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/RingerSelectorToolsDefs.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9fffa79d3571d8a8ac19dda9070ed444580011b7
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/RingerSelectorToolsDefs.cxx
@@ -0,0 +1,234 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerSelectorToolsDefs.cxx 670599 2015-05-28 14:15:35Z wsfreund $
+#include "RingerSelectorTools/RingerSelectorToolsDefs.h"
+
+#ifndef RINGER_STANDALONE
+#include "xAODCaloRings/CaloRingsDefs.h"
+#endif
+
+// Local includes:
+#include "RingerSelectorTools/tools/Exceptions.h"
+
+namespace Ringer {
+
+// =============================================================================
+unsigned numberOfSegments(const SegmentationType e)
+{
+  switch (e){
+    case SegmentationType::NoSegmentation:
+      return 1;
+      break;
+    case SegmentationType::TrackCalSegmentation:
+      return numberOfSegments(SegmentationType::NoSegmentation) + 1;
+      break;
+    case SegmentationType::TrackCalPatTypeSegmentation:
+      return numberOfSegments(SegmentationType::TrackCalSegmentation) + 1;
+      break;
+    case SegmentationType::TrackCalJointSections:
+      return numberOfSegments(TrackCalPatTypeSegmentation) - 1 + 
+#ifdef RINGER_STANDALONE
+        2;
+#else
+        CalJointSection::NJointSections;
+#endif
+      break;
+    case SegmentationType::TrackCalJointLayers:
+      return numberOfSegments(TrackCalPatTypeSegmentation) - 1 + 
+#ifdef RINGER_STANDALONE
+        7;
+#else
+        CalJointLayer::NJointLayers;
+#endif
+      break;
+    default:
+      throw std::runtime_error(std::string("Could not recognize ") +
+            "SegmentationType(" + std::to_string(int(e)) + 
+            ") to numberOfSegments method on RingerSelectorToolsDefs.cxx"
+            " file.");
+  }
+}
+
+// =============================================================================
+template<>
+SegmentationType getType(const char* cStr)
+{
+  std::string strType(cStr);
+  if (strType=="NoSegmentation"){
+    return NoSegmentation;
+  } else if ( strType=="TrackCalSegmentation" ){
+    return TrackCalSegmentation;
+  } else if ( strType=="TrackCalPatTypeSegmentation" ){
+    return TrackCalPatTypeSegmentation;
+  } else if ( strType=="TrackCalJointSections" ){
+    return TrackCalJointSections;
+  } else if ( strType == "TrackCalJointLayers" ){
+    return TrackCalJointLayers;
+  } else {
+    throw Exceptions::no_such_type("SegmentationType",strType,
+        "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+template<>
+EtaDependency getType(const char* cStr)
+{
+  std::string strType(cStr);
+  if (strType=="EtaIndependent"){
+    return EtaIndependent; 
+  } else if ( strType=="EtaDependent" ){
+    return EtaDependent;
+  } else {
+    throw Exceptions::no_such_type("EtaDependency",strType,
+        "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+template<>
+EtDependency getType(const char* cStr)
+{
+  std::string strType(cStr);
+  if (strType=="EtIndependent"){
+    return EtIndependent; 
+  } else if ( strType=="EtDependent" ){
+    return EtDependent;
+  } else {
+    throw Exceptions::no_such_type("EtDependency",strType,
+        "RingerSelectorToolsDefs");
+  }
+}
+// =============================================================================
+template<>
+Requirement getType(const char* cStr)
+{
+  std::string strType(cStr);
+  if ( strType=="Loose" ) {
+    return Loose;
+  } else if ( strType=="Medium" ) {
+    return Medium;
+  } else if ( strType=="Tight" ) {
+    return Tight;
+  } else if (strType=="Loose_CutID_Pd"){
+    return Loose_CutID_Pd;
+  } else if ( strType=="Medium_CutID_Pd" ) {
+    return Medium_CutID_Pd;
+  } else if ( strType=="Tight_CutID_Pd" ) {
+    return Tight_CutID_Pd;
+  } else if (strType=="Loose_CutID_Pd"){
+    return Loose_CutID_Pf;
+  } else if ( strType=="Medium_CutID_Pf" ) {
+    return Medium_CutID_Pf;
+  } else if ( strType=="Tight_CutID_Pf" ) {
+    return Tight_CutID_Pf;
+  } else if ( strType=="Medium_MaxSP" ) {
+    return Medium_MaxSP;
+  } else if ( strType=="NoCut" ) {
+    return NoCut;
+  } else {
+    throw Exceptions::no_such_type("Requirement",strType,
+        "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+const char* toStr(SegmentationType e)
+{
+  switch (e){
+    case SegmentationType::NoSegmentation:
+      return "NoSegmentation";
+      break;
+    case SegmentationType::TrackCalSegmentation:
+      return "TrackCalSegmentation";
+      break;
+    case SegmentationType::TrackCalPatTypeSegmentation:
+      return "TrackCalPatTypeSegmentation";
+      break;
+    case SegmentationType::TrackCalJointSections:
+      return "TrackCalJointSections";
+      break;
+    case SegmentationType::TrackCalJointLayers:
+      return "TrackCalJointLayers";
+      break;
+    default:
+      throw Exceptions::no_such_type(e, "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+const char* toStr(EtaDependency e)
+{
+  switch (e){
+    case EtaDependency::EtaDependent:
+      return "EtaDependent";
+      break;
+    case EtaDependency::EtaIndependent:
+      return "EtaIndependent";
+      break;
+    default:
+      throw Exceptions::no_such_type(e, "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+const char* toStr(EtDependency e)
+{
+  switch (e){
+    case EtDependency::EtDependent:
+      return "EtDependent";
+      break;
+    case EtDependency::EtIndependent:
+      return "EtIndependent";
+      break;
+    default:
+      throw Exceptions::no_such_type(e, "RingerSelectorToolsDefs");
+  }
+}
+
+// =============================================================================
+const char* toStr(Requirement e)
+{
+  switch (e){
+    case Requirement::Loose:
+      return "Loose";
+      break;
+    case Requirement::Medium:
+      return "Medium";
+      break;
+    case Requirement::Tight:
+      return "Tight";
+      break;
+    case Requirement::Loose_CutID_Pd:
+      return "Loose_CutID_Pd";
+      break;
+    case Requirement::Medium_CutID_Pd:
+      return "Medium_CutID_Pd";
+      break;
+    case Requirement::Tight_CutID_Pd:
+      return "Tight_CutID_Pd";
+      break;
+    case Requirement::Loose_CutID_Pf:
+      return "Loose_CutID_Pf";
+      break;
+    case Requirement::Medium_CutID_Pf:
+      return "Medium_CutID_Pf";
+      break;
+    case Requirement::Tight_CutID_Pf:
+      return "Tight_CutID_Pf";
+      break;
+    case Requirement::Medium_MaxSP:
+      return "Medium_MaxSP";
+      break;
+    case Requirement::NoCut:
+      return "NoCut";
+      break;
+    default:
+      throw Exceptions::no_such_type(e, "RingerSelectorToolsDefs");
+  }
+}
+
+} // namespace Ringer
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/IRingerProcedure.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/IRingerProcedure.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aad7b97deaa8d5242bd049b2b47ad135e5245e65
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/IRingerProcedure.cxx
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IRingerProcedure.cxx 667905 2015-05-18 19:07:55Z wsfreund $
+#include "RingerSelectorTools/procedures/IRingerProcedure.h"
+
+#if !(RINGER_USE_NEW_CPP_FEATURES || defined(FORCE_RINGER_PROCEDURE_TYPE_CONST_EXPR))
+template< typename procedure_t >
+const bool RingerProcedureType<procedure_t>::is_pre_processor = 
+    Ringer::is_base_of<PreProcessing::IPreProcessor,procedure_t>::value;
+
+template< typename procedure_t >
+const bool RingerProcedureType<procedure_t>::is_discriminator = 
+    Ringer::is_base_of<Discrimination::IDiscriminator,procedure_t>::value;
+
+template< typename procedure_t >
+const bool RingerProcedureType<procedure_t>::is_threshold = 
+    Ringer::is_base_of<Discrimination::IThreshold,procedure_t>::value;
+#endif
+
+
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/NeuralNetwork.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/NeuralNetwork.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e17cb5d5c5b6272ce6faa980bab7197c60ebee7d
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/NeuralNetwork.cxx
@@ -0,0 +1,284 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: NeuralNetwork.cxx 704615 2015-10-29 18:50:12Z wsfreund $
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+
+// STL includes:
+#include <vector>
+#include <cmath>
+#include <exception>
+#include <algorithm>
+
+//#undef NDEBUG
+
+//#include <boost/python/stl_iterator.hpp>
+
+namespace Ringer {
+
+//template< typename T >
+//inline
+//std::vector< T > to_std_vector( const boost::python::object& iterable )
+//{
+//  return std::vector< T >( boost::python::stl_input_iterator< T >( iterable ),
+//      boost::python::stl_input_iterator< T >( ) );
+//}
+
+namespace Discrimination {
+
+// =============================================================================
+NNFeedForward::NNFeedForward(
+    const std::vector<unsigned int> &n, 
+    const std::vector<float> &w, 
+    const std::vector<float> &b)
+  : m_wM(nullptr),
+    m_bM(nullptr),
+    m_mM(nullptr)
+{
+  changeArchiteture(n,w,b);
+}
+
+
+// =============================================================================
+// void NNFeedForward::changeArchiteture(
+//     boost::python::list &n, 
+//     boost::python::list &w, 
+//     boost::python::list &b)
+// {
+//   changeArchiteture(to_std_vector<unsigned int>(n), 
+//       to_std_vector<float>(w),
+//       to_std_vector<float>(b));
+// }
+
+// =============================================================================
+void NNFeedForward::changeArchiteture(
+    const std::vector<unsigned int> &n, 
+    const std::vector<float> &w, 
+    const std::vector<float> &b)
+{
+
+  if ( n.empty() ) {
+    throw std::invalid_argument(
+        std::string("Invalid node argument (empty)."));
+  }
+  //Verifying weight vector size
+  unsigned int wSize=0;
+  for (unsigned int k=0; k<n.size()-1; ++k) {
+    wSize+=n[k]*n[k+1];
+  }
+  if (wSize != w.size() || !w.size() ) {
+    throw std::invalid_argument(
+      std::string("Invalid weight argument."));
+  }
+  //Verifying bias vector size
+  unsigned int bSize=0;
+  for (unsigned int k=1; k<n.size(); ++k) {
+    bSize+=n[k];
+  }
+  if(bSize != b.size() || !b.size() ) {
+    throw std::invalid_argument(
+      std::string("Invalid bias argument."));
+  }
+
+  // Configuration is ok, copy it:
+  m_nodes = n;
+  m_nLayers = n.size();
+
+  // Release possible older architeture:
+  releaseWeights();
+  releaseBias();
+  releaseMMatrix();
+
+  //First weight dimension
+  m_wM = new float **[m_nLayers-1]; //number of layers excluding input
+  //First bias dimension
+  m_bM = new float *[m_nLayers-1]; //number of layers excluding input
+  //First multiplication dimension
+  m_mM = new float *[m_nLayers]; //number of layers including input
+
+  for (unsigned int l = 0; l<m_nLayers; ++l){ 
+    m_mM[l] = new float[n[l]]; //number of m_nodes in current layer
+  }
+  std::vector<float>::const_iterator itrB = b.begin();
+  std::vector<float>::const_iterator itrW = w.begin();
+  for (unsigned int l = 0; l < m_nLayers-1; ++l){  
+    //Second and last dimension of m_bM
+    m_bM[l] = new float[n[l+1]]; //number of m_nodes in next layer
+    //Second dimension of m_wM
+    m_wM[l] = new float*[n[l+1]]; //number of m_nodes in next layer
+    for (unsigned int i=0; i<n[l+1]; i++){ 
+      //Third and last dimension of m_wM
+      m_wM[l][i]=new float [n[l]]; //number of m_nodes in current layer
+      //Populating bias matrix
+      m_bM[l][i]=(*itrB++);
+      //Populating weight matrix
+      for (unsigned int j=0; j<n[l]; j++){
+        m_wM[l][i][j]=(*itrW++);
+      }
+    }
+    //Populating multiplication matrix so that starting sum equals zero
+    for (unsigned int i=0; i<n[l]; i++){
+      m_mM[l][i]=0;
+    }   
+  }
+}
+
+// =============================================================================
+void NNFeedForward::releaseBias(){
+  if (m_bM){
+    for (unsigned int l=0; l<m_nodes.size()-1; ++l){
+      delete[] m_bM[l]; //Deletes array of values at second dimension of m_bM
+    } 
+  }
+  delete[] m_bM; //Deletes array of pointers at first dimension of m_bM
+  m_bM = nullptr;
+}
+
+// =============================================================================
+void NNFeedForward::releaseWeights(){
+  if (m_wM){ 
+    for (unsigned int l=0; l<m_nodes.size()-1; ++l){
+      if (m_wM[l]){
+        for (unsigned int i=0; i<m_nodes[l+1]; ++i){
+          delete[] m_wM[l][i]; //Deletes array of values at third dimension of m_wM
+        }
+      }
+      delete[] m_wM[l]; // Deletes array of pointers at second dimension of m_wM
+    }
+  }
+  delete[] m_wM; //Deletes array of pointers at first dimension of m_wM
+  m_wM = nullptr;
+}
+
+// =============================================================================
+void NNFeedForward::releaseMMatrix(){
+  if(m_mM){
+    for (unsigned int l=0; l<m_nodes.size(); ++l){
+      delete[] m_mM[l]; //Deletes array of values at second dimension of m_mM
+    }
+  }
+  delete[] m_mM; //Deletes array of pointers at first dimension of m_mM
+  m_mM = nullptr;
+}
+
+
+// =============================================================================
+NNFeedForward::~NNFeedForward()
+{
+  releaseWeights();
+  releaseBias();
+  releaseMMatrix();
+}
+
+// =============================================================================
+void NNFeedForward::execute(
+    const std::vector<float> &input,
+    std::vector<float> &output) const 
+{
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying NNFeedForward. Pattern space is: " << input);
+#endif
+  if ( input.size() != m_nodes[0] ){
+    throw std::runtime_error(std::string("Pattern space size (") + 
+        std::to_string(input.size()) + ") fed to discriminator is "
+        "not compatible with this discriminator pattern space size ("
+        + std::to_string(m_nodes[0]) + ".");
+  }
+  // Copy vector to input layer:
+  for(unsigned int i=0; i<input.size();i++){
+    m_mM[0][i]=input[i];
+  }
+  // Propagate:
+  for(unsigned int l=0; l<m_nodes.size()-1;l++){
+    for(unsigned int k=0; k<m_nodes[l+1]; k++){
+      m_mM[l+1][k]=m_bM[l][k];
+      for (unsigned int j=0;j<m_nodes[l]; j++){
+        m_mM[l+1][k]+=m_mM[l][j]*m_wM[l][k][j];
+      }
+      m_mM[l+1][k]=tanh(m_mM[l+1][k]);
+    }
+  }
+
+  // Resize output to hold new entries
+  output.clear();
+
+  // Insert result at output vector:
+  output.insert( output.begin(),
+      m_mM[m_nLayers-1],
+      m_mM[m_nLayers-1] + m_nodes[m_nLayers-1]
+    );
+
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Output space is: " << output);
+#endif
+}
+
+// =============================================================================
+void NNFeedForward::getWeigthsAndBias(std::vector<float> &weights,
+    std::vector<float> &bias) const
+{
+  weights.clear();
+  bias.clear();
+  for ( size_t cLayer = 0; cLayer < m_nLayers - 1; ++cLayer ){
+    unsigned nCurLayer = m_nodes[cLayer];
+    unsigned nNextLayer = m_nodes[cLayer+1];
+    for ( unsigned cNextLayer = 0; cNextLayer < nNextLayer; ++cNextLayer ){
+      float *weight_ptr = m_wM[cLayer][cNextLayer];
+      std::copy( weight_ptr , weight_ptr + nCurLayer, back_inserter(weights));
+    }
+    float *bias_ptr = m_bM[cLayer];
+    std::copy(bias_ptr, bias_ptr + nNextLayer, back_inserter(bias));
+  }
+}
+
+
+// =============================================================================
+void NNFeedForward::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  std::vector<float> weights, bias;
+  getWeigthsAndBias(weights, bias);
+  msg() << lvl << "Nodes: " << m_nodes << endreq;
+  msg() << static_cast<MSG::Level>((lvl>MSG::VERBOSE)?(lvl-1):(lvl)) 
+    << "Vectorized Weights: " << weights << endreq;
+  msg() << static_cast<MSG::Level>((lvl>MSG::VERBOSE)?(lvl-1):(lvl)) 
+    << "Vectorized Bias: " << bias << endreq;
+}
+
+// =============================================================================
+void NNFeedForward::read(NNFeedForward *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  std::vector<unsigned int> nodes;
+  std::vector<float> weights, bias;
+  IOHelperFcns::readVar(configDir, "nodes", nodes); 
+  IOHelperFcns::readVar(configDir, "weights", weights); 
+  IOHelperFcns::readVar(configDir, "bias", bias); 
+  newObj->changeArchiteture(nodes,weights,bias);
+}
+
+// =============================================================================
+void NNFeedForward::write(TDirectory *configDir, const char *) const
+{
+  if ( m_nLayers && m_wM && m_bM ){
+    std::vector<float> weights, bias;
+    getWeigthsAndBias(weights, bias);
+    IOHelperFcns::writeVar(configDir, "nodes",   m_nodes );
+    IOHelperFcns::writeVar(configDir, "weights", weights );
+    IOHelperFcns::writeVar(configDir, "bias",    bias    );
+  } else {
+    std::runtime_error(std::string("Cannot write configuration from empty" 
+          " (or with pointers not allocated) neural network."));
+  }
+}
+
+} // namespace Discrimination
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Normalizations.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Normalizations.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..264cffc03a4f9b035178edf79e22fc158cbfed18
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Normalizations.cxx
@@ -0,0 +1,293 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Normalizations.cxx 667905 2015-05-18 19:07:55Z wsfreund $
+#include "RingerSelectorTools/procedures/Normalizations.icc"
+
+#include <algorithm>
+
+/** 
+ * @brief Namespace dedicated for Ringer utilities 
+ **/
+namespace Ringer
+{
+
+/** 
+* @brief Namespace dedicated for Ringer pre-processing utilities 
+**/
+namespace PreProcessing
+{
+
+/** 
+ * @brief Namespace dedicated for Ringer normalization utilities 
+ **/
+namespace Norm {
+
+/** 
+ * @brief Helper functions:
+ **/
+namespace {
+// =============================================================================
+inline
+void applySequentialNorm( std::vector<float> &inputSpace, 
+    const float norm, 
+    const float stopEnergy )
+{
+  bool fixed = false;
+  float curNorm = norm;
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    if ( curNorm < stopEnergy ){ 
+      fixed = true;
+    }
+    if ( fixed ) { // Do not increase noise description:
+      curNorm = norm;
+    } else {
+      *itr /= curNorm;
+      curNorm -= *itr; 
+    }
+  }
+
+  if (!norm) return;
+
+  float invNorm = 1/norm;
+  for ( std::vector<float>::iterator itr = inputSpace.begin();
+        itr != inputSpace.end();
+        ++itr){
+    *itr *= invNorm;
+  }
+}
+
+// =============================================================================
+struct minus {
+  float operator()(float in) {
+    return -in;
+  }
+};
+
+
+// =============================================================================
+struct invert {
+  float operator()(float in) {
+    if(in){
+      return 1/in;
+    } else {
+      throw std::runtime_error("Attempt to invert zero");
+    }
+  }
+};
+
+} // Private namespace
+
+// =============================================================================
+void ConstantValue::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  msg() << lvl << "Constant normalization: " << 1/m_constantInv << endreq;
+}
+
+// =============================================================================
+void ConstantValue::read(ConstantValue *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  IOHelperFcns::readVar(configDir, "constantInv", newObj->m_constantInv); 
+}
+
+// =============================================================================
+void ConstantValue::write(TDirectory *configDir, const char *) const
+{
+  IOHelperFcns::writeVar(configDir, "constantInv", m_constantInv );
+}
+
+// =============================================================================
+void Sequential::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  msg() << lvl << "stopEnergy: " << m_stopEnergy << endreq;
+  msg() << lvl << "energyThres: " << m_energyThres << endreq;
+}
+
+// =============================================================================
+void Sequential::read(Sequential *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  IOHelperFcns::readVar(configDir, "stopEnergy", newObj->m_stopEnergy); 
+  IOHelperFcns::readVar(configDir, "energyThres", newObj->m_energyThres); 
+}
+
+// =============================================================================
+void Sequential::write(TDirectory *configDir, const char *) const
+{
+  IOHelperFcns::writeVar(configDir, "stopEnergy", m_stopEnergy );
+  IOHelperFcns::writeVar(configDir, "energyThres", m_energyThres );
+}
+
+// =============================================================================
+void Sequential::execute(std::vector<float> &inputSpace) const {
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Applying sequential. Input space is: " << inputSpace);
+#endif
+  float norm1 = getNorm(inputSpace,1);
+  if ( norm1 < m_stopEnergy ) {
+    float max = getMax(inputSpace); 
+    // If normalization value is very low, do not normalize:
+    if ( norm1 < m_energyThres || max < m_energyThres ) return;
+    // Otherwise normalize with the greater norm value:
+    if ( norm1 < max ){
+      applyNorm(inputSpace,max);
+    } else {
+      applyNorm(inputSpace,norm1);
+    }
+  } else {
+    // Otherwise use sequential normalization:
+    applySequentialNorm( inputSpace, norm1, m_stopEnergy );
+  }
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Pattern space is: " << inputSpace);
+#endif
+}
+
+// =============================================================================
+void Spherization::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  msg() << lvl << "deslocation: " << m_deslocation << endreq;
+  msg() << lvl << "normInv: " << m_normInv << endreq;
+}
+
+// =============================================================================
+void Spherization::read(Spherization *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  IOHelperFcns::readVar(configDir, "deslocation", newObj->m_deslocation ); 
+  IOHelperFcns::readVar(configDir, "normInv",     newObj->m_normInv     ); 
+  newObj->m_dim = newObj->m_deslocation.size();
+}
+
+// =============================================================================
+void Spherization::write(TDirectory *configDir, const char *) const
+{
+  IOHelperFcns::writeVar(configDir, "deslocation", m_deslocation );
+  IOHelperFcns::writeVar(configDir, "normInv",     m_normInv     );
+}
+
+// =============================================================================
+Spherization::Spherization(
+    const std::vector<float> &dataMean,
+    const std::vector<float> &dataStd)
+  : m_dim(dataMean.size())
+{
+  if ( dataMean.empty() || dataStd.empty() ){
+    throw std::runtime_error(std::string("Either DataMean or DataStd "
+          "vectors have no dimension.") );
+  }
+  if ( dataMean.size() != dataStd.size() ){
+    throw std::runtime_error(std::string("DataMean and DataStd vectors do "
+          "no have same dimension."));
+  }
+  m_deslocation.resize(m_dim);
+  m_normInv.resize(m_dim);
+  try {
+    std::transform( dataMean.begin(), 
+        dataMean.end(),
+        m_deslocation.begin(),
+        minus()  );
+
+    std::transform( dataStd.begin(), 
+        dataStd.end(),
+        m_normInv.begin(),
+        invert() );
+  } catch ( const std::runtime_error & ){
+    throw std::runtime_error(std::string("Attempted to create Spherization "
+          "with null standard deviation"));
+  }
+}
+
+
+// =============================================================================
+void MinMax::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  msg() << lvl << "deslocation: " << m_deslocation << endreq;
+  msg() << lvl << "normInv: " << m_normInv << endreq;
+}
+
+// =============================================================================
+void MinMax::read(MinMax *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  IOHelperFcns::readVar(configDir, "deslocation",  newObj->m_deslocation     ); 
+  IOHelperFcns::readVar(configDir, "normInv",      newObj->m_normInv         );
+  newObj->m_dim = newObj->m_deslocation.size();
+}
+
+// =============================================================================
+void MinMax::write(TDirectory *configDir, const char* ) const
+{
+  IOHelperFcns::writeVar(configDir, "deslocation", m_deslocation );
+  IOHelperFcns::writeVar(configDir, "normInv",     m_normInv     );
+}
+
+// =============================================================================
+MinMax::MinMax(
+    const std::vector<float> min,
+    const std::vector<float> max)
+  : m_dim(min.size())
+{
+  if ( min.empty() || max.empty() ){
+    throw std::runtime_error(std::string("Either Min or max vectors have no "
+          "dimension."));
+  }
+  if ( min.size() != max.size() ){
+    throw std::runtime_error(std::string("Min and max vectors do no have same "
+          "dimension."));
+  }
+
+  m_deslocation.reserve(m_dim);
+  m_normInv.reserve(m_dim);
+
+  for (size_t idx = 0; idx < m_dim; ++idx ) {
+    m_deslocation.push_back(-((max[idx]+min[idx])/2));
+    m_normInv.push_back(2/(max[idx]-min[idx]));
+    if (!m_normInv[idx]) {
+      throw std::runtime_error(
+          std::string("MinMax should have different minimum and maximum "
+            "values."));
+    }
+  }
+}
+
+} // namespace Norm
+} // namespace PreProcessing
+} // namespace Ringer
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerDiscriminatorWrapper.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerDiscriminatorWrapper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ad3d14b9090f2b8c798c4cd5b9f7e03a67d399ca
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerDiscriminatorWrapper.cxx
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerDiscriminatorWrapper.cxx 670599 2015-05-28 14:15:35Z wsfreund $
+#include "RingerSelectorTools/procedures/RingerDiscriminatorWrapper.h"
+
+namespace Ringer {
+#if !(RINGER_USE_NEW_CPP_FEATURES)
+const char* IDiscrWrapper::wrapName = "RingerDiscriminatorWrapper"; 
+#else
+constexpr const char* IDiscrWrapper::wrapName; 
+#endif
+
+// =============================================================================
+void IDiscrWrapper::writeCol(const IDiscrWrapperCollection &discrWrapperCol, 
+    const char *fileName)
+{
+  TFile wrapperFile(fileName, "UPDATE");
+  IOHelperFcns::checkFile( wrapperFile );
+
+  TDirectory* configDir = wrapperFile.GetDirectory("");
+
+  // Add package version to directory
+  IOHelperFcns::writeVersion(configDir);
+
+  // Write discrimination wrappers:
+  unsigned discrWrapperSize = discrWrapperCol.size();
+  IOHelperFcns::writeVar( configDir, "discrWrapperSize", discrWrapperSize );
+  for (size_t discrIdx = 0;  discrIdx < discrWrapperSize; ++discrIdx ) {
+    // Write wrapper on the file:
+    discrWrapperCol[discrIdx]->write(configDir, 
+        IOHelperFcns::makeIdxStr(discrIdx).c_str());
+  }
+
+  // Write and close file
+  wrapperFile.Write();
+  wrapperFile.Close();
+}
+
+// =============================================================================
+void IDiscrWrapper::read(IDiscrWrapperCollection &discrWrapperCol, 
+    const char* fileName)
+{
+  // Try to open file and check if nothing wrong happened:
+  TFile wrapperFile(fileName, "READ");
+  IOHelperFcns::checkFile( wrapperFile );
+  TDirectory* configDir = wrapperFile.GetDirectory("");
+
+  // Get written version:
+  unsigned version = IOHelperFcns::getWrittenVersion( configDir );
+
+  // Get its size:
+  unsigned discrWrapperSize(0);
+  IOHelperFcns::readVar( configDir, "discrWrapperSize", discrWrapperSize );
+
+  // Cycle through discrimination collection and fill it:
+  for ( unsigned counter = 0; counter < discrWrapperSize; ++counter) {
+    std::string folderName = IDiscrWrapper::wrapName +
+      IOHelperFcns::makeIdxStr(counter);
+
+    //ATH_MSG_DEBUG("Reading Discriminatior Wrapper on folder \""
+    //    << folderName << "\"" );
+    TDirectory *discrDir = configDir->GetDirectory(folderName.c_str());
+    if ( discrDir == nullptr || discrDir == configDir )
+    {
+      throw std::runtime_error(std::string("Could not find directory \"")
+            + folderName + "\" containing Discriminatior Wrapper" 
+            "information.");
+    }
+    // Get basic preprocessing wrapper information:
+    discrEnum_t discrType;
+    EtaDependency fileEtaDep;
+    EtDependency fileEtDep;
+    SegmentationType fileSegType;
+    IOHelperFcns::readVar<discrEnum_t, unsigned int>( discrDir, 
+        "discrType",
+        discrType);
+    IOHelperFcns::readVar<SegmentationType, unsigned int>( discrDir,
+        "segType",
+        fileSegType);
+    IOHelperFcns::readVar<EtaDependency, unsigned int>( discrDir, 
+        "etaDependency",
+        fileEtaDep);
+    IOHelperFcns::readVar<EtDependency, unsigned int>( discrDir, 
+        "etDependency",
+        fileEtDep);
+    //ATH_MSG_DEBUG("It's type is " << toStr(discrType) << " and dependency is :["
+    //    << toStr(fileSegType) << ","
+    //    << toStr(fileEtaDep) << "," 
+    //    << toStr(fileEtDep) << "]");
+    // Create wrapper and append it to collection. Here we make some checks
+    // whether the wrapper preprocessing type is not IDiscriminatorVarDep.
+    // For some cases, we have some template specializations.
+    switch ( discrType )
+    {
+      case Discrimination::Type::NNFeedForward:
+      {
+        // We create discrimination wrapper specialized for each segmentation
+        // type for the NeuralNetwork, which is one discriminator that we shall
+        // use frequently.
+        READ_ALL_DEP_WRAPPER(discrWrapperCol, 
+            Discrimination::NNFeedForwardVarDep, 
+            fileSegType, 
+            fileEtaDep, 
+            fileEtDep, 
+            discrDir, 
+            version)
+        break;
+      }
+      default:
+      {
+        //ATH_MSG_DEBUG("Using interface for Discriminatior Wrapper on folder \""
+        //    << folderName << "\" and type \"" << discrType.Data() "\"" );
+        /*
+         * In this case, there is no dedicated wrapper for the collection,
+         * we use the interface then:
+         */
+        READ_ALL_DEP_WRAPPER(discrWrapperCol,
+            Discrimination::IDiscriminatorVarDep,
+            fileSegType,
+            fileEtaDep,
+            fileEtDep,
+            discrDir,
+            version)
+      }
+    }
+  }
+
+  // We already got all the information on the file, we can close it:
+  wrapperFile.Close();
+}
+
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerPreProcessorWrapper.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerPreProcessorWrapper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2927f974e73888dd50ba55168c3afe5258aebe9a
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerPreProcessorWrapper.cxx
@@ -0,0 +1,135 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerPreProcessorWrapper.cxx 670599 2015-05-28 14:15:35Z wsfreund $
+#include "RingerSelectorTools/procedures/RingerPreProcessorWrapper.h"
+
+namespace Ringer {
+#if !(RINGER_USE_NEW_CPP_FEATURES)
+const char* IPreProcWrapper::wrapName = "RingerPreProcessorWrapper"; 
+#else
+constexpr const char* IPreProcWrapper::wrapName; 
+#endif
+
+// =============================================================================
+void IPreProcWrapper::writeCol(const IPreProcWrapperCollection &ppWrapperCol, 
+    TDirectory *configDir)
+{
+  bool hasPP = !( ppWrapperCol.empty() );
+  IOHelperFcns::writeVar( configDir, "hasPP", hasPP );
+  // Write pre-processing wrappers:
+  if (hasPP){
+    // Write pre-processing 
+    unsigned ppWrapperSize = ppWrapperCol.size();
+    IOHelperFcns::writeVar( configDir, "ppWrapperSize", ppWrapperSize );
+    for (size_t ppIdx = 0;  ppIdx < ppWrapperSize; ++ppIdx ) {
+      ppWrapperCol[ppIdx]->write(configDir,
+          IOHelperFcns::makeIdxStr(ppIdx).c_str());
+    }
+  }
+}
+
+// =============================================================================
+void IPreProcWrapper::read(IPreProcWrapperCollection &ppWrapperCol, 
+    TDirectory *configDir, 
+    unsigned version)
+{
+
+  // Get its size:
+  unsigned ppWrapperSize(0);
+  IOHelperFcns::readVar( configDir, "ppWrapperSize", ppWrapperSize );
+
+  // Cycle through pp collection and fill it:
+  for ( unsigned counter = 0; counter < ppWrapperSize; ++counter) {
+    std::string folderName = IPreProcWrapper::wrapName +
+      IOHelperFcns::makeIdxStr(counter);
+
+    //ATH_MSG_DEBUG("Reading PreProcessing Wrapper on folder \""
+    //    << folderName << "\"" );
+    TDirectory *ppDir = configDir->GetDirectory(folderName.c_str());
+    if ( ppDir == nullptr || ppDir == configDir )
+    {
+      throw std::runtime_error(std::string("Could not find directory \"")
+            + folderName + "\" containing PreProcessing Wrapper" 
+            "information.");
+    }
+    // Get basic preprocessing wrapper information:
+    preProcEnum_t ppType;
+    EtaDependency fileEtaDep;
+    EtDependency fileEtDep;
+    SegmentationType fileSegType;
+    IOHelperFcns::readVar<preProcEnum_t, unsigned int>( ppDir, 
+        "ppType",
+        ppType);
+    IOHelperFcns::readVar<SegmentationType, unsigned int>( ppDir,
+        "segType",
+        fileSegType);
+    IOHelperFcns::readVar<EtaDependency, unsigned int>( ppDir, 
+        "etaDependency",
+        fileEtaDep);
+    IOHelperFcns::readVar<EtDependency, unsigned int>( ppDir, 
+        "etDependency",
+        fileEtDep);
+    //ATH_MSG_DEBUG("It's type is " << toStr(ppType) << " and dependency is :["
+    //    << toStr(fileSegType) << ","
+    //    << toStr(fileEtaDep) << "," 
+    //    << toStr(fileEtDep) << "]");
+    // Create wrapper and append it to collection. Here we make some checks
+    // whether the wrapper preprocessing type is not IDiscriminatorVarDep.
+    // For some cases, we have some template specializations.
+    switch ( ppType )
+    {
+      case PreProcessing::Type::Norm1:
+      {
+        if (fileEtaDep || fileEtDep) {
+          throw std::runtime_error(std::string("Cannot have Norm1 Preprocessor "
+                "Wrapper eta/et depedent"));
+        }
+        // We create pre-processing wrapper specialized for each segmentation
+        // type for the norm1, which is one normalization that we shall use
+        // frequently. On the other hand, as it hasn't parameters, it makes
+        // no sense for it to be variable dependent:
+        READ_SEG_DEP_WRAPPER(ppWrapperCol, 
+            PreProcessing::Norm::Norm1VarDep, 
+            fileSegType, 
+            EtaIndependent, 
+            EtIndependent, 
+            ppDir, 
+            version)
+        break;
+      }
+      //case PreProcessing::Norm::Type::Spherization:
+      //{
+      //  //  We might want to uncomment this if we want to use spherization
+      //  // as a normalization procedure:
+      //
+      //  READ_ALL_DEP_WRAPPER(ppWrapperCol, 
+      //      PreProcessing::Norm::SpherizationVarDep, 
+      //      fileSegType, 
+      //      fileEtaDep, 
+      //      fileEtDep, 
+      //      ppDir, 
+      //      version)
+      //}
+      default:
+      {
+        //ATH_MSG_DEBUG("Using interface for PreProcessing Wrapper on folder \""
+        //    << folderName << "\" and type \"" << ppType.Data() "\"" );
+        /*
+         * In this case, there is no dedicated wrapper for the collection,
+         * we use the interface then:
+         */
+        READ_ALL_DEP_WRAPPER(ppWrapperCol,
+            PreProcessing::IPreProcessorVarDep,
+            fileSegType,
+            fileEtaDep,
+            fileEtDep,
+            ppDir,
+            version)
+      }
+    }
+  }
+}
+
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerThresholdWrapper.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerThresholdWrapper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a95d089eb64e595d71241a8b09c2221a650bbb13
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/RingerThresholdWrapper.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerThresholdWrapper.cxx 670599 2015-05-28 14:15:35Z wsfreund $
+#include "RingerSelectorTools/procedures/RingerThresholdWrapper.h"
+
+namespace Ringer {
+#if !(RINGER_USE_NEW_CPP_FEATURES)
+const char* IThresWrapper::wrapName = "RingerThresholdWrapper"; 
+#else
+constexpr const char* IThresWrapper::wrapName; 
+#endif
+
+// =============================================================================
+void IThresWrapper::writeWrapper(const IThresWrapper *thresWrapper, 
+    const char *fileName)
+{
+  TFile wrapperFile(fileName, "UPDATE");
+  IOHelperFcns::checkFile( wrapperFile );
+  TDirectory* configDir = wrapperFile.GetDirectory("");
+
+  // Add package version to directory
+  IOHelperFcns::writeVersion(configDir);
+
+  // Write threshold wrapper-processing wrappers:
+  thresWrapper->write(configDir, IOHelperFcns::makeIdxStr(0).c_str());
+
+  // Write and close file
+  wrapperFile.Write();
+  wrapperFile.Close();
+}
+
+// =============================================================================
+void IThresWrapper::read(IThresWrapper *&thresWrapper, 
+    const char* fileName)
+{
+  // Try to open file and check if nothing wrong happened:
+  TFile wrapperFile(fileName, "READ");
+  IOHelperFcns::checkFile( wrapperFile );
+  TDirectory* configDir = wrapperFile.GetDirectory("");
+
+  // Get written version:
+  unsigned version = IOHelperFcns::getWrittenVersion( configDir );
+
+  std::string folderName = IThresWrapper::wrapName +
+    IOHelperFcns::makeIdxStr(0);
+
+  //ATH_MSG_DEBUG("Reading Discriminatior Wrapper on folder \""
+  //    << folderName << "\"" );
+  TDirectory *thresDir = configDir->GetDirectory(folderName.c_str());
+  if ( thresDir == nullptr || thresDir == configDir )
+  {
+    throw std::runtime_error(std::string("Could not find directory \"")
+          + folderName + "\" containing Discriminatior Wrapper" 
+          "information.");
+  }
+
+  // We create a dummy collection just to use it on the macro
+  IThresWrapperCollection thresWrapperCol;
+
+  // Get basic preprocessing wrapper information:
+  thresEnum_t thresType;
+  EtaDependency fileEtaDep;
+  EtDependency fileEtDep;
+  IOHelperFcns::readVar<thresEnum_t, unsigned int>( thresDir, 
+      "thresType",
+      thresType);
+  IOHelperFcns::readVar<EtaDependency, unsigned int>( thresDir, 
+      "etaDependency",
+      fileEtaDep);
+  IOHelperFcns::readVar<EtDependency, unsigned int>( thresDir, 
+      "etDependency",
+      fileEtDep);
+  //ATH_MSG_DEBUG("It's type is " << toStr(thresType) << " and dependency is :["
+  //    << toStr(fileEtaDep) << "," 
+  //    << toStr(fileEtDep) << "]");
+  // Create wrapper. Here we make some checks whether the wrapper preprocessing
+  // type is not IThresholdVarDep.  For some cases, we have some template
+  // specializations.
+  switch ( thresType )
+  {
+    case Discrimination::Type::UniqueThreshold:
+    {
+      // We create a specialized unique threshold for the UniqueThreshold
+      // configuration: 
+      READ_ETA_ET_DEP_WRAPPER(thresWrapperCol, 
+          Discrimination::UniqueThresholdVarDep, 
+          NoSegmentation, 
+          fileEtaDep, 
+          fileEtDep, 
+          thresDir, 
+          version)
+      break;
+    }
+    default:
+    {
+      //ATH_MSG_DEBUG("Using interface for Discriminatior Wrapper on folder \""
+      //    << folderName << "\" and type \"" << thresType.Data() "\"" );
+      /*
+       * In this case, there is no dedicated wrapper for the collection,
+       * we use the interface then:
+       */
+      READ_ETA_ET_DEP_WRAPPER(thresWrapperCol,
+          Discrimination::IThresholdVarDep,
+          NoSegmentation,
+          fileEtaDep,
+          fileEtDep,
+          thresDir,
+          version)
+    }
+  }
+
+  // Set pointer to memory address from the read thres wrapper.
+  thresWrapper = thresWrapperCol[0];
+
+  // We already got all the information on the file, we can close it:
+  wrapperFile.Close();
+}
+
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Thresholds.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Thresholds.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4ed06b408cfdfa24e303bb08a4a9fc594cdd404b
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Thresholds.cxx
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Thresholds.cxx 667905 2015-05-18 19:07:55Z wsfreund $
+#include "RingerSelectorTools/procedures/Thresholds.icc"
+
+namespace Ringer {
+
+namespace Discrimination {
+
+// =============================================================================
+void UniqueThreshold::print(MSG::Level lvl) const
+{
+  if ( !this->isStreamAvailable() ) {
+    std::cerr << "Cannot print " << this->name() << ", stream unavailable"
+      << std::endl;
+  }
+  if ( this->level() > lvl ) {
+    return;
+  }
+  msg() << lvl << "Threshold: " << m_threshold << endreq;
+}
+
+// =============================================================================
+void UniqueThreshold::read(UniqueThreshold *newObj, 
+    TDirectory *configDir, 
+    unsigned /*version*/ )
+{
+  IOHelperFcns::readVar(configDir, "threshold", newObj->m_threshold); 
+}
+
+// =============================================================================
+void UniqueThreshold::write(TDirectory *configDir, const char *) const
+{
+  IOHelperFcns::writeVar(configDir, "threshold",    m_threshold );
+}
+
+} // namespace Discrimination
+
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Types.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Types.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2672bbe8f1f9a25a85c40b411bdac7cd43293a1d
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/procedures/Types.cxx
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: Types.cxx 667905 2015-05-18 19:07:55Z wsfreund $
+#include "RingerSelectorTools/procedures/Types.h"
+
+#include "RingerSelectorTools/procedures/Normalizations.h"
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+#include "RingerSelectorTools/procedures/Thresholds.h"
+
+#include "RingerSelectorTools/tools/Exceptions.h"
+
+namespace Ringer {
+
+// =============================================================================
+template<>
+preProcEnum_t getType(const char* cStr){
+  using namespace PreProcessing;
+  std::string strType(cStr);
+  if        ( strType == IPreProcessorVarDep::procType() ){
+    return preProcEnum_t::IPreProcessorVarDep;
+  } else if ( strType == Norm::Norm1::procType() ){
+    return preProcEnum_t::Norm1;
+  } else if ( strType == Norm::Norm2::procType() ){
+    return preProcEnum_t::Norm2;
+  } else if ( strType == Norm::Sqrt::procType() ){
+    return preProcEnum_t::Sqrt;
+  } else if ( strType == Norm::ConstantValue::procType() ){
+    return preProcEnum_t::ConstantValue;
+  } else if ( strType == Norm::Sequential::procType() ){
+    return preProcEnum_t::Sequential;
+  } else if ( strType == Norm::Spherization::procType() ){
+    return preProcEnum_t::Spherization;
+  } else if ( strType == Norm::MinMax::procType() ){
+    return preProcEnum_t::MinMax;
+  } else if ( strType == IPreProcessor::procType() ){
+    return preProcEnum_t::IPreProcessor;
+  } else {
+    throw Exceptions::no_such_type("PreProcessorType",strType,"Types");
+  }
+}
+
+// =============================================================================
+template<>
+discrEnum_t getType(const char* cStr){
+  using namespace Discrimination;
+  std::string strType(cStr);
+  if        ( strType == IDiscriminatorVarDep::procType() ){
+    return discrEnum_t::IDiscriminatorVarDep;
+  } else if ( strType == NNFeedForward::procType() ){
+    return discrEnum_t::NNFeedForward;
+  } else if ( strType == IDiscriminator::procType() ){
+    return discrEnum_t::IDiscriminator;
+  } else {
+    throw Exceptions::no_such_type("DiscriminatorType",strType,"Types");
+  }
+}
+
+// =============================================================================
+template<>
+thresEnum_t getType(const char* cStr){
+  using namespace Discrimination;
+  std::string strType(cStr);
+  if        ( strType == IThresholdVarDep::procType() ){
+    return thresEnum_t::IThresholdVarDep;
+  } else if ( strType == UniqueThreshold::procType() ){
+    return thresEnum_t::UniqueThreshold;
+  } else if ( strType == IDiscriminator::procType() ){
+    return thresEnum_t::IThreshold;
+  } else {
+    throw Exceptions::no_such_type("ThresholdType",strType,"Types");
+  }
+}
+// =============================================================================
+const char* toStr(preProcEnum_t e){
+  using namespace PreProcessing;
+  switch (e){
+    case preProcEnum_t::IPreProcessorVarDep:
+      return IPreProcessorVarDep::procType();
+      break;
+    case preProcEnum_t::Norm1:
+      return Norm::Norm1::procType();
+      break;
+    case preProcEnum_t::Norm2:
+      return Norm::Norm2::procType();
+      break;
+    case preProcEnum_t::Sqrt:
+      return Norm::Sqrt::procType();
+      break;
+    case preProcEnum_t::ConstantValue:
+      return Norm::ConstantValue::procType();
+      break;
+    case preProcEnum_t::Sequential:
+      return Norm::Sequential::procType();
+      break;
+    case preProcEnum_t::Spherization:
+      return Norm::Spherization::procType();
+      break;
+    case preProcEnum_t::MinMax:
+      return Norm::MinMax::procType();
+      break;
+    case preProcEnum_t::IPreProcessor:
+      return IPreProcessor::procType();
+      break;
+    default:
+      throw Exceptions::no_such_type(e,"Types");
+  }
+}
+
+// =============================================================================
+const char* toStr(discrEnum_t e){
+  using namespace Discrimination;
+  switch (e){
+    case discrEnum_t::IDiscriminatorVarDep:
+      return IDiscriminatorVarDep::procType();
+      break;
+    case discrEnum_t::NNFeedForward:
+      return NNFeedForward::procType();
+      break;
+    case discrEnum_t::IDiscriminator:
+      return IDiscriminator::procType();
+      break;
+    default:
+      throw Exceptions::no_such_type(e,"Types");
+  }
+}
+
+// =============================================================================
+const char* toStr(thresEnum_t t){
+  using namespace Discrimination;
+  switch (t){
+    case thresEnum_t::IThresholdVarDep:
+      return IThresholdVarDep::procType();
+      break;
+    case thresEnum_t::UniqueThreshold:
+      return UniqueThreshold::procType();
+      break;
+    case thresEnum_t::IThreshold:
+      return IThreshold::procType();
+      break;
+    default:
+      throw Exceptions::no_such_type(t,"Types");
+  }
+}
+
+} // namespace Ringer
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/tools/IOHelperFcns.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/tools/IOHelperFcns.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b7afffee288ea5987d3aad8b3d1f19c492f79b30
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/tools/IOHelperFcns.cxx
@@ -0,0 +1,246 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IOHelperFcns.cxx 693573 2015-09-07 19:15:49Z wsfreund $
+#include "RingerSelectorTools/tools/IOHelperFcns.icc"
+
+// STL includes:
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <functional>
+#include <locale>
+#include <memory>
+
+// ROOT includes:
+#include <TClass.h>
+#include <TSystem.h>
+
+namespace Ringer { namespace IOHelperFcns {
+
+namespace {
+
+// =============================================================================
+/**
+ * @brief Fctor for checking if string is digit or comma
+ **/
+//struct is_digit_or_comma {
+//  bool operator ()(int c){
+//    if ( std::isdigit(c) || c != ',' ){
+//      return true;
+//    } else {
+//      return false;
+//    }
+//  }
+//};
+
+// =============================================================================
+/**
+ * @brief Filter index string from 
+ **/
+std::string& filterIdxStr(std::string &str)
+{
+  std::string oldStr = str;
+  // Check if string is in correct format:
+  bool isCorrectFormat = true;
+  std::stringstream ss(str);
+  // We want to discard everything until @
+  std::getline ( ss, str, '@' ); 
+  std::getline ( ss, str, '@' ); 
+  if ( str.empty() || str.front() != '(' || str.back() != ')'){
+    isCorrectFormat = false;
+  }
+  // Strip first and last charater
+  str = str.substr(1, str.size()-2 );
+  if ( str.find_first_not_of( "0123456789," ) != std::string::npos ){
+    isCorrectFormat = false;
+  }
+  if ( !isCorrectFormat ){
+    throw std::runtime_error(std::string("Could not extract index string "
+          "from ") + oldStr );
+  }
+  // Ok, it is on correct format:
+  return str;
+}
+} //private namespace
+
+// =============================================================================
+std::string makeIdxStr(unsigned int idxV) 
+{
+  std::stringstream ss;
+  ss << "@(" << idxV << ")";
+  return ss.str();
+}
+
+// =============================================================================
+std::string makeIdxStr(std::vector<unsigned int> &idxV) 
+{
+  std::stringstream ss;
+  ss << "@(";
+  for ( size_t count = 0; count < idxV.size(); ++count ){
+    ss << idxV[count];
+    if ( count + 1 < idxV.size() ) {
+      ss << ",";
+    }
+  }
+  ss << ")";
+  return ss.str();
+}
+
+// =============================================================================
+void getIdxVecFromStr(const char* cstr, std::vector<unsigned int> &vec) 
+{
+  // Clear vector so that we can fill it with idx array
+  vec.clear();
+  //  Retrieve idxStr from cstr and prepare to loop over indexes
+  std::string str(cstr);
+  std::stringstream ss(filterIdxStr(str));
+  //  Fill vector
+  while ( ss.good() ) {
+    std::getline(ss,str,',');
+    vec.push_back(std::stoul(str));
+  } 
+}
+
+// =============================================================================
+unsigned int getIdxFromStr(const char* cstr, unsigned int n) 
+{
+  std::string str(cstr);
+  std::stringstream ss(filterIdxStr(str));
+  // Ignore any number until we get into our requested index:
+  for ( size_t counter = 0; counter < n ; ++counter ){
+    std::getline(ss,str,',');
+  }
+  return std::stoul(str);
+}
+
+// =============================================================================
+bool startsWith(const char *cStrStart, const char *cStr)
+{
+  std::string strStart(cStrStart);
+  std::string str(cStr);
+  if(str.substr(0, strStart.size()) == strStart) {
+    return true;
+  }
+  return false;
+}
+
+// =============================================================================
+unsigned version()
+{
+
+#ifndef PACKAGE_VERSION
+# error "PACKAGE_VERSION macro is undefined."
+#endif
+
+  std::string versionStr = PACKAGE_VERSION;
+
+  versionStr.erase(std::remove_if( versionStr.begin(),
+      versionStr.end(),
+      std::not1( std::ptr_fun<int,int>( std::isdigit ) ) ),
+      versionStr.end());
+
+  return std::stoul(versionStr);
+}
+
+// =============================================================================
+void checkFile(const TFile& file){
+  if (file.IsZombie()){
+    throw std::runtime_error(std::string("TFile \"") + 
+        file.GetName() + "\"is not in good status");
+  }
+}
+
+// =============================================================================
+bool fileExist(const char* fileName) {
+  Int_t prevMessageLevel = gErrorIgnoreLevel;
+  gErrorIgnoreLevel = kBreak;
+  TFile file(fileName);
+  gErrorIgnoreLevel = prevMessageLevel;
+  try {
+    file.IsZombie();
+    return true;
+  } catch (const std::runtime_error &e){
+    return false;
+  }
+}
+
+// =============================================================================
+int deleteFile(const char* fileName)
+{
+  if (fileExist(fileName)){
+    return gSystem->Exec((std::string("rm ") + fileName).c_str() );
+  } else {
+    return -1;
+  }
+}
+
+// =============================================================================
+void checkDir(TDirectory *dir)
+{
+  if (dir == nullptr)
+  {
+    throw std::runtime_error(std::string("TDirectory points to void."));
+  }
+}
+
+// =============================================================================
+void writeVersion(TDirectory* dir)
+{
+  // Add package version in which we have written this configurable
+  unsigned v = version();
+  IOHelperFcns::writeVar(dir, "writtenOnPkgVersion", v );
+}
+
+// =============================================================================
+TDirectory *makeDir(TDirectory* baseDir, const char *name)
+{
+  checkDir(baseDir);
+  TDirectory* newDir = baseDir->mkdir(name);
+  try {
+    checkDir(newDir);
+  } catch ( std::runtime_error & ) {
+    throw std::runtime_error(std::string("Could not create a directory "
+          "on directory named ") + baseDir->GetName() ); 
+  }
+  writeVersion(newDir);
+  return newDir;
+}
+
+// =============================================================================
+std::shared_ptr<THashList> getDirList(TDirectory* dir)
+{
+  checkDir(dir);
+  THashList* list = static_cast<THashList*>(dir->GetList());
+  if ( list->IsEmpty() ) {
+    return nullptr;
+  }
+  // Create new list
+  std::shared_ptr<THashList> dirList(
+    new THashList( dir->GetListOfKeys()->GetSize() ) );
+  // Push only directories to list:
+  TIter iter(list);
+  while ( TDirectory *dir = static_cast<TDirectory*>(iter()) ){
+    //if ( dir->IsA() == TDirectoryFile::Class() ) {}
+    if ( dir->InheritsFrom(TDirectory::Class()) ) {
+      dirList->Add(dir);
+    }
+  }
+  return dirList;
+}
+
+// =============================================================================
+unsigned getWrittenVersion(TDirectory *configDir)
+{
+  unsigned writtenVersion(0);
+  readVar(configDir, "writtenOnPkgVersion", writtenVersion); 
+  return writtenVersion;
+}
+
+} // namespace IOHelperFcns
+
+} // namespace Ringer
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/tools/RingerCommonSelector.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/tools/RingerCommonSelector.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..35bdb69fc6d9674b3f4991b051f9308cebab5966
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/tools/RingerCommonSelector.cxx
@@ -0,0 +1,209 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: RingerCommonSelector.cxx 668868 2015-05-20 20:26:18Z wsfreund $
+#ifndef RINGER_STANDALONE
+
+//#undef NDEBUG
+
+// Local includes:
+#include "RingerSelectorTools/ElectronTAccept.h"
+#include "RingerSelectorTools/tools/RingerCommonSelector.h"
+#include "RingerSelectorTools/tools/VariableDependency.h"
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.icc"
+
+// STL includes:
+#include <vector>
+
+// xAOD includes:
+#include "xAODCaloRings/CaloRings.h"
+#include "xAODTracking/TrackParticle.h"
+
+namespace Ringer {
+
+//==============================================================================
+RingerCommonSelector::RingerCommonSelector(
+    const Ringer::IDiscrWrapperCollection *discrWrapperCol,
+    const Ringer::IThresWrapper *thresWrapper,
+    Root::TAccept *partDecMsk,
+    const bool useTrackPat,
+    const bool useRawTrackPat,
+    const bool useCaloCommittee)
+  : m_discrWrapperCol(discrWrapperCol),
+    m_thresWrapper(thresWrapper),
+    m_partDecMsk(partDecMsk),
+    m_useTrackPat(useTrackPat),
+    m_useRawTrackPat(useRawTrackPat),
+    m_useCaloCommittee(useCaloCommittee),
+    m_fstDiscrLayer(0),
+    m_lastDiscrLayer(0)
+{
+  if ( !m_discrWrapperCol ) {
+    throw std::runtime_error("Cannot create RingerCommonSelector"
+        "without discrimination wrapper collection.");
+  }
+
+  if ( !m_thresWrapper ) {
+    throw std::runtime_error("Cannot create RingerCommonSelector"
+        "without threshold wrapper.");
+  }
+
+  if ( !m_partDecMsk ) {
+    throw std::runtime_error("Cannot create RingerCommonSelector"
+        "without a decision mask.");
+  }
+
+  m_discrWrapperColSize = discrWrapperCol->size();
+
+  m_fstDiscrLayer  = (*m_discrWrapperCol)[0];
+  m_lastDiscrLayer = (*m_discrWrapperCol)[ m_discrWrapperColSize - 1 ];
+
+  m_nonSegmentedDiscr = m_fstDiscrLayer->getSegType() ==
+    SegmentationType::NoSegmentation;
+}
+
+//==============================================================================
+StatusCode RingerCommonSelector::execute(
+    const DepVarStruct &depVar,
+    const xAOD::CaloRings* clRings,
+    const TrackPatternsHolder* trackPat)
+{
+  ATH_MSG_DEBUG( "Starting executing RingerCommonSelector.");
+
+  if ( !m_discrWrapperColSize ){
+    ATH_MSG_ERROR("Cannot run with empty discrimination "
+        "wrapper collection.");
+    return StatusCode::FAILURE;
+  }
+
+  if ( m_useTrackPat || m_useRawTrackPat ) {
+#ifndef NDEBUG
+    ATH_MSG_DEBUG( "Using track information.");
+#endif
+    if (!trackPat){
+      ATH_MSG_ERROR("Requested to add track patterns, "
+          "but it isn't available.");
+      return StatusCode::FAILURE;
+    }
+
+    // We now check if we want to add run discriminator specialized for track
+    // patterns:
+    const TrackPatternsHolder *localTrackPat = 0;
+    if ( !m_useRawTrackPat ) {
+      localTrackPat = trackPat;
+    }
+
+    if ( m_useCaloCommittee && !m_useRawTrackPat && !m_nonSegmentedDiscr )
+    { 
+#ifndef NDEBUG
+      ATH_MSG_DEBUG( "Using CaloCommite with nonSegmented discriminator.");
+#endif
+      // If we are doing calorimeter committee and have a discriminator
+      // specialized for the track patterns, we need to distinguish the calorimeter
+      // output from the track discriminator output, thus we execute the
+      // discrimination layer two times, one for each type of input and get the
+      // output space representation within two vectors:
+      m_fstDiscrLayer->execute( depVar, 
+          clRings, 
+          nullptr, 
+          m_output);
+      m_fstDiscrLayer->execute( depVar, 
+          nullptr, 
+          localTrackPat, 
+          m_trackDiscr_output);
+    } else {
+#ifndef NDEBUG
+      ATH_MSG_DEBUG( "Not using CaloCommitee or using without segmented "
+          "discriminator or using raw pattern.");
+#endif
+      // Otherwise we simply propagate
+      m_fstDiscrLayer->execute( depVar, clRings, localTrackPat, m_output);
+    }
+  } else {
+#ifndef NDEBUG
+    ATH_MSG_DEBUG( "Not using track information. Propagating first layer.");
+#endif
+    // Do not input track patterns into discrimination layer:
+    m_fstDiscrLayer->execute( depVar, clRings, nullptr, m_output );
+  }
+
+  // Check if we have more than one discrimination layer:
+  if ( m_discrWrapperColSize > 1 ){
+
+    // If we are using raw track pattern and haven't a dedicated committee for
+    // the Calorimeter information, then we add the raw track pattern into the next
+    // classification layer input space:
+    if ( m_useRawTrackPat && !m_useCaloCommittee ) {
+      trackPat->exportPatternsTo(m_input);
+    } 
+
+    // Set input to be same as last layer output, so that we can continue
+    // applying our chain:
+    m_input = m_output;
+
+    // If we have intermediary layers:
+    if ( m_discrWrapperColSize > 2 ){
+      // We use the output from first discrimination layer to work with the
+      // sequential layers (except the last):
+      for (size_t discrIdx = 1; discrIdx < m_discrWrapperColSize - 1; 
+          ++discrIdx ){
+
+        (*m_discrWrapperCol)[discrIdx]->execute( 
+            depVar, 
+            m_input, 
+            m_output );
+        // Set input to be same as last layer output, so that we can continue
+        // applying our chain:
+        m_input = m_output;
+      }
+    }
+    
+    // If we did calorimeter only committee, then we need to add track
+    // information to last discrimination layer:
+    if ( m_useCaloCommittee ) {
+      // We check if we want to add raw track information to the last
+      // discrimination layer input:
+      if ( m_useRawTrackPat ) {
+        trackPat->exportPatternsTo( m_input );
+      } else {
+        // otherwise we need to add track discrimination output, executed by
+        // first layer into the last layer input space:
+        // Copy trackDiscr output to input space:
+        m_input.insert( m_input.end(), 
+            m_trackDiscr_output.begin(), 
+            m_trackDiscr_output.end());
+      }
+    }
+
+    // Apply our last discriminator
+    m_lastDiscrLayer->execute( 
+        depVar, 
+        m_input, 
+        m_output);
+#ifndef NDEBUG
+            ATH_MSG_DEBUG("Final output space is :" << m_output);
+#endif
+  }
+
+  // With the discrimination chain applied, we now move into obtaining its
+  // decision:
+  m_thresWrapper->getOutput(depVar, m_output, m_decVec);
+
+  if ( m_decVec.empty() ){
+    ATH_MSG_ERROR("There was no decision returned "
+        "by discrimination chain.");
+    return StatusCode::FAILURE;
+  }
+
+  // Save discrimination into particle decision mask. We only use the first
+  // decision vector output:
+  m_partDecMsk->setCutResult( BitdefElectron_v1::RingerChainDec, m_decVec[0] );
+
+  return StatusCode::SUCCESS;
+
+}
+
+} // Namespace Ringer
+
+#endif // RINGER_STANDALONE
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/tools/TrackPatternsHolder.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/tools/TrackPatternsHolder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..667ce5ba25aa3b2256f4fb2a34880f288a3c2f1a
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/tools/TrackPatternsHolder.cxx
@@ -0,0 +1,268 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TrackPatternsHolder.cxx 693573 2015-09-07 19:15:49Z wsfreund $
+#ifndef RINGER_STANDALONE
+// Local includes:
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+#include "RingerSelectorTools/tools/cxx/RingerUseNewCppFeatures.h"
+
+// STL includes:
+#include <cmath>
+
+
+// xAOD includes:
+# include "xAODTracking/TrackParticle.h"
+# include "xAODEgamma/EgammaEnums.h"
+# include "xAODEgamma/Electron.h"
+
+#if !defined(XAOD_STANDALONE) && !defined(RINGER_STANDALONE)
+# include "TrkTrackSummary/TrackSummary.h"
+#else
+// XXX This tool should be implemented in AsgTool enviroment... 
+namespace Trk {
+namespace TrackSummary {
+const int SummaryTypeNotSet = -1;
+} // namespace TrackSummary;
+} // namespace Trk
+#endif
+
+namespace Ringer {
+
+#if !(RINGER_USE_NEW_CPP_FEATURES)
+namespace {
+float cutBinEta_TRT[] = {0.1, 0.625, 1.07, 1.304, 1.752, 2.0};
+} // private namespace
+const double TrackPatternsHolder::m_a0 = 33.14; 
+const double TrackPatternsHolder::m_b0 = -129.1; 
+const double TrackPatternsHolder::m_c0 = 1455.;
+const double TrackPatternsHolder::m_a1 = 29.42; 
+const double TrackPatternsHolder::m_b1 = 27.93; 
+const double TrackPatternsHolder::m_c1 = -89.96; 
+const double TrackPatternsHolder::m_d1 = 91.51;
+const double TrackPatternsHolder::m_a2 = 196.3; 
+const double TrackPatternsHolder::m_b2 = -403.; 
+const double TrackPatternsHolder::m_c2 = 230.2;
+const double TrackPatternsHolder::m_a3 = -10.59; 
+const double TrackPatternsHolder::m_b3 = 37.29;
+const double TrackPatternsHolder::m_a4 = -640.9; 
+const double TrackPatternsHolder::m_b4 = 1323.; 
+const double TrackPatternsHolder::m_c4 = -851.8; 
+const double TrackPatternsHolder::m_d4 = 180.8;
+const double TrackPatternsHolder::m_a5 = 159.8; 
+const double TrackPatternsHolder::m_b5 = -70.9;
+const std::vector<float> TrackPatternsHolder::m_cutBinEta_TRT = 
+  std::vector<float>(cutBinEta_TRT, cutBinEta_TRT + sizeof(cutBinEta_TRT) / sizeof(float));
+#else
+constexpr std::array<float,6> TrackPatternsHolder::m_cutBinEta_TRT;
+#endif
+
+// =============================================================================
+void TrackPatternsHolder::resetValues()
+{
+  m_nBL = 0;
+  m_nBLOutliers = 0;
+  m_nPi = 0;
+  m_nPiOutliers = 0;
+  m_nSCT = 0;
+  m_nSCTOutliers = 0;
+  m_nTRThigh          = 0;
+  m_nTRThighOutliers  = 0;
+  m_nTRT         = 0;
+  m_nTRTOutliers = 0;
+  m_nTRTXenonHits = 0;
+  m_expectHitInBLayer = true;
+  m_trackd0 = 0;
+  m_deltaeta = 0;
+  m_deltaphi = 0;
+  m_ep = 0;
+
+  m_energy = 0;
+  m_eta = 0;
+}
+
+// =============================================================================
+void TrackPatternsHolder::extractPatternsFrom(
+    const xAOD::TrackParticle *track,
+    const xAOD::Electron *el)
+{
+
+  // Reset values to default:
+  resetValues();
+
+  // Get cluster energy:
+  m_energy =  el->caloCluster()->e();
+  m_eta = std::fabs(el->caloCluster()->eta());
+
+  bool allFound = true;
+
+  allFound = allFound   && track->summaryValue(m_nBL,               xAOD::numberOfBLayerHits);
+  if (m_useBLOutliers) {
+    allFound = allFound && track->summaryValue(m_nBLOutliers,       xAOD::numberOfBLayerOutliers);
+  }
+  allFound = allFound   && track->summaryValue(m_nPi,               xAOD::numberOfPixelHits);
+  if (m_usePIXOutliers){
+    allFound = allFound && track->summaryValue(m_nPiOutliers,       xAOD::numberOfPixelOutliers);
+  }
+  allFound = allFound   && track->summaryValue(m_nSCT,              xAOD::numberOfSCTHits);
+  if (m_useSCTOutliers){
+    allFound = allFound && track->summaryValue(m_nSCTOutliers,      xAOD::numberOfSCTOutliers);
+  }
+  allFound = allFound   && track->summaryValue(m_nTRThigh,          xAOD::numberOfTRTHighThresholdHits);
+  if (m_useTRTOutliers){
+    allFound = allFound && track->summaryValue(m_nTRThighOutliers,  xAOD::numberOfTRTHighThresholdOutliers);
+  }
+  allFound = allFound   && track->summaryValue(m_nTRT,              xAOD::numberOfTRTHits);
+  allFound = allFound   && track->summaryValue(m_nTRTOutliers,      xAOD::numberOfTRTOutliers);
+  if (m_useTRTXenonHits){
+    allFound = allFound && track->summaryValue(m_nTRTXenonHits,     xAOD::numberOfTRTXenonHits);
+  }
+  allFound = allFound   && track->summaryValue(m_expectHitInBLayer, xAOD::expectBLayerHit);
+
+  m_trackd0 = fabsf(track->d0());
+
+  allFound = allFound && el->trackCaloMatchValue(m_deltaeta,        xAOD::EgammaParameters::deltaEta1);
+  allFound = allFound && el->trackCaloMatchValue(m_deltaphi,        xAOD::EgammaParameters::deltaPhi2);
+
+  m_ep = m_energy * fabs(track->qOverP());
+
+  if (!allFound) {
+    // if object is bad then use the bit for "bad eta"
+    ATH_MSG_WARNING("Have some variables missing.");
+  }
+
+}
+
+// =============================================================================
+void TrackPatternsHolder::exportPatternsTo(std::vector<float> &vec) const 
+{
+
+  // Copy originals:
+  uint8_t nBL = m_nBL;
+  uint8_t nPi = m_nPi;
+  uint8_t nSi = m_nPi + m_nSCT;
+
+  // Add outliers:
+  if (m_useBLOutliers) {
+    nBL += m_nBLOutliers;
+  }
+
+  if (m_usePIXOutliers) {
+    nPi += m_nPiOutliers;
+    nSi += m_nPiOutliers;
+  }
+
+  if (m_useSCTOutliers) {
+    nSi += m_nSCTOutliers;
+  }
+
+  // Track quality cuts (CutID only dependent on eta)
+  //@{
+  // egammaPID::TrackBlayer_Electron (CutID uses min
+  // value cut and check if modules was alive)
+  vec.push_back(nBL);  // Pattern 0
+
+  // We, instead, put it as a pattern
+  vec.push_back(m_expectHitInBLayer); // Pattern 1
+
+  // egammaPID::TrackPixel_Electron (CutID uses min value cut)
+  vec.push_back(nPi); // Pattern 2
+
+  // egammaPID::TrackSi_Electron (CutID uses min value cut)
+  vec.push_back(nSi); // Pattern 3
+
+  // egammaPID::TrackA0_Electron || egammaPID::TrackA0Tight_Electron (CutID
+  // uses max value cut)
+  vec.push_back(m_trackd0); // Pattern 4
+  //@}
+
+  // CutID dependent on eta & et
+  //@{ 
+  // egammaPID::TrackMatchEta_Electron (CutID uses max value cut)
+  vec.push_back(m_deltaeta); // Pattern 5
+
+  // egammaPID::TrackMatchPhi_Electron (CutID uses min & max value cuts)
+  vec.push_back(m_deltaphi); // Pattern 6
+
+  // egammaPID::TrackMatchEoverP_Electron (CutID uses min & max value cuts)
+  vec.push_back(m_ep);  // Pattern 7
+  //@}
+
+  // Use of Transition Radiation Tracker
+  //@{ 
+  double rTRT(0);
+  double trt_estimated_hits(0);
+  getTRTVar(rTRT,trt_estimated_hits);
+
+  // egammaPID::TrackTRTratio(90)_Electron (CutID min value):
+  vec.push_back(rTRT); // Pattern 8
+
+  // egammaPID::TrackTRThits_Electron (CutID min value)
+  vec.push_back(trt_estimated_hits); // Pattern 9
+  // @}
+}
+
+// =============================================================================
+void TrackPatternsHolder::getTRTVar(double &rTRT, double &estHitsTRT) const
+{
+  int nTRTTotal(0);
+  if (m_useTRTOutliers) {
+    if (m_useTRTXenonHits /*&& 
+        (static_cast<int>(m_nTRTXenonHits) != 
+         Trk::TrackSummary::SummaryTypeNotSet)*/) //<- is it always true ? 
+    {
+      nTRTTotal= m_nTRTXenonHits;
+    } else {
+      nTRTTotal = m_nTRT+m_nTRTOutliers;
+    }
+    rTRT = (nTRTTotal) > 0 ?
+      ((double) (m_nTRThigh+m_nTRThighOutliers)/(nTRTTotal) ) : 0.;
+  } else {
+    rTRT = (m_nTRT) > 0 ? ((double) (m_nTRThigh)/(m_nTRT) ) : 0.;
+    nTRTTotal = m_nTRT;
+  }
+  // FIXME Why isn't this in a function available anywhere else?
+  estHitsTRT = -1;
+  int ibin_eta_TRT = -1;
+  for (unsigned int ibinEta=0;ibinEta<m_cutBinEta_TRT.size();ibinEta++) {
+    if ( ibinEta == 0 ){
+      if ( m_eta < m_cutBinEta_TRT[ibinEta] ) {
+        ibin_eta_TRT = ibinEta;
+      }
+    } else {
+      if ( m_eta >= m_cutBinEta_TRT[ibinEta-1] &&
+           m_eta < m_cutBinEta_TRT[ibinEta] ) {
+        ibin_eta_TRT = ibinEta;
+      }
+    }
+  }
+  switch (ibin_eta_TRT) {
+  case 0:
+    estHitsTRT = nTRTTotal - 
+      (m_a0 + m_b0*m_eta + m_c0*m_eta*m_eta);
+    break;
+  case 1:
+    estHitsTRT = nTRTTotal - 
+      (m_a1 + m_b1*m_eta + m_c1*m_eta*m_eta + m_d1*m_eta*m_eta*m_eta);
+    break;
+  case 2:
+    estHitsTRT = nTRTTotal - 
+      (m_a2 + m_b2*m_eta + m_c2*m_eta*m_eta) ;
+    break;
+  case 3:
+    estHitsTRT = nTRTTotal - (m_a3 + m_b3*m_eta);
+    break;
+  case 4:
+    estHitsTRT = nTRTTotal - 
+      (m_a4 + m_b4*m_eta + m_c4*m_eta*m_eta + m_d4*m_eta*m_eta*m_eta);
+    break;
+  case 5:
+    estHitsTRT = nTRTTotal - (m_a5 + m_b5*m_eta);
+  }
+}
+
+
+} // namespace Ringer
+
+#endif // RINGER_STANDALONE
diff --git a/PhysicsAnalysis/RingerSelectorTools/Root/tools/VariableDependency.cxx b/PhysicsAnalysis/RingerSelectorTools/Root/tools/VariableDependency.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..791b25df4fb3c8cd85fc29c4e5235d6693738b19
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/Root/tools/VariableDependency.cxx
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: VariableDependency.cxx 667899 2015-05-18 18:37:25Z wsfreund $
+#include "RingerSelectorTools/tools/VariableDependency.h"
+
+#include "RingerSelectorTools/tools/IOHelperFcns.icc"
+
+namespace Ringer {
+
+// =============================================================================
+const char* VariableDependency::type() const
+{
+  std::stringstream depVar;
+  depVar.precision(2);
+  if (m_etaDependency){
+    if (m_etDependency){
+      depVar << "[" << m_etaMin << "<=eta<" << m_etaMax << ", " 
+             << m_etMin << "<=Et<" << m_etMax << "]";
+    } else {
+      depVar << "[" << m_etaMin << "<=eta<" << m_etaMax << "]";
+    }
+  } else {
+    if (m_etDependency){
+      depVar << "[" << m_etMin << "<=Et<" << m_etMax << "]";
+    } else {
+      return "[eta, Et Independent]";
+    }
+  }
+  const_cast<std::string&>(m_type) = depVar.str();
+  return m_type.c_str();
+}
+
+// =============================================================================
+void VariableDependency::read(VariableDependency *varDep, 
+    TDirectory *configDir, 
+    unsigned /*writtenVersion*/)
+{
+  // Read unsigned int and transform it to EtDependency:
+  IOHelperFcns::readVar<EtaDependency, unsigned int>(configDir, 
+      "etaDependency", 
+      varDep->m_etaDependency ); 
+  // Read unsigned int and transform it to EtDependency:
+  IOHelperFcns::readVar<EtDependency, unsigned int>(configDir, 
+      "etDependency",  
+      varDep->m_etDependency  ); 
+  IOHelperFcns::readVar(configDir, "etaMin",        varDep->m_etaMin        ); 
+  IOHelperFcns::readVar(configDir, "etaMax",        varDep->m_etaMax        ); 
+  IOHelperFcns::readVar(configDir, "etMin",         varDep->m_etMin         ); 
+  IOHelperFcns::readVar(configDir, "etMax",         varDep->m_etMax         ); 
+}
+
+// =============================================================================
+void VariableDependency::writeDepInfo(TDirectory *configDir) const
+{
+  // Write EtaDependency enumeration as unsigned int:
+  IOHelperFcns::writeVar< const EtaDependency, const unsigned int>( configDir, 
+      "etaDependency", 
+      m_etaDependency );
+  // Write EtDependency enumeration as unsigned int:
+  IOHelperFcns::writeVar< const EtDependency, const unsigned int>( configDir, 
+      "etDependency",  
+      m_etDependency  );
+  IOHelperFcns::writeVar(configDir, "etaMin",        m_etaMin        );
+  IOHelperFcns::writeVar(configDir, "etaMax",        m_etaMax        );
+  IOHelperFcns::writeVar(configDir, "etMin",         m_etMin         );
+  IOHelperFcns::writeVar(configDir, "etMax",         m_etMax         );
+}
+
+} // namespace Ringer
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/cmt/Makefile.RootCore b/PhysicsAnalysis/RingerSelectorTools/cmt/Makefile.RootCore
new file mode 100644
index 0000000000000000000000000000000000000000..de3ae64ea5c658ec2a4b24d5c40ede410e5b24c7
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/cmt/Makefile.RootCore
@@ -0,0 +1,29 @@
+# this makefile also gets parsed by shell scripts                                                                                             
+# therefore it does not support full make syntax and features
+# edit with care
+
+# Don't make inline comments, they are not supported.
+
+# for full documentation check:
+# https://twiki.cern.ch/twiki/bin/viewauth/Atlas/RootCore#Package_Makefile
+
+PACKAGE          = RingerSelectorTools
+PACKAGE_PRELOAD  = 
+# This will be set automatically, do not add anything in this field. If it is
+# needed, change precompile.RootCore line that writes this place:
+PACKAGE_CXXFLAGS = -DASGTOOL_STANDALONE -DPACKAGE_VERSION=\"RingerSelectorTools-00-00-01\"
+PACKAGE_OBJFLAGS = 
+PACKAGE_LDFLAGS  = 
+PACKAGE_BINFLAGS = 
+PACKAGE_LIBFLAGS = 
+PACKAGE_DEP      = PATCore AsgTools xAODBase xAODCore xAODEgamma xAODCaloRings xAODPrimitives PathResolver xAODCaloEvent ElectronPhotonSelectorTools xAODTracking 
+PACKAGE_TRYDEP   = 
+PACKAGE_CLEAN    = 
+PACKAGE_NOGRID   = 
+PACKAGE_PEDANTIC = 1
+PACKAGE_NOOPT    = 0
+PACKAGE_NOCC     = 0
+PACKAGE_REFLEX   = 1
+
+include $(ROOTCOREDIR)/Makefile-common
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/cmt/precompile.RootCore b/PhysicsAnalysis/RingerSelectorTools/cmt/precompile.RootCore
new file mode 100755
index 0000000000000000000000000000000000000000..a83ed6d131479f7eb072c4d74f6ae89003cf7ce6
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/cmt/precompile.RootCore
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+MAKEFILE=Makefile.RootCore
+VERSIONFILE=version.cmt
+ROOTCORE_REDIRECT_BASE=MoreFilesForYou-RootCore-
+
+# Check if root version is greater than 6.00/00
+#ROOT_VERSION_TEXT=`root-config --version`
+#ROOT_VERSION_TEXT=${ROOT_VERSION_TEXT//./}
+#ROOT_VERSION_TEXT=${ROOT_VERSION_TEXT//\//}
+#if test "$ROOT_VERSION_TEXT" -gt "60000"
+#then
+#  ROOT_GE_6_00=-DROOT_GE_6_00
+#else
+#  ROOT_GE_6_00= 
+#fi
+
+# Change our Makefile to add dependent information:
+$ROOTCOREDIR/scripts/set_field.sh $MAKEFILE \
+  PACKAGE_CXXFLAGS "-DASGTOOL_STANDALONE -DPACKAGE_VERSION=\\\\\"`cat $VERSIONFILE`\\\\\""
+
+# Create RootCore file redirection for sources (done only to keep multifolder
+# architeture)
+cd ../Root/
+for dir in *
+do
+  if test -d $dir
+  then
+    for file in `find $dir -type f -not -path "*/.*/*" -exec echo "{}" \;`
+    do
+      ROOTCORE_REDIRECT_FILE=`echo "${ROOTCORE_REDIRECT_BASE}${file//\//-}"`
+      if test ! -e $ROOTCORE_REDIRECT_FILE 
+      then
+        ln -s $file $ROOTCORE_REDIRECT_FILE 
+      fi
+    done
+  fi
+done
+cd - >> /dev/null
diff --git a/PhysicsAnalysis/RingerSelectorTools/cmt/requirements b/PhysicsAnalysis/RingerSelectorTools/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..c3a2a1e23efe9a20bd8f0cb97007efc441761c50
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/cmt/requirements
@@ -0,0 +1,106 @@
+package RingerSelectorTools
+
+author Werner S. Freund <wsfreund@cern.ch>
+
+use                AtlasPolicy               AtlasPolicy-*
+use                AthenaKernel              AthenaKernel-*              Control
+use                AtlasROOT                 AtlasROOT-*                 External
+
+use                PATCore                   PATCore-*                   PhysicsAnalysis/AnalysisCommon
+use                AsgTools                  AsgTools-*                  Control/AthToolSupport
+use                xAODEgamma                xAODEgamma-*                Event/xAOD
+use                xAODCaloRings             xAODCaloRings-*             Event/xAOD
+use                xAODTracking              xAODTracking-*              Event/xAOD
+use_unless     tag=ROOT_GE_6_00 \
+               pkg=AtlasBoost            ver=AtlasBoost-*           root=External
+use_unless     tag=ROOT_GE_6_00 \
+               pkg=CxxUtils              ver=CxxUtils-*             root=Control
+
+use ElectronPhotonSelectorTools ElectronPhotonSelectorTools-* PhysicsAnalysis/ElectronPhotonID
+
+private
+
+use            GaudiInterface           GaudiInterface-*            External
+use             PathResolver             PathResolver-*              Tools
+use            AthContainers            AthContainers-*             Control
+
+use               xAODBase                 xAODBase-*              Event/xAOD
+use           TrkTrackSummary          TrkTrackSummary-*        Tracking/TrkEvent
+end_private
+
+# Adds Core,Cint,Tree,pthread,MathCore,Hist Root libs
+apply_tag       ROOTBasicLibs 
+
+branches RingerSelectorTools python src Root share data
+
+# Create a dual-use library (we exclude file that may be created by RootCore to
+# keep source files with multi-folder architeture)
+apply_pattern dual_use_library \
+              files="*.cxx ../Root/*.cxx ../Root/procedures/*.cxx ../Root/tools/*.cxx -x=../Root/MoreFilesForYou-RootCore-*"
+
+# install our python modules
+apply_pattern declare_python_modules files="*.py"
+
+# install the ROOT files (in the data/ directory)                                      
+apply_pattern declare_calib files="../data/*.root ../data/test"
+
+# For reflex dictionary generation                                                                                                   
+use AtlasReflex   AtlasReflex-*   External -no_auto_imports                                                                           
+apply_pattern lcgdict dict=RingerSelectorTools \
+                      selectionfile=selection.xml \
+                      headerfiles="..\/RingerSelectorTools/RingerSelectorToolsDict.h"
+
+# Add binary ringerSel_readTest using testRead.cxx
+#application ringerSel_testRead ../util/testRead.cxx
+#macro_append ringerSel_testRead_dependencies RingerSelectorToolsLib 
+
+# Add binary ringerSel_writeTest using writeRead.cxx
+#application ringerSel_testWrite ../util/testWrite.cxx
+#macro_append ringerSel_testWrite_dependencies RingerSelectorToolsLib
+
+
+###################### Code Graveyard ##########################
+
+#use               AtlasPyROOT               AtlasPyROOT-*               External
+#use           xAODCaloEvent            xAODCaloEvent-*            Event/xAOD
+#use           xAODEventInfo            xAODEventInfo-*            Event/xAOD
+
+# Adds MathMore,Minuit,Minuit2,Matrix,Physics,HistPainter,Rint
+#apply_tag       ROOTMathLibs
+# For more ROOT options, take a look here http://acode-browser.usatlas.bnl.gov/lxr/source/atlas/External/AtlasROOT/cmt/requirements
+
+#macro use_AtlasBoost "AtlasBoost             AtlasBoost-*                External" \
+#      ROOT_GE_6_00 ""
+#use $(use_AtlasBoost)
+#macro use_CxxUtils "CxxUtils             CxxUtils-*                External" \
+#      ROOT_GE_6_00 ""
+#use $(use_CxxUtils)
+
+#macro_append ringerSel_testReadlinkopts "-lRingerSelectorToolsLib -lAtlasSTLAddReflexDict -lGaudiAlg "
+
+#private
+## Python bindings:
+#macro_append Boost_linkopts " $(Boost_linkopts_python) "
+#macro_append pyringerselectortools_util_pp_cppflags " -Wno-unused "
+#end_private
+
+
+# This could be added by asg tool requirements, so that we don't need to do it ourselves.
+#private
+# Uncomment these to run on debug mode for this package only:
+#macro cppdebugflags '$(cppdebugflags_s)'
+#macro_remove componentshr_linkopts "-Wl,-s"
+#macro_remove AtlasCxxPolicy_pp_cppflags "-DNDEBUG"
+#macro_remove AtlasCxxPolicy_pp_cppflags "-O2"
+#macro_append AtlasCxxPolicy_pp_cppflags " -g "
+#end_private
+
+#pattern declare_python_package \
+#    apply_pattern generic_declare_for_link kind=python_package \
+#                      files='-s=../python <pyth_package>/*.py' prefix=python/<pyth_package> name=<name> ; \
+#    private ; \
+#    macro_append <package>_python_init_dependencies " install_<name>python_package " ; \
+#    end_private
+#
+#declare_python_package pyth_package="RingerSelectorTools"
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/python/ConfiguredAsgElectronRingerSelector.py b/PhysicsAnalysis/RingerSelectorTools/python/ConfiguredAsgElectronRingerSelector.py
new file mode 100644
index 0000000000000000000000000000000000000000..35b0fa03b2c92f01b99fb97d7547857eef879750
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/python/ConfiguredAsgElectronRingerSelector.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+##=============================================================================
+## Name:        ConfiguredAsgElectronRingerSelector
+##
+## Author:      Karsten Koeneke (CERN), Jovan Mitrevski (UCSC)
+## Created:     Dec. 2011
+##
+## Description: Apply the default configurations for the AsgPhotonIsEMSelector,
+##              but allow for overwriting them with user-defined values.
+##
+##=============================================================================
+
+from RingerSelectorTools.ElectronRingerSelectorMapping import ElectronRingerMap
+
+def ConfiguredAsgElectronRingerSelector( quality, menu, cutIDConfDict = None, **kwargs ):
+    """
+    Configure the AsgElectronRingerSelector with the quality cuts
+    and allow for setting its configurable properties through 
+    cutIDConfDict and kwargs arguments.
+
+    Use cutIDConfDict argument to set the properties from the CutIDSelector.
+    It can also be set directly by setting the property CutIDSelector through
+    kwargs. Beware not to set them together, as setting CutIDSelector
+    through kwargs will overwrite cutIDConfDict configurations and, thus, it
+    will be the only configuration used for the job.
+    """
+    try:
+      RingerSelectorConfigurable = ElectronRingerMap[(quality, menu)]
+
+      if cutIDConfDict is None:
+        cutIDConfDict = {}
+      # Configure it
+      ringerSelectorTool = RingerSelectorConfigurable(cutIDConfDict = cutIDConfDict,
+                                                      **kwargs)
+      return ringerSelectorTool
+    except KeyError:
+      from AthenaCommon.Logging import logging
+      import traceback
+      mlog = logging.getLogger( 'ConfiguredAsgElectronRingerSelector.py' )
+      mlog.error("There is no such configuration available:\n %s", traceback.format_exc())
+      raise
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorDefs.py b/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorDefs.py
new file mode 100644
index 0000000000000000000000000000000000000000..419379535a90544294833987050de302468b7442
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorDefs.py
@@ -0,0 +1,147 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.Logging import logging
+mlog = logging.getLogger( 'ElectronRingerSelectorDefs.py' )
+
+from AthenaCommon.Configurable import Configurable
+
+# Import from Ringer utilities:
+try:
+  import cppyy
+except ImportError:
+  import PyCintex as cppyy
+
+try :
+  cppyy.loadDictionary('RingerSelectorToolsDict')
+except RuntimeError, e:
+  mlog.error("Could not load RingerSelectorTools dictionary from cppyy.")
+  raise RuntimeError(e)
+
+from ROOT import Ringer
+from ROOT.Ringer import ElectronTAccept_v1
+from RingerSelectorTools.RingerSelectorToolsConf import Ringer__AsgElectronRingerSelector
+from CaloRingerAlgs.CaloRingerKeys import outputElectronRingSetsConfKey
+
+# Import from CutID utilities:
+try :
+  cppyy.loadDictionary('ElectronPhotonSelectorToolsDict')
+except RuntimeError, e:
+  mlog.error("Could not load ElectronPhotonSelectorTools dictionary from cppyy.")
+  raise RuntimeError(e)
+from ROOT import egammaPID
+from ElectronPhotonSelectorTools.ElectronIsEMSelectorMapping import electronPIDmenu
+from ElectronPhotonSelectorTools.ConfiguredAsgElectronIsEMSelectors \
+    import ConfiguredAsgElectronIsEMSelector
+
+def removeClusterCutsFromIsEMMask(CutIDIsEMMask):
+  "Remove egammaPID Electron Calorimeter cuts from isEM"
+  CutIDIsEMMask = CutIDIsEMMask & (~egammaPID.CALO_ELECTRON)
+
+class BaseElectronSelectorConf ( Ringer__AsgElectronRingerSelector ):
+  def _setDefault(self,attrName, default, **kwargs):
+    "Overwrites AsgElectronRingerSelector default to new default value."
+    if not kwargs.has_key(attrName):
+      setattr(self, attrName, default)
+
+  def _setCutIDSelector(self,defaultName,quality,menu,**kwargs):
+    """
+    Set the AsgElectronRingerSelector CutIDSelector to default or to the configuration
+    available in the kwargs
+    """
+    removeMask = False
+    if not kwargs.has_key("cutIDConfDict") and not kwargs.has_key("CutIDSelector"):
+      removeMask = True
+    if not kwargs.has_key("CutIDSelector"):
+      CutIDSelectorTool = ConfiguredAsgElectronIsEMSelector(defaultName, \
+        quality, \
+        menu, \
+        **kwargs.pop("cutIDConfDict",{}))
+      from AthenaCommon.AppMgr import ToolSvc
+      ToolSvc += CutIDSelectorTool
+      self.CutIDSelector = CutIDSelectorTool
+    else:
+      self.CutIDSelector = kwargs.pop("CutIDSelector")
+    if removeMask:
+      removeClusterCutsFromIsEMMask(self.CutIDSelector.isEMMask)
+
+  def __init__(self, name, **kwargs):
+    Ringer__AsgElectronRingerSelector.__init__(self,name,**kwargs)
+    self._setDefault("RingSetConfContainerName",
+                     outputElectronRingSetsConfKey(),
+                     **kwargs)
+    self._setDefault("CacheConfData", True, **kwargs)
+    self._setDefault("useCutIDTrack", False, **kwargs)
+
+
+class ElectronRingerSelectorTestLoose( BaseElectronSelectorConf ):
+  def __init__(self, name = "ElectronRingerSelector_TestLoose", **kwargs):
+    BaseElectronSelectorConf.__init__(self,name,**kwargs)
+    self._setDefault("DiscriminationFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineDiscrLoose.root",
+                     **kwargs)
+    self._setDefault("ThresholdFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineThresLoose.root",
+                     **kwargs)
+    self._setDefault("CutsMask",
+                     ElectronTAccept_v1.getAppliedCutMsk(Ringer.Loose,
+                                                         kwargs.get("useCutIDTrack",False)),
+                     **kwargs)
+    self._setCutIDSelector("LooseRingerIsEMSelector",\
+        egammaPID.ElectronIDLoosePP, \
+        electronPIDmenu.menuDC14, **kwargs)
+
+class ElectronRingerSelectorTestMedium( BaseElectronSelectorConf ):
+  def __init__(self, name = "ElectronRingerSelector_TestMedium", **kwargs):
+    BaseElectronSelectorConf.__init__(self,name,**kwargs)
+    self._setDefault("DiscriminationFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineDiscrMedium.root",
+                     **kwargs)
+    self._setDefault("ThresholdFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineThresMedium.root",
+                     **kwargs)
+    self._setDefault("CutsMask",
+                     ElectronTAccept_v1.getAppliedCutMsk(Ringer.Medium,
+                                                         kwargs.get("useCutIDTrack",False)),
+                     **kwargs)
+    self._setCutIDSelector("MediumRingerIsEMSelector", \
+        egammaPID.ElectronIDMediumPP, \
+        electronPIDmenu.menuDC14, \
+        **kwargs)
+
+class ElectronRingerSelectorTestTight( BaseElectronSelectorConf ):
+  def __init__(self, name = "ElectronRingerSelector_TestTight", **kwargs):
+    BaseElectronSelectorConf.__init__(self,name,**kwargs)
+    self._setDefault("DiscriminationFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineDiscrTight.root",
+                     **kwargs)
+    self._setDefault("ThresholdFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineThresTight.root",
+                     **kwargs)
+    self._setDefault("CutsMask",
+                     ElectronTAccept_v1.getAppliedCutMsk(Ringer.Tight,
+                                                         kwargs.get("useCutIDTrack",False)),
+                     **kwargs)
+    self._setCutIDSelector("TightRingerIsEMSelector", \
+        egammaPID.ElectronIDTightPP, \
+        electronPIDmenu.menuDC14, **kwargs)
+
+class ElectronRingerSelectorTestNoCut( BaseElectronSelectorConf ):
+  def __init__(self, name = "ElectronRingerSelector_TestNoCut", **kwargs):
+    # FIXME This doesn't work, for now...
+    BaseElectronSelectorConf.__init__(self,name,**kwargs)
+    self._setDefault("DiscriminationFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineDiscrMedium.root",
+                     **kwargs)
+    self._setDefault("ThresholdFileName",
+                     "RingerSelectorTools/TestMenu_20150605_v1/ElectronRingerOfflineThresMedium.root",
+                     **kwargs)
+    self._setDefault("CutsMask",
+                     ElectronTAccept_v1.getAppliedCutMsk(Ringer.NoCut,
+                                                         kwargs.get("useCutIDTrack",False)),
+                     **kwargs)
+    self._setCutIDSelector("NoCutRingerIsEMSelector", \
+        egammaPID.ElectronIDNoCut, \
+        electronPIDmenu.menuDC14, \
+        **kwargs)
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorMapping.py b/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorMapping.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e31789f6f8a629e6fdf6d3b6d995354eb95df90
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/python/ElectronRingerSelectorMapping.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+##=============================================================================
+## Name:        ElectronRingerSelectorMapping.py
+##
+## Author:      Werner Spolidoro Freund (LPS/UFRJ)
+## Created:     Mar 2015
+##
+## Description: Retrieve selector from mask mapping 
+##=============================================================================
+
+try:
+  import cppyy
+except ImportError:
+  import PyCintex as cppyy
+
+try :
+  cppyy.loadDictionary('RingerSelectorToolsDict')
+except RuntimeError, e:
+  from AthenaCommon.Logging import logging
+  mlog = logging.getLogger( 'ElectronRingerSelectorMapping.py' )
+  mlog.error("Could not load RingerSelectorTools dictionary from cppyy.")
+  raise RuntimeError(e)
+
+from ElectronPhotonSelectorTools.ElectronIsEMSelectorMapping import electronPIDmenu
+
+# Import from Ringer selector tools dictionary:
+from ROOT import Ringer
+
+from RingerSelectorTools.ElectronRingerSelectorDefs import *
+
+class electronRingerPIDmenu (electronPIDmenu):
+  testMenu = 999
+
+#####################################################################################################
+##                                    Requirements defined are:                                    ##
+##                                 (see RingerSelectorToolsDefs.h)                                 ##
+#####################################################################################################
+##  Loose_CutID_Pd                || Same detection probability as CutID Loose                     ##
+##  Medium_CutID_Pd               || Same detection probability as CutID Medium                    ##
+##  Tight_CutID_Pd                || Same detection probability as CutID Tight                     ##
+##  Loose_CutID_Pf                || Same false alarm probability as CutID Loose                   ##
+##  Medium_CutID_Pf               || Same false alarm probability as CutID Medium                  ##
+##  Tight_CutID_Pf                || Same false alarm probability as CutID Tight                   ##
+##  Loose_LH_Pd,                  || Same detection probability as LH Loose                        ##
+##  Medium_LH_Pd,                 || Same detection probability as LH Medium                       ##
+##  Tight_LH_Pd,                  || Same detection probability as LH Tight                        ##
+##  Loose_LH_Pf,                  || Same false alarm probability as LH Loose                      ##
+##  Medium_LH_Pf,                 || Same false alarm probability as LH Medium                     ##
+##  Tight_LH_Pf,                  || Same false alarm probability as LH Tight                      ##
+##  Medium-MaxSP                  || Maximum SP-product                                            ##
+##  Loose                         || Same as LooseCutIDPd                                          ##
+##  Medium                        || Same as Medium-MaxSP                                          ##
+##  Tight                         || Same as TightCutIDPfa                                         ##
+##  NoCut                         || Run to retrieve discriminators outputs, but no cut is applied ##
+#####################################################################################################
+#####################################################################################################
+
+ElectronRingerMap = {
+  (Ringer.Loose, electronRingerPIDmenu.testMenu): ElectronRingerSelectorTestLoose,
+  (Ringer.Medium, electronRingerPIDmenu.testMenu): ElectronRingerSelectorTestMedium,
+  (Ringer.Tight, electronRingerPIDmenu.testMenu):  ElectronRingerSelectorTestTight,
+  (Ringer.NoCut, electronRingerPIDmenu.testMenu):  ElectronRingerSelectorTestNoCut,
+  }
diff --git a/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_entries.cxx b/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ba0e7d590115e3f4874bd4e25e27e7ae9db55c1f
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_entries.cxx
@@ -0,0 +1,13 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+#include "RingerSelectorTools/AsgElectronRingerSelector.h"
+
+using namespace Ringer;
+
+DECLARE_TOOL_FACTORY( AsgElectronRingerSelector   )
+//DECLARE_TOOL_FACTORY( AsgPhotonRingerSelector     )
+
+DECLARE_FACTORY_ENTRIES( RingerSelectorTools ){
+  DECLARE_ALGTOOL( AsgElectronRingerSelector  )
+  //DECLARE_ALGTOOL( AsgPhotonRingerSelector    )
+}
diff --git a/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_load.cxx b/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..88559f54226337af09164f343e141b2b75ece222
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/src/components/RingerSelectorTools_load.cxx
@@ -0,0 +1,2 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+LOAD_FACTORY_ENTRIES(RingerSelectorTools)
diff --git a/PhysicsAnalysis/RingerSelectorTools/util/testRead.cxx b/PhysicsAnalysis/RingerSelectorTools/util/testRead.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..51f9acf50696b3db6f7d889279640019feb3c98e
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/util/testRead.cxx
@@ -0,0 +1,664 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: testRead.cxx 693573 2015-09-07 19:15:49Z wsfreund $
+/**
+ * In this executable we want to test if wrappers can be sucessfully read.
+ *
+ * This will attempt to read the files written using testWrite.
+ **/
+
+// STL includes:
+#include <iostream>
+#include <limits>
+
+// Root includes:
+#include <TFile.h>
+#include <THashList.h>
+
+// Gaudi includes:
+#if !defined(RINGER_STANDALONE) && !defined(XAOD_STANDALONE)
+# include "GaudiKernel/SystemOfUnits.h"
+using namespace Gaudi::Units;
+// We just do this ugly thing so that we can have a message stream
+// FIXME How can I create a dummy message stream?
+#define protected public
+#define private public
+# include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#undef protected
+#undef private
+Ringer::AsgElectronRingerSelector __AsgRingerSel__("testRead");
+MsgStream &msg = __AsgRingerSel__.msg();
+#else
+#include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#include "AsgTools/MsgStream.h"
+MsgStream msg("testRead");
+#endif
+
+#define BREAKER \
+  "================================================================================"
+
+// Local includes:
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.h"
+#include "RingerSelectorTools/procedures/Normalizations.h"
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+#include "RingerSelectorTools/procedures/Thresholds.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.h"
+#include "RingerSelectorTools/tools/cxx/remove_pointer.h"
+
+using namespace Ringer;
+
+/**
+ * Read first wrapper on file with type wrapper_t
+ **/ 
+template< class wrapper_t >
+void readWrapperFromFile(wrapper_t *&wrapper, const char* fileName);
+
+/**
+ * Read wrapper collection at file named fileName with base wrapper type
+ * wrapperBase_t
+ **/
+template<typename wrapperBase_t>
+void readCollectionFromFile(const char* fileName);
+
+template<>
+void readCollectionFromFile<IThresWrapper>(const char* fileName);
+
+int main(){
+
+  // Change message level and greet user
+  msg.setLevel(MSG::DEBUG);
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading discriminator using interface "
+    "without using normalization." << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read simple discriminator using interface (without using normalization)
+  // ----------------------------------------------------------------------------
+  // Read "basicWrapperWrong" using correct template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation > *basicWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicWrapper)>::type
+  >( basicWrapper, "basicWrapper.root" );
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read as "basicEtaDepWrapper" using correct template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtIndependent,
+      NoSegmentation > *basicEtaDepWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaDepWrapper)>::type
+  >( basicEtaDepWrapper, "basicEtaDepWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtDepWrapper" using correct template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaIndependent,
+      EtDependent,
+      NoSegmentation > *basicEtDepWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtDepWrapper)>::type
+  >( basicEtDepWrapper, "basicEtDepWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaEtDepWrapper.root" using correct template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtDependent,
+      NoSegmentation > *basicEtaEtDepWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaEtDepWrapper)>::type
+  >( basicEtaEtDepWrapper, "basicEtaEtDepWrapper.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg.setLevel(MSG::ERROR);
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading discriminator with wrong types!" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  // ----------------------------------------------------------------------------
+  // Read simple discriminator using interface with WRONG types
+  // ----------------------------------------------------------------------------
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtDependent,
+    NoSegmentation > *basicWrapperWrong(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicWrapperWrong)>::type
+  >( basicWrapperWrong, "basicWrapper.root" );
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read as "basicEtaDepWrapperWrong" using wrong template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicEtaDepWrapperWrong(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaDepWrapperWrong)>::type
+  >( basicEtaDepWrapperWrong, "basicEtaDepWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtDepWrapperWrong" using wrong template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicEtDepWrapperWrong(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtDepWrapperWrong)>::type
+  >( basicEtDepWrapperWrong, "basicEtDepWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaEtDepWrapperWrong.root" using wrong template
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *basicEtaEtDepWrapperWrong(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaEtDepWrapperWrong)>::type
+  >( basicEtaEtDepWrapperWrong, "basicEtaEtDepWrapper.root");
+  // -------------------------- END --- END --- END -----------------------------
+  msg.setLevel(MSG::DEBUG);
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading pre-processings!" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  // ----------------------------------------------------------------------------
+  // Start testing pre-processings
+  // ----------------------------------------------------------------------------
+  // Read "basicPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicPPWrapper)>::type
+  >( basicPPWrapper, "basicPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtIndependent,
+      NoSegmentation > *basicEtaDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaDepPPWrapper)>::type
+  >( basicEtaDepPPWrapper, "basicEtaDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaIndependent,
+      EtDependent,
+      NoSegmentation > *basicEtDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtDepPPWrapper)>::type
+  >( basicEtDepPPWrapper, "basicEtDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtEtaDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtDependent,
+      NoSegmentation > *basicEtEtaDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtEtaDepPPWrapper)>::type
+  >( basicEtEtaDepPPWrapper, "basicEtEtaDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtEtaTrackCalDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalSegmentation > *basicEtEtaTrackCalDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtEtaTrackCalDepPPWrapper)>::type
+  >( basicEtEtaTrackCalDepPPWrapper, "basicEtEtaTrackCalDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtEtaTrackCalPatTypeDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalPatTypeSegmentation > *basicEtEtaTrackCalPatTypeDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtEtaTrackCalPatTypeDepPPWrapper)>::type
+  >( basicEtEtaTrackCalPatTypeDepPPWrapper, "basicEtEtaTrackCalPatTypeDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaEtSectionDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointSections > *basicEtaEtSectionDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaEtSectionDepPPWrapper)>::type
+  >( basicEtaEtSectionDepPPWrapper, "basicEtaEtSectionDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaEtLayerDepPPWrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *basicEtaEtLayerDepPPWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaEtLayerDepPPWrapper)>::type
+  >( basicEtaEtLayerDepPPWrapper, "basicEtaEtLayerDepPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicNorm1Wrapper.root"
+  RingerProcedureWrapper<PreProcessing::IPreProcessorVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicNorm1Wrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicNorm1Wrapper)>::type
+  >( basicNorm1Wrapper, "basicNorm1Wrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicNorm1Wrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::Norm1VarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *basicLayerDepNorm1Wrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicLayerDepNorm1Wrapper)>::type
+  >( basicLayerDepNorm1Wrapper, "basicLayerDepNorm1Wrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicNorm2Wrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::Norm2VarDep,
+      EtaIndependent,
+      EtIndependent,
+      TrackCalJointLayers > *basicNorm2Wrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicNorm2Wrapper)>::type
+  >( basicNorm2Wrapper, "basicNorm2Wrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicSqrtWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::SqrtVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicSqrtWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicSqrtWrapper)>::type
+  >( basicSqrtWrapper, "basicSqrtWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicConstantValueWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::ConstantValueVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicConstantValueWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicConstantValueWrapper)>::type
+  >( basicConstantValueWrapper, "basicConstantValueWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicMevToGevWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::MevToGevVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicMevToGevWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicMevToGevWrapper)>::type
+  >( basicMevToGevWrapper, "basicMevToGevWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicSequentialWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::SequentialVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicSequentialWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicSequentialWrapper)>::type
+  >( basicSequentialWrapper, "basicSequentialWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicSpherizationWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::SpherizationVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicSpherizationWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicSpherizationWrapper)>::type
+  >( basicSpherizationWrapper, "basicSpherizationWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicMinMaxWrapper.root"
+  RingerProcedureWrapper<PreProcessing::Norm::MinMaxVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *basicMinMaxWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicMinMaxWrapper)>::type
+  >( basicMinMaxWrapper, "basicMinMaxWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading discriminators with pre-processings!" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  
+  // ----------------------------------------------------------------------------
+  // Read discriminators with pre-processings
+  // ----------------------------------------------------------------------------
+  // Read "randomNorm1PPDiscrWrapper.root"
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtDependent,
+      NoSegmentation > *randomNorm1PPDiscrWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(randomNorm1PPDiscrWrapper)>::type
+  >( randomNorm1PPDiscrWrapper, "randomNorm1PPDiscrWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "randomNorm1PPDiscrWrapper.root"
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtDependent,
+      NoSegmentation > *randomDepPPrandomDepPPDiscrWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(randomDepPPrandomDepPPDiscrWrapper)>::type
+  >( randomDepPPrandomDepPPDiscrWrapper, "randomDepPPrandomDepPPDiscrWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+  // ----------------------------------------------------------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading segmented discriminator PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read segmented discriminators with pre-processings
+  // ----------------------------------------------------------------------------
+  // Read "randomDepPPrandomDepPPDiscrSegmentedWrapper.root"
+  RingerProcedureWrapper<Discrimination::IDiscriminatorVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *randomDepPPrandomDepPPDiscrSegmentedWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(randomDepPPrandomDepPPDiscrSegmentedWrapper)>::type
+  >( randomDepPPrandomDepPPDiscrSegmentedWrapper, "randomDepPPrandomDepPPDiscrSegmentedWrapper.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading specialized discriminator:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read specialized discriminator wrapper with no pre-processings
+  // ----------------------------------------------------------------------------
+  // Read "NNWrapper.root"
+  RingerProcedureWrapper<Discrimination::NNFeedForwardVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *NNWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(NNWrapper)>::type
+  >( NNWrapper, "NNWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "NNWrapper.root"
+  RingerProcedureWrapper<Discrimination::NNFeedForwardVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *FullDepNNWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(FullDepNNWrapper)>::type
+  >( FullDepNNWrapper, "FullDepNNWrapper.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading specialized discriminator with PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read specialized discriminator wrapper with specialized pre-processings
+  // ----------------------------------------------------------------------------
+  // Read "Norm1NNWrapper.root"
+  RingerProcedureWrapper<Discrimination::NNFeedForwardVarDep,
+      EtaIndependent,
+      EtIndependent,
+      NoSegmentation > *Norm1NNWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(Norm1NNWrapper)>::type
+  >( Norm1NNWrapper, "Norm1NNWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "Norm1Norm1FullDepNNWrapper.root"
+  RingerProcedureWrapper<Discrimination::NNFeedForwardVarDep,
+      EtaDependent,
+      EtDependent,
+      TrackCalJointLayers > *Norm1Norm1FullDepNNWrapper(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(Norm1Norm1FullDepNNWrapper)>::type
+  >( Norm1Norm1FullDepNNWrapper, "Norm1Norm1FullDepNNWrapper.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading threshold wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read thresholds
+  // ----------------------------------------------------------------------------
+  // Read "basicThres.root"
+  RingerProcedureWrapper<Discrimination::IThresholdVarDep,
+      EtaIndependent,
+      EtIndependent > *basicThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicThres)>::type
+  >( basicThres, "basicThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaDepThres.root"
+  RingerProcedureWrapper<Discrimination::IThresholdVarDep,
+      EtaDependent,
+      EtIndependent > *basicEtaDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaDepThres)>::type
+  >( basicEtaDepThres, "basicEtaDepThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtDepThres.root"
+  RingerProcedureWrapper<Discrimination::IThresholdVarDep,
+      EtaIndependent,
+      EtDependent > *basicEtDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtDepThres)>::type
+  >( basicEtDepThres, "basicEtDepThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "basicEtaEtDepThres.root"
+  RingerProcedureWrapper<Discrimination::IThresholdVarDep,
+      EtaDependent,
+      EtDependent > *basicEtaEtDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(basicEtaEtDepThres)>::type
+  >( basicEtaEtDepThres, "basicEtaEtDepThres.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Reading specialized threshold wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Read speaclized thresholds
+  // ----------------------------------------------------------------------------
+  // Read "uniqueThres.root"
+  RingerProcedureWrapper<Discrimination::UniqueThresholdVarDep,
+      EtaIndependent,
+      EtIndependent > *uniqueThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(uniqueThres)>::type
+  >( uniqueThres, "uniqueThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "uniqueEtaDepThres.root"
+  RingerProcedureWrapper<Discrimination::UniqueThresholdVarDep,
+      EtaDependent,
+      EtIndependent > *uniqueEtaDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(uniqueEtaDepThres)>::type
+  >( uniqueEtaDepThres, "uniqueEtaDepThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "uniqueEtDepThres.root"
+  RingerProcedureWrapper<Discrimination::UniqueThresholdVarDep,
+      EtaIndependent,
+      EtDependent > *uniqueEtDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(uniqueEtDepThres)>::type
+  >( uniqueEtDepThres, "uniqueEtDepThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Read "uniqueEtaEtDepThres.root"
+  RingerProcedureWrapper<Discrimination::UniqueThresholdVarDep,
+      EtaDependent,
+      EtDependent > *uniqueEtaEtDepThres(nullptr);
+  readWrapperFromFile< 
+    typename Ringer::remove_pointer<decltype(uniqueEtaEtDepThres)>::type
+  >( uniqueEtaEtDepThres, "uniqueEtaEtDepThres.root");
+  // -------------------------- END --- END --- END -----------------------------
+  
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Special reading" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Test reading multiple wrappers
+  // ----------------------------------------------------------------------------
+  readCollectionFromFile<IDiscrWrapper>("Norm1NNWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+  readCollectionFromFile<IDiscrWrapper>("Norm1Norm1FullDepNNWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+  readCollectionFromFile<IThresWrapper>("uniqueEtaEtDepThres.root");
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Finished!" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  return 0;
+}
+
+// =============================================================================
+template< class wrapper_t >
+void readWrapperFromFile(wrapper_t *&wrapper, const char* fileName)
+{
+
+  msg << MSG::INFO << "Reading wrapper: " << wrapper_t::staticFullName() 
+    << ", at file named: " << fileName << endreq;
+
+  // Read file and bring everything to memory:
+  TFile wrapperFile(fileName, "READ");
+  wrapperFile.ReadAll();
+  TDirectory *baseDir = wrapperFile.GetDirectory("");
+
+  std::shared_ptr<THashList> wrapperDirList(nullptr);
+  if ( !( wrapperDirList = IOHelperFcns::getDirList(baseDir) ) ) {
+    throw std::runtime_error(std::string("There are no directories available"));
+  }
+
+  msg << MSG::INFO << "Number(s) of folder(s) within this TFile is " 
+    << wrapperDirList->GetSize()
+    << endreq;
+
+  try {
+
+    TIter iter( wrapperDirList.get() );
+    TDirectory* wrapperDir(nullptr);
+    
+    bool foundDir = false;
+
+    while ( (wrapperDir = static_cast<TDirectoryFile*>(iter())) ){
+      if ( wrapperDir->GetName() == 
+            ( std::string(wrapper_t::wrapName) + 
+              IOHelperFcns::makeIdxStr(0) ) )
+      {
+        msg << MSG::INFO << "Found directory named " 
+          << wrapperDir->GetName() << endreq;
+        foundDir = true;
+        break;
+      }
+    }
+
+    if ( !foundDir ){
+      throw std::runtime_error(std::string("Couldn't find the wrapper directory"));
+    }
+
+    wrapper = wrapper_t::read(wrapperDir,IOHelperFcns::version());
+
+    if (wrapper == nullptr){
+      throw std::runtime_error(std::string("Returned void pointer."));
+    }
+
+    // Use dummy message stream:
+    wrapper->setMsgStream(&msg);
+
+    msg << MSG::INFO << "Printing wrapper " << endreq;
+
+    // to print wrapper information:
+    wrapper->print();
+
+  } catch ( const std::runtime_error &e){
+    msg << MSG::ERROR << "Couldn't read due to error: " 
+      << e.what() << endreq;
+  }
+
+  // Close file
+  wrapperFile.Close();
+}
+
+// =============================================================================
+template<typename wrapperBase_t>
+void readCollectionFromFile(const char* fileName)
+{
+
+  msg << MSG::INFO << "Reading file: " << fileName << endreq;
+
+  // Get wrapper collection and read it:
+  typename wrapperBase_t::WrapperCollection col;
+  wrapperBase_t::read( col, fileName );
+
+  unsigned counter(0);
+  for ( auto *wrapper : col ) {
+    if (wrapper){ 
+      msg << MSG::INFO << "Printing wrapper " << wrapper->fullName() 
+        << " at position " << IOHelperFcns::makeIdxStr(counter++) << endreq;
+      wrapper->setMsgStream(&msg);wrapper->print();
+    } else {
+      msg << MSG::ERROR << "Couldn't print wrapper on file " << fileName << endreq;
+    }
+  }
+
+  msg << MSG::INFO << "File configuration: " << endreq;
+  AsgElectronRingerSelector::IOConfStruct ioConf;
+  AsgElectronRingerSelector::retrieveFileConf( fileName, ioConf );
+  AsgElectronRingerSelector::printConf(ioConf, &msg);
+}
+
+// =============================================================================
+template<>
+void readCollectionFromFile<IThresWrapper>(const char* fileName)
+{
+  
+  msg << MSG::INFO << "Reading file: " << fileName << endreq;
+
+  // Get wrapper collection and read it:
+  IThresWrapper *wrapper;
+  IThresWrapper::read( wrapper, fileName );
+  if (wrapper) {wrapper->setMsgStream(&msg);  wrapper->print();}
+  else msg << MSG::ERROR << "Couldn't print wrapper on file " << fileName << endreq;
+}
+
+
+
diff --git a/PhysicsAnalysis/RingerSelectorTools/util/testWrite.cxx b/PhysicsAnalysis/RingerSelectorTools/util/testWrite.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..454b59609c86ca8eb52de92557679db0b765a92c
--- /dev/null
+++ b/PhysicsAnalysis/RingerSelectorTools/util/testWrite.cxx
@@ -0,0 +1,1442 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: testWrite.cxx 694257 2015-09-10 22:45:27Z wsfreund $
+/**
+ * In this executable we want to test if wrappers can be sucessfully written.
+ *
+ * For that we will create different wrapper types and write them into different
+ * files. Afterwards, it is needed to run testRead on the same path that
+ * testWrite was run and check if the information written is correct.
+ *
+ **/
+
+// STL includes:
+#include <iostream>
+#include <limits>
+#include <type_traits>
+
+// Root includes:
+#include <TFile.h>
+
+// Gaudi includes:
+#if !defined(RINGER_STANDALONE) && !defined(XAOD_STANDALONE)
+# include "GaudiKernel/SystemOfUnits.h"
+using namespace Gaudi::Units;
+// We just do this ugly thing so that we can have a message stream
+// FIXME How can I create a dummy message stream without doing this?
+#define protected public
+#define private public
+# include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#undef protected
+#undef private
+Ringer::AsgElectronRingerSelector __AsgRingerSel__("testWrite");
+MsgStream &msg = __AsgRingerSel__.msg();
+#else
+#include "RingerSelectorTools/AsgElectronRingerSelector.h"
+#include "AsgTools/MsgStream.h"
+MsgStream msg("testWrite");
+#endif
+
+#define BREAKER \
+  "================================================================================"
+
+// Local includes:
+#include "RingerSelectorTools/procedures/RingerProcedureWrapper.h"
+#include "RingerSelectorTools/procedures/Normalizations.h"
+#include "RingerSelectorTools/procedures/NeuralNetwork.h"
+#include "RingerSelectorTools/procedures/Thresholds.h"
+#include "RingerSelectorTools/tools/IOHelperFcns.h"
+#include "RingerSelectorTools/tools/TrackPatternsHolder.h"
+
+using namespace Ringer;
+
+/**
+ * Method dedicated for testing pre-processing wrapper creation
+ **/
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency,
+  SegmentationType segType
+>
+IPreProcWrapper* createPPWrapper(const char *fileName,
+    const std::vector<float> &etaDepBounderies = {0, 2.5},
+    const std::vector<float> &etDepBounderies 
+      = {0, std::numeric_limits<float>::infinity()}
+    );
+
+
+/**
+ * PP factory with segType, eta and et dependency
+ **/
+template<typename procedure_t>
+procedure_t* ppFactoryEtaEtDep(SegmentationType cSegType, 
+    unsigned segIdx, 
+    float etaMin, float etaMax, 
+    float etMin, float etMax,
+    MSG::Level lvl);
+
+/**
+ * PP factory with segType and eta dependency
+ **/
+template<typename procedure_t>
+procedure_t* ppFactoryEtaDep(SegmentationType cSegType,
+    unsigned segIdx, 
+    float etaMin, float etaMax,
+    MSG::Level lvl);
+ 
+/**
+ * PP factory with segType and et dependency
+ **/
+template<typename procedure_t>
+procedure_t* ppFactoryEtDep(SegmentationType cSegType,
+    unsigned segIdx, 
+    float etMin, float etMax,
+    MSG::Level lvl);
+
+/**
+ * PP factory with segType dependency
+ **/
+template<typename procedure_t>
+procedure_t* ppFactoryDep(SegmentationType cSegType, 
+    unsigned segIdx = 0,
+    MSG::Level lvl = MSG::INFO);
+
+/**
+ * PP random factory
+ **/
+PreProcessing::IPreProcessorVarDep* createRandomPP(
+    SegmentationType cSegType, 
+    unsigned segIdx = 0,
+    MSG::Level lvl = MSG::INFO);
+
+/**
+ * Create PP of t
+ **/
+template<typename procedure_t>
+procedure_t* createPP(
+    SegmentationType cSegType, 
+    unsigned segIdx = 0,
+    MSG::Level lvl = MSG::INFO);
+
+/**
+ * Method dedicated for testing discriminator wrapper creation
+ **/
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency,
+  SegmentationType segType
+>
+void createDiscrWrapper(const char* fileName,
+    const IPreProcWrapperCollection* ppWrapper = nullptr,
+    const std::vector<float> &etaDepBounderies = {0, 2.5},
+    const std::vector<float> &etDepBounderies = 
+      {0, std::numeric_limits<float>::infinity()}
+    );
+
+/**
+ * @brief Write wrapper to file
+ **/
+void writeWrapperOnFile(const IProcWrapperBase &wrapper, 
+    const char* fileName, MSG::Level);
+
+/**
+ * Creates eta/et independent neural network
+ *
+ * If goodStatus = false, returns a dummy neural network which always returns 0
+ * as output for an pattern space of dimension size of 100.
+ *
+ * An old MC12 Zee x JF14 neural network is created otherwise.
+ **/
+template<bool goodStatus = true>
+Discrimination::NNFeedForwardVarDep* createNN(SegmentationType cSegType, 
+    unsigned segIdx);
+
+/**
+ * Creates eta dependent, et independent neural network
+ **/
+template<bool goodStatus = true>
+Discrimination::NNFeedForwardVarDep* createEtaDepNN(SegmentationType cSegType, 
+    unsigned segIdx, 
+    float etaMin, float etaMax);
+
+/**
+ * Creates eta independent, et dependent neural network
+ **/
+template<bool goodStatus = true>
+Discrimination::NNFeedForwardVarDep* createEtDepNN(
+    SegmentationType cSegType, 
+    unsigned segIdx, 
+    float etMin, float etMax);
+
+/**
+ * Creates eta dependent, et dependent neural network
+ **/
+template<bool goodStatus = true>
+Discrimination::NNFeedForwardVarDep* createEtaEtDepNN(
+    SegmentationType cSegType, 
+    unsigned segIdx,
+    float etaMin, float etaMax,
+    float etMin, float etMax);
+
+/**
+ * Method dedicated for testing threshold wrapper creation
+ **/
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency
+>
+void createThresWrapper(const char* fileName,
+    const std::vector<float> &etaDepBounderies = {0, 2.5},
+    const std::vector<float> &etDepBounderies = 
+      {0, std::numeric_limits<float>::infinity()},
+    float thresValue = 0
+    );
+
+Discrimination::UniqueThresholdVarDep* createThres(float thresValue);
+Discrimination::UniqueThresholdVarDep* createEtaDepThres(float etaMin, float etaMax,
+    float thresValue);
+Discrimination::UniqueThresholdVarDep* createEtDepThres(float etMin, float etMax,
+    float thresValue);
+Discrimination::UniqueThresholdVarDep* createEtaEtDepThres(
+    float etaMin, float etaMax,
+    float etMin, float etMax,
+    float thresValue);
+
+std::vector< std::vector<unsigned> > segmentationEntries = 
+{
+  { 100 },
+  { 100, (unsigned)(TrackPatternsHolder::numberOfPatterns()) },
+  { 100, (unsigned)(TrackPatternsHolder::numberOfPatterns()), 10 },
+  { 88,  12, (unsigned)(TrackPatternsHolder::numberOfPatterns()), 10 },
+  { 8, 64, 8, 8, 4, 4, 4, (unsigned)(TrackPatternsHolder::numberOfPatterns()), 10 } 
+};
+
+// =============================================================================
+int main( /*int argc, char* argv[]*/){
+
+#if !defined(XAOD_STANDALONE) && !defined(RINGER_STANDALONE)
+  const float GeVf = GeV;
+#endif
+
+  msg.setLevel(MSG::DEBUG);
+
+  // Eta and Et dependency bounderies:
+  const std::vector<float> etaIndepBounderies = {0, 2.5};
+  const std::vector<float> etaDepBounderies = 
+        {0, .1, .6, 1.15, 1.37, 1.52, 1.81, 2.01, 2.37, 2.47, 2.5};
+
+  const std::vector<float> etIndepBounderies = {0, std::numeric_limits<float>::infinity()};
+  const std::vector<float> etDepBounderies =
+#if !defined(XAOD_STANDALONE) && !defined(RINGER_STANDALONE)
+        {0, 5*GeVf, 10*GeVf, 15*GeVf, 20*GeVf, 30*GeVf, 40*GeVf, 50*GeVf, 60*GeVf, 70*GeVf, 80*GeVf, //}
+#else
+        {0, 5*1e3, 10*1e3, 15*1e3, 20*1e3, 30*1e3, 40*1e3, 50*1e3, 60*1e3, 70*1e3, 80*1e3,
+#endif
+        std::numeric_limits<float>::infinity()};
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Testing simple discriminator wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write simple discriminator using interface (without using normalization)
+  // ----------------------------------------------------------------------------
+  // Create independent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // Write it as "basicWrapper"
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Create eta dependent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // Write it as "basicEtaDepWrapper"
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtIndependent,
+    NoSegmentation >("basicEtaDepWrapper.root",
+        nullptr,
+        etaDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Create Et dependent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // Write it as "basicEtDepWrapper"
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaIndependent,
+    EtDependent,
+    NoSegmentation >("basicEtDepWrapper.root",
+        nullptr,
+        etaIndepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Create eta, Et dependent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // Write it as "basicEtDepWrapper"
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtDependent,
+    NoSegmentation >("basicEtaEtDepWrapper.root",
+        nullptr,
+        etaDepBounderies,
+        etDepBounderies);
+
+  // Turn off the messages:
+  msg.setLevel(MSG::ERROR);
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Testing creation of badly configured wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  // -------------------------- END --- END --- END -----------------------------
+
+  // ----------------------------------------------------------------------------
+  // This block shoudln't work
+  // ----------------------------------------------------------------------------
+  // Create independent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // It shouldn't be written because its eta size is different from unit.
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("shouldntWrite.root",
+        nullptr,
+        etaDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Create independent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // No pre-processings available.
+  // It shouldn't be written because its eta size is different from unit.
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("shouldntWrite.root",
+        nullptr,
+        etaIndepBounderies,
+        etDepBounderies);
+  msg.setLevel(MSG::DEBUG);
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  // ----------------------------------------------------------------------------
+
+  // ----------------------------------------------------------------------------
+  // Start testing pre-processings
+  // ----------------------------------------------------------------------------
+  // Create eta, Et dependent and non segmented pp wrapper.
+  // Test it allocating all possible permutations of seg/eta/et dependency.
+  // No pre-processings available.
+  // Write it as "basicPPWrapper"
+  auto *basicPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicPPWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtIndependent,
+    NoSegmentation >("basicEtaDepPPWrapper.root",
+        etaDepBounderies);
+  if (basicEtaDepPPWrapper) basicEtaDepPPWrapper->releaseMemory();
+  delete basicEtaDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaIndependent,
+    EtDependent,
+    NoSegmentation >("basicEtDepPPWrapper.root",
+        etaIndepBounderies,
+        etDepBounderies);
+  if (basicEtDepPPWrapper) basicEtDepPPWrapper->releaseMemory();
+  delete basicEtDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaEtDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtDependent,
+    NoSegmentation >("basicEtEtaDepPPWrapper.root",
+        etaDepBounderies,
+        etDepBounderies);
+  if (basicEtaEtDepPPWrapper) basicEtaEtDepPPWrapper->releaseMemory();
+  delete basicEtaEtDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaEtTrackCalDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalSegmentation >("basicEtEtaTrackCalDepPPWrapper.root",
+        etaDepBounderies,
+        etDepBounderies);
+  if (basicEtaEtTrackCalDepPPWrapper) basicEtaEtTrackCalDepPPWrapper->releaseMemory();
+  delete basicEtaEtTrackCalDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaEtTrackCalPatTypeDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalPatTypeSegmentation >("basicEtEtaTrackCalPatTypeDepPPWrapper.root",
+        etaDepBounderies,
+        etDepBounderies);
+  if (basicEtaEtTrackCalDepPPWrapper) basicEtaEtTrackCalPatTypeDepPPWrapper->releaseMemory();
+  delete basicEtaEtTrackCalPatTypeDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaEtSectionDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointSections >("basicEtaEtSectionDepPPWrapper.root",
+        etaDepBounderies,
+        etDepBounderies);
+  if (basicEtaEtSectionDepPPWrapper) basicEtaEtSectionDepPPWrapper->releaseMemory();
+  delete basicEtaEtSectionDepPPWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicEtaEtLayerDepPPWrapper = createPPWrapper<PreProcessing::IPreProcessorVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointLayers >("basicEtaEtLayerDepPPWrapper.root",
+        etaDepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicNorm1Wrapper = createPPWrapper<PreProcessing::Norm::Norm1VarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicNorm1Wrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicLayerDepNorm1Wrapper = createPPWrapper<PreProcessing::Norm::Norm1VarDep,
+    EtaIndependent,
+    EtIndependent,
+    TrackCalJointLayers >("basicLayerDepNorm1Wrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicNorm2Wrapper = createPPWrapper<PreProcessing::Norm::Norm2VarDep,
+    EtaIndependent,
+    EtIndependent,
+    TrackCalJointLayers >("basicNorm2Wrapper.root");
+  if (basicNorm2Wrapper) basicNorm2Wrapper->releaseMemory();
+  delete basicNorm2Wrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicSqrtWrapper = createPPWrapper<PreProcessing::Norm::SqrtVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicSqrtWrapper.root");
+  if (basicSqrtWrapper) basicSqrtWrapper->releaseMemory();
+  delete basicSqrtWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicConstantValueWrapper = createPPWrapper<PreProcessing::Norm::ConstantValueVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicConstantValueWrapper.root");
+  if (basicConstantValueWrapper) basicConstantValueWrapper->releaseMemory();
+  delete basicConstantValueWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicMevToGevWrapper = createPPWrapper<PreProcessing::Norm::MevToGevVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicMevToGevWrapper.root");
+  if (basicMevToGevWrapper) basicMevToGevWrapper->releaseMemory();
+  delete basicMevToGevWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicSequentialWrapper = createPPWrapper<PreProcessing::Norm::SequentialVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicSequentialWrapper.root");
+  if (basicSequentialWrapper) basicSequentialWrapper->releaseMemory();
+  delete basicSequentialWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicSpherizationWrapper = createPPWrapper<PreProcessing::Norm::SpherizationVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicSpherizationWrapper.root");
+  if (basicSpherizationWrapper) basicSpherizationWrapper->releaseMemory();
+  delete basicSpherizationWrapper;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  auto *basicMinMaxWrapper = createPPWrapper<PreProcessing::Norm::MinMaxVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("basicMinMaxWrapper.root");
+  if (basicMinMaxWrapper) basicMinMaxWrapper->releaseMemory();
+  delete basicMinMaxWrapper;
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating discriminator with PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+  
+  // ----------------------------------------------------------------------------
+  // Write discriminators with pre-processings
+  // ----------------------------------------------------------------------------
+  // Create Eta, Et dependent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // PP available {Unspecialized Norm1}.
+  // Write it as "randomNorm1DiscrWrapper.root"
+  IPreProcWrapperCollection randomNorm1PP = {basicPPWrapper};
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtDependent,
+    NoSegmentation >("randomNorm1PPDiscrWrapper.root",
+        &randomNorm1PP,
+        etaDepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // Create Eta, Et dependent and non segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // PP available {Unspecialized}.
+  // Write it as "randomDepPPrandomDepPP"
+  IPreProcWrapperCollection randomDepPPrandomDepPP = {
+    basicEtaEtLayerDepPPWrapper, basicEtaEtLayerDepPPWrapper
+  };
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtDependent,
+    NoSegmentation >("randomDepPPrandomDepPPDiscrWrapper.root",
+        &randomDepPPrandomDepPP,
+        etaDepBounderies,
+        etDepBounderies);
+  // ----------------------------------------------------------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating segmented discriminator with PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write segmented discriminators with pre-processings
+  // ----------------------------------------------------------------------------
+  // Create Eta, Et dependent and segmented wrapper.
+  // Test it allocating all possible permutations of eta/et dependency.
+  // PP available {Unspecialized Unspecialized}.
+  // Write it as "randomDepPPrandomDepPPDiscrSegmentedWrapper"
+  createDiscrWrapper<Discrimination::IDiscriminatorVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointLayers >("randomDepPPrandomDepPPDiscrSegmentedWrapper.root",
+        &randomDepPPrandomDepPP,
+        etaDepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating specialized discriminator:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write specialized discriminator wrapper with no pre-processings
+  // ----------------------------------------------------------------------------
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("NNWrapper.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointLayers >("FullDepNNWrapper.root",
+        {},
+        etaDepBounderies,
+        etDepBounderies);
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating specialized discriminator with PP wrappers:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write specialized discriminator wrapper with specialized pre-processings
+  // ----------------------------------------------------------------------------
+  IPreProcWrapperCollection basicNorm1WrapperVec = {basicNorm1Wrapper};
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("Norm1NNWrapper.root", &basicNorm1WrapperVec);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  IPreProcWrapperCollection fullDepWrapperVec0 = {basicLayerDepNorm1Wrapper};
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointLayers >("Norm1FullDepNNWrapper.root",
+        &fullDepWrapperVec0,
+        etaDepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  IPreProcWrapperCollection fullDepWrapperVec = {basicLayerDepNorm1Wrapper, basicLayerDepNorm1Wrapper};
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaDependent,
+    EtDependent,
+    TrackCalJointLayers >("Norm1Norm1FullDepNNWrapper.root",
+        &fullDepWrapperVec,
+        etaDepBounderies,
+        etDepBounderies);
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating thresholds:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write thresholds
+  // ----------------------------------------------------------------------------
+  createThresWrapper<Discrimination::IThresholdVarDep,
+    EtaIndependent,
+    EtIndependent >("basicThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::IThresholdVarDep,
+    EtaDependent,
+    EtIndependent >("basicEtaDepThres.root",
+        etaDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::IThresholdVarDep,
+    EtaIndependent,
+    EtDependent >("basicEtDepThres.root",
+        etaIndepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::IThresholdVarDep,
+    EtaDependent,
+    EtDependent >("basicEtaEtDepThres.root",
+        etaDepBounderies,
+        etDepBounderies);
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Creating specialized thresholds:" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  // ----------------------------------------------------------------------------
+  // Write specialized thresholds
+  // ----------------------------------------------------------------------------
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaIndependent,
+    EtIndependent >("uniqueThres.root");
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaDependent,
+    EtIndependent >("uniqueEtaDepThres.root",
+        etaDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaIndependent,
+    EtDependent >("uniqueEtDepThres.root",
+        etaIndepBounderies,
+        etDepBounderies);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaDependent,
+    EtDependent >("uniqueEtaEtDepThres.root",
+        etaDepBounderies,
+        etDepBounderies);
+  // -------------------------- END --- END --- END -----------------------------
+
+
+  // ----------------------------------------------------------------------------
+  // Creating test discrimination wrappers:
+  // ----------------------------------------------------------------------------
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("ElectronRingerDiscrTestLoose.root", &basicNorm1WrapperVec);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("ElectronRingerDiscrTestMedium.root", &basicNorm1WrapperVec);
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createDiscrWrapper<Discrimination::NNFeedForwardVarDep,
+    EtaIndependent,
+    EtIndependent,
+    NoSegmentation >("ElectronRingerDiscrTestTight.root", &basicNorm1WrapperVec);
+  msg << MSG::INFO << BREAKER << endreq;
+  // -------------------------- END --- END --- END -----------------------------
+
+  // ----------------------------------------------------------------------------
+  // Creating test threshold wrappers:
+  // ----------------------------------------------------------------------------
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaIndependent,
+    EtIndependent >("ElectronRingerThresTestLoose.root",
+        etaIndepBounderies,
+        etIndepBounderies,
+        0.948 );
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaIndependent,
+    EtIndependent >("ElectronRingerThresTestMedium.root",
+        etaIndepBounderies,
+        etIndepBounderies,
+        0.2644 );
+  msg << MSG::INFO << BREAKER << endreq;
+
+  createThresWrapper<Discrimination::UniqueThresholdVarDep,
+    EtaIndependent,
+    EtIndependent >("ElectronRingerThresTestTight.root",
+        etaIndepBounderies,
+        etIndepBounderies,
+        0.2826 );
+  // -------------------------- END --- END --- END -----------------------------
+
+  msg << MSG::INFO << BREAKER << endreq;
+  msg << MSG::INFO << "Finished!" << endreq;
+  msg << MSG::INFO << BREAKER << endreq;
+
+  return 0;
+}
+
+// =============================================================================
+void writeWrapperOnFile(const IProcWrapperBase &wrapper, const char* fileName,
+    MSG::Level lvl)
+{
+  msg << lvl << "Writing to file!" << endreq;
+
+  TFile wrapperFile(fileName, "RECREATE");
+  auto wrapperDir = wrapperFile.GetDirectory("");
+
+  // Write wrapper on the file:
+  wrapper.write(wrapperDir, IOHelperFcns::makeIdxStr(0).c_str());
+
+  if ( msg.level() <= lvl ){
+    wrapperDir->ls();
+  }
+
+  // Write and close file
+  wrapperFile.Write();
+  wrapperFile.Close();
+}
+
+// =============================================================================
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency,
+  SegmentationType segType
+>
+IPreProcWrapper* createPPWrapper(const char *fileName,
+    const std::vector<float> &etaDepBounderies,
+    const std::vector<float> &etDepBounderies)
+{
+  // Typedef to make things easier
+  typedef RingerProcedureWrapper<procedure_t, 
+          etaDependency, 
+          etDependency, 
+          segType> wrapper_t;
+
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+
+  msg << MSG::INFO << "Attempting to create a RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((std::is_same<procedure_t,PreProcessing::IPreProcessorVarDep>::value)?",":"(VarDep),")
+        << toStr(etaDependency) << "," 
+        << toStr(etDependency) << "," 
+        << toStr(segType) << "> with file name: " << fileName << "." << endreq;
+
+  unsigned etaDepProc = etaDepBounderies.size() - 1; 
+  unsigned etDepProc = etDepBounderies.size() - 1; 
+
+  IPreProcWrapper *ret(nullptr);
+
+  // Loop over variable dependencies
+  for ( unsigned uSegType = NoSegmentation; 
+      uSegType < NSegmentations;
+      ++uSegType )
+  {
+    SegmentationType cSegType = static_cast<SegmentationType>(uSegType);
+    //if ( segType == SegmentationType::TrackCalPatTypeSegmentation ) {
+    //  continue;
+    //}
+    for ( unsigned uEtaDep = EtaIndependent; uEtaDep <= EtaDependent; ++uEtaDep ){
+      EtaDependency etaDep = static_cast<EtaDependency>(uEtaDep);
+      for ( unsigned uEtDep = EtIndependent; uEtDep <= EtDependent; ++uEtDep ){
+        EtDependency etDep = static_cast<EtDependency>(uEtDep);
+
+        // Change message level accondingly if we are creating correct wrapper
+        // type
+        MSG::Level lvl(MSG::VERBOSE);
+        if ( cSegType == segType && 
+            etaDep == etaDependency &&
+            etDep == etDependency )
+        {
+          lvl = MSG::INFO;
+        }
+
+
+        // The collection holder
+        typename wrapper_t::PPDepProcCollection ppCol(
+            numberOfSegments(cSegType),
+            std::vector< std::vector<procedure_t*> >(
+                etDepProc, std::vector<procedure_t*>(etaDepProc,
+                  nullptr)));
+
+        // Fill collection
+        for ( unsigned segDepIdx = 0; segDepIdx < numberOfSegments(cSegType); ++segDepIdx ){
+          for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+            // Get et bounderies:
+            float etMin(etDepBounderies[etDepIdx]),
+                  etMax(etDepBounderies[etDepIdx+1]);
+            for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+              // Get eta bounderies:
+              float etaMin(etaDepBounderies[etaDepIdx]),
+                    etaMax(etaDepBounderies[etaDepIdx+1]);
+
+
+              // Fill collection:
+              if (etaDep) {
+                if (etDep) {
+                  ppCol[segDepIdx][etDepIdx][etaDepIdx] = 
+                    ppFactoryEtaEtDep<procedure_t>(cSegType,
+                        segDepIdx,
+                        etaMin, 
+                        etaMax, 
+                        etMin, 
+                        etMax,
+                        MSG::VERBOSE);
+                } else {
+                  ppCol[segDepIdx][etDepIdx][etaDepIdx] = 
+                    ppFactoryEtaDep<procedure_t>(cSegType,
+                        segDepIdx,
+                        etaMin, 
+                        etaMax,
+                        MSG::VERBOSE);
+                }
+              } else {
+                if (etDep) {
+                  ppCol[segDepIdx][etDepIdx][etaDepIdx] = 
+                    ppFactoryEtDep<procedure_t>(cSegType, 
+                        segDepIdx,
+                        etMin, 
+                        etMax,
+                        MSG::VERBOSE);
+                } else {
+                  ppCol[segDepIdx][etDepIdx][etaDepIdx] = 
+                    ppFactoryDep<procedure_t>(cSegType,
+                        segDepIdx,
+                        MSG::VERBOSE);
+                }
+              }
+            }
+          }
+        } // Finished looping and filling collection
+
+        // Attempt to create a wrapper with filled collection:
+        try {
+
+          msg << lvl << "Attempting to create wrapper with (" 
+            << toStr(segType) << "," << toStr(etaDep) << "," << toStr(etDep) 
+            << ") pre-processing" << endreq;
+
+          //msg << lvl << ppCol << endreq;
+
+          // Create wrapper:
+          auto wrapper = new wrapper_t(ppCol);
+          // Use dummy message stream:
+          wrapper->setMsgStream(&msg);
+          // Print wrapper:
+          wrapper->print(MSG::DEBUG);
+
+          // If it succeed, write it into file:
+          writeWrapperOnFile(*wrapper, fileName, MSG::VERBOSE);
+          //IPreProcWrapperCollection ppWrapperCol = {wrapper};
+          //IPreProcWrapper::writeCol( ppWrapperCol, fileName );
+
+          // We do not release memory for the wrapper, it will be given as a
+          // return parameter.
+          ret = wrapper;
+
+          msg << lvl << "Succeed!" << endreq;
+
+        } catch (const std::runtime_error &e) {
+
+          msg << MSG::VERBOSE << "Couldn't create wrapper. Reason: "
+            << e.what() << endreq;
+
+          // Release collection memory
+          for ( unsigned segDepIdx = 0; segDepIdx < numberOfSegments(cSegType); ++segDepIdx ){
+            for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+              for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+                delete ppCol[segDepIdx][etDepIdx][etaDepIdx];
+                ppCol[segDepIdx][etDepIdx][etaDepIdx] = nullptr;
+              }
+            }
+          }
+        } // Finished creating wrapper and handling possible errors
+
+      }
+    }
+  }  // Finished looping over segType/eta/et.
+  return ret;
+}
+
+// =============================================================================
+template<typename procedure_t>
+procedure_t* ppFactoryEtaEtDep(SegmentationType cSegType,
+    unsigned segIdx, 
+    float etaMin, float etaMax, 
+    float etMin, float etMax,
+    MSG::Level lvl)
+{
+  procedure_t* pp(nullptr);
+  if ( std::is_same<procedure_t,PreProcessing::IPreProcessorVarDep>::value )
+  {
+    pp = reinterpret_cast<procedure_t*>(createRandomPP(cSegType, segIdx, lvl));
+  } else {
+    pp = createPP<procedure_t>( cSegType, segIdx, lvl );
+  }
+  pp->setEtaEtDep(etaMin, etaMax, etMin, etMax);
+  return pp;
+}
+
+// =============================================================================
+template<typename procedure_t>
+procedure_t* ppFactoryEtaDep(SegmentationType cSegType,
+    unsigned segIdx, 
+    float etaMin, float etaMax,
+    MSG::Level lvl)
+{
+  procedure_t* pp(nullptr);
+  if ( std::is_same<procedure_t,PreProcessing::IPreProcessorVarDep>::value )
+  {
+    pp = reinterpret_cast<procedure_t*>(createRandomPP(cSegType, segIdx, lvl));
+  } else {
+    pp = createPP<procedure_t>( cSegType, segIdx, lvl );
+  }
+  pp->setEtaDep(etaMin, etaMax);
+  return pp;
+}
+ 
+// =============================================================================
+template<typename procedure_t>
+procedure_t* ppFactoryEtDep(SegmentationType cSegType,
+    unsigned segIdx, 
+    float etMin, float etMax,
+    MSG::Level lvl)
+{
+  procedure_t* pp(nullptr);
+  if ( std::is_same<procedure_t,PreProcessing::IPreProcessorVarDep>::value )
+  {
+    pp = reinterpret_cast<procedure_t*>(createRandomPP(cSegType, segIdx, lvl));
+  } else {
+    pp = createPP<procedure_t>( cSegType, segIdx, lvl );
+  }
+  pp->setEtDep(etMin, etMax);
+  return pp;
+}
+
+// =============================================================================
+template<typename procedure_t>
+procedure_t* ppFactoryDep(SegmentationType cSegType, 
+    unsigned segIdx,
+    MSG::Level lvl)
+{
+  if ( std::is_same<procedure_t,PreProcessing::IPreProcessorVarDep>::value )
+  {
+    return reinterpret_cast<procedure_t*>(createRandomPP( cSegType, segIdx, lvl));
+  } else {
+    return createPP<procedure_t>( cSegType, segIdx, lvl );
+  }
+}
+
+// =============================================================================
+PreProcessing::IPreProcessorVarDep* createRandomPP(SegmentationType cSegType, 
+    unsigned segIdx,
+    MSG::Level lvl)
+{
+  static unsigned sequenceLoop = 0;
+  switch ( static_cast<PreProcessing::Type::PreProcessorTypes>(2+((sequenceLoop++)%7)) ) {
+    case PreProcessing::Type::Norm1:
+      msg << lvl << "Creating Norm1" << endreq;
+      return new PreProcessing::Norm::Norm1VarDep;
+      break;
+    case PreProcessing::Type::Norm2:
+      msg << lvl << "Creating Norm2" << endreq;
+      return new PreProcessing::Norm::Norm2VarDep;
+      break;
+    case PreProcessing::Type::Sqrt:
+      msg << lvl << "Creating Sqrt" << endreq;
+      return new PreProcessing::Norm::SqrtVarDep;
+      break;
+    case PreProcessing::Type::ConstantValue:
+      msg << lvl << "Creating ConstantValue" << endreq;
+      return new PreProcessing::Norm::ConstantValueVarDep(987);
+      break;
+    case PreProcessing::Type::Sequential:
+      msg << lvl << "Creating Sequential" << endreq;
+      return new PreProcessing::Norm::SequentialVarDep(100,.001);
+      break;
+    case PreProcessing::Type::Spherization:
+    {
+      msg << lvl << "Creating Spherization" << endreq;
+      auto std = new PreProcessing::Norm::SpherizationVarDep(
+          std::vector<float>( segmentationEntries[cSegType][segIdx], 21 ),
+          std::vector<float>( segmentationEntries[cSegType][segIdx], 61 )
+          );
+      return std;
+      break;
+    }
+    case PreProcessing::Type::MinMax:
+    {
+      msg << lvl << "Creating MinMax" << endreq;
+      auto minMax = new PreProcessing::Norm::MinMaxVarDep(
+          std::vector<float>( segmentationEntries[cSegType][segIdx], 11 ),
+          std::vector<float>( segmentationEntries[cSegType][segIdx], 92 )
+          );
+      return minMax;
+      break;
+    }
+    default:
+      throw std::runtime_error(std::string( "Couldn't create pre-processing." ));
+  }
+}
+
+// =============================================================================
+template<typename procedure_t>
+procedure_t* createPP(SegmentationType cSegType, unsigned segIdx,
+    MSG::Level /*lvl*/)
+{
+  if ( Ringer::is_same<procedure_t,PreProcessing::Norm::Norm1VarDep>::value ){
+    return reinterpret_cast<procedure_t*>(new PreProcessing::Norm::Norm1VarDep);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::Norm2VarDep>::value ) {
+    return reinterpret_cast<procedure_t*>(new PreProcessing::Norm::Norm2VarDep);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::SqrtVarDep>::value ) {
+    return reinterpret_cast<procedure_t*>(new PreProcessing::Norm::SqrtVarDep);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::ConstantValueVarDep>::value ) {
+    return reinterpret_cast<procedure_t*>(new PreProcessing::Norm::ConstantValueVarDep(123));
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::MevToGevVarDep>::value ) {
+    return reinterpret_cast<procedure_t*>(new PreProcessing::Norm::MevToGevVarDep);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::SequentialVarDep>::value ) {
+    auto seq = new PreProcessing::Norm::SequentialVarDep(100,.001);
+    return reinterpret_cast<procedure_t*>(seq);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::SpherizationVarDep>::value ) {
+    auto std = new PreProcessing::Norm::SpherizationVarDep(
+        std::vector<float>( segmentationEntries[cSegType][segIdx], 21 ),
+        std::vector<float>( segmentationEntries[cSegType][segIdx], 61 )
+        );
+    return reinterpret_cast<procedure_t*>(std);
+  } else if ( Ringer::is_same<procedure_t,PreProcessing::Norm::MinMaxVarDep>::value ) {
+    auto minMax = new PreProcessing::Norm::MinMaxVarDep(
+        std::vector<float>( segmentationEntries[cSegType][segIdx], 11 ),
+        std::vector<float>( segmentationEntries[cSegType][segIdx], 92 )
+        );
+    return reinterpret_cast<procedure_t*>(minMax);
+  } else {
+    throw std::runtime_error(std::string("Unknown pre-processing type."));
+  }
+}
+
+// =============================================================================
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency,
+  SegmentationType segType
+>
+void createDiscrWrapper(const char *fileName,
+    const IPreProcWrapperCollection* ppWrapperCol,
+    const std::vector<float> &etaDepBounderies,
+    const std::vector<float> &etDepBounderies)
+{
+  // Typedef to make things easier
+  typedef RingerProcedureWrapper<procedure_t, 
+          etaDependency, 
+          etDependency, 
+          segType> wrapper_t;
+
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+
+  msg << MSG::INFO << "Attempting to create a RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((Ringer::is_same<procedure_t,Discrimination::IDiscriminatorVarDep>::value)?",":"(VarDep),")
+        << toStr(etaDependency) << "," 
+        << toStr(etDependency) << "," 
+        << toStr(segType) << "> with file name: " << fileName << "." << endreq;
+
+  unsigned etaDepProc = etaDepBounderies.size() - 1; 
+  unsigned etDepProc = etDepBounderies.size() - 1; 
+
+  // Loop over variable dependencies
+  for ( unsigned uEtaDep = EtaIndependent; uEtaDep <= EtaDependent; ++uEtaDep ){
+    for ( unsigned uEtDep = EtIndependent; uEtDep <= EtDependent; ++uEtDep ){
+      // The enumerations
+      EtaDependency etaDep = static_cast<EtaDependency>(uEtaDep);
+      EtDependency etDep = static_cast<EtDependency>(uEtDep);
+
+      // Change message level accondingly if we are creating correct wrapper
+      // type
+      MSG::Level lvl(MSG::VERBOSE);
+      if ( etaDep == etaDependency &&
+          etDep == etDependency )
+      {
+        lvl = MSG::INFO;
+      }
+
+      // The collection holder
+      typename wrapper_t::DiscrDepProcCollection discrCol(numberOfSegments(segType),
+          std::vector< std::vector<procedure_t*> >(
+              etDepProc, std::vector<procedure_t*>(etaDepProc,
+                nullptr)));
+
+      // Fill collection
+      for ( unsigned segDepIdx = 0; segDepIdx < numberOfSegments(segType); ++segDepIdx ){
+        for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+          // Get et bounderies:
+          float etMin(etDepBounderies[etDepIdx]),
+                etMax(etDepBounderies[etDepIdx+1]);
+          for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+            // Get eta bounderies:
+            float etaMin(etaDepBounderies[etaDepIdx]),
+                  etaMax(etaDepBounderies[etaDepIdx+1]);
+
+            // Fill collection:
+            if (etaDep) {
+              if (etDep) {
+                discrCol[segDepIdx][etDepIdx][etaDepIdx] = createEtaEtDepNN(
+                    segType, segDepIdx,
+                    etaMin, 
+                    etaMax, 
+                    etMin, 
+                    etMax);
+              } else {
+                discrCol[segDepIdx][etDepIdx][etaDepIdx] = createEtaDepNN(
+                    segType, segDepIdx,
+                    etaMin, 
+                    etaMax);
+            }
+            } else {
+              if (etDep) {
+                discrCol[segDepIdx][etDepIdx][etaDepIdx] = createEtDepNN(
+                    segType, segDepIdx,
+                    etMin, 
+                    etMax);
+              } else {
+                discrCol[segDepIdx][etDepIdx][etaDepIdx] = createNN(segType, segDepIdx);
+              }
+            }
+          }
+        }
+      } // Finished looping and filling collection
+
+      // Attempt to create a wrapper with filled collection:
+      try {
+
+        msg << lvl << "Attempting to create wrapper with (" 
+          << toStr(etaDep) << "," << toStr(etDep) << ") discriminator" 
+          << endreq;
+
+        wrapper_t* wrapper(nullptr); 
+        // Create wrapper:
+        if ( !ppWrapperCol || ppWrapperCol->empty() ){
+          wrapper = new wrapper_t(discrCol);
+        } else {
+          wrapper = new wrapper_t(*ppWrapperCol, discrCol);
+        }
+        // Use dummy message stream:
+        wrapper->setMsgStream(&msg);
+        // Print wrapper:
+        wrapper->print(MSG::DEBUG);
+
+        // Delete file if it already exists:
+        IOHelperFcns::deleteFile( fileName );
+
+        // Create IDiscrWrapperCollection and write it:
+        //writeWrapperOnFile(*wrapper, fileName, MSG::VERBOSE);
+        IDiscrWrapperCollection discrWrapperCol = {wrapper};
+        IDiscrWrapper::writeCol(discrWrapperCol, fileName);
+
+        // Add file io information:
+        AsgElectronRingerSelector::IOConfStruct ioConf;
+        ioConf.useBLOutliers = true;
+        AsgElectronRingerSelector::writeConf( fileName, ioConf );
+        AsgElectronRingerSelector::printConf(ioConf, &msg );
+
+        // Release wrapper memory:
+        //wrapper->releaseMemory();
+        //delete wrapper;
+
+        msg << lvl << "Succeed!" << endreq;
+
+      } catch (const std::runtime_error &e) {
+
+        msg << MSG::VERBOSE << "Couldn't create wrapper. Reason: "
+          << e.what() << endreq;
+
+        // Release collection memory
+        for ( unsigned segDepIdx = 0; segDepIdx < numberOfSegments(segType); ++segDepIdx ){
+          for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+            for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+              delete discrCol[segDepIdx][etDepIdx][etaDepIdx];
+              discrCol[segDepIdx][etDepIdx][etaDepIdx] = nullptr;
+            }
+          }
+        }
+      } // Finished creating wrapper and handling possible errors
+
+    }
+  } // Finished looping over eta/et.
+}
+
+// =============================================================================
+template<bool goodStatus>
+Discrimination::NNFeedForwardVarDep* createNN(SegmentationType cSegType, 
+    unsigned segIdx)
+{
+  if ( goodStatus ){
+    switch (cSegType)
+    {
+      case SegmentationType::NoSegmentation:
+      {
+        std::vector<unsigned int> nodes = {100,16,1};
+          std::vector<float> weights = {0.028688,-0.062593,-0.110670,-0.109672,-0.224397,-0.113062,0.039054,-0.529236,-2.888686,-0.605837,-0.994450,0.006954,-0.056765,-0.031750,-0.503685,-0.494298,-0.221056,0.400392,-0.531358,-0.629313,0.089911,-1.007010,-0.629093,-0.716350,-0.273729,-0.826810,-0.214472,-0.975512,-0.396733,-0.003727,-0.276535,-0.056521,0.186771,-0.077535,-0.058493,-0.245285,-0.982163,-0.797398,-0.073127,-0.115995,-0.007802,-1.154354,-0.132477,-0.594071,0.124951,-0.115163,-0.164945,-0.095116,-0.324021,-0.066871,-0.051343,-0.719736,-0.064108,0.144933,-0.404720,-0.052662,-0.203778,-0.495595,0.025789,-0.115119,-0.153406,-1.088269,-1.284559,0.007588,-0.376025,-0.218487,-0.014306,0.037344,-0.159262,0.033259,-0.300734,-0.328634,-1.224337,0.318360,-0.545602,0.263710,-0.034113,-0.121256,-0.271094,-0.406514,0.282135,0.078523,0.364275,-0.856901,-0.442518,-0.008571,-0.030869,0.089742,-1.372179,0.552057,-0.457882,-0.200123,-1.674263,-0.621302,-0.498098,-0.299907,-1.576183,0.046803,-0.091531,-0.096722,1.568295,0.231312,-0.640472,-3.136615,-2.410643,-13.031759,33.412286,-8.683243,1.475885,0.969468,0.017705,0.295497,0.938570,-0.365949,-1.487067,-1.581031,-7.219507,-5.611233,-2.667463,-3.709057,-0.538870,-0.711813,0.433348,-0.594230,-0.844310,-1.288160,-0.741892,-1.830146,-0.325822,-1.631410,-1.751475,-1.720901,-0.898951,-13.288799,-1.933127,-3.081192,-6.221801,-1.104714,-3.841797,-3.328604,-5.193892,-0.808612,-0.796501,-0.288802,7.600919,-0.329103,-2.054659,-0.080070,-7.080676,-0.922352,-4.327209,-3.596929,-1.918411,-3.564654,3.974327,-2.244009,-4.969694,-8.027518,-6.920259,-8.452600,-2.703256,-6.863256,-3.882042,-6.151130,-26.816965,-94.151225,-14.878026,-9.943644,-37.491924,-46.556123,-1.433659,-2.125969,0.698555,1.188699,-1.000490,-0.471744,-0.684885,-4.686223,11.678164,-9.628196,12.210666,-2.342332,-1.902629,-1.247211,-1.661623,-1.388010,-1.868174,-1.932632,-1.209638,2.603166,0.492622,1.332110,-1.645321,1.261750,-4.505736,0.740274,-0.668193,-0.267155,0.334967,3.742837,0.740339,-0.073527,-0.324355,-0.064818,-0.051392,0.094401,0.154956,-0.067873,0.440951,0.138248,-0.572323,-0.010880,-0.047062,-0.180201,-0.479383,-0.188006,-0.424571,-0.457951,-0.638549,-0.298774,-0.708894,-0.359068,-0.192183,-1.064735,-0.140763,-0.518375,0.131144,-0.282072,-0.277306,-0.393560,0.307943,-0.087220,-0.106205,-0.135257,-0.082795,-0.240611,-0.450951,-0.439167,-0.101002,-0.123107,-0.063369,-0.086694,-0.493826,0.086611,0.178572,-0.215764,-0.120014,0.351601,-0.273922,0.485342,-0.132585,0.111573,-0.076256,0.067623,-0.109474,0.206897,-0.093580,-0.016174,0.008848,-0.061735,0.014456,-0.013979,-0.631338,0.191005,-0.191373,-0.267904,0.389943,0.057172,-0.028360,-0.138402,-0.162590,-0.098487,-0.271238,-0.218225,0.084942,-0.490171,-0.076231,-0.104584,-0.075355,-0.206857,1.956858,1.263630,-1.606997,0.258611,-0.221201,-0.126122,0.055639,-0.052784,0.267501,-0.976859,0.077316,-0.236870,-1.100098,-0.340871,0.266472,-0.033575,-1.106904,-0.048352,-0.034147,-0.027628,-0.907428,-0.114443,0.639170,-5.046371,2.117636,12.534221,4.109699,1.002582,-6.121682,-1.300009,0.000709,0.001165,-0.206458,0.354377,-3.450948,3.458475,17.388021,19.380078,5.190390,4.633401,9.791459,1.829216,29.071445,2.496838,3.528770,5.186754,1.097003,1.898567,1.687048,1.712853,18.696546,2.422834,2.972473,1.986865,1.978833,2.538006,8.025286,10.573317,16.791273,3.481498,3.077972,1.144574,0.829633,5.784941,3.109096,7.093387,53.518546,45.052680,9.139784,13.222146,2.750695,3.407295,6.188783,3.406966,-23.018505,2.266498,5.030206,8.614132,5.835313,5.992136,7.205853,6.317150,0.141573,7.108026,-93.605318,-111.675271,2.469222,2.625255,1.189963,0.092941,1.280597,0.471347,-0.712683,-0.367087,0.920240,-0.766278,0.996182,10.240765,8.472205,8.538664,0.794154,3.866253,2.359055,2.030608,1.149638,2.585729,2.002529,1.638214,1.052308,-1.465720,-1.196036,-3.249994,1.560568,-20.990768,0.155179,-1.015941,0.794045,-0.179825,-19.952022,1.910052,1.051576,0.060563,0.031857,0.070955,0.007167,0.378318,0.023833,0.649955,4.275588,0.027542,0.627095,-0.024055,0.048692,0.653087,-0.136869,0.853252,0.711888,0.746423,0.917728,1.660293,0.943031,0.591943,-0.978663,1.058206,0.267564,-0.642447,0.024186,0.398969,-0.004766,0.372238,0.077377,-0.042264,0.054782,0.081330,0.037063,0.236487,0.187889,-0.077143,-0.182055,-0.012978,-0.179301,-0.157928,0.005376,-0.020677,5.841787,0.412119,0.708508,0.070569,-0.645499,-0.112014,0.125128,0.024352,0.703745,0.062582,0.280714,0.045282,0.155499,0.189150,0.299881,0.054184,-0.049919,0.111692,0.026760,0.135167,0.270543,0.148473,-0.015246,-0.100352,0.165556,0.170405,0.228728,0.319828,0.835729,-0.198271,0.439356,-0.002287,0.066184,0.327133,0.233683,0.278432,-3.083528,-1.286595,1.464285,0.698704,0.024064,0.079657,0.007752,0.066683,0.711628,-0.769123,0.203221,0.116553,0.573138,0.035675,-0.406918,0.183639,-1.605187,-0.058066,0.070112,0.147746,-2.392498,-2.745882,1.263215,0.181240,0.343909,-3.675908,4.112136,0.180781,-4.340636,-2.242731,-2.255890,-2.695255,-1.605709,0.047641,-0.994458,5.288881,3.168465,4.077442,1.480216,1.922621,-1.683723,1.113707,0.608307,1.749436,1.209098,3.086876,0.551001,-1.049812,0.239036,-1.736003,-1.371147,29.087469,0.396884,1.155119,4.757856,-0.492357,-2.349446,0.096400,-3.124810,0.448417,0.128918,0.592998,0.331566,0.300982,0.001730,0.269922,-3.360424,-15.594998,-0.537339,9.110059,-2.362906,-1.938478,-1.143943,-0.152321,-2.628727,-0.891215,-1.643069,-4.414059,-10.897783,-6.394373,0.097377,-11.008657,-2.151860,-11.556536,-16.268739,-31.602494,-11.505709,-1.876816,-6.329613,1.669843,0.571898,-2.337885,-1.365757,-0.944771,0.970493,-0.442543,0.995064,-3.749592,-5.691184,-4.139481,-0.788088,4.890539,2.398736,2.532407,1.881680,1.500637,0.623273,-30.264643,9.645718,10.514421,8.475971,0.121070,2.874658,4.640818,1.437012,1.848824,-2.715429,-0.324435,0.844252,6.818916,2.389538,0.107453,0.263178,4.235293,0.609985,1.110795,0.093694,-1.311855,2.269984,5.058177,1.137608,1.277659,-0.033944,-0.164212,-2.001901,-7.228751,-1.036251,1.976840,-2.504326,4.353166,-1.511555,-1.452743,-0.663433,-0.976442,-0.693744,0.198484,-0.407872,-0.506523,-0.590362,4.043677,6.314065,0.126364,-0.194009,-16.236056,4.068819,1.224119,1.543314,-0.128289,1.302668,1.465868,1.603645,-0.031988,0.175951,0.158367,0.120493,-0.004462,7.682568,0.469458,-0.000680,-7.551085,0.606771,0.200480,1.057136,0.555353,4.748190,0.039710,0.263192,0.593023,3.582425,1.947296,0.517452,-0.076818,0.682754,0.357066,0.075757,-0.007521,0.317154,1.510008,0.580695,5.009438,0.728683,-0.267382,2.371758,0.446246,-0.167985,-7.106345,-0.097237,3.584461,4.274035,4.095569,-1.738810,-6.914329,-3.810478,1.208624,1.140845,2.095668,0.575353,0.626909,-2.226223,-2.056425,-1.312785,-1.551202,-2.271757,-0.504885,-0.277969,-0.431348,2.347458,-0.027946,-0.392081,-0.388553,8.689883,4.189324,-0.862448,-5.671942,-1.845137,9.754921,-10.775090,72.349025,6.208780,6.869102,0.123899,0.383385,0.675272,-0.332477,-0.960122,-31.058836,-7.949740,-3.758648,7.108799,11.528299,8.149853,-0.615473,-0.439979,-0.677038,-0.723783,29.196677,-0.859601,-1.499570,-0.576167,-1.667575,-1.829887,-1.398700,-0.515988,41.517160,0.713953,30.545081,-6.188533,-7.091922,-9.414879,-1.904592,-7.658521,-2.284183,-7.772925,21.863106,20.947830,-1.751241,13.477022,-7.682248,-8.168043,-20.637880,10.466483,0.089507,-5.340472,-3.344616,-8.410060,-2.282409,-6.121732,-6.918085,-6.073172,-11.025504,-8.407571,-6.208835,-4.529416,-5.678833,-5.714158,-1.018523,19.611186,-2.653425,-1.897749,-3.690523,0.166875,-0.394813,0.722076,-0.189588,-0.930066,0.943887,-0.845358,-5.028208,-4.240671,-15.165471,-0.622049,-3.294203,1.575702,3.755827,-1.110502,-1.434140,-1.507328,-12.166484,2.660743,2.035036,0.891480,2.444064,-2.451179,-1.473334,0.802695,-0.310561,0.390210,0.371984,-15.530832,1.328315,-6.511445,-1.310474,1.158307,20.504969,0.870710,1.396723,0.227466,-1.831463,-2.830913,-5.143690,-0.271427,-0.426230,-0.240882,-0.115466,0.874429,1.650408,4.967956,1.912887,2.400235,1.008770,2.862430,1.166314,0.933473,2.330710,2.444949,1.830853,1.049244,2.607336,2.804982,3.107458,3.294002,3.170131,13.693583,76.926670,3.845448,23.346861,9.812383,2.391273,10.606641,1.963476,2.967598,1.526888,0.866287,4.209006,18.102486,0.533338,1.445390,0.872831,0.853834,0.273607,1.321337,0.123892,0.412314,0.355130,-4.645920,0.283349,-6.881706,0.901227,-4.195997,0.916571,-0.388821,0.565599,1.117080,0.812389,5.323900,1.317251,0.320280,0.308174,-26.829184,1.149731,1.275011,2.000144,-1.470072,-0.767747,0.202361,-1.587088,1.155752,1.098314,1.257929,-3.200987,0.668693,4.033012,0.999027,-1.208894,1.632769,1.014471,0.723843,2.399647,-2.593154,-9.382237,1.349194,-0.021662,-3.713423,-1.746662,-6.558139,-1.554877,-2.434262,1.989675,0.249551,-2.443816,-3.779906,-2.636414,-1.277373,-4.628381,-0.505515,-3.990376,-11.436412,-2.227947,-2.823871,-6.863975,-1.281835,-3.663759,-0.310102,0.149827,2.020108,2.642968,1.497769,3.041259,2.015148,1.067337,-0.013860,0.981229,0.631989,1.125228,0.752725,-1.872923,0.565742,0.566382,0.054049,0.409526,-0.925388,-0.245978,-0.132565,-0.171097,-3.199698,2.047109,-2.335864,-0.230441,-3.463833,-2.292295,-0.984754,-0.119444,-0.079340,-1.964507,-0.163262,-0.044391,-3.299204,-1.317512,-1.653288,-360.611655,-0.792871,-1.526987,-5.112393,-0.545486,-8.757870,-0.044763,0.033397,-1.166951,-3.586482,-3.397790,-0.226581,-0.680198,-0.470130,-0.421405,-3.563391,-0.720706,0.001545,-2.030093,-3.074116,-0.915965,-2.567866,0.300819,-2.735884,-2.183676,4.409152,0.644427,-0.628248,-3.267413,-3.548809,-4.949955,3.555070,8.891552,3.580243,1.056337,-1.324928,-1.612563,-0.576405,-0.681977,2.571778,1.858078,1.474100,0.776536,3.534101,0.802548,-0.213475,0.434609,-4.311330,-1.056947,0.292802,-0.536683,-9.690235,-3.111939,-0.113073,5.260060,0.512237,1.040290,34.479682,2.148753,-3.126262,-2.802152,-0.047654,-0.012042,1.508002,5.959009,1.083541,1.424925,-1.638421,-3.557558,-1.322984,4.979366,2.018343,1.150012,1.216431,-0.280425,2.333079,1.243301,0.841088,1.886149,1.498563,1.629537,3.290616,1.685732,2.013451,0.862097,1.742377,-25.609594,1.644792,4.482274,-18.463892,1.851310,0.167115,-0.404057,0.565838,4.045443,1.878586,0.753386,-16.788055,0.126791,-10.594349,3.300475,-0.634618,0.747863,7.905016,3.666997,31.245129,3.526583,9.021474,8.262771,10.631880,-3.141672,4.410128,6.165324,12.481022,5.635590,8.770696,8.735834,10.870203,3.874316,21.608977,4.526612,1.156461,1.276455,-0.976077,-0.288614,1.000854,0.298251,0.383862,0.127455,-10.489012,-1.725379,-7.637858,9.150683,2.160111,1.407201,1.326115,1.018763,2.385681,1.744191,1.730315,7.003605,-10.912519,4.530976,3.405832,13.760234,-1.191210,-1.174960,0.549645,0.459820,3.840778,12.674068,-2.126857,-3.227273,0.883224,5.710771,2.435913,-63.068527,3.723472,10.381427,-6.550155,-5.879445,-0.212391,-0.055838,-0.030079,0.349785,0.068710,3.085991,5.712933,5.268697,4.278224,2.301436,0.565240,0.997076,0.590336,0.721163,0.832828,1.161940,0.703974,1.480778,0.505237,1.669236,1.958621,1.691473,0.893302,19.534316,1.782585,1.056738,-3.575074,16.543404,26.596598,24.057324,6.166616,11.768488,2.438942,0.139397,2.026144,3.923045,8.086570,7.847441,5.052775,3.426013,3.642981,2.268567,-0.649373,3.161143,7.047121,2.205177,5.594592,-61.189816,8.415619,8.300800,-2.673700,-2.996654,5.218760,-23.693685,-2.322776,8.623765,4.627958,3.368395,46.500027,5.639402,-8.165272,0.796185,-0.706099,0.135805,0.868030,0.306016,0.789311,7.124334,4.242289,9.727023,0.681696,3.756994,3.622855,1.035487,1.025518,1.451887,1.854145,53.213359,-1.431522,-0.091550,-1.656084,-29.300245,1.570393,-0.978860,-1.027790,0.540321,-0.337222,-0.445398,5.875282,-1.581966,-2.580338,-0.264537,1.197146,-1.569363,-1.206515,-4.797875,-4.215951,8.528007,-6.191259,-2.189876,-2.501495,-0.966387,-1.200414,-1.520622,1.784751,3.031218,2.192351,1.142476,3.948292,1.763238,1.458057,1.396658,0.608675,1.724458,1.444704,-0.337446,0.570233,-0.657234,0.994609,-1.613324,-1.018631,9.949645,0.400291,0.977540,2.793460,9.773625,-2.396520,-2.783999,-2.708673,0.222687,-0.809978,0.368899,0.299932,-0.449218,0.185562,-0.459102,19.015891,-5.459218,-5.169562,-2.773216,-2.557959,-1.678736,-1.842239,-2.521119,-2.590653,-1.349186,-6.084066,13.539631,-2.590764,-6.882887,-4.029900,-1.488305,-4.217717,-0.591442,-4.848400,-2.261591,-1.905966,0.042691,-46.258913,-34.478861,-0.503401,-0.420428,-2.167570,-0.846137,0.870438,-2.407570,0.566669,-4.854715,12.200811,-2.699115,2.800773,7.892013,12.472750,0.180263,1.710783,0.879254,-2.253537,-2.573041,23.346808,6.059341,2.580303,14.766641,5.840801,4.124855,2.460706,1.147568,-1.740196,-0.196835,0.446965,-4.702591,1.964575,-0.052577,0.050285,-0.335195,0.303068,-0.149456,0.085326,-0.495100,1.934900,1.936413,1.653900,0.018581,-0.061852,-0.204984,-1.333097,-1.018476,-0.999683,-1.024398,-2.082589,-1.729892,-1.682701,-1.436921,-0.425914,0.474230,-0.613048,2.100885,-0.575348,-0.652350,0.685484,0.915968,0.304119,33.087667,22.601027,-0.104921,-0.177293,0.234389,0.198040,-0.238190,0.024597,-0.234056,2.822241,0.004142,-0.021054,-1.552198,0.397562,0.077244,-0.810139,0.196844,0.939802,-0.136742,0.592149,-0.255330,0.163302,0.318883,-0.064531,0.062070,0.694546,0.209702,-0.010243,-0.073304,0.410424,0.204043,0.361079,-0.055767,-0.101269,-0.050839,0.051487,0.718138,0.694693,0.435695,-0.256583,1.158518,1.995850,0.439841,-6.203604,-0.985698,-0.155184,0.593911,2.482176,0.946247,-8.436521,2.401151,1.810159,-1.035090,1.092773,0.036518,0.601562,0.147424,-1.833577,-0.126662,-0.374717,0.021811,-1.851743,2.796177,7.877599,0.255243,1.929069,0.112273,1.512485,-0.092995,2.856183,2.717226,-2.437687,29.901422,-2.085927,-19.040682,7.366650,-6.152353,2.929612,2.416426,0.020353,0.695380,-1.096458,-0.048956,-4.537238,-1.349666,-1.191487,-4.125253,-1.868902,-0.829698,0.339131,-0.988083,-0.657337,-1.539595,-0.878505,0.020183,-0.606991,-6.575499,-1.118187,-5.901197,-1.902425,-1.830654,-0.680334,-5.982117,-0.672636,-0.566174,0.880422,-0.227259,16.390507,16.269985,0.259872,-0.607438,-0.343732,-0.055939,-0.167441,-0.216072,-0.726638,-1.074767,-0.762545,0.036361,-1.061878,-0.472379,0.016452,-0.140865,10.090679,-0.235577,-0.524869,0.212008,-0.585822,7.323222,-0.135613,0.180593,-0.011106,-0.042434,-12.922468,-1.085171,-0.292372,-0.325988,-1.179218,-1.970896,-16.414723,0.919156,1.402566,2.696173,-0.709757,1.263208,-4.311061,-1.912170,0.871238,3.954405,-0.151088,-1.171526,-4.635838,-1.823951,-1.739963,-1.850814,-0.681339,-4.348577,6.466663,-1.359048,-2.297508,0.873118,-2.400759,-1.233752,-11.830300,-4.348966,0.058590,-0.093309,-0.269750,-0.034210,2.940893,0.216562,-0.620224,-5.364289,2.643353,-14.314586,0.580299,-7.502483,3.299922,3.749239,0.036450,2.614238,2.437889,-0.351271,-1.562823,-1.413144,-5.498119,-3.459754,0.428530,-0.058354,-0.386101,-0.304795,-0.544952,-1.530170,-0.663988,-0.703933,-0.727071,-1.581068,-0.311638,-1.667302,-1.823642,-1.680038,1.580470,177.705612,-1.861632,6.898606,1.315608,-1.085525,-5.474480,-1.913068,-1.113184,-0.820879,-0.721986,-0.105046,0.573232,-0.567043,-0.447164,-1.654838,-6.803239,-0.794338,-4.504619,-2.908429,-4.093875,-3.466304,-3.426859,-2.315266,-5.298508,-10.366847,-17.253376,-8.906028,-8.385869,-6.196990,-2.296948,-5.304315,-18.097126,-25.213401,1.869964,-2.902289,-1.899073,-1.705180,-1.426860,-2.510971,0.838146,0.526502,-0.782129,0.808493,-0.845322,-12.005751,-18.375311,-9.925110,-1.189432,-1.891818,-5.313697,-1.043915,-1.121079,-1.301175,-2.109128,-2.104007,2.245467,0.933534,-3.669234,0.044000,-3.064914,-3.341542,-2.857548,-0.249489,-0.592423,-0.582685,0.247260,7.506503,1.967544,0.566159,0.832930,-0.418475,-0.390811,-0.564865,0.433205,0.504496,-0.647795,-0.236603,-0.652715,-0.487510,-0.544541,0.332621,0.466587,0.523348};
+        std::vector<float> bias = {-350.736300,1.530207,-9.805541,-1.676745,6.448848,-0.185940,-0.834116,1.642355,-0.557261,0.211599,-1.207916,-1.731354,-0.243328,-0.166474,0.338915,1.356859,-0.370182};
+        return new Discrimination::NNFeedForwardVarDep(nodes,weights,bias);
+      }
+      default:
+      {
+        std::vector<unsigned int> nodes = {segmentationEntries[cSegType][segIdx],1};
+        std::vector<float> weights(segmentationEntries[cSegType][segIdx],.01);
+        std::vector<float> bias={0};
+        return new Discrimination::NNFeedForwardVarDep(nodes, weights, bias);
+      }
+    }
+  } else {
+    std::vector<unsigned int> nodes = {100,1};
+    std::vector<float> weights(100,1);
+    std::vector<float> bias={0};
+    return new Discrimination::NNFeedForwardVarDep(nodes, weights, bias);
+  }
+}
+
+// =============================================================================
+template<bool goodStatus>
+Discrimination::NNFeedForwardVarDep* createEtaDepNN(
+    SegmentationType cSegType, 
+    unsigned segIdx, 
+    float etaMin, float etaMax)
+{
+  Discrimination::NNFeedForwardVarDep* nn = createNN(cSegType, segIdx);
+  nn->setEtaDep(etaMin, etaMax);
+  return nn;
+}
+
+// =============================================================================
+template<bool goodStatus>
+Discrimination::NNFeedForwardVarDep* createEtDepNN(
+    SegmentationType cSegType, 
+    unsigned segIdx,
+    float etMin, float etMax)
+{
+  Discrimination::NNFeedForwardVarDep* nn = createNN(cSegType, segIdx);
+  nn->setEtDep(etMin, etMax);
+  return nn;
+}
+
+// =============================================================================
+template<bool goodStatus>
+Discrimination::NNFeedForwardVarDep* createEtaEtDepNN(SegmentationType cSegType, 
+    unsigned segIdx,
+    float etaMin, float etaMax,
+    float etMin, float etMax)
+{
+  Discrimination::NNFeedForwardVarDep* nn = createNN(cSegType, segIdx);
+  nn->setEtaEtDep(etaMin, etaMax, etMin, etMax);
+  return nn;
+}
+
+// =============================================================================
+template<
+  typename procedure_t, 
+  EtaDependency etaDependency,
+  EtDependency etDependency
+>
+void createThresWrapper(const char* fileName,
+    const std::vector<float> &etaDepBounderies,
+    const std::vector<float> &etDepBounderies,
+    float thresValue)
+{
+  // Typedef to make things easier
+  typedef RingerProcedureWrapper<procedure_t, 
+          etaDependency, 
+          etDependency> wrapper_t;
+
+  typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
+
+  msg << MSG::INFO << "Attempting to create a RingerProcedureWrapper<"
+        << toStr(procedure_t::template procType<procEnum_t>() ) 
+        << ((Ringer::is_same<procedure_t,Discrimination::IThresholdVarDep>::value)?",":"(VarDep),")
+        << toStr(etaDependency) << "," 
+        << toStr(etDependency) << "> with file name: " << fileName << "." << endreq;
+
+  unsigned etaDepProc = etaDepBounderies.size() - 1; 
+  unsigned etDepProc = etDepBounderies.size() - 1; 
+
+  // Loop over variable dependencies
+  for ( unsigned uEtaDep = EtaIndependent; uEtaDep <= EtaDependent; ++uEtaDep ){
+    for ( unsigned uEtDep = EtIndependent; uEtDep <= EtDependent; ++uEtDep ){
+      // The enumerations
+      EtaDependency etaDep = static_cast<EtaDependency>(uEtaDep);
+      EtDependency etDep = static_cast<EtDependency>(uEtDep);
+
+      // Change message level accondingly if we are creating correct wrapper
+      // type
+      MSG::Level lvl(MSG::VERBOSE);
+      if ( etaDep == etaDependency &&
+          etDep == etDependency )
+      {
+        lvl = MSG::INFO;
+      }
+
+      // The collection holder
+      typename wrapper_t::ThresDepProcCollection thresCol( etDepProc, 
+          std::vector<procedure_t*>(etaDepProc, nullptr));
+
+      // Fill collection
+      for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+        // Get et bounderies:
+        float etMin(etDepBounderies[etDepIdx]),
+              etMax(etDepBounderies[etDepIdx+1]);
+        for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+          // Get eta bounderies:
+          float etaMin(etaDepBounderies[etaDepIdx]),
+                etaMax(etaDepBounderies[etaDepIdx+1]);
+
+          // Fill collection:
+          if (etaDep) {
+            if (etDep) {
+              thresCol[etDepIdx][etaDepIdx] = createEtaEtDepThres(
+                  etaMin, 
+                  etaMax, 
+                  etMin, 
+                  etMax,
+                  thresValue);
+            } else {
+              thresCol[etDepIdx][etaDepIdx] = createEtaDepThres(
+                  etaMin, 
+                  etaMax,
+                  thresValue);
+          }
+          } else {
+            if (etDep) {
+              thresCol[etDepIdx][etaDepIdx] = createEtDepThres(
+                  etMin, 
+                  etMax,
+                  thresValue);
+            } else {
+              thresCol[etDepIdx][etaDepIdx] = createThres(thresValue);
+            }
+          }
+        }
+      } // Finished looping and filling collection
+
+      // Attempt to create a wrapper with filled collection:
+      try {
+
+        msg << lvl << "Attempting to create wrapper with (" 
+          << toStr(etaDep) << "," << toStr(etDep) << ") discriminator" 
+          << endreq;
+
+        // Create wrapper:
+        auto wrapper = new wrapper_t(thresCol);
+
+        // Use dummy message stream:
+        wrapper->setMsgStream(&msg);
+        // Print wrapper:
+        wrapper->print(MSG::DEBUG);
+
+        // Delete file if it already exists:
+        IOHelperFcns::deleteFile( fileName );
+
+        // If it succeed, write it into file:
+        //writeWrapperOnFile(*wrapper, fileName, MSG::VERBOSE);
+        IThresWrapper::writeWrapper(wrapper, fileName);
+
+        // Release wrapper memory:
+        //wrapper->releaseMemory();
+        //delete wrapper;
+
+        msg << lvl << "Succeed!" << endreq;
+
+      } catch (const std::runtime_error &e) {
+
+        msg << MSG::VERBOSE << "Couldn't create wrapper. Reason: "
+          << e.what() << endreq;
+
+        // Release collection memory
+        for ( unsigned etDepIdx = 0; etDepIdx < etDepProc; ++etDepIdx){
+          for ( unsigned etaDepIdx = 0; etaDepIdx < etaDepProc; ++etaDepIdx){
+            delete thresCol[etDepIdx][etaDepIdx];
+            thresCol[etDepIdx][etaDepIdx] = nullptr;
+          }
+        }
+      } // Finished creating wrapper and handling possible errors
+
+    }
+  } // Finished looping over eta/et.
+}
+
+
+// =============================================================================
+Discrimination::UniqueThresholdVarDep* createThres(float thresValue)
+{
+  return new Discrimination::UniqueThresholdVarDep(thresValue);
+}
+
+// =============================================================================
+Discrimination::UniqueThresholdVarDep* createEtaDepThres(
+    float etaMin, float etaMax,
+    float thresValue)
+{
+  Discrimination::UniqueThresholdVarDep* thres = createThres(thresValue);
+  thres->setEtaDep(etaMin, etaMax);
+  return thres;
+}
+
+// =============================================================================
+Discrimination::UniqueThresholdVarDep* createEtDepThres(
+    float etMin, float etMax,
+    float thresValue)
+{
+  Discrimination::UniqueThresholdVarDep* thres = createThres(thresValue);
+  thres->setEtDep(etMin, etMax);
+  return thres;
+}
+
+// =============================================================================
+Discrimination::UniqueThresholdVarDep* createEtaEtDepThres(
+    float etaMin, float etaMax,
+    float etMin, float etMax,
+    float thresValue)
+{
+  Discrimination::UniqueThresholdVarDep* thres = createThres(thresValue);
+  thres->setEtaEtDep(etaMin, etaMax, etMin, etMax);
+  return thres;
+}