From eee527e249edc947ea3735258d9f33b9401d5b5e Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Fri, 2 Aug 2019 13:55:41 +0200
Subject: [PATCH 1/9] Follow changes in lhcb/LHCb!2045

* follow renaming of interfaces
* follow constification of interface methods
* disentangle CaloFutureHypoEstimator and FutureNeutralIDTool usage
   note: CaloFutureHypoEstimator is still not thread-safe, but at
   least FutureNeutralIDTool is...
---
 .../src/CaloFutureAlignmentNtp.h              |  12 +-
 .../src/CaloFutureElectronNtp.h               |  14 +-
 .../src/CaloFutureHypoNtp.cpp                 |  44 ++-
 .../CaloFutureMoniDst/src/CaloFutureHypoNtp.h |   6 +-
 .../src/CaloFuturePi0Monitor.cpp              |   6 +-
 .../CaloFutureMoniDst/src/CaloFuturePi0Ntp.h  |  10 +-
 .../src/CaloFuturePhotonIdAlg.cpp             |  27 +-
 .../src/CaloFuturePhotonIdAlg.h               |   3 +-
 .../src/CaloFutureCorrectionBase.cpp          |   6 +-
 ...loFutureSelectNeutralClusterWithTracks.cpp |  40 +-
 ...CaloFutureSelectNeutralClusterWithTracks.h |  23 +-
 .../src/CaloFuture2CaloFuture.cpp             |  99 +++--
 .../src/CaloFuture2CaloFuture.h               |  66 ++--
 .../src/CaloFutureHypo2CaloFuture.cpp         |  34 +-
 .../src/CaloFutureHypo2CaloFuture.h           |  53 +--
 .../src/CaloFutureHypoEstimator.cpp           | 343 +++++++++---------
 .../src/CaloFutureHypoEstimator.h             |  68 ++--
 .../src/CaloFutureRelationsGetter.cpp         |  37 +-
 .../src/CaloFutureRelationsGetter.h           |   6 +-
 .../src/FutureNeutralIDTool.cpp               |  49 +--
 .../CaloFutureTools/src/FutureNeutralIDTool.h |   9 +-
 .../FutureChargedProtoParticleAddBremInfo.cpp |  22 +-
 .../FutureChargedProtoParticleAddEcalInfo.cpp |  14 +-
 ...eChargedProtoParticleCALOFUTUREBaseAlg.cpp |   3 +-
 ...ureChargedProtoParticleCALOFUTUREBaseAlg.h |   2 +-
 Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp | 142 ++++----
 Rec/GlobalReco/src/FutureNeutralProtoPAlg.h   |  18 +-
 27 files changed, 544 insertions(+), 612 deletions(-)

diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
index e195fc9506c..c9edf323ed9 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
@@ -72,12 +72,12 @@ private:
   DeCalorimeter* m_calo = nullptr;
   std::string    m_vertLoc;
 
-  ToolHandle<IFutureCounterLevel>        m_counterStat{"FutureCounterLevel"};
-  ToolHandle<ICaloFutureElectron>        m_caloElectron{"CaloFutureElectron", this};
-  ToolHandle<IEventTimeDecoder>          m_odin{"OdinTimeDecoder/OdinDecoder", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
-  ToolHandle<ITrackExtrapolator>         m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
+  ToolHandle<IFutureCounterLevel>                  m_counterStat{"FutureCounterLevel"};
+  ToolHandle<ICaloFutureElectron>                  m_caloElectron{"CaloFutureElectron", this};
+  ToolHandle<IEventTimeDecoder>                    m_odin{"OdinTimeDecoder/OdinDecoder", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
+  ToolHandle<ITrackExtrapolator>                   m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
 
   // Flags -- init
   Gaudi::Property<bool>             m_usePV3D{this, "UsePV3D", false};
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
index 79b0d416aab..9981a53b637 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
@@ -56,13 +56,13 @@ private:
   DeCalorimeter* m_calo = nullptr;
   std::string    m_vertLoc;
 
-  mutable std::mutex                     m_badtoolmutex;
-  ToolHandle<IFutureCounterLevel>        m_counterStat{"FutureCounterLevel"};
-  ToolHandle<ICaloFutureElectron>        m_caloElectron{"CaloFutureElectron", this};
-  ToolHandle<IEventTimeDecoder>          m_odin{"OdinTimeDecoder/OdinDecoder", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
-  ToolHandle<ITrackExtrapolator>         m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
+  mutable std::mutex                               m_badtoolmutex;
+  ToolHandle<IFutureCounterLevel>                  m_counterStat{"FutureCounterLevel"};
+  ToolHandle<ICaloFutureElectron>                  m_caloElectron{"CaloFutureElectron", this};
+  ToolHandle<IEventTimeDecoder>                    m_odin{"OdinTimeDecoder/OdinDecoder", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
+  ToolHandle<ITrackExtrapolator>                   m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
 
   Gaudi::Property<std::pair<double, double>> m_e{this, "EFilter", {0., 99999999}};
   Gaudi::Property<std::pair<double, double>> m_et{this, "EtFilter", {200., 999999.}};
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
index af9d6e8ce9c..ed44fd74fc1 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
@@ -49,19 +49,16 @@ StatusCode CaloFutureHypoNtp::initialize() {
   }
 
   // Configure tool
-  std::string seed = m_seed ? "true" : "false";
-  std::string line = m_extrapol ? "true" : "false";
-  std::string neig = m_neig ? "true" : "false";
-  m_estimator->hypo2CaloFuture()->_setProperty( "Seed", seed ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "PhotonLine", line ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "AddNeighbors", neig ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
 
   // Configure input locations
   using namespace LHCb::CaloHypoLocation;
   // get the user-override input
   auto                     loc = inputLocation<2>(); // <-- Careful with the index, 'Location' is 3rd.
   std::vector<std::string> m_locs{};
-  if ( loc != "" ) m_locs.push_back( loc );
+  if ( !loc.empty() ) m_locs.push_back( loc );
   // get the respective input from Hypos
   for ( const auto h : m_hypos ) {
     if ( h == "Photons" )
@@ -86,7 +83,7 @@ StatusCode CaloFutureHypoNtp::initialize() {
 void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos& hypos, const Tracks& tracks,
                                     const Vertices& verts ) const {
 
-  using namespace CaloFutureDataType;
+  using namespace Calo::Future::Enum;
 
   // declare tuple
   Tuple ntp = ( !m_tupling ) ? Tuple{nullptr} : nTuple( 500, "HypoNtp", CLID_ColumnWiseTuple );
@@ -108,15 +105,15 @@ void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos&
     std::string hypothesis = type.str();
 
     // filtering hypo
-    if ( !inRange( m_et, fixup( m_estimator )->data( hypo, HypoEt, 0. ) ) ) continue;
-    if ( !inRange( m_e, fixup( m_estimator )->data( hypo, HypoE, 0. ) ) ) continue;
-    if ( !inRange( m_spdM, fixup( m_estimator )->data( hypo, HypoSpdM, 0. ) ) ) continue;
-    if ( !inRange( m_prsE, fixup( m_estimator )->data( hypo, HypoPrsE, 0. ) ) ) continue;
+    if ( !inRange( m_et, fixup( m_estimator )->data( *hypo, DataType::HypoEt ).value_or( 0. ) ) ) continue;
+    if ( !inRange( m_e, fixup( m_estimator )->data( *hypo, DataType::HypoE ).value_or( 0. ) ) ) continue;
+    if ( !inRange( m_spdM, fixup( m_estimator )->data( *hypo, DataType::HypoSpdM ).value_or( 0. ) ) ) continue;
+    if ( !inRange( m_prsE, fixup( m_estimator )->data( *hypo, DataType::HypoPrsE ).value_or( 0. ) ) ) continue;
 
     // MC-associated filtering
     if ( m_checker ) {
       const auto mcp = fixup( m_2MC )->from( hypo )->bestMC();
-      if ( mcp == nullptr ) continue;
+      if ( !mcp ) continue;
       if ( m_mcID >= 0 && (int)mcp->particleID().abspid() != m_mcID ) continue;
     }
 
@@ -128,11 +125,12 @@ void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos&
     }
 
     // DataTypes statistics
-    for ( int i = 0; i < CaloFutureDataType::Last; ++i ) {
-      const auto val = fixup( m_estimator )->data( hypo, (DataType)i, 0. );
-      if ( m_stat && m_counterStat->isQuiet() ) counter( Name[i] + " for " + hypothesis ) += val;
-      if ( m_tupling ) ok &= ntp->column( Name[i], val );
-      if ( m_print ) info() << "   --> " << Name[i] << " : " << val << endmsg;
+    for ( int j = 0; j < count<DataType>(); ++j ) {
+      auto       i   = DataType{j};
+      const auto val = fixup( m_estimator )->data( *hypo, i ).value_or( 0. );
+      if ( m_stat && m_counterStat->isQuiet() ) counter( std::string{toString( i )} + " for " + hypothesis ) += val;
+      if ( m_tupling ) ok &= ntp->column( toString( i ), val );
+      if ( m_print ) info() << "   --> " << toString( i ) << " : " << val << endmsg;
     }
 
     // Tupling
@@ -142,15 +140,15 @@ void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos&
       ok &= ntp->column( "hypothesis", hypo->hypothesis() );
 
       // kinematics
-      const auto cluster = fixup( m_estimator )->toCluster( CaloFutureClusterType::SplitOrMain );
+      const auto cluster = fixup( m_estimator )->toCluster( ClusterType::SplitOrMain );
       ok &= ntp->column( "ClusterR", position3d( cluster ) );
       ok &= ntp->column( "HypoR", position3d( hypo ) );
       ok &= ntp->column( "HypoP", momentum( hypo ) );
 
       // matched tracks
-      for ( int match = 0; match < CaloFutureMatchType::Last; ++match ) {
-        const auto track = fixup( m_estimator )->toTrack( (CaloFutureMatchType::MatchType)match );
-        ok &= ntp->column( CaloFutureMatchType::Name[match] + "TrackP", momentum( track ) );
+      for ( auto match : {MatchType::ClusterMatch, MatchType::ElectronMatch, MatchType::BremMatch} ) {
+        const auto track = fixup( m_estimator )->toTrack( match );
+        ok &= ntp->column( std::string{toString( match )} + "TrackP", momentum( track ) );
       }
 
       // odin info
@@ -167,7 +165,7 @@ void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos&
         double     weight  = -999;
         double     quality = -999;
         const auto mcp     = fixup( m_2MC )->from( hypo )->bestMC();
-        if ( mcp != nullptr ) {
+        if ( mcp ) {
           id      = mcp->particleID().pid();
           weight  = fixup( m_2MC )->from( hypo )->weight( mcp );
           quality = fixup( m_2MC )->from( hypo )->quality( mcp );
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h
index 36a8b3ef88c..454b2f897b8 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h
@@ -42,9 +42,9 @@ public:
   void       operator()( const ODIN&, const L0&, const Hypos&, const Tracks&, const Vertices& ) const override;
 
 private:
-  ToolHandle<ICaloFuture2MCTool>       m_2MC         = {"CaloFuture2MCTool", this};
-  ToolHandle<IFutureCounterLevel>      m_counterStat = {"FutureCounterLevel"};
-  ToolHandle<ICaloFutureHypoEstimator> m_estimator   = {"CaloFutureHypoEstimator", this};
+  ToolHandle<ICaloFuture2MCTool>                       m_2MC         = {"CaloFuture2MCTool", this};
+  ToolHandle<IFutureCounterLevel>                      m_counterStat = {"FutureCounterLevel"};
+  ToolHandle<Calo::Future::Interfaces::IHypoEstimator> m_estimator   = {"CaloFutureHypoEstimator", this};
 
   Gaudi::Property<bool> m_extrapol{this, "Extrapolation", true};
   Gaudi::Property<bool> m_seed{this, "AddSeed", false};
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp
index 1c8dd58929d..e7d15edff98 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp
@@ -55,9 +55,9 @@ public:
   CaloFuturePi0Monitor( const std::string& name, ISvcLocator* pSvcLocator );
 
 private:
-  DeCalorimeter*                         m_calo = nullptr;
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
+  DeCalorimeter*                                   m_calo = nullptr;
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
 
   bool valid_photon( const LHCb::CaloHypo* g ) const;
 
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h
index a8da2767f6a..d2ee196b4b3 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h
@@ -44,11 +44,11 @@ private:
                 const Gaudi::LorentzVector, const LHCb::CaloCellID, int nVert ) const;
 
   // Tools
-  DeCalorimeter*                         m_calo = nullptr;
-  ToolHandle<IFutureCounterLevel>        m_counterStat{"FutureCounterLevel"};
-  ToolHandle<IEventTimeDecoder>          m_odin{"OdinTimeDecoder/OdinDecoder", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
-  ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
+  DeCalorimeter*                                   m_calo = nullptr;
+  ToolHandle<IFutureCounterLevel>                  m_counterStat{"FutureCounterLevel"};
+  ToolHandle<IEventTimeDecoder>                    m_odin{"OdinTimeDecoder/OdinDecoder", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
 
   Gaudi::Property<std::pair<double, double>> m_ppt{this, "PhotonPt", {250., 15000.}};
 
diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp
index 8d8ee06ac4f..02f31d30e77 100644
--- a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp
+++ b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp
@@ -85,12 +85,9 @@ StatusCode CaloFuturePhotonIdAlg::initialize() {
 
   // Warning : the algorithm settings overwrite the caloHypo2CaloFuture default
   // settings
-  std::string seed = m_seed ? "true" : "false";
-  std::string line = m_extrapol ? "true" : "false";
-  std::string neig = m_neig ? "true" : "false";
-  m_estimator->hypo2CaloFuture()->_setProperty( "Seed", seed ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "PhotonLine", line ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "AddNeighbors", neig ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
   m_estimator->_setProperty( "SkipNeutralID", "true" ).ignore(); // avoid loop
 
   return sc;
@@ -162,7 +159,7 @@ double CaloFuturePhotonIdAlg::likelihood( const LHCb::CaloHypo* hypo ) const {
 
   // get chi2
   chi2 = -999.;
-  if ( m_tracking ) chi2 = m_estimator->data( hypo, CaloFutureDataType::ClusterMatch, +999. );
+  if ( m_tracking ) chi2 = m_estimator->data( *hypo, Calo::Future::Enum::DataType::ClusterMatch ).value_or( +999. );
   // evaluate
   return evalLikelihood( energy, et, eSeed, nSpd, ePrs, chi2, area );
 }
@@ -171,13 +168,15 @@ double CaloFuturePhotonIdAlg::likelihood( const LHCb::CaloHypo* hypo ) const {
 
 StatusCode CaloFuturePhotonIdAlg::evalParam( const LHCb::CaloHypo* hypo, double& energy, double& et, double& eSeed,
                                              int& nSpd, double& ePrs, unsigned int& area ) const {
-  using namespace CaloFutureDataType;
-  energy = m_estimator->data( hypo, HypoE );
-  et     = m_estimator->data( hypo, HypoEt );
-  eSeed  = m_estimator->data( hypo, E1Hypo );
-  nSpd   = (int)m_estimator->data( hypo, ToSpdM );
-  ePrs   = m_estimator->data( hypo, ToPrsE );
-  area   = LHCb::CaloCellID( (LHCb::CaloCellID::ContentType)m_estimator->data( hypo, CellID ) ).area();
+  using namespace Calo::Future::Enum;
+  energy = m_estimator->data( *hypo, DataType::HypoE ).value_or( Default );
+  et     = m_estimator->data( *hypo, DataType::HypoEt ).value_or( Default );
+  eSeed  = m_estimator->data( *hypo, DataType::E1Hypo ).value_or( Default );
+  nSpd   = (int)m_estimator->data( *hypo, DataType::ToSpdM ).value_or( Default );
+  ePrs   = m_estimator->data( *hypo, DataType::ToPrsE ).value_or( Default );
+  area   = LHCb::CaloCellID(
+             (LHCb::CaloCellID::ContentType)m_estimator->data( *hypo, DataType::CellID ).value_or( Default ) )
+             .area();
   if ( !m_estimator->status() ) return StatusCode::FAILURE;
   return StatusCode::SUCCESS;
 }
diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h
index 2fb90028629..ccdd3e94d81 100644
--- a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h
+++ b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h
@@ -71,7 +71,8 @@ private:
 private:
   ToolHandle<IFutureCounterLevel> m_counterStat{"FutureCounterLevel"};
 
-  mutable ToolHandle<ICaloFutureHypoEstimator> m_estimator{"CaloFutureHypoEstimator/CaloFutureHypoEstimator", this};
+  mutable ToolHandle<Calo::Future::Interfaces::IHypoEstimator> m_estimator{
+      "CaloFutureHypoEstimator/CaloFutureHypoEstimator", this};
 
   bool         m_extrapol   = true;
   bool         m_seed       = false;
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index 18e64dfa9cd..e4378c83ac1 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -331,9 +331,9 @@ double CaloFutureCorrectionBase::incidence( const LHCb::CaloHypo* hypo, bool str
   double                   incidence = 0;
   if ( LHCb::CaloHypo::Hypothesis::EmCharged == hypo->hypothesis() && !straight ) {
     // for electron hypothesis : get the matching track
-    if ( exist<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc ) ) {
-      auto*      ctable = m_tables->getClusTrTable( m_cmLoc );
-      const auto range  = ctable->relations( cluster );
+    auto* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
+    if ( ctable ) {
+      const auto range = ctable->relations( cluster );
       if ( !range.empty() ) {
         const LHCb::Track* ctrack = range.front();
         // temporary protoParticle
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp
index f5790b7a733..819c51302f2 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp
@@ -27,40 +27,6 @@
 
 DECLARE_COMPONENT( CaloFutureSelectNeutralClusterWithTracks )
 
-// ============================================================================
-/** Standard constructor
- *  @see  GaudiTool
- *  @see   AlgTool
- *  @see  IAlgTool
- *  @param type tool type (?)
- *  @param name name of the concrete instance
- *  @param parent pointer to the parent
- */
-// ============================================================================
-CaloFutureSelectNeutralClusterWithTracks::CaloFutureSelectNeutralClusterWithTracks( const std::string& type,
-                                                                                    const std::string& name,
-                                                                                    const IInterface*  parent )
-    : GaudiTool( type, name, parent ) {
-  declareInterface<ICaloFutureClusterSelector>( this );
-  m_tableLocation = LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch" );
-}
-
-// ============================================================================
-/** standard initialization method
- *  @see GaudiTool
- *  @see  AlgTool
- *  @see IAlgTool
- *  @return status code
- */
-// ============================================================================
-StatusCode CaloFutureSelectNeutralClusterWithTracks::initialize() {
-  // initialize the base class
-  StatusCode sc = GaudiTool::initialize();
-  if ( sc.isFailure() ) { return Error( "Could not initialize the base class GaudiTool!", sc ); }
-  m_tables = tool<ICaloFutureRelationsGetter>( "CaloFutureRelationsGetter", "CaloFutureRelationsGetter", this );
-  return StatusCode::SUCCESS;
-}
-
 // ============================================================================
 /** @brief "select"  method
  *
@@ -92,14 +58,14 @@ bool CaloFutureSelectNeutralClusterWithTracks::select( const LHCb::CaloCluster*
 // ============================================================================
 bool CaloFutureSelectNeutralClusterWithTracks::operator()( const LHCb::CaloCluster* cluster ) const {
   // check the cluster
-  if ( 0 == cluster ) {
+  if ( !cluster ) {
     Warning( "CaloCluster* points to NULL!" ).ignore();
     return false;
   }
 
   // locate the table
-  LHCb::CaloFuture2Track::IClusTrTable* table = m_tables->getClusTrTable( m_tableLocation );
-  if ( NULL == table ) return true;
+  LHCb::CaloFuture2Track::IClusTrTable* table = getIfExists<LHCb::CaloFuture2Track::IClusTrTable*>( m_tableLocation );
+  if ( !table ) return true;
 
   // get all relations with WEIGHT = 'chi2' under the threshold value
   const LHCb::CaloFuture2Track::IClusTrTable::Range range = table->relations( cluster, m_chi2cut, false );
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h
index 340f7a01cab..15e7908431a 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h
@@ -38,7 +38,7 @@
  *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
  *  @date   26/04/2002
  */
-class CaloFutureSelectNeutralClusterWithTracks : public virtual ICaloFutureClusterSelector, public GaudiTool {
+class CaloFutureSelectNeutralClusterWithTracks : public extends<GaudiTool, ICaloFutureClusterSelector> {
 public:
   /** @brief "select"  method
    *
@@ -64,29 +64,14 @@ public:
    */
   bool operator()( const LHCb::CaloCluster* cluster ) const override;
 
-  /** standard initialization method
-   *  @see GaudiTool
-   *  @see  AlgTool
-   *  @see IAlgTool
-   *  @return status code
-   */
-  StatusCode initialize() override;
-
   /** Standard constructor
-   *  @see  GaudiTool
-   *  @see   AlgTool
-   *  @see  IAlgTool
-   *  @param type tool type (?)
-   *  @param name name of the concrete instance
-   *  @param parent pointer to the parent
    */
-  CaloFutureSelectNeutralClusterWithTracks( const std::string& type, const std::string& name,
-                                            const IInterface* parent );
+  using extends::extends;
 
 private:
-  Gaudi::Property<std::string>           m_tableLocation{this, "Table", LHCb::CaloFutureIdLocation::ClusterMatch};
+  Gaudi::Property<std::string>           m_tableLocation{this, "Table",
+                                               LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch" )};
   Gaudi::Property<float>                 m_chi2cut{this, "MinChi2", -100};
-  ICaloFutureRelationsGetter*            m_tables = nullptr;
   mutable Gaudi::Accumulators::Counter<> m_counter{this, "selected clusters"};
 };
 #endif // CALOFUTURERECO_CALOFUTURESELECTNEUTRALCLUSTERWITHTRACKS_H
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
index 28c0b2f1ae9..f50f9c9749b 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
@@ -32,14 +32,6 @@
 DECLARE_COMPONENT( CaloFuture2CaloFuture )
 // ============================================================================
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-CaloFuture2CaloFuture::CaloFuture2CaloFuture( const std::string& type, const std::string& name,
-                                              const IInterface* parent )
-    : base_class( type, name, parent ) {
-  declareInterface<ICaloFuture2CaloFuture>( this );
-}
 //=============================================================================
 StatusCode CaloFuture2CaloFuture::initialize() {
   StatusCode sc = base_class::initialize();
@@ -57,18 +49,18 @@ StatusCode CaloFuture2CaloFuture::initialize() {
   int mask      = m_getter->detectorsMask();
   m_det["Ecal"] = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
   m_det["Hcal"] = getDet<DeCalorimeter>( DeCalorimeterLocation::Hcal );
-  m_det["Prs"]  = ( ( mask & 2 ) == 0 ) ? NULL : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Prs );
-  m_det["Spd"]  = ( ( mask & 1 ) == 0 ) ? NULL : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Spd );
+  m_det["Prs"]  = ( ( mask & 2 ) == 0 ) ? nullptr : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Prs );
+  m_det["Spd"]  = ( ( mask & 1 ) == 0 ) ? nullptr : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Spd );
   // CellSize reference (outer section)  Warning : factor 2 for Hcal
-  m_refSize["Hcal"] = ( *( m_det["Hcal"]->cellParams().begin() ) ).size() / 2.;
-  m_refSize["Ecal"] = ( *( m_det["Ecal"]->cellParams().begin() ) ).size();
-  if ( NULL != m_det["Prs"] ) m_refSize["Prs"] = ( *( m_det["Prs"]->cellParams().begin() ) ).size();
-  if ( NULL != m_det["Spd"] ) m_refSize["Spd"] = ( *( m_det["Spd"]->cellParams().begin() ) ).size();
+  m_refSize["Hcal"] = m_det["Hcal"]->cellParams().front().size() / 2.;
+  m_refSize["Ecal"] = m_det["Ecal"]->cellParams().front().size();
+  if ( m_det["Prs"] ) m_refSize["Prs"] = m_det["Prs"]->cellParams().front().size();
+  if ( m_det["Spd"] ) m_refSize["Spd"] = m_det["Spd"]->cellParams().front().size();
   // CaloPlanes
   m_plane["Hcal"] = m_det["Hcal"]->plane( CaloPlane::ShowerMax );
   m_plane["Ecal"] = m_det["Ecal"]->plane( CaloPlane::ShowerMax );
-  if ( NULL != m_det["Prs"] ) m_plane["Prs"] = m_det["Prs"]->plane( CaloPlane::ShowerMax );
-  if ( NULL != m_det["Spd"] ) m_plane["Spd"] = m_det["Spd"]->plane( CaloPlane::ShowerMax );
+  if ( m_det["Prs"] ) m_plane["Prs"] = m_det["Prs"]->plane( CaloPlane::ShowerMax );
+  if ( m_det["Spd"] ) m_plane["Spd"] = m_det["Spd"]->plane( CaloPlane::ShowerMax );
 
   reset();
 
@@ -79,53 +71,56 @@ StatusCode CaloFuture2CaloFuture::initialize() {
   //
 
   if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) {
-    if ( NULL == m_det["Prs"] && ( m_fromCaloFuture == "Prs" || m_toCaloFuture == "Prs" ) )
+    if ( !m_det["Prs"] && ( m_fromCaloFuture == "Prs" || m_toCaloFuture == "Prs" ) )
       debug() << "Try to access non-existing Prs DetectorElement" << endmsg;
-    if ( NULL == m_det["Spd"] && ( m_fromCaloFuture == "Spd" || m_toCaloFuture == "Spd" ) )
+    if ( !m_det["Spd"] && ( m_fromCaloFuture == "Spd" || m_toCaloFuture == "Spd" ) )
       debug() << "Try to access non-existing Spd DetectorElement" << endmsg;
   }
   return sc;
 }
 
-void CaloFuture2CaloFuture::reset() {
+void CaloFuture2CaloFuture::reset() const {
   m_digits.clear();
   m_cells.clear();
   m_energy = 0;
   m_count  = 0;
 }
 
-void CaloFuture2CaloFuture::setCalos( const std::string& fromCaloFuture, const std::string& toCaloFuture ) {
+void CaloFuture2CaloFuture::setCalos( const std::string& fromCaloFuture, const std::string& toCaloFuture ) const {
+
+  auto* self = const_cast<CaloFuture2CaloFuture*>( this );
 
   m_ok = true;
-  if ( NULL == m_det["Prs"] && ( fromCaloFuture == "Prs" || toCaloFuture == "Prs" ) ) {
+  if ( !self->m_det["Prs"] && ( fromCaloFuture == "Prs" || toCaloFuture == "Prs" ) ) {
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Try to access non-existing Prs DetectorElement" << endmsg;
     m_ok = false;
     return;
   }
 
-  if ( NULL == m_det["Spd"] && ( fromCaloFuture == "Spd" || toCaloFuture == "Spd" ) ) {
+  if ( !self->m_det["Spd"] && ( fromCaloFuture == "Spd" || toCaloFuture == "Spd" ) ) {
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Try to access non-existing Spd DetectorElement" << endmsg;
     m_ok = false;
     return;
   }
 
-  m_fromCaloFuture = fromCaloFuture;
-  m_toCaloFuture   = toCaloFuture;
-  m_fromDet        = m_det[m_fromCaloFuture];
-  m_fromSize       = m_refSize[m_fromCaloFuture];
-  m_toDet          = m_det[m_toCaloFuture];
-  m_toPlane        = m_plane[m_toCaloFuture];
-  m_toSize         = m_refSize[m_toCaloFuture];
-  m_toLoc          = m_loc[m_toCaloFuture];
+  self->m_fromCaloFuture = fromCaloFuture;
+  self->m_toCaloFuture   = toCaloFuture;
+  self->m_fromDet        = self->m_det[m_fromCaloFuture];
+  self->m_fromSize       = self->m_refSize[m_fromCaloFuture];
+  self->m_toDet          = self->m_det[m_toCaloFuture];
+  self->m_toPlane        = self->m_plane[m_toCaloFuture];
+  self->m_toSize         = self->m_refSize[m_toCaloFuture];
+  self->m_toLoc          = self->m_loc[m_toCaloFuture];
 }
 //=======================================================================================================
 const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::cellIDs( const LHCb::CaloCluster& fromCluster,
-                                                                     const std::string&       toCaloFuture ) {
+                                                                     const std::string&       toCaloFuture ) const {
 
   reset();
   LHCb::CaloCellID seedID         = fromCluster.seed();
   std::string      fromCaloFuture = CaloCellCode::CaloNameFromNum( seedID.calo() );
-  if ( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture ) setCalos( fromCaloFuture, toCaloFuture );
+  if ( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture )
+    const_cast<CaloFuture2CaloFuture*>( this )->setCalos( fromCaloFuture, toCaloFuture );
   if ( !m_ok ) return m_cells;
 
   for ( const auto& ent : fromCluster.entries() ) {
@@ -136,7 +131,7 @@ const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::cellIDs( const LHCb:
 }
 //=======================================================================================================
 const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::addCell( const LHCb::CaloCellID& id,
-                                                                     const std::string&      toCaloFuture ) {
+                                                                     const std::string&      toCaloFuture ) const {
 
   if ( !m_ok ) return m_cells;
   // consistency check
@@ -151,13 +146,13 @@ const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::addCell( const LHCb:
   m_cells.push_back( id );
 
   // added by VB.
-  if ( 0 == m_digs ) {
+  if ( !m_digs ) {
     Error( "Digits* points to NULL" );
     return m_cells;
   }
 
   LHCb::CaloDigit* digit = m_digs->object( id );
-  if ( NULL != digit ) {
+  if ( digit ) {
     m_digits.push_back( digit );
     m_energy += digit->e();
     m_count++;
@@ -166,8 +161,8 @@ const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::addCell( const LHCb:
 }
 
 //=======================================================================================================
-const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::cellIDs( const LHCb::CaloCellID& fromId,
-                                                                     const std::string& toCaloFuture, bool init ) {
+const std::vector<LHCb::CaloCellID>&
+CaloFuture2CaloFuture::cellIDs( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture, bool init ) const {
 
   if ( init ) reset();
   std::string fromCaloFuture = CaloCellCode::CaloNameFromNum( fromId.calo() );
@@ -234,51 +229,51 @@ const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::cellIDs( const LHCb:
 
 // Digits
 const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCellID& fromId,
-                                                                    const std::string&      toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+                                                                    const std::string&      toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_digits;
 }
 
 const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCluster& fromCluster,
-                                                                    const std::string&       toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+                                                                    const std::string&       toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_digits;
 }
 
 // Energy
-double CaloFuture2CaloFuture::energy( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+double CaloFuture2CaloFuture::energy( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_energy;
 }
 
-int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_count;
 }
 
-double CaloFuture2CaloFuture::energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+double CaloFuture2CaloFuture::energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_energy;
 }
 
-int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) {
-  m_digs = m_getter->digits( m_toLoc );
+int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const {
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_count;
 }
 
 // ============================================================================
 // Additional method : isLocalMax
-bool CaloFuture2CaloFuture::isLocalMax( const LHCb::CaloDigit& digit ) {
+bool CaloFuture2CaloFuture::isLocalMax( const LHCb::CaloDigit& digit ) const {
   const LHCb::CaloCellID& id     = digit.cellID();
   std::string             calo   = CaloCellCode::CaloNameFromNum( id.calo() );
-  DeCalorimeter*          det    = m_det[calo];
-  const LHCb::CaloDigits* digits = m_getter->digits( m_loc[calo] );
+  DeCalorimeter*          det    = const_cast<CaloFuture2CaloFuture*>( this )->m_det[calo];
+  const LHCb::CaloDigits* digits = m_getter->digits( const_cast<CaloFuture2CaloFuture*>( this )->m_loc[calo] );
   //
   return LHCb::CaloFutureDataFunctor::isLocalMax( &digit, det, digits );
 }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
index 4185fe2858e..b1406c901ed 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
@@ -24,62 +24,62 @@
  *  @date   2007-05-29
  */
 
-class CaloFuture2CaloFuture : public extends<GaudiTool, ICaloFuture2CaloFuture> {
+class CaloFuture2CaloFuture : public extends<GaudiTool, Calo::Future::Interfaces::ICalo2Calo> {
 public:
   /// Standard constructor
-  CaloFuture2CaloFuture( const std::string& type, const std::string& name, const IInterface* parent );
+  using extends::extends;
 
   StatusCode initialize() override;
   // setting
-  void setCalos( const std::string& fromCaloFuture, const std::string& toCaloFuture ) override;
+  void setCalos( const std::string& fromCaloFuture, const std::string& toCaloFuture ) const override;
   // CaloCellIDs
   const std::vector<LHCb::CaloCellID>& cellIDs( const LHCb::CaloCluster& fromCluster,
-                                                const std::string&       toCaloFuture ) override;
+                                                const std::string&       toCaloFuture ) const override;
   const std::vector<LHCb::CaloCellID>& cellIDs( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture,
-                                                bool init = true ) override;
-  const std::vector<LHCb::CaloCellID>& cellIDs() override { return m_cells; };
+                                                bool init = true ) const override;
+  const std::vector<LHCb::CaloCellID>& cellIDs() const override { return m_cells; };
   // Digits
   const std::vector<LHCb::CaloDigit*>& digits( const LHCb::CaloCellID& fromId,
-                                               const std::string&      toCaloFuture ) override;
+                                               const std::string&      toCaloFuture ) const override;
   const std::vector<LHCb::CaloDigit*>& digits( const LHCb::CaloCluster& fromCluster,
-                                               const std::string&       toCaloFuture ) override;
-  const std::vector<LHCb::CaloDigit*>& digits() override { return m_digits; };
+                                               const std::string&       toCaloFuture ) const override;
+  const std::vector<LHCb::CaloDigit*>& digits() const override { return m_digits; };
   // Energy
-  double energy( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) override;
-  double energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) override;
-  double energy() override { return m_energy; };
+  double energy( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const override;
+  double energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const override;
+  double energy() const override { return m_energy; };
   // multiplicity
-  int multiplicity( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) override;
-  int multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) override;
-  int multiplicity() override { return m_count; };
+  int multiplicity( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const override;
+  int multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const override;
+  int multiplicity() const override { return m_count; };
   // Additional
-  bool isLocalMax( const LHCb::CaloDigit& digit ) override;
+  bool isLocalMax( const LHCb::CaloDigit& digit ) const override;
 
 protected:
   //
-  void                                 reset();
-  const std::vector<LHCb::CaloCellID>& addCell( const LHCb::CaloCellID& id, const std::string& toCaloFuture );
+  void                                 reset() const;
+  const std::vector<LHCb::CaloCellID>& addCell( const LHCb::CaloCellID& id, const std::string& toCaloFuture ) const;
   // CaloFuture Maps
   std::map<std::string, DeCalorimeter*> m_det;
   std::map<std::string, std::string>    m_loc;
   std::map<std::string, double>         m_refSize;
   std::map<std::string, Gaudi::Plane3D> m_plane;
   //
-  Gaudi::Property<std::string>  m_fromCaloFuture{this, "FromCaloFuture", "??"};
-  Gaudi::Property<std::string>  m_toCaloFuture{this, "ToCaloFuture", "??"};
-  std::vector<LHCb::CaloCellID> m_cells;
-  std::vector<LHCb::CaloDigit*> m_digits;
-  double                        m_energy   = 0.;
-  int                           m_count    = 0;
-  DeCalorimeter*                m_fromDet  = nullptr;
-  DeCalorimeter*                m_toDet    = nullptr;
-  double                        m_fromSize = 0.;
-  double                        m_toSize   = 0.;
-  std::string                   m_toLoc;
-  Gaudi::Plane3D                m_toPlane;
-  LHCb::CaloDigits*             m_digs   = nullptr;
-  ICaloFutureGetterTool*        m_getter = nullptr;
-  bool                          m_ok     = true;
+  Gaudi::Property<std::string>          m_fromCaloFuture{this, "FromCaloFuture", "??"};
+  Gaudi::Property<std::string>          m_toCaloFuture{this, "ToCaloFuture", "??"};
+  mutable std::vector<LHCb::CaloCellID> m_cells;
+  mutable std::vector<LHCb::CaloDigit*> m_digits;
+  mutable double                        m_energy   = 0.;
+  mutable int                           m_count    = 0;
+  DeCalorimeter*                        m_fromDet  = nullptr;
+  DeCalorimeter*                        m_toDet    = nullptr;
+  double                                m_fromSize = 0.;
+  double                                m_toSize   = 0.;
+  std::string                           m_toLoc;
+  Gaudi::Plane3D                        m_toPlane;
+  LHCb::CaloDigits*                     m_digs   = nullptr;
+  ICaloFutureGetterTool*                m_getter = nullptr;
+  mutable bool                          m_ok     = true;
 
 private:
   Gaudi::Property<bool>        m_geo{this, "IdealGeometry", true};
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
index b1886c9aff0..57ae77796aa 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
@@ -41,7 +41,7 @@ StatusCode CaloFutureHypo2CaloFuture::initialize() {
 
 //=============================================================================
 const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const LHCb::CaloHypo& fromHypo,
-                                                                         const std::string&    toCaloFuture ) {
+                                                                         const std::string&    toCaloFuture ) const {
 
   if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
     debug() << "Matching CaloHypo to " << toCaloFuture << " hypo energy = " << fromHypo.e() << endmsg;
@@ -49,7 +49,7 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
   // get the cluster
   const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &fromHypo );
 
-  if ( cluster == 0 ) {
+  if ( !cluster ) {
     Error( "No valid cluster!" ).ignore();
     return m_cells;
   }
@@ -65,7 +65,7 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
 
   m_point  = Gaudi::XYZPoint();
   m_lineID = LHCb::CaloCellID();
-  if ( m_line && fromHypo.position() != NULL ) {
+  if ( m_line && fromHypo.position() != nullptr ) {
     const Gaudi::XYZPoint  ref( fromHypo.position()->x(), fromHypo.position()->y(), fromHypo.position()->z() );
     const Gaudi::XYZVector vec   = ( ref - Gaudi::XYZPoint( 0, 0, 0 ) );
     const Gaudi::Plane3D   plane = m_toPlane;
@@ -79,7 +79,7 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
 }
 
 const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const LHCb::CaloCluster& fromCluster,
-                                                                         const std::string&       toCaloFuture ) {
+                                                                         const std::string&       toCaloFuture ) const {
   if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << " toCaloFuture " << toCaloFuture << endmsg;
   reset();
   LHCb::CaloCellID seedID         = fromCluster.seed();
@@ -92,18 +92,18 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
   m_neighbour.setDet( m_fromDet );
 
   // get data
-  m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFutureHypo2CaloFuture*>( this )->m_digs =
+      const_cast<CaloFutureHypo2CaloFuture*>( this )->m_getter->digits( m_toLoc );
 
   // matching cluster
   const LHCb::CaloCluster::Entries& entries = fromCluster.entries();
-  for ( LHCb::CaloCluster::Entries::const_iterator ent = entries.begin(); ent != entries.end(); ++ent ) {
-    LHCb::CaloClusterEntry entry  = *ent;
-    LHCb::CaloCellID       cellID = entry.digit()->cellID();
+  for ( const LHCb::CaloClusterEntry& entry : entries ) {
+    LHCb::CaloCellID cellID = entry.digit()->cellID();
     if ( !( m_seed && ( LHCb::CaloDigitStatus::SeedCell & entry.status() ) != 0 ) &&
          !( m_seed && m_neighb && m_neighbour( seedID, cellID ) != 0. ) && !( ( m_status & entry.status() ) != 0 ) &&
          !( m_whole ) )
       continue;
-    SmartRef<LHCb::CaloDigit> digit = ( *ent ).digit();
+    SmartRef<LHCb::CaloDigit> digit = entry.digit();
     CaloFuture2CaloFuture::cellIDs( digit->cellID(), toCaloFuture, false );
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
       debug() << toCaloFuture << ":  digit is selected in front of the cluster : " << cellID << "/" << seedID << " "
@@ -127,7 +127,7 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
                 << m_digits.size() << endmsg;
       if ( m_neighb ) {
         const std::vector<LHCb::CaloCellID>& neighbors = m_toDet->neighborCells( m_lineID );
-        for ( std::vector<LHCb::CaloCellID>::const_iterator n = neighbors.begin(); n != neighbors.end(); n++ ) {
+        for ( auto n = neighbors.begin(); n != neighbors.end(); n++ ) {
           double                halfCell   = m_toDet->cellSize( *n ) * 0.5;
           const Gaudi::XYZPoint cellCenter = m_toDet->cellCenter( *n );
           if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
@@ -150,31 +150,33 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
 }
 
 const std::vector<LHCb::CaloDigit*>& CaloFutureHypo2CaloFuture::digits( const LHCb::CaloHypo& fromHypo,
-                                                                        const std::string&    toCaloFuture ) {
+                                                                        const std::string&    toCaloFuture ) const {
   cellIDs( fromHypo, toCaloFuture );
   return m_digits;
 }
 
-double CaloFutureHypo2CaloFuture::energy( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) {
+double CaloFutureHypo2CaloFuture::energy( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) const {
   cellIDs( fromHypo, toCaloFuture );
   return m_energy;
 }
 const std::vector<LHCb::CaloDigit*>& CaloFutureHypo2CaloFuture::digits( const LHCb::CaloCluster& fromCluster,
-                                                                        const std::string&       toCaloFuture ) {
+                                                                        const std::string&       toCaloFuture ) const {
   cellIDs( fromCluster, toCaloFuture );
   return m_digits;
 }
 
-double CaloFutureHypo2CaloFuture::energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) {
+double CaloFutureHypo2CaloFuture::energy( const LHCb::CaloCluster& fromCluster,
+                                          const std::string&       toCaloFuture ) const {
   cellIDs( fromCluster, toCaloFuture );
   return m_energy;
 }
 
-int CaloFutureHypo2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) {
+int CaloFutureHypo2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster,
+                                             const std::string&       toCaloFuture ) const {
   cellIDs( fromCluster, toCaloFuture );
   return m_count;
 }
-int CaloFutureHypo2CaloFuture::multiplicity( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) {
+int CaloFutureHypo2CaloFuture::multiplicity( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) const {
   cellIDs( fromHypo, toCaloFuture );
   return m_count;
 }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h
index b1fcc0830f5..42e90448a91 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h
@@ -24,7 +24,7 @@
  *  @author Olivier Deschamps
  *  @date   2008-09-11
  */
-class CaloFutureHypo2CaloFuture : public extends<CaloFuture2CaloFuture, ICaloFutureHypo2CaloFuture> {
+class CaloFutureHypo2CaloFuture : public extends<CaloFuture2CaloFuture, Calo::Future::Interfaces::IHypo2Calo> {
 public:
   /// Standard constructor
   using extends::extends;
@@ -33,44 +33,45 @@ public:
   // cellIDs
   using CaloFuture2CaloFuture::cellIDs;
   const std::vector<LHCb::CaloCellID>& cellIDs( const LHCb::CaloHypo& fromHypo,
-                                                const std::string&    toCaloFuture ) override;
+                                                const std::string&    toCaloFuture ) const override;
   const std::vector<LHCb::CaloCellID>& cellIDs( const LHCb::CaloCluster& fromCluster,
-                                                const std::string&       toCaloFuture ) override;
-  const std::vector<LHCb::CaloCellID>& cellIDs() override { return m_cells; };
+                                                const std::string&       toCaloFuture ) const override;
+  const std::vector<LHCb::CaloCellID>& cellIDs() const override { return m_cells; };
   // digits
   using CaloFuture2CaloFuture::digits;
   const std::vector<LHCb::CaloDigit*>& digits( const LHCb::CaloCluster& fromCluster,
-                                               const std::string&       toCaloFuture ) override;
+                                               const std::string&       toCaloFuture ) const override;
   const std::vector<LHCb::CaloDigit*>& digits( const LHCb::CaloHypo& fromHypo,
-                                               const std::string&    toCaloFuture ) override;
-  const std::vector<LHCb::CaloDigit*>& digits() override { return m_digits; };
+                                               const std::string&    toCaloFuture ) const override;
+  const std::vector<LHCb::CaloDigit*>& digits() const override { return m_digits; };
   // energy
   using CaloFuture2CaloFuture::energy;
-  double energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) override;
-  double energy( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) override;
-  double energy() override { return m_energy; };
+  double energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const override;
+  double energy( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) const override;
+  double energy() const override { return m_energy; };
   // multiplicity
   using CaloFuture2CaloFuture::multiplicity;
-  int  multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) override;
-  int  multiplicity( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) override;
-  int  multiplicity() override { return m_count; };
-  void setCalos( const std::string& from, const std::string& to ) override {
-    CaloFuture2CaloFuture::setCalos( from, to );
-  };
+  int multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const override;
+  int multiplicity( const LHCb::CaloHypo& fromHypo, const std::string& toCaloFuture ) const override;
+  int multiplicity() const override { return m_count; };
+  using CaloFuture2CaloFuture::setCalos;
+  void setCalos( const std::string& fromCaloFuture, const std::string& toCaloFuture ) const override {
+    return CaloFuture2CaloFuture::setCalos( fromCaloFuture, toCaloFuture );
+  }
 
   // external setting
   StatusCode _setProperty( const std::string& p, const std::string& v ) override { return setProperty( p, v ); };
 
 private:
-  Gaudi::Property<bool>  m_seed{this, "Seed", true};
-  Gaudi::Property<bool>  m_neighb{this, "AddNeighbors", true};
-  Gaudi::Property<bool>  m_line{this, "PhotonLine", true};
-  Gaudi::Property<bool>  m_whole{this, "WholeCluster", false};
-  Gaudi::Property<int>   m_status{this, "StatusMask", 0x0};
-  Gaudi::Property<float> m_x{this, "xTolerance", 5. * Gaudi::Units::mm};
-  Gaudi::Property<float> m_y{this, "yTolerance", 5. * Gaudi::Units::mm};
-  CellNeighbour          m_neighbour;
-  LHCb::CaloCellID       m_lineID;
-  Gaudi::XYZPoint        m_point;
+  Gaudi::Property<bool>    m_seed{this, "Seed", true};
+  Gaudi::Property<bool>    m_neighb{this, "AddNeighbors", true};
+  Gaudi::Property<bool>    m_line{this, "PhotonLine", true};
+  Gaudi::Property<bool>    m_whole{this, "WholeCluster", false};
+  Gaudi::Property<int>     m_status{this, "StatusMask", 0x0};
+  Gaudi::Property<float>   m_x{this, "xTolerance", 5. * Gaudi::Units::mm};
+  Gaudi::Property<float>   m_y{this, "yTolerance", 5. * Gaudi::Units::mm};
+  mutable CellNeighbour    m_neighbour;
+  mutable LHCb::CaloCellID m_lineID;
+  mutable Gaudi::XYZPoint  m_point;
 };
 #endif // CALOFUTUREHYPO2CALOFUTURE_H
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index 429fc15efa2..8cedbf1d40e 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -37,9 +37,9 @@ StatusCode CaloFutureHypoEstimator::initialize() {
   if ( inc ) inc->addListener( this, IncidentType::BeginEvent );
 
   m_toCaloFuture.retrieve();
-  hypo2CaloFuture()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
-  hypo2CaloFuture()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
-  hypo2CaloFuture()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
+  hypo2Calo()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
+  hypo2Calo()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
+  hypo2Calo()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
 
   m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
 
@@ -51,10 +51,9 @@ StatusCode CaloFutureHypoEstimator::initialize() {
 //=============================================================================
 
 // ------------
-double CaloFutureHypoEstimator::data( const LHCb::CaloCluster* cluster, CaloFutureDataType::DataType type,
-                                      double def ) {
-  double val = def;
-  if ( cluster != m_cluster || !cluster ) {
+std::optional<double> CaloFutureHypoEstimator::data( const LHCb::CaloCluster&     cluster,
+                                                     Calo::Future::Enum::DataType type ) const {
+  if ( &cluster != m_cluster ) {
     clean();
     m_status = estimator( cluster );
     if ( !m_status ) {
@@ -63,14 +62,14 @@ double CaloFutureHypoEstimator::data( const LHCb::CaloCluster* cluster, CaloFutu
     }
   }
   auto it = m_data.find( type );
-  if ( it != m_data.end() ) val = m_data[type];
-  return val == CaloFutureDataType::Default ? def : val;
+  if ( it != m_data.end() ) return m_data[type];
+  return {};
 }
 
 // ------------
-double CaloFutureHypoEstimator::data( const LHCb::CaloHypo* hypo, CaloFutureDataType::DataType type, double def ) {
-  double val = def;
-  if ( hypo != m_hypo || !hypo ) {
+std::optional<double> CaloFutureHypoEstimator::data( const LHCb::CaloHypo&        hypo,
+                                                     Calo::Future::Enum::DataType type ) const {
+  if ( &hypo != m_hypo ) {
     clean();
     m_status = estimator( hypo );
     if ( !m_status ) {
@@ -79,70 +78,69 @@ double CaloFutureHypoEstimator::data( const LHCb::CaloHypo* hypo, CaloFutureData
     }
   }
   auto it = m_data.find( type );
-  if ( it != m_data.end() ) val = m_data[type];
-  return val == CaloFutureDataType::Default ? def : val;
+  if ( it != m_data.end() ) return m_data[type];
+  return {};
 }
 
 // ------------ FROM HYPO
-bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo* hypo ) {
-  using namespace CaloFutureDataType;
-  if ( !hypo ) return false;
-  m_hypo = (LHCb::CaloHypo*)hypo;
-
-  LHCb::CaloMomentum mom( hypo );
-  m_data[HypoE]  = mom.e();
-  m_data[HypoEt] = mom.pt();
-  m_data[HypoM]  = mom.mass(); // for mergedPi0 hypothesis only (->for all clusters - toDo in CaloFutureMergedPi0Alg)
-  m_data[ToPrsE] = m_toCaloFuture->energy( *hypo, "Prs" );
-  m_data[ToPrsM] = m_toCaloFuture->multiplicity( *hypo, "Prs" );
-  m_data[ToSpdM] = m_toCaloFuture->multiplicity( *hypo, "Spd" );
+bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
+  using namespace Calo::Future::Enum;
+  m_hypo = &hypo;
+
+  LHCb::CaloMomentum mom( &hypo );
+  m_data[DataType::HypoE]  = mom.e();
+  m_data[DataType::HypoEt] = mom.pt();
+  m_data[DataType::HypoM] =
+      mom.mass(); // for mergedPi0 hypothesis only (->for all clusters - toDo in CaloFutureMergedPi0Alg)
+  m_data[DataType::ToPrsE] = m_toCaloFuture->energy( hypo, "Prs" );
+  m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( hypo, "Prs" );
+  m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( hypo, "Spd" );
   // using extra-digits
-  const LHCb::CaloHypo::Digits&     digits = hypo->digits();
+  const LHCb::CaloHypo::Digits&     digits = hypo.digits();
   LHCb::CaloDataFunctor::IsFromCalo isSpd{DeCalorimeterLocation::Spd};
   LHCb::CaloDataFunctor::IsFromCalo isPrs{DeCalorimeterLocation::Prs};
-  m_data[HypoSpdM] = std::count_if( digits.begin(), digits.end(), isSpd );
-  m_data[HypoPrsM] = std::count_if( digits.begin(), digits.end(), isPrs );
-  double sumPrs    = 0;
-  for ( LHCb::CaloHypo::Digits::const_iterator id = digits.begin(); id != digits.end(); ++id ) {
-    if ( 0 != *id && isPrs( *id ) ) { sumPrs += ( *id )->e(); }
-  }
-  m_data[HypoPrsE] = sumPrs;
+  m_data[DataType::HypoSpdM] = std::count_if( digits.begin(), digits.end(), isSpd );
+  m_data[DataType::HypoPrsM] = std::count_if( digits.begin(), digits.end(), isPrs );
+  m_data[DataType::HypoPrsE] = std::accumulate( digits.begin(), digits.end(), 0., [&]( double sumPrs, const auto& id ) {
+    if ( id && isPrs( id ) ) { sumPrs += id->e(); }
+    return sumPrs;
+  } );
 
   // electron matching
   if ( !m_skipC ) {
-    double             chi2e  = CaloFutureDataType::Default;
-    double             trajL  = CaloFutureDataType::Default;
+    double             chi2e  = Default;
+    double             trajL  = Default;
     const LHCb::Track* etrack = nullptr;
     // LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc);
-    LHCb::CaloFuture2Track::ITrHypoTable2D* etable = m_tables->getTrHypoTable2D( m_emLoc );
+    const LHCb::CaloFuture2Track::ITrHypoTable2D* etable = m_tables->getTrHypoTable2D( m_emLoc );
     if ( etable ) {
-      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = etable->inverse()->relations( hypo );
+      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = etable->inverse()->relations( &hypo );
       if ( !range.empty() ) {
         chi2e  = range.front().weight();
         etrack = range.front();
         if ( etrack ) {
-          LHCb::ProtoParticle* dummy = new LHCb::ProtoParticle();
-          dummy->setTrack( etrack );
-          dummy->addToCalo( hypo );
+          LHCb::ProtoParticle dummy;
+          dummy.setTrack( etrack );
+          dummy.addToCalo( &hypo );
           // CaloFutureElectron->caloTrajectory must be after addToCalo
-          if ( m_electron->set( dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax, "hypo" );
-          delete dummy;
+          if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax, "hypo" );
+          m_electron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
         }
       }
     } else if ( counterStat->isQuiet() )
       counter( "Missing " + m_emLoc ) += 1;
 
-    m_track[CaloFutureMatchType::ElectronMatch] = etrack;
-    m_data[ElectronMatch]                       = chi2e;
-    m_data[TrajectoryL]                         = trajL;
+    m_track[MatchType::ElectronMatch] = etrack;
+    m_data[DataType::ElectronMatch]   = chi2e;
+    m_data[DataType::TrajectoryL]     = trajL;
 
     // brem matching
-    double             chi2b  = CaloFutureDataType::Default;
-    const LHCb::Track* btrack = NULL;
+    double             chi2b  = Default;
+    const LHCb::Track* btrack = nullptr;
     // LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc);
-    LHCb::CaloFuture2Track::ITrHypoTable2D* btable = m_tables->getTrHypoTable2D( m_bmLoc );
+    const LHCb::CaloFuture2Track::ITrHypoTable2D* btable = m_tables->getTrHypoTable2D( m_bmLoc );
     if ( btable ) {
-      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = btable->inverse()->relations( hypo );
+      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = btable->inverse()->relations( &hypo );
       if ( !range.empty() ) {
         chi2b  = range.front().weight();
         btrack = range.front();
@@ -150,38 +148,38 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo* hypo ) {
     } else if ( counterStat->isQuiet() )
       counter( "Missing " + m_bmLoc ) += 1;
 
-    m_track[CaloFutureMatchType::BremMatch] = btrack;
-    m_data[BremMatch]                       = chi2b;
+    m_track[MatchType::BremMatch] = btrack;
+    m_data[DataType::BremMatch]   = chi2b;
   }
 
   // NeutralID (warning : protect against infinite loop from CaloFuturePhotonIDAlg using this tools with DoD active)
   if ( !m_skipN ) {
     for ( auto&& [hypothesis, loc] : m_pidLoc ) {
-      if ( exist<LHCb::CaloFuture2Track::IHypoEvalTable>( loc ) )
-        // m_idTable[hypothesis] = get<LHCb::CaloFuture2Track::IHypoEvalTable> ( loc ) ;
-        m_idTable[hypothesis] = m_tables->getHypoEvalTable( loc );
-      else if ( counterStat->isQuiet() )
+      const LHCb::CaloFuture2Track::IHypoEvalTable* tbl = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( loc );
+      if ( tbl ) {
+        m_idTable[hypothesis] = tbl;
+      } else if ( counterStat->isQuiet() ) {
         counter( "Missing " + loc ) += 1;
+      }
     }
     std::ostringstream type( "" );
-    type << hypo->hypothesis();
-    std::string                                                              hypothesis = type.str();
-    const LHCb::CaloFuture2Track::IHypoEvalTable*                            idTable    = nullptr;
-    std::map<std::string, LHCb::CaloFuture2Track::IHypoEvalTable*>::iterator it         = m_idTable.find( hypothesis );
+    type << hypo.hypothesis();
+    std::string                                   hypothesis = type.str();
+    const LHCb::CaloFuture2Track::IHypoEvalTable* idTable    = nullptr;
+    auto                                          it         = m_idTable.find( hypothesis );
     if ( it != m_idTable.end() ) idTable = it->second;
     if ( idTable ) {
-      const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( hypo );
-      if ( !range.empty() ) m_data[NeutralID] = range.front().to();
+      const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( &hypo );
+      if ( !range.empty() ) m_data[DataType::NeutralID] = range.front().to();
     }
   }
   // link 2 cluster :
-  const LHCb::CaloCluster* cluster               = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo );
-  m_clusters[CaloFutureClusterType::SplitOrMain] = cluster;
-  m_clusters[CaloFutureClusterType::Main] =
-      LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo, false ); // get the main cluster
+  const LHCb::CaloCluster* cluster     = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
+  m_clusters[ClusterType::SplitOrMain] = cluster;
+  m_clusters[ClusterType::Main] = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false ); // get the main cluster
 
   // Prs info
-  if ( cluster == NULL ) {
+  if ( !cluster ) {
     Warning( "Cluster point to NULL", StatusCode::SUCCESS ).ignore();
   } else {
     // Ecal seed
@@ -224,71 +222,93 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo* hypo ) {
       //
       double Prse4max =
           std::accumulate( Prse4s.begin(), Prse4s.end(), 0., []( double l, double r ) { return std::max( l, r ); } );
-      m_data[PrsE4Max] = Prse4max;
-      double sum9Inv   = 0.;
+      m_data[DataType::PrsE4Max] = Prse4max;
+      double sum9Inv             = 0.;
       if ( sum9 > 0. ) {
-        sum9Inv        = 1. / sum9;
-        m_data[PrsE49] = Prse4max * sum9Inv;
-        m_data[PrsE19] = sum1 * sum9Inv;
+        sum9Inv                  = 1. / sum9;
+        m_data[DataType::PrsE49] = Prse4max * sum9Inv;
+        m_data[DataType::PrsE19] = sum1 * sum9Inv;
       } else {
-        m_data[PrsE49] = 0.;
-        m_data[PrsE19] = 0.;
+        m_data[DataType::PrsE49] = 0.;
+        m_data[DataType::PrsE19] = 0.;
       }
-      m_data[PrsE1] = Prse9[0];
-      m_data[PrsE2] = Prse9[1];
-      m_data[PrsE3] = Prse9[2];
-      m_data[PrsE4] = Prse9[3];
-      m_data[PrsE5] = Prse9[4];
-      m_data[PrsE6] = Prse9[5];
-      m_data[PrsE7] = Prse9[6];
-      m_data[PrsE8] = Prse9[7];
-      m_data[PrsE9] = Prse9[8];
+      m_data[DataType::PrsE1] = Prse9[0];
+      m_data[DataType::PrsE2] = Prse9[1];
+      m_data[DataType::PrsE3] = Prse9[2];
+      m_data[DataType::PrsE4] = Prse9[3];
+      m_data[DataType::PrsE5] = Prse9[4];
+      m_data[DataType::PrsE6] = Prse9[5];
+      m_data[DataType::PrsE7] = Prse9[6];
+      m_data[DataType::PrsE8] = Prse9[7];
+      m_data[DataType::PrsE9] = Prse9[8];
     }
   }
 
   // gamma/pi0 separation
-  m_data[CaloFutureDataType::DataType::isPhoton]    = m_GammaPi0->isPhoton( hypo );
-  m_data[CaloFutureDataType::DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( hypo );
+  m_data[DataType::isPhoton]    = m_GammaPi0->isPhoton( &hypo );
+  m_data[DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( &hypo );
 
   // 1- Ecal variables :
-  std::map<std::string, double> isPhotonData = m_GammaPi0->inputDataMap();
-  for ( std::map<std::string, double>::iterator idata = isPhotonData.begin(); isPhotonData.end() != idata; ++idata ) {
-    std::string name = "isPhoton_" + idata->first;
-    double      val  = idata->second;
+  for ( const auto& [key, val] : m_GammaPi0->inputDataMap() ) {
+    std::string name = "isPhoton_" + key;
     bool        ok   = false;
-    for ( int i = 0; i < Last; ++i ) {
-      if ( Name[i] == name ) {
-        m_data[(DataType)i] = val;
-        ok                  = true;
+    for ( int i = 0; i < count<DataType>(); ++i ) {
+      DataType j{i};
+      if ( toString( j ) == name ) {
+        m_data[j] = val;
+        ok        = true;
         break;
       }
     }
     if ( !ok ) Warning( "DataType '" + name + "' is undefined", StatusCode::SUCCESS ).ignore();
   }
   //
-  bool ok = ( 0 != cluster ) ? estimator( cluster, hypo ) : false;
+  bool ok = ( cluster && estimator( *cluster, &hypo ) );
 
   // Estimator MUST be at the end (after all inputs are loaded)
-  m_data[isNotH] = m_neutralID->isNotH( *hypo, this );
-  m_data[isNotE] = m_neutralID->isNotE( *hypo, this );
+
+  auto get_data = [&]( Calo::Future::Enum::DataType type ) {
+    auto d = m_data.find( type );
+    return d != m_data.end() ? d->second : 0.;
+  };
+
+// FIXME: C++20: remove pragmas
+// designated initializers are part of C99 (so both clang and gcc support them)
+// and C++20, but when using C++17, they generate a '-Wpedantic' warning.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+
+  auto obs = Calo::Future::Interfaces::INeutralID::Observables{.clmatch = get_data( DataType::ClusterMatch ),
+                                                               .prse    = get_data( DataType::ToPrsE ),
+                                                               .e19     = get_data( DataType::E19 ),
+                                                               .hclecl  = get_data( DataType::Hcal2Ecal ),
+                                                               .prse19  = get_data( DataType::PrsE19 ),
+                                                               .prse49  = get_data( DataType::PrsE49 ),
+                                                               .sprd    = get_data( DataType::Spread ),
+                                                               .prse4mx = get_data( DataType::PrsE4Max ),
+                                                               .prsm    = get_data( DataType::HypoPrsM ),
+                                                               .spdm    = get_data( DataType::HypoSpdM )};
+#pragma GCC diagnostic pop
+
+  m_data[DataType::isNotH] = m_neutralID->isNotH( hypo, obs );
+  m_data[DataType::isNotE] = m_neutralID->isNotE( hypo, obs );
 
   return ok;
 }
 
 // ------------ FROM CLUSTER
-bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster* cluster, const LHCb::CaloHypo* fromHypo ) {
-  using namespace CaloFutureDataType;
-  if ( NULL == cluster ) return false;
-  m_cluster = (LHCb::CaloCluster*)cluster;
+bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo ) const {
+  using namespace Calo::Future::Enum;
+  m_cluster = &cluster;
 
-  if ( cluster->entries().empty() ) {
+  if ( cluster.entries().empty() ) {
     if ( counterStat->isQuiet() ) counter( "Empty cluster" ) += 1;
     return false;
   }
-  LHCb::CaloCluster::Entries::const_iterator iseed = LHCb::ClusterFunctors::locateDigit(
-      cluster->entries().begin(), cluster->entries().end(), LHCb::CaloDigitStatus::SeedCell );
+  auto iseed = LHCb::ClusterFunctors::locateDigit( cluster.entries().begin(), cluster.entries().end(),
+                                                   LHCb::CaloDigitStatus::SeedCell );
 
-  if ( iseed != cluster->entries().end() ) {
+  if ( iseed != cluster.entries().end() ) {
 
     const LHCb::CaloDigit* seed = iseed->digit();
     if ( 0 == seed ) {
@@ -296,41 +316,35 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster* cluster, const
       return false;
     }
 
-    double eEcal     = cluster->e();
-    m_data[ClusterE] = eEcal;
+    double eEcal               = cluster.e();
+    m_data[DataType::ClusterE] = eEcal;
     //
-    double          cSize   = m_ecal->cellSize( cluster->seed() );
-    Gaudi::XYZPoint cCenter = m_ecal->cellCenter( cluster->seed() );
-    double          asX     = ( cluster->position().x() - cCenter.x() ) / cSize;
-    double          asY     = ( cluster->position().y() - cCenter.y() ) / cSize;
-    m_data[ClusterAsX]      = asX;
-    m_data[ClusterAsY]      = asY;
-
-    m_data[E1]                   = seed->e();
-    caloDataType::iterator it    = m_data.find( HypoE );
-    double                 eHypo = ( it != m_data.end() ) ? m_data[HypoE] : 0;
-    m_data[E1Hypo]               = eHypo > 0. ? ( seed->e() ) / eHypo : -1.;
-    LHCb::CaloCellID sid         = seed->cellID();
-    m_data[CellID]               = (double)sid.all();
-    m_data[Spread]               = cluster->position().spread()( 1, 1 ) + cluster->position().spread()( 0, 0 );
+    double          cSize        = m_ecal->cellSize( cluster.seed() );
+    Gaudi::XYZPoint cCenter      = m_ecal->cellCenter( cluster.seed() );
+    double          asX          = ( cluster.position().x() - cCenter.x() ) / cSize;
+    double          asY          = ( cluster.position().y() - cCenter.y() ) / cSize;
+    m_data[DataType::ClusterAsX] = asX;
+    m_data[DataType::ClusterAsY] = asY;
+
+    m_data[DataType::E1]     = seed->e();
+    auto   it                = m_data.find( DataType::HypoE );
+    double eHypo             = ( it != m_data.end() ) ? m_data[DataType::HypoE] : 0;
+    m_data[DataType::E1Hypo] = eHypo > 0. ? ( seed->e() ) / eHypo : -1.;
+    LHCb::CaloCellID sid     = seed->cellID();
+    m_data[DataType::CellID] = sid.all();
+    m_data[DataType::Spread] = cluster.position().spread()( 1, 1 ) + cluster.position().spread()( 0, 0 );
     // E4
-    std::vector<double> e4s;
-    e4s.reserve( 4 );
-    e4s.push_back( 0 );
-    e4s.push_back( 0 );
-    e4s.push_back( 0 );
-    e4s.push_back( 0 );
-    double e9        = 0.;
-    double ee9       = 0.; // full cluster energy without fraction applied
-    double e2        = 0.;
-    bool   hasShared = false;
-    int    code      = 0.;
-    int    mult      = 0.;
-    int    nsat      = 0; // number of saturated cells
-    for ( LHCb::CaloCluster::Entries::const_iterator ie = cluster->entries().begin(); cluster->entries().end() != ie;
-          ++ie ) {
-      const LHCb::CaloDigit* dig = ( *ie ).digit();
-      if ( NULL == dig ) continue;
+    std::array<double, 4> e4s       = {0, 0, 0, 0};
+    double                e9        = 0.;
+    double                ee9       = 0.; // full cluster energy without fraction applied
+    double                e2        = 0.;
+    bool                  hasShared = false;
+    int                   code      = 0.;
+    int                   mult      = 0.;
+    int                   nsat      = 0; // number of saturated cells
+    for ( auto ie = cluster.entries().begin(); cluster.entries().end() != ie; ++ie ) {
+      const LHCb::CaloDigit* dig = ie->digit();
+      if ( !dig ) continue;
       double ecel = dig->e() * ie->fraction();
       if ( ( ( ie->status() & LHCb::CaloDigitStatus::UseForEnergy ) != 0 ||
              ( ie->status() & LHCb::CaloDigitStatus::UseForCovariance ) != 0 ) &&
@@ -356,45 +370,45 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster* cluster, const
         code   = 3 * dr + dc;
       }
     }
-    m_data[Saturation] = (double)nsat;
-    double e4max       = 0;
-    for ( std::vector<double>::iterator ih = e4s.begin(); e4s.end() != ih; ++ih ) {
+    m_data[DataType::Saturation] = nsat;
+    double e4max                 = 0;
+    for ( auto ih = e4s.begin(); e4s.end() != ih; ++ih ) {
       if ( *ih >= e4max ) e4max = *ih;
     }
 
     code = mult * 10 + code;
     if ( hasShared ) code *= -1;
-    m_data[ClusterCode] = (double)code;
-    m_data[ClusterFrac] = ( e9 > 0. ) ? e9 / ee9 : -1;
+    m_data[DataType::ClusterCode] = (double)code;
+    m_data[DataType::ClusterFrac] = ( e9 > 0. ) ? e9 / ee9 : -1;
 
-    m_data[E4]  = e4max;
-    m_data[E9]  = e9;
-    m_data[E49] = ( e9 > 0. ) ? e4max / e9 : 0.;
-    m_data[E19] = ( e9 > 0. ) ? seed->e() / e9 : -1.;
+    m_data[DataType::E4]  = e4max;
+    m_data[DataType::E9]  = e9;
+    m_data[DataType::E49] = ( e9 > 0. ) ? e4max / e9 : 0.;
+    m_data[DataType::E19] = ( e9 > 0. ) ? seed->e() / e9 : -1.;
 
-    if ( NULL == fromHypo ) {
+    if ( !fromHypo ) {
       // hypo and cluster parameters may produce small difference according to m_toCaloFuture setting (due to
       // extrapolation)
-      m_data[ToPrsE] = m_toCaloFuture->energy( *cluster, "Prs" );
-      m_data[ToPrsM] = m_toCaloFuture->multiplicity( *cluster, "Prs" );
-      m_data[ToSpdM] = m_toCaloFuture->multiplicity( *cluster, "Spd" );
+      m_data[DataType::ToPrsE] = m_toCaloFuture->energy( cluster, "Prs" );
+      m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( cluster, "Prs" );
+      m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( cluster, "Spd" );
     }
-    double eHcal      = m_toCaloFuture->energy( *cluster, "Hcal" );
-    m_data[ToHcalE]   = eHcal;
-    m_data[Hcal2Ecal] = ( eEcal > 0 ) ? eHcal / eEcal : 0.;
+    double eHcal                = m_toCaloFuture->energy( cluster, "Hcal" );
+    m_data[DataType::ToHcalE]   = eHcal;
+    m_data[DataType::Hcal2Ecal] = ( eEcal > 0 ) ? eHcal / eEcal : 0.;
   }
 
   // cluster-match chi2
   if ( !m_skipCl ) {
-    const LHCb::CaloCluster* clus = cluster;
+    const LHCb::CaloCluster* clus = &cluster;
     // special trick for split cluster : use full cluster matching
-    if ( NULL != fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
+    if ( fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
       clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo, false ); // get the main cluster
-    double             chi2   = CaloFutureDataType::Default;
-    const LHCb::Track* ctrack = NULL;
+    double             chi2   = Default;
+    const LHCb::Track* ctrack = nullptr;
     // LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc);
-    LHCb::CaloFuture2Track::IClusTrTable* ctable = m_tables->getClusTrTable( m_cmLoc );
-    if ( NULL != ctable ) {
+    const LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
+    if ( ctable ) {
       const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable->relations( clus );
 
       if ( !range.empty() ) {
@@ -404,16 +418,15 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster* cluster, const
     } else if ( counterStat->isQuiet() )
       counter( "Missing " + m_cmLoc ) += 1;
 
-    m_track[CaloFutureMatchType::ClusterMatch] = ctrack;
-    m_data[ClusterMatch]                       = chi2;
+    m_track[MatchType::ClusterMatch] = ctrack;
+    m_data[DataType::ClusterMatch]   = chi2;
   }
   return true;
 }
 
-void CaloFutureHypoEstimator::clean() {
+void CaloFutureHypoEstimator::clean() const {
   m_data.clear();
-  m_cluster = NULL;
-  m_hypo    = NULL;
+  m_cluster = nullptr;
+  m_hypo    = nullptr;
   m_track.clear();
-  return;
 }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index 32a4723f9b4..e370cb0890a 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -41,7 +41,7 @@
  *  @date   2010-08-18
  */
 
-class CaloFutureHypoEstimator : public extends<GaudiTool, ICaloFutureHypoEstimator, IIncidentListener> {
+class CaloFutureHypoEstimator : public extends<GaudiTool, Calo::Future::Interfaces::IHypoEstimator, IIncidentListener> {
 public:
   /// Standard constructor
   using extends::extends;
@@ -49,44 +49,47 @@ public:
   StatusCode initialize() override;
   StatusCode finalize() override;
 
-  double data( const LHCb::CaloCluster* cluster, CaloFutureDataType::DataType type,
-               double def = CaloFutureDataType::Default ) override;
-  double data( const LHCb::CaloHypo* hypo, CaloFutureDataType::DataType type,
-               double def = CaloFutureDataType::Default ) override;
+  std::optional<double> data( const LHCb::CaloCluster& cluster, Calo::Future::Enum::DataType type ) const override;
+  std::optional<double> data( const LHCb::CaloHypo& hypo, Calo::Future::Enum::DataType type ) const override;
 
   void handle( const Incident& ) override {
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "IIncident Svc reset" << endmsg;
     clean();
   }
-  ICaloFutureHypo2CaloFuture* hypo2CaloFuture() override { return m_toCaloFuture.get(); };
-  const LHCb::Track*          toTrack( CaloFutureMatchType::MatchType match ) override {
-    caloMatchType::iterator it = m_track.find( match );
-    if ( it == m_track.end() ) return NULL;
-    return ( *it ).second;
+
+  Calo::Future::Interfaces::IHypo2Calo* hypo2Calo() override { return m_toCaloFuture.get(); }
+
+  const LHCb::Track* toTrack( Calo::Future::Enum::MatchType match ) const override {
+    auto it = m_track.find( match );
+    return it != m_track.end() ? it->second : nullptr;
   }
+
   const LHCb::CaloCluster*
-  toCluster( CaloFutureClusterType::ClusterType clus = CaloFutureClusterType::SplitOrMain ) override {
-    caloClusterType::iterator it = m_clusters.find( clus );
-    if ( it == m_clusters.end() ) return NULL;
-    return ( *it ).second;
+  toCluster( Calo::Future::Enum::ClusterType clus = Calo::Future::Enum::ClusterType::SplitOrMain ) const override {
+    auto it = m_clusters.find( clus );
+    return it != m_clusters.end() ? it->second : nullptr;
   }
 
   StatusCode _setProperty( const std::string& p, const std::string& v ) override { return setProperty( p, v ); };
-  bool       status() override { return m_status; }
+  bool       status() const override { return m_status; }
 
 private:
-  bool estimator( const LHCb::CaloCluster* cluster, const LHCb::CaloHypo* fromHypo = NULL );
-  bool estimator( const LHCb::CaloHypo* hypo );
-  void clean();
+  bool estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo = nullptr ) const;
+  bool estimator( const LHCb::CaloHypo& hypo ) const;
+  void clean() const;
+
+  using caloDataType    = std::map<Calo::Future::Enum::DataType, double>;
+  using caloMatchType   = std::map<Calo::Future::Enum::MatchType, const LHCb::Track*>;
+  using caloClusterType = std::map<Calo::Future::Enum::ClusterType, const LHCb::CaloCluster*>;
 
-  caloDataType       m_data;
-  caloMatchType      m_track;
-  caloClusterType    m_clusters;
-  LHCb::CaloHypo*    m_hypo    = nullptr;
-  LHCb::CaloCluster* m_cluster = nullptr;
+  mutable caloDataType             m_data;
+  mutable caloMatchType            m_track;
+  mutable caloClusterType          m_clusters;
+  mutable const LHCb::CaloHypo*    m_hypo    = nullptr;
+  mutable const LHCb::CaloCluster* m_cluster = nullptr;
 
-  std::map<std::string, LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable;
-  bool                                                           m_status = true;
+  mutable std::map<std::string, const LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable;
+  mutable bool                                                                 m_status = true;
 
   Gaudi::Property<bool>                               m_extrapol{this, "Extrapolation", true};
   Gaudi::Property<bool>                               m_seed{this, "AddSeed", false};
@@ -107,13 +110,14 @@ private:
   Gaudi::Property<bool>        m_skipN{this, "SkipNeutralID", false};
   Gaudi::Property<bool>        m_skipCl{this, "SkipClusterMatch", false};
 
-  PublicToolHandle<IFutureCounterLevel>            counterStat{this, "CounterLevel", "FutureCounterLevel"};
-  ToolHandle<ICaloFutureHypo2CaloFuture>           m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
-  ToolHandle<ICaloFutureElectron>                  m_electron{this, "Electron", "CaloFutureElectron"};
-  ToolHandle<IFutureGammaPi0SeparationTool>        m_GammaPi0{this, "Pi0Separation", "FutureGammaPi0SeparationTool"};
-  PublicToolHandle<IFutureGammaPi0SeparationTool>  m_GammaPi0XGB{this, "PiOSeparation", "FutureGammaPi0XGBoostTool"};
-  ToolHandle<Calo::Future::Interfaces::INeutralID> m_neutralID{this, "NeutralID", "FutureNeutralIDTool"};
-  ToolHandle<ICaloFutureRelationsGetter>           m_tables{this, "RelationGetter", "CaloFutureRelationsGetter"};
+  PublicToolHandle<IFutureCounterLevel>             counterStat{this, "CounterLevel", "FutureCounterLevel"};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo>  m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
+  mutable ToolHandle<ICaloFutureElectron>           m_electron{this, "Electron", "CaloFutureElectron"};
+  mutable ToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0{this, "Pi0Separation", "FutureGammaPi0SeparationTool"};
+  mutable PublicToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0XGB{this, "PiOSeparation",
+                                                                        "FutureGammaPi0XGBoostTool"};
+  ToolHandle<Calo::Future::Interfaces::INeutralID>        m_neutralID{this, "NeutralID", "FutureNeutralIDTool"};
+  mutable ToolHandle<ICaloFutureRelationsGetter>          m_tables{this, "RelationGetter", "CaloFutureRelationsGetter"};
 
   DeCalorimeter* m_ecal = nullptr;
 };
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp
index 3ad539af232..ff3fb75dbfc 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp
@@ -43,31 +43,18 @@ StatusCode CaloFutureRelationsGetter::finalize() {
   return GaudiTool::finalize();
 }
 
-LHCb::CaloFuture2Track::ITrHypoTable2D* CaloFutureRelationsGetter::getTrHypoTable2D( std::string location ) {
-  auto it = m_hypoTr.find( location );
-  if ( it == m_hypoTr.end() ) m_hypoTr[location] = getIfExists<LHCb::CaloFuture2Track::IHypoTrTable2D>( location );
-
-  auto links = m_hypoTr[location]->relations();
-  m_trHypo.i_clear().ignore();
-  for ( const auto& l : links ) m_trHypo.i_push( l.to(), l.from(), l.weight() );
-  m_trHypo.i_sort();
+const LHCb::CaloFuture2Track::ITrHypoTable2D*
+CaloFutureRelationsGetter::getTrHypoTable2D( std::string location ) const {
+  auto self = const_cast<CaloFutureRelationsGetter*>( this );
+  auto it   = m_hypoTr.find( location );
+  if ( it == m_hypoTr.end() )
+    self->m_hypoTr[location] = getIfExists<LHCb::CaloFuture2Track::IHypoTrTable2D>( location );
+
+  auto links = self->m_hypoTr[location]->relations();
+  self->m_trHypo.i_clear().ignore();
+  for ( const auto& l : links ) self->m_trHypo.i_push( l.to(), l.from(), l.weight() );
+  self->m_trHypo.i_sort();
   return &m_trHypo;
 }
 
-LHCb::CaloFuture2Track::IHypoEvalTable* CaloFutureRelationsGetter::getHypoEvalTable( std::string location ) {
-  auto it = m_hypoEval.find( location );
-  if ( it == m_hypoEval.end() ) m_hypoEval[location] = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( location );
-  return m_hypoEval[location];
-}
-
-LHCb::CaloFuture2Track::IClusTrTable* CaloFutureRelationsGetter::getClusTrTable( std::string location ) {
-  auto it = m_clusTr.find( location );
-  if ( it == m_clusTr.end() ) m_clusTr[location] = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( location );
-  return m_clusTr[location];
-}
-
-void CaloFutureRelationsGetter::clean() {
-  m_clusTr.clear();
-  m_hypoEval.clear();
-  m_hypoTr.clear();
-}
+void CaloFutureRelationsGetter::clean() { m_hypoTr.clear(); }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h
index b98d7072438..18fc5d32110 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h
@@ -47,15 +47,11 @@ public:
   }
 
   // getters
-  LHCb::CaloFuture2Track::ITrHypoTable2D* getTrHypoTable2D( std::string location ) override;
-  LHCb::CaloFuture2Track::IHypoEvalTable* getHypoEvalTable( std::string location ) override;
-  LHCb::CaloFuture2Track::IClusTrTable*   getClusTrTable( std::string location ) override;
+  const LHCb::CaloFuture2Track::ITrHypoTable2D* getTrHypoTable2D( std::string location ) const override;
 
 private:
   LHCb::RelationWeighted2D<LHCb::Track, LHCb::CaloHypo, float>   m_trHypo;
   std::map<std::string, LHCb::CaloFuture2Track::IHypoTrTable2D*> m_hypoTr;
-  std::map<std::string, LHCb::CaloFuture2Track::IHypoEvalTable*> m_hypoEval;
-  std::map<std::string, LHCb::CaloFuture2Track::IClusTrTable*>   m_clusTr;
   void                                                           clean();
 };
 #endif // CALOFUTURERELATIONSGETTER_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
index 96ffa66f5d2..84000503428 100644
--- a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
@@ -73,24 +73,22 @@ StatusCode FutureNeutralIDTool::finalize() {
 // Main execution
 //=============================================================================
 
-double FutureNeutralIDTool::isNotE( const LHCb::CaloHypo& hypo, ICaloFutureHypoEstimator* estimator ) const {
-
-  if ( estimator ) m_estimator = estimator;
+double FutureNeutralIDTool::isNotE( const LHCb::CaloHypo&                                    hypo,
+                                    const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
   double pt = LHCb::CaloMomentum( &hypo ).pt();
-  if ( pt <= m_minPt ) return CaloFutureDataType::Default;
+  if ( pt <= m_minPt ) return Calo::Future::Enum::Default;
   const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false );
-  if ( !cluster ) return CaloFutureDataType::Default;
-  return isNotE( observables( hypo ) );
+  if ( !cluster ) return Calo::Future::Enum::Default;
+  return isNotE( v );
 }
 
-double FutureNeutralIDTool::isNotH( const LHCb::CaloHypo& hypo, ICaloFutureHypoEstimator* estimator ) const {
-
-  if ( estimator ) m_estimator = estimator;
+double FutureNeutralIDTool::isNotH( const LHCb::CaloHypo&                                    hypo,
+                                    const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
   double pt = LHCb::CaloMomentum( &hypo ).pt();
-  if ( pt <= m_minPt ) return CaloFutureDataType::Default;
+  if ( pt <= m_minPt ) return Calo::Future::Enum::Default;
   const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false );
-  if ( !cluster ) return CaloFutureDataType::Default;
-  return isNotH( observables( hypo ) );
+  if ( !cluster ) return Calo::Future::Enum::Default;
+  return isNotH( v );
 }
 
 double FutureNeutralIDTool::isNotE( const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
@@ -102,30 +100,3 @@ double FutureNeutralIDTool::isNotH( const Calo::Future::Interfaces::INeutralID::
   return m_reader1->GetMvaValue(
       {tanh( v.clmatch / 2000 ), v.prse, v.e19, v.hclecl, v.prse19, v.prse49, v.sprd, v.prse4mx, v.prsm, v.spdm} );
 }
-
-Calo::Future::Interfaces::INeutralID::Observables FutureNeutralIDTool::observables( const LHCb::CaloHypo& hypo ) const {
-  using namespace CaloFutureDataType;
-
-  // load the estimator tool only when not passed in argument (to avoid circular initialization with the estimator
-  // itself)
-  if ( !m_estimator )
-    m_estimator =
-        tool<ICaloFutureHypoEstimator>( "CaloFutureHypoEstimator", "CaloFutureHypoEstimatorForNeutralID", this );
-
-// FIXME: C++20: remove pragmas
-// designated initializers are part of C99 (so both clang and gcc support them)
-// and C++20, but when using C++17, they generate a '-Wpedantic' warning.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic"
-  return {.clmatch = m_estimator->data( &hypo, ClusterMatch, 0. ),
-          .prse    = m_estimator->data( &hypo, ToPrsE, 0. ),
-          .e19     = m_estimator->data( &hypo, E19, 0. ),
-          .hclecl  = m_estimator->data( &hypo, Hcal2Ecal, 0. ),
-          .prse19  = m_estimator->data( &hypo, PrsE19, 0. ),
-          .prse49  = m_estimator->data( &hypo, PrsE49, 0. ),
-          .sprd    = m_estimator->data( &hypo, Spread, 0. ),
-          .prse4mx = m_estimator->data( &hypo, PrsE4Max, 0. ),
-          .prsm    = m_estimator->data( &hypo, HypoPrsM, 0. ),
-          .spdm    = m_estimator->data( &hypo, HypoSpdM, 0. )};
-#pragma GCC diagnostic pop
-}
diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
index 194698fdfe7..363aba975e1 100644
--- a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
@@ -42,9 +42,10 @@ public:
   StatusCode initialize() override;
   StatusCode finalize() override;
 
-  double isNotE( const LHCb::CaloHypo& hypo, ICaloFutureHypoEstimator* e ) const override;
-  double isNotH( const LHCb::CaloHypo& hypo, ICaloFutureHypoEstimator* e ) const override;
-  Calo::Future::Interfaces::INeutralID::Observables observables( const LHCb::CaloHypo& hypo ) const override;
+  double isNotE( const LHCb::CaloHypo&                                    hypo,
+                 const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
+  double isNotH( const LHCb::CaloHypo&                                    hypo,
+                 const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
 
   double isNotE( const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
   double isNotH( const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
@@ -54,7 +55,5 @@ private:
 
   std::unique_ptr<IClassifierReader> m_reader0;
   std::unique_ptr<IClassifierReader> m_reader1;
-
-  mutable ICaloFutureHypoEstimator* m_estimator = nullptr;
 };
 #endif // FUTURENEUTRALIDTOOL_H
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp
index 67237d0528c..c6b3df2d817 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp
@@ -115,15 +115,21 @@ bool FutureChargedProtoParticleAddBremInfo::addBrem( LHCb::ProtoParticle* proto
       if ( !hRange.empty() ) {
         const auto* hypo = hRange.front().to();
         proto->addToCalo( hypo );
-        using namespace CaloFutureDataType;
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, m_estimator->data( hypo, HypoSpdM ) > 0 );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, m_estimator->data( hypo, HypoPrsE ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal, m_estimator->data( hypo, ClusterE ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloBremMatch, m_estimator->data( hypo, BremMatch ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralID, m_estimator->data( hypo, CellID ) );
+        using namespace Calo::Future::Enum;
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd,
+                        m_estimator->data( *hypo, DataType::HypoSpdM ).value_or( Default ) > 0 );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs,
+                        m_estimator->data( *hypo, DataType::HypoPrsE ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal,
+                        m_estimator->data( *hypo, DataType::ClusterE ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloBremMatch,
+                        m_estimator->data( *hypo, DataType::BremMatch ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralID,
+                        m_estimator->data( *hypo, DataType::CellID ).value_or( Default ) );
         proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal,
-                        m_estimator->data( hypo, Hcal2Ecal ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralE49, m_estimator->data( hypo, E49 ) );
+                        m_estimator->data( *hypo, DataType::Hcal2Ecal ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloNeutralE49,
+                        m_estimator->data( *hypo, DataType::E49 ).value_or( Default ) );
       }
 
       // Get the BremChi2 (intermediate) estimator
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
index 5b52e765277..2330d38ff4f 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
@@ -149,11 +149,15 @@ bool FutureChargedProtoParticleAddEcalInfo::addEcal( LHCb::ProtoParticle* proto
           proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloEoverP, electronTool()->eOverP() );
         }
 
-        using namespace CaloFutureDataType;
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedSpd, m_estimator->data( hypo, HypoSpdM ) > 0 );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedPrs, m_estimator->data( hypo, HypoPrsE ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedEcal, m_estimator->data( hypo, ClusterE ) );
-        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedID, m_estimator->data( hypo, CellID ) );
+        using namespace Calo::Future::Enum;
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedSpd,
+                        m_estimator->data( *hypo, DataType::HypoSpdM ).value_or( Default ) > 0 );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedPrs,
+                        m_estimator->data( *hypo, DataType::HypoPrsE ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedEcal,
+                        m_estimator->data( *hypo, DataType::ClusterE ).value_or( Default ) );
+        proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloChargedID,
+                        m_estimator->data( *hypo, DataType::CellID ).value_or( Default ) );
         proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloElectronMatch, hRange.front().weight() );
       }
 
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp
index dfa4acf56db..8dc062cfa49 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp
@@ -31,7 +31,8 @@ StatusCode FutureChargedProtoParticleCALOFUTUREBaseAlg::initialize() {
   if ( sc.isFailure() ) return sc;
 
   counterStat = tool<IFutureCounterLevel>( "FutureCounterLevel" );
-  m_estimator = tool<ICaloFutureHypoEstimator>( "CaloFutureHypoEstimator", "CaloFutureHypoEstimator", this );
+  m_estimator =
+      tool<Calo::Future::Interfaces::IHypoEstimator>( "CaloFutureHypoEstimator", "CaloFutureHypoEstimator", this );
 
   return sc;
 }
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h
index ca217bbd865..4cd07222086 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h
@@ -71,7 +71,7 @@ protected:
 
 protected:
   // Add extra info from CaloDigits (Spd+Prs)
-  ICaloFutureHypoEstimator* m_estimator = nullptr;
+  Calo::Future::Interfaces::IHypoEstimator* m_estimator = nullptr;
 };
 
 #endif // GLOBALRECO_FutureChargedProtoParticleCALOFUTUREBaseAlg_H
diff --git a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp
index 8d31b6ccfe4..88259be1311 100644
--- a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp
+++ b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp
@@ -52,10 +52,11 @@ StatusCode FutureNeutralProtoPAlg::initialize() {
 
   if ( lightMode() ) info() << "FutureNeutral protoparticles will be created in 'Light' Mode" << endmsg;
 
-  m_estimator = tool<ICaloFutureHypoEstimator>( "CaloFutureHypoEstimator", "CaloFutureHypoEstimator", this );
-  m_estimator->hypo2CaloFuture()->_setProperty( "Seed", "false" ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "PhotonLine", "true" ).ignore();
-  m_estimator->hypo2CaloFuture()->_setProperty( "AddNeighbors", "false" ).ignore();
+  m_estimator =
+      tool<Calo::Future::Interfaces::IHypoEstimator>( "CaloFutureHypoEstimator", "CaloFutureHypoEstimator", this );
+  m_estimator->hypo2Calo()->_setProperty( "Seed", "false" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "PhotonLine", "true" ).ignore();
+  m_estimator->hypo2Calo()->_setProperty( "AddNeighbors", "false" ).ignore();
 
   m_mass.clear();
   m_setMass = false;
@@ -69,15 +70,14 @@ double FutureNeutralProtoPAlg::getMass( const int cellCode ) const {
              StatusCode::SUCCESS, 1 )
         .ignore();
     // === storing masses
-    m_setMass = true;
-    using namespace LHCb::CaloHypoLocation;
-    const auto* hypos = getIfExists<LHCb::CaloHypos>( MergedPi0s );
+    m_setMass         = true;
+    const auto* hypos = getIfExists<LHCb::CaloHypos>( LHCb::CaloHypoLocation::MergedPi0s );
     if ( !hypos ) return 0.;
     for ( const auto& hypo : *hypos ) {
       if ( !hypo ) continue;
-      using namespace CaloFutureDataType;
-      const auto cellCode = int( m_estimator->data( hypo, CellID ) );
-      m_mass[cellCode]    = m_estimator->data( hypo, HypoM );
+      using namespace Calo::Future::Enum;
+      const int cellCode = m_estimator->data( *hypo, DataType::CellID ).value_or( Default );
+      m_mass[cellCode]   = m_estimator->data( *hypo, DataType::HypoM ).value_or( Default );
     }
   }
   const auto it = m_mass.find( cellCode );
@@ -137,7 +137,7 @@ StatusCode FutureNeutralProtoPAlg::execute() {
       protos->insert( proto );
 
       // == link CaloHypo to ProtoP
-      using namespace CaloFutureDataType;
+      using namespace Calo::Future::Enum;
       proto->addToCalo( hypo );
 
       // ===== add data to protoparticle
@@ -146,9 +146,9 @@ StatusCode FutureNeutralProtoPAlg::execute() {
         type << hypo->hypothesis();
         const auto hypothesis = type.str();
         // extra data :
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralID, hypo, CellID ); // seed cellID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralID, *hypo, DataType::CellID ); // seed cellID
         // retrieve HypoM for photon
-        const auto cellCode = int( m_estimator->data( hypo, CellID ) );
+        const int cellCode = m_estimator->data( *hypo, DataType::CellID ).value_or( Default );
         if ( hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::Photon ) {
           const auto mass = getMass( cellCode );
           if ( mass > 0. ) {
@@ -156,85 +156,89 @@ StatusCode FutureNeutralProtoPAlg::execute() {
             if ( counterStat->isVerbose() ) counter( "ClusterMass for Photon" ) += mass;
           }
         } else if ( hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::Pi0Merged ) {
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterMass, hypo, HypoM );
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterMass, *hypo, DataType::HypoM );
           m_setMass        = true;
-          m_mass[cellCode] = m_estimator->data( hypo, HypoM );
+          m_mass[cellCode] = m_estimator->data( *hypo, DataType::HypoM ).value_or( Default );
         }
         if ( hypo->hypothesis() != LHCb::CaloHypo::Hypothesis::Pi0Merged ) {
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterAsX, hypo, ClusterAsX, 0 );
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterAsY, hypo, ClusterAsY, 0 );
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterAsX, *hypo, DataType::ClusterAsX, 0 );
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::ClusterAsY, *hypo, DataType::ClusterAsY, 0 );
         }
 
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, hypo, HypoPrsE );
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal, hypo, ClusterE );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, *hypo, DataType::HypoPrsE );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal, *hypo, DataType::ClusterE );
 
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloTrMatch, hypo, ClusterMatch,
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloTrMatch, *hypo, DataType::ClusterMatch,
                   +1.e+06 ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::ShowerShape, hypo,
-                  Spread ); // ** input to neutralID  && isPhoton (as Fr2)
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, hypo, HypoSpdM ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal, hypo,
-                  Hcal2Ecal ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloClusterCode, hypo, ClusterCode );
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloClusterFrac, hypo, ClusterFrac, 1 );
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::Saturation, hypo, Saturation, 0 );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::ShowerShape, *hypo,
+                  DataType::Spread ); // ** input to neutralID  && isPhoton (as Fr2)
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, *hypo,
+                  DataType::HypoSpdM ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal, *hypo,
+                  DataType::Hcal2Ecal ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloClusterCode, *hypo, DataType::ClusterCode );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloClusterFrac, *hypo, DataType::ClusterFrac, 1 );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::Saturation, *hypo, DataType::Saturation, 0 );
 
-        auto dep = ( m_estimator->data( hypo, ToSpdM ) > 0 ) ? -1. : +1.;
-        dep *= m_estimator->data( hypo, ToPrsE );
+        auto dep = ( m_estimator->data( *hypo, DataType::ToSpdM ) > 0 ) ? -1. : +1.;
+        dep *= m_estimator->data( *hypo, DataType::ToPrsE ).value_or( Default );
         proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloDepositID,
                         dep ); // ** input to neutralID toPrsE=|caloDepositID|
 
         // DLL-based neutralID (to be obsolete)  :
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::PhotonID, hypo, NeutralID, -1.,
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::PhotonID, *hypo, DataType::NeutralID, -1.,
                   true ); // old DLL-based neutral-ID // FORCE
 
         // isNotX  inputs :
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE49, hypo, E49 );
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE19, hypo, E19 ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE49, hypo,
-                  PrsE49 ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE19, hypo,
-                  PrsE19 ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE4max, hypo,
-                  PrsE4Max ); // ** input to neutralID
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrsM, hypo,
-                  HypoPrsM ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE49, *hypo, DataType::E49 );
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE19, *hypo,
+                  DataType::E19 ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE49, *hypo,
+                  DataType::PrsE49 ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE19, *hypo,
+                  DataType::PrsE19 ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE4max, *hypo,
+                  DataType::PrsE4Max ); // ** input to neutralID
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrsM, *hypo,
+                  DataType::HypoPrsM ); // ** input to neutralID
         // isNotX output :
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::IsNotH, hypo, isNotH, -1.,
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::IsNotH, *hypo, DataType::isNotH, -1.,
                   true ); // new NN-based neutral-ID (anti-H) // FORCE
-        pushData( proto, LHCb::ProtoParticle::additionalInfo::IsNotE, hypo, isNotE, -1.,
+        pushData( proto, LHCb::ProtoParticle::additionalInfo::IsNotE, *hypo, DataType::isNotE, -1.,
                   true ); // new NN-based neutral-ID (anti-E) // FORCE
 
         // isPhoton inputs (photon & mergedPi0 only)
         if ( hypo->hypothesis() != LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) {
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeFr2r4, hypo,
-                    isPhotonFr2r4 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeAsym, hypo,
-                    isPhotonAsym ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeKappa, hypo,
-                    isPhotonKappa ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE1, hypo,
-                    isPhotonEseed );                                                             // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE2, hypo, isPhotonE2 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeE2, hypo,
-                    isPhotonPrsE2 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeEmax, hypo,
-                    isPhotonPrsEmax ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeFr2, hypo,
-                    isPhotonPrsFr2 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeAsym, hypo,
-                    isPhotonPrsAsym );                                                          // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM, hypo, isPhotonPrsM ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM15, hypo,
-                    isPhotonPrsM15 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM30, hypo,
-                    isPhotonPrsM30 ); // -- input to isPhoton
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM45, hypo,
-                    isPhotonPrsM45 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeFr2r4, *hypo,
+                    DataType::isPhotonFr2r4 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeAsym, *hypo,
+                    DataType::isPhotonAsym ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeKappa, *hypo,
+                    DataType::isPhotonKappa ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE1, *hypo,
+                    DataType::isPhotonEseed ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE2, *hypo,
+                    DataType::isPhotonE2 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeE2, *hypo,
+                    DataType::isPhotonPrsE2 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeEmax, *hypo,
+                    DataType::isPhotonPrsEmax ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeFr2, *hypo,
+                    DataType::isPhotonPrsFr2 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeAsym, *hypo,
+                    DataType::isPhotonPrsAsym ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM, *hypo,
+                    DataType::isPhotonPrsM ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM15, *hypo,
+                    DataType::isPhotonPrsM15 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM30, *hypo,
+                    DataType::isPhotonPrsM30 ); // -- input to isPhoton
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM45, *hypo,
+                    DataType::isPhotonPrsM45 ); // -- input to isPhoton
           // isPhoton output :
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::IsPhoton, hypo, isPhoton, +1.,
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::IsPhoton, *hypo, DataType::isPhoton, +1.,
                     true ); // NN-based neutral-ID (anti-pi0) // FORCE to +1 when missing (i.e. PT < 2 GeV)
-          pushData( proto, LHCb::ProtoParticle::additionalInfo::IsPhotonXGB, hypo, isPhotonXGB, +1.,
+          pushData( proto, LHCb::ProtoParticle::additionalInfo::IsPhotonXGB, *hypo, DataType::isPhotonXGB, +1.,
                     true ); // XGBoost-based neutral-ID (anti-pi0) // FORCE to +1 when missing (i.e. PT < 2 GeV)
         }
       } // lightmode
diff --git a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h
index 4e23f184e96..78d2586abb7 100644
--- a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h
+++ b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h
@@ -68,8 +68,8 @@ private:
   /// use"light" mode? ( suitable fo recalibration purposes)
   inline bool lightMode() const noexcept { return m_light_mode; }
 
-  void pushData( LHCb::ProtoParticle*, LHCb::ProtoParticle::additionalInfo, const LHCb::CaloHypo*,
-                 const CaloFutureDataType::DataType, const double def = CaloFutureDataType::Default,
+  void pushData( LHCb::ProtoParticle*, LHCb::ProtoParticle::additionalInfo, const LHCb::CaloHypo&,
+                 Calo::Future::Enum::DataType, double def = Calo::Future::Enum::Default,
                  const bool force = false ) const;
 
   double getMass( const int cellCode ) const;
@@ -80,20 +80,20 @@ private: // data
   std::string              m_protoLocation;
   std::vector<std::string> m_hyposLocations;
   /// flag to indicate "light/calibration" mode
-  bool                                m_light_mode{false};
-  ICaloFutureHypoEstimator*           m_estimator = nullptr;
-  mutable std::map<const int, double> m_mass      = {{}};
-  mutable bool                        m_setMass{false};
+  bool                                      m_light_mode{false};
+  Calo::Future::Interfaces::IHypoEstimator* m_estimator = nullptr;
+  mutable std::map<const int, double>       m_mass      = {{}};
+  mutable bool                              m_setMass{false};
 };
 
 inline void FutureNeutralProtoPAlg::pushData( LHCb::ProtoParticle* proto, LHCb::ProtoParticle::additionalInfo pflag,
-                                              const LHCb::CaloHypo* hypo, const CaloFutureDataType::DataType hflag,
+                                              const LHCb::CaloHypo& hypo, Calo::Future::Enum::DataType hflag,
                                               const double def, const bool force ) const {
-  const auto data = m_estimator->data( hypo, hflag, def );
+  const auto data = m_estimator->data( hypo, hflag ).value_or( def );
   if ( data != def || force ) {
     proto->addInfo( pflag, data ); // only store when different from default
     std::ostringstream mess;
-    mess << pflag << " for " << hypo->hypothesis();
+    mess << pflag << " for " << hypo.hypothesis();
     counter( mess.str() ) += data;
   }
 }
-- 
GitLab


From 1b28e3c77b5604504a58ef5ea53a829750114d8f Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Fri, 2 Aug 2019 14:48:36 +0200
Subject: [PATCH 2/9] remove (use of) CaloFutureHypoEstimator::toCluster

---
 .../CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp      |  2 +-
 .../CaloFutureTools/src/CaloFutureHypoEstimator.cpp  | 12 +++++-------
 .../CaloFutureTools/src/CaloFutureHypoEstimator.h    |  7 -------
 3 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
index ed44fd74fc1..3e33d3c5039 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp
@@ -140,7 +140,7 @@ void CaloFutureHypoNtp::operator()( const ODIN& odin, const L0& l0, const Hypos&
       ok &= ntp->column( "hypothesis", hypo->hypothesis() );
 
       // kinematics
-      const auto cluster = fixup( m_estimator )->toCluster( ClusterType::SplitOrMain );
+      const auto cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo );
       ok &= ntp->column( "ClusterR", position3d( cluster ) );
       ok &= ntp->column( "HypoR", position3d( hypo ) );
       ok &= ntp->column( "HypoP", momentum( hypo ) );
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index 8cedbf1d40e..57401598d2d 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -112,9 +112,9 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
     double             trajL  = Default;
     const LHCb::Track* etrack = nullptr;
     // LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc);
-    const LHCb::CaloFuture2Track::ITrHypoTable2D* etable = m_tables->getTrHypoTable2D( m_emLoc );
+    const auto* etable = m_tables->getTrHypoTable2D( m_emLoc );
     if ( etable ) {
-      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = etable->inverse()->relations( &hypo );
+      const auto range = etable->inverse()->relations( &hypo );
       if ( !range.empty() ) {
         chi2e  = range.front().weight();
         etrack = range.front();
@@ -138,9 +138,9 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
     double             chi2b  = Default;
     const LHCb::Track* btrack = nullptr;
     // LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc);
-    const LHCb::CaloFuture2Track::ITrHypoTable2D* btable = m_tables->getTrHypoTable2D( m_bmLoc );
+    const auto* btable = m_tables->getTrHypoTable2D( m_bmLoc );
     if ( btable ) {
-      const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = btable->inverse()->relations( &hypo );
+      const auto range = btable->inverse()->relations( &hypo );
       if ( !range.empty() ) {
         chi2b  = range.front().weight();
         btrack = range.front();
@@ -174,9 +174,7 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
     }
   }
   // link 2 cluster :
-  const LHCb::CaloCluster* cluster     = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
-  m_clusters[ClusterType::SplitOrMain] = cluster;
-  m_clusters[ClusterType::Main] = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false ); // get the main cluster
+  const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
 
   // Prs info
   if ( !cluster ) {
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index e370cb0890a..01e70c61601 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -64,12 +64,6 @@ public:
     return it != m_track.end() ? it->second : nullptr;
   }
 
-  const LHCb::CaloCluster*
-  toCluster( Calo::Future::Enum::ClusterType clus = Calo::Future::Enum::ClusterType::SplitOrMain ) const override {
-    auto it = m_clusters.find( clus );
-    return it != m_clusters.end() ? it->second : nullptr;
-  }
-
   StatusCode _setProperty( const std::string& p, const std::string& v ) override { return setProperty( p, v ); };
   bool       status() const override { return m_status; }
 
@@ -84,7 +78,6 @@ private:
 
   mutable caloDataType             m_data;
   mutable caloMatchType            m_track;
-  mutable caloClusterType          m_clusters;
   mutable const LHCb::CaloHypo*    m_hypo    = nullptr;
   mutable const LHCb::CaloCluster* m_cluster = nullptr;
 
-- 
GitLab


From 41cad431aa134dc2cfc9000c22b82e00948d9a5e Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Fri, 2 Aug 2019 15:25:20 +0200
Subject: [PATCH 3/9] follow move of ICaloFutureElectron.h from CaloFutureUtils
 to CaloFutureInterfaces

---
 .../CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h     |  2 +-
 .../CaloFutureMoniDst/src/CaloFutureElectronNtp.h      |  3 ++-
 .../src/CaloFutureProtoElectronMonitor.h               |  2 +-
 .../CaloFutureReco/src/CaloFutureCorrectionBase.h      |  2 +-
 CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp  |  6 +++---
 CaloFuture/CaloFutureTools/src/CaloFutureElectron.h    | 10 +++++-----
 .../CaloFutureTools/src/CaloFutureHypoEstimator.h      |  2 +-
 .../src/FutureChargedProtoParticleAddEcalInfo.h        |  2 +-
 8 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
index c9edf323ed9..46435797bce 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
@@ -26,7 +26,7 @@
 // #include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h"
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
 
 // List of Consumers dependencies
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
index 9981a53b637..34c718b09ef 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
@@ -15,13 +15,14 @@
 #include "CaloDet/DeCalorimeter.h"
 #include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h"
 #include "CaloFutureInterfaces/IFutureCounterLevel.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "Event/ODIN.h"
 #include "Event/ProtoParticle.h"
 #include "Event/RecVertex.h"
 #include "GaudiAlg/Consumer.h"
 #include "GaudiAlg/GaudiTupleAlg.h"
 #include "GaudiKernel/IEventTimeDecoder.h"
+#include "GaudiKernel/Vector4DTypes.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
 
 // List of Consumers dependencies
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
index bea54516dcf..28d938aad80 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
@@ -13,7 +13,7 @@
 
 // Includes
 #include "CaloFutureMoniAlg.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "Event/ProtoParticle.h"
 #include "GaudiAlg/Consumer.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 122fba23e4e..989adbb80cb 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -16,11 +16,11 @@
 #include "CaloFutureDAQ/ICaloFutureDigitFilterTool.h"
 #include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h"
 #include "CaloFutureInterfaces/IFutureCounterLevel.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureUtils/CaloFuture2Track.h"
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
 #include "CaloFutureUtils/ClusterFunctors.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
 #include "DetDesc/Condition.h"
 #include "Event/CaloDigit.h"
 #include "Event/CaloHypo.h"
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
index 7774fdfa10c..e982c890c95 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
@@ -53,7 +53,7 @@ LHCb::CaloHypo* CaloFutureElectron::electron() { return m_electron; }
 LHCb::CaloHypo* CaloFutureElectron::bremstrahlung() { return m_bremstrahlung; }
 //=============================================================================
 LHCb::CaloMomentum CaloFutureElectron::bremCaloFutureMomentum() {
-  if ( !m_status || NULL == m_bremstrahlung ) return LHCb::CaloMomentum();
+  if ( !m_status || !m_bremstrahlung ) return LHCb::CaloMomentum();
   Gaudi::XYZPoint     point;
   Gaudi::SymMatrix3x3 matrix;
   m_track->position( point, matrix );
@@ -64,12 +64,12 @@ LHCb::CaloMomentum CaloFutureElectron::bremCaloFutureMomentum() {
 //=============================================================================
 double CaloFutureElectron::ecalE() {
   if ( !m_status ) return 0.;
-  return (double)m_electron->e();
+  return m_electron->e();
 }
 //=============================================================================
 double CaloFutureElectron::eOverP() {
   if ( !m_status ) return 0.;
-  return (double)m_electron->e() / m_track->p();
+  return m_electron->e() / m_track->p();
 }
 //=============================================================================
 LHCb::State CaloFutureElectron::closestState( std::string toWhat ) {
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
index be905e58992..f191f6b5d97 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
@@ -16,7 +16,7 @@
 
 // from LHCb
 #include "CaloFutureUtils/CaloMomentum.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 
 // Forward declarations
 namespace LHCb {
@@ -34,10 +34,10 @@ public:
   /// Standard constructor
   CaloFutureElectron( const std::string& type, const std::string& name, const IInterface* parent );
 
-  bool set( const LHCb::Particle* particle, std::string det = DeCalorimeterLocation::Ecal,
-            CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0 ) override;
-  bool set( const LHCb::ProtoParticle* proto, std::string det = DeCalorimeterLocation::Ecal,
-            CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0 ) override;
+  bool set( const LHCb::Particle* particle, std::string det ,
+            CaloPlane::Plane plane, double delta  ) override;
+  bool set( const LHCb::ProtoParticle* proto, std::string det,
+            CaloPlane::Plane plane , double delta  ) override;
 
   LHCb::CaloHypo*    electron() override;
   LHCb::CaloHypo*    bremstrahlung() override;
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index 01e70c61601..04ac4003f1b 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -23,7 +23,7 @@
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
 #include "CaloFutureUtils/ClusterFunctors.h"
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "Event/CaloDataFunctor.h"
 #include "Event/Track.h"
 #include "GaudiAlg/GaudiTool.h"
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
index f3c84b3e5e1..39111c2d12c 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
@@ -21,7 +21,7 @@
 #ifndef GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H
 #define GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H 1
 
-#include "CaloFutureUtils/ICaloFutureElectron.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h"
 
 /** @class FutureChargedProtoParticleAddEcalInfo FutureChargedProtoParticleAddEcalInfo.h
-- 
GitLab


From 75be18fec87e6236ff23a5ce6a01f0ceb9396b99 Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Fri, 2 Aug 2019 20:51:47 +0200
Subject: [PATCH 4/9] Follow concatention of ITrack2CaloFuture,
 IPart2CaloFuture and ICaloFutureElectron interfaces

---
 Calo/CaloMoniDst/src/CaloMoniAlg.cpp          |  12 +-
 .../src/CaloFutureAlignmentNtp.cpp            |  31 ++-
 .../src/CaloFutureAlignmentNtp.h              |   4 +-
 .../src/CaloFutureElectronNtp.cpp             |  16 +-
 .../src/CaloFutureElectronNtp.h               |  11 +-
 .../src/CaloFutureMoniAlg.cpp                 |  12 +-
 .../src/CaloFutureProtoElectronMonitor.cpp    |  28 +--
 .../src/CaloFutureProtoElectronMonitor.h      |   6 +-
 .../src/CaloFutureCorrectionBase.cpp          |  12 +-
 .../src/CaloFutureCorrectionBase.h            |   4 +-
 .../src/CaloFutureElectron.cpp                | 228 +++++++++++-------
 .../CaloFutureTools/src/CaloFutureElectron.h  |  62 -----
 .../src/CaloFutureHypoEstimator.cpp           |   2 +-
 .../src/CaloFutureHypoEstimator.h             |   8 +-
 .../CaloFutureTools/src/Part2CaloFuture.cpp   |  62 -----
 .../CaloFutureTools/src/Part2CaloFuture.h     |  54 -----
 .../CaloFutureTools/src/Track2CaloFuture.cpp  | 150 ------------
 .../CaloFutureTools/src/Track2CaloFuture.h    |  71 ------
 .../FutureChargedProtoParticleAddEcalInfo.cpp |   9 +-
 .../FutureChargedProtoParticleAddEcalInfo.h   |   5 +-
 20 files changed, 217 insertions(+), 570 deletions(-)
 delete mode 100644 CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
 delete mode 100644 CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp
 delete mode 100644 CaloFuture/CaloFutureTools/src/Part2CaloFuture.h
 delete mode 100644 CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp
 delete mode 100644 CaloFuture/CaloFutureTools/src/Track2CaloFuture.h

diff --git a/Calo/CaloMoniDst/src/CaloMoniAlg.cpp b/Calo/CaloMoniDst/src/CaloMoniAlg.cpp
index cc62a038224..29116551282 100644
--- a/Calo/CaloMoniDst/src/CaloMoniAlg.cpp
+++ b/Calo/CaloMoniDst/src/CaloMoniAlg.cpp
@@ -100,7 +100,7 @@ void CaloMoniAlg::fillCounters( std::string unit ) const {
   } else if ( m_split ) {
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloCellCode::CaloAreaFromNum( CaloCellCode::CaloNumFromName( m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) || m_mcount[i] == 0 ) continue;
       GaudiAlg::HistoID id( area + "/" + unit );
       fill( m_h1[id], m_mcount[i], 1 );
@@ -129,7 +129,7 @@ void CaloMoniAlg::hBook1( const std::string hid, const std::string titl, const d
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Booking histogram1D per calo area" << endmsg;
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloCellCode::CaloAreaFromNum( CaloCellCode::CaloNumFromName( m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       std::string       tit = titl + " (" + area + ")";
@@ -155,7 +155,7 @@ void CaloMoniAlg::h1binLabel( const std::string hid, int bin, std::string label
   } else if ( m_split ) {
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloCellCode::CaloAreaFromNum( CaloCellCode::CaloNumFromName( m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       const auto        th = Gaudi::Utils::Aida2ROOT::aida2root( m_h1[id] );
@@ -183,7 +183,7 @@ void CaloMoniAlg::hBook2( const std::string hid, const std::string titl, const d
   } else if ( m_split ) {
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Booking histogram2D per calo region" << endmsg;
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       std::string       tit = titl + " (" + area + ")";
@@ -258,7 +258,7 @@ void CaloMoniAlg::hFill1( LHCb::CaloCellID cellID, std::string hid, double value
     if ( hh == nullptr ) return;
     fill( hh, value, w );
   } else if ( m_split && !( cellID == LHCb::CaloCellID() ) ) {
-    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), cellID.area() );
+    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), cellID.area() );
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Filling histogram2D per calo region " << cellID << endmsg;
     if ( validArea( area ) ) {
       if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "valid area " << area << endmsg;
@@ -302,7 +302,7 @@ void CaloMoniAlg::hFill2( LHCb::CaloCellID cellID, std::string hid, double x, do
     fill( hh, x, y, w );
   } else if ( m_split && !( cellID == LHCb::CaloCellID() ) ) {
     // std::string area = CaloCellCode::CaloAreaFromNum( CaloCellCode::CaloNumFromName( m_detData ), cellID.area() );
-    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), cellID.area() );
+    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), cellID.area() );
     if ( validArea( area ) ) {
       GaudiAlg::HistoID id( area + "/" + hid );
       const auto        hh = m_h2[id];
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp
index f4ba9b6e710..8fc258cbbf3 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp
@@ -73,8 +73,7 @@ StatusCode CaloFutureAlignmentNtp::initialize() {
 
   // Get & retrieve & configure tools
   m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
-  if ( !( m_counterStat.retrieve() && m_caloElectron.retrieve() && m_odin.retrieve() && m_toSpd.retrieve() &&
-          m_toPrs.retrieve() && m_extrapolator.retrieve() ) ) {
+  if ( !( m_toSpd.retrieve() && m_toPrs.retrieve() ) ) {
     error() << "Unable to retrive one of the ToolHandles" << endmsg;
     return StatusCode::FAILURE;
   }
@@ -166,12 +165,12 @@ void CaloFutureAlignmentNtp::operator()( const Vertices& verts, const ODIN& odin
     if ( m_counterStat->isQuiet() ) counter( "3-selected tracks" ) += 1;
 
     // 4: Validate hypo
-    const auto hypo = fixup( m_caloElectron )->electron();
+    const auto hypo = m_caloElectron->electron();
     if ( !hypoProcessing( hypo ) ) continue;
     if ( m_counterStat->isQuiet() ) counter( "4-selected hypos" ) += 1;
 
     // 5: Validate electron
-    const auto eOp = fixup( m_caloElectron )->eOverP();
+    const auto eOp = m_caloElectron->eOverP();
     if ( !inRange( m_eop, eOp ) ) continue;
     if ( !inRange( m_dlle, proto->info( LHCb::ProtoParticle::additionalInfo::CombDLLe, 9999. ) ) ) continue;
     if ( !inRange( m_rdlle, proto->info( LHCb::ProtoParticle::additionalInfo::RichDLLe, 9999. ) ) ) continue;
@@ -185,19 +184,19 @@ void CaloFutureAlignmentNtp::operator()( const Vertices& verts, const ODIN& odin
     const auto id      = cluster->seed();
     const auto hypoR   = position3d( hypo );
     const auto clusR   = position3d( cluster );
-    const auto statR   = position3d( fixup( m_caloElectron )->caloState() );
-    const auto closR   = position3d( fixup( m_caloElectron )->closestState() );
-    const auto cs      = momentum( fixup( m_caloElectron )->caloState() );
-    const auto theta   = fixup( m_caloElectron )->caloState().momentum().Theta();
+    const auto statR   = position3d( m_caloElectron->caloState() );
+    const auto closR   = position3d( m_caloElectron->closestState() );
+    const auto cs      = momentum( m_caloElectron->caloState() );
+    const auto theta   = m_caloElectron->caloState().momentum().Theta();
     const auto t       = momentum( track );
-    const auto brem    = fixup( m_caloElectron )->bremstrahlung();
+    const auto brem    = m_caloElectron->bremstrahlung();
     const auto hasBrem = ( brem != nullptr );
     if ( m_brem && !hasBrem ) continue; // is Brem explicitly requested
 
     const Gaudi::XYZPoint cellR( m_calo->cellX( id ), m_calo->cellY( id ), m_calo->cellZ( id ) ); // seed position
 
     // Bremstrahllung
-    const auto bP       = momentum( fixup( m_caloElectron )->bremCaloFutureMomentum() );
+    const auto bP       = momentum( m_caloElectron->bremCaloFutureMomentum() );
     const auto bremR    = position3d( brem );
     const auto bcluster = firstCluster( brem );
     const auto bid      = bcluster->seed();
@@ -217,10 +216,10 @@ void CaloFutureAlignmentNtp::operator()( const Vertices& verts, const ODIN& odin
         const auto proto2 = *pp;
         if ( !fixup( m_caloElectron )->set( proto2 ) ) continue;
         ;
-        const auto hypo2 = fixup( m_caloElectron )->electron();
+        const auto hypo2 = m_caloElectron->electron();
         if ( hypo == hypo2 ) continue;
         if ( !hypoProcessing( hypo2 ) ) continue;
-        const auto eOp2 = fixup( m_caloElectron )->eOverP();
+        const auto eOp2 = m_caloElectron->eOverP();
         if ( !inRange( m_eop, eOp2 ) ) continue;
         if ( !inRange( m_dlle, proto2->info( LHCb::ProtoParticle::additionalInfo::CombDLLe, 0. ) ) ) continue;
         if ( !inRange( m_rdlle, proto2->info( LHCb::ProtoParticle::additionalInfo::RichDLLe, 0. ) ) ) continue;
@@ -275,10 +274,10 @@ void CaloFutureAlignmentNtp::operator()( const Vertices& verts, const ODIN& odin
       ntp->column( "TrackR", statR );
       ntp->column( "ClosestR", closR );
       ntp->column( "caloState", cs );
-      ntp->column( "caloStateErrX", sqrt( fixup( m_caloElectron )->caloState().covariance()( 0, 0 ) ) );
-      ntp->column( "caloStateErrY", sqrt( fixup( m_caloElectron )->caloState().covariance()( 1, 1 ) ) );
-      ntp->column( "caloStateErrTX", sqrt( fixup( m_caloElectron )->caloState().covariance()( 2, 2 ) ) );
-      ntp->column( "caloStateErrTY", sqrt( fixup( m_caloElectron )->caloState().covariance()( 3, 3 ) ) );
+      ntp->column( "caloStateErrX", sqrt( m_caloElectron->caloState().covariance()( 0, 0 ) ) );
+      ntp->column( "caloStateErrY", sqrt( m_caloElectron->caloState().covariance()( 1, 1 ) ) );
+      ntp->column( "caloStateErrTX", sqrt( m_caloElectron->caloState().covariance()( 2, 2 ) ) );
+      ntp->column( "caloStateErrTY", sqrt( m_caloElectron->caloState().covariance()( 3, 3 ) ) );
       ntp->column( "incidence", theta );
       // cluster info
       ntp->column( "id", id.index() );
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
index 46435797bce..0b79cc41b35 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h
@@ -24,9 +24,9 @@
 #include "GaudiAlg/GaudiTupleAlg.h"
 #include "GaudiKernel/IEventTimeDecoder.h"
 // #include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
-#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
 
 // List of Consumers dependencies
@@ -73,7 +73,7 @@ private:
   std::string    m_vertLoc;
 
   ToolHandle<IFutureCounterLevel>                  m_counterStat{"FutureCounterLevel"};
-  ToolHandle<ICaloFutureElectron>                  m_caloElectron{"CaloFutureElectron", this};
+  ToolHandle<Calo::Future::Interfaces::IElectron>  m_caloElectron{"CaloFutureElectron", this};
   ToolHandle<IEventTimeDecoder>                    m_odin{"OdinTimeDecoder/OdinDecoder", this};
   ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
   ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp
index 8794581493c..dc48e791529 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp
@@ -85,8 +85,8 @@ StatusCode CaloFutureElectronNtp::initialize() {
 // Note, extra flag count to count at the specific place. Because this method
 // is used on both first-electron, and second-electron, the counting should only
 // be enabled in the first one only.
-bool CaloFutureElectronNtp::set_and_validate( ICaloFutureElectron& caloElectron, const LHCb::ProtoParticle* proto,
-                                              bool count ) const {
+bool CaloFutureElectronNtp::set_and_validate( Calo::Future::Interfaces::IElectron& caloElectron,
+                                              const LHCb::ProtoParticle* proto, bool count ) const {
   // abort if fail to set
   if ( !caloElectron.set( proto ) ) return false;
   // counting
@@ -163,17 +163,17 @@ void CaloFutureElectronNtp::operator()( const ODIN& odin, const Protos& protos,
     // Retrieve info for tuple
     const auto ePrs         = proto->info( LHCb::ProtoParticle::additionalInfo::CaloPrsE, 0. );
     const auto track1       = proto->track();
-    const auto hypo         = fixup( m_caloElectron ).electron();
+    const auto hypo         = m_caloElectron->electron();
     const auto iSpd         = (int)fixup( m_toSpd ).multiplicity( *hypo, "Spd" );
     const auto track1mmt    = momentum( track1 );
     const auto caloCluster  = firstCluster( hypo );
     const auto caloCellId   = caloCluster->seed();
-    const auto caloState    = fixup( m_caloElectron ).caloState();
+    const auto caloState    = m_caloElectron->caloState();
     const auto caloStateMmt = momentum( caloState );
-    const auto brem         = fixup( m_caloElectron ).bremstrahlung();
+    const auto brem         = m_caloElectron->bremstrahlung();
     const auto bremCellId   = firstCluster( brem )->seed();
-    const auto bremMmt      = momentum( fixup( m_caloElectron ).bremCaloFutureMomentum() );
-    const auto eOp          = fixup( m_caloElectron ).eOverP();
+    const auto bremMmt      = momentum( m_caloElectron->bremCaloFutureMomentum() );
+    const auto eOp          = m_caloElectron->eOverP();
     const auto e            = LHCb::CaloMomentum( hypo ).e();
 
     // dielectron filter
@@ -183,7 +183,7 @@ void CaloFutureElectronNtp::operator()( const ODIN& odin, const Protos& protos,
         const auto proto2 = *pp;
         if ( !set_and_validate( fixup( m_caloElectron ), proto2 ) ) continue;
         // abort if same pair (shouldn't happen)
-        const auto hypo2 = fixup( m_caloElectron ).electron();
+        const auto hypo2 = m_caloElectron->electron();
         if ( hypo == hypo2 ) continue;
         // Need opposite charge
         const auto t1 = proto->track();
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
index 34c718b09ef..76342fce050 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h
@@ -13,9 +13,9 @@
 
 // Include files
 #include "CaloDet/DeCalorimeter.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h"
 #include "CaloFutureInterfaces/IFutureCounterLevel.h"
-#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "Event/ODIN.h"
 #include "Event/ProtoParticle.h"
 #include "Event/RecVertex.h"
@@ -48,19 +48,14 @@ public:
   StatusCode initialize() override;
   void       operator()( const ODIN&, const Protos&, const Vertices& ) const override;
 
-  /// C++11 non-copyable idiom
-  CaloFutureElectronNtp()                               = delete;
-  CaloFutureElectronNtp( const CaloFutureElectronNtp& ) = delete;
-  CaloFutureElectronNtp& operator=( const CaloFutureElectronNtp& ) = delete;
-
 private:
   DeCalorimeter* m_calo = nullptr;
   std::string    m_vertLoc;
 
   mutable std::mutex                               m_badtoolmutex;
   ToolHandle<IFutureCounterLevel>                  m_counterStat{"FutureCounterLevel"};
-  ToolHandle<ICaloFutureElectron>                  m_caloElectron{"CaloFutureElectron", this};
   ToolHandle<IEventTimeDecoder>                    m_odin{"OdinTimeDecoder/OdinDecoder", this};
+  ToolHandle<Calo::Future::Interfaces::IElectron>  m_caloElectron{"CaloFutureElectron", this};
   ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this};
   ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this};
   ToolHandle<ITrackExtrapolator>                   m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
@@ -81,7 +76,7 @@ private:
   Gaudi::Property<std::vector<int>> m_tracks{
       this, "TrackTypes", {LHCb::Track::Types::Long, LHCb::Track::Types::Downstream}};
 
-  bool   set_and_validate( ICaloFutureElectron& caloElectron, const LHCb::ProtoParticle* proto,
+  bool   set_and_validate( Calo::Future::Interfaces::IElectron& caloElectron, const LHCb::ProtoParticle* proto,
                            bool count = false ) const;
   double invar_mass_squared( const LHCb::Track* t1, const LHCb::Track* t2 ) const;
   void   fillH( double eOp, Gaudi::LorentzVector t, LHCb::CaloCellID id, std::string hat = "" ) const;
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp
index 06a564c43ee..f84166d7685 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp
@@ -102,7 +102,7 @@ void CaloFutureMoniAlg::fillFutureCounters( std::string unit ) const {
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName(
       // m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) || m_mcount[i] == 0 ) continue;
       GaudiAlg::HistoID id( area + "/" + unit );
       fill( m_h1[id], m_mcount[i], 1 );
@@ -132,7 +132,7 @@ void CaloFutureMoniAlg::hBook1( const std::string hid, const std::string titl, c
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName(
       // m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       std::string       tit = titl + " (" + area + ")";
@@ -159,7 +159,7 @@ void CaloFutureMoniAlg::h1binLabel( const std::string hid, int bin, std::string
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
       // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName(
       // m_detData ), i );
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       const auto        th = Gaudi::Utils::Aida2ROOT::aida2root( m_h1[id] );
@@ -187,7 +187,7 @@ void CaloFutureMoniAlg::hBook2( const std::string hid, const std::string titl, c
   } else if ( m_split ) {
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Booking histogram2D per calo region" << endmsg;
     for ( unsigned int i = 0; i != m_nAreas; ++i ) {
-      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), i );
+      std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), i );
       if ( !validArea( area ) ) continue;
       GaudiAlg::HistoID id( area + "/" + hid );
       std::string       tit = titl + " (" + area + ")";
@@ -262,7 +262,7 @@ void CaloFutureMoniAlg::hFill1( LHCb::CaloCellID cellID, std::string hid, double
     if ( hh == nullptr ) return;
     fill( hh, value, w );
   } else if ( m_split && !( cellID == LHCb::CaloCellID() ) ) {
-    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), cellID.area() );
+    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), cellID.area() );
     if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Filling histogram2D per calo region " << cellID << endmsg;
     if ( validArea( area ) ) {
       if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "valid area " << area << endmsg;
@@ -307,7 +307,7 @@ void CaloFutureMoniAlg::hFill2( LHCb::CaloCellID cellID, std::string hid, double
   } else if ( m_split && !( cellID == LHCb::CaloCellID() ) ) {
     // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName(
     // m_detData ), cellID.area() );
-    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData ), cellID.area() );
+    std::string area = CaloCellCode::caloArea( CaloCellCode::caloNum( m_detData.value() ), cellID.area() );
     if ( validArea( area ) ) {
       GaudiAlg::HistoID id( area + "/" + hid );
       const auto        hh = m_h2[id];
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp
index b637a841b0b..4cc8d31851d 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp
@@ -59,12 +59,6 @@ StatusCode CaloFutureProtoElectronMonitor::initialize() {
   else
     info() << "Will look at any track type" << endmsg;
 
-  // Get, retrieve, configure tools
-  if ( !( m_caloElectron.retrieve() && m_extrapolator.retrieve() ) ) {
-    error() << "Unable to retrive one of the ToolHandles" << endmsg;
-    return StatusCode::FAILURE;
-  }
-
   // histograms
   hBook1( "1", "# of CaloElectron protoP   " + inputLocation(), m_multMin, m_multMax, m_multBin );
   hBook1( "2", "CaloElectron protoP Energy   " + inputLocation(), m_energyMin, m_energyMax, m_energyBin );
@@ -114,8 +108,8 @@ void CaloFutureProtoElectronMonitor::operator()( const Input& protos ) const {
     if ( !fixup( m_caloElectron )->set( proto ) ) continue;
 
     // Abort if null hypo
-    const auto hypo = fixup( m_caloElectron )->electron();
-    if ( hypo == nullptr ) continue;
+    const auto hypo = m_caloElectron->electron();
+    if ( !hypo ) continue;
 
     // Abort if energy too low
     LHCb::CaloMomentum momentum( hypo );
@@ -128,18 +122,18 @@ void CaloFutureProtoElectronMonitor::operator()( const Input& protos ) const {
 
     // Retrieve the seed id
     auto id = LHCb::CaloCellID();
-    if ( hypo->clusters().size() > 0 ) {
-      SmartRef<LHCb::CaloCluster> cluster = *( hypo->clusters().begin() );
-      id                                  = cluster->seed();
+    if ( !hypo->clusters().empty() ) {
+      const auto& cluster = *( hypo->clusters().begin() );
+      id                  = cluster->seed();
     }
-    double eOp = fixup( m_caloElectron )->eOverP();
+    double eOp = m_caloElectron->eOverP();
 
     // Fill histograms
     count( id );
     hFill1( id, "2", e );
     hFill1( id, "3", et );
     const auto position = hypo->position();
-    if ( position != nullptr ) {
+    if ( position ) {
       hFill2( id, "4", position->x(), position->y() );
       hFill2( id, "5", position->x(), position->y(), e );
     }
@@ -165,8 +159,8 @@ void CaloFutureProtoElectronMonitor::operator()( const Input& protos ) const {
       // Abort if fail hypo, or duplicate
       if ( !fixup( m_caloElectron )->set( proto2 ) ) continue;
       ;
-      const auto hypo2 = fixup( m_caloElectron )->electron();
-      if ( hypo2 == nullptr ) continue;
+      const auto hypo2 = m_caloElectron->electron();
+      if ( !hypo2 ) continue;
       if ( hypo == hypo2 ) continue;
 
       // filtering proto2
@@ -186,7 +180,7 @@ void CaloFutureProtoElectronMonitor::operator()( const Input& protos ) const {
       // Validate tracks
       const auto t1 = proto->track();
       const auto t2 = proto2->track();
-      if ( t1 == nullptr || t2 == nullptr ) continue;
+      if ( !t1 || !t2 ) continue;
       if ( t1->charge() * t2->charge() != -1 ) continue;
       auto st1 = t1->firstState();
       auto st2 = t2->firstState();
@@ -216,7 +210,7 @@ void CaloFutureProtoElectronMonitor::operator()( const Input& protos ) const {
       hFill1( id, "9", caloM );
       if ( m2 < m_massFilterMax ) {
         hFill1( id, "10", eOp );
-        const double eOp2 = fixup( m_caloElectron )->eOverP();
+        const double eOp2 = m_caloElectron->eOverP();
         hFill1( id, "10", eOp2 );
       }
     }
diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
index 28d938aad80..4462fba4f05 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h
@@ -12,8 +12,8 @@
 #define CALOFUTUREPROTOELECTRONMONITOR_H 1
 
 // Includes
-#include "CaloFutureMoniAlg.h"
 #include "CaloFutureInterfaces/ICaloFutureElectron.h"
+#include "CaloFutureMoniAlg.h"
 #include "Event/ProtoParticle.h"
 #include "GaudiAlg/Consumer.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
@@ -42,8 +42,8 @@ public:
   CaloFutureProtoElectronMonitor& operator=( const CaloFutureProtoElectronMonitor& ) = delete;
 
 private:
-  ToolHandle<ICaloFutureElectron> m_caloElectron{"CaloFutureElectron", this};
-  ToolHandle<ITrackExtrapolator>  m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
+  ToolHandle<Calo::Future::Interfaces::IElectron> m_caloElectron{"CaloFutureElectron", this};
+  ToolHandle<ITrackExtrapolator>                  m_extrapolator{"TrackRungeKuttaExtrapolator/Extrapolator", this};
 
   bool valid_track( const LHCb::ProtoParticle* proto ) const;
 
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index e4378c83ac1..830d6faa024 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -67,7 +67,7 @@ StatusCode CaloFutureCorrectionBase::initialize() {
   }
 
   // get external tools
-  m_caloElectron = tool<ICaloFutureElectron>( "CaloFutureElectron", this );
+  m_caloElectron = tool<Calo::Future::Interfaces::IElectron>( "CaloFutureElectron", this );
   m_pileup       = tool<ICaloFutureDigitFilterTool>( "CaloFutureDigitFilterTool", "FilterTool" );
   m_tables       = tool<ICaloFutureRelationsGetter>( "CaloFutureRelationsGetter", "CaloFutureRelationsGetter", this );
   counterStat    = tool<IFutureCounterLevel>( "FutureCounterLevel" );
@@ -337,11 +337,11 @@ double CaloFutureCorrectionBase::incidence( const LHCb::CaloHypo* hypo, bool str
       if ( !range.empty() ) {
         const LHCb::Track* ctrack = range.front();
         // temporary protoParticle
-        auto* proto = new LHCb::ProtoParticle();
-        proto->setTrack( ctrack );
-        proto->addToCalo( hypo );
-        if ( m_caloElectron->set( proto ) ) { incidence = m_caloElectron->caloState().momentum().Theta(); }
-        delete proto;
+        LHCb::ProtoParticle tmp;
+        tmp.setTrack( ctrack );
+        tmp.addToCalo( hypo );
+        if ( m_caloElectron->set( &tmp ) ) { incidence = m_caloElectron->caloState().momentum().Theta(); }
+        m_caloElectron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
       }
     }
   } else {
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 989adbb80cb..b2e9a256c04 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -14,9 +14,9 @@
 // Include files
 #include "CaloDet/DeCalorimeter.h"
 #include "CaloFutureDAQ/ICaloFutureDigitFilterTool.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h"
 #include "CaloFutureInterfaces/IFutureCounterLevel.h"
-#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureUtils/CaloFuture2Track.h"
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
@@ -304,7 +304,7 @@ private:
     return static_cast<CaloFutureCorrection::Type>( CaloFutureCorrection::lastType );
   }
 
-  ICaloFutureElectron* m_caloElectron = nullptr;
+  Calo::Future::Interfaces::IElectron* m_caloElectron = nullptr;
 
   bool accept( const std::string& name ) {
     return std::any_of( m_corrections.begin(), m_corrections.end(),
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
index e982c890c95..97da0bf17a7 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp
@@ -10,96 +10,157 @@
 \*****************************************************************************/
 // Include files
 
-// LHCb
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
+#include "CaloFutureUtils/CaloMomentum.h"
+#include "Event/CaloCluster.h"
+#include "Event/CaloHypo.h"
 #include "Event/Particle.h"
+#include "Event/ProtoParticle.h"
+#include "Event/Track.h"
+#include "GaudiAlg/GaudiTool.h"
 #include "GaudiKernel/Point3DTypes.h"
 #include "GaudiKernel/Vector3DTypes.h"
+#include "Kernel/TrackDefaultParticles.h"
+#include "LHCbMath/GeomFun.h"
+#include "LHCbMath/Line.h"
+#include "TrackInterfaces/ITrackExtrapolator.h"
+#include "TrackKernel/TrackFunctors.h"
 
-// local
-#include "CaloFutureElectron.h"
+/** @class CaloFutureElectron CaloFutureElectron.h
+ *
+ *
+ *  @author Olivier Deschamps
+ *  @date   2006-11-30
+ */
+class CaloFutureElectron final : public extends<GaudiTool, Calo::Future::Interfaces::IElectron> {
+public:
+  /// Standard constructor
+  using extends::extends;
 
-//-----------------------------------------------------------------------------
-// Implementation file for class : CaloFutureElectron
-//
-// 2006-11-30 : Olivier Deschamps
-//-----------------------------------------------------------------------------
+  StatusCode initialize() override;
+
+  bool set( LHCb::ProtoParticle const* proto, std::string const& det, CaloPlane::Plane plane, double delta ) override;
+
+  LHCb::State           caloState() const override { return m_state; }
+  LHCb::State           closestState() const override;
+  LHCb::CaloHypo const* electron() const override { return m_electron; }
+  LHCb::CaloHypo const* bremstrahlung() const override { return m_bremstrahlung; }
+  LHCb::CaloMomentum    bremCaloFutureMomentum() const override;
+  double                eOverP() const override { return m_status ? m_electron->e() / m_track->p() : 0.; }
+  double                caloTrajectoryL( CaloPlane::Plane plane ) const override;
+
+private:
+  LHCb::State caloState( CaloPlane::Plane plane, double delta = 0 ) const;
+
+  // configuration-dependent state
+  ITrackExtrapolator*          m_extrapolator = nullptr;
+  Gaudi::Property<std::string> m_extrapolatorType{this, "ExtrapolatorType", "TrackRungeKuttaExtrapolator"};
+  Gaudi::Property<float>       m_tolerance{this, "Tolerance", 0.01};
+
+  // call-dependent state -- set by 'set', and afterwards const -- so could be returned as data from 'set'...
+  bool                  m_status        = false;
+  const LHCb::Track*    m_track         = nullptr;
+  const LHCb::CaloHypo* m_electron      = nullptr;
+  const LHCb::CaloHypo* m_bremstrahlung = nullptr;
+  LHCb::State           m_state;
+  DeCalorimeter*        m_calo = nullptr;
+};
 
 // Declaration of the Tool Factory
 DECLARE_COMPONENT( CaloFutureElectron )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-CaloFutureElectron::CaloFutureElectron( const std::string& type, const std::string& name, const IInterface* parent )
-    : base_class( type, name, parent ) {
-  declareInterface<ICaloFutureElectron>( this );
-}
+namespace {
+  // fix name clash with Track2Calo::closestState
+  decltype( auto ) closest_state( const LHCb::Track& t, const Gaudi::Plane3D& p ) { return closestState( t, p ); }
+} // namespace
 
 //=============================================================================
-bool CaloFutureElectron::set( const LHCb::Particle* particle, std::string det, CaloPlane::Plane plane, double delta ) {
-  m_status = setting( particle ) && caloSetting();
-  if ( m_status ) return Part2CaloFuture::match( particle, det, plane, delta );
-  return m_status;
+StatusCode CaloFutureElectron::initialize() {
+  StatusCode sc = extends::initialize();
+  if ( sc.isFailure() ) return Error( "Failed to initialize", sc );
+  m_extrapolator = tool<ITrackExtrapolator>( m_extrapolatorType, "Extrapolator", this );
+  return StatusCode::SUCCESS;
 }
-bool CaloFutureElectron::set( const LHCb::ProtoParticle* proto, std::string det, CaloPlane::Plane plane,
+//=============================================================================
+bool CaloFutureElectron::set( LHCb::ProtoParticle const* proto, std::string const& det, CaloPlane::Plane plane,
                               double delta ) {
-  m_status = setting( proto ) && caloSetting();
-  if ( m_status ) return Part2CaloFuture::match( proto, det, plane, delta );
+  m_electron      = nullptr;
+  m_bremstrahlung = nullptr;
+  m_calo          = nullptr;
+  m_state         = {};
+  m_track         = proto ? proto->track() : nullptr;
+
+  m_status = ( m_track != nullptr );
+  if ( !m_status ) return false;
+
+  for ( const LHCb::CaloHypo* hypo : proto->calo() ) {
+    if ( !hypo ) continue;
+    switch ( hypo->hypothesis() ) {
+    case LHCb::CaloHypo::Hypothesis::EmCharged:
+      m_electron = hypo;
+      break;
+    case LHCb::CaloHypo::Hypothesis::Photon:
+      m_bremstrahlung = hypo;
+      break;
+    default:; // nothing;
+    }
+  }
+  m_status = ( m_electron && m_electron->position() ); // Electron hypo is mandatory - brem. not
+  if ( !m_status ) return false;
+
+  m_calo  = getDet<DeCalorimeter>( det );
+  m_state = caloState( plane, delta );
+  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
+    debug() << " CaloFutureElectron setting [" << *m_track << "," << det << "] status : " << m_status << endmsg;
   return m_status;
 }
 //=============================================================================
-LHCb::CaloHypo* CaloFutureElectron::electron() { return m_electron; }
-//=============================================================================
-LHCb::CaloHypo* CaloFutureElectron::bremstrahlung() { return m_bremstrahlung; }
-//=============================================================================
-LHCb::CaloMomentum CaloFutureElectron::bremCaloFutureMomentum() {
-  if ( !m_status || !m_bremstrahlung ) return LHCb::CaloMomentum();
+LHCb::CaloMomentum CaloFutureElectron::bremCaloFutureMomentum() const {
+  if ( !m_status || !m_bremstrahlung ) return {};
   Gaudi::XYZPoint     point;
   Gaudi::SymMatrix3x3 matrix;
   m_track->position( point, matrix );
-  LHCb::CaloMomentum bremPhoton( m_bremstrahlung, point, matrix );
-  return bremPhoton;
+  return {m_bremstrahlung, point, matrix};
 }
 
 //=============================================================================
-double CaloFutureElectron::ecalE() {
-  if ( !m_status ) return 0.;
-  return m_electron->e();
-}
-//=============================================================================
-double CaloFutureElectron::eOverP() {
-  if ( !m_status ) return 0.;
-  return m_electron->e() / m_track->p();
-}
-//=============================================================================
-LHCb::State CaloFutureElectron::closestState( std::string toWhat ) {
-  LHCb::State state; // empty state
-  if ( !m_status ) return state;
+LHCb::State CaloFutureElectron::closestState() const {
+  if ( !m_status ) return {};
+
+  // get state on Front of Ecal
+  LHCb::State calostate = caloState( CaloPlane::Front );
+  if ( calostate.z() == 0 ) return {};
+
+  // get frontPlane
+  ROOT::Math::Plane3D frontPlane = m_calo->plane( CaloPlane::Front );
+
   // get hypo position
-  double x = 0.;
-  double y = 0.;
-  if ( "hypo" == toWhat ) {
-    x = m_calopos->parameters()( LHCb::CaloPosition::Index::X );
-    y = m_calopos->parameters()( LHCb::CaloPosition::Index::Y );
-  } else if ( "cluster" == toWhat ) {
-    x = m_calopos->center()( LHCb::CaloPosition::Index::X );
-    y = m_calopos->center()( LHCb::CaloPosition::Index::Y );
-  } else {
-    return state;
-  }
+  const auto& params = m_electron->position()->parameters();
+  double      x      = params( LHCb::CaloPosition::Index::X );
+  double      y      = params( LHCb::CaloPosition::Index::Y );
+
+  // Define calo line (from transversal barycenter) and track line in Ecal
+  Gaudi::XYZVector  normal = frontPlane.Normal();
+  double            zEcal  = ( -normal.X() * x - normal.Y() * y - frontPlane.HesseDistance() ) / normal.Z(); // tilt
+  Gaudi::XYZPoint   point{x, y, zEcal};
+  Gaudi::Math::Line cLine{point, frontPlane.Normal()};
+  Gaudi::Math::Line tLine{calostate.position(), calostate.slopes()};
+
+  // Find points of closest distance between calo Line and track Line
+  Gaudi::XYZPoint cP, tP;
+  Gaudi::Math::closestPoints( cLine, tLine, cP, tP );
+
   // default to electron
-  LHCb::Tr::PID pid = ( m_particle ? LHCb::Tr::PID( m_particle->particleID().abspid() ) : LHCb::Tr::PID::Electron() );
-  return Part2CaloFuture::closestState( x, y, pid );
-}
-//=============================================================================
-double CaloFutureElectron::caloTrajectoryZ( CaloPlane::Plane refPlane, std::string toWhat ) {
-  LHCb::State theState = closestState( toWhat );
-  LHCb::State refState = caloState( refPlane );
-  return m_zOffset + theState.z() - refState.z();
+  auto pid = LHCb::Tr::PID::Electron();
+  // propagate the state the new Z of closest distance
+  StatusCode sc = m_extrapolator->propagate( calostate, tP.Z(), pid );
+
+  if ( sc.isFailure() ) return {};
+  return calostate;
 }
 //=============================================================================
-double CaloFutureElectron::caloTrajectoryL( CaloPlane::Plane refPlane, std::string toWhat ) {
-  LHCb::State         theState = closestState( toWhat );
+double CaloFutureElectron::caloTrajectoryL( CaloPlane::Plane refPlane ) const {
+  LHCb::State         theState = closestState();
   LHCb::State         refState = caloState( refPlane );
   Gaudi::XYZVector    depth    = theState.position() - refState.position();
   ROOT::Math::Plane3D plane    = m_calo->plane( refPlane );
@@ -108,23 +169,24 @@ double CaloFutureElectron::caloTrajectoryL( CaloPlane::Plane refPlane, std::stri
 }
 
 //=============================================================================
-bool CaloFutureElectron::caloSetting() {
-  // CaloFuture setting
-  m_electron      = NULL;
-  m_bremstrahlung = NULL;
-  m_calopos       = NULL;
-
-  SmartRefVector<LHCb::CaloHypo> hypos = m_proto->calo();
-  if ( 0 == hypos.size() ) return false;
-
-  for ( SmartRefVector<LHCb::CaloHypo>::const_iterator ihypo = hypos.begin(); ihypo != hypos.end(); ++ihypo ) {
-    const LHCb::CaloHypo* hypo = *ihypo;
-    if ( NULL == hypo ) continue;
-    if ( LHCb::CaloHypo::Hypothesis::EmCharged == hypo->hypothesis() ) m_electron = (LHCb::CaloHypo*)hypo;
-    if ( LHCb::CaloHypo::Hypothesis::Photon == hypo->hypothesis() ) m_bremstrahlung = (LHCb::CaloHypo*)hypo;
-  }
-  if ( NULL == m_electron ) return false; // Electron hypo is mandatory - brem. not
-  m_calopos = m_electron->position();
-  if ( NULL == m_calopos ) return false;
-  return true;
+LHCb::State CaloFutureElectron::caloState( CaloPlane::Plane plane, double delta ) const {
+  if ( !m_status ) return {};
+
+  // get caloPlane
+  ROOT::Math::Plane3D refPlane = m_calo->plane( plane );
+  // propagate state to refPlane
+  const LHCb::Tr::PID pid       = LHCb::Tr::PID::Pion();
+  LHCb::State         calostate = closest_state( *m_track, refPlane );
+  StatusCode          sc        = m_extrapolator->propagate( calostate, refPlane, m_tolerance, pid );
+  if ( sc.isFailure() ) return {};
+
+  if ( 0. == delta ) return calostate;
+
+  Gaudi::XYZVector dir( calostate.tx(), calostate.ty(), 1. );
+  Gaudi::XYZPoint  point = calostate.position() + delta * dir / dir.R();
+  // extrapolate to the new point
+  sc = m_extrapolator->propagate( calostate, point.z(), pid );
+  if ( sc.isFailure() ) return {};
+  return calostate;
 }
+//=============================================================================
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
deleted file mode 100644
index f191f6b5d97..00000000000
--- a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-#ifndef CALOFUTUREELECTRON_H
-#define CALOFUTUREELECTRON_H 1
-
-// Include files
-#include "Part2CaloFuture.h"
-
-// from LHCb
-#include "CaloFutureUtils/CaloMomentum.h"
-#include "CaloFutureInterfaces/ICaloFutureElectron.h"
-
-// Forward declarations
-namespace LHCb {
-  class ProtoParticle;
-}
-
-/** @class CaloFutureElectron CaloFutureElectron.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2006-11-30
- */
-class CaloFutureElectron : public extends<Part2CaloFuture, ICaloFutureElectron> {
-public:
-  /// Standard constructor
-  CaloFutureElectron( const std::string& type, const std::string& name, const IInterface* parent );
-
-  bool set( const LHCb::Particle* particle, std::string det ,
-            CaloPlane::Plane plane, double delta  ) override;
-  bool set( const LHCb::ProtoParticle* proto, std::string det,
-            CaloPlane::Plane plane , double delta  ) override;
-
-  LHCb::CaloHypo*    electron() override;
-  LHCb::CaloHypo*    bremstrahlung() override;
-  LHCb::CaloMomentum bremCaloFutureMomentum() override;
-  double             ecalE() override;
-  double             eOverP() override;
-  using ICaloFutureElectron::closestState;
-  LHCb::State closestState( std::string toWhat = "hypo" ) override;
-  double      caloTrajectoryZ( CaloPlane::Plane refPlane = CaloPlane::ShowerMax, std::string toWhat = "hypo" ) override;
-  double      caloTrajectoryL( CaloPlane::Plane refPlane = CaloPlane::ShowerMax, std::string toWhat = "hypo" ) override;
-
-protected:
-  bool caloSetting();
-
-private:
-  LHCb::CaloHypo*           m_electron      = nullptr;
-  LHCb::CaloHypo*           m_bremstrahlung = nullptr;
-  const LHCb::CaloPosition* m_calopos       = nullptr;
-  Gaudi::Property<float>    m_zOffset{this, "zOffset", 0,
-                                   "Should be 0.0 if ShowerMax plane is correctly defined in condDB"};
-};
-#endif // CALOFUTUREELECTRON_H
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index 57401598d2d..70a1fcd3fd0 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -123,7 +123,7 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
           dummy.setTrack( etrack );
           dummy.addToCalo( &hypo );
           // CaloFutureElectron->caloTrajectory must be after addToCalo
-          if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax, "hypo" );
+          if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax );
           m_electron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
         }
       }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index 04ac4003f1b..66cf9f5ae83 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -14,6 +14,7 @@
 // Include files
 // from Gaudi
 #include "CaloDet/DeCalorimeter.h"
+#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" // Interface
 #include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h"
 #include "CaloFutureInterfaces/IFutureCounterLevel.h"
@@ -23,7 +24,6 @@
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/CaloMomentum.h"
 #include "CaloFutureUtils/ClusterFunctors.h"
-#include "CaloFutureInterfaces/ICaloFutureElectron.h"
 #include "Event/CaloDataFunctor.h"
 #include "Event/Track.h"
 #include "GaudiAlg/GaudiTool.h"
@@ -103,9 +103,9 @@ private:
   Gaudi::Property<bool>        m_skipN{this, "SkipNeutralID", false};
   Gaudi::Property<bool>        m_skipCl{this, "SkipClusterMatch", false};
 
-  PublicToolHandle<IFutureCounterLevel>             counterStat{this, "CounterLevel", "FutureCounterLevel"};
-  ToolHandle<Calo::Future::Interfaces::IHypo2Calo>  m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
-  mutable ToolHandle<ICaloFutureElectron>           m_electron{this, "Electron", "CaloFutureElectron"};
+  PublicToolHandle<IFutureCounterLevel>            counterStat{this, "CounterLevel", "FutureCounterLevel"};
+  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
+  mutable ToolHandle<Calo::Future::Interfaces::IElectron> m_electron{this, "Electron", "CaloFutureElectron"};
   mutable ToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0{this, "Pi0Separation", "FutureGammaPi0SeparationTool"};
   mutable PublicToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0XGB{this, "PiOSeparation",
                                                                         "FutureGammaPi0XGBoostTool"};
diff --git a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp
deleted file mode 100644
index 5da36678605..00000000000
--- a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-// Include files
-
-// from LHCb
-#include "Event/Particle.h"
-#include "Kernel/TrackDefaultParticles.h"
-// local
-#include "Part2CaloFuture.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Part2CaloFuture
-//
-// 2006-11-30 : Olivier Deschamps
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( Part2CaloFuture )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Part2CaloFuture::Part2CaloFuture( const std::string& type, const std::string& name, const IInterface* parent )
-    : Track2CaloFuture( type, name, parent ), m_particle( NULL ), m_proto( NULL ) {
-  declareInterface<IPart2CaloFuture>( this );
-}
-
-//=============================================================================
-bool Part2CaloFuture::match( const LHCb::Particle* part, std::string det, CaloPlane::Plane plane, double delta ) {
-  m_status = setting( part );
-  if ( m_status )
-    return Track2CaloFuture::match( m_track, det, plane, delta, LHCb::Tr::PID( m_particle->particleID().abspid() ) );
-  return m_status;
-}
-//=============================================================================
-bool Part2CaloFuture::match( const LHCb::ProtoParticle* proto, std::string det, CaloPlane::Plane plane, double delta ) {
-  m_status = setting( proto );
-  if ( m_status ) return Track2CaloFuture::match( m_track, det, plane, delta );
-  return m_status;
-}
-//=============================================================================
-bool Part2CaloFuture::setting( const LHCb::Particle* particle ) {
-  m_particle = particle;
-  if ( NULL == m_particle ) return false;
-  const LHCb::ProtoParticle* proto = m_particle->proto();
-  return setting( proto );
-}
-//=============================================================================
-bool Part2CaloFuture::setting( const LHCb::ProtoParticle* proto ) {
-  m_proto = proto;
-  if ( NULL == m_proto ) return false;
-  return Track2CaloFuture::setting( m_proto->track() );
-}
-//=============================================================================
diff --git a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h
deleted file mode 100644
index 86242d94c79..00000000000
--- a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-#ifndef PART2CALOFUTURE_H
-#define PART2CALOFUTURE_H 1
-
-// Include files
-#include "Event/ProtoParticle.h"
-#include "Track2CaloFuture.h"
-// from Gaudi
-#include "CaloFutureInterfaces/IPart2CaloFuture.h"
-
-/** @class Part2CaloFuture Part2CaloFuture.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2006-11-30
- */
-class Part2CaloFuture : public Track2CaloFuture, virtual public IPart2CaloFuture {
-public:
-  /// Standard constructor
-  Part2CaloFuture( const std::string& type, const std::string& name, const IInterface* parent );
-
-  using Track2CaloFuture::match;
-  bool match( const LHCb::ProtoParticle* proto, std::string det = DeCalorimeterLocation::Ecal,
-              CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0. ) override;
-  bool match( const LHCb::Particle* part, std::string det = DeCalorimeterLocation::Ecal,
-              CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0. ) override;
-  bool inAcceptance() override {
-    if ( m_det == DeCalorimeterLocation::Spd )
-      return m_proto->info( LHCb::ProtoParticle::additionalInfo::InAccSpd, 0. ) != 0;
-    if ( m_det == DeCalorimeterLocation::Prs )
-      return m_proto->info( LHCb::ProtoParticle::additionalInfo::InAccPrs, 0. ) != 0;
-    if ( m_det == DeCalorimeterLocation::Ecal )
-      return m_proto->info( LHCb::ProtoParticle::additionalInfo::InAccEcal, 0. ) != 0;
-    if ( m_det == DeCalorimeterLocation::Hcal )
-      return m_proto->info( LHCb::ProtoParticle::additionalInfo::InAccHcal, 0. ) != 0;
-    return false;
-  }
-
-protected:
-  bool                       setting( const LHCb::Particle* part );
-  bool                       setting( const LHCb::ProtoParticle* proto );
-  const LHCb::Particle*      m_particle;
-  const LHCb::ProtoParticle* m_proto;
-};
-#endif // PART2CALOFUTURE_H
diff --git a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp
deleted file mode 100644
index 3fdb3dced33..00000000000
--- a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-// Include files
-
-// LHCb
-#include "Event/CaloCluster.h"
-#include "Event/CaloHypo.h"
-#include "Event/Track.h"
-#include "GaudiKernel/Point3DTypes.h"
-#include "GaudiKernel/Vector3DTypes.h"
-#include "LHCbMath/GeomFun.h"
-#include "LHCbMath/Line.h"
-#include "TrackInterfaces/ITrackExtrapolator.h"
-#include "TrackKernel/TrackFunctors.h"
-
-// local
-#include "Track2CaloFuture.h"
-
-namespace {
-
-  // fix name clash with Track2Calo::closestState
-  auto closest_state( const LHCb::Track& t, const Gaudi::Plane3D& p ) { return closestState( t, p ); }
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : Track2CaloFuture
-//
-// Simple tool to propagate track to Calo reference planes
-//
-// 2007-06-25 : Olivier Deschamps
-//-----------------------------------------------------------------------------
-
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( Track2CaloFuture )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-Track2CaloFuture::Track2CaloFuture( const std::string& type, const std::string& name, const IInterface* parent )
-    : GaudiTool( type, name, parent ) {
-  declareInterface<ITrack2CaloFuture>( this );
-}
-
-//=============================================================================
-StatusCode Track2CaloFuture::initialize() {
-  StatusCode sc = GaudiTool::initialize();
-  if ( sc.isFailure() ) return Error( "Failed to initialize", sc );
-  m_extrapolator = tool<ITrackExtrapolator>( m_extrapolatorType, "Extrapolator", this );
-  return StatusCode::SUCCESS;
-}
-//=============================================================================
-bool Track2CaloFuture::match( const LHCb::Track* track, std::string det, CaloPlane::Plane plane, double delta,
-                              const LHCb::Tr::PID pid ) {
-  m_status = setting( track );
-  m_det    = det;
-  m_calo   = getDet<DeCalorimeter>( det );
-  m_state  = caloState( plane, delta, pid );
-  m_cell   = m_calo->Cell( m_state.position() );
-  m_valid  = m_calo->valid( m_cell );
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
-    debug() << " Track2CaloFuture setting [" << *track << "," << det << "] status : " << m_status << endmsg;
-  return m_status;
-}
-//=============================================================================
-LHCb::State Track2CaloFuture::caloState( CaloPlane::Plane plane, double delta, const LHCb::Tr::PID pid ) {
-
-  LHCb::State state; // empty state
-  if ( !m_status ) return state;
-
-  // get caloPlane
-  ROOT::Math::Plane3D refPlane = m_calo->plane( plane );
-  // propagate state to refPlane
-  LHCb::State calostate( closest_state( *m_track, refPlane ) );
-  StatusCode  sc = m_extrapolator->propagate( calostate, refPlane, m_tolerance, pid );
-  if ( sc.isFailure() ) return state;
-
-  if ( 0. == delta ) return calostate;
-
-  Gaudi::XYZVector dir( calostate.tx(), calostate.ty(), 1. );
-  Gaudi::XYZPoint  point = calostate.position() + delta * dir / dir.R();
-  // extrapolate to the new point
-  sc = m_extrapolator->propagate( calostate, point.z(), pid );
-  if ( sc.isFailure() ) return state;
-  return calostate;
-}
-//=============================================================================
-bool Track2CaloFuture::setting( const LHCb::Track* track ) {
-  m_track = track;
-  return m_track != nullptr;
-}
-
-LHCb::State Track2CaloFuture::closestState( LHCb::CaloCluster* cluster, const LHCb::Tr::PID pid ) {
-  return closestState( cluster->position(), pid );
-}
-
-LHCb::State Track2CaloFuture::closestState( LHCb::CaloHypo* hypo, const LHCb::Tr::PID pid ) {
-  LHCb::State         state; // emtpy state
-  LHCb::CaloPosition* calopos = hypo->position();
-  if ( calopos == NULL ) return state;
-  return closestState( *calopos, pid );
-}
-LHCb::State Track2CaloFuture::closestState( LHCb::CaloPosition calopos, const LHCb::Tr::PID pid ) {
-  double x = calopos.parameters()( LHCb::CaloPosition::Index::X );
-  double y = calopos.parameters()( LHCb::CaloPosition::Index::Y );
-  return closestState( x, y, pid );
-}
-LHCb::State Track2CaloFuture::closestState( LHCb::CaloCellID cellID, const LHCb::Tr::PID pid ) {
-  Gaudi::XYZPoint point = m_calo->cellCenter( cellID );
-  return closestState( point.X(), point.Y(), pid );
-}
-
-//=============================================================================
-LHCb::State Track2CaloFuture::closestState( double x, double y, const LHCb::Tr::PID pid ) {
-  LHCb::State state; // empty state
-  if ( !m_status ) return state;
-
-  // get state on Front of Ecal
-  LHCb::State calostate = caloState( CaloPlane::Front );
-  if ( calostate.z() == 0 ) return state;
-
-  // get frontPlane
-  ROOT::Math::Plane3D frontPlane = m_calo->plane( CaloPlane::Front );
-
-  // Define calo line (from transversal barycenter) and track line in Ecal
-  typedef Gaudi::Math::Line<Gaudi::XYZPoint, Gaudi::XYZVector> Line;
-  Gaudi::XYZVector                                             normal = frontPlane.Normal();
-  double          zEcal = ( -normal.X() * x - normal.Y() * y - frontPlane.HesseDistance() ) / normal.Z(); // tilt
-  Gaudi::XYZPoint point( x, y, zEcal );
-  Line            cLine( point, frontPlane.Normal() );
-  Line            tLine( calostate.position(), calostate.slopes() );
-
-  // Find points of closest distance between calo Line and track Line
-  Gaudi::XYZPoint cP, tP;
-  Gaudi::Math::closestPoints<Line, Line, Gaudi::XYZPoint>( cLine, tLine, cP, tP );
-
-  // propagate the state the new Z of closest distance
-  StatusCode sc = m_extrapolator->propagate( calostate, tP.Z(), pid );
-
-  if ( sc.isFailure() ) return state;
-  return calostate;
-}
diff --git a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h
deleted file mode 100644
index 5a46b2167e1..00000000000
--- a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-#ifndef TRACK2CALOFUTURE_H
-#define TRACK2CALOFUTURE_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiTool.h"
-// from LHCb
-#include "CaloFutureInterfaces/ITrack2CaloFuture.h"
-#include "Event/Track.h"
-
-// Forward declarations
-struct ITrackExtrapolator;
-namespace LHCb {}
-
-/** @class Track2CaloFuture Track2CaloFuture.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2006-11-30
- */
-class Track2CaloFuture : public GaudiTool, virtual public ITrack2CaloFuture {
-public:
-  /// Standard constructor
-  Track2CaloFuture( const std::string& type, const std::string& name, const IInterface* parent );
-
-  StatusCode initialize() override;
-
-  bool match( const LHCb::Track* track, std::string det = DeCalorimeterLocation::Ecal,
-              CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0.,
-              const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) override;
-
-  LHCb::State      caloState() override { return m_state; };
-  LHCb::CaloCellID caloCellID() override { return m_cell; };
-  bool             isValid() override { return m_valid; };
-
-  // Closest State
-  LHCb::State closestState( LHCb::CaloHypo* hypo, const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) override;
-  LHCb::State closestState( LHCb::CaloCluster* cluster, const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) override;
-  LHCb::State closestState( LHCb::CaloPosition calopos, const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) override;
-  LHCb::State closestState( LHCb::CaloCellID cellID, const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) override;
-  const LHCb::Track* track() override { return m_track; };
-
-protected:
-  LHCb::State        closestState( double x, double y, const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() );
-  LHCb::State        caloState( CaloPlane::Plane plane = CaloPlane::ShowerMax, double delta = 0,
-                                const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() );
-  bool               setting( const LHCb::Track* track );
-  bool               m_status = false;
-  const LHCb::Track* m_track  = nullptr;
-  LHCb::State        m_state;
-  DeCalorimeter*     m_calo = nullptr;
-  std::string        m_det;
-
-private:
-  ITrackExtrapolator*          m_extrapolator = nullptr;
-  Gaudi::Property<std::string> m_extrapolatorType{this, "ExtrapolatorType", "TrackRungeKuttaExtrapolator"};
-  Gaudi::Property<float>       m_tolerance{this, "Tolerance", 0.01};
-  LHCb::CaloCellID             m_cell;
-  bool                         m_valid = false;
-};
-#endif // TRACK2CALOFUTURE_H
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
index 2330d38ff4f..e76fef34f52 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp
@@ -66,8 +66,7 @@ StatusCode FutureChargedProtoParticleAddEcalInfo::initialize() {
   if ( sc.isFailure() ) return sc;
 
   // CaloElectron tool
-  // m_electron = tool<ICaloElectron>("CaloElectron","CaloElectron",this);
-  m_electron = tool<ICaloFutureElectron>( "CaloFutureElectron", "CaloFutureElectron", this );
+  m_electron = tool<Calo::Future::Interfaces::IElectron>( "CaloFutureElectron", "CaloFutureElectron", this );
 
   return sc;
 }
@@ -143,10 +142,10 @@ bool FutureChargedProtoParticleAddEcalInfo::addEcal( LHCb::ProtoParticle* proto
         const auto* hypo = hRange.front().to();
         proto->addToCalo( hypo );
         // CaloElectron->caloTrajectory must be after addToCalo
-        if ( electronTool()->set( proto ) ) {
+        if ( m_electron->set( proto ) ) {
           proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloTrajectoryL,
-                          electronTool()->caloTrajectoryL( CaloPlane::ShowerMax, "hypo" ) );
-          proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloEoverP, electronTool()->eOverP() );
+                          m_electron->caloTrajectoryL( CaloPlane::ShowerMax ) );
+          proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloEoverP, m_electron->eOverP() );
         }
 
         using namespace Calo::Future::Enum;
diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
index 39111c2d12c..8b5582b3df3 100644
--- a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
+++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h
@@ -48,9 +48,6 @@ private:
   /// Add Calo Ecal information to the given ProtoParticle
   bool addEcal( LHCb::ProtoParticle* proto ) const;
 
-  /// Access the electron tool
-  inline ICaloFutureElectron* electronTool() const noexcept { return m_electron; }
-
 private:
   std::string m_protoPath; ///< Location of the ProtoParticles in the TES
 
@@ -73,7 +70,7 @@ private:
   const LHCb::CaloFuture2Track::ITrEvalTable*   m_dllmuEcalTable = nullptr;
 
   /// CaloElectron tool
-  ICaloFutureElectron* m_electron = nullptr;
+  Calo::Future::Interfaces::IElectron* m_electron = nullptr;
 };
 
 #endif // GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H
-- 
GitLab


From 37a31191bea08c77682167174e79e238a6b0b269 Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Sun, 4 Aug 2019 12:36:07 +0200
Subject: [PATCH 5/9] remove unused CaloFutureGetterInit

---
 .../src/CaloFutureGetterInit.cpp              | 61 -------------------
 .../CaloFutureReco/src/CaloFutureGetterInit.h | 39 ------------
 2 files changed, 100 deletions(-)
 delete mode 100644 CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp
 delete mode 100644 CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp
deleted file mode 100644
index 44a6ef3c07a..00000000000
--- a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-// Include files
-
-// local
-#include "CaloFutureGetterInit.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : CaloFutureGetterInit
-//
-// 2009-04-17 : Olivier Deschamps
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( CaloFutureGetterInit )
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode CaloFutureGetterInit::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;              // error printed already by GaudiAlgorithm
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Initialize" << endmsg;
-
-  m_getter = tool<ICaloFutureGetterTool>( "CaloFutureGetterTool", m_name );
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode CaloFutureGetterInit::execute() {
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Execute" << endmsg;
-
-  m_getter->update();
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode CaloFutureGetterInit::finalize() {
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
-
-  return GaudiAlgorithm::finalize(); // must be called after all other actions
-}
-
-//=============================================================================
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h
deleted file mode 100644
index 2b0dbbaa93e..00000000000
--- a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-#ifndef CALOFUTUREGETTERINIT_H
-#define CALOFUTUREGETTERINIT_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiAlgorithm.h"
-// from LHCb
-#include "CaloFutureInterfaces/ICaloFutureGetterTool.h"
-
-/** @class CaloFutureGetterInit CaloFutureGetterInit.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2009-04-17
- */
-class CaloFutureGetterInit : public GaudiAlgorithm {
-public:
-  /// Standard constructor
-  using GaudiAlgorithm::GaudiAlgorithm;
-
-  StatusCode initialize() override; ///< Algorithm initialization
-  StatusCode execute() override;    ///< Algorithm execution
-  StatusCode finalize() override;   ///< Algorithm finalization
-
-private:
-  ICaloFutureGetterTool*       m_getter = nullptr;
-  Gaudi::Property<std::string> m_name{this, "ToolName", "CaloFutureGetter"};
-};
-#endif // CALOFUTUREGETTERINIT_H
-- 
GitLab


From 595767ce0ab89a1490479744a70864e1ba006a72 Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Sun, 4 Aug 2019 14:38:10 +0200
Subject: [PATCH 6/9] remove unneccessary CaloFutureGetterTool

---
 .../python/CaloFutureReco/Configuration.py    |  12 -
 .../src/CaloFutureClusterCovarianceAlg.h      |  20 +-
 .../src/CaloFuture2CaloFuture.cpp             |  26 +-
 .../src/CaloFuture2CaloFuture.h               |  10 +-
 .../src/CaloFutureGetterTool.cpp              | 236 ------------------
 .../src/CaloFutureGetterTool.h                | 140 -----------
 .../src/CaloFutureHypo2CaloFuture.cpp         |   3 +-
 7 files changed, 20 insertions(+), 427 deletions(-)
 delete mode 100644 CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp
 delete mode 100644 CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h

diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py
index a803dc6fd7b..df0d231cdaa 100644
--- a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py
+++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py
@@ -351,12 +351,6 @@ class CaloFutureRecoConf(LHCbConfigurableUser):
             self.mergedPi0s()
             self.electrons()
 
-        # configure the public getter tool
-        from Configurables import ToolSvc, CaloFutureGetterTool
-        tsvc = ToolSvc()
-        tsvc.addTool(CaloFutureGetterTool, name="CaloFutureGetter")
-        tsvc.CaloFutureGetter.DetectorMask = 12
-
         self.setCounterLevel()
 
         # add only the requested components to the sequence
@@ -643,12 +637,6 @@ class CaloFutureProcessor(CaloFutureRecoConf, LHCbConfigurableUser):
                 'Context', 'Offline'
             )  # default is Offline is neither context nor name is specified
 
-        # configure the public getter tool
-        from Configurables import ToolSvc, CaloFutureGetterTool
-        tsvc = ToolSvc()
-        tsvc.addTool(CaloFutureGetterTool, name="CaloFutureGetter")
-        tsvc.CaloFutureGetter.DetectorMask = 12
-
         self.setCounterLevel()
         # overwrite Reco & PID onDemand
         dod = self.getProp('EnableOnDemand')
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h
index 116ac226a70..7b612523988 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h
@@ -61,23 +61,9 @@ public:
                                                                                                  ///< execution
 
 protected:
-  inline ICaloFutureClusterTool*       cov() const { return m_cov; }
-  inline ICaloFutureClusterTool*       spread() const { return m_spread; }
-  inline FutureSubClusterSelectorTool* tagger() const { return m_tagger; }
-
-private:
-  /// default constructor is private
-  CaloFutureClusterCovarianceAlg();
-
-  /** copy constructor is private
-   *  @param copy object to be copied
-   */
-  CaloFutureClusterCovarianceAlg( const CaloFutureClusterCovarianceAlg& copy );
-
-  /** assignement operator is private
-   *  @param copy object to be copied
-   */
-  CaloFutureClusterCovarianceAlg& operator=( const CaloFutureClusterCovarianceAlg& copy );
+  ICaloFutureClusterTool*       cov() const { return m_cov; }
+  ICaloFutureClusterTool*       spread() const { return m_spread; }
+  FutureSubClusterSelectorTool* tagger() const { return m_tagger; }
 
 private:
   // CHECK if needed for CaloFuture
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
index f50f9c9749b..7522f335b40 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
@@ -37,16 +37,13 @@ StatusCode CaloFuture2CaloFuture::initialize() {
   StatusCode sc = base_class::initialize();
   if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Initialize CaloFuture2CaloFuture tool " << endmsg;
 
-  // get getter tool : public tool
-  m_getter = tool<ICaloFutureGetterTool>( "CaloFutureGetterTool", m_getterName );
-
   // CaloDigit locations
   m_loc["Ecal"] = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Ecal" );
   m_loc["Hcal"] = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Hcal" );
   m_loc["Prs"]  = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Prs" );
   m_loc["Spd"]  = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Spd" );
   // DeCalorimeter* pointers
-  int mask      = m_getter->detectorsMask();
+  int mask      = m_detMask.value();
   m_det["Ecal"] = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
   m_det["Hcal"] = getDet<DeCalorimeter>( DeCalorimeterLocation::Hcal );
   m_det["Prs"]  = ( ( mask & 2 ) == 0 ) ? nullptr : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Prs );
@@ -230,39 +227,39 @@ CaloFuture2CaloFuture::cellIDs( const LHCb::CaloCellID& fromId, const std::strin
 // Digits
 const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCellID& fromId,
                                                                     const std::string&      toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_digits;
 }
 
 const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCluster& fromCluster,
                                                                     const std::string&       toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_digits;
 }
 
 // Energy
 double CaloFuture2CaloFuture::energy( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_energy;
 }
 
 int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCellID& fromId, const std::string& toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromId, toCaloFuture );
   return m_count;
 }
 
 double CaloFuture2CaloFuture::energy( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_energy;
 }
 
 int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster, const std::string& toCaloFuture ) const {
-  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = m_getter->digits( m_toLoc );
+  const_cast<CaloFuture2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
   cellIDs( fromCluster, toCaloFuture );
   return m_count;
 }
@@ -270,10 +267,11 @@ int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster, c
 // ============================================================================
 // Additional method : isLocalMax
 bool CaloFuture2CaloFuture::isLocalMax( const LHCb::CaloDigit& digit ) const {
-  const LHCb::CaloCellID& id     = digit.cellID();
-  std::string             calo   = CaloCellCode::CaloNameFromNum( id.calo() );
-  DeCalorimeter*          det    = const_cast<CaloFuture2CaloFuture*>( this )->m_det[calo];
-  const LHCb::CaloDigits* digits = m_getter->digits( const_cast<CaloFuture2CaloFuture*>( this )->m_loc[calo] );
+  const LHCb::CaloCellID& id   = digit.cellID();
+  std::string             calo = CaloCellCode::CaloNameFromNum( id.calo() );
+  DeCalorimeter*          det  = const_cast<CaloFuture2CaloFuture*>( this )->m_det[calo];
+  const LHCb::CaloDigits* digits =
+      getIfExists<LHCb::CaloDigits>( const_cast<CaloFuture2CaloFuture*>( this )->m_loc[calo] );
   //
   return LHCb::CaloFutureDataFunctor::isLocalMax( &digit, det, digits );
 }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
index b1406c901ed..246a13c7816 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h
@@ -15,7 +15,6 @@
 // from Gaudi
 #include "CaloDet/DeCalorimeter.h"
 #include "CaloFutureInterfaces/ICaloFuture2CaloFuture.h" // Interface
-#include "CaloFutureInterfaces/ICaloFutureGetterTool.h"
 #include "GaudiAlg/GaudiTool.h"
 /** @class CaloFuture2CaloFuture CaloFuture2CaloFuture.h
  *
@@ -77,12 +76,11 @@ protected:
   double                                m_toSize   = 0.;
   std::string                           m_toLoc;
   Gaudi::Plane3D                        m_toPlane;
-  LHCb::CaloDigits*                     m_digs   = nullptr;
-  ICaloFutureGetterTool*                m_getter = nullptr;
-  mutable bool                          m_ok     = true;
+  LHCb::CaloDigits*                     m_digs = nullptr;
+  mutable bool                          m_ok   = true;
 
 private:
-  Gaudi::Property<bool>        m_geo{this, "IdealGeometry", true};
-  Gaudi::Property<std::string> m_getterName{this, "GetterName", "CaloFutureGetter"};
+  Gaudi::Property<bool> m_geo{this, "IdealGeometry", true};
+  Gaudi::Property<int>  m_detMask{this, "DetectorMask", 0x8 + 0x4};
 };
 #endif // CALOFUTURE2CALOFUTURE_H
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp
deleted file mode 100644
index 717b19f44d0..00000000000
--- a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-// ============================================================================
-// Include files
-// ============================================================================
-// from Gaudi
-// ============================================================================
-#include "CaloFutureUtils/CaloFutureAlgUtils.h"
-#include "GaudiKernel/IIncidentSvc.h"
-#include "GaudiKernel/Incident.h"
-// ============================================================================
-// local
-// ============================================================================
-#include "CaloFutureGetterTool.h"
-// ============================================================================
-/** @file
- *  Implementation file for class : CaloFutureGetterTool
- *
- *  @date 2009-04-17
- *  @author Olivier Deschamps
- */
-// ============================================================================
-// Declaration of the Tool Factory
-DECLARE_COMPONENT( CaloFutureGetterTool )
-// ============================================================================
-// Standard constructor, initializes variables
-// ============================================================================
-CaloFutureGetterTool::CaloFutureGetterTool( const std::string& type, const std::string& name, const IInterface* parent )
-    : base_class( type, name, parent ) {
-  declareInterface<ICaloFutureGetterTool>( this );
-
-  // digits
-  if ( ( m_detMask & 8 ) != 0 )
-    m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Hcal" ) );
-  if ( ( m_detMask & 4 ) != 0 )
-    m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Ecal" ) );
-  if ( ( m_detMask & 2 ) != 0 )
-    m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Prs" ) );
-  if ( ( m_detMask & 1 ) != 0 )
-    m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Spd" ) );
-
-  if ( ( m_detMask & 8 ) != 0 )
-    m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( "Hcal" ) );
-  if ( ( m_detMask & 4 ) != 0 )
-    m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( "Ecal" ) );
-  m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureSplitClusterLocation() );
-
-  m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "Photons" ) );
-  m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "Electrons" ) );
-  m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "SplitPhotons" ) );
-  m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "MergedPi0s" ) );
-}
-
-// ============================================================================
-
-StatusCode CaloFutureGetterTool::initialize() {
-  StatusCode sc = base_class::initialize();
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Initialize CaloFuture2CaloFuture tool " << endmsg;
-
-  counterStat = tool<IFutureCounterLevel>( "FutureCounterLevel" );
-
-  if ( m_detMask != 0xF )
-    info() << "Incomplete calorimeter detector is requested - mask = " << m_detMask.value() << endmsg;
-
-  // subscribe to the incidents
-  IIncidentSvc* inc = incSvc();
-  if ( 0 != inc ) {
-    inc->addListener( this, IncidentType::BeginEvent );
-    inc->addListener( this, IncidentType::EndEvent );
-  }
-  // prepare the known locations:
-  //
-  // digits
-  if ( m_digiUpd ) {
-    m_digits.clear();
-    for ( std::vector<std::string>::iterator iloc = m_digiLoc.begin(); m_digiLoc.end() != iloc; ++iloc ) {
-      m_digits[*iloc] = 0;
-    }
-  }
-  // clusters
-  if ( m_clusUpd ) {
-    m_clusters.clear();
-    for ( std::vector<std::string>::iterator iloc = m_clusLoc.begin(); m_clusLoc.end() != iloc; ++iloc ) {
-      m_clusters[*iloc] = 0;
-    }
-  }
-  // hypos
-  if ( m_hypoUpd ) {
-    m_hypos.clear();
-    for ( std::vector<std::string>::iterator iloc = m_hypoLoc.begin(); m_hypoLoc.end() != iloc; ++iloc ) {
-      m_hypos[*iloc] = 0;
-    }
-  }
-  //
-  return StatusCode::SUCCESS;
-}
-// ============================================================================
-StatusCode CaloFutureGetterTool::finalize() {
-  // un-subscribe to the incidents
-  IIncidentSvc* inc = incSvc();
-  if ( 0 != inc ) { inc->removeListener( this ); }
-  // clear data
-  nullify();
-  // finalize the base
-  return base_class::finalize();
-}
-// ============================================================================
-namespace {
-  // =========================================================================
-  template <class TYPE>
-  void __nullify( std::map<std::string, TYPE*>& _map ) {
-    for ( typename std::map<std::string, TYPE*>::iterator ientry = _map.begin(); _map.end() != ientry; ++ientry ) {
-      ientry->second = 0;
-    }
-  }
-  // ==========================================================================
-} // namespace
-// ============================================================================
-void CaloFutureGetterTool::nullify() {
-  __nullify( m_digits );
-  __nullify( m_clusters );
-  __nullify( m_hypos );
-}
-// ============================================================================
-// getters
-// ============================================================================
-LHCb::CaloDigits* CaloFutureGetterTool::digits( const std::string& loc ) {
-  std::map<std::string, LHCb::CaloDigits*>::iterator it = m_digits.find( loc );
-  //
-  if ( m_digits.end() == it ) {
-    Error( "Illegal Attempt to retrive digits   from '" + loc + "'" ).ignore();
-    return 0;
-  }
-  //
-  if ( 0 != it->second ) { return it->second; }
-  //
-  it->second = getIfExists<LHCb::CaloDigits>( loc );
-  if ( NULL != it->second ) {
-    if ( counterStat->isQuiet() ) counter( "#Digits   @ " + loc ) += it->second->size();
-    return it->second;
-  }
-  //
-  Error( "No Digits   at " + loc ).ignore();
-  return 0;
-}
-// ============================================================================
-LHCb::CaloClusters* CaloFutureGetterTool::clusters( const std::string& loc ) {
-  std::map<std::string, LHCb::CaloClusters*>::iterator it = m_clusters.find( loc );
-  //
-  if ( m_clusters.end() == it ) {
-    Error( "Illegal attempt to retrive clusters from '" + loc + "'" ).ignore();
-    return 0;
-  }
-  //
-  if ( 0 != it->second ) { return it->second; }
-  //
-  it->second = getIfExists<LHCb::CaloClusters>( loc );
-  if ( NULL != it->second ) {
-    if ( counterStat->isQuiet() ) counter( "#Clusters @ " + loc ) += it->second->size();
-    return it->second;
-  }
-  //
-  Error( "No Clusters at " + loc ).ignore();
-  return 0;
-}
-// ============================================================================
-LHCb::CaloHypos* CaloFutureGetterTool::hypos( const std::string& loc ) {
-  std::map<std::string, LHCb::CaloHypos*>::iterator it = m_hypos.find( loc );
-  //
-  if ( m_hypos.end() == it ) {
-    Error( "Illegal attempt to retrive hypos    from '" + loc + "'" ).ignore();
-    return 0;
-  }
-  //
-  if ( 0 != it->second ) { return it->second; }
-  //
-  it->second = getIfExists<LHCb::CaloHypos>( loc );
-  if ( NULL != it->second ) {
-    if ( counterStat->isQuiet() ) counter( "#Hypos    @ " + loc ) += it->second->size();
-    return it->second;
-  }
-  //
-  Error( "No Hypos    at " + loc ).ignore();
-  return 0;
-}
-// ============================================================================
-void CaloFutureGetterTool::update() {
-  // digits
-  if ( m_digiUpd ) {
-    for ( std::vector<std::string>::iterator iloc = m_digiLoc.begin(); m_digiLoc.end() != iloc; ++iloc ) {
-      if ( exist<LHCb::CaloDigits>( *iloc ) && 0 == m_digits[*iloc] ) {
-        LHCb::CaloDigits* digits = get<LHCb::CaloDigits>( *iloc );
-        m_digits[*iloc]          = digits;
-        if ( counterStat->isQuiet() ) counter( "#Digits   @ " + ( *iloc ) ) += digits->size();
-      }
-    }
-  }
-  // clusters
-  if ( m_clusUpd ) {
-    for ( const auto& iloc : m_clusLoc ) {
-      LHCb::CaloClusters* clusters = getIfExists<LHCb::CaloClusters>( iloc );
-      if ( clusters ) {
-        m_clusters[iloc] = clusters;
-        if ( counterStat->isQuiet() ) counter( "#Clusters @ " + iloc ) += clusters->size();
-      }
-    }
-  }
-  // hypos
-  if ( m_hypoUpd ) {
-    for ( const auto& iloc : m_hypoLoc ) {
-      LHCb::CaloHypos* hypos = getIfExists<LHCb::CaloHypos>( iloc );
-      if ( hypos ) {
-        m_hypos[iloc] = hypos;
-        if ( counterStat->isQuiet() ) counter( "#Hypos    @ " + iloc ) += hypos->size();
-      }
-    }
-  }
-  // provider
-  //  if( m_provUpd)
-  // {
-  //  for(std::map<std::string,ICaloFutureDataProvider*>::iterator ip = m_provider.begin();m_provider.end()!=ip;++ip)
-  //  {
-  //    const std::string& det = ip->first;
-  //    ICaloFutureDataProvider* provider = ip->second;
-  //    m_prov[det] = provider->getBanks();
-  //  }
-  //  }
-}
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h
deleted file mode 100644
index 2207e90ec25..00000000000
--- a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-// ============================================================================
-#ifndef CALOFUTUREGETTERTOOL_H
-#define CALOFUTUREGETTERTOOL_H 1
-// ============================================================================
-// Include files
-// ============================================================================
-// STD & STL
-// ============================================================================
-#include <algorithm>
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-#include "GaudiKernel/IIncidentListener.h"
-// ============================================================================
-// GaudiAlg
-// ============================================================================
-#include "GaudiAlg/GaudiTool.h"
-// ============================================================================
-// Event
-// ============================================================================
-#include "Event/CaloCluster.h"
-#include "Event/CaloDigit.h"
-#include "Event/CaloHypo.h"
-// ============================================================================
-// Calo
-// ============================================================================
-#include "CaloFutureInterfaces/ICaloFutureGetterTool.h" // Interface
-#include "CaloFutureInterfaces/IFutureCounterLevel.h"
-// ============================================================================
-/** @class CaloFutureGetterTool CaloFutureGetterTool.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2009-04-17
- */
-class CaloFutureGetterTool : public extends<GaudiTool, ICaloFutureGetterTool, IIncidentListener> {
-public:
-  /// Standard constructor
-  CaloFutureGetterTool( const std::string& type, const std::string& name, const IInterface* parent );
-
-  // ==========================================================================
-  StatusCode initialize() override;
-  StatusCode finalize() override;
-  // ==========================================================================
-
-  // update
-  void update() override;
-  int  detectorsMask() override { return m_detMask; }
-
-  // setters
-  void addToDigits( const std::string& loc, bool clear ) override {
-    if ( clear ) {
-      m_digiLoc.clear();
-      m_digits.clear();
-    }
-    //
-    if ( m_digiLoc.end() == std::find( m_digiLoc.begin(), m_digiLoc.end(), loc ) ) {
-      m_digiLoc.value().push_back( loc );
-    }
-    //
-    if ( m_digits.end() == m_digits.find( loc ) ) { m_digits[loc] = 0; }
-    //
-  }
-  void addToClusters( const std::string& loc, bool clear ) override {
-    if ( clear ) {
-      m_clusLoc.clear();
-      m_clusters.clear();
-    }
-    //
-    if ( m_clusLoc.end() == std::find( m_clusLoc.begin(), m_clusLoc.end(), loc ) ) {
-      m_clusLoc.value().push_back( loc );
-    }
-    //
-    if ( m_clusters.end() == m_clusters.find( loc ) ) { m_clusters[loc] = 0; }
-    //
-  }
-  void addToHypos( const std::string& loc, bool clear ) override {
-    if ( clear ) {
-      m_hypoLoc.clear();
-      m_hypos.clear();
-    }
-    //
-    if ( m_hypoLoc.end() == std::find( m_hypoLoc.begin(), m_hypoLoc.end(), loc ) ) {
-      m_hypoLoc.value().push_back( loc );
-    }
-    //
-    if ( m_hypos.end() == m_hypos.find( loc ) ) { m_hypos[loc] = 0; }
-    //
-  }
-
-  // getters
-  LHCb::CaloDigits*   digits( const std::string& loc ) override;
-  LHCb::CaloClusters* clusters( const std::string& loc ) override;
-  LHCb::CaloHypos*    hypos( const std::string& loc ) override;
-
-  bool hasData( const std::string& det ) override {
-    std::map<std::string, bool>::iterator it = m_prov.find( det );
-    return ( it == m_prov.end() ) ? false : ( *it ).second;
-  }
-
-public:
-  // =========================================================================
-  /// Inform that a new incident has occurred
-  void handle( const Incident& /* inc */ ) override { nullify(); }
-  // =========================================================================
-protected:
-  // =========================================================================
-  /// nullify the pointers
-  void nullify();
-  // =========================================================================
-private:
-  IFutureCounterLevel* counterStat = nullptr;
-  // =========================================================================
-  std::map<std::string, LHCb::CaloDigits*>   m_digits;
-  std::map<std::string, LHCb::CaloClusters*> m_clusters;
-  std::map<std::string, LHCb::CaloHypos*>    m_hypos;
-  std::map<std::string, bool>                m_prov;
-  Gaudi::Property<bool>                      m_digiUpd{this, "GetDigits", true};
-  Gaudi::Property<bool>                      m_clusUpd{this, "GetClusters", false};
-  Gaudi::Property<bool>                      m_hypoUpd{this, "GetHypos", false};
-  //  bool m_provUpd;
-  Gaudi::Property<std::vector<std::string>> m_digiLoc{this, "DigitLocations"};
-  Gaudi::Property<std::vector<std::string>> m_clusLoc{this, "ClusterLocations"};
-  Gaudi::Property<std::vector<std::string>> m_hypoLoc{this, "HypoLocations"};
-  Gaudi::Property<int>                      m_detMask{this, "DetectorMask", 0xF};
-};
-// ============================================================================
-// The END
-// ============================================================================
-#endif // CALOFUTUREGETTERTOOL_H
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
index 57ae77796aa..f2e53b34dff 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp
@@ -92,8 +92,7 @@ const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs( const L
   m_neighbour.setDet( m_fromDet );
 
   // get data
-  const_cast<CaloFutureHypo2CaloFuture*>( this )->m_digs =
-      const_cast<CaloFutureHypo2CaloFuture*>( this )->m_getter->digits( m_toLoc );
+  const_cast<CaloFutureHypo2CaloFuture*>( this )->m_digs = getIfExists<LHCb::CaloDigits>( m_toLoc );
 
   // matching cluster
   const LHCb::CaloCluster::Entries& entries = fromCluster.entries();
-- 
GitLab


From c15bbd2bc8518db68bf9a042a85ae2252a04cd32 Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Thu, 8 Aug 2019 16:11:48 +0200
Subject: [PATCH 7/9] Streamline HypoEstimater and GammaPi0Estimators

* put CaloFutureHypoEstimater in Calo::Future namespace
* simplify FutureGammaPi0XGBoostTool and FutureXGBClassifierPhPi0 tools
* follow interface changes in HypoEstimator and GammaPiSeperation
---
 .../src/CaloFuturePhotonChecker.cpp           |   1 -
 .../src/CaloFutureHypoEstimator.cpp           | 708 +++++++++---------
 .../src/CaloFutureHypoEstimator.h             | 150 ++--
 .../src/FutureGammaPi0SeparationTool.cpp      | 332 ++++----
 .../src/FutureGammaPi0SeparationTool.h        |  73 +-
 .../src/FutureGammaPi0XGBoostTool.cpp         | 286 ++++---
 .../src/FutureGammaPi0XGBoostTool.h           |  88 +--
 .../src/FutureXGBClassifierPhPi0.cpp          |  18 +-
 .../src/FutureXGBClassifierPhPi0.h            |  19 +-
 ...FutureNeutralProtoParticleAddNeutralID.cpp |   3 +-
 .../FutureNeutralProtoParticleAddNeutralID.h  |  18 +-
 11 files changed, 819 insertions(+), 877 deletions(-)

diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp
index 623c4666dd4..1a3ee3291f7 100644
--- a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp
+++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp
@@ -13,7 +13,6 @@
 #include "CaloFutureMoniUtils.h"
 
 #include "CaloDet/DeCalorimeter.h"
-#include "CaloFutureInterfaces/ICaloFutureHypoLikelihood.h"
 #include "CaloFutureUtils/CaloFuture2Track.h"
 #include "CaloFutureUtils/CaloMomentum.h"
 #include "CaloFutureUtils/ClusterFunctors.h"
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index 70a1fcd3fd0..961c7a8362a 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -23,252 +23,243 @@
 //-----------------------------------------------------------------------------
 
 // Declaration of the Tool Factory
-DECLARE_COMPONENT( CaloFutureHypoEstimator )
+DECLARE_COMPONENT_WITH_ID( Calo::Future::HypoEstimator, "CaloFutureHypoEstimator" )
 
-StatusCode CaloFutureHypoEstimator::finalize() {
-  IIncidentSvc* inc = incSvc();
-  if ( inc ) { inc->removeListener( this ); }
-  return GaudiTool::finalize();
-}
+namespace Calo::Future {
 
-StatusCode CaloFutureHypoEstimator::initialize() {
-  StatusCode    sc  = GaudiTool::initialize(); // must be executed first
-  IIncidentSvc* inc = incSvc();
-  if ( inc ) inc->addListener( this, IncidentType::BeginEvent );
-
-  m_toCaloFuture.retrieve();
-  hypo2Calo()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
-  hypo2Calo()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
-  hypo2Calo()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
+  StatusCode HypoEstimator::finalize() {
+    IIncidentSvc* inc = incSvc();
+    if ( inc ) { inc->removeListener( this ); }
+    return GaudiTool::finalize();
+  }
 
-  m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
+  StatusCode HypoEstimator::initialize() {
+    StatusCode    sc  = GaudiTool::initialize(); // must be executed first
+    IIncidentSvc* inc = incSvc();
+    if ( inc ) inc->addListener( this, IncidentType::BeginEvent );
 
-  clean();
-  m_status = true;
-  return sc;
-}
+    m_toCaloFuture.retrieve();
+    hypo2Calo()->_setProperty( "Seed", m_seed ? "true" : "false" ).ignore();
+    hypo2Calo()->_setProperty( "PhotonLine", m_extrapol ? "true" : "false" ).ignore();
+    hypo2Calo()->_setProperty( "AddNeighbors", m_neig ? "true" : "false" ).ignore();
 
-//=============================================================================
+    m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
 
-// ------------
-std::optional<double> CaloFutureHypoEstimator::data( const LHCb::CaloCluster&     cluster,
-                                                     Calo::Future::Enum::DataType type ) const {
-  if ( &cluster != m_cluster ) {
     clean();
-    m_status = estimator( cluster );
-    if ( !m_status ) {
-      if ( counterStat->isQuiet() ) counter( "Cluster estimation failed" ) += 1;
+    m_status = true;
+    return sc;
+  }
+
+  //=============================================================================
+
+  // ------------
+  std::optional<double> HypoEstimator::data( const LHCb::CaloCluster&     cluster,
+                                             Calo::Future::Enum::DataType type ) const {
+    if ( &cluster != m_cluster ) {
       clean();
+      m_status = estimator( cluster );
+      if ( !m_status ) {
+        if ( counterStat->isQuiet() ) counter( "Cluster estimation failed" ) += 1;
+        clean();
+      }
     }
+    auto it = m_data.find( type );
+    if ( it != m_data.end() ) return m_data[type];
+    return {};
   }
-  auto it = m_data.find( type );
-  if ( it != m_data.end() ) return m_data[type];
-  return {};
-}
-
-// ------------
-std::optional<double> CaloFutureHypoEstimator::data( const LHCb::CaloHypo&        hypo,
-                                                     Calo::Future::Enum::DataType type ) const {
-  if ( &hypo != m_hypo ) {
-    clean();
-    m_status = estimator( hypo );
-    if ( !m_status ) {
-      if ( counterStat->isQuiet() ) counter( "Hypo estimation failed" ) += 1;
+
+  // ------------
+  std::optional<double> HypoEstimator::data( const LHCb::CaloHypo& hypo, Calo::Future::Enum::DataType type ) const {
+    if ( &hypo != m_hypo ) {
       clean();
+      m_status = estimator( hypo );
+      if ( !m_status ) {
+        if ( counterStat->isQuiet() ) counter( "Hypo estimation failed" ) += 1;
+        clean();
+      }
     }
+    auto it = m_data.find( type );
+    if ( it != m_data.end() ) return m_data[type];
+    return {};
   }
-  auto it = m_data.find( type );
-  if ( it != m_data.end() ) return m_data[type];
-  return {};
-}
-
-// ------------ FROM HYPO
-bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
-  using namespace Calo::Future::Enum;
-  m_hypo = &hypo;
-
-  LHCb::CaloMomentum mom( &hypo );
-  m_data[DataType::HypoE]  = mom.e();
-  m_data[DataType::HypoEt] = mom.pt();
-  m_data[DataType::HypoM] =
-      mom.mass(); // for mergedPi0 hypothesis only (->for all clusters - toDo in CaloFutureMergedPi0Alg)
-  m_data[DataType::ToPrsE] = m_toCaloFuture->energy( hypo, "Prs" );
-  m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( hypo, "Prs" );
-  m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( hypo, "Spd" );
-  // using extra-digits
-  const LHCb::CaloHypo::Digits&     digits = hypo.digits();
-  LHCb::CaloDataFunctor::IsFromCalo isSpd{DeCalorimeterLocation::Spd};
-  LHCb::CaloDataFunctor::IsFromCalo isPrs{DeCalorimeterLocation::Prs};
-  m_data[DataType::HypoSpdM] = std::count_if( digits.begin(), digits.end(), isSpd );
-  m_data[DataType::HypoPrsM] = std::count_if( digits.begin(), digits.end(), isPrs );
-  m_data[DataType::HypoPrsE] = std::accumulate( digits.begin(), digits.end(), 0., [&]( double sumPrs, const auto& id ) {
-    if ( id && isPrs( id ) ) { sumPrs += id->e(); }
-    return sumPrs;
-  } );
-
-  // electron matching
-  if ( !m_skipC ) {
-    double             chi2e  = Default;
-    double             trajL  = Default;
-    const LHCb::Track* etrack = nullptr;
-    // LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc);
-    const auto* etable = m_tables->getTrHypoTable2D( m_emLoc );
-    if ( etable ) {
-      const auto range = etable->inverse()->relations( &hypo );
-      if ( !range.empty() ) {
-        chi2e  = range.front().weight();
-        etrack = range.front();
-        if ( etrack ) {
-          LHCb::ProtoParticle dummy;
-          dummy.setTrack( etrack );
-          dummy.addToCalo( &hypo );
-          // CaloFutureElectron->caloTrajectory must be after addToCalo
-          if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax );
-          m_electron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
-        }
-      }
-    } else if ( counterStat->isQuiet() )
-      counter( "Missing " + m_emLoc ) += 1;
-
-    m_track[MatchType::ElectronMatch] = etrack;
-    m_data[DataType::ElectronMatch]   = chi2e;
-    m_data[DataType::TrajectoryL]     = trajL;
-
-    // brem matching
-    double             chi2b  = Default;
-    const LHCb::Track* btrack = nullptr;
-    // LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc);
-    const auto* btable = m_tables->getTrHypoTable2D( m_bmLoc );
-    if ( btable ) {
-      const auto range = btable->inverse()->relations( &hypo );
-      if ( !range.empty() ) {
-        chi2b  = range.front().weight();
-        btrack = range.front();
-      }
-    } else if ( counterStat->isQuiet() )
-      counter( "Missing " + m_bmLoc ) += 1;
 
-    m_track[MatchType::BremMatch] = btrack;
-    m_data[DataType::BremMatch]   = chi2b;
-  }
+  // ------------ FROM HYPO
+  bool HypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
+    using namespace Calo::Future::Enum;
+    m_hypo = &hypo;
+
+    LHCb::CaloMomentum mom( &hypo );
+    m_data[DataType::HypoE]  = mom.e();
+    m_data[DataType::HypoEt] = mom.pt();
+    m_data[DataType::HypoM] =
+        mom.mass(); // for mergedPi0 hypothesis only (->for all clusters - toDo in CaloFutureMergedPi0Alg)
+    m_data[DataType::ToPrsE] = m_toCaloFuture->energy( hypo, "Prs" );
+    m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( hypo, "Prs" );
+    m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( hypo, "Spd" );
+    // using extra-digits
+    const LHCb::CaloHypo::Digits&     digits = hypo.digits();
+    LHCb::CaloDataFunctor::IsFromCalo isSpd{DeCalorimeterLocation::Spd};
+    LHCb::CaloDataFunctor::IsFromCalo isPrs{DeCalorimeterLocation::Prs};
+    m_data[DataType::HypoSpdM] = std::count_if( digits.begin(), digits.end(), isSpd );
+    m_data[DataType::HypoPrsM] = std::count_if( digits.begin(), digits.end(), isPrs );
+    m_data[DataType::HypoPrsE] =
+        std::accumulate( digits.begin(), digits.end(), 0., [&]( double sumPrs, const auto& id ) {
+          if ( id && isPrs( id ) ) { sumPrs += id->e(); }
+          return sumPrs;
+        } );
+
+    // electron matching
+    if ( !m_skipC ) {
+      double             chi2e  = Default;
+      double             trajL  = Default;
+      const LHCb::Track* etrack = nullptr;
+      // LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc);
+      const auto* etable = m_tables->getTrHypoTable2D( m_emLoc );
+      if ( etable ) {
+        const auto range = etable->inverse()->relations( &hypo );
+        if ( !range.empty() ) {
+          chi2e  = range.front().weight();
+          etrack = range.front();
+          if ( etrack ) {
+            LHCb::ProtoParticle dummy;
+            dummy.setTrack( etrack );
+            dummy.addToCalo( &hypo );
+            // CaloFutureElectron->caloTrajectory must be after addToCalo
+            if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax );
+            m_electron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
+          }
+        }
+      } else if ( counterStat->isQuiet() )
+        counter( "Missing " + m_emLoc ) += 1;
+
+      m_track[MatchType::ElectronMatch] = etrack;
+      m_data[DataType::ElectronMatch]   = chi2e;
+      m_data[DataType::TrajectoryL]     = trajL;
+
+      // brem matching
+      double             chi2b  = Default;
+      const LHCb::Track* btrack = nullptr;
+      // LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc);
+      const auto* btable = m_tables->getTrHypoTable2D( m_bmLoc );
+      if ( btable ) {
+        const auto range = btable->inverse()->relations( &hypo );
+        if ( !range.empty() ) {
+          chi2b  = range.front().weight();
+          btrack = range.front();
+        }
+      } else if ( counterStat->isQuiet() )
+        counter( "Missing " + m_bmLoc ) += 1;
 
-  // NeutralID (warning : protect against infinite loop from CaloFuturePhotonIDAlg using this tools with DoD active)
-  if ( !m_skipN ) {
-    for ( auto&& [hypothesis, loc] : m_pidLoc ) {
-      const LHCb::CaloFuture2Track::IHypoEvalTable* tbl = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( loc );
-      if ( tbl ) {
-        m_idTable[hypothesis] = tbl;
-      } else if ( counterStat->isQuiet() ) {
-        counter( "Missing " + loc ) += 1;
-      }
-    }
-    std::ostringstream type( "" );
-    type << hypo.hypothesis();
-    std::string                                   hypothesis = type.str();
-    const LHCb::CaloFuture2Track::IHypoEvalTable* idTable    = nullptr;
-    auto                                          it         = m_idTable.find( hypothesis );
-    if ( it != m_idTable.end() ) idTable = it->second;
-    if ( idTable ) {
-      const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( &hypo );
-      if ( !range.empty() ) m_data[DataType::NeutralID] = range.front().to();
+      m_track[MatchType::BremMatch] = btrack;
+      m_data[DataType::BremMatch]   = chi2b;
     }
-  }
-  // link 2 cluster :
-  const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
-
-  // Prs info
-  if ( !cluster ) {
-    Warning( "Cluster point to NULL", StatusCode::SUCCESS ).ignore();
-  } else {
-    // Ecal seed
-    auto iseed = LHCb::ClusterFunctors::locateDigit( cluster->entries().begin(), cluster->entries().end(),
-                                                     LHCb::CaloDigitStatus::SeedCell );
-    if ( iseed != cluster->entries().end() ) {
-      const LHCb::CaloDigit* seed   = iseed->digit();
-      const LHCb::CaloCellID idseed = seed->cellID();
-      double                 sum9   = 0.;
-      double                 sum1   = 0.;
-      // PrsE4
-      std::array<double, 4> Prse4s = {};
-      std::array<double, 9> Prse9  = {};
-
-      for ( auto id = digits.begin(); id != digits.end(); ++id ) {
-
-        if ( 0 == *id || !isPrs( *id ) ) continue;
-        LHCb::CaloCellID id2 = ( *id )->cellID();
-        if ( abs( (int)( *id )->cellID().row() - (int)idseed.row() ) < 2 &&
-             abs( (int)( *id )->cellID().col() - (int)idseed.col() ) < 2 ) {
-          // Build sum1 and sum9
-          //
-          sum9 += ( *id )->e();
-          if ( ( *id )->cellID().row() == idseed.row() && ( *id )->cellID().col() == idseed.col() ) sum1 = ( *id )->e();
-          // Prs4
-          //
-          if ( id2.col() <= idseed.col() && id2.row() >= idseed.row() ) Prse4s[0] += ( *id )->e();
-          if ( id2.col() >= idseed.col() && id2.row() >= idseed.row() ) Prse4s[1] += ( *id )->e();
-          if ( id2.col() >= idseed.col() && id2.row() <= idseed.row() ) Prse4s[2] += ( *id )->e();
-          if ( id2.col() <= idseed.col() && id2.row() <= idseed.row() ) Prse4s[3] += ( *id )->e();
-          // Select the 3X3 cluster
-          //
-          int dcol     = (int)id2.col() - (int)idseed.col() + 1;
-          int drow     = (int)id2.row() - (int)idseed.row() + 1;
-          int indexPrs = drow * 3 + dcol;
-          Prse9[indexPrs] += ( *id )->e();
+
+    // NeutralID (warning : protect against infinite loop from CaloFuturePhotonIDAlg using this tools with DoD active)
+    if ( !m_skipN ) {
+      for ( auto&& [hypothesis, loc] : m_pidLoc ) {
+        const LHCb::CaloFuture2Track::IHypoEvalTable* tbl = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( loc );
+        if ( tbl ) {
+          m_idTable[hypothesis] = tbl;
+        } else if ( counterStat->isQuiet() ) {
+          counter( "Missing " + loc ) += 1;
         }
       }
-      //    Build E19 and E49
-      //
-      double Prse4max =
-          std::accumulate( Prse4s.begin(), Prse4s.end(), 0., []( double l, double r ) { return std::max( l, r ); } );
-      m_data[DataType::PrsE4Max] = Prse4max;
-      double sum9Inv             = 0.;
-      if ( sum9 > 0. ) {
-        sum9Inv                  = 1. / sum9;
-        m_data[DataType::PrsE49] = Prse4max * sum9Inv;
-        m_data[DataType::PrsE19] = sum1 * sum9Inv;
-      } else {
-        m_data[DataType::PrsE49] = 0.;
-        m_data[DataType::PrsE19] = 0.;
+      std::ostringstream type( "" );
+      type << hypo.hypothesis();
+      std::string                                   hypothesis = type.str();
+      const LHCb::CaloFuture2Track::IHypoEvalTable* idTable    = nullptr;
+      auto                                          it         = m_idTable.find( hypothesis );
+      if ( it != m_idTable.end() ) idTable = it->second;
+      if ( idTable ) {
+        const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( &hypo );
+        if ( !range.empty() ) m_data[DataType::NeutralID] = range.front().to();
       }
-      m_data[DataType::PrsE1] = Prse9[0];
-      m_data[DataType::PrsE2] = Prse9[1];
-      m_data[DataType::PrsE3] = Prse9[2];
-      m_data[DataType::PrsE4] = Prse9[3];
-      m_data[DataType::PrsE5] = Prse9[4];
-      m_data[DataType::PrsE6] = Prse9[5];
-      m_data[DataType::PrsE7] = Prse9[6];
-      m_data[DataType::PrsE8] = Prse9[7];
-      m_data[DataType::PrsE9] = Prse9[8];
     }
-  }
-
-  // gamma/pi0 separation
-  m_data[DataType::isPhoton]    = m_GammaPi0->isPhoton( &hypo );
-  m_data[DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( &hypo );
-
-  // 1- Ecal variables :
-  for ( const auto& [key, val] : m_GammaPi0->inputDataMap() ) {
-    std::string name = "isPhoton_" + key;
-    bool        ok   = false;
-    for ( int i = 0; i < count<DataType>(); ++i ) {
-      DataType j{i};
-      if ( toString( j ) == name ) {
-        m_data[j] = val;
-        ok        = true;
-        break;
+    // link 2 cluster :
+    const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
+
+    // Prs info
+    if ( !cluster ) {
+      Warning( "Cluster point to NULL", StatusCode::SUCCESS ).ignore();
+    } else {
+      // Ecal seed
+      auto iseed = LHCb::ClusterFunctors::locateDigit( cluster->entries().begin(), cluster->entries().end(),
+                                                       LHCb::CaloDigitStatus::SeedCell );
+      if ( iseed != cluster->entries().end() ) {
+        const LHCb::CaloDigit* seed   = iseed->digit();
+        const LHCb::CaloCellID idseed = seed->cellID();
+        double                 sum9   = 0.;
+        double                 sum1   = 0.;
+        // PrsE4
+        std::array<double, 4> Prse4s = {};
+        std::array<double, 9> Prse9  = {};
+
+        for ( auto id = digits.begin(); id != digits.end(); ++id ) {
+
+          if ( 0 == *id || !isPrs( *id ) ) continue;
+          LHCb::CaloCellID id2 = ( *id )->cellID();
+          if ( abs( (int)( *id )->cellID().row() - (int)idseed.row() ) < 2 &&
+               abs( (int)( *id )->cellID().col() - (int)idseed.col() ) < 2 ) {
+            // Build sum1 and sum9
+            //
+            sum9 += ( *id )->e();
+            if ( ( *id )->cellID().row() == idseed.row() && ( *id )->cellID().col() == idseed.col() )
+              sum1 = ( *id )->e();
+            // Prs4
+            //
+            if ( id2.col() <= idseed.col() && id2.row() >= idseed.row() ) Prse4s[0] += ( *id )->e();
+            if ( id2.col() >= idseed.col() && id2.row() >= idseed.row() ) Prse4s[1] += ( *id )->e();
+            if ( id2.col() >= idseed.col() && id2.row() <= idseed.row() ) Prse4s[2] += ( *id )->e();
+            if ( id2.col() <= idseed.col() && id2.row() <= idseed.row() ) Prse4s[3] += ( *id )->e();
+            // Select the 3X3 cluster
+            //
+            int dcol     = (int)id2.col() - (int)idseed.col() + 1;
+            int drow     = (int)id2.row() - (int)idseed.row() + 1;
+            int indexPrs = drow * 3 + dcol;
+            Prse9[indexPrs] += ( *id )->e();
+          }
+        }
+        //    Build E19 and E49
+        //
+        double Prse4max =
+            std::accumulate( Prse4s.begin(), Prse4s.end(), 0., []( double l, double r ) { return std::max( l, r ); } );
+        m_data[DataType::PrsE4Max] = Prse4max;
+        double sum9Inv             = 0.;
+        if ( sum9 > 0. ) {
+          sum9Inv                  = 1. / sum9;
+          m_data[DataType::PrsE49] = Prse4max * sum9Inv;
+          m_data[DataType::PrsE19] = sum1 * sum9Inv;
+        } else {
+          m_data[DataType::PrsE49] = 0.;
+          m_data[DataType::PrsE19] = 0.;
+        }
+        m_data[DataType::PrsE1] = Prse9[0];
+        m_data[DataType::PrsE2] = Prse9[1];
+        m_data[DataType::PrsE3] = Prse9[2];
+        m_data[DataType::PrsE4] = Prse9[3];
+        m_data[DataType::PrsE5] = Prse9[4];
+        m_data[DataType::PrsE6] = Prse9[5];
+        m_data[DataType::PrsE7] = Prse9[6];
+        m_data[DataType::PrsE8] = Prse9[7];
+        m_data[DataType::PrsE9] = Prse9[8];
       }
     }
-    if ( !ok ) Warning( "DataType '" + name + "' is undefined", StatusCode::SUCCESS ).ignore();
-  }
-  //
-  bool ok = ( cluster && estimator( *cluster, &hypo ) );
 
-  // Estimator MUST be at the end (after all inputs are loaded)
+    // gamma/pi0 separation
+    m_data[DataType::isPhoton]    = m_GammaPi0->isPhoton( hypo );
+    m_data[DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( hypo );
+
+    // 1- Ecal variables :
+    for ( const auto& [key, val] : m_GammaPi0->inputDataMap() ) m_data[key] = val;
+    //
+    bool ok = ( cluster && estimator( *cluster, &hypo ) );
+
+    // Estimator MUST be at the end (after all inputs are loaded)
 
-  auto get_data = [&]( Calo::Future::Enum::DataType type ) {
-    auto d = m_data.find( type );
-    return d != m_data.end() ? d->second : 0.;
-  };
+    auto get_data = [&]( Calo::Future::Enum::DataType type ) {
+      auto d = m_data.find( type );
+      return d != m_data.end() ? d->second : 0.;
+    };
 
 // FIXME: C++20: remove pragmas
 // designated initializers are part of C99 (so both clang and gcc support them)
@@ -276,155 +267,156 @@ bool CaloFutureHypoEstimator::estimator( const LHCb::CaloHypo& hypo ) const {
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpedantic"
 
-  auto obs = Calo::Future::Interfaces::INeutralID::Observables{.clmatch = get_data( DataType::ClusterMatch ),
-                                                               .prse    = get_data( DataType::ToPrsE ),
-                                                               .e19     = get_data( DataType::E19 ),
-                                                               .hclecl  = get_data( DataType::Hcal2Ecal ),
-                                                               .prse19  = get_data( DataType::PrsE19 ),
-                                                               .prse49  = get_data( DataType::PrsE49 ),
-                                                               .sprd    = get_data( DataType::Spread ),
-                                                               .prse4mx = get_data( DataType::PrsE4Max ),
-                                                               .prsm    = get_data( DataType::HypoPrsM ),
-                                                               .spdm    = get_data( DataType::HypoSpdM )};
+    auto obs = Calo::Future::Interfaces::INeutralID::Observables{.clmatch = get_data( DataType::ClusterMatch ),
+                                                                 .prse    = get_data( DataType::ToPrsE ),
+                                                                 .e19     = get_data( DataType::E19 ),
+                                                                 .hclecl  = get_data( DataType::Hcal2Ecal ),
+                                                                 .prse19  = get_data( DataType::PrsE19 ),
+                                                                 .prse49  = get_data( DataType::PrsE49 ),
+                                                                 .sprd    = get_data( DataType::Spread ),
+                                                                 .prse4mx = get_data( DataType::PrsE4Max ),
+                                                                 .prsm    = get_data( DataType::HypoPrsM ),
+                                                                 .spdm    = get_data( DataType::HypoSpdM )};
 #pragma GCC diagnostic pop
 
-  m_data[DataType::isNotH] = m_neutralID->isNotH( hypo, obs );
-  m_data[DataType::isNotE] = m_neutralID->isNotE( hypo, obs );
+    m_data[DataType::isNotH] = m_neutralID->isNotH( hypo, obs );
+    m_data[DataType::isNotE] = m_neutralID->isNotE( hypo, obs );
 
-  return ok;
-}
-
-// ------------ FROM CLUSTER
-bool CaloFutureHypoEstimator::estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo ) const {
-  using namespace Calo::Future::Enum;
-  m_cluster = &cluster;
-
-  if ( cluster.entries().empty() ) {
-    if ( counterStat->isQuiet() ) counter( "Empty cluster" ) += 1;
-    return false;
+    return ok;
   }
-  auto iseed = LHCb::ClusterFunctors::locateDigit( cluster.entries().begin(), cluster.entries().end(),
-                                                   LHCb::CaloDigitStatus::SeedCell );
 
-  if ( iseed != cluster.entries().end() ) {
+  // ------------ FROM CLUSTER
+  bool HypoEstimator::estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo ) const {
+    using namespace Calo::Future::Enum;
+    m_cluster = &cluster;
 
-    const LHCb::CaloDigit* seed = iseed->digit();
-    if ( 0 == seed ) {
-      if ( counterStat->isQuiet() ) counter( "Seed points to NULL" ) += 1;
+    if ( cluster.entries().empty() ) {
+      if ( counterStat->isQuiet() ) counter( "Empty cluster" ) += 1;
       return false;
     }
+    auto iseed = LHCb::ClusterFunctors::locateDigit( cluster.entries().begin(), cluster.entries().end(),
+                                                     LHCb::CaloDigitStatus::SeedCell );
 
-    double eEcal               = cluster.e();
-    m_data[DataType::ClusterE] = eEcal;
-    //
-    double          cSize        = m_ecal->cellSize( cluster.seed() );
-    Gaudi::XYZPoint cCenter      = m_ecal->cellCenter( cluster.seed() );
-    double          asX          = ( cluster.position().x() - cCenter.x() ) / cSize;
-    double          asY          = ( cluster.position().y() - cCenter.y() ) / cSize;
-    m_data[DataType::ClusterAsX] = asX;
-    m_data[DataType::ClusterAsY] = asY;
-
-    m_data[DataType::E1]     = seed->e();
-    auto   it                = m_data.find( DataType::HypoE );
-    double eHypo             = ( it != m_data.end() ) ? m_data[DataType::HypoE] : 0;
-    m_data[DataType::E1Hypo] = eHypo > 0. ? ( seed->e() ) / eHypo : -1.;
-    LHCb::CaloCellID sid     = seed->cellID();
-    m_data[DataType::CellID] = sid.all();
-    m_data[DataType::Spread] = cluster.position().spread()( 1, 1 ) + cluster.position().spread()( 0, 0 );
-    // E4
-    std::array<double, 4> e4s       = {0, 0, 0, 0};
-    double                e9        = 0.;
-    double                ee9       = 0.; // full cluster energy without fraction applied
-    double                e2        = 0.;
-    bool                  hasShared = false;
-    int                   code      = 0.;
-    int                   mult      = 0.;
-    int                   nsat      = 0; // number of saturated cells
-    for ( auto ie = cluster.entries().begin(); cluster.entries().end() != ie; ++ie ) {
-      const LHCb::CaloDigit* dig = ie->digit();
-      if ( !dig ) continue;
-      double ecel = dig->e() * ie->fraction();
-      if ( ( ( ie->status() & LHCb::CaloDigitStatus::UseForEnergy ) != 0 ||
-             ( ie->status() & LHCb::CaloDigitStatus::UseForCovariance ) != 0 ) &&
-           m_ecal->isSaturated( dig->e(), dig->cellID() ) )
-        nsat++;
-      LHCb::CaloCellID id = dig->cellID();
-      if ( id.area() != sid.area() || abs( (int)id.col() - (int)sid.col() ) > 1 ||
-           abs( (int)id.row() - (int)sid.row() ) > 1 )
-        continue;
-      if ( id.col() <= sid.col() && id.row() >= sid.row() ) e4s[0] += ecel;
-      if ( id.col() >= sid.col() && id.row() >= sid.row() ) e4s[1] += ecel;
-      if ( id.col() >= sid.col() && id.row() <= sid.row() ) e4s[2] += ecel;
-      if ( id.col() <= sid.col() && id.row() <= sid.row() ) e4s[3] += ecel;
-      e9 += ecel;
-      // new info
-      ee9 += dig->e();
-      mult++;
-      if ( ie->status() & LHCb::CaloDigitStatus::SharedCell ) hasShared = true;
-      if ( !( id == sid ) && ecel > e2 ) {
-        e2     = ecel;
-        int dc = (int)id.col() - (int)sid.col() + 1;
-        int dr = (int)id.row() - (int)sid.row() + 1;
-        code   = 3 * dr + dc;
+    if ( iseed != cluster.entries().end() ) {
+
+      const LHCb::CaloDigit* seed = iseed->digit();
+      if ( 0 == seed ) {
+        if ( counterStat->isQuiet() ) counter( "Seed points to NULL" ) += 1;
+        return false;
       }
+
+      double eEcal               = cluster.e();
+      m_data[DataType::ClusterE] = eEcal;
+      //
+      double          cSize        = m_ecal->cellSize( cluster.seed() );
+      Gaudi::XYZPoint cCenter      = m_ecal->cellCenter( cluster.seed() );
+      double          asX          = ( cluster.position().x() - cCenter.x() ) / cSize;
+      double          asY          = ( cluster.position().y() - cCenter.y() ) / cSize;
+      m_data[DataType::ClusterAsX] = asX;
+      m_data[DataType::ClusterAsY] = asY;
+
+      m_data[DataType::E1]     = seed->e();
+      auto   it                = m_data.find( DataType::HypoE );
+      double eHypo             = ( it != m_data.end() ) ? m_data[DataType::HypoE] : 0;
+      m_data[DataType::E1Hypo] = eHypo > 0. ? ( seed->e() ) / eHypo : -1.;
+      LHCb::CaloCellID sid     = seed->cellID();
+      m_data[DataType::CellID] = sid.all();
+      m_data[DataType::Spread] = cluster.position().spread()( 1, 1 ) + cluster.position().spread()( 0, 0 );
+      // E4
+      std::array<double, 4> e4s       = {0, 0, 0, 0};
+      double                e9        = 0.;
+      double                ee9       = 0.; // full cluster energy without fraction applied
+      double                e2        = 0.;
+      bool                  hasShared = false;
+      int                   code      = 0.;
+      int                   mult      = 0.;
+      int                   nsat      = 0; // number of saturated cells
+      for ( auto ie = cluster.entries().begin(); cluster.entries().end() != ie; ++ie ) {
+        const LHCb::CaloDigit* dig = ie->digit();
+        if ( !dig ) continue;
+        double ecel = dig->e() * ie->fraction();
+        if ( ( ( ie->status() & LHCb::CaloDigitStatus::UseForEnergy ) != 0 ||
+               ( ie->status() & LHCb::CaloDigitStatus::UseForCovariance ) != 0 ) &&
+             m_ecal->isSaturated( dig->e(), dig->cellID() ) )
+          nsat++;
+        LHCb::CaloCellID id = dig->cellID();
+        if ( id.area() != sid.area() || abs( (int)id.col() - (int)sid.col() ) > 1 ||
+             abs( (int)id.row() - (int)sid.row() ) > 1 )
+          continue;
+        if ( id.col() <= sid.col() && id.row() >= sid.row() ) e4s[0] += ecel;
+        if ( id.col() >= sid.col() && id.row() >= sid.row() ) e4s[1] += ecel;
+        if ( id.col() >= sid.col() && id.row() <= sid.row() ) e4s[2] += ecel;
+        if ( id.col() <= sid.col() && id.row() <= sid.row() ) e4s[3] += ecel;
+        e9 += ecel;
+        // new info
+        ee9 += dig->e();
+        mult++;
+        if ( ie->status() & LHCb::CaloDigitStatus::SharedCell ) hasShared = true;
+        if ( !( id == sid ) && ecel > e2 ) {
+          e2     = ecel;
+          int dc = (int)id.col() - (int)sid.col() + 1;
+          int dr = (int)id.row() - (int)sid.row() + 1;
+          code   = 3 * dr + dc;
+        }
+      }
+      m_data[DataType::Saturation] = nsat;
+      double e4max                 = 0;
+      for ( auto ih = e4s.begin(); e4s.end() != ih; ++ih ) {
+        if ( *ih >= e4max ) e4max = *ih;
+      }
+
+      code = mult * 10 + code;
+      if ( hasShared ) code *= -1;
+      m_data[DataType::ClusterCode] = (double)code;
+      m_data[DataType::ClusterFrac] = ( e9 > 0. ) ? e9 / ee9 : -1;
+
+      m_data[DataType::E4]  = e4max;
+      m_data[DataType::E9]  = e9;
+      m_data[DataType::E49] = ( e9 > 0. ) ? e4max / e9 : 0.;
+      m_data[DataType::E19] = ( e9 > 0. ) ? seed->e() / e9 : -1.;
+
+      if ( !fromHypo ) {
+        // hypo and cluster parameters may produce small difference according to m_toCaloFuture setting (due to
+        // extrapolation)
+        m_data[DataType::ToPrsE] = m_toCaloFuture->energy( cluster, "Prs" );
+        m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( cluster, "Prs" );
+        m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( cluster, "Spd" );
+      }
+      double eHcal                = m_toCaloFuture->energy( cluster, "Hcal" );
+      m_data[DataType::ToHcalE]   = eHcal;
+      m_data[DataType::Hcal2Ecal] = ( eEcal > 0 ) ? eHcal / eEcal : 0.;
     }
-    m_data[DataType::Saturation] = nsat;
-    double e4max                 = 0;
-    for ( auto ih = e4s.begin(); e4s.end() != ih; ++ih ) {
-      if ( *ih >= e4max ) e4max = *ih;
-    }
 
-    code = mult * 10 + code;
-    if ( hasShared ) code *= -1;
-    m_data[DataType::ClusterCode] = (double)code;
-    m_data[DataType::ClusterFrac] = ( e9 > 0. ) ? e9 / ee9 : -1;
-
-    m_data[DataType::E4]  = e4max;
-    m_data[DataType::E9]  = e9;
-    m_data[DataType::E49] = ( e9 > 0. ) ? e4max / e9 : 0.;
-    m_data[DataType::E19] = ( e9 > 0. ) ? seed->e() / e9 : -1.;
-
-    if ( !fromHypo ) {
-      // hypo and cluster parameters may produce small difference according to m_toCaloFuture setting (due to
-      // extrapolation)
-      m_data[DataType::ToPrsE] = m_toCaloFuture->energy( cluster, "Prs" );
-      m_data[DataType::ToPrsM] = m_toCaloFuture->multiplicity( cluster, "Prs" );
-      m_data[DataType::ToSpdM] = m_toCaloFuture->multiplicity( cluster, "Spd" );
+    // cluster-match chi2
+    if ( !m_skipCl ) {
+      const LHCb::CaloCluster* clus = &cluster;
+      // special trick for split cluster : use full cluster matching
+      if ( fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
+        clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo, false ); // get the main cluster
+      double             chi2   = Default;
+      const LHCb::Track* ctrack = nullptr;
+      // LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc);
+      const LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
+      if ( ctable ) {
+        const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable->relations( clus );
+
+        if ( !range.empty() ) {
+          chi2   = range.front().weight();
+          ctrack = range.front();
+        }
+      } else if ( counterStat->isQuiet() )
+        counter( "Missing " + m_cmLoc ) += 1;
+
+      m_track[MatchType::ClusterMatch] = ctrack;
+      m_data[DataType::ClusterMatch]   = chi2;
     }
-    double eHcal                = m_toCaloFuture->energy( cluster, "Hcal" );
-    m_data[DataType::ToHcalE]   = eHcal;
-    m_data[DataType::Hcal2Ecal] = ( eEcal > 0 ) ? eHcal / eEcal : 0.;
+    return true;
   }
 
-  // cluster-match chi2
-  if ( !m_skipCl ) {
-    const LHCb::CaloCluster* clus = &cluster;
-    // special trick for split cluster : use full cluster matching
-    if ( fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
-      clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo, false ); // get the main cluster
-    double             chi2   = Default;
-    const LHCb::Track* ctrack = nullptr;
-    // LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc);
-    const LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
-    if ( ctable ) {
-      const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable->relations( clus );
-
-      if ( !range.empty() ) {
-        chi2   = range.front().weight();
-        ctrack = range.front();
-      }
-    } else if ( counterStat->isQuiet() )
-      counter( "Missing " + m_cmLoc ) += 1;
-
-    m_track[MatchType::ClusterMatch] = ctrack;
-    m_data[DataType::ClusterMatch]   = chi2;
+  void HypoEstimator::clean() const {
+    m_data.clear();
+    m_cluster = nullptr;
+    m_hypo    = nullptr;
+    m_track.clear();
   }
-  return true;
-}
-
-void CaloFutureHypoEstimator::clean() const {
-  m_data.clear();
-  m_cluster = nullptr;
-  m_hypo    = nullptr;
-  m_track.clear();
-}
+} // namespace Calo::Future
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index 66cf9f5ae83..ccea2eec766 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -41,77 +41,81 @@
  *  @date   2010-08-18
  */
 
-class CaloFutureHypoEstimator : public extends<GaudiTool, Calo::Future::Interfaces::IHypoEstimator, IIncidentListener> {
-public:
-  /// Standard constructor
-  using extends::extends;
-
-  StatusCode initialize() override;
-  StatusCode finalize() override;
-
-  std::optional<double> data( const LHCb::CaloCluster& cluster, Calo::Future::Enum::DataType type ) const override;
-  std::optional<double> data( const LHCb::CaloHypo& hypo, Calo::Future::Enum::DataType type ) const override;
-
-  void handle( const Incident& ) override {
-    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "IIncident Svc reset" << endmsg;
-    clean();
-  }
-
-  Calo::Future::Interfaces::IHypo2Calo* hypo2Calo() override { return m_toCaloFuture.get(); }
-
-  const LHCb::Track* toTrack( Calo::Future::Enum::MatchType match ) const override {
-    auto it = m_track.find( match );
-    return it != m_track.end() ? it->second : nullptr;
-  }
-
-  StatusCode _setProperty( const std::string& p, const std::string& v ) override { return setProperty( p, v ); };
-  bool       status() const override { return m_status; }
-
-private:
-  bool estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo = nullptr ) const;
-  bool estimator( const LHCb::CaloHypo& hypo ) const;
-  void clean() const;
-
-  using caloDataType    = std::map<Calo::Future::Enum::DataType, double>;
-  using caloMatchType   = std::map<Calo::Future::Enum::MatchType, const LHCb::Track*>;
-  using caloClusterType = std::map<Calo::Future::Enum::ClusterType, const LHCb::CaloCluster*>;
-
-  mutable caloDataType             m_data;
-  mutable caloMatchType            m_track;
-  mutable const LHCb::CaloHypo*    m_hypo    = nullptr;
-  mutable const LHCb::CaloCluster* m_cluster = nullptr;
-
-  mutable std::map<std::string, const LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable;
-  mutable bool                                                                 m_status = true;
-
-  Gaudi::Property<bool>                               m_extrapol{this, "Extrapolation", true};
-  Gaudi::Property<bool>                               m_seed{this, "AddSeed", false};
-  Gaudi::Property<bool>                               m_neig{this, "AddNeighbors", false};
-  Gaudi::Property<std::map<std::string, std::string>> m_pidLoc{
-      this,
-      "NeutralIDLocations",
-      {{"Photon", LHCb::CaloFutureIdLocation::PhotonID},
-       {"Pi0Merged", LHCb::CaloFutureIdLocation::MergedID},
-       {"PhotonFromMergedPi0", LHCb::CaloFutureIdLocation::PhotonFromMergedID}}};
-  Gaudi::Property<std::string> m_cmLoc{this, "ClusterMatchLocation",
-                                       LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch" )};
-  Gaudi::Property<std::string> m_emLoc{this, "ElectronMatchLocation",
-                                       LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ElectronMatch" )};
-  Gaudi::Property<std::string> m_bmLoc{this, "BremMatchLocation",
-                                       LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "BremMatch" )};
-  Gaudi::Property<bool>        m_skipC{this, "SkipChargedID", false};
-  Gaudi::Property<bool>        m_skipN{this, "SkipNeutralID", false};
-  Gaudi::Property<bool>        m_skipCl{this, "SkipClusterMatch", false};
-
-  PublicToolHandle<IFutureCounterLevel>            counterStat{this, "CounterLevel", "FutureCounterLevel"};
-  ToolHandle<Calo::Future::Interfaces::IHypo2Calo> m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
-  mutable ToolHandle<Calo::Future::Interfaces::IElectron> m_electron{this, "Electron", "CaloFutureElectron"};
-  mutable ToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0{this, "Pi0Separation", "FutureGammaPi0SeparationTool"};
-  mutable PublicToolHandle<IFutureGammaPi0SeparationTool> m_GammaPi0XGB{this, "PiOSeparation",
-                                                                        "FutureGammaPi0XGBoostTool"};
-  ToolHandle<Calo::Future::Interfaces::INeutralID>        m_neutralID{this, "NeutralID", "FutureNeutralIDTool"};
-  mutable ToolHandle<ICaloFutureRelationsGetter>          m_tables{this, "RelationGetter", "CaloFutureRelationsGetter"};
-
-  DeCalorimeter* m_ecal = nullptr;
-};
+namespace Calo::Future {
+
+  class HypoEstimator : public extends<GaudiTool, Interfaces::IHypoEstimator, IIncidentListener> {
+  public:
+    /// Standard constructor
+    using extends::extends;
+
+    StatusCode initialize() override;
+    StatusCode finalize() override;
+
+    std::optional<double> data( const LHCb::CaloCluster& cluster, Enum::DataType type ) const override;
+    std::optional<double> data( const LHCb::CaloHypo& hypo, Enum::DataType type ) const override;
+
+    void handle( const Incident& ) override {
+      if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "IIncident Svc reset" << endmsg;
+      clean();
+    }
+
+    Interfaces::IHypo2Calo* hypo2Calo() override { return m_toCaloFuture.get(); }
+
+    const LHCb::Track* toTrack( Enum::MatchType match ) const override {
+      auto it = m_track.find( match );
+      return it != m_track.end() ? it->second : nullptr;
+    }
+
+    StatusCode _setProperty( const std::string& p, const std::string& v ) override { return setProperty( p, v ); };
+    bool       status() const override { return m_status; }
+
+  private:
+    bool estimator( const LHCb::CaloCluster& cluster, const LHCb::CaloHypo* fromHypo = nullptr ) const;
+    bool estimator( const LHCb::CaloHypo& hypo ) const;
+    void clean() const;
+
+    using caloDataType    = std::map<Enum::DataType, double>;
+    using caloMatchType   = std::map<Enum::MatchType, const LHCb::Track*>;
+    using caloClusterType = std::map<Enum::ClusterType, const LHCb::CaloCluster*>;
+
+    mutable caloDataType             m_data;
+    mutable caloMatchType            m_track;
+    mutable const LHCb::CaloHypo*    m_hypo    = nullptr;
+    mutable const LHCb::CaloCluster* m_cluster = nullptr;
+
+    mutable std::map<std::string, const LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable;
+    mutable bool                                                                 m_status = true;
+
+    Gaudi::Property<bool>                               m_extrapol{this, "Extrapolation", true};
+    Gaudi::Property<bool>                               m_seed{this, "AddSeed", false};
+    Gaudi::Property<bool>                               m_neig{this, "AddNeighbors", false};
+    Gaudi::Property<std::map<std::string, std::string>> m_pidLoc{
+        this,
+        "NeutralIDLocations",
+        {{"Photon", LHCb::CaloFutureIdLocation::PhotonID},
+         {"Pi0Merged", LHCb::CaloFutureIdLocation::MergedID},
+         {"PhotonFromMergedPi0", LHCb::CaloFutureIdLocation::PhotonFromMergedID}}};
+    Gaudi::Property<std::string> m_cmLoc{this, "ClusterMatchLocation",
+                                         LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch" )};
+    Gaudi::Property<std::string> m_emLoc{this, "ElectronMatchLocation",
+                                         LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ElectronMatch" )};
+    Gaudi::Property<std::string> m_bmLoc{this, "BremMatchLocation",
+                                         LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "BremMatch" )};
+    Gaudi::Property<bool>        m_skipC{this, "SkipChargedID", false};
+    Gaudi::Property<bool>        m_skipN{this, "SkipNeutralID", false};
+    Gaudi::Property<bool>        m_skipCl{this, "SkipClusterMatch", false};
+
+    PublicToolHandle<IFutureCounterLevel>               counterStat{this, "CounterLevel", "FutureCounterLevel"};
+    ToolHandle<Interfaces::IHypo2Calo>                  m_toCaloFuture{this, "Hypo2Calo", "CaloFutureHypo2CaloFuture"};
+    mutable ToolHandle<Interfaces::IElectron>           m_electron{this, "Electron", "CaloFutureElectron"};
+    mutable ToolHandle<Interfaces::IGammaPi0Separation> m_GammaPi0{this, "Pi0Separation",
+                                                                   "FutureGammaPi0SeparationTool"};
+    mutable PublicToolHandle<Interfaces::IGammaPi0Separation> m_GammaPi0XGB{this, "PiOSeparation",
+                                                                            "FutureGammaPi0XGBoostTool"};
+    ToolHandle<Interfaces::INeutralID>                        m_neutralID{this, "NeutralID", "FutureNeutralIDTool"};
+    mutable ToolHandle<ICaloFutureRelationsGetter> m_tables{this, "RelationGetter", "CaloFutureRelationsGetter"};
+
+    DeCalorimeter* m_ecal = nullptr;
+  };
+} // namespace Calo::Future
 #endif // CALOFUTUREHYPOESTIMATOR_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
index 21cf75dfcaa..f4d9c21720a 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
@@ -31,184 +31,174 @@ using namespace Gaudi::Units;
 //-----------------------------------------------------------------------------
 
 // Declaration of the Tool Factory
-DECLARE_COMPONENT( FutureGammaPi0SeparationTool )
+DECLARE_COMPONENT_WITH_ID( Calo::Future::GammaPi0Separation, "FutureGammaPi0SeparationTool" )
+namespace Calo::Future {
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FutureGammaPi0SeparationTool::FutureGammaPi0SeparationTool( const std::string& type, const std::string& name,
-                                                            const IInterface* parent )
-    : base_class( type, name, parent ) {
-  declareInterface<IFutureGammaPi0SeparationTool>( this );
-}
+  //=============================================================================
+  // Initialization
+  //=============================================================================
+  StatusCode GammaPi0Separation::initialize() {
 
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode FutureGammaPi0SeparationTool::initialize() {
-
-  StatusCode sc = base_class::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;          // error printed already by GaudiAlgorithm
+    StatusCode sc = base_class::initialize(); // must be executed first
+    if ( sc.isFailure() ) return sc;          // error printed already by GaudiAlgorithm
 
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Initialize" << endmsg;
-
-  /// Retrieve geometry of detector
-  m_ecal = getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Ecal );
-
-  // TMVA discriminant
-  static const std::vector<std::string> inputVars = {"isPhfr2",   "isPhfr2r4", "abs(isPhasym)",
-                                                     "isPhkappa", "isPhEseed", "isPhE2"};
-
-  m_reader0 = std::make_unique<ReadMLPOuter>( inputVars );
-  m_reader1 = std::make_unique<ReadMLPMiddle>( inputVars );
-  m_reader2 = std::make_unique<ReadMLPInner>( inputVars );
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode FutureGammaPi0SeparationTool::finalize() {
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
-
-  m_reader0.reset();
-  m_reader1.reset();
-  m_reader2.reset();
-
-  return base_class::finalize(); // must be executed last
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-
-double FutureGammaPi0SeparationTool::isPhoton( const LHCb::CaloHypo* hypo ) {
-
-  // clear all data
-  m_data.clear();
-
-  if ( !m_ecal ) return m_def;
-  if ( LHCb::CaloMomentum( hypo ).pt() < m_minPt ) return m_def;
-
-  double fr2    = 0;
-  double fasym  = 0;
-  double fkappa = 0;
-  double fr2r4  = 0;
-  double Eseed  = 0;
-  double E2     = 0;
-  double Ecl    = 0;
-  int    area   = 0;
-
-  // evaluate the NN inputs
-  bool ecalV = ClusterVariables( hypo, fr2, fasym, fkappa, fr2r4, Ecl, Eseed, E2, area );
-
-  if ( !ecalV ) return m_def;
-  // return NN output
-  return photonDiscriminant( area, fr2, fr2r4, fasym, fkappa, Eseed, E2 );
-}
-
-bool FutureGammaPi0SeparationTool::ClusterVariables( const LHCb::CaloHypo* hypo, double& fr2, double& fasym,
-                                                     double& fkappa, double& fr2r4, double& etot, double& Eseed,
-                                                     double& E2, int& area ) {
-  m_data.clear();
-
-  if ( !hypo ) return false;
-  const LHCb::CaloCluster* cluster =
-      LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); // OD 2014/05 - change to Split Or Main  cluster
-  if ( !cluster ) return false;
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Inside ClusterVariables ------" << endmsg;
-
-  const auto cxx = cluster->position().spread()( 0, 0 );
-  const auto cyy = cluster->position().spread()( 1, 1 );
-  const auto cxy = cluster->position().spread()( 0, 1 );
-  fr2            = cxx + cyy;
-  fasym          = ( cxx > 0 && cyy > 0 ? cxy / std::sqrt( cxx * cyy ) : 0 );
-  const auto arg = ( fr2 > 0. ? 1. - 4. * ( cxx * cyy - cxy * cxy ) / ( fr2 * fr2 ) : 0. );
-  fkappa         = std::sqrt( arg > 0. ? arg : 0. );
-
-  const auto xmean = cluster->position().x();
-  const auto ymean = cluster->position().y();
-
-  // OD : WARNING cluster->e() is cluster-shape dependent (3x3 / 2x2 ...) RE-EVALUATE E3x3 instead for back.
-  // compatibility etot = cluster->e(); //same as position.e
-  etot = 0.;
-
-  const Gaudi::XYZPoint position( xmean, ymean, cluster->position().z() );
-
-  double r4      = 0.;
-  area           = -1;
-  int    ncells  = 0;
-  double secondE = 0.;
-
-  const auto& entries = cluster->entries();
-  for ( auto entry = entries.begin(); entries.end() != entry; ++entry ) {
-    const LHCb::CaloDigit* digit = entry->digit();
-    if ( !digit ) { continue; }
-    const auto fraction = entry->fraction();
-    const auto energy   = digit->e() * fraction;
+    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Initialize" << endmsg;
 
-    if ( abs( (int)digit->cellID().col() - (int)cluster->seed().col() ) <= 1 &&
-         abs( (int)digit->cellID().row() - (int)cluster->seed().row() ) <= 1 &&
-         digit->cellID().area() == cluster->seed().area() ) {
-      etot += energy;
-    }
+    /// Retrieve geometry of detector
+    m_ecal = getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Ecal );
+
+    // TMVA discriminant
+    static const std::vector<std::string> inputVars = {"isPhfr2",   "isPhfr2r4", "abs(isPhasym)",
+                                                       "isPhkappa", "isPhEseed", "isPhE2"};
+
+    m_reader0 = std::make_unique<ReadMLPOuter>( inputVars );
+    m_reader1 = std::make_unique<ReadMLPMiddle>( inputVars );
+    m_reader2 = std::make_unique<ReadMLPInner>( inputVars );
+
+    return StatusCode::SUCCESS;
+  }
+
+  //=============================================================================
+  //  Finalize
+  //=============================================================================
+  StatusCode GammaPi0Separation::finalize() {
+
+    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
+
+    m_reader0.reset();
+    m_reader1.reset();
+    m_reader2.reset();
+
+    return base_class::finalize(); // must be executed last
+  }
 
-    if ( entry->status() & LHCb::CaloDigitStatus::SeedCell ) {
-      area  = digit->cellID().area();
-      Eseed = energy;
+  //=============================================================================
+  // Main execution
+  //=============================================================================
+
+  double GammaPi0Separation::isPhoton( const LHCb::CaloHypo& hypo ) {
+
+    constexpr double c_def = -1.e+06;
+    // clear all data
+    m_data.clear();
+
+    if ( !m_ecal ) return c_def;
+    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return c_def;
+
+    double fr2    = 0;
+    double fasym  = 0;
+    double fkappa = 0;
+    double fr2r4  = 0;
+    double Eseed  = 0;
+    double E2     = 0;
+    double Ecl    = 0;
+    int    area   = 0;
+
+    // evaluate the NN inputs
+    bool ecalV = ClusterVariables( hypo, fr2, fasym, fkappa, fr2r4, Ecl, Eseed, E2, area );
+
+    if ( !ecalV ) return c_def;
+    // return NN output
+    return photonDiscriminant( area, fr2, fr2r4, fasym, fkappa, Eseed, E2 );
+  }
+
+  bool GammaPi0Separation::ClusterVariables( const LHCb::CaloHypo& hypo, double& fr2, double& fasym, double& fkappa,
+                                             double& fr2r4, double& etot, double& Eseed, double& E2, int& area ) {
+    m_data.clear();
+
+    const LHCb::CaloCluster* cluster =
+        LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo ); // OD 2014/05 - change to Split Or Main  cluster
+    if ( !cluster ) return false;
+
+    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Inside ClusterVariables ------" << endmsg;
+
+    const auto cxx = cluster->position().spread()( 0, 0 );
+    const auto cyy = cluster->position().spread()( 1, 1 );
+    const auto cxy = cluster->position().spread()( 0, 1 );
+    fr2            = cxx + cyy;
+    fasym          = ( cxx > 0 && cyy > 0 ? cxy / std::sqrt( cxx * cyy ) : 0 );
+    const auto arg = ( fr2 > 0. ? 1. - 4. * ( cxx * cyy - cxy * cxy ) / ( fr2 * fr2 ) : 0. );
+    fkappa         = std::sqrt( arg > 0. ? arg : 0. );
+
+    const auto xmean = cluster->position().x();
+    const auto ymean = cluster->position().y();
+
+    // OD : WARNING cluster->e() is cluster-shape dependent (3x3 / 2x2 ...) RE-EVALUATE E3x3 instead for back.
+    // compatibility etot = cluster->e(); //same as position.e
+    etot = 0.;
+
+    const Gaudi::XYZPoint position( xmean, ymean, cluster->position().z() );
+
+    double r4      = 0.;
+    area           = -1;
+    int    ncells  = 0;
+    double secondE = 0.;
+
+    const auto& entries = cluster->entries();
+    for ( auto entry = entries.begin(); entries.end() != entry; ++entry ) {
+      const LHCb::CaloDigit* digit = entry->digit();
+      if ( !digit ) { continue; }
+      const auto fraction = entry->fraction();
+      const auto energy   = digit->e() * fraction;
+
+      if ( abs( (int)digit->cellID().col() - (int)cluster->seed().col() ) <= 1 &&
+           abs( (int)digit->cellID().row() - (int)cluster->seed().row() ) <= 1 &&
+           digit->cellID().area() == cluster->seed().area() ) {
+        etot += energy;
+      }
+
+      if ( entry->status() & LHCb::CaloDigitStatus::SeedCell ) {
+        area  = digit->cellID().area();
+        Eseed = energy;
+      } else {
+        if ( energy > secondE ) { secondE = energy; }
+      }
+
+      const auto& pos = m_ecal->cellCenter( digit->cellID() );
+      const auto  x   = pos.x();
+      const auto  y   = pos.y();
+
+      if ( energy <= 0 ) { continue; }
+      const double weight = energy > 0.0 ? energy : 0.0;
+
+      auto rr = std::pow( x - xmean, 2 ) + std::pow( y - ymean, 2 );
+      if ( entries.size() <= 1 || rr < 1.e-10 ) { rr = 0; } // to avoid huge unphysical value due to machine precision
+      r4 += weight * rr * rr;
+
+      ncells++;
+    } // loop cluster cells
+
+    if ( etot > 0. ) {
+      r4 /= etot;
+      fr2r4 = ( r4 != 0 ) ? ( r4 - fr2 * fr2 ) / r4 : 0.;
+      E2    = ( secondE + Eseed ) / etot;
+      Eseed = Eseed / etot;
     } else {
-      if ( energy > secondE ) { secondE = energy; }
+      // should never happen
+      r4    = 0;
+      fr2r4 = 0.;
+      E2    = 0.;
+      Eseed = 0.;
     }
 
-    const auto& pos = m_ecal->cellCenter( digit->cellID() );
-    const auto  x   = pos.x();
-    const auto  y   = pos.y();
-
-    if ( energy <= 0 ) { continue; }
-    const double weight = energy > 0.0 ? energy : 0.0;
-
-    auto rr = std::pow( x - xmean, 2 ) + std::pow( y - ymean, 2 );
-    if ( entries.size() <= 1 || rr < 1.e-10 ) { rr = 0; } // to avoid huge unphysical value due to machine precision
-    r4 += weight * rr * rr;
-
-    ncells++;
-  } // loop cluster cells
-
-  if ( etot > 0. ) {
-    r4 /= etot;
-    fr2r4 = ( r4 != 0 ) ? ( r4 - fr2 * fr2 ) / r4 : 0.;
-    E2    = ( secondE + Eseed ) / etot;
-    Eseed = Eseed / etot;
-  } else {
-    // should never happen
-    r4    = 0;
-    fr2r4 = 0.;
-    E2    = 0.;
-    Eseed = 0.;
+    m_data[Enum::DataType::isPhotonEcl]   = etot;
+    m_data[Enum::DataType::isPhotonFr2]   = fr2;
+    m_data[Enum::DataType::isPhotonFr2r4] = fr2r4;
+    m_data[Enum::DataType::isPhotonAsym]  = fasym;
+    m_data[Enum::DataType::isPhotonKappa] = fkappa;
+    m_data[Enum::DataType::isPhotonEseed] = Eseed;
+    m_data[Enum::DataType::isPhotonE2]    = E2;
+    return true;
   }
 
-  m_data["Ecl"]   = etot;
-  m_data["Fr2"]   = fr2;
-  m_data["Fr2r4"] = fr2r4;
-  m_data["Asym"]  = fasym;
-  m_data["Kappa"] = fkappa;
-  m_data["Eseed"] = Eseed;
-  m_data["E2"]    = E2;
-  return true;
-}
-
-double FutureGammaPi0SeparationTool::photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa,
-                                                         double Eseed, double E2 ) {
-  std::vector<double> input = {r2,    r2r4, std::abs( asym ), kappa,
-                               Eseed, // already divided by Ecl
-                               E2};   // means (e2+eseed)/ecl
-
-  double value =
-      ( area == 0 ? m_reader0->GetMvaValue( input )
-                  : area == 1 ? m_reader1->GetMvaValue( input ) : area == 2 ? m_reader2->GetMvaValue( input ) : -1e10 );
-  // info() << " INPUT TO GAMMA/PI0 : NN[" << input << "]= " << value << " (area="<<area<<")"<< endmsg;
-  return value;
-}
+  double GammaPi0Separation::photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa,
+                                                 double Eseed, double E2 ) const {
+    std::vector<double> input = {r2,    r2r4, std::abs( asym ), kappa,
+                                 Eseed, // already divided by Ecl
+                                 E2};   // means (e2+eseed)/ecl
+
+    return area == 0
+               ? m_reader0->GetMvaValue( input )
+               : area == 1 ? m_reader1->GetMvaValue( input ) : area == 2 ? m_reader2->GetMvaValue( input ) : -1e10;
+  }
+} // namespace Calo::Future
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
index 9d02e5d9b64..56384587e0b 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
@@ -35,45 +35,36 @@
  *  @author Miriam Calvo Gomez
  *  @date   2019-03-28
  */
-
-class FutureGammaPi0SeparationTool : public extends<GaudiTool, IFutureGammaPi0SeparationTool> {
-public:
-  /// Standard constructor
-  FutureGammaPi0SeparationTool( const std::string& type, const std::string& name, const IInterface* parent );
-
-  StatusCode initialize() override;
-  StatusCode finalize() override;
-
-  // double isPhoton(const LHCb::Particle* gamma);
-  double isPhoton( const LHCb::CaloHypo* hypo ) override;
-
-  bool ClusterVariables( const LHCb::CaloHypo* hypo, double& fr2, double& fasym, double& fkappa, double& fr2r4,
-                         double& etot, double& Eseed, double& E2, int& area ) override;
-
-  double inputData( std::string data ) override { //@TODO: const-ify
-    // try ecal data
-    auto it = m_data.find( data );
-    if ( it != m_data.end() ) return it->second;
-    return 0.;
-  }
-  std::map<std::string, double> inputDataMap() override { return m_data; }
-
-  double isPhoton( const double* v ) override {
-    return photonDiscriminant( int( v[0] ), v[1], v[2], v[3], v[4], v[5], v[6] );
-  }
-
-private:
-  Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
-
-  std::unique_ptr<IClassifierReader> m_reader0;
-  std::unique_ptr<IClassifierReader> m_reader1;
-  std::unique_ptr<IClassifierReader> m_reader2;
-
-  const DeCalorimeter* m_ecal = nullptr;
-
-  double photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa, double Eseed, double E2 );
-
-  std::map<std::string, double> m_data;
-  double                        m_def = -1.e+06;
-};
+namespace Calo::Future {
+  class GammaPi0Separation : public extends<GaudiTool, Interfaces::IGammaPi0Separation> {
+  public:
+    /// Standard constructor
+    using extends::extends;
+
+    StatusCode initialize() override;
+    StatusCode finalize() override;
+
+    double isPhoton( const LHCb::CaloHypo& hypo ) override;
+    double isPhoton( LHCb::span<const double> v ) override {
+      return photonDiscriminant( int( v[0] ), v[1], v[2], v[3], v[4], v[5], v[6] );
+    }
+    const std::map<Enum::DataType, double>& inputDataMap() override { return m_data; }
+
+  private:
+    bool   ClusterVariables( const LHCb::CaloHypo& hypo, double& fr2, double& fasym, double& fkappa, double& fr2r4,
+                             double& etot, double& Eseed, double& E2, int& area );
+    double photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa, double Eseed,
+                               double E2 ) const;
+
+    Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
+
+    std::unique_ptr<IClassifierReader> m_reader0;
+    std::unique_ptr<IClassifierReader> m_reader1;
+    std::unique_ptr<IClassifierReader> m_reader2;
+
+    const DeCalorimeter* m_ecal = nullptr;
+
+    std::map<Enum::DataType, double> m_data;
+  };
+} // namespace Calo::Future
 #endif // FUTUREGAMMAPI0SEPARATIONTOOL_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
index e3049064dd7..47ceb6dfea9 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
@@ -67,165 +67,161 @@ namespace {
 } // namespace
 
 // Declaration of the Tool Factory
-DECLARE_COMPONENT( FutureGammaPi0XGBoostTool )
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode FutureGammaPi0XGBoostTool::initialize() {
-
-  StatusCode sc = base_class::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;          // error printed already by GaudiAlgorithm
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Initialize" << endmsg;
-
-  /// Retrieve geometry of detector
-  m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
-
-  const std::string paramEnv  = "PARAMFILESROOT";
-  std::string       paramRoot = std::string( getenv( paramEnv.c_str() ) );
-
-  m_xgb0    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl0.model" );
-  m_xgb1    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl1.model" );
-  m_xgb2    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl2.model" );
-  m_xgb03_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound03.model" );
-  m_xgb06_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound06.model" );
-  m_xgb14_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound14.model" );
-  m_xgb17_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound17.model" );
-  m_xgb25_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound25.model" );
-  m_xgb28_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound28.model" );
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode FutureGammaPi0XGBoostTool::finalize() {
-
-  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
-
-  m_xgb0.reset();
-  m_xgb1.reset();
-  m_xgb2.reset();
-  m_xgb03_b.reset();
-  m_xgb06_b.reset();
-  m_xgb14_b.reset();
-  m_xgb17_b.reset();
-  m_xgb25_b.reset();
-  m_xgb28_b.reset();
-
-  return base_class::finalize(); // must be executed last
-}
-
-//=============================================================================
-// Main execution
-//=============================================================================
-
-double FutureGammaPi0XGBoostTool::isPhoton( const LHCb::CaloHypo* hypo ) {
-
-  if ( !m_ecal ) return m_def;
-  if ( LHCb::CaloMomentum( hypo ).pt() < m_minPt ) return m_def;
-  const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo );
-  if ( !cluster ) return m_def;
-
-  std::vector<double> rawEnergyVector( 25, 0.0 );
-
-  int  cluster_type = getClusterType( cluster->seed() );
-  bool rawEnergy    = GetRawEnergy( hypo, cluster_type, rawEnergyVector );
-
-  if ( !rawEnergy ) return m_def;
-
-  double prediction_xgb = XGBDiscriminant( cluster_type, rawEnergyVector );
-  return prediction_xgb;
-}
-
-double FutureGammaPi0XGBoostTool::XGBDiscriminant( int cluster_type, std::vector<double>& row_energies ) {
-
-  double value = -1e10;
-  switch ( cluster_type ) {
-  case 0:
-    value = m_xgb0->getClassifierValues( row_energies );
-    break;
-  case 1:
-    value = m_xgb1->getClassifierValues( row_energies );
-    break;
-  case 2:
-    value = m_xgb2->getClassifierValues( row_energies );
-    break;
-  case 3:
-    value = m_xgb03_b->getClassifierValues( row_energies );
-    break;
-  case 4:
-    value = m_xgb14_b->getClassifierValues( row_energies );
-    break;
-  case 5:
-    value = m_xgb25_b->getClassifierValues( row_energies );
-    break;
-  case 6:
-    value = m_xgb06_b->getClassifierValues( row_energies );
-    break;
-  case 7:
-    value = m_xgb17_b->getClassifierValues( row_energies );
-    break;
-  case 8:
-    value = m_xgb28_b->getClassifierValues( row_energies );
-    break;
-  default:
-    warning() << "FutureGammaPi0XGBoostTool: Unsupperted cluster type" << endmsg;
+DECLARE_COMPONENT_WITH_ID( Calo::Future::GammaPi0XGBoost, "FutureGammaPi0XGBoostTool" )
+
+namespace Calo::Future {
+  //=============================================================================
+  // Initialization
+  //=============================================================================
+  StatusCode GammaPi0XGBoost::initialize() {
+
+    StatusCode sc = base_class::initialize(); // must be executed first
+    if ( sc.isFailure() ) return sc;          // error printed already by GaudiAlgorithm
+
+    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Initialize" << endmsg;
+
+    /// Retrieve geometry of detector
+    m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
+
+    std::string paramRoot = getenv( "PARAMFILESROOT" );
+
+    m_xgb0    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl0.model" );
+    m_xgb1    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl1.model" );
+    m_xgb2    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl2.model" );
+    m_xgb03_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound03.model" );
+    m_xgb06_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound06.model" );
+    m_xgb14_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound14.model" );
+    m_xgb17_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound17.model" );
+    m_xgb25_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound25.model" );
+    m_xgb28_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound28.model" );
+
+    return StatusCode::SUCCESS;
+  }
+
+  //=============================================================================
+  //  Finalize
+  //=============================================================================
+  StatusCode GammaPi0XGBoost::finalize() {
+
+    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
+
+    m_xgb0.reset();
+    m_xgb1.reset();
+    m_xgb2.reset();
+    m_xgb03_b.reset();
+    m_xgb06_b.reset();
+    m_xgb14_b.reset();
+    m_xgb17_b.reset();
+    m_xgb25_b.reset();
+    m_xgb28_b.reset();
+
+    return base_class::finalize(); // must be executed last
+  }
+
+  //=============================================================================
+  // Main execution
+  //=============================================================================
+
+  double GammaPi0XGBoost::isPhoton( const LHCb::CaloHypo& hypo ) {
+    constexpr double c_def = -1.e+06;
+
+    if ( !m_ecal ) return c_def;
+    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return c_def;
+    const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
+    if ( !cluster ) return c_def;
+
+    std::array<double, 25> rawEnergyVector{0};
+
+    int  cluster_type = getClusterType( cluster->seed() );
+    bool rawEnergy    = GetRawEnergy( hypo, cluster_type, rawEnergyVector );
+
+    if ( !rawEnergy ) return c_def;
+
+    return XGBDiscriminant( cluster_type, rawEnergyVector );
   }
-  return value;
-}
 
-bool FutureGammaPi0XGBoostTool::GetRawEnergy( const LHCb::CaloHypo* hypo, int& cluster_type,
-                                              std::vector<double>& rowEnergy ) const {
-  if ( nullptr == hypo ) return false;
+  double GammaPi0XGBoost::XGBDiscriminant( int cluster_type, LHCb::span<const double> raw_energies ) {
+
+    double value = -1e10;
+    switch ( cluster_type ) {
+    case 0:
+      value = m_xgb0->getClassifierValues( raw_energies );
+      break;
+    case 1:
+      value = m_xgb1->getClassifierValues( raw_energies );
+      break;
+    case 2:
+      value = m_xgb2->getClassifierValues( raw_energies );
+      break;
+    case 3:
+      value = m_xgb03_b->getClassifierValues( raw_energies );
+      break;
+    case 4:
+      value = m_xgb14_b->getClassifierValues( raw_energies );
+      break;
+    case 5:
+      value = m_xgb25_b->getClassifierValues( raw_energies );
+      break;
+    case 6:
+      value = m_xgb06_b->getClassifierValues( raw_energies );
+      break;
+    case 7:
+      value = m_xgb17_b->getClassifierValues( raw_energies );
+      break;
+    case 8:
+      value = m_xgb28_b->getClassifierValues( raw_energies );
+      break;
+    default:
+      warning() << "GammaPi0XGBoost: Unsupperted cluster type" << endmsg;
+    }
+    return value;
+  }
 
-  const LHCb::CaloDigits*  digits_full = getIfExists<LHCb::CaloDigits>( LHCb::CaloDigitLocation::Ecal );
-  const LHCb::CaloCluster* cluster =
-      LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); // OD 2014/05 - change to Split Or Main  cluster
+  bool GammaPi0XGBoost::GetRawEnergy( const LHCb::CaloHypo& hypo, int cluster_type,
+                                      LHCb::span<double, 25> rawEnergy ) const {
 
-  if ( nullptr == digits_full || nullptr == cluster ) return false;
+    const LHCb::CaloDigits*  digits_full = getIfExists<LHCb::CaloDigits>( LHCb::CaloDigitLocation::Ecal );
+    const LHCb::CaloCluster* cluster =
+        LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo ); // OD 2014/05 - change to Split Or Main  cluster
 
-  LHCb::CaloCellID centerID = cluster->seed();
+    if ( nullptr == digits_full || nullptr == cluster ) return false;
 
-  std::vector<std::vector<double>> vector_cells( 5, std::vector<double>( 5, 0.0 ) );
+    LHCb::CaloCellID centerID = cluster->seed();
 
-  std::vector<int> col_numbers = {(int)centerID.col() - 2, (int)centerID.col() - 1, (int)centerID.col(),
+    auto col_numbers = std::array{(int)centerID.col() - 2, (int)centerID.col() - 1, (int)centerID.col(),
                                   (int)centerID.col() + 1, (int)centerID.col() + 2};
-  std::vector<int> row_numbers = {(int)centerID.row() - 2, (int)centerID.row() - 1, (int)centerID.row(),
+    auto row_numbers = std::array{(int)centerID.row() - 2, (int)centerID.row() - 1, (int)centerID.row(),
                                   (int)centerID.row() + 1, (int)centerID.row() + 2};
 
-  if ( cluster_type > 2 ) {
-    for ( auto& col_number : col_numbers ) {
-      for ( auto& row_number : row_numbers ) {
-        const auto id_  = LHCb::CaloCellID( centerID.calo(), centerID.area(), row_number, col_number );
-        auto*      test = digits_full->object( id_ );
-        if ( test ) {
-          vector_cells[col_number - (int)centerID.col() + 2][row_number - (int)centerID.row() + 2] = test->e();
-        } else {
-          continue;
+    auto rawEnergy_ = [&rawEnergy]( int i, int j ) -> double& { return rawEnergy[i * 5 + j]; };
+    std::fill( rawEnergy.begin(), rawEnergy.end(), 0. );
+
+    if ( cluster_type > 2 ) {
+      for ( auto col_number : col_numbers ) {
+        for ( auto row_number : row_numbers ) {
+          const auto id_  = LHCb::CaloCellID( centerID.calo(), centerID.area(), row_number, col_number );
+          auto*      test = digits_full->object( id_ );
+          if ( test ) {
+            rawEnergy_( col_number - (int)centerID.col() + 2, row_number - (int)centerID.row() + 2 ) = test->e();
+          } else {
+            continue;
+          }
         }
       }
-    }
-  }
-
-  else {
-    for ( auto& col_number : col_numbers ) {
-      for ( auto& row_number : row_numbers ) {
-        const auto id_  = LHCb::CaloCellID( centerID.calo(), centerID.area(), row_number, col_number );
-        auto*      test = digits_full->object( id_ );
-        if ( test ) {
-          vector_cells[col_number - (int)centerID.col() + 2][row_number - (int)centerID.row() + 2] = test->e();
-        } else {
-          continue;
+    } else {
+      for ( auto col_number : col_numbers ) {
+        for ( auto row_number : row_numbers ) {
+          const auto id_  = LHCb::CaloCellID( centerID.calo(), centerID.area(), row_number, col_number );
+          auto*      test = digits_full->object( id_ );
+          if ( test ) {
+            rawEnergy_( col_number - (int)centerID.col() + 2, row_number - (int)centerID.row() + 2 ) = test->e();
+          } else {
+            continue;
+          }
         }
       }
     }
-  }
 
-  for ( int i = 0; i < 5; i++ ) {
-    for ( int j = 0; j < 5; j++ ) { rowEnergy[i * 5 + j] = vector_cells[i][j]; }
+    return true;
   }
-  return true;
-}
+} // namespace Calo::Future
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
index a344ad8e465..4d2aabb40ba 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
@@ -33,57 +33,39 @@
  *  @author @sayankotor
  *  @date   2018-03-24
  */
-
-class FutureGammaPi0XGBoostTool : public extends<GaudiTool, IFutureGammaPi0SeparationTool> {
-
-public:
-  using extends::extends;
-
-  StatusCode initialize() override;
-  StatusCode finalize() override;
-
-  // double isPhoton(const LHCb::Particle* gamma);
-  double isPhoton( const LHCb::CaloHypo* hypo ) override;
-
-  bool GetRawEnergy( const LHCb::CaloHypo* hypo, int& cluster_type, std::vector<double>& rowEnergy ) const;
-  std::vector<std::vector<double>> GetCluster( const LHCb::CaloCellID& centerID,
-                                               const LHCb::CaloDigits* digits_full ) const;
-
-  double inputData( std::string ) override { //@TODO: const-ify
-    /* // try ecal data */
-    /* auto it = m_data.find(data); */
-    /* if( it != m_data.end() )return it->second; */
-    /* // else try prs data : */
-    /* auto itp = m_prsdata.find(data); */
-    /* if( itp != m_prsdata.end() )return itp->second; */
-    /* // yapa */
-    return 0.;
-  }
-
-  std::map<std::string, double> inputDataMap() override { return std::map<std::string, double>(); }
-  bool ClusterVariables( const LHCb::CaloHypo*, double&, double&, double&, double&, double&, double&, double&,
-                         int& ) override {
-    return true;
-  }
-  double isPhoton( const double* ) override { return 0.0; };
-
-private:
-  Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
-
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb0;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb1;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb2;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb03_b;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb14_b;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb25_b;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb06_b;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb17_b;
-  std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb28_b;
-
-  const DeCalorimeter* m_ecal = nullptr;
-
-  double XGBDiscriminant( int cluster_type, std::vector<double>& row_energies );
-
-  const double m_def = -1.e+06;
-};
+namespace Calo::Future {
+  class GammaPi0XGBoost : public extends<GaudiTool, Interfaces::IGammaPi0Separation> {
+
+  public:
+    using extends::extends;
+
+    StatusCode initialize() override;
+    StatusCode finalize() override;
+
+    double                                  isPhoton( const LHCb::CaloHypo& hypo ) override;
+    double                                  isPhoton( LHCb::span<const double> ) override { return 0; }
+    const std::map<Enum::DataType, double>& inputDataMap() override {
+      static std::map<Enum::DataType, double> s_map;
+      return s_map;
+    }
+
+  private:
+    bool GetRawEnergy( const LHCb::CaloHypo& hypo, int cluster_type, LHCb::span<double, 25> rawEnergy ) const;
+    Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
+
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb0;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb1;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb2;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb03_b;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb14_b;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb25_b;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb06_b;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb17_b;
+    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb28_b;
+
+    const DeCalorimeter* m_ecal = nullptr;
+
+    double XGBDiscriminant( int cluster_type, LHCb::span<const double> raw_energies );
+  };
+} // namespace Calo::Future
 #endif // FutureGammaPi0XGBoostTool_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
index 9dc8ef3bbed..2d097760bb4 100644
--- a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
@@ -27,26 +27,22 @@ FutureXGBClassifierPhPi0::FutureXGBClassifierPhPi0( const std::string& path ) {
 
 void FutureXGBClassifierPhPi0::setPath( const std::string& path ) {
   XGBoosterCreate( &m_cache_matrix, 1, &m_booster );
-  try {
-    XGBoosterLoadModel( m_booster, path.c_str() );
-  } catch ( const std::exception& e ) { log << MSG::WARNING << "Standard exception " << endmsg; }
+  XGBoosterLoadModel( m_booster, path.c_str() );
 }
 
-double FutureXGBClassifierPhPi0::getClassifierValues( const std::vector<double>& featureValues ) {
+double FutureXGBClassifierPhPi0::getClassifierValues( LHCb::span<const double> featureValues ) {
   // currently XGBoost only supports float
   std::vector<float> features_f( featureValues.begin(), featureValues.end() );
 
   // fill the feature vector into a XGBoost DMatrix
-  XGDMatrixCreateFromMat( &features_f.at( 0 ), 1, features_f.size(), 0, &m_feature_matrix );
+  XGDMatrixCreateFromMat( features_f.data(), 1, features_f.size(), 0, &m_feature_matrix );
 
   // XGBoost returns the predictions into a arrayish object and return
   // its size
-  unsigned long predictions_length;
-  const float*  predictions;
-  try {
-    XGBoosterPredict( m_booster, m_feature_matrix, 0, 0, &predictions_length, &predictions );
-  } catch ( ... ) { log << MSG::WARNING << "some exeption " << endmsg; }
+  unsigned long predictions_length = 0;
+  const float*  predictions        = nullptr;
+  XGBoosterPredict( m_booster, m_feature_matrix, 0, 0, &predictions_length, &predictions );
   std::vector<double> vec_predictions;
   for ( unsigned int i = 0; i < predictions_length; i++ ) { vec_predictions.push_back( predictions[i] ); }
   return vec_predictions[0];
-}
\ No newline at end of file
+}
diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
index 53abbc4d988..dd3a54e5acf 100644
--- a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
+++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
@@ -14,27 +14,20 @@
 #include "GaudiKernel/IMessageSvc.h"
 #include "GaudiKernel/MsgStream.h"
 #include "GaudiKernel/ServiceHandle.h"
+#include "Kernel/STLExtensions.h"
 #include "xgboost/c_api.h"
 #include <string>
 #include <vector>
 
-class IClassifier {
+class FutureXGBClassifierPhPi0 {
 public:
-  virtual ~IClassifier() = default;
-
+  FutureXGBClassifierPhPi0();
+  FutureXGBClassifierPhPi0( const std::string& path );
   /**    * @brief      Main classification method    *
-   * Takes a vector of values of features and returns the corresponding MVA
-   * output.
+   * Takes a vector of feature values, and return the corresponding MVA output.
    *    * @param[in]  featureValues  A vector of feature values
    *    * @return     MVA classifier value    */
-  virtual double getClassifierValues( const std::vector<double>& featureValues ) = 0;
-};
-
-class FutureXGBClassifierPhPi0 : public IClassifier {
-public:
-  FutureXGBClassifierPhPi0();
-  FutureXGBClassifierPhPi0( const std::string& path );
-  double                     getClassifierValues( const std::vector<double>& featureValues ) override;
+  double                     getClassifierValues( LHCb::span<const double> featureValues );
   void                       setPath( const std::string& path );
   ServiceHandle<IMessageSvc> msgh = ServiceHandle<IMessageSvc>( "MessageSvc", "XGBLog" );
   MsgStream                  log  = MsgStream( &( *msgh ), "XGBLog" );
diff --git a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
index 5d396048c5a..b7575cb6a0c 100644
--- a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
+++ b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
@@ -108,12 +108,11 @@ StatusCode FutureNeutralProtoParticleAddNeutralID::execute() {
       pOk &= addInput( pV[12], proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM15 );
       pOk &= addInput( pV[13], proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM30 );
       pOk &= addInput( pV[14], proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM45 );
-      const double* ppV = pV;
 
       if ( m_isPhoton.value() && pOk ) {
         const auto temp = proto->info( LHCb::ProtoParticle::additionalInfo::IsPhoton, -1. );
         proto->eraseInfo( LHCb::ProtoParticle::additionalInfo::IsPhoton );
-        const auto val = ( pt > m_isPhoton_Pt.value() ) ? m_gammaPi0->isPhoton( ppV ) : -1.;
+        const auto val = ( pt > m_isPhoton_Pt.value() ) ? m_gammaPi0->isPhoton( pV ) : -1.;
         proto->addInfo( LHCb::ProtoParticle::additionalInfo::IsPhoton, val );
         if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
           debug() << "UPDATING IsPhoton : " << temp << " ---> "
diff --git a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h
index e7691cd1a12..9045252ca39 100644
--- a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h
+++ b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h
@@ -33,15 +33,15 @@ public:
   StatusCode execute() override; ///< Algorithm execution
 
 private:
-  Gaudi::Property<std::string>                     m_input{this, "Input", LHCb::ProtoParticleLocation::Neutrals};
-  Gaudi::Property<bool>                            m_isNotE{this, "UpdateIsNotE", true};
-  Gaudi::Property<bool>                            m_isNotH{this, "UpdateIsNotH", true};
-  Gaudi::Property<bool>                            m_isPhoton{this, "UpdateIsPhoton", true};
-  Gaudi::Property<double>                          m_isNotE_Pt{this, "MinPtIsNotE", 75.0};
-  Gaudi::Property<double>                          m_isNotH_Pt{this, "MinPtIsNotH", 75.0};
-  Gaudi::Property<double>                          m_isPhoton_Pt{this, "MinPtIsPhoton", 2000.0};
-  ToolHandle<IFutureGammaPi0SeparationTool>        m_gammaPi0{this, "FutureGammaPi0SeparationTool",
-                                                       "FutureGammaPi0SeparationTool"};
+  Gaudi::Property<std::string> m_input{this, "Input", LHCb::ProtoParticleLocation::Neutrals};
+  Gaudi::Property<bool>        m_isNotE{this, "UpdateIsNotE", true};
+  Gaudi::Property<bool>        m_isNotH{this, "UpdateIsNotH", true};
+  Gaudi::Property<bool>        m_isPhoton{this, "UpdateIsPhoton", true};
+  Gaudi::Property<double>      m_isNotE_Pt{this, "MinPtIsNotE", 75.0};
+  Gaudi::Property<double>      m_isNotH_Pt{this, "MinPtIsNotH", 75.0};
+  Gaudi::Property<double>      m_isPhoton_Pt{this, "MinPtIsPhoton", 2000.0};
+  ToolHandle<Calo::Future::Interfaces::IGammaPi0Separation> m_gammaPi0{this, "FutureGammaPi0SeparationTool",
+                                                                       "FutureGammaPi0SeparationTool"};
   ToolHandle<Calo::Future::Interfaces::INeutralID> m_neutralID{this, "FutureNeutralIDTool", "FutureNeutralIDTool"};
 };
 
-- 
GitLab


From b80ddfaa1f0af5d4e6a7eca0078ff5456eb4bb8c Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Fri, 9 Aug 2019 22:10:25 +0200
Subject: [PATCH 8/9] Follow changes to IGammaPi0Separation::isPhoton and
 INeutralID::isNot{E,H}

* instead of returning double, with unclear special value
  to distinguish absence of information, return std::optional<double>
---
 Calo/CaloMoniDst/src/CaloPhotonChecker.cpp    |  1 -
 .../CaloFutureReco/src/CaloFutureSelector.cpp | 31 +---------------
 .../CaloFutureReco/src/CaloFutureSelector.h   | 15 +-------
 .../src/CaloFutureHypoEstimator.cpp           | 27 +++++++-------
 .../src/CaloFutureHypoEstimator.h             | 12 ++----
 .../src/FutureGammaPi0SeparationTool.cpp      | 37 +++++++++++--------
 .../src/FutureGammaPi0SeparationTool.h        | 12 +++---
 .../src/FutureGammaPi0XGBoostTool.cpp         | 11 +++---
 .../src/FutureGammaPi0XGBoostTool.h           |  4 +-
 .../src/FutureNeutralIDTool.cpp               | 16 ++++----
 .../CaloFutureTools/src/FutureNeutralIDTool.h |  8 ++--
 ...FutureNeutralProtoParticleAddNeutralID.cpp |  2 +-
 12 files changed, 68 insertions(+), 108 deletions(-)

diff --git a/Calo/CaloMoniDst/src/CaloPhotonChecker.cpp b/Calo/CaloMoniDst/src/CaloPhotonChecker.cpp
index 95bd622d10a..42f032a903f 100644
--- a/Calo/CaloMoniDst/src/CaloPhotonChecker.cpp
+++ b/Calo/CaloMoniDst/src/CaloPhotonChecker.cpp
@@ -17,7 +17,6 @@
 #include "GaudiKernel/Vector3DTypes.h"
 // From PartProp
 #include "CaloDet/DeCalorimeter.h"
-#include "CaloInterfaces/ICaloHypoLikelihood.h"
 #include "CaloUtils/Calo2Track.h"
 #include "CaloUtils/CaloMomentum.h"
 #include "CaloUtils/ClusterFunctors.h"
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp
index b9719aea05c..6408682aace 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp
@@ -27,19 +27,6 @@
 
 DECLARE_COMPONENT( CaloFutureSelector )
 
-// ============================================================================
-/** Standard constructor
- *  @param    type   tool type (?)
- *  @param    name   tool name
- *  @param    parent tool parent
- */
-// ============================================================================
-CaloFutureSelector::CaloFutureSelector( const std::string& type, const std::string& name, const IInterface* parent )
-    : GaudiTool( type, name, parent ) {
-  // interfaces
-  declareInterface<ICaloFutureClusterSelector>( this );
-}
-
 // ============================================================================
 /** standard initialization of the tool
  *  @see IAlgTool
@@ -55,24 +42,11 @@ StatusCode CaloFutureSelector::initialize() {
   /// locate the tool
   m_likelihood = m_lhName.empty() ? tool<ICaloFutureLikelihood>( m_lhType, this )
                                   : tool<ICaloFutureLikelihood>( m_lhType, m_lhName, this );
-  if ( 0 == m_likelihood ) { return StatusCode::FAILURE; }
+  if ( !m_likelihood ) { return StatusCode::FAILURE; }
   //
   return StatusCode::SUCCESS;
 }
 
-// ============================================================================
-/** standard finalization  of the tool
- *  @see IAlgTool
- *  @see AlgTool
- *  @see GaudiTool
- *  @return status code
- */
-// ============================================================================
-StatusCode CaloFutureSelector::finalize() {
-  /// finalize the base class
-  return GaudiTool::finalize();
-}
-
 // ============================================================================
 /** "select"/"preselect" method (functor interface)
  *  @see ICaloFutureClusterSelector
@@ -81,8 +55,7 @@ StatusCode CaloFutureSelector::finalize() {
  */
 // ============================================================================
 bool CaloFutureSelector::operator()( const LHCb::CaloCluster* cluster ) const {
-  if ( 0 == cluster ) { return false; }
-  return m_cut <= ( *m_likelihood )( cluster );
+  return cluster && m_cut <= ( *m_likelihood )( cluster );
 }
 
 // ============================================================================
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h
index 5f1742ace36..db51bb1f2cd 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h
@@ -33,7 +33,7 @@ struct ICaloFutureLikelihood; // from CaloFutureInterfaces ;
  *  @author Vanya Belyaev Ivan.Belyaev@itep.ru
  *  @date   31/03/2002
  */
-class CaloFutureSelector : public virtual ICaloFutureClusterSelector, public GaudiTool {
+class CaloFutureSelector : public extends<GaudiTool, ICaloFutureClusterSelector> {
 public:
   /** "select"/"preselect" method
    *  @see ICaloFutureClusterSelector
@@ -57,20 +57,9 @@ public:
    */
   StatusCode initialize() override;
 
-  /** standard finalization  of the tool
-   *  @see IAlgTool
-   *  @see AlgTool
-   *  @see GaudiTool
-   *  @return status code
-   */
-  StatusCode finalize() override;
-
   /** Standard constructor
-   *  @param    type   tool type (?)
-   *  @param    name   tool name
-   *  @param    parent tool parent
    */
-  CaloFutureSelector( const std::string& type, const std::string& name, const IInterface* parent );
+  using extends::extends;
 
 private:
   // type of Likelyhood tool to be used
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index 961c7a8362a..afe918cc853 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -64,7 +64,7 @@ namespace Calo::Future {
       }
     }
     auto it = m_data.find( type );
-    if ( it != m_data.end() ) return m_data[type];
+    if ( it != m_data.end() ) return it->second;
     return {};
   }
 
@@ -79,7 +79,7 @@ namespace Calo::Future {
       }
     }
     auto it = m_data.find( type );
-    if ( it != m_data.end() ) return m_data[type];
+    if ( it != m_data.end() ) return it->second;
     return {};
   }
 
@@ -245,9 +245,13 @@ namespace Calo::Future {
       }
     }
 
+    auto insert_if = [&]( DataType key, std::optional<double> val ) {
+      if ( val ) m_data[key] = val.value();
+    };
+
     // gamma/pi0 separation
-    m_data[DataType::isPhoton]    = m_GammaPi0->isPhoton( hypo );
-    m_data[DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( hypo );
+    insert_if( DataType::isPhoton, m_GammaPi0->isPhoton( hypo ) );
+    insert_if( DataType::isPhotonXGB, m_GammaPi0XGB->isPhoton( hypo ) );
 
     // 1- Ecal variables :
     for ( const auto& [key, val] : m_GammaPi0->inputDataMap() ) m_data[key] = val;
@@ -279,8 +283,8 @@ namespace Calo::Future {
                                                                  .spdm    = get_data( DataType::HypoSpdM )};
 #pragma GCC diagnostic pop
 
-    m_data[DataType::isNotH] = m_neutralID->isNotH( hypo, obs );
-    m_data[DataType::isNotE] = m_neutralID->isNotE( hypo, obs );
+    insert_if( DataType::isNotH, m_neutralID->isNotH( hypo, obs ) );
+    insert_if( DataType::isNotE, m_neutralID->isNotE( hypo, obs ) );
 
     return ok;
   }
@@ -317,7 +321,7 @@ namespace Calo::Future {
 
       m_data[DataType::E1]     = seed->e();
       auto   it                = m_data.find( DataType::HypoE );
-      double eHypo             = ( it != m_data.end() ) ? m_data[DataType::HypoE] : 0;
+      double eHypo             = ( it != m_data.end() ) ? it->second : 0;
       m_data[DataType::E1Hypo] = eHypo > 0. ? ( seed->e() ) / eHypo : -1.;
       LHCb::CaloCellID sid     = seed->cellID();
       m_data[DataType::CellID] = sid.all();
@@ -393,22 +397,17 @@ namespace Calo::Future {
       // special trick for split cluster : use full cluster matching
       if ( fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
         clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo, false ); // get the main cluster
-      double             chi2   = Default;
-      const LHCb::Track* ctrack = nullptr;
       // LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc);
       const LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
       if ( ctable ) {
         const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable->relations( clus );
 
         if ( !range.empty() ) {
-          chi2   = range.front().weight();
-          ctrack = range.front();
+          m_track[MatchType::ClusterMatch] = range.front();
+          m_data[DataType::ClusterMatch]   = range.front().weight();
         }
       } else if ( counterStat->isQuiet() )
         counter( "Missing " + m_cmLoc ) += 1;
-
-      m_track[MatchType::ClusterMatch] = ctrack;
-      m_data[DataType::ClusterMatch]   = chi2;
     }
     return true;
   }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
index ccea2eec766..de45e5dcba2 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h
@@ -74,14 +74,10 @@ namespace Calo::Future {
     bool estimator( const LHCb::CaloHypo& hypo ) const;
     void clean() const;
 
-    using caloDataType    = std::map<Enum::DataType, double>;
-    using caloMatchType   = std::map<Enum::MatchType, const LHCb::Track*>;
-    using caloClusterType = std::map<Enum::ClusterType, const LHCb::CaloCluster*>;
-
-    mutable caloDataType             m_data;
-    mutable caloMatchType            m_track;
-    mutable const LHCb::CaloHypo*    m_hypo    = nullptr;
-    mutable const LHCb::CaloCluster* m_cluster = nullptr;
+    mutable std::map<Enum::DataType, double>              m_data;
+    mutable std::map<Enum::MatchType, const LHCb::Track*> m_track;
+    mutable const LHCb::CaloHypo*                         m_hypo    = nullptr;
+    mutable const LHCb::CaloCluster*                      m_cluster = nullptr;
 
     mutable std::map<std::string, const LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable;
     mutable bool                                                                 m_status = true;
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
index f4d9c21720a..04d533e0f53 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp
@@ -76,14 +76,13 @@ namespace Calo::Future {
   // Main execution
   //=============================================================================
 
-  double GammaPi0Separation::isPhoton( const LHCb::CaloHypo& hypo ) {
+  std::optional<double> GammaPi0Separation::isPhoton( const LHCb::CaloHypo& hypo ) {
 
-    constexpr double c_def = -1.e+06;
     // clear all data
     m_data.clear();
 
-    if ( !m_ecal ) return c_def;
-    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return c_def;
+    if ( !m_ecal ) return {};
+    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return {};
 
     double fr2    = 0;
     double fasym  = 0;
@@ -97,7 +96,7 @@ namespace Calo::Future {
     // evaluate the NN inputs
     bool ecalV = ClusterVariables( hypo, fr2, fasym, fkappa, fr2r4, Ecl, Eseed, E2, area );
 
-    if ( !ecalV ) return c_def;
+    if ( !ecalV ) return {};
     // return NN output
     return photonDiscriminant( area, fr2, fr2r4, fasym, fkappa, Eseed, E2 );
   }
@@ -118,7 +117,7 @@ namespace Calo::Future {
     fr2            = cxx + cyy;
     fasym          = ( cxx > 0 && cyy > 0 ? cxy / std::sqrt( cxx * cyy ) : 0 );
     const auto arg = ( fr2 > 0. ? 1. - 4. * ( cxx * cyy - cxy * cxy ) / ( fr2 * fr2 ) : 0. );
-    fkappa         = std::sqrt( arg > 0. ? arg : 0. );
+    fkappa         = arg > 0. ? std::sqrt( arg ) : 0.;
 
     const auto xmean = cluster->position().x();
     const auto ymean = cluster->position().y();
@@ -135,11 +134,10 @@ namespace Calo::Future {
     double secondE = 0.;
 
     const auto& entries = cluster->entries();
-    for ( auto entry = entries.begin(); entries.end() != entry; ++entry ) {
-      const LHCb::CaloDigit* digit = entry->digit();
+    for ( const auto& entry : entries ) {
+      const LHCb::CaloDigit* digit = entry.digit();
       if ( !digit ) { continue; }
-      const auto fraction = entry->fraction();
-      const auto energy   = digit->e() * fraction;
+      const auto energy = digit->e() * entry.fraction();
 
       if ( abs( (int)digit->cellID().col() - (int)cluster->seed().col() ) <= 1 &&
            abs( (int)digit->cellID().row() - (int)cluster->seed().row() ) <= 1 &&
@@ -147,7 +145,7 @@ namespace Calo::Future {
         etot += energy;
       }
 
-      if ( entry->status() & LHCb::CaloDigitStatus::SeedCell ) {
+      if ( entry.status() & LHCb::CaloDigitStatus::SeedCell ) {
         area  = digit->cellID().area();
         Eseed = energy;
       } else {
@@ -191,14 +189,21 @@ namespace Calo::Future {
     return true;
   }
 
-  double GammaPi0Separation::photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa,
-                                                 double Eseed, double E2 ) const {
+  std::optional<double> GammaPi0Separation::photonDiscriminant( int area, double r2, double r2r4, double asym,
+                                                                double kappa, double Eseed, double E2 ) const {
     std::vector<double> input = {r2,    r2r4, std::abs( asym ), kappa,
                                  Eseed, // already divided by Ecl
                                  E2};   // means (e2+eseed)/ecl
 
-    return area == 0
-               ? m_reader0->GetMvaValue( input )
-               : area == 1 ? m_reader1->GetMvaValue( input ) : area == 2 ? m_reader2->GetMvaValue( input ) : -1e10;
+    switch ( area ) {
+    case 0:
+      return m_reader0->GetMvaValue( input );
+    case 1:
+      return m_reader1->GetMvaValue( input );
+    case 2:
+      return m_reader2->GetMvaValue( input );
+    default:
+      return {};
+    }
   }
 } // namespace Calo::Future
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
index 56384587e0b..50d37211e19 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h
@@ -44,17 +44,17 @@ namespace Calo::Future {
     StatusCode initialize() override;
     StatusCode finalize() override;
 
-    double isPhoton( const LHCb::CaloHypo& hypo ) override;
-    double isPhoton( LHCb::span<const double> v ) override {
+    std::optional<double> isPhoton( const LHCb::CaloHypo& hypo ) override;
+    std::optional<double> isPhoton( LHCb::span<const double> v ) override {
       return photonDiscriminant( int( v[0] ), v[1], v[2], v[3], v[4], v[5], v[6] );
     }
     const std::map<Enum::DataType, double>& inputDataMap() override { return m_data; }
 
   private:
-    bool   ClusterVariables( const LHCb::CaloHypo& hypo, double& fr2, double& fasym, double& fkappa, double& fr2r4,
-                             double& etot, double& Eseed, double& E2, int& area );
-    double photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa, double Eseed,
-                               double E2 ) const;
+    bool ClusterVariables( const LHCb::CaloHypo& hypo, double& fr2, double& fasym, double& fkappa, double& fr2r4,
+                           double& etot, double& Eseed, double& E2, int& area );
+    std::optional<double> photonDiscriminant( int area, double r2, double r2r4, double asym, double kappa, double Eseed,
+                                              double E2 ) const;
 
     Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
 
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
index 47ceb6dfea9..bcc693f11ac 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
@@ -122,20 +122,19 @@ namespace Calo::Future {
   // Main execution
   //=============================================================================
 
-  double GammaPi0XGBoost::isPhoton( const LHCb::CaloHypo& hypo ) {
-    constexpr double c_def = -1.e+06;
+  std::optional<double> GammaPi0XGBoost::isPhoton( const LHCb::CaloHypo& hypo ) {
 
-    if ( !m_ecal ) return c_def;
-    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return c_def;
+    if ( !m_ecal ) return {};
+    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return {};
     const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
-    if ( !cluster ) return c_def;
+    if ( !cluster ) return {};
 
     std::array<double, 25> rawEnergyVector{0};
 
     int  cluster_type = getClusterType( cluster->seed() );
     bool rawEnergy    = GetRawEnergy( hypo, cluster_type, rawEnergyVector );
 
-    if ( !rawEnergy ) return c_def;
+    if ( !rawEnergy ) return {};
 
     return XGBDiscriminant( cluster_type, rawEnergyVector );
   }
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
index 4d2aabb40ba..fb725b1bfb8 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
@@ -42,8 +42,8 @@ namespace Calo::Future {
     StatusCode initialize() override;
     StatusCode finalize() override;
 
-    double                                  isPhoton( const LHCb::CaloHypo& hypo ) override;
-    double                                  isPhoton( LHCb::span<const double> ) override { return 0; }
+    std::optional<double>                   isPhoton( const LHCb::CaloHypo& hypo ) override;
+    std::optional<double>                   isPhoton( LHCb::span<const double> ) override { return 0; }
     const std::map<Enum::DataType, double>& inputDataMap() override {
       static std::map<Enum::DataType, double> s_map;
       return s_map;
diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
index 84000503428..c59a852b8b9 100644
--- a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp
@@ -73,21 +73,21 @@ StatusCode FutureNeutralIDTool::finalize() {
 // Main execution
 //=============================================================================
 
-double FutureNeutralIDTool::isNotE( const LHCb::CaloHypo&                                    hypo,
-                                    const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
+std::optional<double> FutureNeutralIDTool::isNotE( const LHCb::CaloHypo&                                    hypo,
+                                                   const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
   double pt = LHCb::CaloMomentum( &hypo ).pt();
-  if ( pt <= m_minPt ) return Calo::Future::Enum::Default;
+  if ( pt <= m_minPt ) return {};
   const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false );
-  if ( !cluster ) return Calo::Future::Enum::Default;
+  if ( !cluster ) return {};
   return isNotE( v );
 }
 
-double FutureNeutralIDTool::isNotH( const LHCb::CaloHypo&                                    hypo,
-                                    const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
+std::optional<double> FutureNeutralIDTool::isNotH( const LHCb::CaloHypo&                                    hypo,
+                                                   const Calo::Future::Interfaces::INeutralID::Observables& v ) const {
   double pt = LHCb::CaloMomentum( &hypo ).pt();
-  if ( pt <= m_minPt ) return Calo::Future::Enum::Default;
+  if ( pt <= m_minPt ) return {};
   const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo, false );
-  if ( !cluster ) return Calo::Future::Enum::Default;
+  if ( !cluster ) return {};
   return isNotH( v );
 }
 
diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
index 363aba975e1..c9d92b3e09c 100644
--- a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h
@@ -42,10 +42,10 @@ public:
   StatusCode initialize() override;
   StatusCode finalize() override;
 
-  double isNotE( const LHCb::CaloHypo&                                    hypo,
-                 const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
-  double isNotH( const LHCb::CaloHypo&                                    hypo,
-                 const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
+  std::optional<double> isNotE( const LHCb::CaloHypo&                                    hypo,
+                                const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
+  std::optional<double> isNotH( const LHCb::CaloHypo&                                    hypo,
+                                const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
 
   double isNotE( const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
   double isNotH( const Calo::Future::Interfaces::INeutralID::Observables& v ) const override;
diff --git a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
index b7575cb6a0c..6c69d10dcea 100644
--- a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
+++ b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp
@@ -112,7 +112,7 @@ StatusCode FutureNeutralProtoParticleAddNeutralID::execute() {
       if ( m_isPhoton.value() && pOk ) {
         const auto temp = proto->info( LHCb::ProtoParticle::additionalInfo::IsPhoton, -1. );
         proto->eraseInfo( LHCb::ProtoParticle::additionalInfo::IsPhoton );
-        const auto val = ( pt > m_isPhoton_Pt.value() ) ? m_gammaPi0->isPhoton( pV ) : -1.;
+        const auto val = ( pt > m_isPhoton_Pt.value() ) ? m_gammaPi0->isPhoton( pV ).value_or( -1. ) : -1.;
         proto->addInfo( LHCb::ProtoParticle::additionalInfo::IsPhoton, val );
         if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) )
           debug() << "UPDATING IsPhoton : " << temp << " ---> "
-- 
GitLab


From 46dca84d33f7a7c14d69ab5b83af8720a3ef771a Mon Sep 17 00:00:00 2001
From: Gerhard Raven <gerhard.raven@nikhef.nl>
Date: Sat, 10 Aug 2019 12:44:53 +0200
Subject: [PATCH 9/9] Tweak tools

* remove redundant constructors
* avoid default values, use `optional` instead
* make FutureXGBClassifierPhPi0 thread safe
* streamline FutureGammaPi0XGBoostTool
---
 .../src/CaloFuture2CaloFuture.cpp             |   3 +-
 .../CaloFutureTools/src/CaloFuture2MCTool.cpp |  25 +---
 .../CaloFutureTools/src/CaloFuture2MCTool.h   |   6 +-
 .../src/CaloFutureHypoEstimator.cpp           | 123 ++++++++----------
 .../src/CheckCaloFutureHypoRef.cpp            |  10 --
 .../src/CheckCaloFutureHypoRef.h              |  12 +-
 .../src/FutureGammaPi0XGBoostTool.cpp         | 101 +++-----------
 .../src/FutureGammaPi0XGBoostTool.h           |  15 +--
 .../src/FutureXGBClassifierPhPi0.cpp          |  28 ++--
 .../src/FutureXGBClassifierPhPi0.h            |  14 +-
 10 files changed, 116 insertions(+), 221 deletions(-)

diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
index 7522f335b40..6c18ea2e0ca 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp
@@ -193,8 +193,7 @@ CaloFuture2CaloFuture::cellIDs( const LHCb::CaloCellID& fromId, const std::strin
       for ( int j = 0; j != 2; ++j ) {
         double           x        = m_fromDet->cellCenter( fromId ).X() + ( i * 2 - 1 ) * fromSize;
         double           y        = m_fromDet->cellCenter( fromId ).Y() + ( j * 2 - 1 ) * fromSize;
-        Gaudi::XYZPoint  corner   = Gaudi::XYZPoint( x, y, center.Z() );
-        LHCb::CaloCellID cornerId = m_toDet->Cell( corner );
+        LHCb::CaloCellID cornerId = m_toDet->Cell( {x, y, center.Z()} );
         if ( LHCb::CaloCellID() == cornerId ) continue;
         toId = cornerId;
       }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp
index d6fea9e3b0e..e167026c5e5 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp
@@ -31,15 +31,6 @@
 // Declaration of the Tool Factory
 DECLARE_COMPONENT( CaloFuture2MCTool )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-CaloFuture2MCTool::CaloFuture2MCTool( const std::string& type, const std::string& name, const IInterface* parent )
-    : base_class( type, name, parent ) {
-  declareInterface<ICaloFuture2MCTool>( this );
-  m_cluster2MCLoc = "Relations/" + LHCb::CaloClusterLocation::Default;
-}
-
 //=============================================================================
 
 StatusCode CaloFuture2MCTool::initialize() {
@@ -405,19 +396,17 @@ void CaloFuture2MCTool::mcDigest() {
   } // end loop over MCParticles
   // build MC tree
   // 1- get related MC particle (seed) without any descendant listed in the related mcParticles
+  auto hasProd = [&]( const LHCb::MCParticle* mcp ) {
+    const auto& vertices = mcp->endVertices();
+    return std::any_of( vertices.begin(), vertices.end(), [&]( const auto& v ) {
+      return std::any_of( v->products().begin(), v->products().end(),
+                          [&]( const auto& p ) { return m_mcMap.find( p ) != m_mcMap.end(); } );
+    } );
+  };
   std::vector<const LHCb::MCParticle*> seeds;
   for ( const auto& imap : m_mcMap ) {
     const LHCb::MCParticle* mcPart = imap.first;
     int                     _pID   = mcPart->particleID().abspid();
-
-    auto hasProd = [&]( const LHCb::MCParticle* mcp ) {
-      const auto& vertices = mcp->endVertices();
-      return std::any_of( vertices.begin(), vertices.end(), [&]( const auto& v ) {
-        return std::any_of( v->products().begin(), v->products().end(),
-                            [&]( const auto& p ) { return m_mcMap.find( p ) != m_mcMap.end(); } );
-      } );
-    };
-
     // include electron with brems and converted photons as seeds
     if ( _pID == 11 || _pID == 22 || !hasProd( mcPart ) ) seeds.push_back( mcPart );
   }
diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h
index 44bf370c317..1b617bd031d 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h
+++ b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h
@@ -59,7 +59,7 @@ public:
   };
 
   /// Standard constructor
-  CaloFuture2MCTool( const std::string& type, const std::string& name, const IInterface* parent );
+  using extends::extends;
 
   StatusCode initialize() override;
 
@@ -123,7 +123,9 @@ private:
   LHCb::Particle*                         m_part    = nullptr;
   CaloFutureMCTools::CaloFutureMCMap      m_mcMap;
   //
-  Gaudi::Property<std::string> m_cluster2MCLoc{this, "Cluster2MCTable", "", "Cluster->MC relation table location"};
+  Gaudi::Property<std::string> m_cluster2MCLoc{this, "Cluster2MCTable",
+                                               "Relations/" + LHCb::CaloClusterLocation::Default,
+                                               "Cluster->MC relation table location"};
 
   Gaudi::Property<std::string> m_digit2MCLoc{this, "Digit2MCTable", "Relations/" + LHCb::CaloDigitLocation::Default,
                                              "Digit->MC relation table location"};
diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
index afe918cc853..af5ceca49d0 100644
--- a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
+++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp
@@ -104,74 +104,64 @@ namespace Calo::Future {
     m_data[DataType::HypoPrsM] = std::count_if( digits.begin(), digits.end(), isPrs );
     m_data[DataType::HypoPrsE] =
         std::accumulate( digits.begin(), digits.end(), 0., [&]( double sumPrs, const auto& id ) {
-          if ( id && isPrs( id ) ) { sumPrs += id->e(); }
+          if ( id && isPrs( id ) ) sumPrs += id->e();
           return sumPrs;
         } );
 
     // electron matching
     if ( !m_skipC ) {
-      double             chi2e  = Default;
-      double             trajL  = Default;
-      const LHCb::Track* etrack = nullptr;
       // LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc);
       const auto* etable = m_tables->getTrHypoTable2D( m_emLoc );
       if ( etable ) {
         const auto range = etable->inverse()->relations( &hypo );
         if ( !range.empty() ) {
-          chi2e  = range.front().weight();
-          etrack = range.front();
-          if ( etrack ) {
+          m_data[DataType::ElectronMatch]   = range.front().weight();
+          m_track[MatchType::ElectronMatch] = range.front();
+          if ( range.front() ) {
             LHCb::ProtoParticle dummy;
-            dummy.setTrack( etrack );
+            dummy.setTrack( range.front() );
             dummy.addToCalo( &hypo );
             // CaloFutureElectron->caloTrajectory must be after addToCalo
-            if ( m_electron->set( &dummy ) ) trajL = m_electron->caloTrajectoryL( CaloPlane::ShowerMax );
+            if ( m_electron->set( &dummy ) )
+              m_data[DataType::TrajectoryL] = m_electron->caloTrajectoryL( CaloPlane::ShowerMax );
             m_electron->set( static_cast<LHCb::ProtoParticle*>( nullptr ) );
           }
         }
       } else if ( counterStat->isQuiet() )
         counter( "Missing " + m_emLoc ) += 1;
 
-      m_track[MatchType::ElectronMatch] = etrack;
-      m_data[DataType::ElectronMatch]   = chi2e;
-      m_data[DataType::TrajectoryL]     = trajL;
-
       // brem matching
-      double             chi2b  = Default;
-      const LHCb::Track* btrack = nullptr;
       // LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc);
-      const auto* btable = m_tables->getTrHypoTable2D( m_bmLoc );
-      if ( btable ) {
+
+      if ( const auto* btable = m_tables->getTrHypoTable2D( m_bmLoc ); btable ) {
         const auto range = btable->inverse()->relations( &hypo );
         if ( !range.empty() ) {
-          chi2b  = range.front().weight();
-          btrack = range.front();
+          m_track[MatchType::BremMatch] = range.front();
+          m_data[DataType::BremMatch]   = range.front().weight();
         }
       } else if ( counterStat->isQuiet() )
         counter( "Missing " + m_bmLoc ) += 1;
-
-      m_track[MatchType::BremMatch] = btrack;
-      m_data[DataType::BremMatch]   = chi2b;
     }
 
     // NeutralID (warning : protect against infinite loop from CaloFuturePhotonIDAlg using this tools with DoD active)
     if ( !m_skipN ) {
       for ( auto&& [hypothesis, loc] : m_pidLoc ) {
-        const LHCb::CaloFuture2Track::IHypoEvalTable* tbl = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( loc );
-        if ( tbl ) {
+
+        if ( const LHCb::CaloFuture2Track::IHypoEvalTable* tbl =
+                 getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable>( loc );
+             tbl ) {
           m_idTable[hypothesis] = tbl;
         } else if ( counterStat->isQuiet() ) {
           counter( "Missing " + loc ) += 1;
         }
       }
-      std::ostringstream type( "" );
+      std::ostringstream type;
       type << hypo.hypothesis();
-      std::string                                   hypothesis = type.str();
-      const LHCb::CaloFuture2Track::IHypoEvalTable* idTable    = nullptr;
-      auto                                          it         = m_idTable.find( hypothesis );
-      if ( it != m_idTable.end() ) idTable = it->second;
-      if ( idTable ) {
-        const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( &hypo );
+      std::string hypothesis = type.str();
+      auto        it         = m_idTable.find( hypothesis );
+      if ( const LHCb::CaloFuture2Track::IHypoEvalTable* idTable = ( it != m_idTable.end() ? it->second : nullptr );
+           idTable ) {
+        const auto& range = idTable->relations( &hypo );
         if ( !range.empty() ) m_data[DataType::NeutralID] = range.front().to();
       }
     }
@@ -183,9 +173,9 @@ namespace Calo::Future {
       Warning( "Cluster point to NULL", StatusCode::SUCCESS ).ignore();
     } else {
       // Ecal seed
-      auto iseed = LHCb::ClusterFunctors::locateDigit( cluster->entries().begin(), cluster->entries().end(),
-                                                       LHCb::CaloDigitStatus::SeedCell );
-      if ( iseed != cluster->entries().end() ) {
+      if ( auto iseed = LHCb::ClusterFunctors::locateDigit( cluster->entries().begin(), cluster->entries().end(),
+                                                            LHCb::CaloDigitStatus::SeedCell );
+           iseed != cluster->entries().end() ) {
         const LHCb::CaloDigit* seed   = iseed->digit();
         const LHCb::CaloCellID idseed = seed->cellID();
         double                 sum9   = 0.;
@@ -194,29 +184,28 @@ namespace Calo::Future {
         std::array<double, 4> Prse4s = {};
         std::array<double, 9> Prse9  = {};
 
-        for ( auto id = digits.begin(); id != digits.end(); ++id ) {
+        for ( const auto& id : digits ) {
 
-          if ( 0 == *id || !isPrs( *id ) ) continue;
-          LHCb::CaloCellID id2 = ( *id )->cellID();
-          if ( abs( (int)( *id )->cellID().row() - (int)idseed.row() ) < 2 &&
-               abs( (int)( *id )->cellID().col() - (int)idseed.col() ) < 2 ) {
+          if ( 0 == id || !isPrs( id ) ) continue;
+          LHCb::CaloCellID id2 = id->cellID();
+          if ( abs( (int)( id )->cellID().row() - (int)idseed.row() ) < 2 &&
+               abs( (int)( id )->cellID().col() - (int)idseed.col() ) < 2 ) {
             // Build sum1 and sum9
             //
-            sum9 += ( *id )->e();
-            if ( ( *id )->cellID().row() == idseed.row() && ( *id )->cellID().col() == idseed.col() )
-              sum1 = ( *id )->e();
+            sum9 += id->e();
+            if ( id->cellID().row() == idseed.row() && id->cellID().col() == idseed.col() ) sum1 = id->e();
             // Prs4
             //
-            if ( id2.col() <= idseed.col() && id2.row() >= idseed.row() ) Prse4s[0] += ( *id )->e();
-            if ( id2.col() >= idseed.col() && id2.row() >= idseed.row() ) Prse4s[1] += ( *id )->e();
-            if ( id2.col() >= idseed.col() && id2.row() <= idseed.row() ) Prse4s[2] += ( *id )->e();
-            if ( id2.col() <= idseed.col() && id2.row() <= idseed.row() ) Prse4s[3] += ( *id )->e();
+            if ( id2.col() <= idseed.col() && id2.row() >= idseed.row() ) Prse4s[0] += ( id )->e();
+            if ( id2.col() >= idseed.col() && id2.row() >= idseed.row() ) Prse4s[1] += ( id )->e();
+            if ( id2.col() >= idseed.col() && id2.row() <= idseed.row() ) Prse4s[2] += ( id )->e();
+            if ( id2.col() <= idseed.col() && id2.row() <= idseed.row() ) Prse4s[3] += ( id )->e();
             // Select the 3X3 cluster
             //
             int dcol     = (int)id2.col() - (int)idseed.col() + 1;
             int drow     = (int)id2.row() - (int)idseed.row() + 1;
             int indexPrs = drow * 3 + dcol;
-            Prse9[indexPrs] += ( *id )->e();
+            Prse9[indexPrs] += id->e();
           }
         }
         //    Build E19 and E49
@@ -224,9 +213,8 @@ namespace Calo::Future {
         double Prse4max =
             std::accumulate( Prse4s.begin(), Prse4s.end(), 0., []( double l, double r ) { return std::max( l, r ); } );
         m_data[DataType::PrsE4Max] = Prse4max;
-        double sum9Inv             = 0.;
         if ( sum9 > 0. ) {
-          sum9Inv                  = 1. / sum9;
+          double sum9Inv           = 1. / sum9;
           m_data[DataType::PrsE49] = Prse4max * sum9Inv;
           m_data[DataType::PrsE19] = sum1 * sum9Inv;
         } else {
@@ -298,13 +286,12 @@ namespace Calo::Future {
       if ( counterStat->isQuiet() ) counter( "Empty cluster" ) += 1;
       return false;
     }
-    auto iseed = LHCb::ClusterFunctors::locateDigit( cluster.entries().begin(), cluster.entries().end(),
-                                                     LHCb::CaloDigitStatus::SeedCell );
-
-    if ( iseed != cluster.entries().end() ) {
+    if ( auto iseed = LHCb::ClusterFunctors::locateDigit( cluster.entries().begin(), cluster.entries().end(),
+                                                          LHCb::CaloDigitStatus::SeedCell );
+         iseed != cluster.entries().end() ) {
 
       const LHCb::CaloDigit* seed = iseed->digit();
-      if ( 0 == seed ) {
+      if ( !seed ) {
         if ( counterStat->isQuiet() ) counter( "Seed points to NULL" ) += 1;
         return false;
       }
@@ -335,12 +322,12 @@ namespace Calo::Future {
       int                   code      = 0.;
       int                   mult      = 0.;
       int                   nsat      = 0; // number of saturated cells
-      for ( auto ie = cluster.entries().begin(); cluster.entries().end() != ie; ++ie ) {
-        const LHCb::CaloDigit* dig = ie->digit();
+      for ( const auto& ie : cluster.entries() ) {
+        const LHCb::CaloDigit* dig = ie.digit();
         if ( !dig ) continue;
-        double ecel = dig->e() * ie->fraction();
-        if ( ( ( ie->status() & LHCb::CaloDigitStatus::UseForEnergy ) != 0 ||
-               ( ie->status() & LHCb::CaloDigitStatus::UseForCovariance ) != 0 ) &&
+        double ecel = dig->e() * ie.fraction();
+        if ( ( ( ie.status() & LHCb::CaloDigitStatus::UseForEnergy ) != 0 ||
+               ( ie.status() & LHCb::CaloDigitStatus::UseForCovariance ) != 0 ) &&
              m_ecal->isSaturated( dig->e(), dig->cellID() ) )
           nsat++;
         LHCb::CaloCellID id = dig->cellID();
@@ -355,7 +342,7 @@ namespace Calo::Future {
         // new info
         ee9 += dig->e();
         mult++;
-        if ( ie->status() & LHCb::CaloDigitStatus::SharedCell ) hasShared = true;
+        if ( ie.status() & LHCb::CaloDigitStatus::SharedCell ) hasShared = true;
         if ( !( id == sid ) && ecel > e2 ) {
           e2     = ecel;
           int dc = (int)id.col() - (int)sid.col() + 1;
@@ -371,13 +358,13 @@ namespace Calo::Future {
 
       code = mult * 10 + code;
       if ( hasShared ) code *= -1;
-      m_data[DataType::ClusterCode] = (double)code;
-      m_data[DataType::ClusterFrac] = ( e9 > 0. ) ? e9 / ee9 : -1;
+      m_data[DataType::ClusterCode] = code;
+      m_data[DataType::ClusterFrac] = ( e9 > 0. ? e9 / ee9 : -1 );
 
       m_data[DataType::E4]  = e4max;
       m_data[DataType::E9]  = e9;
-      m_data[DataType::E49] = ( e9 > 0. ) ? e4max / e9 : 0.;
-      m_data[DataType::E19] = ( e9 > 0. ) ? seed->e() / e9 : -1.;
+      m_data[DataType::E49] = ( e9 > 0. ? e4max / e9 : 0. );
+      m_data[DataType::E19] = ( e9 > 0. ? seed->e() / e9 : -1. );
 
       if ( !fromHypo ) {
         // hypo and cluster parameters may produce small difference according to m_toCaloFuture setting (due to
@@ -398,10 +385,10 @@ namespace Calo::Future {
       if ( fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )
         clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo, false ); // get the main cluster
       // LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc);
-      const LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
-      if ( ctable ) {
-        const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable->relations( clus );
-
+      if ( const LHCb::CaloFuture2Track::IClusTrTable* ctable =
+               getIfExists<LHCb::CaloFuture2Track::IClusTrTable>( m_cmLoc );
+           ctable ) {
+        const auto& range = ctable->relations( clus );
         if ( !range.empty() ) {
           m_track[MatchType::ClusterMatch] = range.front();
           m_data[DataType::ClusterMatch]   = range.front().weight();
diff --git a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp
index 3bf040ff89d..9b41ec99b40 100644
--- a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp
+++ b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp
@@ -25,16 +25,6 @@
 // Declaration of the Algorithm Factory
 DECLARE_COMPONENT( CheckCaloFutureHypoRef )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-CheckCaloFutureHypoRef::CheckCaloFutureHypoRef( const std::string& name, ISvcLocator* pSvcLocator )
-    : GaudiAlgorithm( name, pSvcLocator ) {
-  using namespace LHCb::CaloFutureAlgUtils;
-  m_inputs.value() = {CaloFutureHypoLocation( "Photons" ), CaloFutureHypoLocation( "Electrons" ),
-                      CaloFutureHypoLocation( "MergedPi0s" )};
-}
-
 //=============================================================================
 // Main execution
 //=============================================================================
diff --git a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h
index 6ae2fdd154d..14b94775dd6 100644
--- a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h
+++ b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h
@@ -24,13 +24,17 @@
  */
 class CheckCaloFutureHypoRef : public GaudiAlgorithm {
 public:
-  /// Standard constructor
-  CheckCaloFutureHypoRef( const std::string& name, ISvcLocator* pSvcLocator );
+  using GaudiAlgorithm::GaudiAlgorithm;
 
   StatusCode execute() override; ///< Algorithm execution
 
 private:
-  Gaudi::Property<std::vector<std::string>> m_inputs{this, "CaloHypos"};
-  IFutureCounterLevel*                      counterStat = nullptr;
+  Gaudi::Property<std::vector<std::string>> m_inputs{
+      this,
+      "CaloHypos",
+      {LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "Photons" ),
+       LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "Electrons" ),
+       LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( "MergedPi0s" )}};
+  IFutureCounterLevel* counterStat = nullptr;
 };
 #endif // CHECKCALOFUTUREHYPOREF_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
index bcc693f11ac..9c253135abd 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp
@@ -82,108 +82,50 @@ namespace Calo::Future {
 
     /// Retrieve geometry of detector
     m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal );
+    if ( !m_ecal ) return StatusCode::FAILURE;
 
     std::string paramRoot = getenv( "PARAMFILESROOT" );
 
-    m_xgb0    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl0.model" );
-    m_xgb1    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl1.model" );
-    m_xgb2    = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_simpl2.model" );
-    m_xgb03_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound03.model" );
-    m_xgb06_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound06.model" );
-    m_xgb14_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound14.model" );
-    m_xgb17_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound17.model" );
-    m_xgb25_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound25.model" );
-    m_xgb28_b = std::make_unique<FutureXGBClassifierPhPi0>( paramRoot + "/data/GammaPi0XgbTool_bound28.model" );
+    m_xgb[0].emplace( paramRoot + "/data/GammaPi0XgbTool_simpl0.model" );
+    m_xgb[1].emplace( paramRoot + "/data/GammaPi0XgbTool_simpl1.model" );
+    m_xgb[2].emplace( paramRoot + "/data/GammaPi0XgbTool_simpl2.model" );
+    m_xgb[3].emplace( paramRoot + "/data/GammaPi0XgbTool_bound03.model" );
+    m_xgb[4].emplace( paramRoot + "/data/GammaPi0XgbTool_bound14.model" );
+    m_xgb[5].emplace( paramRoot + "/data/GammaPi0XgbTool_bound25.model" );
+    m_xgb[6].emplace( paramRoot + "/data/GammaPi0XgbTool_bound06.model" );
+    m_xgb[7].emplace( paramRoot + "/data/GammaPi0XgbTool_bound17.model" );
+    m_xgb[8].emplace( paramRoot + "/data/GammaPi0XgbTool_bound28.model" );
 
     return StatusCode::SUCCESS;
   }
 
-  //=============================================================================
-  //  Finalize
-  //=============================================================================
-  StatusCode GammaPi0XGBoost::finalize() {
-
-    if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "==> Finalize" << endmsg;
-
-    m_xgb0.reset();
-    m_xgb1.reset();
-    m_xgb2.reset();
-    m_xgb03_b.reset();
-    m_xgb06_b.reset();
-    m_xgb14_b.reset();
-    m_xgb17_b.reset();
-    m_xgb25_b.reset();
-    m_xgb28_b.reset();
-
-    return base_class::finalize(); // must be executed last
-  }
-
   //=============================================================================
   // Main execution
   //=============================================================================
 
   std::optional<double> GammaPi0XGBoost::isPhoton( const LHCb::CaloHypo& hypo ) {
-
-    if ( !m_ecal ) return {};
-    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return {};
+    if ( LHCb::CaloMomentum( &hypo ).pt() < m_minPt ) return std::nullopt;
     const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo );
-    if ( !cluster ) return {};
-
-    std::array<double, 25> rawEnergyVector{0};
-
-    int  cluster_type = getClusterType( cluster->seed() );
-    bool rawEnergy    = GetRawEnergy( hypo, cluster_type, rawEnergyVector );
-
-    if ( !rawEnergy ) return {};
-
-    return XGBDiscriminant( cluster_type, rawEnergyVector );
-  }
-
-  double GammaPi0XGBoost::XGBDiscriminant( int cluster_type, LHCb::span<const double> raw_energies ) {
-
-    double value = -1e10;
-    switch ( cluster_type ) {
-    case 0:
-      value = m_xgb0->getClassifierValues( raw_energies );
-      break;
-    case 1:
-      value = m_xgb1->getClassifierValues( raw_energies );
-      break;
-    case 2:
-      value = m_xgb2->getClassifierValues( raw_energies );
-      break;
-    case 3:
-      value = m_xgb03_b->getClassifierValues( raw_energies );
-      break;
-    case 4:
-      value = m_xgb14_b->getClassifierValues( raw_energies );
-      break;
-    case 5:
-      value = m_xgb25_b->getClassifierValues( raw_energies );
-      break;
-    case 6:
-      value = m_xgb06_b->getClassifierValues( raw_energies );
-      break;
-    case 7:
-      value = m_xgb17_b->getClassifierValues( raw_energies );
-      break;
-    case 8:
-      value = m_xgb28_b->getClassifierValues( raw_energies );
-      break;
-    default:
+    if ( !cluster ) return std::nullopt;
+    int cluster_type = getClusterType( cluster->seed() );
+    if ( cluster_type > static_cast<int>( m_xgb.size() ) ) {
       warning() << "GammaPi0XGBoost: Unsupperted cluster type" << endmsg;
+      return std::nullopt;
     }
-    return value;
+    std::array<double, 25> rawEnergyVector{0};
+    bool                   rawEnergy = GetRawEnergy( hypo, cluster_type, rawEnergyVector );
+    if ( !rawEnergy ) return std::nullopt;
+    return m_xgb[cluster_type]->getClassifierValues( rawEnergyVector );
   }
 
   bool GammaPi0XGBoost::GetRawEnergy( const LHCb::CaloHypo& hypo, int cluster_type,
                                       LHCb::span<double, 25> rawEnergy ) const {
 
-    const LHCb::CaloDigits*  digits_full = getIfExists<LHCb::CaloDigits>( LHCb::CaloDigitLocation::Ecal );
+    const LHCb::CaloDigits*  digits_full = m_digits.get();
     const LHCb::CaloCluster* cluster =
         LHCb::CaloFutureAlgUtils::ClusterFromHypo( &hypo ); // OD 2014/05 - change to Split Or Main  cluster
 
-    if ( nullptr == digits_full || nullptr == cluster ) return false;
+    if ( !digits_full || !cluster ) return false;
 
     LHCb::CaloCellID centerID = cluster->seed();
 
@@ -220,7 +162,6 @@ namespace Calo::Future {
         }
       }
     }
-
     return true;
   }
 } // namespace Calo::Future
diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
index fb725b1bfb8..e563016e0a7 100644
--- a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
+++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h
@@ -40,7 +40,6 @@ namespace Calo::Future {
     using extends::extends;
 
     StatusCode initialize() override;
-    StatusCode finalize() override;
 
     std::optional<double>                   isPhoton( const LHCb::CaloHypo& hypo ) override;
     std::optional<double>                   isPhoton( LHCb::span<const double> ) override { return 0; }
@@ -53,19 +52,11 @@ namespace Calo::Future {
     bool GetRawEnergy( const LHCb::CaloHypo& hypo, int cluster_type, LHCb::span<double, 25> rawEnergy ) const;
     Gaudi::Property<float> m_minPt{this, "MinPt", 2000.};
 
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb0;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb1;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb2;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb03_b;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb14_b;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb25_b;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb06_b;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb17_b;
-    std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb28_b;
+    std::array<std::optional<FutureXGBClassifierPhPi0>, 9> m_xgb;
 
-    const DeCalorimeter* m_ecal = nullptr;
+    DataObjectReadHandle<LHCb::CaloDigits> m_digits{this, "DigitLocation", LHCb::CaloDigitLocation::Ecal};
 
-    double XGBDiscriminant( int cluster_type, LHCb::span<const double> raw_energies );
+    const DeCalorimeter* m_ecal = nullptr;
   };
 } // namespace Calo::Future
 #endif // FutureGammaPi0XGBoostTool_H
diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
index 2d097760bb4..0f09184eee1 100644
--- a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
+++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp
@@ -9,31 +9,25 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "FutureXGBClassifierPhPi0.h"
-#include <exception>
-#include <iostream>
+#include <stdexcept>
 
 FutureXGBClassifierPhPi0::FutureXGBClassifierPhPi0() {
-  XGDMatrixCreateFromMat( &m_predictionsCache.at( 0 ), 1, 2, 0.5, &m_cache_matrix );
+  XGDMatrixCreateFromMat( m_predictionsCache.data(), 1, m_predictionsCache.size(), 0.5, &m_cache_matrix );
 }
 
 FutureXGBClassifierPhPi0::FutureXGBClassifierPhPi0( const std::string& path ) {
-  xgb_path = path;
-  // std::cout<<"PATH str: "<< xgb_path << std::endl;
-  XGDMatrixCreateFromMat( &m_predictionsCache.at( 0 ), 1, 2, 0.5, &m_cache_matrix );
+  // std::cout<<"PATH str: "<< path << std::endl;
+  XGDMatrixCreateFromMat( &m_predictionsCache.at( 0 ), 1, m_predictionsCache.size(), 0.5, &m_cache_matrix );
   XGBoosterCreate( &m_cache_matrix, 1, &m_booster );
-  int err_code = XGBoosterLoadModel( m_booster, xgb_path.c_str() );
-  if ( err_code == -1 ) { log << MSG::WARNING << "Do not load XGBModel " << endmsg; }
+  int err_code = XGBoosterLoadModel( m_booster, path.c_str() );
+  if ( err_code == -1 ) throw std::runtime_error( "Failed to load XGBModel from " + path );
 }
 
-void FutureXGBClassifierPhPi0::setPath( const std::string& path ) {
-  XGBoosterCreate( &m_cache_matrix, 1, &m_booster );
-  XGBoosterLoadModel( m_booster, path.c_str() );
-}
-
-double FutureXGBClassifierPhPi0::getClassifierValues( LHCb::span<const double> featureValues ) {
+double FutureXGBClassifierPhPi0::getClassifierValues( LHCb::span<const double> featureValues ) const {
   // currently XGBoost only supports float
   std::vector<float> features_f( featureValues.begin(), featureValues.end() );
 
+  auto lock = std::lock_guard{m_mut};
   // fill the feature vector into a XGBoost DMatrix
   XGDMatrixCreateFromMat( features_f.data(), 1, features_f.size(), 0, &m_feature_matrix );
 
@@ -42,7 +36,7 @@ double FutureXGBClassifierPhPi0::getClassifierValues( LHCb::span<const double> f
   unsigned long predictions_length = 0;
   const float*  predictions        = nullptr;
   XGBoosterPredict( m_booster, m_feature_matrix, 0, 0, &predictions_length, &predictions );
-  std::vector<double> vec_predictions;
-  for ( unsigned int i = 0; i < predictions_length; i++ ) { vec_predictions.push_back( predictions[i] ); }
-  return vec_predictions[0];
+  assert( predictions != nullptr );
+  assert( predictions_length > 0 );
+  return predictions[0];
 }
diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
index dd3a54e5acf..64f0dea3ae3 100644
--- a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
+++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h
@@ -16,6 +16,7 @@
 #include "GaudiKernel/ServiceHandle.h"
 #include "Kernel/STLExtensions.h"
 #include "xgboost/c_api.h"
+#include <mutex>
 #include <string>
 #include <vector>
 
@@ -27,16 +28,13 @@ public:
    * Takes a vector of feature values, and return the corresponding MVA output.
    *    * @param[in]  featureValues  A vector of feature values
    *    * @return     MVA classifier value    */
-  double                     getClassifierValues( LHCb::span<const double> featureValues );
-  void                       setPath( const std::string& path );
-  ServiceHandle<IMessageSvc> msgh = ServiceHandle<IMessageSvc>( "MessageSvc", "XGBLog" );
-  MsgStream                  log  = MsgStream( &( *msgh ), "XGBLog" );
+  double getClassifierValues( LHCb::span<const double> featureValues ) const;
 
 private:
-  std::string        xgb_path           = "def_path";
-  std::vector<float> m_predictionsCache = {0, 0};
-  DMatrixHandle      m_cache_matrix, m_feature_matrix;
-  BoosterHandle      m_booster;
+  mutable std::mutex           m_mut;
+  mutable std::array<float, 2> m_predictionsCache = {0, 0};
+  mutable DMatrixHandle        m_cache_matrix, m_feature_matrix;
+  mutable BoosterHandle        m_booster;
 };
 
 #endif // XGBCLASSIFIER_H
-- 
GitLab