From 80b34d311eac025a657bfa46fed28d5e54e2d8dd Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Fri, 23 Sep 2022 15:16:03 +0200
Subject: [PATCH 01/26] Cleaned up ITransportSvc and IMaterialLocator interface

In particular :
 - dropped old non reentrant methods
 - renamed reentrant methods withour "_r"
 - return intersections in intersect/intersections methods, rather than relying on filling a vector passed by reference (and cleaning it first)
 - dropped unused entry points
---
 .../src/RichTrackRadiatorMaterial.cpp         |  2 +-
 ...ichTrackFunctionalCherenkovResolutions.cpp | 10 ++--
 .../src/DetailedMaterialLocator.cpp           | 20 +++----
 .../src/MaterialLocatorBase.cpp               | 55 +++++++------------
 .../src/MaterialLocatorBase.h                 | 21 +++----
 .../src/SimplifiedMaterialLocator.cpp         | 14 ++---
 .../src/TrackMasterExtrapolator.cpp           |  5 +-
 Tr/TrackFitter/src/TrackMasterFitter.cpp      | 14 +----
 Tr/TrackFitter/src/TrackMasterFitter.h        |  4 --
 .../TrackInterfaces/IMaterialLocator.h        | 16 +-----
 10 files changed, 60 insertions(+), 101 deletions(-)

diff --git a/Rich/RichFutureRecMonitors/src/RichTrackRadiatorMaterial.cpp b/Rich/RichFutureRecMonitors/src/RichTrackRadiatorMaterial.cpp
index 335e2307094..cf19a910f38 100644
--- a/Rich/RichFutureRecMonitors/src/RichTrackRadiatorMaterial.cpp
+++ b/Rich/RichFutureRecMonitors/src/RichTrackRadiatorMaterial.cpp
@@ -177,7 +177,7 @@ void TrackRadiatorMaterial::operator()( LHCb::RichTrackSegment::Vector const& se
 #ifdef USE_DD4HEP
                                   0.0
 #else
-                                  m_transSvc->distanceInRadUnits_r( entP, extP, tsCache, geometry, 0, nullptr )
+                                  m_transSvc->distanceInRadUnits( entP, extP, tsCache, geometry, 0, nullptr )
 #endif
       );
       const auto effLOvL = ( length > 0 ? effL / length : 1e-7 );
diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
index a21e51b14b3..b99173152ec 100644
--- a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
+++ b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
@@ -193,9 +193,9 @@ StatusCode TrackFunctionalCherenkovResolutions::initialize() {
                               // in each RICH radiator medium
                               for ( const auto rad : Rich::radiators() ) {
                                 if ( m_cacheRadLenP[rad] && !m_useTSForMS[rad] ) {
-                                  const auto effL     = m_transSvc->distanceInRadUnits_r( radVs[rad].first,  //
-                                                                                      radVs[rad].second, //
-                                                                                      tsCache, *lhcb.geometry(), 0 );
+                                  const auto effL     = m_transSvc->distanceInRadUnits( radVs[rad].first,  //
+                                                                                    radVs[rad].second, //
+                                                                                    tsCache, *lhcb.geometry(), 0 );
                                   const auto length   = std::sqrt( ( radVs[rad].second - radVs[rad].first ).mag2() );
                                   radLenPerUnitL[rad] = ( length > 0 ? effL / length : 0.0 );
                                   _ri_debug << std::setprecision( 9 ) << rad //
@@ -261,8 +261,8 @@ CherenkovResolutions::Vector TrackFunctionalCherenkovResolutions::
       } else {
         // Full TS treatment ...
         try {
-          effL = m_transSvc->distanceInRadUnits_r( segment.entryPoint(), segment.exitPoint(), //
-                                                   tsCache, *lhcb.geometry(), 0 );
+          effL = m_transSvc->distanceInRadUnits( segment.entryPoint(), segment.exitPoint(), //
+                                                 tsCache, *lhcb.geometry(), 0 );
         } catch ( const TransportSvcException& excpt ) {
           effL = 0;
           ++m_pathLenWarn;
diff --git a/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp b/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
index 9269a23111a..8a2c207d2e8 100644
--- a/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
+++ b/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
@@ -9,7 +9,6 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "DetDesc/IDetectorElement.h"
-#include "DetDesc/ITransportSvc.h"
 #include "DetDesc/Material.h"
 #include "GaudiKernel/ServiceHandle.h"
 #include "GaudiKernel/SystemOfUnits.h"
@@ -30,9 +29,10 @@ public:
   using MaterialLocatorBase::intersect;
   using MaterialLocatorBase::MaterialLocatorBase;
 
+protected:
   /// Intersect a line with volumes in the geometry
-  size_t intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, ILVolume::Intersections& intersepts,
-                    std::any& accelCache, IGeometryInfo const& geometry ) const override;
+  ILVolume::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any& accelCache,
+                                             IGeometryInfo const& geometry ) const override;
 
 private:
   Gaudi::Property<double> m_minRadThickness{this, "MinRadThickness", 1e-4}; ///< minimum radiation thickness
@@ -46,13 +46,11 @@ namespace {
   inline const std::string chronotag = "DetailedMaterialLocator";
 }
 
-size_t DetailedMaterialLocator::intersect( const Gaudi::XYZPoint& start, const Gaudi::XYZVector& vect,
-                                           ILVolume::Intersections& intersepts, std::any& accelCache,
-                                           IGeometryInfo const& geometry ) const {
+ILVolume::Intersections DetailedMaterialLocator::intersect_volumes( const Gaudi::XYZPoint&  start,
+                                                                    const Gaudi::XYZVector& vect, std::any& accelCache,
+                                                                    IGeometryInfo const& geometry ) const {
   // check if transport is within LHCb
   constexpr double m_25m = 25 * Gaudi::Units::m;
-  size_t           rc    = 0;
-  intersepts.clear();
 
   if ( std::abs( start.x() ) > m_25m || std::abs( start.y() ) > m_25m || std::abs( start.z() ) > m_25m ||
        std::abs( start.x() + vect.x() ) > m_25m || std::abs( start.y() + vect.y() ) > m_25m ||
@@ -62,21 +60,21 @@ size_t DetailedMaterialLocator::intersect( const Gaudi::XYZPoint& start, const G
       debug() << "No transport between z= " << start.z() << " and " << start.z() + vect.z()
               << ", since it reaches outside LHCb"
               << "start = " << start << " vect= " << vect << endmsg;
+    return {};
   } else {
     try {
       chronoSvc()->chronoStart( chronotag );
       const double mintick = 0;
       const double maxtick = 1;
-      rc =
-          m_tSvc->intersections_r( start, vect, mintick, maxtick, intersepts, accelCache, geometry, m_minRadThickness );
+      auto intersepts = m_tSvc->intersections( start, vect, mintick, maxtick, accelCache, geometry, m_minRadThickness );
       chronoSvc()->chronoStop( chronotag );
+      return intersepts;
     } catch ( const GaudiException& exception ) {
       error() << "caught transportservice exception " << exception << '\n'
               << "propagating pos/vec: " << start << " / " << vect << endmsg;
       throw exception;
     }
   }
-  return rc;
 }
 
 #ifdef USE_DD4HEP
diff --git a/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp b/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
index 72a17a33bec..fcd0879b6b6 100644
--- a/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
+++ b/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
@@ -35,25 +35,21 @@ namespace {
   }
 } // namespace
 
-size_t MaterialLocatorBase::intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v,
-                                       IMaterialLocator::Intersections& intersepts, std::any& accelCache,
-                                       IGeometryInfo const& geometry ) const
-
-{
-  ILVolume::Intersections origintersepts;
-  origintersepts.clear();
-  const auto rc = intersect( p, v, origintersepts, accelCache, geometry );
-  const auto dz = v.z();
-  const auto z1 = p.z();
-  const auto tx = v.x() / v.z();
-  const auto ty = v.y() / v.z();
-  intersepts.clear();
+IMaterialLocator::Intersections MaterialLocatorBase::intersect_point( const Gaudi::XYZPoint&  p,
+                                                                      const Gaudi::XYZVector& v, std::any& accelCache,
+                                                                      IGeometryInfo const& geometry ) const {
+  ILVolume::Intersections         origintersepts = intersect_volumes( p, v, accelCache, geometry );
+  const auto                      dz             = v.z();
+  const auto                      z1             = p.z();
+  const auto                      tx             = v.x() / v.z();
+  const auto                      ty             = v.y() / v.z();
+  IMaterialLocator::Intersections intersepts;
   intersepts.reserve( origintersepts.size() );
   std::transform( origintersepts.begin(), origintersepts.end(), std::back_inserter( intersepts ),
                   [&]( ILVolume::Intersections::const_reference i ) -> IMaterialLocator::Intersection {
                     return {z1 + dz * i.first.first, z1 + dz * i.first.second, tx, ty, i.second};
                   } );
-  return rc;
+  return intersepts;
 }
 
 inline double pointerror( const LHCb::StateVector& begin, const LHCb::StateVector& end, const LHCb::StateVector& mid ) {
@@ -78,10 +74,10 @@ inline double linearerror( const LHCb::StateVector& origin, const LHCb::StateVec
   return 0.25 * std::sqrt( ( dx * dx ) + ( dy * dy ) );
 }
 
-size_t MaterialLocatorBase::intersect( const LHCb::ZTrajectory<double>& traj,
-                                       IMaterialLocator::Intersections& intersepts, std::any& accelCache,
-                                       IGeometryInfo const& geometry ) const {
-  intersepts.clear();
+IMaterialLocator::Intersections MaterialLocatorBase::intersect( const LHCb::ZTrajectory<double>& traj,
+                                                                std::any&                        accelCache,
+                                                                IGeometryInfo const&             geometry ) const {
+  IMaterialLocator::Intersections intersepts;
   if ( std::abs( traj.endRange() - traj.beginRange() ) > TrackParameters::propagationTolerance ) {
     // The material locators can only use straight lines, so we
     // approximate the trajectory by straight lines. The less
@@ -170,34 +166,23 @@ size_t MaterialLocatorBase::intersect( const LHCb::ZTrajectory<double>& traj,
     }
 
     // Now create intersections for each of the intervals.
-    IMaterialLocator::Intersections tmpintersepts;
-    auto                            p1 = nodes.front().position();
+    auto p1 = nodes.front().position();
     for ( inode = nodes.begin(); ( nextnode = std::next( inode ) ) != nodes.end(); ++inode ) {
       auto p2 = nextnode->position();
       try {
-        MaterialLocatorBase::intersect( p1, p2 - p1, tmpintersepts, accelCache, geometry );
+        IMaterialLocator::Intersections tmpintersepts =
+            MaterialLocatorBase::intersect_point( p1, p2 - p1, accelCache, geometry );
+        intersepts.insert( intersepts.end(), tmpintersepts.begin(), tmpintersepts.end() );
+        p1 = p2;
       } catch ( GaudiException& exception ) {
         error() << "propagating pos1, pos2: " << p1 << " " << p2 << " " << traj.beginPoint() << " " << traj.endPoint()
                 << endmsg;
         throw exception;
       }
-      intersepts.insert( intersepts.end(), tmpintersepts.begin(), tmpintersepts.end() );
-      p1 = p2;
     }
   }
 
-  return intersepts.size();
-}
-
-size_t MaterialLocatorBase::intersect( const LHCb::StateVector& origin, const LHCb::StateVector& target,
-                                       IMaterialLocator::Intersections& intersepts, std::any& accelCache,
-                                       IGeometryInfo const& geometry ) const {
-  intersepts.clear();
-  if ( std::abs( origin.z() - target.z() ) > TrackParameters::propagationTolerance ) {
-    // create a trajectory for interpolation
-    intersect( LHCb::CubicStateVectorInterpolationTraj{origin, target}, intersepts, accelCache, geometry );
-  }
-  return intersepts.size();
+  return intersepts;
 }
 
 // FIXME: add createCache() function + `std::any` argument here for the two buffers we use
diff --git a/Tr/TrackExtrapolators/src/MaterialLocatorBase.h b/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
index f74c6217b60..f935dc140c6 100644
--- a/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
+++ b/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
@@ -43,23 +43,24 @@ public:
   // Create an instance of the accelerator cache
   std::any createCache() const override { return m_tSvc->createCache(); }
 
-  /// Intersect a line with volumes in the geometry
-  size_t intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, Intersections& intersepts,
-                    std::any& accelCache, IGeometryInfo const& geometry ) const override;
-
   /// Intersect a trajectory with volumes in the geometry
-  size_t intersect( const LHCb::ZTrajectory<double>& traj, Intersections& intersepts, std::any& accelCache,
-                    IGeometryInfo const& geometry ) const override;
-
-  /// Intersect a trajectory interpolated between two statevectors with volumes in the geometry
-  size_t intersect( const LHCb::StateVector& origin, const LHCb::StateVector& target, Intersections& intersepts,
-                    std::any& accelCache, IGeometryInfo const& geometry ) const override;
+  Intersections intersect( const LHCb::ZTrajectory<double>& traj, std::any& accelCache,
+                           IGeometryInfo const& geometry ) const override;
 
   void applyMaterialCorrections( LHCb::State& stateAtTarget, const IMaterialLocator::Intersections& intersepts,
                                  double zorigin, const LHCb::Tr::PID pid, bool applyScatteringCorrection,
                                  bool applyEnergyLossCorrection ) const override;
 
+protected:
+  /// Intersect a line with volumes in the geometry
+  virtual ILVolume::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v,
+                                                     std::any& accelCache, IGeometryInfo const& geometry ) const = 0;
+
 private:
+  /// Intersect a line with volumes in the geometry
+  Intersections intersect_point( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any& accelCache,
+                                 IGeometryInfo const& geometry ) const;
+
   static constexpr size_t m_maxNumIntervals             = 20;
   static constexpr double m_maxDeviation                = 5 * Gaudi::Units::cm;
   static constexpr double m_maxDeviationAtRefstates     = 2 * Gaudi::Units::mm;
diff --git a/Tr/TrackExtrapolators/src/SimplifiedMaterialLocator.cpp b/Tr/TrackExtrapolators/src/SimplifiedMaterialLocator.cpp
index f0923a67ddf..b05feadd6ba 100644
--- a/Tr/TrackExtrapolators/src/SimplifiedMaterialLocator.cpp
+++ b/Tr/TrackExtrapolators/src/SimplifiedMaterialLocator.cpp
@@ -123,8 +123,8 @@ public:
   using MaterialLocatorBase::intersect;
 
   /// Intersect a line with volumes in the geometry
-  size_t intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, ILVolume::Intersections& intersepts, std::any&,
-                    IGeometryInfo const& geometry ) const override;
+  ILVolume::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any&,
+                                             IGeometryInfo const& geometry ) const override;
 
 private:
   Gaudi::Property<std::string>                                               m_tgvolname{this, "Geometry",
@@ -167,13 +167,13 @@ inline bool compareFirstTick( const ILVolume::Intersection& lhs, const ILVolume:
   return lhs.first.first < rhs.first.first;
 }
 
-size_t SimplifiedMaterialLocator::intersect( const Gaudi::XYZPoint& start, const Gaudi::XYZVector& vect,
-                                             ILVolume::Intersections& intersepts, std::any&,
-                                             IGeometryInfo const& ) const {
+ILVolume::Intersections SimplifiedMaterialLocator::intersect_volumes( const Gaudi::XYZPoint&  start,
+                                                                      const Gaudi::XYZVector& vect, std::any&,
+                                                                      IGeometryInfo const& ) const {
   // for now, no navigation
-  intersepts.clear();
+  ILVolume::Intersections intersepts;
   for ( auto& i : m_volumes ) i->addintersections( start, vect, intersepts );
   std::sort( std::begin( intersepts ), std::end( intersepts ), compareFirstTick );
-  return intersepts.size();
+  return intersepts;
 }
 #endif
diff --git a/Tr/TrackExtrapolators/src/TrackMasterExtrapolator.cpp b/Tr/TrackExtrapolators/src/TrackMasterExtrapolator.cpp
index f7751417abc..bcb7a5181d5 100644
--- a/Tr/TrackExtrapolators/src/TrackMasterExtrapolator.cpp
+++ b/Tr/TrackExtrapolators/src/TrackMasterExtrapolator.cpp
@@ -9,7 +9,6 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "DetDesc/ILVolume.h"
-#include "DetDesc/ITransportSvc.h"
 #include "DetDesc/Material.h"
 #include "Event/TrackParameters.h"
 #include "GaudiKernel/ToolHandle.h"
@@ -230,8 +229,8 @@ StatusCode TrackMasterExtrapolator::propagate( LHCb::State& state, double zNew,
     if ( m_useMaterial ) {
       assert( stateAtOrigin.has_value() );
       LHCb::CubicStateInterpolationTraj traj( stateAtOrigin.value(), state );
-      IMaterialLocator::Intersections   intersections;
-      if ( m_materialLocator->intersect( traj, intersections, materialCache, geometry ) > 0 ) {
+      IMaterialLocator::Intersections   intersections = m_materialLocator->intersect( traj, materialCache, geometry );
+      if ( intersections.size() > 0 ) {
         nWallsTot += intersections.size();
         m_materialLocator->applyMaterialCorrections( state, intersections, zorigin, pid, m_applyMultScattCorr,
                                                      m_applyEnergyLossCorr || m_applyElectronEnergyLossCorr );
diff --git a/Tr/TrackFitter/src/TrackMasterFitter.cpp b/Tr/TrackFitter/src/TrackMasterFitter.cpp
index 7007a1ab7d2..0a15ca1ab9b 100644
--- a/Tr/TrackFitter/src/TrackMasterFitter.cpp
+++ b/Tr/TrackFitter/src/TrackMasterFitter.cpp
@@ -727,17 +727,9 @@ StatusCode TrackMasterFitter::updateMaterialCorrections( LHCb::Track& track, con
       if ( zmin > zmax ) std::swap( zmin, zmax );
       tracktraj.setRange( zmin, zmax );
 
-      auto& intersections = fit->intersections();
-      // make sure we have the space we need in intersections so we don't need to
-      // reallocate (offline, I've seen tracks with more than 670 intersections
-      // in 100 events; we stay a bit above that to be on the safe side - and we
-      // don't mind the occasional reallocate if it's a rare track that has even
-      // more intersections)
-      intersections.clear();
-      intersections.reserve( 1024 );
-      m_materialLocator->intersect( tracktraj, intersections, accelCache, geometry );
+      fit->intersections() = m_materialLocator->intersect( tracktraj, accelCache, geometry );
       // shall can we free up the space?
-      intersections.shrink_to_fit();
+      fit->intersections().shrink_to_fit();
 
       // now we need to redistribute the result between the nodes. the first node cannot have any noise.
       auto inode   = nodes.begin();
@@ -748,7 +740,7 @@ StatusCode TrackMasterFitter::updateMaterialCorrections( LHCb::Track& track, con
         LHCb::State state( node->refVector() );
         state.covariance() = Gaudi::TrackSymMatrix();
         state.setQOverP( 1 / scatteringMomentum );
-        m_materialLocator->applyMaterialCorrections( state, intersections, zorigin, pid, true, applyenergyloss );
+        m_materialLocator->applyMaterialCorrections( state, fit->intersections(), zorigin, pid, true, applyenergyloss );
         auto deltaE = 1 / state.qOverP() - scatteringMomentum;
 
         node->setNoiseMatrix( state.covariance() );
diff --git a/Tr/TrackFitter/src/TrackMasterFitter.h b/Tr/TrackFitter/src/TrackMasterFitter.h
index f3dcdb39cd0..9d47718ef85 100644
--- a/Tr/TrackFitter/src/TrackMasterFitter.h
+++ b/Tr/TrackFitter/src/TrackMasterFitter.h
@@ -25,10 +25,6 @@
 #include "TrackInterfaces/ITrackFitter.h"
 #include "TrackInterfaces/ITrackKalmanFilter.h"
 
-// Forward declarations
-struct IMaterialLocator;
-struct ITrackExtrapolator;
-
 namespace LHCb {
   class FitNode;
   class State;
diff --git a/Tr/TrackInterfaces/include/TrackInterfaces/IMaterialLocator.h b/Tr/TrackInterfaces/include/TrackInterfaces/IMaterialLocator.h
index 72a4d2ab124..118314386ea 100644
--- a/Tr/TrackInterfaces/include/TrackInterfaces/IMaterialLocator.h
+++ b/Tr/TrackInterfaces/include/TrackInterfaces/IMaterialLocator.h
@@ -47,21 +47,9 @@ struct IMaterialLocator : extend_interfaces<IAlgTool> {
   /// Create an instance of the accelerator cache
   virtual std::any createCache() const = 0;
 
-  /// Intersect a line with volumes in the geometry
-  virtual size_t intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, ILVolume::Intersections& intersepts,
-                            std::any& accelCache, IGeometryInfo const& geometry ) const = 0;
-
-  /// Intersect a line with volumes in the geometry
-  virtual size_t intersect( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, Intersections& intersepts,
-                            std::any& accelCache, IGeometryInfo const& geometry ) const = 0;
-
   /// Intersect a trajectory with volumes in the geometry
-  virtual size_t intersect( const LHCb::ZTrajectory<double>& traj, Intersections& intersepts, std::any& accelCache,
-                            IGeometryInfo const& geometry ) const = 0;
-
-  /// Intersect a trajectory interpolated between two statevectors with volumes in the geometry
-  virtual size_t intersect( const LHCb::StateVector& origin, const LHCb::StateVector& target, Intersections& intersepts,
-                            std::any& accelCache, IGeometryInfo const& geometry ) const = 0;
+  virtual Intersections intersect( const LHCb::ZTrajectory<double>& traj, std::any& accelCache,
+                                   IGeometryInfo const& geometry ) const = 0;
 
   /// Apply material corrections using material in intersepts
   virtual void applyMaterialCorrections( LHCb::State& stateAtTarget, const Intersections& intersepts, double zorigin,
-- 
GitLab


From c593a6df6e1e46990f297ff37dd93fbd7a990f8b Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Tue, 27 Sep 2022 15:24:37 +0200
Subject: [PATCH 02/26] Adapted TransportSvc interface to DD4hep

Essentially fixing the code in MaterialLocators and EnergyCorrection tools
---
 .../src/SelectiveElectronMatchAlg.cpp         |  1 +
 .../CaloFuturePIDs/src/SelectiveMatchUtils.h  |  2 -
 .../src/RichDetailedTrSegMakerFromTracks.cpp  |  1 +
 ...ichTrackFunctionalCherenkovResolutions.cpp |  1 +
 .../src/DetailedMaterialLocator.cpp           | 10 ++--
 .../src/MaterialLocatorBase.cpp               |  4 +-
 .../src/MaterialLocatorBase.h                 |  4 +-
 .../include/Event/TrackMaterialIntersection.h | 12 ++---
 .../TrackInterfaces/IStateCorrectionTool.h    | 13 ++----
 ...DetailedBetheBlochEnergyCorrectionTool.cpp | 46 +++++++++++++------
 .../src/StateElectronEnergyCorrectionTool.cpp | 13 ++++--
 ...teSimpleBetheBlochEnergyCorrectionTool.cpp | 10 ++--
 .../src/StateThickMSCorrectionTool.cpp        |  8 +++-
 .../src/StateThinMSCorrectionTool.cpp         | 12 +++--
 14 files changed, 85 insertions(+), 52 deletions(-)

diff --git a/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp b/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
index 544ed2e736d..9f853a9df93 100644
--- a/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
+++ b/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
@@ -10,6 +10,7 @@
  \*****************************************************************************/
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/TrackUtils.h"
+#include "DetDesc/Condition.h"
 #include "Gaudi/Accumulators.h"
 #include "GaudiAlg/GaudiTool.h"
 #include "GaudiKernel/GaudiException.h"
diff --git a/CaloFuture/CaloFuturePIDs/src/SelectiveMatchUtils.h b/CaloFuture/CaloFuturePIDs/src/SelectiveMatchUtils.h
index 038b56945de..094efac75db 100644
--- a/CaloFuture/CaloFuturePIDs/src/SelectiveMatchUtils.h
+++ b/CaloFuture/CaloFuturePIDs/src/SelectiveMatchUtils.h
@@ -12,8 +12,6 @@
 #define SELECTIVEMATCHUTILS_H
 
 #include "CaloDet/DeCalorimeter.h"
-#include "CaloDet/DeSubCalorimeter.h"
-#include "CaloDet/DeSubSubCalorimeter.h"
 #include "CaloFutureUtils/CaloFutureNeighbours.h"
 #include "LHCbMath/GeomFun.h"
 #include "LHCbMath/Line.h"
diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
index 0dcb6941396..ac2e1ee1b9b 100644
--- a/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
+++ b/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
@@ -48,6 +48,7 @@
 #include "Kernel/RichSmartID.h"
 
 // Interfaces
+#include "DetDesc/DetectorElement.h"
 #include "GaudiAlg/IGenericTool.h"
 #include "TrackInterfaces/ITrackExtrapolator.h"
 #include "TrackInterfaces/ITrackStateProvider.h"
diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
index b99173152ec..1db5f5f8e3e 100644
--- a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
+++ b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.cpp
@@ -31,6 +31,7 @@
 #include "RichFutureRecEvent/RichRecMassHypoRings.h"
 
 // Utils
+#include "DetDesc/DetectorElement.h"
 #include "RichFutureUtils/RichTabulatedRefIndex.h"
 #include "RichUtils/FastMaths.h"
 #include "RichUtils/RichGeomFunctions.h"
diff --git a/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp b/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
index 8a2c207d2e8..d517dbfbda4 100644
--- a/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
+++ b/Tr/TrackExtrapolators/src/DetailedMaterialLocator.cpp
@@ -31,8 +31,8 @@ public:
 
 protected:
   /// Intersect a line with volumes in the geometry
-  ILVolume::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any& accelCache,
-                                             IGeometryInfo const& geometry ) const override;
+  ::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any& accelCache,
+                                     IGeometryInfo const& geometry ) const override;
 
 private:
   Gaudi::Property<double> m_minRadThickness{this, "MinRadThickness", 1e-4}; ///< minimum radiation thickness
@@ -46,9 +46,9 @@ namespace {
   inline const std::string chronotag = "DetailedMaterialLocator";
 }
 
-ILVolume::Intersections DetailedMaterialLocator::intersect_volumes( const Gaudi::XYZPoint&  start,
-                                                                    const Gaudi::XYZVector& vect, std::any& accelCache,
-                                                                    IGeometryInfo const& geometry ) const {
+::Intersections DetailedMaterialLocator::intersect_volumes( const Gaudi::XYZPoint& start, const Gaudi::XYZVector& vect,
+                                                            std::any&            accelCache,
+                                                            IGeometryInfo const& geometry ) const {
   // check if transport is within LHCb
   constexpr double m_25m = 25 * Gaudi::Units::m;
 
diff --git a/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp b/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
index fcd0879b6b6..b0605c40e69 100644
--- a/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
+++ b/Tr/TrackExtrapolators/src/MaterialLocatorBase.cpp
@@ -38,7 +38,7 @@ namespace {
 IMaterialLocator::Intersections MaterialLocatorBase::intersect_point( const Gaudi::XYZPoint&  p,
                                                                       const Gaudi::XYZVector& v, std::any& accelCache,
                                                                       IGeometryInfo const& geometry ) const {
-  ILVolume::Intersections         origintersepts = intersect_volumes( p, v, accelCache, geometry );
+  ::Intersections                 origintersepts = intersect_volumes( p, v, accelCache, geometry );
   const auto                      dz             = v.z();
   const auto                      z1             = p.z();
   const auto                      tx             = v.x() / v.z();
@@ -46,7 +46,7 @@ IMaterialLocator::Intersections MaterialLocatorBase::intersect_point( const Gaud
   IMaterialLocator::Intersections intersepts;
   intersepts.reserve( origintersepts.size() );
   std::transform( origintersepts.begin(), origintersepts.end(), std::back_inserter( intersepts ),
-                  [&]( ILVolume::Intersections::const_reference i ) -> IMaterialLocator::Intersection {
+                  [&]( auto const& i ) -> IMaterialLocator::Intersection {
                     return {z1 + dz * i.first.first, z1 + dz * i.first.second, tx, ty, i.second};
                   } );
   return intersepts;
diff --git a/Tr/TrackExtrapolators/src/MaterialLocatorBase.h b/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
index f935dc140c6..dec77d83e23 100644
--- a/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
+++ b/Tr/TrackExtrapolators/src/MaterialLocatorBase.h
@@ -53,8 +53,8 @@ public:
 
 protected:
   /// Intersect a line with volumes in the geometry
-  virtual ILVolume::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v,
-                                                     std::any& accelCache, IGeometryInfo const& geometry ) const = 0;
+  virtual ::Intersections intersect_volumes( const Gaudi::XYZPoint& p, const Gaudi::XYZVector& v, std::any& accelCache,
+                                             IGeometryInfo const& geometry ) const = 0;
 
 private:
   /// Intersect a line with volumes in the geometry
diff --git a/Tr/TrackFitEvent/include/Event/TrackMaterialIntersection.h b/Tr/TrackFitEvent/include/Event/TrackMaterialIntersection.h
index a811b2585c0..e35e174200a 100644
--- a/Tr/TrackFitEvent/include/Event/TrackMaterialIntersection.h
+++ b/Tr/TrackFitEvent/include/Event/TrackMaterialIntersection.h
@@ -10,17 +10,17 @@
 \*****************************************************************************/
 #pragma once
 
-#include "DetDesc/Material.h"
+#include "DetDesc/ITransportSvc.h"
 
 namespace LHCb {
   /**
    * See https://gitlab.cern.ch/lhcb/Rec/-/issues/153 about the numerical precision
    **/
   struct TrackMaterialIntersection final {
-    double          z1       = 0.;
-    double          z2       = 0.;
-    double          tx       = 0.;
-    double          ty       = 0.;
-    const Material* material = nullptr;
+    double      z1 = 0.;
+    double      z2 = 0.;
+    double      tx = 0.;
+    double      ty = 0.;
+    MaterialPtr material{};
   };
 } // namespace LHCb
diff --git a/Tr/TrackInterfaces/include/TrackInterfaces/IStateCorrectionTool.h b/Tr/TrackInterfaces/include/TrackInterfaces/IStateCorrectionTool.h
index ab46a49d4fd..0f78937412c 100644
--- a/Tr/TrackInterfaces/include/TrackInterfaces/IStateCorrectionTool.h
+++ b/Tr/TrackInterfaces/include/TrackInterfaces/IStateCorrectionTool.h
@@ -8,12 +8,9 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#ifndef TRACKINTERFACES_ISTATECORRECTIONTOOL_H
-#define TRACKINTERFACES_ISTATECORRECTIONTOOL_H 1
+#pragma once
 
-// Include files
-// -------------
-// from Gaudi
+#include "DetDesc/ITransportSvc.h"
 #include "GaudiKernel/IAlgTool.h"
 #include <any>
 
@@ -23,8 +20,7 @@ namespace LHCb {
   class State;
 }
 
-/** @class IStateCorrectionTool IStateCorrectionTool.h TrackInterfaces/IStateCorrectionTool.h
- *
+/**
  *  Interface for state correction tools
  *
  *  @author Eduardo Rodrigues
@@ -34,9 +30,8 @@ struct IStateCorrectionTool : extend_interfaces<IAlgTool> {
 
   DeclareInterfaceID( IStateCorrectionTool, 2, 0 );
   /// Correct a State
-  virtual void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness = 0,
+  virtual void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness = 0,
                              bool upstream = true, double mass = 0 ) const = 0;
 
   virtual std::any createBuffer() const { return std::any(); }
 };
-#endif // TRACKINTERFACES_ISTATECORRECTIONTOOL_H
diff --git a/Tr/TrackTools/src/StateDetailedBetheBlochEnergyCorrectionTool.cpp b/Tr/TrackTools/src/StateDetailedBetheBlochEnergyCorrectionTool.cpp
index 99abcd42bdf..b15f81dd4f4 100644
--- a/Tr/TrackTools/src/StateDetailedBetheBlochEnergyCorrectionTool.cpp
+++ b/Tr/TrackTools/src/StateDetailedBetheBlochEnergyCorrectionTool.cpp
@@ -8,7 +8,7 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "DetDesc/Material.h"
+#include "Core/Material.h"
 #include "Event/State.h"
 #include "GaudiAlg/GaudiTool.h"
 #include "GaudiKernel/PhysicalConstants.h"
@@ -28,10 +28,18 @@ namespace {
 
   const auto log_2_me = std::log( 2 * electron_mass_c2 );
 
+#ifdef USE_DD4HEP
+  using InternalPtr = decltype( std::declval<MaterialPtr>().access() );
+  using MaterialRef = const LHCb::Detector::Material;
+#else
+  using InternalPtr = const Material*;
+  using MaterialRef = const Material&;
+#endif
+
   class MaterialCache {
     struct CacheData {
       double X0, C, X1, a, m, DensityFactor, LogI;
-      CacheData( const Material& mat )
+      CacheData( MaterialRef mat )
           : X0{mat.X0()}
           , C{mat.C()}
           , X1{mat.X1()}
@@ -40,20 +48,26 @@ namespace {
           , DensityFactor{( 30.71 * MeV * mm2 / mole ) * mat.Z() * mat.density() / mat.A()}
           , LogI{std::log( mat.I() )} {}
     };
-    using Material2FactorMap = std::unordered_map<const Material*, CacheData>;
+    using Material2FactorMap = std::unordered_map<InternalPtr, CacheData>;
 
-    Material2FactorMap           mat2factors;
+    Material2FactorMap           mat2factors{};
     Material2FactorMap::iterator last = end( mat2factors );
 
   public:
-    const CacheData& operator()( const Material* material ) {
+    const CacheData& operator()( MaterialPtr material ) {
+#ifdef USE_DD4HEP
+      assert( material.isValid() );
+      InternalPtr ptr = material.access();
+#else
       assert( material != nullptr );
+      InternalPtr ptr = material;
+#endif
       // material lookups are slightly different: the "hot spot" occupied by the
       // last material used is likely to be missed (about 85% of the time), but if
       // we can save the hash by looking at the last used element first, that's a
       // good thing
-      if ( end( mat2factors ) == last || last->first != material ) {
-        last = mat2factors.find( material );
+      if ( end( mat2factors ) == last || last->first != ptr ) {
+        last = mat2factors.find( ptr );
         // cache material quantities:
         // - X0, C, X1, a, m
         // - const. * Z / A * density ("DensityFactor")
@@ -63,7 +77,15 @@ namespace {
         if ( end( mat2factors ) == last ) {
           // coming here is the very rare exception - after the first couple of
           // events, the material cache miss rate is essentially zero
-          last = mat2factors.try_emplace( material, *material ).first;
+          last = mat2factors
+                     .try_emplace( ptr,
+#ifdef USE_DD4HEP
+                                   material
+#else
+                                   *material
+#endif
+                                   )
+                     .first;
         }
       }
       return last->second;
@@ -92,8 +114,8 @@ public:
   using extends::extends;
 
   /// Correct a State for dE/dx energy losses with a simplified Bethe-Bloch equiaton
-  void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness, bool upstream,
-                     double mass ) const override;
+  void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness,
+                     bool upstream, double mass ) const override;
 
   std::any createBuffer() const override { return MaterialCache(); }
 
@@ -110,7 +132,7 @@ DECLARE_COMPONENT( StateDetailedBetheBlochEnergyCorrectionTool )
 //=============================================================================
 // Correct a State for dE/dx energy losses
 //=============================================================================
-void StateDetailedBetheBlochEnergyCorrectionTool::correctState( LHCb::State& state, const Material* material,
+void StateDetailedBetheBlochEnergyCorrectionTool::correctState( LHCb::State& state, const MaterialPtr material,
                                                                 std::any& cache, double wallThickness, bool upstream,
                                                                 const double mass ) const {
   // mass zero is quite unlikely here, and we'll save a lot of computation in
@@ -145,5 +167,3 @@ void StateDetailedBetheBlochEnergyCorrectionTool::correctState( LHCb::State& sta
 
   qOverP /= 1 + eLoss * qOverP;
 }
-
-//=============================================================================
diff --git a/Tr/TrackTools/src/StateElectronEnergyCorrectionTool.cpp b/Tr/TrackTools/src/StateElectronEnergyCorrectionTool.cpp
index bb81582717e..271cf77cf7e 100644
--- a/Tr/TrackTools/src/StateElectronEnergyCorrectionTool.cpp
+++ b/Tr/TrackTools/src/StateElectronEnergyCorrectionTool.cpp
@@ -34,8 +34,8 @@ public:
   /// Standard constructor
   using extends::extends;
   /// Correct a State for electron dE/dx energy losses
-  void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness, bool upstream,
-                     double ) const override;
+  void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness,
+                     bool upstream, double ) const override;
 
 private:
   // Job options
@@ -48,11 +48,16 @@ DECLARE_COMPONENT( StateElectronEnergyCorrectionTool )
 //=============================================================================
 // Correct a State for electron dE/dx energy losses
 //=============================================================================
-void StateElectronEnergyCorrectionTool::correctState( LHCb::State& state, const Material* material, std::any& /*cache*/,
-                                                      double wallThickness, bool upstream, double ) const {
+void StateElectronEnergyCorrectionTool::correctState( LHCb::State& state, const MaterialPtr material,
+                                                      std::any& /*cache*/, double wallThickness, bool upstream,
+                                                      double ) const {
   // hard energy loss for electrons
   double t =
+#ifdef USE_DD4HEP
+      wallThickness / material.radiationLength() * sqrt( 1. + std::pow( state.tx(), 2 ) + std::pow( state.ty(), 2 ) );
+#else
       wallThickness / material->radiationLength() * sqrt( 1. + std::pow( state.tx(), 2 ) + std::pow( state.ty(), 2 ) );
+#endif
   if ( !upstream ) t *= -1.;
 
   // protect against t too big
diff --git a/Tr/TrackTools/src/StateSimpleBetheBlochEnergyCorrectionTool.cpp b/Tr/TrackTools/src/StateSimpleBetheBlochEnergyCorrectionTool.cpp
index 48b229c33b9..dfe8d17e298 100644
--- a/Tr/TrackTools/src/StateSimpleBetheBlochEnergyCorrectionTool.cpp
+++ b/Tr/TrackTools/src/StateSimpleBetheBlochEnergyCorrectionTool.cpp
@@ -38,8 +38,8 @@ public:
   /// Standard constructor
   using extends::extends;
   /// Correct a State for dE/dx energy losses with a simplified Bethe-Bloch equiaton
-  void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness, bool upstream,
-                     double ) const override;
+  void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness,
+                     bool upstream, double ) const override;
 
 private:
   // Job options
@@ -62,11 +62,15 @@ DECLARE_COMPONENT( StateSimpleBetheBlochEnergyCorrectionTool )
 //=============================================================================
 // Correct a State for dE/dx energy losses
 //=============================================================================
-void StateSimpleBetheBlochEnergyCorrectionTool::correctState( LHCb::State& state, const Material* material,
+void StateSimpleBetheBlochEnergyCorrectionTool::correctState( LHCb::State& state, const MaterialPtr material,
                                                               std::any& /*cache*/, double wallThickness, bool upstream,
                                                               double ) const {
   double bbLoss = wallThickness * sqrt( 1. + std::pow( state.tx(), 2 ) + std::pow( state.ty(), 2 ) ) *
+#ifdef USE_DD4HEP
+                  m_energyLossCorr * material.Z() * material.density() / material.A();
+#else
                   m_energyLossCorr * material->Z() * material->density() / material->A();
+#endif
   bbLoss = std::min( m_maxEnergyLoss.value(), bbLoss );
   if ( !upstream ) bbLoss *= -1.;
 
diff --git a/Tr/TrackTools/src/StateThickMSCorrectionTool.cpp b/Tr/TrackTools/src/StateThickMSCorrectionTool.cpp
index 2e0d32a67b0..ccd744f4fba 100644
--- a/Tr/TrackTools/src/StateThickMSCorrectionTool.cpp
+++ b/Tr/TrackTools/src/StateThickMSCorrectionTool.cpp
@@ -62,7 +62,7 @@ public:
   StatusCode initialize() override;
 
   /// Correct a State for multiple scattering in the case of a thick scatter
-  void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness = 0,
+  void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness = 0,
                      bool upstream = true, double pmass = 0 ) const override;
 
 private:
@@ -103,9 +103,13 @@ StatusCode StateThickMSCorrectionTool::initialize() {
 //=============================================================================
 // Correct a State for multiple scattering in the case of a thick scatter
 //=============================================================================
-void StateThickMSCorrectionTool::correctState( LHCb::State& state, const Material* material, std::any& /*cache*/,
+void StateThickMSCorrectionTool::correctState( LHCb::State& state, const MaterialPtr material, std::any& /*cache*/,
                                                double wallThickness, bool upstream, double ) const {
+#ifdef USE_DD4HEP
+  const auto t = wallThickness / material.radiationLength();
+#else
   const auto t = wallThickness / material->radiationLength();
+#endif
   // if t is below tolerance, all corrections end up zero anyway, so we can
   // stop early
   if ( t <= TrackParameters::lowTolerance ) return;
diff --git a/Tr/TrackTools/src/StateThinMSCorrectionTool.cpp b/Tr/TrackTools/src/StateThinMSCorrectionTool.cpp
index 41ca413e21a..e209f3b7ac8 100644
--- a/Tr/TrackTools/src/StateThinMSCorrectionTool.cpp
+++ b/Tr/TrackTools/src/StateThinMSCorrectionTool.cpp
@@ -38,8 +38,8 @@ public:
   using extends::extends;
 
   /// Correct a State for multiple scattering in the approximation of a thin scatter
-  void correctState( LHCb::State& state, const Material* material, std::any& cache, double wallThickness, bool upstream,
-                     double ) const override;
+  void correctState( LHCb::State& state, const MaterialPtr material, std::any& cache, double wallThickness,
+                     bool upstream, double ) const override;
 
 private:
   // Job options
@@ -53,9 +53,13 @@ DECLARE_COMPONENT( StateThinMSCorrectionTool )
 // Correct a State for multiple scattering
 // in the approximation of a thin scatter
 //=============================================================================
-void StateThinMSCorrectionTool::correctState( LHCb::State& state, const Material* material, std::any& /*cache*/,
+void StateThinMSCorrectionTool::correctState( LHCb::State& state, const MaterialPtr material, std::any& /*cache*/,
                                               double wallThickness, bool, double ) const {
-  const double t          = wallThickness / material->radiationLength();
+#ifdef USE_DD4HEP
+  const double t = wallThickness / material.radiationLength();
+#else
+  const double t = wallThickness / material->radiationLength();
+#endif
   const double norm2      = 1.0 + std::pow( state.tx(), 2 ) + std::pow( state.ty(), 2 );
   double       scatLength = 0.;
   if ( t > TrackParameters::lowTolerance ) {
-- 
GitLab


From e8d384eb4a1b4dfd38e802202bd2f2423d8e5703 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Tue, 27 Sep 2022 16:59:50 +0200
Subject: [PATCH 03/26] Dropped used of PreloadGeometryTool in Rich code. This
 is obsolete

---
 .../RichFutureRecSys/ConfiguredRichReco.py       |  5 -----
 .../src/RichDetailedTrSegMakerFromTracks.cpp     | 16 ----------------
 2 files changed, 21 deletions(-)

diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py
index c5699c41989..62f8f05e64e 100644
--- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py
+++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py
@@ -277,10 +277,6 @@ def RichRecoSequence(
         # Disable non-tread-safe tracking tools
         makeTkToolsThreadSafe=False,
 
-        # Development option to preload the detector geometry.
-        # Useful for timing studies.
-        preloadGeometry=False,
-
         # Max Number points for mass hypothesis ring ray tracing
         NRingPointsMax=(96, 96, 96),
 
@@ -547,7 +543,6 @@ def RichRecoSequence(
         # Properties
         segCr.TrackExtrapolator = trackExtrapolator
         segCr.MaxTracks = maxTracks
-        segCr.PreloadGeometry = preloadGeometry
         segCr.CreateMissingStates = createMissingStates
         # Some track tools are not thread safe so turn off their use and extend some z tolerences to compensate...
         # This is temporary ....
diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
index ac2e1ee1b9b..e08025bbab3 100644
--- a/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
+++ b/Rich/RichFutureRecTrackAlgorithms/src/RichDetailedTrSegMakerFromTracks.cpp
@@ -241,9 +241,6 @@ namespace Rich::Future::Rec {
     /// Track extrapolator ( Best options either TrackSTEPExtrapolator or TrackRungeKuttaExtrapolator )
     ToolHandle<const ITrackExtrapolator> m_trExt{this, "TrackExtrapolator", "TrackSTEPExtrapolator/TrackExtrapolator"};
 
-    /// data preloader
-    ToolHandle<IGenericTool> m_preloadTool{this, "PreloadGeometryTool", "PreloadGeometryTool"};
-
   private:
     // properties
 
@@ -330,11 +327,6 @@ namespace Rich::Future::Rec {
         "Maximum track momentum value in RICH1/RICH2 to perform a finessing of the radiator intersections "
         "to account for track curvature."};
 
-    /// Preload Geometry ?
-    Gaudi::Property<bool> m_preload{
-        this, "PreloadGeometry", false,
-        "Preload the full LHCb geometry during initialisation. Useful for CPU timing studies."};
-
     /// Max number tracks GEC
     Gaudi::Property<unsigned int> m_maxTracks{this, "MaxTracks", std::numeric_limits<unsigned int>::max(),
                                               "Maximum input track global event cut."};
@@ -425,14 +417,6 @@ StatusCode DetailedTrSegMakerFromTracks::initialize() {
   Utils::RadIntersects::addConditionDerivation( this );
   Utils::TabulatedRefIndex::addConditionDerivation( this );
 
-  // Preload Geometry ?
-  if ( m_preload ) {
-    m_preloadTool->execute();
-    sc = m_preloadTool.release();
-  } else {
-    m_preloadTool.disable();
-  }
-
   // Force debug messages
   // sc = setProperty( "OutputLevel", MSG::VERBOSE );
 
-- 
GitLab


From 07479036e3400731dee8f97d323e108b437007f3 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Wed, 28 Sep 2022 08:52:38 +0200
Subject: [PATCH 04/26] Drop unused features of CaloFutureCorrectionBase

Namely the possibility to avoid using the CondDB and go through opt params defined by hand in the config file
This is a prerequisite to convert CaloFutureCorrection classes to derived conditions so that we can support DD4hep
---
 .../python/CaloFutureReco/Corrections.py      | 148 ------------------
 .../src/CaloFutureCorrectionBase.cpp          |  94 ++---------
 .../src/CaloFutureCorrectionBase.h            |  10 +-
 .../src/CaloFutureShowerOverlapTool.cpp       |   2 +-
 .../src/FutureClusterCovarianceMatrixTool.cpp |   2 +-
 .../src/FutureSubClusterSelectorTool.cpp      |   3 +-
 .../python/GlobalReco/Configuration.py        |   3 -
 7 files changed, 13 insertions(+), 249 deletions(-)
 delete mode 100644 CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py

diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py
deleted file mode 100644
index f2e56f40a29..00000000000
--- a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py
+++ /dev/null
@@ -1,148 +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.                                       #
-###############################################################################
-
-#!/usr/bin/env python
-# =============================================================================
-# =============================================================================
-## @file CaloFutureReco/Corrections.py
-#  Set of E/S/L-correction parameters
-#  @see CaloFutureECorrection
-#  @see CaloFutureSCorrection
-#  @see CaloFutureLCorrection
-#  @todo Move the correction to Conditions Data Base
-# =============================================================================
-"""
-Set of CaloFuture E/S/L-correction parameters
-"""
-from __future__ import print_function
-# =============================================================================
-# =============================================================================
-__all__ = (
-    'eCorrection',  ## E-corretions
-    'sCorrection',  ## S-corretions
-    'lCorrection',  ## L-corretions
-    'showerProfile'  ## Transversal shower profile
-)
-# =============================================================================
-from Gaudi.Configuration import log
-
-
-# =============================================================================
-## function which sets the E-correction parameters
-#  @see CaloFutureECorrection
-def eCorrection(ecorr, version=None):
-    """
-    Function which sets the E-correction parameters:
-
-    >>> tool = ...
-    >>> eCorrection ( tool )
-    """
-    # ============================================================================
-    #                      function   #params      Outer         Middle       Inner
-    # ============================================================================
-    ecorr.Parameters["alphaG"] = [0, 1, 1.0, 1.0, 1.0]
-    ecorr.Parameters["alphaE"] = [
-        0, 2, 1.0105, 1.0208, 1.0325, 0.11561E-06, 0.33802E-07, -0.28272E-07
-    ]
-    ecorr.Parameters["alphaB"] = [
-        0, 2, 1.0159, 1.0210, 1.0256, -0.67500E-01, -0.78525E-01, -0.8901E-01
-    ]
-    ecorr.Parameters["alphaX"] = [0, 2, 1, 1, 1, 0., 0.0171, 0.0315]
-    ecorr.Parameters["alphaY"] = [0, 2, 1, 1, 1, 0., 0.0362, 0.0479]
-
-    ##
-    log.debug('Configure E-Corrections for Ecal hypotheses: %s' % ecorr.name())
-    #    ecorr.OutputLevel = 2
-    return ecorr
-
-
-# =============================================================================
-## function which sets the S-correction parameters
-#  @see CaloFutureSCorrection
-def sCorrection(scorr, version=None):
-    """
-    Function which sets the S-correction parameters:
-
-    >>> tool = ...
-    >>> sCorrection ( tool )
-    """
-    scorr.Parameters["shapeX"] = [5, 1, 0.102, 0.129, 0.144]
-    scorr.Parameters["shapeY"] = [5, 1, 0.102, 0.129, 0.144]
-    scorr.Parameters["residual"] = [
-        1, 8, -0.47496E-03, -0.97712E-05, -0.14401E-03, 0.44911, 0.33898,
-        0.29037, -0.34187E-01, 0.14566E-01, 0.28848E-01, -9.0335, -5.9958,
-        -5.1697, 0.46190, -0.13533, -0.34664, 53.041, 32.711, 26.885, -1.2801,
-        0.33460E-01, 0.99928, -97.865, -58.743, -45.032
-    ]
-    scorr.Parameters["asymP"] = [
-        1, 3, 0.24742E-01, 0.28587E-01, 0.19870E-01, 0.11487E-01, 0.11557E-01,
-        0.38043E-02, -0.32640, -0.31548, -0.21436
-    ]
-    scorr.Parameters["asymM"] = [
-        1, 3, -0.29386E-01, -0.28587E-01, -0.19870E-01, 0.11472E-01,
-        0.11557E-01, 0.38043E-02, 0.35928, 0.31548, 0.21436
-    ]
-    ##
-    log.debug('Configure S-Corrections for Ecal hypotheses: %s' % scorr.name())
-    return scorr
-
-
-# =============================================================================
-## function which sets the L-correction parameters
-#  @see CaloFutureLCorrection
-def lCorrection(lcorr, version=None):
-    """
-    Function which sets the L-correction parameters:
-
-    >>> tool = ...
-    >>> lCorrection ( tool )
-    """
-    lcorr.Parameters["gamma0"] = [1, 1, 22.305, 19.053, 17.936]
-    lcorr.Parameters["gammaP"] = [
-        2, 2, 2.04, 1.53, 1.15, -0.0281, -0.455, -0.0392
-    ]
-    lcorr.Parameters["delta0"] = [1, 1, 49.04, 51.87, 45.54]
-    lcorr.Parameters["deltaP"] = [
-        2, 2, 4.38, 4.15, 4.02, -0.0247, -0.0597, -0.0308
-    ]
-
-    ##
-    log.debug('Configure L-Corrections for Ecal hypotheses: %s' % lcorr.name())
-    return lcorr
-
-
-# =============================================================================
-## function which provide the Transversal Shower profile (for MergedPi0 reconstruction)
-#  @see CaloFutureMergedPi0ALg
-def showerProfile(shape, version=None):
-    """
-    Function which sets the E-correction parameters:
-    """
-
-    # ============================================================================
-    #                      function   #params      Outer         Middle       Inner
-    # ============================================================================
-    shape.Parameters["profile"] = [
-        6, 10, -0.0060, 0.0464, 0.0981, 2.4956, 2.0384, 2.2529, 115.0827,
-        36.5885, 33.8837, 9.8842, 8.0260, 8.0532, 0.0320, 0.0460, 0.0654,
-        2.0982, 2.3936, 2.2046, 1.0302, 1.0703, 1.1092, 0.0409, 0.1611, 0.1645,
-        0.0030, 0.0238, 0.0248, -9.6135, -5.8899, -5.7248
-    ]
-
-    ##
-    log.debug('Configure showerShape for Ecal hypotheses: %s' % shape.name())
-    #    shape.OutputLevel = 2
-    return shape
-
-
-# =============================================================================
-if '__main__' == __name__:
-    print(__doc__)
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index 96f840d674e..bb35da8e8b2 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -158,84 +158,24 @@ CaloFutureCorrectionBase::CaloFutureCorrectionBase( const std::string& type, con
 }
 
 StatusCode CaloFutureCorrectionBase::initialize() {
-  StatusCode sc = GaudiTool::initialize();
-  if ( sc.isFailure() ) return sc;
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Initialize" << endmsg;
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Condition name : " << m_conditionName << endmsg;
-
-  if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
-
-  // debug printout of all allowed hypos
-  if ( msgLevel( MSG::DEBUG ) ) {
-    debug() << " List of allowed hypotheses : " << endmsg;
-    for ( const auto& h : m_hypos ) { debug() << " -->" << h << endmsg; }
-    for ( const auto& c : m_corrections ) { debug() << "Accepted corrections :  '" << c << "'" << endmsg; }
-  }
-
-  return setConditionParams( m_conditionName );
+  return GaudiTool::initialize().andThen( [&]() -> StatusCode {
+    if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
+    return StatusCode::SUCCESS;
+  } );
 }
 
 StatusCode CaloFutureCorrectionBase::finalize() {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Finalize" << endmsg;
-
   if ( m_corrections.size() > 1 || *( m_corrections.begin() ) != "All" ) {
     for ( const auto& c : m_corrections ) { info() << "Accepted corrections :  '" << c << "'" << endmsg; }
   }
   if ( m_corrections.empty() ) warning() << "All corrections have been disabled for " << name() << endmsg;
-
-  if ( !m_cond )
-    warning() << " Applied corrections configured via options for  " << name() << endmsg;
-  else if ( msgLevel( MSG::DEBUG ) )
-    debug() << " Applied corrections configured via condDB  ('" << m_conditionName << "') for " << name() << endmsg;
-
-  if ( msgLevel( MSG::DEBUG ) ) {
-    for ( auto itype = 0; itype < static_cast<int>( CaloFutureCorrection::nT ); ++itype ) {
-      for ( auto area = 0; area < 3; ++area ) {
-        debug() << " o  '" << static_cast<CaloFutureCorrection::Type>( itype ) << "'  correction as a '"
-                << correctionName( m_params[itype][area] ) << "' function" << endmsg;
-      }
-    }
-  }
-
+  if ( !m_cond ) warning() << " Applied corrections configured via options for  " << name() << endmsg;
   m_hypos.clear();
-
   return GaudiTool::finalize(); // must be called after all other actions
 }
 
-//=============================================================================
-StatusCode CaloFutureCorrectionBase::setDBParams() {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Get params from CondDB condition = " << m_conditionName << endmsg;
-  registerCondition( m_conditionName, m_cond, &CaloFutureCorrectionBase::updParams );
-  return runUpdate();
-}
-// ============================================================================
-StatusCode CaloFutureCorrectionBase::setOptParams() {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Get params from options " << endmsg;
-  if ( m_optParams.empty() && m_conditionName != "none" ) {
-    info() << "No default options parameters defined" << endmsg;
-    return StatusCode::SUCCESS;
-  }
-  for ( const auto& [name, parVec] : m_optParams ) {
-    auto type = accept( name );
-    if ( !type ) continue;
-    if ( parVec.size() < 2 ) {
-      error() << " # of parameters is insufficient!!" << endmsg;
-      continue;
-    }
-    constructParams( m_params[*type], parVec );
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << " o Will apply correction '" << *type << "' as a '" << correctionName( m_params[*type].front() )
-              << "' function" << endmsg;
-  }
-  return StatusCode::SUCCESS;
-}
-// ============================================================================
 StatusCode CaloFutureCorrectionBase::updParams() {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "updParams() called" << endmsg;
   if ( !m_cond ) return Error( "Condition points to NULL", StatusCode::FAILURE );
-
   for ( const auto& paramName : m_cond->paramNames() ) {
     auto type = accept( paramName );
     if ( !type || !m_cond->exists( paramName ) ) continue;
@@ -375,24 +315,8 @@ std::optional<float> CaloFutureCorrectionBase::getCorrection( const CaloFutureCo
       m_params[type][id.area()] );
 }
 
-StatusCode CaloFutureCorrectionBase::setConditionParams( const std::string& cond,
-                                                         bool force ) { // force = true : forcing access via condDB only
-  if ( cond != m_conditionName ) m_conditionName = cond;
-
-  // get parameters from options  :
-  if ( !m_useCondDB && !force ) return setOptParams();
-
-  // get from DB if exists :
-  if ( !existDet<DataObject>( m_conditionName ) ) {
-    if ( force ) {
-      if ( m_conditionName != "none" )
-        info() << "Condition '" << m_conditionName.value() << "' has not been found " << endmsg;
-      return StatusCode::SUCCESS;
-    } else {
-      if ( msgLevel( MSG::DEBUG ) )
-        debug() << " Condition '" << m_conditionName.value() << "' has not found -- try options parameters !" << endmsg;
-      return setOptParams();
-    }
-  }
-  return setDBParams();
+StatusCode CaloFutureCorrectionBase::setConditionParams( const std::string& cond ) {
+  m_conditionName = cond;
+  registerCondition( m_conditionName, m_cond, &CaloFutureCorrectionBase::updParams );
+  return runUpdate();
 }
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 1482b98e9c1..707c514211a 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -129,8 +129,7 @@ public:
   StatusCode initialize() override;
   StatusCode finalize() override;
 
-  StatusCode setConditionParams( const std::string& cond,
-                                 bool               force = false ); // force = true : forcing access via condDB only
+  StatusCode setConditionParams( const std::string& cond );
 
   struct CorrectionResult {
     float value;
@@ -208,8 +207,6 @@ private:
   }
 
   StatusCode updParams();
-  StatusCode setOptParams();
-  StatusCode setDBParams();
 
 private:
   struct Polynomial {
@@ -286,10 +283,5 @@ private:
   std::array<std::array<Function, area_size>, CaloFutureCorrection::lastType + 1> m_params;
   void constructParams( std::array<Function, area_size>&, const LHCb::span<const double> );
 
-  Gaudi::Property<std::map<std::string, std::vector<double>>> m_optParams{this, "Parameters"};
-
   Condition*                   m_cond = nullptr;
-  Gaudi::Property<std::string> m_cmLoc{this, "ClusterMatchLocation",
-                                       LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch" )};
-  Gaudi::Property<bool>        m_useCondDB{this, "UseCondDB", true};
 };
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
index 21feb4cb8d3..77df71e7a48 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
@@ -198,7 +198,7 @@ namespace LHCb::Calo::Tools {
 
   StatusCode ShowerOverlap::initialize() {
     return GaudiTool::initialize().andThen( [&] { return m_shape.retrieve(); } ).andThen( [&] {
-      return m_shape->setConditionParams( m_pcond, true );
+      return m_shape->setConditionParams( m_pcond );
     } );
   }
 
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
index 6785deca7d3..0ba638ce3ed 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
@@ -100,7 +100,7 @@ namespace LHCb::Calo {
 
     // set DB accessor
     m_dbAccessor.retrieve().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
-    if ( m_conditionName.empty() || m_dbAccessor->setConditionParams( m_conditionName, true ).isFailure() )
+    if ( m_conditionName.empty() || m_dbAccessor->setConditionParams( m_conditionName ).isFailure() )
       return Error( "Cannot access DB", StatusCode::FAILURE );
 
     registerCondition( m_conditionName.value(), &ClusterCovarianceMatrixTool::setEstimatorParams_wrapper );
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
index e758fba2bae..24860fb053a 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
@@ -65,8 +65,7 @@ namespace LHCb::Calo {
 
     // setup DB accessor tool
     m_dbAccessor = tool<CaloFutureCorrectionBase>( "CaloFutureCorrectionBase", "DBAccessor", this );
-    sc           = m_dbAccessor->setConditionParams( m_condition,
-                                           true ); // force access via DB - if not exist will return empty params
+    sc           = m_dbAccessor->setConditionParams( m_condition );
     if ( sc.isFailure() ) return sc;
     m_DBtaggerE = std::vector<std::string>( nareas, "unset" );
     m_DBtaggerP = std::vector<std::string>( nareas, "unset" );
diff --git a/Rec/GlobalReco/python/GlobalReco/Configuration.py b/Rec/GlobalReco/python/GlobalReco/Configuration.py
index 850e083cb67..551d6eea6c8 100644
--- a/Rec/GlobalReco/python/GlobalReco/Configuration.py
+++ b/Rec/GlobalReco/python/GlobalReco/Configuration.py
@@ -206,7 +206,6 @@ class GlobalRecoConf(LHCbConfigurableUser):
         ecal_hypo = ecal.addTool(CaloFutureHypoEstimator,
                                  "CaloFutureHypoEstimator")
         ecal_hypo.ElectronMatchLocation = ecal.InputElectronMatchLocation
-        ecal_hypo.ClusterMatchLocation = ecal.InputClusterMatchLocation
         ecal_hypo.BremMatchLocation = ecal.InputElectronMatchLocation
 
         brem = addInfo(charged, ChargedProtoParticleAddBremInfo, "AddBrem")
@@ -215,7 +214,6 @@ class GlobalRecoConf(LHCbConfigurableUser):
                                  "CaloFutureHypoEstimator")
         brem_hypo.BremMatchLocation = brem.InputBremMatchLocation
         brem_hypo.ElectronMatchLocation = ecal.InputElectronMatchLocation
-        brem_hypo.ClusterMatchLocation = ecal.InputClusterMatchLocation
 
         hcal = addInfo(charged, ChargedProtoParticleAddHcalInfo, "AddHcal")
 
@@ -244,7 +242,6 @@ class GlobalRecoConf(LHCbConfigurableUser):
                                        "CaloFutureHypoEstimator")
 
         neutral_hypo.ElectronMatchLocation = ecal.InputElectronMatchLocation
-        neutral_hypo.ClusterMatchLocation = ecal.InputClusterMatchLocation
         neutral_hypo.BremMatchLocation = ecal.InputElectronMatchLocation  # FIXME???
 
         nseq.Members += [mpi0_converter1, ecal_converter1, neutral]
-- 
GitLab


From 2f901c5b62449e91bc5344b69bbe3d7729095284 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Wed, 28 Sep 2022 13:54:33 +0200
Subject: [PATCH 05/26] Cleaned up condition usage in CaloReco code

Essentially used proper condition derivations so that we are compatible with DD4hep
---
 .../src/CaloFutureCorrectionBase.cpp          |  42 ++--
 .../src/CaloFutureCorrectionBase.h            |  36 ++--
 .../src/CaloFutureShowerOverlapTool.cpp       |  10 +-
 .../src/FutureClusterCovarianceMatrixTool.cpp |  87 +++-----
 .../src/FutureClusterCovarianceMatrixTool.h   |  33 ++--
 .../src/FutureSubClusterSelectorTool.cpp      | 187 +++++++-----------
 .../src/FutureSubClusterSelectorTool.h        |  25 ++-
 7 files changed, 145 insertions(+), 275 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index bb35da8e8b2..8e870af61e6 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -153,13 +153,15 @@ DECLARE_COMPONENT( CaloFutureCorrectionBase )
 
 CaloFutureCorrectionBase::CaloFutureCorrectionBase( const std::string& type, const std::string& name,
                                                     const IInterface* parent )
-    : GaudiTool( type, name, parent ) {
+    : ConditionAccessorHolder( type, name, parent ) {
   declareInterface<CaloFutureCorrectionBase>( this );
 }
 
 StatusCode CaloFutureCorrectionBase::initialize() {
-  return GaudiTool::initialize().andThen( [&]() -> StatusCode {
+  return ConditionAccessorHolder::initialize().andThen( [&]() -> StatusCode {
     if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
+    addConditionDerivation( {m_conditionName}, m_params.key(),
+                            [&]( Condition const& cond ) { return updParams( cond ); } );
     return StatusCode::SUCCESS;
   } );
 }
@@ -169,32 +171,26 @@ StatusCode CaloFutureCorrectionBase::finalize() {
     for ( const auto& c : m_corrections ) { info() << "Accepted corrections :  '" << c << "'" << endmsg; }
   }
   if ( m_corrections.empty() ) warning() << "All corrections have been disabled for " << name() << endmsg;
-  if ( !m_cond ) warning() << " Applied corrections configured via options for  " << name() << endmsg;
   m_hypos.clear();
-  return GaudiTool::finalize(); // must be called after all other actions
+  return ConditionAccessorHolder::finalize(); // must be called after all other actions
 }
 
-StatusCode CaloFutureCorrectionBase::updParams() {
-  if ( !m_cond ) return Error( "Condition points to NULL", StatusCode::FAILURE );
-  for ( const auto& paramName : m_cond->paramNames() ) {
+CaloFutureCorrectionBase::Parameters CaloFutureCorrectionBase::updParams( Condition const& cond ) {
+  Parameters params;
+  for ( const auto& paramName : cond.paramNames() ) {
     auto type = accept( paramName );
-    if ( !type || !m_cond->exists( paramName ) ) continue;
-    const auto& parVec = m_cond->param<std::vector<double>>( paramName );
+    if ( !type || !cond.exists( paramName ) ) continue;
+    const auto& parVec = cond.param<std::vector<double>>( paramName );
     if ( parVec.size() < 2 ) {
       error() << " # of parameters is insufficient!!" << endmsg;
       continue;
     }
-    constructParams( m_params[*type], parVec );
-    if ( msgLevel( MSG::DEBUG ) ) {
-      debug() << " o Will apply correction '" << *type << "' as a '" << correctionName( m_params[*type].front() )
-              << "' function" << endmsg;
-    }
+    constructParams( params[*type], parVec );
   }
-  return StatusCode::SUCCESS;
+  return params;
 }
 
-void CaloFutureCorrectionBase::constructParams( std::array<Function, area_size>& fun,
-                                                LHCb::span<const double>         params ) {
+void CaloFutureCorrectionBase::constructParams( Functions& fun, LHCb::span<const double> params ) {
   // NOTE: conversion from double (params) to float (ParamVector)
   const auto func = static_cast<CaloFutureCorrection::Function>( std::lround( params[0] ) );
   const auto dim  = static_cast<int>( std::lround( params[1] ) );
@@ -207,7 +203,7 @@ void CaloFutureCorrectionBase::constructParams( std::array<Function, area_size>&
     if ( 3 * dim + 2 != static_cast<int>( params.size() ) ) {
       warning() << "o Size of DB parameter vector does not match the expectation for the DB specified type." << endmsg;
     }
-    for ( unsigned int area = 0; area != area_size; ++area ) {
+    for ( unsigned int area = 0; area < fun.size(); ++area ) {
       // transpose the parameters into the right order...
       std::vector<float> p;
       p.reserve( dim );
@@ -301,7 +297,7 @@ CaloFutureCorrectionBase::getCorrectionAndDerivative( const CaloFutureCorrection
                        []( const ParamVector& ) -> std::optional<CorrectionResult> {
                          return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
                        } ),
-      m_params[type][id.area()] );
+      m_params.get()[type][id.area()] );
 }
 
 std::optional<float> CaloFutureCorrectionBase::getCorrection( const CaloFutureCorrection::Type   type,
@@ -312,11 +308,5 @@ std::optional<float> CaloFutureCorrectionBase::getCorrection( const CaloFutureCo
                        []( const ParamVector& ) -> std::optional<float> {
                          return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
                        } ),
-      m_params[type][id.area()] );
-}
-
-StatusCode CaloFutureCorrectionBase::setConditionParams( const std::string& cond ) {
-  m_conditionName = cond;
-  registerCondition( m_conditionName, m_cond, &CaloFutureCorrectionBase::updParams );
-  return runUpdate();
+      m_params.get()[type][id.area()] );
 }
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 707c514211a..1f9eb9ee11a 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -15,6 +15,7 @@
 #include "CaloFutureUtils/CaloMomentum.h"
 #include "CaloFutureUtils/ClusterFunctors.h"
 #include "DetDesc/Condition.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "Detector/Calo/CaloCellID.h"
 #include "Event/CaloHypos_v2.h"
 #include "Event/Track.h"
@@ -119,7 +120,7 @@ namespace Gaudi::Parsers {
   StatusCode parse( std::vector<LHCb::Event::Calo::Hypotheses::Type>& r, const std::string& s );
 } // namespace Gaudi::Parsers
 
-class CaloFutureCorrectionBase : public GaudiTool {
+class CaloFutureCorrectionBase : public LHCb::DetDesc::ConditionAccessorHolder<GaudiTool> {
 
 public:
   static const InterfaceID& interfaceID() { return IID_CaloFutureCorrectionBase; }
@@ -129,8 +130,6 @@ public:
   StatusCode initialize() override;
   StatusCode finalize() override;
 
-  StatusCode setConditionParams( const std::string& cond );
-
   struct CorrectionResult {
     float value;
     float derivative;
@@ -146,7 +145,7 @@ public:
   const std::vector<float>&
   getParamVector( const CaloFutureCorrection::Type   type,
                   const LHCb::Detector::Calo::CellID id = LHCb::Detector::Calo::CellID() ) const {
-    return std::get<ParamVector>( m_params[type][id.area()] ).params;
+    return std::get<ParamVector>( m_params.get()[type][id.area()] ).params;
   }
 
   std::optional<float> getParameter( CaloFutureCorrection::Type type, unsigned int i,
@@ -173,14 +172,8 @@ protected:
         std::array{"Outer"sv, "Middle"sv, "Inner"sv, "PinArea"sv} );
   }
 
-  LHCb::ClusterFunctors::ClusterArea m_area;
-  Gaudi::Property<bool>              m_correctCovariance{this, "CorrectCovariance", true};
-
-private:
-  Gaudi::Property<std::string>              m_conditionName{this, "ConditionName", "none"};
-  Gaudi::Property<std::vector<std::string>> m_corrections{this, "Corrections", {"All"}};
-
-protected:
+  LHCb::ClusterFunctors::ClusterArea       m_area;
+  Gaudi::Property<bool>                    m_correctCovariance{this, "CorrectCovariance", true};
   Gaudi::Property<VectorOfHypothesesTypes> m_hypos{this,
                                                    "Hypotheses",
                                                    {
@@ -188,11 +181,12 @@ protected:
                                                        LHCb::Event::Calo::Hypotheses::Type::PhotonFromMergedPi0,
                                                        LHCb::Event::Calo::Hypotheses::Type::EmCharged,
                                                    },
-                                                   "acceptable hypotheses"
-
-  };
+                                                   "acceptable hypotheses"};
 
 private:
+  Gaudi::Property<std::string>              m_conditionName{this, "ConditionName", "none"};
+  Gaudi::Property<std::vector<std::string>> m_corrections{this, "Corrections", {"All"}};
+
   std::optional<CaloFutureCorrection::Type> accept( const std::string& name ) const {
     auto b = std::any_of( m_corrections.begin(), m_corrections.end(),
                           [&]( const auto& i ) { return i == name || i == "All"; } );
@@ -206,9 +200,6 @@ private:
     return std::nullopt;
   }
 
-  StatusCode updParams();
-
-private:
   struct Polynomial {
     static constexpr const char*               name = "Polynomial";
     boost::container::static_vector<float, 10> pars; // FIXME: how do I know that 10 is enough? Seems to depend on the
@@ -279,9 +270,10 @@ private:
   static const char* correctionName( const Function& cp ) {
     return std::visit( []( const auto& i ) { return i.name; }, cp );
   }
-  static constexpr int area_size = 3; // size of m_params (outer, middle, inner)
-  std::array<std::array<Function, area_size>, CaloFutureCorrection::lastType + 1> m_params;
-  void constructParams( std::array<Function, area_size>&, const LHCb::span<const double> );
 
-  Condition*                   m_cond = nullptr;
+  using Functions  = std::array<Function, 3>; // Inner, middle and Outer
+  using Parameters = std::array<Functions, CaloFutureCorrection::lastType + 1>;
+  void                          constructParams( Functions&, const LHCb::span<const double> );
+  ConditionAccessor<Parameters> m_params{this, name() + "/CaloFutureCorrectionBaseParameters"};
+  Parameters                    updParams( Condition const& );
 };
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
index 77df71e7a48..a356c4fe5ab 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
@@ -192,18 +192,10 @@ namespace LHCb::Calo::Tools {
     }
   } // namespace
 
-  //=============================================================================
-  // Initializer
-  //=============================================================================
-
   StatusCode ShowerOverlap::initialize() {
-    return GaudiTool::initialize().andThen( [&] { return m_shape.retrieve(); } ).andThen( [&] {
-      return m_shape->setConditionParams( m_pcond );
-    } );
+    return GaudiTool::initialize().andThen( [&] { return m_shape->setProperty( "ConditionName", m_pcond ); } );
   }
 
-  //=============================================================================
-
   void ShowerOverlap::process(
       const DeCalorimeter&                                                                              calo,
       LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cl1,
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
index 0ba638ce3ed..ecab140dfa5 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
@@ -30,91 +30,48 @@ namespace LHCb::Calo {
    */
   ClusterCovarianceMatrixTool::ClusterCovarianceMatrixTool( const std::string& type, const std::string& name,
                                                             const IInterface* parent )
-      : extends( type, name, parent ) {
+      : ConditionAccessorHolder( type, name, parent ) {
 
     // set default configuration as a function of detector
     auto det = LHCb::CaloFutureAlgUtils::CaloIndexFromAlg( name );
     assert( det == Detector::Calo::CellCode::Index::EcalCalo || det == Detector::Calo::CellCode::Index::HcalCalo );
     m_conditionName = "Conditions/Reco/Calo/" + toString( det ) + "Covariance";
-
-    // initialize parameters
-    auto push_if_not_present = [&]( const auto& key, auto value ) {
-      if ( !m_parameters.value().contains( key ) ) m_parameters.value().insert( key, {value} );
-    };
-
-    const auto ecal_default = {std::pair{LHCb::Calo::CovarianceMatrixTool::detail::Stochastic, 0.10},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::GainError, 0.01},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::IncoherentNoise, 1.20},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::CoherentNoise, 0.30},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::ConstantE, 0.},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::ConstantX, 0.},
-                               std::pair{LHCb::Calo::CovarianceMatrixTool::detail::ConstantY, 0.}};
-
-    for ( const auto& [key, value] : ecal_default ) push_if_not_present( key, value );
   }
 
-  StatusCode ClusterCovarianceMatrixTool::getParamsFromDB() {
-    // read parameters from DB // TODO: can they change with detector conditions?
-    static constexpr int nareas = 3; // FIXME: get it from DeCalorimeter instead?
-
+  CovarianceMatrixTool::detail::ParameterMap ClusterCovarianceMatrixTool::getParams() {
     LHCb::Calo::CovarianceMatrixTool::detail::ParameterMap parameters;
-    for ( unsigned int area = 0; area < nareas; ++area ) { // loop over calo area
+    for ( unsigned int area = 0; area < 3; ++area ) { // loop over calo area
       const auto& params = m_dbAccessor->getParamVector(
           CaloFutureCorrection::ClusterCovariance,
           Detector::Calo::CellID{LHCb::Detector::Calo::CellCode::Index::EcalCalo, area, 0, 0} );
       // FIXME: read Calo index from DeCalorimeter
       if ( params.size() > LHCb::Calo::CovarianceMatrixTool::detail::Parameter::Last ) ++m_parExceeded;
+      if ( params.size() < LHCb::Calo::CovarianceMatrixTool::detail::Parameter::Last ) {
+        throw GaudiException( "ClusterCovarianceMatrixTool::getParams",
+                              "Not enough values found in DB for ClusterCovariance", StatusCode::FAILURE );
+      }
       for ( auto index : LHCb::Calo::CovarianceMatrixTool::detail::Parameters{} ) {
-        if ( index < params.size() ) {
-          parameters[index].push_back( params[index] );
-        } else {
-          if ( msgLevel( MSG::DEBUG ) )
-            debug() << "Parameter '" << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::name( index )
-                    << "' not found in DB - use default options value" << endmsg;
-          if ( !m_parameters.value().contains( index ) )
-            return Error( fmt::format( "No default value for parameter '{}'",
-                                       LHCb::Calo::CovarianceMatrixTool::detail::Parameters::name( index ) ),
-                          StatusCode::FAILURE );
-          parameters[index].push_back( m_parameters[index][area] );
-        }
+        parameters[index].push_back( params[index] );
       }
     }
-    m_parameters = std::move( parameters );
-
-    return m_parameters.empty() ? StatusCode::FAILURE // no parameters set
-                                : StatusCode::SUCCESS;
-  }
-
-  void ClusterCovarianceMatrixTool::setEstimatorParams() {
-    // update DB parameters
-    if ( getParamsFromDB().isFailure() ) {
-      ++m_failureUpdating;
-      return; // failed to update parameters from DB
-    }
     ++m_parUpdate;
-  }
-
-  StatusCode ClusterCovarianceMatrixTool::initialize() {
-    StatusCode sc = extends::initialize();
-    if ( sc.isFailure() ) return sc;
-
-    // set DB accessor
-    m_dbAccessor.retrieve().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
-    if ( m_conditionName.empty() || m_dbAccessor->setConditionParams( m_conditionName ).isFailure() )
-      return Error( "Cannot access DB", StatusCode::FAILURE );
-
-    registerCondition( m_conditionName.value(), &ClusterCovarianceMatrixTool::setEstimatorParams_wrapper );
-
-    // read parameters
-    setEstimatorParams();
-
     // info
     info() << " \t ==  Parameters for covariance estimation ==" << endmsg;
     for ( auto index : LHCb::Calo::CovarianceMatrixTool::detail::Parameters{} ) {
-      info() << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::name( index )
-             << " \t : " << m_parameters.value()[index] << " "
-             << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::unit( index ) << endmsg;
+      info() << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::name( index ) << " \t : " << parameters[index]
+             << " " << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::unit( index ) << endmsg;
     }
-    return sc;
+    return parameters;
+  }
+
+  StatusCode ClusterCovarianceMatrixTool::initialize() {
+    return ConditionAccessorHolder::initialize()
+        .andThen( [&] { return m_dbAccessor->setProperty( "ConditionName", m_conditionName ); } )
+        .andThen( [&] {
+          // depends on m_conditionName so that calls to m_dbAccessor give proper results
+          addConditionDerivation( {m_conditionName}, m_parameters.key(),
+                                  [&]( Condition const& ) { return getParams(); } );
+          return StatusCode::SUCCESS;
+        } );
   }
 } // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index bb9025d5581..ff99721f010 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -11,6 +11,7 @@
 
 #include "CaloFutureCorrectionBase.h"
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "Detector/Calo/CaloCellID.h"
 #include "Event/CaloClusters_v2.h"
 #include "Event/CaloDataFunctor.h"
@@ -259,7 +260,8 @@ namespace std {
 } // namespace std
 
 namespace LHCb::Calo {
-  class ClusterCovarianceMatrixTool : public extends<GaudiTool, Interfaces::IClusterTool> {
+  class ClusterCovarianceMatrixTool
+      : public LHCb::DetDesc::ConditionAccessorHolder<extends<GaudiTool, Interfaces::IClusterTool>> {
   public:
     ClusterCovarianceMatrixTool( const std::string& type, const std::string& name, const IInterface* parent );
     StatusCode initialize() override;
@@ -453,21 +455,14 @@ namespace LHCb::Calo {
     }
 
   private:
-    StatusCode setEstimatorParams_wrapper() {
-      setEstimatorParams();
-      return StatusCode::SUCCESS;
-    }
-    StatusCode getParamsFromDB();
-    void       setEstimatorParams();
+    CovarianceMatrixTool::detail::ParameterMap getParams();
 
-    Gaudi::Property<LHCb::Calo::CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, "Parameters"};
-    Gaudi::Property<std::string>                                            m_conditionName{this, "ConditionName"};
+    ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "/Parameters"};
+    Gaudi::Property<std::string>                                  m_conditionName{this, "ConditionName"};
     ToolHandle<CaloFutureCorrectionBase> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
 
     mutable Gaudi::Accumulators::Counter<>              m_parUpdate{this, "parameter updated"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_negative_energy{this, "negative energy cluster"};
-    mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_failureUpdating{
-        this, "Failed updating the covariance parameters from DB"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_parExceeded{
         this, "Parameters vector exceeds the number of known parameters"};
 
@@ -475,7 +470,7 @@ namespace LHCb::Calo {
      *  @return A*A*GeV resolution parameter
      */
     [[nodiscard]] double a2GeV( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::Stochastic );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::Stochastic );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()] * Gaudi::Units::GeV;
     }
@@ -484,7 +479,7 @@ namespace LHCb::Calo {
      *  @return dispersion of relative gain error
      */
     [[nodiscard]] double s2gain( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::GainError );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::GainError );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
@@ -500,7 +495,7 @@ namespace LHCb::Calo {
      *  @return dispersion of incoherent noise
      */
     [[nodiscard]] double s2incoherent( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::IncoherentNoise );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::IncoherentNoise );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
@@ -509,27 +504,27 @@ namespace LHCb::Calo {
      *  @return dispersion of coherent noise
      */
     [[nodiscard]] double s2coherent( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::CoherentNoise );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::CoherentNoise );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
     [[nodiscard]] double s2E( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantE );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantE );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
     [[nodiscard]] double s2X( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantX );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantX );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
     [[nodiscard]] double s2Y( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.value().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantY );
+      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantY );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
   }; ///< end of class FutureClusterCovarianceMatrixTool
-} // namespace LHCb::Calo
\ No newline at end of file
+} // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
index 24860fb053a..c59783290b9 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
@@ -20,12 +20,9 @@ namespace LHCb::Calo {
   // Declaration of the Tool Factory
   DECLARE_COMPONENT_WITH_ID( SubClusterSelectorTool, "FutureSubClusterSelectorTool" )
 
-  //=============================================================================
-  // Standard constructor, initializes variables
-  //=============================================================================
   SubClusterSelectorTool::SubClusterSelectorTool( const std::string& type, const std::string& name,
                                                   const IInterface* parent )
-      : GaudiTool( type, name, parent ) {
+      : ConditionAccessorHolder( type, name, parent ) {
     declareInterface<SubClusterSelectorTool>( this );
 
     // define calo-dependent property
@@ -53,104 +50,18 @@ namespace LHCb::Calo {
     }
   }
 
-  //=============================================================================
-
   StatusCode SubClusterSelectorTool::initialize() {
-    StatusCode sc = GaudiTool::initialize(); // must be executed first
-    if ( sc.isFailure() ) return sc;         // error printed already by GaudiTool
-
-    // get detector info
-    // FIXME: get it from DeCalorimeter instead
-    static constexpr int nareas = 3;
-
-    // setup DB accessor tool
-    m_dbAccessor = tool<CaloFutureCorrectionBase>( "CaloFutureCorrectionBase", "DBAccessor", this );
-    sc           = m_dbAccessor->setConditionParams( m_condition );
-    if ( sc.isFailure() ) return sc;
-    m_DBtaggerE = std::vector<std::string>( nareas, "unset" );
-    m_DBtaggerP = std::vector<std::string>( nareas, "unset" );
-    m_sourceE   = " (none)";
-    m_sourceP   = " (none)";
-
-    // always set options parameters first
-    sc = getParamsFromOptions();
-    if ( sc.isFailure() ) return sc;
-
-    // then possibly update from DB
-    updateParamsFromDB().ignore();
-
-    updMgrSvc()->registerCondition( this, m_condition.value(), &SubClusterSelectorTool::updateParamsFromDB );
-
-    info() << " Energy   mask : " << m_DBtaggerE << m_sourceE << endmsg;
-    info() << " Position mask : " << m_DBtaggerP << m_sourceP << endmsg;
-
-    return sc;
-  }
-
-  StatusCode SubClusterSelectorTool::updateParamsFromDB() {
-
-    // FIXME: get it from DeCalorimeter instead
-    static constexpr int nareas  = 3;
-    auto                 caloidx = LHCb::Detector::Calo::CellCode::Index::EcalCalo;
-
-    if ( msgLevel( MSG::DEBUG ) ) {
-      debug() << "SubClusterSelectorTool::updateParamsFromDB:" << endmsg;
-      debug() << m_taggerE << endmsg;
-      debug() << m_taggerP << endmsg;
-    }
-
-    using namespace CaloFutureClusterMask;
-
-    for ( unsigned int area = 0; area < nareas; ++area ) {
-      LHCb::Detector::Calo::CellID id = LHCb::Detector::Calo::CellID( caloidx, area, 0, 0 );
-
-      if ( m_taggerE[area] == "useDB" ) {
-        m_sourceE = " (from DB) ";
-        Mask maskE =
-            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::EnergyMask, 0, id ).value_or( 0. ); // default is
-                                                                                                        // 3x3 when no
-                                                                                                        // DB
-        std::string nameE = maskName[maskE];
-        if ( nameE != m_DBtaggerE[area] ) { // DB has changed ! update !
-          std::string taggerE =
-              ( m_clusterTaggers.find( nameE ) != m_clusterTaggers.end() ) ? m_clusterTaggers[nameE] : "";
-          if ( !taggerE.empty() ) {
-            Interfaces::ISubClusterTag* tE =
-                tool<Interfaces::ISubClusterTag>( taggerE, id.areaName() + "EnergyTagger", this );
-            tE->setMask( m_energyStatus );
-            m_tagE.push_back( tE );
-            m_DBtaggerE[area] = nameE;
-          } else
-            ++m_energy_update_failed;
-        }
-      }
-
-      if ( m_taggerP[area] == "useDB" ) {
-        m_sourceP = " (from DB) ";
-        Mask maskP =
-            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::PositionMask, 0, id ).value_or( 0. ); // default is
-                                                                                                          // 3x3 when no
-                                                                                                          // DB
-        std::string nameP = maskName[maskP];
-        if ( nameP != m_DBtaggerP[area] ) { // DB has changed ! update !
-          std::string taggerP =
-              ( m_clusterTaggers.find( nameP ) != m_clusterTaggers.end() ) ? m_clusterTaggers[nameP] : "";
-          if ( !taggerP.empty() ) {
-            Interfaces::ISubClusterTag* tP =
-                tool<Interfaces::ISubClusterTag>( taggerP, id.areaName() + "PositionTagger", this );
-            tP->setMask( m_positionStatus );
-            m_tagP.push_back( tP );
-            m_DBtaggerP[area] = nameP;
-          } else
-            ++m_position_update_failed;
-        }
-      }
-    }
-    return StatusCode::SUCCESS;
+    return ConditionAccessorHolder::initialize()
+        .andThen( [&] { return m_dbAccessor->setProperty( "ConditionName", m_condition ); } )
+        .andThen( [&] {
+          // depends on m_conditio so that calls to m_dbAccessor give proper results
+          addConditionDerivation( {m_condition}, m_tags.key(), [&]( Condition const& ) { return getParams(); } );
+          return StatusCode::SUCCESS;
+        } );
   }
 
-  StatusCode SubClusterSelectorTool::getParamsFromOptions() {
-
+  SubClusterSelectorTool::Tags SubClusterSelectorTool::getParams() {
+    Tags tags;
     // FIXME: get it from DeCalorimeter instead
     static constexpr int narea   = 3;
     auto                 caloidx = LHCb::Detector::Calo::CellCode::Index::EcalCalo;
@@ -158,47 +69,83 @@ namespace LHCb::Calo {
     // extend tagger per area when needed
     if ( m_taggerE.size() == 1 ) m_taggerE = std::vector<std::string>( narea, m_taggerE[0] );
     if ( m_taggerP.size() == 1 ) m_taggerP = std::vector<std::string>( narea, m_taggerP[0] );
-    if ( m_taggerE.size() != narea || m_taggerP.size() != narea )
-      return Error( "You must define the tagger for each calo area" );
-
+    if ( m_taggerE.size() != narea || m_taggerP.size() != narea ) {
+      throw GaudiException( "SubClusterSelectorTool", "You must define the tagger for each calo area",
+                            StatusCode::FAILURE );
+    }
     using namespace CaloFutureClusterMask;
-    // == Define Energy tagger per area
-    m_DBtaggerE = std::vector<std::string>( narea, "unset" );
-    m_DBtaggerP = std::vector<std::string>( narea, "unset" );
+    std::string sourceE = " (none)";
+    std::string sourceP = " (none)";
 
     for ( unsigned int area = 0; area < narea; ++area ) {
-      std::string areaName = LHCb::Detector::Calo::CellID( caloidx, area, 0, 0 ).areaName();
+      LHCb::Detector::Calo::CellID id       = LHCb::Detector::Calo::CellID( caloidx, area, 0, 0 );
+      std::string                  areaName = id.areaName();
 
       std::string nameE = m_taggerE[area];
       if ( nameE != "useDB" ) {
-        m_sourceE = " (from options) ";
+        sourceE = " (from options) ";
         std::string taggerE =
             ( m_clusterTaggers.find( nameE ) != m_clusterTaggers.end() ) ? m_clusterTaggers[nameE] : "";
-        if ( taggerE == "" )
-          return Error( "Cannot find a  '" + nameE + "' tagger - You must select or define a known tagging method",
-                        StatusCode::FAILURE );
+        if ( taggerE == "" ) {
+          throw GaudiException( "SubClusterSelectorTool",
+                                "Cannot find a  '" + nameE +
+                                    "' tagger - You must select or define a known tagging method",
+                                StatusCode::FAILURE );
+        }
         Interfaces::ISubClusterTag* tE = tool<Interfaces::ISubClusterTag>( taggerE, areaName + "EnergyTagger", this );
         tE->setMask( m_energyStatus );
-        m_tagE.push_back( tE );
-        m_DBtaggerE[area] = nameE;
+        tags[0].push_back( tE );
+      } else {
+        sourceE = " (from DB) ";
+        Mask maskE =
+            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::EnergyMask, 0, id ).value_or( 0. ); // default is
+                                                                                                        // when no DB
+        std::string name    = maskName[maskE];
+        std::string taggerE = ( m_clusterTaggers.find( name ) != m_clusterTaggers.end() ) ? m_clusterTaggers[name] : "";
+        if ( !taggerE.empty() ) {
+          Interfaces::ISubClusterTag* tE =
+              tool<Interfaces::ISubClusterTag>( taggerE, id.areaName() + "EnergyTagger", this );
+          tE->setMask( m_energyStatus );
+          tags[0].push_back( tE );
+        } else {
+          ++m_energy_update_failed;
+        }
       }
 
       std::string nameP = m_taggerP[area];
       if ( nameP != "useDB" ) {
-        m_sourceP = " (from options) ";
+        sourceP = " (from options) ";
         std::string taggerP =
             ( m_clusterTaggers.find( nameP ) != m_clusterTaggers.end() ) ? m_clusterTaggers[nameP] : "";
-        if ( taggerP.empty() )
-          return Error( "Cannot find a  '" + nameP + "' tagger - You must select or define a known tagging method",
-                        StatusCode::FAILURE );
+        if ( taggerP.empty() ) {
+          throw GaudiException( "SubClusterSelectorTool",
+                                "Cannot find a  '" + nameP +
+                                    "' tagger - You must select or define a known tagging method",
+                                StatusCode::FAILURE );
+        }
         Interfaces::ISubClusterTag* tP = tool<Interfaces::ISubClusterTag>( taggerP, areaName + "PositionTagger", this );
         tP->setMask( m_positionStatus );
-        m_tagP.push_back( tP );
-        m_DBtaggerP[area] = nameP;
+        tags[1].push_back( tP );
+      } else {
+        sourceP = " (from DB) ";
+        Mask maskP =
+            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::PositionMask, 0, id ).value_or( 0. ); // default is
+        // 3x3 when no
+        // DB
+        std::string name    = maskName[maskP];
+        std::string taggerP = ( m_clusterTaggers.find( name ) != m_clusterTaggers.end() ) ? m_clusterTaggers[name] : "";
+        if ( !taggerP.empty() ) {
+          Interfaces::ISubClusterTag* tP =
+              tool<Interfaces::ISubClusterTag>( taggerP, id.areaName() + "PositionTagger", this );
+          tP->setMask( m_positionStatus );
+          tags[1].push_back( tP );
+        } else
+          ++m_position_update_failed;
       }
     }
-
-    return StatusCode::SUCCESS;
+    info() << " Energy   mask : " << sourceE << endmsg;
+    info() << " Position mask : " << sourceP << endmsg;
+    return tags;
   }
 
 } // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
index 521ae3b058a..5b113cb9874 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
@@ -14,6 +14,7 @@
 // from Gaudi
 #include "CaloDet/DeCalorimeter.h"
 #include "CaloFutureCorrectionBase.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "Event/CaloClusters_v2.h"
 #include "GaudiAlg/GaudiTool.h"
 #include "ICaloFutureSubClusterTag.h"
@@ -40,7 +41,7 @@ namespace LHCb::Calo {
    *  @date   2014-06-20
    */
 
-  class SubClusterSelectorTool : public GaudiTool {
+  class SubClusterSelectorTool : public LHCb::DetDesc::ConditionAccessorHolder<GaudiTool> {
   public:
     // Return the interface ID
     static const InterfaceID& interfaceID() { return IID_FutureSubClusterSelectorTool; }
@@ -54,7 +55,7 @@ namespace LHCb::Calo {
     StatusCode tagEnergy( const DeCalorimeter& calo, LHCb::Detector::Calo::CellID id,
                           LHCb::Event::Calo::Clusters::Entries<simd, behaviour> entries ) const {
       // get the tagger
-      auto* tagger = ( id.area() < m_tagE.size() ) ? m_tagE[id.area()] : nullptr;
+      auto* tagger = ( id.area() < m_tags.get()[0].size() ) ? m_tags.get()[0][id.area()] : nullptr;
       if ( !tagger ) {
         ++m_no_tagger;
         return StatusCode::FAILURE;
@@ -66,7 +67,7 @@ namespace LHCb::Calo {
     StatusCode tagPosition( const DeCalorimeter& calo, LHCb::Detector::Calo::CellID id,
                             LHCb::Event::Calo::Clusters::Entries<simd, behaviour> entries ) const {
       // get the tagger
-      auto* tagger = ( id.area() < m_tagP.size() ) ? m_tagP[id.area()] : nullptr;
+      auto* tagger = ( id.area() < m_tags.get()[1].size() ) ? m_tags.get()[1][id.area()] : nullptr;
       if ( !tagger ) {
         ++m_no_tagger;
         return StatusCode::FAILURE;
@@ -81,13 +82,12 @@ namespace LHCb::Calo {
     }
 
   private:
-    StatusCode getParamsFromOptions();
-    StatusCode updateParamsFromDB();
-
     Gaudi::Property<std::vector<std::string>> m_taggerE{this, "EnergyTags", {}};
     Gaudi::Property<std::vector<std::string>> m_taggerP{this, "PositionTags", {}};
-    std::vector<Interfaces::ISubClusterTag*>  m_tagE;
-    std::vector<Interfaces::ISubClusterTag*>  m_tagP;
+    using Tags = std::array<std::vector<Interfaces::ISubClusterTag*>, 2>; // 0 -> Energy, 1 -> Position
+    ConditionAccessor<Tags> m_tags{this, name() + "/SubClusterSelectorToolTags"};
+
+    Tags getParams();
 
     // associate known cluster mask to tagger tool
     Gaudi::Property<std::map<std::string, std::string>> m_clusterTaggers{
@@ -104,15 +104,12 @@ namespace LHCb::Calo {
 
     Gaudi::Property<std::string> m_condition{this, "ConditionName", ""};
 
-    CaloFutureCorrectionBase*     m_dbAccessor = nullptr;
-    std::vector<std::string>      m_DBtaggerE;
-    std::vector<std::string>      m_DBtaggerP;
-    LHCb::CaloDigitStatus::Status m_energyStatus = LHCb::CaloDigitStatus::Status{
+    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase",
+                                                      "CaloFutureCorrectionBase/DBAccessor"};
+    LHCb::CaloDigitStatus::Status        m_energyStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForEnergy, LHCb::CaloDigitStatus::Mask::UseForCovariance};
     LHCb::CaloDigitStatus::Status m_positionStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForPosition, LHCb::CaloDigitStatus::Mask::UseForCovariance};
-    std::string m_sourceE;
-    std::string m_sourceP;
 
     mutable Gaudi::Accumulators::MsgCounter<MSG::WARNING> m_no_tagger{this, "Tagger not found"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::WARNING> m_energy_update_failed{this,
-- 
GitLab


From 25029c0f17cd0c8548767474a48a57ef7c0edbf6 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Thu, 29 Sep 2022 13:12:01 +0200
Subject: [PATCH 06/26] Fixed handling of properties

---
 .../python/CaloFutureReco/Reconstruction.py   | 30 +++++++++++++++++++
 .../src/CaloFutureClusterCovarianceAlg.cpp    | 21 -------------
 .../src/CaloFutureCorrectionBase.h            |  2 +-
 .../src/CaloFutureShowerOverlapTool.cpp       |  6 ----
 .../src/FutureClusterCovarianceMatrixTool.cpp | 28 ++++-------------
 .../src/FutureClusterCovarianceMatrixTool.h   |  6 ++--
 .../src/FutureSubClusterSelectorTool.cpp      | 24 ++++-----------
 .../src/FutureSubClusterSelectorTool.h        |  6 ++--
 .../python/JetAccessories/HltJetConf.py       |  8 +++++
 .../JetAccessories/ParticleFlow_Config.py     |  8 +++++
 10 files changed, 62 insertions(+), 77 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
index a02c0e78e47..9c73c034c64 100644
--- a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
+++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
@@ -78,8 +78,26 @@ def clusterFutureReco(enableRecoOnDemand,
     seq.Members[:] = []
 
     clust = FutureCellularAutomatonAlg("FutureEcalClust")
+
     share = CaloFutureShowerOverlap("FutureEcalShare")
+    share.SubClusterSelector = 'FutureSubClusterSelectorTool/EcalClusterTag'
+    share.SubClusterSelector.ConditionName = 'Conditions/Reco/Calo/EcalClusterMasks'
+    share.SubClusterSelector.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+    share.SubClusterSelector.CaloFutureCorrectionBase.ConditionName = share.EcalClusterTag.ConditionName
+    share.OverlapTool = 'CaloFutureShowerOverlapTool/PhotonShowerOverlap'
+    share.OverlapTool.ConditionName = 'Conditions/Reco/Calo/PhotonShowerProfile'
+    share.OverlapTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/ShowerProfile'
+    share.OverlapTool.CaloFutureCorrectionBase.ConditionName = share.SplitPhotonShowerOverlap.ConditionName
+
     covar = CaloFutureClusterCovarianceAlg("FutureEcalCovar")
+    covar.CovarianceTool = 'FutureClusterCovarianceMatrixTool/EcalCovarTool'
+    covar.CovarianceTool.ConditionName = 'Conditions/Reco/Calo/EcalCovariance'
+    covar.CovarianceTool.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+    covar.CovarianceTool.CorrectionBase.ConditionName = covar.CovarianceTool.ConditionName
+    covar.TaggerTool = 'FutureSubClusterSelectorTool/EcalClusterTag'
+    covar.TaggerTool.ConditionName = 'Conditions/Reco/Calo/EcalClusterMasks'
+    covar.TaggerTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+    covar.TaggerTool.CaloFutureCorrectionBase.ConditionName = covar.TaggerTool.ConditionName
 
     if masksE != []:
         share.EnergyTags = masksE
@@ -220,6 +238,18 @@ def mergedPi0FutureReco(enableRecoOnDemand,
 
     ## Merged Pi0
     pi0 = CaloFutureMergedPi0('MergedPi0RecFuture')
+    pi0.EcalCovariance = 'FutureClusterCovarianceMatrixTool/EcalCovariance'
+    pi0.EcalCovariance.ConditionName = 'Conditions/Reco/Calo/EcalCovariance'
+    pi0.EcalCovariance.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+    pi0.EcalCovariance.CorrectionBase.ConditionName = i0.EcalCovariance.ConditionName
+    pi0.EcalClusterTag = 'FutureSubClusterSelectorTool/EcalClusterTag'
+    pi0.EcalClusterTag.ConditionName = 'Conditions/Reco/Calo/EcalClusterMasks'
+    pi0.EcalClusterTag.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+    pi0.EcalClusterTag.CaloFutureCorrectionBase.ConditionName = pi0.EcalClusterTag.ConditionName
+    pi0.SplitPhotonShowerOverlap = 'CaloFutureShowerOverlapTool/SplitPhotonShowerOverlap'
+    pi0.SplitPhotonShowerOverlap.ConditionName = 'Conditions/Reco/Calo/PhotonShowerProfile'
+    pi0.SplitPhotonShowerOverlap.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/ShowerProfile'
+    pi0.SplitPhotonShowerOverlap.CaloFutureCorrectionBase.ConditionName = pi0.SplitPhotonShowerOverlap.ConditionName
 
     if masksE != []:
         pi0.EnergyTags = masksE
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
index b023e529422..e6a200aa821 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
@@ -37,18 +37,7 @@ namespace LHCb::Calo::Algorithms {
                                       LHCb::DetDesc::usesConditions<DeCalorimeter>> {
 
   public:
-    /** Standard constructor
-     *  @param   name          algorithm name
-     *  @param   pSvcLocator   pointer to Service Locator
-     */
     ClusterCovariance( const std::string& name, ISvcLocator* pSvcLocator );
-
-    /** standard execution method
-     *  @see GaudiAlgorithm
-     *  @see     Algorithm
-     *  @see    IAlgorithm
-     *  @return Container of
-     */
     Event::Calo::Clusters operator()( const EventContext& evtCtx, const DeCalorimeter&,
                                       const Event::Calo::Clusters& ) const override;
 
@@ -79,19 +68,12 @@ namespace LHCb::Calo::Algorithms {
   };
   DECLARE_COMPONENT_WITH_ID( ClusterCovariance, "CaloFutureClusterCovarianceAlg" )
 
-  // ============================================================================
-  /** Standard constructor
-   *  @param   name          algorithm name
-   *  @param   pSVcLocator   pointer to Service Locator
-   */
-  // ============================================================================
   ClusterCovariance::ClusterCovariance( const std::string& name, ISvcLocator* pSvcLocator )
       : Transformer( name, pSvcLocator,
                      {KeyValue{"Detector", Utilities::DeCaloFutureLocation( name )},
                       KeyValue{"InputData", CaloFutureAlgUtils::CaloFutureClusterLocation( name, "EcalOverlap" )}},
                      KeyValue{"OutputData", CaloFutureAlgUtils::CaloFutureClusterLocation( name, "Ecal" )} ) {}
 
-  // ===========================================================================
   [[gnu::flatten]] Event::Calo::Clusters ClusterCovariance::
                                          operator()( const EventContext& evtCtx, const DeCalorimeter& calo, const Event::Calo::Clusters& clusters ) const {
 
@@ -125,10 +107,7 @@ namespace LHCb::Calo::Algorithms {
         continue;
       }
     }
-
-    // == counter
     m_clusters += clusters.size();
-
     return outputClusters;
   }
 } // namespace LHCb::Calo::Algorithms
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 1f9eb9ee11a..5134218b163 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -274,6 +274,6 @@ private:
   using Functions  = std::array<Function, 3>; // Inner, middle and Outer
   using Parameters = std::array<Functions, CaloFutureCorrection::lastType + 1>;
   void                          constructParams( Functions&, const LHCb::span<const double> );
-  ConditionAccessor<Parameters> m_params{this, name() + "/CaloFutureCorrectionBaseParameters"};
+  ConditionAccessor<Parameters> m_params{this, name() + "-CaloFutureCorrectionBaseParameters"};
   Parameters                    updParams( Condition const& );
 };
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
index a356c4fe5ab..6c1563f160a 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
@@ -52,8 +52,6 @@ namespace LHCb::Calo::Tools {
   public:
     using extends::extends;
 
-    StatusCode initialize() override;
-
     // if niter < 0, stop if the tolerance criteria is satisfied (see definition),
     // perform maximum -niter iterations
     void process( const DeCalorimeter& calo,
@@ -192,10 +190,6 @@ namespace LHCb::Calo::Tools {
     }
   } // namespace
 
-  StatusCode ShowerOverlap::initialize() {
-    return GaudiTool::initialize().andThen( [&] { return m_shape->setProperty( "ConditionName", m_pcond ); } );
-  }
-
   void ShowerOverlap::process(
       const DeCalorimeter&                                                                              calo,
       LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cl1,
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
index ecab140dfa5..b6a2826e965 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
@@ -23,21 +23,6 @@
 namespace LHCb::Calo {
   DECLARE_COMPONENT_WITH_ID( ClusterCovarianceMatrixTool, "FutureClusterCovarianceMatrixTool" )
 
-  /** Standard constructor
-   *  @param type tool type (useless)
-   *  @param name tool name
-   *  @param parent pointer to parent object (service, algorithm or tool)
-   */
-  ClusterCovarianceMatrixTool::ClusterCovarianceMatrixTool( const std::string& type, const std::string& name,
-                                                            const IInterface* parent )
-      : ConditionAccessorHolder( type, name, parent ) {
-
-    // set default configuration as a function of detector
-    auto det = LHCb::CaloFutureAlgUtils::CaloIndexFromAlg( name );
-    assert( det == Detector::Calo::CellCode::Index::EcalCalo || det == Detector::Calo::CellCode::Index::HcalCalo );
-    m_conditionName = "Conditions/Reco/Calo/" + toString( det ) + "Covariance";
-  }
-
   CovarianceMatrixTool::detail::ParameterMap ClusterCovarianceMatrixTool::getParams() {
     LHCb::Calo::CovarianceMatrixTool::detail::ParameterMap parameters;
     for ( unsigned int area = 0; area < 3; ++area ) { // loop over calo area
@@ -65,13 +50,10 @@ namespace LHCb::Calo {
   }
 
   StatusCode ClusterCovarianceMatrixTool::initialize() {
-    return ConditionAccessorHolder::initialize()
-        .andThen( [&] { return m_dbAccessor->setProperty( "ConditionName", m_conditionName ); } )
-        .andThen( [&] {
-          // depends on m_conditionName so that calls to m_dbAccessor give proper results
-          addConditionDerivation( {m_conditionName}, m_parameters.key(),
-                                  [&]( Condition const& ) { return getParams(); } );
-          return StatusCode::SUCCESS;
-        } );
+    return ConditionAccessorHolder::initialize().andThen( [&] {
+      // depends on m_conditionName so that calls to m_dbAccessor give proper results
+      addConditionDerivation( {m_conditionName}, m_parameters.key(), [&]( Condition const& ) { return getParams(); } );
+      return StatusCode::SUCCESS;
+    } );
   }
 } // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index ff99721f010..9897fb3a54e 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -263,7 +263,7 @@ namespace LHCb::Calo {
   class ClusterCovarianceMatrixTool
       : public LHCb::DetDesc::ConditionAccessorHolder<extends<GaudiTool, Interfaces::IClusterTool>> {
   public:
-    ClusterCovarianceMatrixTool( const std::string& type, const std::string& name, const IInterface* parent );
+    using ConditionAccessorHolder::ConditionAccessorHolder;
     StatusCode initialize() override;
 
     StatusCode
@@ -457,8 +457,8 @@ namespace LHCb::Calo {
   private:
     CovarianceMatrixTool::detail::ParameterMap getParams();
 
-    ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "/Parameters"};
-    Gaudi::Property<std::string>                                  m_conditionName{this, "ConditionName"};
+    ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "-Parameters"};
+    Gaudi::Property<std::string>                                  m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
     ToolHandle<CaloFutureCorrectionBase> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
 
     mutable Gaudi::Accumulators::Counter<>              m_parUpdate{this, "parameter updated"};
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
index c59783290b9..694c67695d7 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
@@ -24,11 +24,6 @@ namespace LHCb::Calo {
                                                   const IInterface* parent )
       : ConditionAccessorHolder( type, name, parent ) {
     declareInterface<SubClusterSelectorTool>( this );
-
-    // define calo-dependent property
-    m_condition = fmt::format( "Conditions/Reco/Calo/{}ClusterMasks",
-                               toString( LHCb::CaloFutureAlgUtils::CaloIndexFromAlg( name ) ) );
-
     // inherit properties from parents
     if ( parent ) {
       if ( const IProperty* prop = dynamic_cast<const IProperty*>( parent ); prop ) {
@@ -38,26 +33,17 @@ namespace LHCb::Calo {
           setProperty( prop->getProperty( "PositionTags" ) ).orThrow( "oops", "oops" );
       }
     }
-
     // apply local default setting if not defined by parent
     if ( m_taggerE.empty() ) m_taggerE = std::vector<std::string>( 1, "useDB" );
     if ( m_taggerP.empty() ) m_taggerP = std::vector<std::string>( 1, "useDB" );
-
-    if ( msgLevel( MSG::DEBUG ) ) {
-      debug() << "SubClusterSelectorTool::SubClusterSelectorTool:" << endmsg;
-      debug() << m_taggerE << endmsg;
-      debug() << m_taggerP << endmsg;
-    }
   }
 
   StatusCode SubClusterSelectorTool::initialize() {
-    return ConditionAccessorHolder::initialize()
-        .andThen( [&] { return m_dbAccessor->setProperty( "ConditionName", m_condition ); } )
-        .andThen( [&] {
-          // depends on m_conditio so that calls to m_dbAccessor give proper results
-          addConditionDerivation( {m_condition}, m_tags.key(), [&]( Condition const& ) { return getParams(); } );
-          return StatusCode::SUCCESS;
-        } );
+    return ConditionAccessorHolder::initialize().andThen( [&] {
+      // depends on m_condition so that calls to m_dbAccessor give proper results
+      addConditionDerivation( {m_condition}, m_tags.key(), [&]( Condition const& ) { return getParams(); } );
+      return StatusCode::SUCCESS;
+    } );
   }
 
   SubClusterSelectorTool::Tags SubClusterSelectorTool::getParams() {
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
index 5b113cb9874..abe6c73a83b 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
@@ -85,7 +85,7 @@ namespace LHCb::Calo {
     Gaudi::Property<std::vector<std::string>> m_taggerE{this, "EnergyTags", {}};
     Gaudi::Property<std::vector<std::string>> m_taggerP{this, "PositionTags", {}};
     using Tags = std::array<std::vector<Interfaces::ISubClusterTag*>, 2>; // 0 -> Energy, 1 -> Position
-    ConditionAccessor<Tags> m_tags{this, name() + "/SubClusterSelectorToolTags"};
+    ConditionAccessor<Tags> m_tags{this, name() + "-SubClusterSelectorToolTags"};
 
     Tags getParams();
 
@@ -103,9 +103,7 @@ namespace LHCb::Calo {
         "associate known cluster mask to tagger tool"};
 
     Gaudi::Property<std::string> m_condition{this, "ConditionName", ""};
-
-    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase",
-                                                      "CaloFutureCorrectionBase/DBAccessor"};
+    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
     LHCb::CaloDigitStatus::Status        m_energyStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForEnergy, LHCb::CaloDigitStatus::Mask::UseForCovariance};
     LHCb::CaloDigitStatus::Status m_positionStatus = LHCb::CaloDigitStatus::Status{
diff --git a/Phys/JetAccessories/python/JetAccessories/HltJetConf.py b/Phys/JetAccessories/python/JetAccessories/HltJetConf.py
index 9e3566614ef..33c6d176fd2 100644
--- a/Phys/JetAccessories/python/JetAccessories/HltJetConf.py
+++ b/Phys/JetAccessories/python/JetAccessories/HltJetConf.py
@@ -119,6 +119,14 @@ class HltParticleFlowConf(object):
         clustCov.CovarianceParameters["Stochastic"] = [0.7]
         clustCov.CovarianceParameters["GainError"] = [0.1]
         clustCov.OutputData = 'Rec/Calo/HcalClustersCov'
+        clustCov.CovarianceTool = 'FutureClusterCovarianceMatrixTool/HcalCovarTool'
+        clustCov.CovarianceTool.ConditionName = 'Conditions/Reco/Calo/HcalCovariance'
+        clustCov.CovarianceTool.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+        clustCov.CovarianceTool.CorrectionBase.ConditionName = clustCov.CovarianceTool.ConditionName
+        clustCov.TaggerTool = 'FutureSubClusterSelectorTool/HcalClusterTag'
+        clustCov.TaggerTool.ConditionName = 'Conditions/Reco/Calo/HcalClusterMasks'
+        clustCov.TaggerTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+        clustCov.TaggerTool.CaloFutureCorrectionBase.ConditionName = clustCov.TaggerTool.ConditionName
         self.seq.Members += [clustCov]
         return clustCov.OutputData.toStringProperty()
 
diff --git a/Phys/JetAccessories/python/JetAccessories/ParticleFlow_Config.py b/Phys/JetAccessories/python/JetAccessories/ParticleFlow_Config.py
index 08b04f67eda..2e4c56819bb 100644
--- a/Phys/JetAccessories/python/JetAccessories/ParticleFlow_Config.py
+++ b/Phys/JetAccessories/python/JetAccessories/ParticleFlow_Config.py
@@ -268,6 +268,14 @@ class ParticleFlowConf(object):
         clustCov.EnergyTags = ['2x2']
         clustCov.CovarianceParameters["Stochastic"] = [0.7]
         clustCov.CovarianceParameters["GainError"] = [0.1]
+        clustCov.CovarianceTool = 'FutureClusterCovarianceMatrixTool/HcalCovarTool'
+        clustCov.CovarianceTool.ConditionName = 'Conditions/Reco/Calo/HcalCovariance'
+        clustCov.CovarianceTool.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+        clustCov.CovarianceTool.CorrectionBase.ConditionName = clustCov.CovarianceTool.ConditionName
+        clustCov.TaggerTool = 'FutureSubClusterSelectorTool/HcalClusterTag'
+        clustCov.TaggerTool.ConditionName = 'Conditions/Reco/Calo/HcalClusterMasks'
+        clustCov.TaggerTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
+        clustCov.TaggerTool.CaloFutureCorrectionBase.ConditionName = clustCov.TaggerTool.ConditionName
         self.PFSeq.Members += [clustCov]
 
         ## Get Association to tracks
-- 
GitLab


From 6cc28b5e907fdadfaff30adb48f164b18299676a Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Thu, 29 Sep 2022 16:10:20 +0200
Subject: [PATCH 07/26] Put non stupid defaults for derived conditions' paths
 so that the functor cache is happy...

---
 CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h     | 2 +-
 .../CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h   | 2 +-
 CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h | 5 +++--
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 5134218b163..5cc417fa89b 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -184,7 +184,7 @@ protected:
                                                    "acceptable hypotheses"};
 
 private:
-  Gaudi::Property<std::string>              m_conditionName{this, "ConditionName", "none"};
+  Gaudi::Property<std::string> m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
   Gaudi::Property<std::vector<std::string>> m_corrections{this, "Corrections", {"All"}};
 
   std::optional<CaloFutureCorrection::Type> accept( const std::string& name ) const {
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index 9897fb3a54e..4c7809498c7 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -458,7 +458,7 @@ namespace LHCb::Calo {
     CovarianceMatrixTool::detail::ParameterMap getParams();
 
     ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "-Parameters"};
-    Gaudi::Property<std::string>                                  m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
+    Gaudi::Property<std::string>         m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
     ToolHandle<CaloFutureCorrectionBase> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
 
     mutable Gaudi::Accumulators::Counter<>              m_parUpdate{this, "parameter updated"};
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
index abe6c73a83b..f94aa1aafe1 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
@@ -102,8 +102,9 @@ namespace LHCb::Calo {
         },
         "associate known cluster mask to tagger tool"};
 
-    Gaudi::Property<std::string> m_condition{this, "ConditionName", ""};
-    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
+    Gaudi::Property<std::string>         m_condition{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
+    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase",
+                                                      "CaloFutureCorrectionBase/DBAccessor"};
     LHCb::CaloDigitStatus::Status        m_energyStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForEnergy, LHCb::CaloDigitStatus::Mask::UseForCovariance};
     LHCb::CaloDigitStatus::Status m_positionStatus = LHCb::CaloDigitStatus::Status{
-- 
GitLab


From 93e98b83fcf02dd22d824487c79a31bb996e6e5d Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 09:48:21 +0200
Subject: [PATCH 08/26] Converted CaloFutureCorrectionBase to use of yaml for
 conditions

---
 .../src/CaloFutureCorrectionBase.cpp          | 33 +++++++++----------
 .../src/CaloFutureCorrectionBase.h            |  1 -
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index 8e870af61e6..5dbec9d5b6f 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -11,6 +11,8 @@
 #include "CaloFutureCorrectionBase.h"
 #include "Event/ProtoParticle.h"
 
+#include <yaml-cpp/yaml.h>
+
 using namespace LHCb::Math::Approx;
 
 namespace Gaudi::Parsers {
@@ -160,8 +162,20 @@ CaloFutureCorrectionBase::CaloFutureCorrectionBase( const std::string& type, con
 StatusCode CaloFutureCorrectionBase::initialize() {
   return ConditionAccessorHolder::initialize().andThen( [&]() -> StatusCode {
     if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
-    addConditionDerivation( {m_conditionName}, m_params.key(),
-                            [&]( Condition const& cond ) { return updParams( cond ); } );
+    addConditionDerivation( {m_conditionName}, m_params.key(), [&]( YAML::Node const& cond ) {
+      Parameters params;
+      for ( auto it = cond.begin(); it != cond.end(); it++ ) {
+        auto type = accept( it->first.as<std::string>() );
+        if ( !type ) continue;
+        const auto& parVec = it->second.as<std::vector<double>>();
+        if ( parVec.size() < 2 ) {
+          error() << " # of parameters is insufficient!!" << endmsg;
+          continue;
+        }
+        constructParams( params[*type], parVec );
+      }
+      return params;
+    } );
     return StatusCode::SUCCESS;
   } );
 }
@@ -175,21 +189,6 @@ StatusCode CaloFutureCorrectionBase::finalize() {
   return ConditionAccessorHolder::finalize(); // must be called after all other actions
 }
 
-CaloFutureCorrectionBase::Parameters CaloFutureCorrectionBase::updParams( Condition const& cond ) {
-  Parameters params;
-  for ( const auto& paramName : cond.paramNames() ) {
-    auto type = accept( paramName );
-    if ( !type || !cond.exists( paramName ) ) continue;
-    const auto& parVec = cond.param<std::vector<double>>( paramName );
-    if ( parVec.size() < 2 ) {
-      error() << " # of parameters is insufficient!!" << endmsg;
-      continue;
-    }
-    constructParams( params[*type], parVec );
-  }
-  return params;
-}
-
 void CaloFutureCorrectionBase::constructParams( Functions& fun, LHCb::span<const double> params ) {
   // NOTE: conversion from double (params) to float (ParamVector)
   const auto func = static_cast<CaloFutureCorrection::Function>( std::lround( params[0] ) );
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 5cc417fa89b..8d5f597636e 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -275,5 +275,4 @@ private:
   using Parameters = std::array<Functions, CaloFutureCorrection::lastType + 1>;
   void                          constructParams( Functions&, const LHCb::span<const double> );
   ConditionAccessor<Parameters> m_params{this, name() + "-CaloFutureCorrectionBaseParameters"};
-  Parameters                    updParams( Condition const& );
 };
-- 
GitLab


From ef80c6137d72cb8b464d8d669670cd302bbee64e Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 09:52:46 +0200
Subject: [PATCH 09/26] Converted FutureClusterCovarianceMatrixTool to use of
 yaml for conditions

---
 .../CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp | 5 +++--
 .../CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h   | 3 +--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
index b6a2826e965..383b67664dd 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
@@ -11,6 +11,8 @@
 
 #include "FutureClusterCovarianceMatrixTool.h"
 
+#include <yaml-cpp/yaml.h>
+
 /** @file
  *
  *  Implementation file for class FutureClusterCovarianceMatrixTool
@@ -39,7 +41,6 @@ namespace LHCb::Calo {
         parameters[index].push_back( params[index] );
       }
     }
-    ++m_parUpdate;
     // info
     info() << " \t ==  Parameters for covariance estimation ==" << endmsg;
     for ( auto index : LHCb::Calo::CovarianceMatrixTool::detail::Parameters{} ) {
@@ -52,7 +53,7 @@ namespace LHCb::Calo {
   StatusCode ClusterCovarianceMatrixTool::initialize() {
     return ConditionAccessorHolder::initialize().andThen( [&] {
       // depends on m_conditionName so that calls to m_dbAccessor give proper results
-      addConditionDerivation( {m_conditionName}, m_parameters.key(), [&]( Condition const& ) { return getParams(); } );
+      addConditionDerivation( {m_conditionName}, m_parameters.key(), [&]( YAML::Node const& ) { return getParams(); } );
       return StatusCode::SUCCESS;
     } );
   }
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index 4c7809498c7..fb3c6277dca 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -457,11 +457,10 @@ namespace LHCb::Calo {
   private:
     CovarianceMatrixTool::detail::ParameterMap getParams();
 
-    ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "-Parameters"};
+    ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "_Parameters"};
     Gaudi::Property<std::string>         m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
     ToolHandle<CaloFutureCorrectionBase> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
 
-    mutable Gaudi::Accumulators::Counter<>              m_parUpdate{this, "parameter updated"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_negative_energy{this, "negative energy cluster"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_parExceeded{
         this, "Parameters vector exceeds the number of known parameters"};
-- 
GitLab


From e2e4c56bc58c04b89374ab9aa66bf9ac1ea0d82b Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 11:19:24 +0200
Subject: [PATCH 10/26] Converted FutureSubClusterSelectorTool to use of yaml
 for conditions

---
 .../CaloFutureReco/src/FutureSubClusterSelectorTool.cpp      | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
index 694c67695d7..1e12d9b8bd5 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
@@ -9,8 +9,11 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "FutureSubClusterSelectorTool.h"
+
 #include "fmt/format.h"
 
+#include <yaml-cpp/yaml.h>
+
 //-----------------------------------------------------------------------------
 // Implementation file for class : FutureSubClusterSelectorTool
 //
@@ -41,7 +44,7 @@ namespace LHCb::Calo {
   StatusCode SubClusterSelectorTool::initialize() {
     return ConditionAccessorHolder::initialize().andThen( [&] {
       // depends on m_condition so that calls to m_dbAccessor give proper results
-      addConditionDerivation( {m_condition}, m_tags.key(), [&]( Condition const& ) { return getParams(); } );
+      addConditionDerivation( {m_condition}, m_tags.key(), [&]( YAML::Node const& ) { return getParams(); } );
       return StatusCode::SUCCESS;
     } );
   }
-- 
GitLab


From 848c18fa02362a2ae5f0b7e47e19de13f149c902 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 11:19:48 +0200
Subject: [PATCH 11/26] Converted PVOfflineTool to use derived conditions and
 yaml for conditions

---
 Tr/PatPV/src/PVOfflineTool.cpp | 106 +++++++++++----------------------
 1 file changed, 34 insertions(+), 72 deletions(-)

diff --git a/Tr/PatPV/src/PVOfflineTool.cpp b/Tr/PatPV/src/PVOfflineTool.cpp
index 00150acfdab..ae87744fa81 100644
--- a/Tr/PatPV/src/PVOfflineTool.cpp
+++ b/Tr/PatPV/src/PVOfflineTool.cpp
@@ -8,26 +8,31 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "DetDesc/Condition.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "Event/RecVertex.h"
 #include "Event/State.h"
 #include "Event/Track.h"
-#include "GaudiAlg/GaudiTool.h"
-#include "GaudiAlg/ISequencerTimerTool.h"
-#include "GaudiKernel/IUpdateManagerSvc.h"
-#include "GaudiKernel/SystemOfUnits.h"
 #include "IPVFitter.h"
 #include "IPVSeeding.h"
 #include "Kernel/STLExtensions.h"
 #include "PVOfflineRecalculate.h"
 #include "TrackInterfaces/IPVOfflineTool.h"
+#include "VPDet/DeVP.h"
+
+#include "GaudiAlg/GaudiTool.h"
+#include "GaudiAlg/ISequencerTimerTool.h"
+#include "GaudiKernel/IUpdateManagerSvc.h"
+#include "GaudiKernel/SystemOfUnits.h"
+
 #include <functional>
 #include <numeric>
 #include <optional>
 #include <string>
 #include <vector>
 
-class PVOfflineTool : public extends<GaudiTool, IPVOfflineTool> {
+#include <yaml-cpp/yaml.h>
+
+class PVOfflineTool : public extends<LHCb::DetDesc::ConditionAccessorHolder<GaudiTool>, IPVOfflineTool> {
 public:
   // Standard constructor
   using extends::extends;
@@ -77,10 +82,8 @@ private:
   Gaudi::Property<double>       m_beamSpotRCut{this, "BeamSpotRCut", 0.2};
   Gaudi::Property<double>       m_beamSpotRCutHMC{this, "BeamSpotRHighMultiplicityCut", 0.4};
   Gaudi::Property<unsigned int> m_beamSpotRMT{this, "BeamSpotRMultiplicityTreshold", 10};
-  double                        m_beamSpotX = 0;
-  double                        m_beamSpotY = 0;
-  Gaudi::Property<double>       m_resolverBound{this, "ResolverBound", 5 * Gaudi::Units::mm};
-  bool                          m_veloClosed = false;
+
+  ConditionAccessor<DeVP> m_vp{this, "DeVP", LHCb::Det::VP::det_path};
 
   // Member functions
   LHCb::RecVertex* matchVtxByTracks( const LHCb::RecVertex& invtx, std::vector<LHCb::RecVertex>& outvtxvec ) const;
@@ -92,8 +95,6 @@ private:
 
   void removeTracksUsedByVertex( std::vector<const LHCb::Track*>& tracks, LHCb::RecVertex& rvtx ) const;
 
-  StatusCode UpdateBeamSpot();
-
   // timing
   Gaudi::Property<bool>           m_doTiming{this, "TimingMeasurement", false};
   ToolHandle<ISequencerTimerTool> m_timerTool{"SequencerTimerTool/Timer", this};
@@ -125,8 +126,6 @@ DECLARE_COMPONENT( PVOfflineTool )
 
 namespace {
 
-  static const std::string s_beamSpotCond = "/dd/Conditions/Online/Velo/MotionSystem";
-
   template <typename Iterator, typename Projection, typename Threshold>
   std::pair<Iterator, Threshold> max_above_threshold( Iterator begin, Iterator end, Projection proj, Threshold mx ) {
     auto r = std::make_pair( end, std::move( mx ) );
@@ -233,28 +232,19 @@ namespace {
 // Initialize
 //=========================================================================
 StatusCode PVOfflineTool::initialize() {
-  StatusCode sc = extends::initialize();
-  if ( !sc ) return sc;
-
-  if ( m_useBeamSpotRCut.value() ) {
-    IUpdateManagerSvc* m_updMgrSvc = svc<IUpdateManagerSvc>( "UpdateManagerSvc", true );
-    m_updMgrSvc->registerCondition( this, s_beamSpotCond, &PVOfflineTool::UpdateBeamSpot );
-    StatusCode scu = m_updMgrSvc->update( this );
-    if ( !scu.isSuccess() ) return Error( "Failed to update conditions!", scu );
-  }
-
-  if ( m_doTiming ) {
-    m_timerTool.retrieve().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
-    m_timer[static_cast<int>( timers_t::Total )] = m_timerTool->addTimer( "PatPV total" );
-    m_timerTool->increaseIndent();
-    m_timer[static_cast<int>( timers_t::Seeding )] = m_timerTool->addTimer( "PatPV seeding" );
-    m_timer[static_cast<int>( timers_t::Fitting )] = m_timerTool->addTimer( "PatPV fitting" );
-    m_timerTool->decreaseIndent();
-  } else {
-    m_timerTool.disable();
-  }
-
-  return StatusCode::SUCCESS;
+  return extends::initialize().andThen( [&] {
+    if ( m_doTiming ) {
+      m_timerTool.retrieve().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
+      m_timer[static_cast<int>( timers_t::Total )] = m_timerTool->addTimer( "PatPV total" );
+      m_timerTool->increaseIndent();
+      m_timer[static_cast<int>( timers_t::Seeding )] = m_timerTool->addTimer( "PatPV seeding" );
+      m_timer[static_cast<int>( timers_t::Fitting )] = m_timerTool->addTimer( "PatPV fitting" );
+      m_timerTool->decreaseIndent();
+    } else {
+      m_timerTool.disable();
+    }
+    return StatusCode::SUCCESS;
+  } );
 }
 
 //=============================================================================
@@ -343,12 +333,13 @@ namespace {
 StatusCode PVOfflineTool::reconstructMultiPVFromTracks( std::vector<const LHCb::Track*>& rtracks,
                                                         std::vector<LHCb::RecVertex>&    outvtxvec,
                                                         IGeometryInfo const&             geometry ) const {
-  auto totaltime_guard = make_timeguard( timers_t::Total );
-
+  auto            totaltime_guard = make_timeguard( timers_t::Total );
+  DeVP const&     deVP            = m_vp.get();
+  Gaudi::XYZPoint beamSpot        = deVP.beamSpot();
   outvtxvec.clear();
 
   if ( m_saveSeedsAsPV ) {
-    auto seeds = m_pvSeedTool->getSeeds( rtracks, {m_beamSpotX, m_beamSpotY, 0.0}, geometry );
+    auto seeds = m_pvSeedTool->getSeeds( rtracks, beamSpot, geometry );
     outvtxvec  = storeDummyVertices( seeds, rtracks );
     return StatusCode::SUCCESS;
   }
@@ -359,7 +350,7 @@ StatusCode PVOfflineTool::reconstructMultiPVFromTracks( std::vector<const LHCb::
     auto seeds = [&]() {
       auto seedingtime_guard = make_timeguard( timers_t::Seeding );
       // seeding
-      return m_pvSeedTool->getSeeds( rtracks, {m_beamSpotX, m_beamSpotY, 0.0}, geometry );
+      return m_pvSeedTool->getSeeds( rtracks, beamSpot, geometry );
     }();
 
     if ( msgLevel( MSG::DEBUG ) ) { debug() << " seeds  " << seeds.size() << " pos: " << seeds << endmsg; }
@@ -383,9 +374,9 @@ StatusCode PVOfflineTool::reconstructMultiPVFromTracks( std::vector<const LHCb::
         outvtxvec.pop_back();
         continue;
       }
-      if ( m_useBeamSpotRCut.value() && m_veloClosed ) {
+      if ( m_useBeamSpotRCut.value() && deVP.veloClosed() ) {
         const auto& pos = recvtx.position();
-        auto        r2  = std::pow( pos.x() - m_beamSpotX, 2 ) + std::pow( pos.y() - m_beamSpotY, 2 );
+        auto        r2  = std::pow( pos.x() - beamSpot.x(), 2 ) + std::pow( pos.y() - beamSpot.y(), 2 );
         auto        r =
             ( recvtx.tracks().size() < m_beamSpotRMT.value() ? m_beamSpotRCut.value() : m_beamSpotRCutHMC.value() );
         if ( r2 > r * r ) {
@@ -442,14 +433,8 @@ void PVOfflineTool::removeTracksByLHCbIDs( std::vector<const LHCb::Track*>& trac
 //=============================================================================
 // removeTracksUsedByVertex
 //=============================================================================
-void PVOfflineTool::removeTracksUsedByVertex( std::vector<const LHCb::Track*>& tracks, LHCb::RecVertex& rvtx ) const
-
-{
-  if ( msgLevel( MSG::VERBOSE ) ) { verbose() << " removeTracksUsedByVertex method" << endmsg; }
-
+void PVOfflineTool::removeTracksUsedByVertex( std::vector<const LHCb::Track*>& tracks, LHCb::RecVertex& rvtx ) const {
   removeTracks( tracks, rvtx.tracks() );
-
-  if ( msgLevel( MSG::VERBOSE ) ) { verbose() << " leaving removeTracksUsedByVertex method" << endmsg; }
 }
 
 //=============================================================================
@@ -479,26 +464,3 @@ StatusCode PVOfflineTool::removeTracksAndRecalculatePV( const LHCb::RecVertex*
                                                         LHCb::RecVertex& vtx, IGeometryInfo const& geometry ) const {
   return m_pvRecalc->RecalculateVertex( pvin, tracks2remove, vtx, geometry );
 }
-
-//=============================================================================
-// Update of the beam spot position
-//=============================================================================
-StatusCode PVOfflineTool::UpdateBeamSpot() {
-  if ( !exist<Condition>( detSvc(), s_beamSpotCond ) ) {
-    Warning( "Unable to locate beam spot condition" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
-    return StatusCode::FAILURE;
-  }
-  Condition* myCond = get<Condition>( detSvc(), s_beamSpotCond );
-  //
-  const double xRC = myCond->paramAsDouble( "ResolPosRC" );
-  const double xLA = myCond->paramAsDouble( "ResolPosLA" );
-  const double Y   = myCond->paramAsDouble( "ResolPosY" );
-  //
-  m_beamSpotX = ( xRC + xLA ) / 2;
-  m_beamSpotY = Y;
-
-  m_veloClosed = ( std::abs( xRC - m_beamSpotX ) < m_resolverBound.value() &&
-                   std::abs( xLA - m_beamSpotX ) < m_resolverBound.value() );
-
-  return StatusCode::SUCCESS;
-}
-- 
GitLab


From aa72124dc9b96345cc1dac853497ca1e6b8c0326 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 12:07:30 +0200
Subject: [PATCH 12/26] Converted TrackParametrizedExtrapolator to use derived
 conditions

---
 Tr/TrackExtrapolators/src/BasisFunctions.h    |   5 +-
 .../src/TrackParametrizedExtrapolator.cpp     | 187 +++++++-----------
 2 files changed, 72 insertions(+), 120 deletions(-)

diff --git a/Tr/TrackExtrapolators/src/BasisFunctions.h b/Tr/TrackExtrapolators/src/BasisFunctions.h
index 59d198d9b08..9ea106122a0 100644
--- a/Tr/TrackExtrapolators/src/BasisFunctions.h
+++ b/Tr/TrackExtrapolators/src/BasisFunctions.h
@@ -1,5 +1,4 @@
-#ifndef __TRACKEXTRAPOLATORS_BASISFUNCTIONS__
-#define __TRACKEXTRAPOLATORS_BASISFUNCTIONS__
+#pragma once
 
 /*****************************************************************************\
 * (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
@@ -146,5 +145,3 @@ namespace BasisFunctions {
     auto evaluateDerivative( const Arguments& x ) const { return evaluateDerivative( x( 0, 0 ) ); }
   };
 } // namespace BasisFunctions
-
-#endif
diff --git a/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp b/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
index c4260f0856f..6acd18c6f6c 100644
--- a/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
+++ b/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
@@ -9,40 +9,33 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "BasisFunctions.h"
-#include <Eigen/Dense>
+#include "TrackExtrapolator.h"
 
-// Include files
-// -------------
-// from TrackExtrapolators
-#include "DetDesc/IDetectorElement.h"
+#include "DetDesc/DetectorElement.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "DetDesc/ValidDataObject.h"
 #include "Event/StateParameters.h"
 #include "Event/TrackParameters.h"
 #include "GaudiKernel/IUpdateManagerSvc.h"
 #include "Kernel/ILHCbMagnetSvc.h"
-#include "TrackExtrapolator.h"
+
+#include <Eigen/Dense>
 
 namespace {
 
   using namespace BasisFunctions;
 
-  class Plane {
-  public:
-    Plane() : m_z( 0 ), m_xmin( 0 ), m_xmax( 0 ), m_ymin( 0 ), m_ymax( 0 ) {}
+  struct Plane {
+    Plane() = default;
     Plane( double z, double x1, double x2, double y1, double y2 )
-        : m_z( z ), m_xmin( x1 ), m_xmax( x2 ), m_ymin( y1 ), m_ymax( y2 ) {}
+        : z( z ), xmin( x1 ), xmax( x2 ), ymin( y1 ), ymax( y2 ) {}
     Plane( double z, double txmax, double tymax )
-        : m_z( z ), m_xmin( -z * txmax ), m_xmax( z * txmax ), m_ymin( -z * tymax ), m_ymax( z * tymax ) {}
-    double z() const { return m_z; }
-    double xmin() const { return m_xmin; }
-    double xmax() const { return m_xmax; }
-    double ymin() const { return m_ymin; }
-    double ymax() const { return m_ymax; }
-    double m_z;
-    double m_xmin;
-    double m_xmax;
-    double m_ymin;
-    double m_ymax;
+        : z( z ), xmin( -z * txmax ), xmax( z * txmax ), ymin( -z * tymax ), ymax( z * tymax ) {}
+    double z{0};
+    double xmin{0};
+    double xmax{0};
+    double ymin{0};
+    double ymax{0};
   };
 
   template <class FunctionBasisT>
@@ -113,7 +106,6 @@ namespace {
   public:
     // enum{ OrderX = 0, OrderY = 0, OrderTx = 2, OrderTy = 2, OrderQoP= 4 } ;
     enum : std::size_t { OrderX = 0, OrderY = 0, OrderTx = 2, OrderTy = 2, OrderQoP = 4 };
-    // typedef ChebychevPolynomial1D Poly1D ;
     template <size_t N>
     using Poly1D = Polynomial1D<N>;
     typedef BasicFunctionProduct<
@@ -121,12 +113,10 @@ namespace {
         BasicFunctionProduct<
             Poly1D<OrderY>,
             BasicFunctionProduct<Poly1D<OrderTx>, BasicFunctionProduct<Poly1D<OrderTy>, Poly1D<OrderQoP>>>>>
-        FunctionBasis;
-
+                                                     FunctionBasis;
     typedef PropagatorParametrization<FunctionBasis> Propagator;
 
   private:
-    //
     Plane m_plane1;
     Plane m_plane2;
     // the number of bins in x and y. these will become template parameters?
@@ -140,23 +130,23 @@ namespace {
     const Plane& plane1() const { return m_plane1; }
     const Plane& plane2() const { return m_plane2; }
     auto&        propagators() { return m_propagators; }
-    double       dz() const { return m_plane2.z() - m_plane1.z(); }
+    double       dz() const { return m_plane2.z - m_plane1.z; }
 
     InterPlaneParametrization( const Plane& p1, const Plane& p2 )
         : m_plane1{p1}
         , m_plane2{p2}
         , m_numbinsX{50}
         , m_numbinsY{50}
-        , m_propagators( m_numbinsX * m_numbinsY, Propagator( p2.z() - p1.z() ) ) {
+        , m_propagators( m_numbinsX * m_numbinsY, Propagator( p2.z - p1.z ) ) {
       // do some work for every bin
-      const double dx = ( m_plane1.xmax() - m_plane1.xmin() ) / ( m_numbinsX );
-      const double dy = ( m_plane1.ymax() - m_plane1.ymin() ) / ( m_numbinsY );
+      const double dx = ( m_plane1.xmax - m_plane1.xmin ) / ( m_numbinsX );
+      const double dy = ( m_plane1.ymax - m_plane1.ymin ) / ( m_numbinsY );
 
       for ( size_t xbin = 0; xbin < m_numbinsX; ++xbin )
         for ( size_t ybin = 0; ybin < m_numbinsY; ++ybin ) {
-          const double xmin     = m_plane1.xmin() + dx * xbin;
+          const double xmin     = m_plane1.xmin + dx * xbin;
           const double xmax     = xmin + dx;
-          const double ymin     = m_plane1.ymin() + dy * ybin;
+          const double ymin     = m_plane1.ymin + dy * ybin;
           const double ymax     = ymin + dy;
           const size_t thexybin = xbin + m_numbinsX * ybin;
           // offsets are set such that the mean of the argument becomes about zero
@@ -166,7 +156,7 @@ namespace {
           offset[1]    = 0.5 * ( ymax + ymin );
           // these are substantially more tricky. this only works far
           // away from the ip and only when propagating to larger z.
-          const double z = m_plane1.z();
+          const double z = m_plane1.z;
           offset[2]      = z > 0 ? offset[0] / z : 0;
           offset[3]      = z > 0 ? offset[1] / z : 0;
           offset[4]      = 0;
@@ -180,8 +170,8 @@ namespace {
     }
 
     size_t xybin( const double x, const double y ) const {
-      size_t xbin = ( x - m_plane1.xmin() ) / ( m_plane1.xmax() - m_plane1.xmin() ) * m_numbinsX;
-      size_t ybin = ( y - m_plane1.ymin() ) / ( m_plane1.ymax() - m_plane1.ymin() ) * m_numbinsY;
+      size_t xbin = ( x - m_plane1.xmin ) / ( m_plane1.xmax - m_plane1.xmin ) * m_numbinsX;
+      size_t ybin = ( y - m_plane1.ymin ) / ( m_plane1.ymax - m_plane1.ymin ) * m_numbinsY;
       xbin        = ( xbin >= m_numbinsX ? m_numbinsX - 1 : xbin );
       ybin        = ( ybin >= m_numbinsY ? m_numbinsY - 1 : ybin );
       return xbin + m_numbinsX * ybin;
@@ -207,12 +197,7 @@ namespace {
     Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>   m_second;
 
   public:
-    PropagatorAccumulator( PropagatorParametrization& client )
-        : m_client{&client}
-        , m_numentries( 0 )
-    //, m_second{ Eigen::Matrix<double,Dim,Dim>::Zero() }
-    {
-      // m_second = new Eigen::Matrix<double,Dim,Dim>() ;
+    PropagatorAccumulator( PropagatorParametrization& client ) : m_client{&client}, m_numentries( 0 ) {
       m_second = Eigen::Matrix<double, Dim, Dim>::Zero();
       m_first.fill( Eigen::Matrix<double, Dim, 1>::Zero() );
     }
@@ -249,26 +234,20 @@ namespace {
   };
 } // namespace
 
-/** @class TrackParametrizedExtrapolator TrackParametrizedExtrapolator.h
- * TrackExtrapolators/TrackParametrizedExtrapolator.h
- *
+/**
  *  A TrackParametrizedExtrapolator is a TrackExtrapolator with access to the magnetic field
  *
  *  @author Wouter Hulsbergen
  *  @date   16/09/2016
  */
-
-class TrackParametrizedExtrapolator : public TrackExtrapolator {
+class TrackParametrizedExtrapolator : public LHCb::DetDesc::ConditionAccessorHolder<TrackExtrapolator> {
 
 public:
   typedef Gaudi::XYZVector FieldVector;
   typedef Gaudi::Matrix3x3 FieldGradient;
-  /// constructor
-  TrackParametrizedExtrapolator( const std::string& type, const std::string& name, const IInterface* parent );
 
-  /// initialize (picks up the field service)
+  using ConditionAccessorHolder::ConditionAccessorHolder;
   StatusCode initialize() override;
-
   using TrackExtrapolator::propagate;
 
   /// the one function that we need to implement
@@ -279,75 +258,58 @@ public:
                         const LHCb::Magnet::MagneticFieldGrid* grid = nullptr ) const override;
 
 private:
-  /// Update the parameters used in the parametrization
-  StatusCode computeParameters();
-
-private:
-  const ToolHandle<ITrackExtrapolator> m_refextrapolator;
+  const ToolHandle<ITrackExtrapolator> m_refextrapolator{this, "RefExtrapolator", "TrackRungeKuttaExtrapolator"};
 
   Gaudi::Property<std::string> m_standardGeometry_address{this, "StandardGeometryTop", LHCb::standard_geometry_top};
 
-  std::vector<InterPlaneParametrization> m_forwardpars;
-  std::vector<InterPlaneParametrization> m_backwardpars;
+  struct Parameters {
+    std::vector<InterPlaneParametrization> forwardpars;
+    std::vector<InterPlaneParametrization> backwardpars;
+  };
+  ConditionAccessor<Parameters> m_parameters{this, name() + "-Parameters"};
+  Parameters                    computeParameters( LHCb::Detector::DeLHCb const&, ITrackExtrapolator const& );
 };
 
 DECLARE_COMPONENT( TrackParametrizedExtrapolator )
 
-// Include files
-// -------------
-// from Gaudi
-
-//=============================================================================
-// TrackParametrizedExtrapolator constructor.
-//=============================================================================
-TrackParametrizedExtrapolator::TrackParametrizedExtrapolator( const std::string& type, const std::string& name,
-                                                              const IInterface* parent )
-    : TrackExtrapolator( type, name, parent ), m_refextrapolator( "TrackRungeKuttaExtrapolator" ) {
-  // declareProperty("RefExtrapolator",m_refextrapolator) ;
+StatusCode TrackParametrizedExtrapolator::initialize() {
+  return ConditionAccessorHolder::initialize().andThen( [&] {
+    addConditionDerivation(
+        {m_standardGeometry_address}, m_parameters.key(),
+        [&]( LHCb::Detector::DeLHCb const& lhcb ) { return computeParameters( lhcb, *m_refextrapolator ); } );
+    return StatusCode::SUCCESS;
+  } );
 }
 
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode TrackParametrizedExtrapolator::initialize() {
-  StatusCode sc = TrackExtrapolator::initialize();
-  if ( sc.isFailure() ) return sc;
+TrackParametrizedExtrapolator::Parameters
+TrackParametrizedExtrapolator::computeParameters( LHCb::Detector::DeLHCb const& lhcb,
+                                                  ITrackExtrapolator const&     refextrapolator ) {
+  // do we do upstream and downstream simultaneously?
+  // do we start every trajectory from about the origin?
+  // do we do all bins simultaneously?
+  std::vector<InterPlaneParametrization> forwardpars;
+  std::vector<InterPlaneParametrization> backwardpars;
+  forwardpars.reserve( 3 );
+  backwardpars.reserve( 3 );
 
-  // lets's create two planes
+  // lets's create a few planes
   const double txmax = 0.3;
   const double tymax = 0.25;
   Plane        endvelo{StateParameters::ZEndVelo, txmax, tymax};
   Plane        beginTT{2200., txmax, tymax}; // need to add ZBegTT to StateParemeters
   Plane        endTT{StateParameters::ZEndTT, txmax, tymax};
   Plane        beginT{StateParameters::ZBegT, txmax, tymax};
-  m_forwardpars.push_back( InterPlaneParametrization( endvelo, beginTT ) ); // 770 to 2200
-  m_forwardpars.push_back( InterPlaneParametrization( endvelo, beginT ) );  // 770 to 7500
-  m_forwardpars.push_back( InterPlaneParametrization( endTT, beginT ) );    // 2700 to 7500
-  for ( const auto& p : m_forwardpars ) m_backwardpars.push_back( InterPlaneParametrization( p.plane2(), p.plane1() ) );
-  // subscribe to the updatemanagersvc with a dependency on the magnetic field svc
-  ILHCbMagnetSvc* m_fieldSvc = svc<ILHCbMagnetSvc>( "MagneticFieldSvc", true );
-  updMgrSvc()->registerCondition( this, m_standardGeometry_address, &TrackParametrizedExtrapolator::computeParameters );
-  updMgrSvc()->registerCondition( this, m_fieldSvc, &TrackParametrizedExtrapolator::computeParameters );
-  sc = updMgrSvc()->update( this );
-
-  return sc;
-}
-
-StatusCode TrackParametrizedExtrapolator::computeParameters() {
-  // do we do upstream and downstream simultaneously?
-  // do we start every trajectory from about the origin?
-  // do we do all bins simultaneously?
-
-  // Get the defaulf geometry FIXME, use functional algo
-  auto lhcb = getDet<IDetectorElement>( m_standardGeometry_address );
-  if ( !lhcb ) { throw GaudiException( "Could not load geometry", name(), StatusCode::FAILURE ); }
+  forwardpars.push_back( InterPlaneParametrization( endvelo, beginTT ) ); // 770 to 2200
+  forwardpars.push_back( InterPlaneParametrization( endvelo, beginT ) );  // 770 to 7500
+  forwardpars.push_back( InterPlaneParametrization( endTT, beginT ) );    // 2700 to 7500
+  for ( const auto& p : forwardpars ) backwardpars.push_back( InterPlaneParametrization( p.plane2(), p.plane1() ) );
 
   info() << "Start training." << endmsg;
   chronoSvc()->chronoStart( "Training" );
   // easier if we have all of them in one container
   std::vector<InterPlaneParametrization*> planepars;
-  for ( auto& i : m_forwardpars ) planepars.push_back( &i );
-  for ( auto& i : m_backwardpars ) planepars.push_back( &i );
+  for ( auto& i : forwardpars ) planepars.push_back( &i );
+  for ( auto& i : backwardpars ) planepars.push_back( &i );
   for ( auto& i : planepars ) {
     auto&        par        = *i;
     const size_t npoints[5] = {par.OrderX + 1, par.OrderY + 1, par.OrderTx + 1, par.OrderTy + 1, par.OrderQoP + 1};
@@ -366,9 +328,6 @@ StatusCode TrackParametrizedExtrapolator::computeParameters() {
             grid[j].push_back( 0.5 * ( binprop.varmax( j ) + binprop.varmin( j ) ) );
           else {
             for ( size_t i = 0; i < npoints[j]; ++i ) {
-              // equal spacing
-              // grid[j].push_back(binprop.varmin(j) + i * (binprop.varmax(j)-binprop.varmin(j) ) /
-              //(npoints[j]-1) )  ;
               double xi = cos( M_PI * ( i + 0.5 ) / double( npoints[j] ) );
               grid[j].push_back( 0.5 * ( ( 1 - xi ) * binprop.varmin( j ) + ( 1 + xi ) * binprop.varmax( j ) ) );
             } // for loop closed
@@ -390,8 +349,7 @@ StatusCode TrackParametrizedExtrapolator::computeParameters() {
                   // const double qop = statein[4] ;
                   Gaudi::TrackVector stateout = statein;
                   if ( std::abs( qop ) > 1e-9 ) {
-                    sc =
-                        m_refextrapolator->propagate( stateout, par.plane1().z(), par.plane2().z(), *lhcb->geometry() );
+                    sc = refextrapolator.propagate( stateout, par.plane1().z, par.plane2().z, *lhcb.geometry() );
                     // FIX ME: do we only accept propagation that actually
                     // end up in the target plane?
                     if ( sc.isSuccess() ) {
@@ -411,8 +369,8 @@ StatusCode TrackParametrizedExtrapolator::computeParameters() {
                     // if qop==0, use the jacobian instead. this only
                     // works if step size is small enough.  FIXME
                     Gaudi::TrackMatrix jacobian;
-                    sc = m_refextrapolator->propagate( stateout, par.plane1().z(), par.plane2().z(), &jacobian,
-                                                       *lhcb->geometry() );
+                    sc = refextrapolator.propagate( stateout, par.plane1().z, par.plane2().z, &jacobian,
+                                                    *lhcb.geometry() );
                     if ( sc.isSuccess() ) {
                       std::array<double, 4> delta = {jacobian( 0, 4 ), jacobian( 1, 4 ), jacobian( 2, 4 ),
                                                      jacobian( 3, 4 )};
@@ -430,7 +388,7 @@ StatusCode TrackParametrizedExtrapolator::computeParameters() {
   chronoSvc()->chronoStop( "Training" );
   info() << "Ready training." << endmsg;
 
-  return StatusCode::SUCCESS;
+  return {forwardpars, backwardpars};
 }
 
 StatusCode TrackParametrizedExtrapolator::propagate( Gaudi::TrackVector& in, double z1, double z2,
@@ -440,14 +398,14 @@ StatusCode TrackParametrizedExtrapolator::propagate( Gaudi::TrackVector& in, dou
   // new approach: we take the interplane-extrapolator that has the
   // largest overlap in z. for now we only use it if it is fully
   // contained.
-  StatusCode                       sc        = StatusCode::SUCCESS;
-  int                              direction = z1 < z2 ? +1 : -1;
-  auto&                            container = direction == +1 ? m_forwardpars : m_backwardpars;
+  StatusCode sc        = StatusCode::SUCCESS;
+  int        direction = z1 < z2 ? +1 : -1;
+  auto&      container = direction == +1 ? m_parameters.get().forwardpars : m_parameters.get().backwardpars;
   const InterPlaneParametrization* thepar( 0 );
   for ( auto& par : container ) {
     // check that it is contained
-    if ( ( ( par.plane1().z() - z1 ) * direction + TrackParameters::propagationTolerance ) >= 0 &&
-         ( ( z2 - par.plane2().z() ) * direction + TrackParameters::propagationTolerance >= 0 ) ) {
+    if ( ( ( par.plane1().z - z1 ) * direction + TrackParameters::propagationTolerance ) >= 0 &&
+         ( ( z2 - par.plane2().z ) * direction + TrackParameters::propagationTolerance >= 0 ) ) {
       if ( thepar == 0 || std::abs( thepar->dz() ) < std::abs( par.dz() ) ) { thepar = &par; }
     }
   }
@@ -457,15 +415,12 @@ StatusCode TrackParametrizedExtrapolator::propagate( Gaudi::TrackVector& in, dou
   // way.
 
   if ( thepar ) {
-    // info() << "Selected parametrization to transport from/to: "
-    //       << thepar->plane1().z() << " --> " << thepar->plane2().z() << endmsg ;
-
     // propagate to it. assume that jacobian will be set correctly
     Gaudi::TrackMatrix  jac;
     Gaudi::TrackMatrix* pjac = m ? &jac : 0;
     double              z    = z1;
-    sc                       = m_refextrapolator->propagate( in, z, thepar->plane1().z(), m, geometry );
-    z                        = thepar->plane1().z();
+    sc                       = m_refextrapolator->propagate( in, z, thepar->plane1().z, m, geometry );
+    z                        = thepar->plane1().z;
 
     if ( sc.isSuccess() ) {
       thepar->propagate( in, pjac );
@@ -474,7 +429,7 @@ StatusCode TrackParametrizedExtrapolator::propagate( Gaudi::TrackVector& in, dou
         Gaudi::TrackMatrix mtmp = ( *pjac ) * ( *m );
         *m                      = mtmp;
       }
-      z  = thepar->plane2().z();
+      z  = thepar->plane2().z;
       sc = m_refextrapolator->propagate( in, z, z2, pjac, geometry );
       if ( m ) {
         Gaudi::TrackMatrix mtmp = ( *pjac ) * ( *m );
-- 
GitLab


From 1f2b6aff2289fb9c2b85a33141b7092335312911 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 12:37:13 +0200
Subject: [PATCH 13/26] Converted SelectiveElectronMatchAlg to use of yaml for
 conditions

---
 .../src/SelectiveElectronMatchAlg.cpp         | 30 +++++++------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp b/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
index 9f853a9df93..db716c5ecf1 100644
--- a/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
+++ b/CaloFuture/CaloFuturePIDs/src/SelectiveElectronMatchAlg.cpp
@@ -10,7 +10,6 @@
  \*****************************************************************************/
 #include "CaloFutureUtils/CaloFutureAlgUtils.h"
 #include "CaloFutureUtils/TrackUtils.h"
-#include "DetDesc/Condition.h"
 #include "Gaudi/Accumulators.h"
 #include "GaudiAlg/GaudiTool.h"
 #include "GaudiKernel/GaudiException.h"
@@ -18,6 +17,8 @@
 #include "Magnet/DeMagnet.h"
 #include "SelectiveMatchUtils.h"
 
+#include <yaml-cpp/yaml.h>
+
 /** @class SelectiveElectronMatchAlg SelectiveElectronMatchAlg.h
  *
  *  Matches tracks with local electron hypos in and around calo cell
@@ -52,15 +53,6 @@ namespace LHCb::Calo {
   // local helper functions for class
   namespace {
 
-    // helper function, copied / adapted from DeRichBase.h
-    template <typename OUTTYPE, std::size_t N, typename INTYPE = OUTTYPE>
-    decltype( auto ) toarray( const std::vector<INTYPE>& v ) {
-      if ( v.size() != N ) throw GaudiException( "Vector to Array Size Error", __func__, StatusCode::FAILURE );
-      std::array<OUTTYPE, N> a;
-      std::copy( v.begin(), v.end(), a.begin() );
-      return a;
-    }
-
     // conditions for x-correction
     class electronXcorrections {
     private:
@@ -73,13 +65,13 @@ namespace LHCb::Calo {
 
     public:
       electronXcorrections() = default; // needed by DD4hep even if unused !
-      electronXcorrections( Condition const& c )
-          : alphaPOut{toarray<double, 4>( c.paramAsDoubleVect( "alphaPOut" ) )}
-          , alphaNOut{toarray<double, 4>( c.paramAsDoubleVect( "alphaNOut" ) )}
-          , alphaPMid{toarray<double, 4>( c.paramAsDoubleVect( "alphaPMid" ) )}
-          , alphaNMid{toarray<double, 4>( c.paramAsDoubleVect( "alphaNMid" ) )}
-          , alphaPInn{toarray<double, 4>( c.paramAsDoubleVect( "alphaPInn" ) )}
-          , alphaNInn{toarray<double, 4>( c.paramAsDoubleVect( "alphaNInn" ) )} {}
+      electronXcorrections( YAML::Node const& c )
+          : alphaPOut{c["alphaPOut"].as<std::array<double, 4>>()}
+          , alphaNOut{c["alphaNOut"].as<std::array<double, 4>>()}
+          , alphaPMid{c["alphaPMid"].as<std::array<double, 4>>()}
+          , alphaNMid{c["alphaNMid"].as<std::array<double, 4>>()}
+          , alphaPInn{c["alphaPInn"].as<std::array<double, 4>>()}
+          , alphaNInn{c["alphaNInn"].as<std::array<double, 4>>()} {}
 
       const std::array<double, 4>& operator()( const int area, const int charge, const int polarity ) const {
         bool qpolarity = charge * polarity > 0;
@@ -192,8 +184,8 @@ namespace LHCb::Calo {
   // ============================================================================
   StatusCode SelectiveElectronMatchAlg::initialize() {
     auto sc = Transformer::initialize().andThen( [&] {
-      addConditionDerivation<electronXcorrections( Condition const& )>( {m_xcorrectionlocation.value()},
-                                                                        inputLocation<electronXcorrections>() );
+      addConditionDerivation<electronXcorrections( YAML::Node const& )>( {m_xcorrectionlocation.value()},
+                                                                         inputLocation<electronXcorrections>() );
     } );
     return sc;
   }
-- 
GitLab


From e057b9b376871b3657a63273fd9a189d942d6a67 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 12:37:39 +0200
Subject: [PATCH 14/26] Converted TrackUnbiasedPVFinderSoA to use of yaml for
 conditions

---
 Tr/PatPV/src/TrackUnbiasedPVFinderSoA.cpp | 62 +++++++----------------
 1 file changed, 19 insertions(+), 43 deletions(-)

diff --git a/Tr/PatPV/src/TrackUnbiasedPVFinderSoA.cpp b/Tr/PatPV/src/TrackUnbiasedPVFinderSoA.cpp
index 9153648a2b1..66228b00a79 100644
--- a/Tr/PatPV/src/TrackUnbiasedPVFinderSoA.cpp
+++ b/Tr/PatPV/src/TrackUnbiasedPVFinderSoA.cpp
@@ -8,8 +8,7 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "DetDesc/Condition.h"
-#include "DetDesc/ConditionAccessorHolder.h"
+#include "DetDesc/GenericConditionAccessorHolder.h"
 #include "Event/PrVeloTracks.h"
 #include "Event/RecVertex_v2.h"
 #include "Event/Track.h"
@@ -17,6 +16,7 @@
 #include "GaudiKernel/ToolHandle.h"
 #include "Kernel/EventLocalAllocator.h"
 #include "Kernel/STLExtensions.h"
+#include "VPDet/DeVP.h"
 
 #include "Event/TrackVertexUtils.h"
 #include "LHCbMath/StateVertexUtils.h"
@@ -37,6 +37,8 @@
 #include <limits>
 #include <vector>
 
+#include <yaml-cpp/yaml.h>
+
 /**
  * PV finding strategy:
  * step 1: select tracks with velo info and cache some information useful for PV finding
@@ -49,29 +51,18 @@
  **/
 namespace {
 
-  inline const std::string beamSpotCond = "/dd/Conditions/Online/Velo/MotionSystem";
-
   using simd    = SIMDWrapper::best::types;
   using float_v = simd::float_v;
   using int_v   = simd::int_v;
 
-  struct Beamline_t {
-    double X = std::numeric_limits<double>::signaling_NaN();
-    double Y = std::numeric_limits<double>::signaling_NaN();
-    Beamline_t( Condition const& c )
-        : X{( c.param<double>( "ResolPosRC" ) + c.param<double>( "ResolPosLA" ) ) / 2}
-        , Y{c.param<double>( "ResolPosY" )} {}
-    Beamline_t() = default;
-  };
-
 } // namespace
 
 using namespace LHCb::Event::PV;
 
 class TrackUnbiasedPVFinderSoA
     : public Gaudi::Functional::Transformer<PrimaryVertexContainer( const EventContext&, const LHCb::Pr::Velo::Tracks&,
-                                                                    const LHCb::Pr::Velo::Tracks&, const Beamline_t& ),
-                                            LHCb::DetDesc::usesConditions<Beamline_t>> {
+                                                                    const LHCb::Pr::Velo::Tracks&, const DeVP& ),
+                                            LHCb::DetDesc::usesConditions<DeVP>> {
 public:
   /// Standard constructor
   TrackUnbiasedPVFinderSoA( const std::string& name, ISvcLocator* pSvcLocator );
@@ -80,7 +71,7 @@ public:
   /// Execution
   /// Execution
   PrimaryVertexContainer operator()( const EventContext&, const LHCb::Pr::Velo::Tracks&, const LHCb::Pr::Velo::Tracks&,
-                                     const Beamline_t& ) const override;
+                                     const DeVP& ) const override;
 
 private:
   Gaudi::Property<uint32_t> m_minNumTracksPerVertex{this, "MinNumTracksPerVertex", 5};
@@ -111,9 +102,6 @@ private:
 
 DECLARE_COMPONENT( TrackUnbiasedPVFinderSoA )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
 TrackUnbiasedPVFinderSoA::TrackUnbiasedPVFinderSoA( const std::string& name, ISvcLocator* pSvcLocator )
     : Transformer( name, pSvcLocator,
                    {KeyValue{"TracksBackwardLocation", "Rec/Track/VeloBackward"},
@@ -121,27 +109,18 @@ TrackUnbiasedPVFinderSoA::TrackUnbiasedPVFinderSoA( const std::string& name, ISv
                     KeyValue{"BeamSpotLocation", "AlgorithmSpecific-" + name + "-beamspot"}},
                    KeyValue{"OutputVertices", LHCb::Event::v2::RecVertexLocation::Primary} ) {}
 
-//=============================================================================
-// ::initialize()
-//=============================================================================
 StatusCode TrackUnbiasedPVFinderSoA::initialize() {
-  auto sc = Transformer::initialize().andThen(
-      [&] { addConditionDerivation<Beamline_t( Condition const& )>( {beamSpotCond}, inputLocation<Beamline_t>() ); } );
-
+  return Transformer::initialize().andThen( [&] {
 #ifdef TIMINGHISTOGRAMMING
-  auto hsvc       = service<IHistogramSvc>( "HistogramDataSvc", true );
-  m_timeperstepPr = hsvc->bookProf( name() + "/timeperstep", "time per step", 20, -0.5, 19.5 );
-  m_timevsntrksPr = hsvc->bookProf( name() + "/timevsntrks", "time vs number of tracks", 50, -0.5, 249.5 );
-  m_timevsnvtxPr  = hsvc->bookProf( name() + "/timevsnvtx", "time vs number of vertices", 12, -0.5, 11.5 );
+    auto hsvc       = service<IHistogramSvc>( "HistogramDataSvc", true );
+    m_timeperstepPr = hsvc->bookProf( name() + "/timeperstep", "time per step", 20, -0.5, 19.5 );
+    m_timevsntrksPr = hsvc->bookProf( name() + "/timevsntrks", "time vs number of tracks", 50, -0.5, 249.5 );
+    m_timevsnvtxPr  = hsvc->bookProf( name() + "/timevsnvtx", "time vs number of vertices", 12, -0.5, 11.5 );
 #endif
-
-  return sc;
+    return StatusCode::SUCCESS;
+  } );
 }
 
-//=============================================================================
-// ::execute()
-//=============================================================================
-
 namespace {
 
   using namespace LHCb::Event;
@@ -248,7 +227,7 @@ namespace {
 PrimaryVertexContainer TrackUnbiasedPVFinderSoA::operator()( const EventContext&           evtCtx,
                                                              const LHCb::Pr::Velo::Tracks& tracksBackward,
                                                              const LHCb::Pr::Velo::Tracks& tracksForward,
-                                                             const Beamline_t&             beamline ) const {
+                                                             const DeVP&                   deVP ) const {
   /*
 
     Some observations:
@@ -301,18 +280,15 @@ PrimaryVertexContainer TrackUnbiasedPVFinderSoA::operator()( const EventContext&
    */
 
   // Get the beamline. this only accounts for position, not
-  // rotation. that's something to improve! I have considered caching
-  // this (with a handle for changes in the geometry, but the
-  // computation is so fast that it isn't worth it.)
-  // const auto beamline = Gaudi::XYZVector{beamline.X, beamline.Y, 0};
-  // const Vec3<float_v> BL = Vec3<float_v>( beamline.X, beamline.Y, 0 );
+  // rotation. that's something to improve!
 
   // Get the memory resource
   auto memResource = LHCb::getMemResource( evtCtx );
 
   // Allow for correction for beamline position derived from conditions
-  const auto beamlineX = beamline.X + m_beamLineOffsetX;
-  const auto beamlineY = beamline.Y + m_beamLineOffsetY;
+  Gaudi::XYZPoint beamline  = deVP.beamSpot();
+  const auto      beamlineX = beamline.x() + m_beamLineOffsetX;
+  const auto      beamlineY = beamline.y() + m_beamLineOffsetY;
 
   // Step 1: select tracks with velo info, compute the poca to the
   // beamline. cache the covariance matrix at this position. I'd
-- 
GitLab


From 89c08442b4336973fbabc110c67a6f1844caaccf Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 12:37:54 +0200
Subject: [PATCH 15/26] Converted TrackBeamLineVertexFinder to use derived
 conditions and yaml for conditions

---
 Tr/PatPV/src/TrackBeamLineVertexFinder.cpp | 147 ++++++++-------------
 1 file changed, 58 insertions(+), 89 deletions(-)

diff --git a/Tr/PatPV/src/TrackBeamLineVertexFinder.cpp b/Tr/PatPV/src/TrackBeamLineVertexFinder.cpp
index d20e4dafa2f..bad2be32937 100644
--- a/Tr/PatPV/src/TrackBeamLineVertexFinder.cpp
+++ b/Tr/PatPV/src/TrackBeamLineVertexFinder.cpp
@@ -11,15 +11,15 @@
 #include "DetDesc/Condition.h"
 #include "Event/RecVertex_v2.h"
 #include "Event/Track.h"
-#include "GaudiAlg/Transformer.h"
-#include "GaudiKernel/ToolHandle.h"
+#include "LHCbAlgs/Transformer.h"
 #include "PrKernel/PrSelection.h"
 #include "Timer.h"
+#include "VPDet/DeVP.h"
+
+#include "GaudiKernel/ToolHandle.h"
 
-// boost includes
 #include <boost/container/static_vector.hpp>
 
-// std includes
 #include <array>
 #include <vector>
 
@@ -30,8 +30,10 @@
 #  include "GaudiKernel/IHistogramSvc.h"
 #endif
 
-/** @class TrackBeamLineVertexFinder TrackBeamLineVertexFinder.cpp
- *
+using namespace LHCb::Event::v2;
+using TrackBeamLineVertexFinderOutput = std::tuple<std::vector<RecVertex>, Pr::Selection<Track>>;
+
+/**
  * PV finding strategy:
  * step 1: select tracks with velo info and cache some information useful for PV finding
  * step 2: fill a histogram with the z of the poca to the beamline
@@ -41,23 +43,13 @@
  *
  *  @author Wouter Hulsbergen (Nikhef, 2018)
  **/
-
-namespace {
-  static const std::string beamSpotCond = "/dd/Conditions/Online/Velo/MotionSystem";
-}
-
-using namespace LHCb::Event::v2;
-using TrackBeamLineVertexFinderOutput = std::tuple<std::vector<RecVertex>, Pr::Selection<Track>>;
-
-class TrackBeamLineVertexFinder
-    : public Gaudi::Functional::MultiTransformer<TrackBeamLineVertexFinderOutput( const std::vector<Track>& )> {
+class TrackBeamLineVertexFinder : public LHCb::Algorithm::MultiTransformer<TrackBeamLineVertexFinderOutput(
+                                                                               std::vector<Track> const&, DeVP const& ),
+                                                                           LHCb::DetDesc::usesConditions<DeVP>> {
 public:
-  /// Standard constructor
   TrackBeamLineVertexFinder( const std::string& name, ISvcLocator* pSvcLocator );
-  /// Execution
-  TrackBeamLineVertexFinderOutput operator()( const std::vector<LHCb::Event::v2::Track>& ) const override;
-  /// Initialization
-  StatusCode initialize() override;
+  TrackBeamLineVertexFinderOutput operator()( std::vector<LHCb::Event::v2::Track> const&, DeVP const& ) const override;
+  StatusCode                      initialize() override;
 
 private:
   Gaudi::Property<uint32_t> m_minNumTracksPerVertex{this, "MinNumTracksPerVertex", 4};
@@ -87,87 +79,66 @@ private:
   static const uint16_t Nztemplates           = 32;
   static const uint16_t TemplateNormalization = 128;
   uint16_t              m_ztemplates[2 * Nztemplates][Nztemplatebins]; // odd and even, see note
-  double                m_beamlineX = 0, m_beamlineY = 0;
   mutable Gaudi::Accumulators::SummingCounter<unsigned int> m_nbPVsCounter{this, "Nb PVs"};
 };
 
 DECLARE_COMPONENT( TrackBeamLineVertexFinder )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
 TrackBeamLineVertexFinder::TrackBeamLineVertexFinder( const std::string& name, ISvcLocator* pSvcLocator )
-    : MultiTransformer( name, pSvcLocator, KeyValue{"InputTracks", LHCb::Event::v2::TrackLocation::Default},
-                        {KeyValue{"OutputVertices", LHCb::Event::v2::RecVertexLocation::Primary},
-                         KeyValue{"UnusedTracks", "Rec/Track/NonPVTracks"}} ) {}
+    : MultiTransformer(
+          name, pSvcLocator,
+          {KeyValue{"InputTracks", LHCb::Event::v2::TrackLocation::Default}, KeyValue{"DEVP", LHCb::Det::VP::det_path}},
+          {KeyValue{"OutputVertices", LHCb::Event::v2::RecVertexLocation::Primary},
+           KeyValue{"UnusedTracks", "Rec/Track/NonPVTracks"}} ) {}
 
-//=============================================================================
-// ::initialize()
-//=============================================================================
 StatusCode TrackBeamLineVertexFinder::initialize() {
-  auto sc = MultiTransformer::initialize();
-
-  if ( !exist<Condition>( detSvc(), beamSpotCond ) ) {
-    return Warning( "Unable to locate beam spot condition", StatusCode::FAILURE );
-  }
-  Condition* myCond = get<Condition>( detSvc(), beamSpotCond );
-  //
-  const double xRC = myCond->paramAsDouble( "ResolPosRC" );
-  const double xLA = myCond->paramAsDouble( "ResolPosLA" );
-  const double Y   = myCond->paramAsDouble( "ResolPosY" );
-  //
-  m_beamlineX = ( xRC + xLA ) / 2;
-  m_beamlineY = Y;
-
+  return MultiTransformer::initialize().andThen( [&] {
 #ifdef TIMINGHISTOGRAMMING
-  auto hsvc       = service<IHistogramSvc>( "HistogramDataSvc", true );
-  m_timeperstepPr = hsvc->bookProf( name() + "/timeperstep", "time per step", 20, -0.5, 19.5 );
-  m_timevsntrksPr = hsvc->bookProf( name() + "/timevsntrks", "time vs number of tracks", 50, -0.5, 249.5 );
-  m_timevsnvtxPr  = hsvc->bookProf( name() + "/timevsnvtx", "time vs number of vertices", 12, -0.5, 11.5 );
+    auto hsvc       = service<IHistogramSvc>( "HistogramDataSvc", true );
+    m_timeperstepPr = hsvc->bookProf( name() + "/timeperstep", "time per step", 20, -0.5, 19.5 );
+    m_timevsntrksPr = hsvc->bookProf( name() + "/timevsntrks", "time vs number of tracks", 50, -0.5, 249.5 );
+    m_timevsnvtxPr  = hsvc->bookProf( name() + "/timevsnvtx", "time vs number of vertices", 12, -0.5, 11.5 );
 #endif
 
-  // Fill the odd templates first
-  const double sqrthalf = std::sqrt( 0.5 );
-  {
-    // of course, since the thing is symmetric we can do this more efficiently, but that's not quite worth it now
-    const double zmaxodd = m_dz * ( Nztemplatebins / 2 - 1 + 0.5 );
-    const double zminodd = -zmaxodd;
-    for ( int itemplate = 0; itemplate < Nztemplates; ++itemplate ) {
-      const double sigmaz   = m_maxTrackZ0Err * double( itemplate + 1 ) / Nztemplates;
-      double       integral = 0.5 * std::erf( sqrthalf * zminodd / sigmaz );
-      for ( int ibin = 0; ibin < Nztemplatebins - 1; ++ibin ) {
-        double thisintegral                   = 0.5 * std::erf( sqrthalf * ( zminodd + ( ibin + 1 ) * m_dz ) / sigmaz );
-        double bincontent                     = thisintegral - integral;
-        m_ztemplates[2 * itemplate + 1][ibin] = int( bincontent * TemplateNormalization );
-        integral                              = thisintegral;
+    // Fill the odd templates first
+    const double sqrthalf = std::sqrt( 0.5 );
+    {
+      // of course, since the thing is symmetric we can do this more efficiently, but that's not quite worth it now
+      const double zmaxodd = m_dz * ( Nztemplatebins / 2 - 1 + 0.5 );
+      const double zminodd = -zmaxodd;
+      for ( int itemplate = 0; itemplate < Nztemplates; ++itemplate ) {
+        const double sigmaz   = m_maxTrackZ0Err * double( itemplate + 1 ) / Nztemplates;
+        double       integral = 0.5 * std::erf( sqrthalf * zminodd / sigmaz );
+        for ( int ibin = 0; ibin < Nztemplatebins - 1; ++ibin ) {
+          double thisintegral = 0.5 * std::erf( sqrthalf * ( zminodd + ( ibin + 1 ) * m_dz ) / sigmaz );
+          double bincontent   = thisintegral - integral;
+          m_ztemplates[2 * itemplate + 1][ibin] = int( bincontent * TemplateNormalization );
+          integral                              = thisintegral;
+        }
+        m_ztemplates[2 * itemplate + 1][Nztemplatebins - 1] = 0;
       }
-      m_ztemplates[2 * itemplate + 1][Nztemplatebins - 1] = 0;
     }
-  }
 
-  // even templates
-  {
-    // of course, since the thing is symmetric we can do this more efficiently, but that's not quite worth it now
-    const double zmaxeven = m_dz * Nztemplatebins / 2;
-    const double zmineven = -zmaxeven;
-    for ( int itemplate = 0; itemplate < Nztemplates; ++itemplate ) {
-      const double sigmaz   = m_maxTrackZ0Err * double( itemplate + 1 ) / Nztemplates;
-      double       integral = 0.5 * std::erf( sqrthalf * zmineven / sigmaz );
-      for ( int ibin = 0; ibin < Nztemplatebins; ++ibin ) {
-        double thisintegral               = 0.5 * std::erf( sqrthalf * ( zmineven + ( ibin + 1 ) * m_dz ) / sigmaz );
-        double bincontent                 = thisintegral - integral;
-        m_ztemplates[2 * itemplate][ibin] = int( bincontent * TemplateNormalization );
-        integral                          = thisintegral;
+    // even templates
+    {
+      // of course, since the thing is symmetric we can do this more efficiently, but that's not quite worth it now
+      const double zmaxeven = m_dz * Nztemplatebins / 2;
+      const double zmineven = -zmaxeven;
+      for ( int itemplate = 0; itemplate < Nztemplates; ++itemplate ) {
+        const double sigmaz   = m_maxTrackZ0Err * double( itemplate + 1 ) / Nztemplates;
+        double       integral = 0.5 * std::erf( sqrthalf * zmineven / sigmaz );
+        for ( int ibin = 0; ibin < Nztemplatebins; ++ibin ) {
+          double thisintegral               = 0.5 * std::erf( sqrthalf * ( zmineven + ( ibin + 1 ) * m_dz ) / sigmaz );
+          double bincontent                 = thisintegral - integral;
+          m_ztemplates[2 * itemplate][ibin] = int( bincontent * TemplateNormalization );
+          integral                          = thisintegral;
+        }
       }
     }
-  }
-  return sc;
+    return StatusCode::SUCCESS;
+  } );
 }
 
-//=============================================================================
-// ::execute()
-//=============================================================================
-
 namespace {
 
   // structure with minimal track info needed for PV search
@@ -327,12 +298,10 @@ namespace {
 } // namespace
 
 TrackBeamLineVertexFinderOutput TrackBeamLineVertexFinder::
-                                operator()( std::vector<LHCb::Event::v2::Track> const& tracks ) const {
+                                operator()( std::vector<LHCb::Event::v2::Track> const& tracks, DeVP const& deVP ) const {
   // Get the beamline. this only accounts for position, not
-  // rotation. that's something to improve! I have considered caching
-  // this (with a handle for changes in the geometry, but the
-  // computation is so fast that it isn't worth it.)
-  const auto beamline = Gaudi::XYZVector{m_beamlineX, m_beamlineY, 0};
+  // rotation. that's something to improve!
+  Gaudi::XYZPoint beamline = deVP.beamSpot();
 
   // get the tracks
 #ifdef TIMINGHISTOGRAMMING
-- 
GitLab


From 4213cc8ce3a902bf1f431c1fcd464081f18e09a7 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 13:23:42 +0200
Subject: [PATCH 16/26] Modernization of FastPVFinder

- modernized the C++ (e.g. use range based loops)
- use Gaudi::Property
- used functional algorithms
- used derived conditions
- used yaml for conditions
---
 Tf/FastPV/CMakeLists.txt       |   1 +
 Tf/FastPV/src/FastPVFinder.cpp | 230 +++++++++------------------------
 Tf/FastPV/src/FastPVFinder.h   |  53 --------
 3 files changed, 62 insertions(+), 222 deletions(-)
 delete mode 100644 Tf/FastPV/src/FastPVFinder.h

diff --git a/Tf/FastPV/CMakeLists.txt b/Tf/FastPV/CMakeLists.txt
index cf29114ce4c..7752349602b 100644
--- a/Tf/FastPV/CMakeLists.txt
+++ b/Tf/FastPV/CMakeLists.txt
@@ -23,6 +23,7 @@ gaudi_add_module(FastPV
         Gaudi::GaudiAlgLib
         Gaudi::GaudiKernel
         LHCb::DetDescLib
+        LHCb::VPDetLib
         LHCb::MCEvent
         LHCb::RecEvent
         LHCb::TrackEvent
diff --git a/Tf/FastPV/src/FastPVFinder.cpp b/Tf/FastPV/src/FastPVFinder.cpp
index bb32b2e24d3..f66427ae512 100644
--- a/Tf/FastPV/src/FastPVFinder.cpp
+++ b/Tf/FastPV/src/FastPVFinder.cpp
@@ -8,119 +8,69 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-// Include files
+#include "FastVertex.h"
+#include "TrackForPV.h"
 
-// from Gaudi
 #include "DetDesc/Condition.h"
 #include "Event/RecVertex.h"
 #include "Event/Track.h"
-#include "GaudiKernel/IUpdateManagerSvc.h"
-// local
-#include "FastPVFinder.h"
-#include "FastVertex.h"
-#include "TrackForPV.h"
-
-//-----------------------------------------------------------------------------
-// Implementation file for class : FastPVFinder
-//
-// 2011-11-15 : Olivier Callot
-//-----------------------------------------------------------------------------
-
-// Declaration of the Algorithm Factory
-DECLARE_COMPONENT( FastPVFinder )
-
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
-FastPVFinder::FastPVFinder( const std::string& name, ISvcLocator* pSvcLocator ) : GaudiAlgorithm( name, pSvcLocator ) {
-  declareProperty( "InputLocation", m_inputLocation = LHCb::TrackLocation::Velo );
-  // declareProperty( "InputLocation",  m_inputLocation  = LHCb::TrackLocation::VP );
-  declareProperty( "OutputLocation", m_outputLocation = LHCb::RecVertexLocation::Primary );
-  declareProperty( "MaxIPToBeam", m_maxIPToBeam = 0.200 * Gaudi::Units::mm );
-  declareProperty( "MaxDeltaZ", m_maxDeltaZ = 3.000 * Gaudi::Units::mm );
-  declareProperty( "MinTracksInPV", m_minTracksInPV = 5 );
-  declareProperty( "MaxChi2ToAdd", m_maxChi2ToAdd = 50. );
-  declareProperty( "MaxChi2Fit", m_maxChi2Fit = 12. );
-  declareProperty( "MaxChi2PerDoF", m_maxChi2PerDoF = 3. );
-}
-
-//=============================================================================
-// Initialization
-//=============================================================================
-StatusCode FastPVFinder::initialize() {
-  StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;              // error printed already by GaudiAlgorithm
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Initialize" << endmsg;
-
-  m_xBeam = 0.0;
-  m_yBeam = 0.0;
-
-  m_beamSpotCondition          = "/dd/Conditions/Online/Velo/MotionSystem";
-  IUpdateManagerSvc* updMgrSvc = svc<IUpdateManagerSvc>( "UpdateManagerSvc", true );
-  updMgrSvc->registerCondition( this, m_beamSpotCondition, &FastPVFinder::updateBeamSpot );
-  updMgrSvc->update( this ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
-
-  m_debug = msgLevel( MSG::DEBUG );
-
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-//  Update the beam position when the condition change
-//=========================================================================
-StatusCode FastPVFinder::updateBeamSpot() {
-  if ( !exist<Condition>( detSvc(), m_beamSpotCondition ) ) {
-    return Warning( "Unable to locate beam spot condition", StatusCode::FAILURE );
-  }
-  Condition* myCond = get<Condition>( detSvc(), m_beamSpotCondition );
-
-  const double xRC = myCond->paramAsDouble( "ResolPosRC" );
-  const double xLA = myCond->paramAsDouble( "ResolPosLA" );
-  const double Y   = myCond->paramAsDouble( "ResolPosY" );
-
-  m_xBeam = ( xRC + xLA ) / 2;
-  m_yBeam = Y;
-
-  info() << "*** Update beam spot, x " << m_xBeam << " y " << m_yBeam << endmsg;
-
-  return StatusCode::SUCCESS;
-}
-//=============================================================================
-// Main execution
-//=============================================================================
-StatusCode FastPVFinder::execute() {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
-  LHCb::RecVertices* out = new LHCb::RecVertices();
-  put( out, m_outputLocation );
-
-  LHCb::Tracks* tracks = get<LHCb::Tracks>( m_inputLocation );
+#include "LHCbAlgs/Transformer.h"
+#include "VPDet/DeVP.h"
+
+namespace LHCb {
+
+  /**
+   *  @author Olivier Callot
+   *  @date   2011-11-15
+   */
+  class FastPVFinder : public Algorithm::MultiTransformerFilter<std::tuple<RecVertices>( Tracks const&, DeVP const& ),
+                                                                LHCb::DetDesc::usesConditions<DeVP>> {
+  public:
+    FastPVFinder( const std::string& name, ISvcLocator* pSvcLocator );
+    std::tuple<bool, RecVertices> operator()( Tracks const&, DeVP const& ) const override;
+
+  private:
+    Gaudi::Property<double>       m_maxIPToBeam{this, "MaxIPToBeam", 0.200 * Gaudi::Units::mm};
+    Gaudi::Property<double>       m_maxDeltaZ{this, "MaxDeltaZ", 3.000 * Gaudi::Units::mm};
+    Gaudi::Property<unsigned int> m_minTracksInPV{this, "MinTracksInPV", 5};
+    Gaudi::Property<double>       m_maxChi2ToAdd{this, "MaxChi2ToAdd", 50};
+    Gaudi::Property<double>       m_maxChi2Fit{this, "MaxChi2Fit", 12};
+    Gaudi::Property<double>       m_maxChi2PerDoF{this, "MaxChi2PerDoF", 3};
+  };
+
+  // Declaration of the Algorithm Factory
+  DECLARE_COMPONENT_WITH_ID( FastPVFinder, "FastPVFinder" )
+} // namespace LHCb
+
+LHCb::FastPVFinder::FastPVFinder( const std::string& name, ISvcLocator* pSvcLocator )
+    : MultiTransformerFilter(
+          name, pSvcLocator,
+          {KeyValue{"InputLocation", TrackLocation::Velo}, KeyValue{"DEVP", LHCb::Det::VP::det_path}},
+          {KeyValue{"OutputLocation", RecVertexLocation::Primary}} ) {}
+
+std::tuple<bool, LHCb::RecVertices> LHCb::FastPVFinder::operator()( LHCb::Tracks const& tracks,
+                                                                    DeVP const&         deVP ) const {
+  std::tuple<bool, LHCb::RecVertices> fullOutput;
+  auto& [filter, out] = fullOutput;
+  filter              = false;
 
   //== Select tracks with a cut on their R at beam
-
   std::vector<TrackForPV> pvTracks;
-  for ( LHCb::Tracks::iterator itT = tracks->begin(); tracks->end() != itT; ++itT ) {
-    TrackForPV temp( *itT, m_xBeam, m_yBeam );
+  pvTracks.reserve( tracks.size() );
+  for ( auto& track : tracks ) {
+    Gaudi::XYZPoint beamSpot = deVP.beamSpot();
+    TrackForPV      temp( track, beamSpot.x(), beamSpot.y() );
     if ( temp.rAtBeam() < m_maxIPToBeam ) { pvTracks.push_back( temp ); }
   }
+
+  //== At least enough tracks for a vertex
+  if ( pvTracks.size() < m_minTracksInPV ) return fullOutput;
+
   //== Create a vector of pointer to these tracks, and sort them by zBeam
   std::vector<TrackForPV*> myTracks;
-  for ( std::vector<TrackForPV>::iterator itTr = pvTracks.begin(); pvTracks.end() != itTr; ++itTr ) {
-    myTracks.push_back( &( *itTr ) );
-  }
+  for ( auto& pvTrack : pvTracks ) { myTracks.push_back( &pvTrack ); }
   std::sort( myTracks.begin(), myTracks.end(), TrackForPV::LowerByZ() );
-  std::vector<TrackForPV*>::iterator itT;
-  if ( m_debug ) {
-    for ( itT = myTracks.begin(); myTracks.end() != itT; ++itT ) {
-      info() << format( "Track %3d IP %7.3f at z = %7.3f ", ( *itT )->track()->key(), ( *itT )->rAtBeam(),
-                        ( *itT )->zAtBeam() )
-             << endmsg;
-    }
-  }
 
-  //== At least enough tracks for a vertex
-  if ( myTracks.size() < m_minTracksInPV ) return StatusCode::SUCCESS;
   unsigned int minTracks = 0.3 * myTracks.size(); // Search first for large accumulation
   int          nLoop     = 2;
   if ( minTracks < m_minTracksInPV ) {
@@ -133,11 +83,9 @@ StatusCode FastPVFinder::execute() {
   std::vector<TrackForPV*>::iterator itT1;
   while ( 0 < nLoop ) {
     std::vector<TrackForPV*> unusedTracks;
-    for ( itT1 = myTracks.begin(); myTracks.end() != itT1; ++itT1 ) {
-      if ( !( *itT1 )->used() ) unusedTracks.push_back( *itT1 );
+    for ( auto* myTrack : myTracks ) {
+      if ( !myTrack->used() ) unusedTracks.push_back( myTrack );
     }
-    if ( m_debug )
-      info() << "== Loop " << nLoop << " minTracks " << minTracks << " size " << unusedTracks.size() << endmsg;
     --nLoop;
     if ( unusedTracks.size() < minTracks ) continue;
     for ( itT1 = unusedTracks.begin(); unusedTracks.end() - minTracks > itT1; ++itT1 ) {
@@ -174,16 +122,12 @@ StatusCode FastPVFinder::execute() {
 
       //== Final fit, and checks
       temp.removeWorsts( m_maxChi2Fit );
-      if ( m_debug )
-        info() << "tentative vertex at z " << temp.vertex().z() << " n track " << temp.nTracks() << " chi2/DoF "
-               << temp.chi2PerDoF() << endmsg;
 
       if ( temp.nTracks() < minTracks ) continue;
       if ( temp.nbUsed() > 0.9 * temp.tracks().size() ) continue; // avoid duplicates
       if ( temp.chi2PerDoF() > m_maxChi2PerDoF ) continue;
       myVertices.push_back( temp );
       temp.setTracksUsed( true );
-      if ( m_debug ) info() << "    stored" << endmsg;
     }
     minTracks = m_minTracksInPV;
   }
@@ -195,17 +139,6 @@ StatusCode FastPVFinder::execute() {
     for ( itT1 = myTracks.begin(); myTracks.end() != itT1; ++itT1 ) {
       if ( !( *itT1 )->used() ) unusedTracks.push_back( *itT1 );
     }
-    if ( m_debug ) {
-      if ( m_debug ) info() << "-- Try unused tracks, size = " << unusedTracks.size() << endmsg;
-      for ( itT = unusedTracks.begin(); unusedTracks.end() != itT; ++itT ) {
-        info() << format( "Track %3d beamIP %7.3f at z = %8.3f ", ( *itT )->track()->key(), ( *itT )->rAtBeam(),
-                          ( *itT )->zAtBeam() );
-        for ( std::vector<FastVertex>::iterator itV = myVertices.begin(); myVertices.end() != itV; ++itV ) {
-          info() << format( " %9.1f", ( *itT )->chi2( ( *itV ).vertex() ) );
-        }
-        info() << endmsg;
-      }
-    }
     found = false;
     if ( m_minTracksInPV > unusedTracks.size() ) continue;
     FastVertex temp( unusedTracks.begin(), unusedTracks.end() - 1 );
@@ -214,62 +147,21 @@ StatusCode FastPVFinder::execute() {
       myVertices.push_back( temp );
       temp.setTracksUsed( true );
       found = true;
-      if ( m_debug ) {
-        info() << format( "Unused Vertex at x %7.3f y%7.3f z%7.3f  Ntr %3d chi2/DoF%7.3f", temp.vertex().x(),
-                          temp.vertex().y(), temp.vertex().z(), temp.nTracks(), temp.chi2PerDoF() )
-               << endmsg;
-        for ( std::vector<TrackForPV*>::iterator itT = temp.tracks().begin(); temp.tracks().end() != itT; ++itT ) {
-          info() << format( "     Track %3d IP %7.3f at z = %7.3f chi2 %7.3f ", ( *itT )->track()->key(),
-                            ( *itT )->rAtBeam(), ( *itT )->zAtBeam(), ( *itT )->chi2( temp.vertex() ) )
-                 << endmsg;
-        }
-      }
-    }
-  }
-
-  std::vector<FastVertex>::iterator itV;
-  //== Summary
-  if ( m_debug ) {
-    info() << "Number of reconstructed vertices " << myVertices.size() << endmsg;
-    for ( itV = myVertices.begin(); myVertices.end() != itV; ++itV ) {
-      info() << format( "Vertex at x %7.3f y%7.3f z%7.3f  Ntr %3d ", ( *itV ).vertex().x(), ( *itV ).vertex().y(),
-                        ( *itV ).vertex().z(), ( *itV ).nTracks() )
-             << endmsg;
-      for ( std::vector<TrackForPV*>::iterator itT = ( *itV ).tracks().begin(); ( *itV ).tracks().end() != itT;
-            ++itT ) {
-        info() << format( "     Track %3d IP %7.3f at z = %7.3f chi2 %7.3f ", ( *itT )->track()->key(),
-                          ( *itT )->rAtBeam(), ( *itT )->zAtBeam(), ( *itT )->chi2( ( *itV ).vertex() ) )
-               << endmsg;
-      }
     }
   }
 
   //== Store the vertices in the appropriate container
-  for ( itV = myVertices.begin(); myVertices.end() != itV; ++itV ) {
-    LHCb::RecVertex* tmp = new LHCb::RecVertex;
+  for ( auto& myVertex : myVertices ) {
+    RecVertex* tmp = new RecVertex;
     tmp->setTechnique( LHCb::RecVertex::RecVertexType::Primary );
-    tmp->setPosition( ( *itV ).vertex() );
-    for ( std::vector<TrackForPV*>::iterator itT = ( *itV ).tracks().begin(); ( *itV ).tracks().end() != itT; ++itT ) {
+    tmp->setPosition( myVertex.vertex() );
+    for ( std::vector<TrackForPV*>::iterator itT = myVertex.tracks().begin(); myVertex.tracks().end() != itT; ++itT ) {
       tmp->addToTracks( ( *itT )->track() );
     }
-    tmp->setChi2AndDoF( ( *itV ).chi2(), 2 * ( *itV ).nTracks() - 3 );
-    tmp->setCovMatrix( ( *itV ).cov() );
-    out->insert( tmp );
+    tmp->setChi2AndDoF( myVertex.chi2(), 2 * myVertex.nTracks() - 3 );
+    tmp->setCovMatrix( myVertex.cov() );
+    out.insert( tmp );
   }
-
-  setFilterPassed( !out->empty() );
-
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-//  Finalize
-//=============================================================================
-StatusCode FastPVFinder::finalize() {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Finalize" << endmsg;
-
-  return GaudiAlgorithm::finalize(); // must be called after all other actions
+  filter = !out.empty();
+  return fullOutput;
 }
-
-//=============================================================================
diff --git a/Tf/FastPV/src/FastPVFinder.h b/Tf/FastPV/src/FastPVFinder.h
deleted file mode 100644
index 44d45e9b588..00000000000
--- a/Tf/FastPV/src/FastPVFinder.h
+++ /dev/null
@@ -1,53 +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 FASTPVFINDER_H
-#define FASTPVFINDER_H 1
-
-// Include files
-// from Gaudi
-#include "GaudiAlg/GaudiAlgorithm.h"
-
-/** @class FastPVFinder FastPVFinder.h
- *
- *
- *  @author Olivier Callot
- *  @date   2011-11-15
- */
-class FastPVFinder : public GaudiAlgorithm {
-public:
-  /// Standard constructor
-  FastPVFinder( const std::string& name, ISvcLocator* pSvcLocator );
-
-  StatusCode initialize() override; ///< Algorithm initialization
-  StatusCode execute() override;    ///< Algorithm execution
-  StatusCode finalize() override;   ///< Algorithm finalization
-
-protected:
-  StatusCode updateBeamSpot();
-
-private:
-  std::string m_inputLocation;
-  std::string m_outputLocation;
-  std::string m_beamSpotCondition;
-
-  double       m_maxIPToBeam;
-  unsigned int m_minTracksInPV;
-  double       m_maxDeltaZ;
-  double       m_maxChi2ToAdd;
-  double       m_maxChi2Fit;
-  double       m_maxChi2PerDoF;
-
-  double m_xBeam;
-  double m_yBeam;
-
-  bool m_debug;
-};
-#endif // FASTPVFINDER_H
-- 
GitLab


From 0776995739ce36c91468baef57f4ababab967310 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 14:17:06 +0200
Subject: [PATCH 17/26] Dropped unused static string in PatPV3DFuture

---
 Tr/PatPV/src/PatPV3DFuture.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Tr/PatPV/src/PatPV3DFuture.cpp b/Tr/PatPV/src/PatPV3DFuture.cpp
index b0578710e32..3cb125d9762 100644
--- a/Tr/PatPV/src/PatPV3DFuture.cpp
+++ b/Tr/PatPV/src/PatPV3DFuture.cpp
@@ -210,8 +210,6 @@ PatPV3DFuture::PatPV3DFuture( const std::string& name, ISvcLocator* pSvcLocator
 
 namespace {
 
-  static const std::string s_beamSpotCond = "/dd/Conditions/Online/Velo/MotionSystem";
-
   using RecVertexSpan = LHCb::span<const PatPV3DFuture::RecVertex>;
   bool isChi2Separated( const PatPV3DFuture::RecVertex& rvtx, const LHCb::RecVertices& outvtxvec,
                         double minAllowedChi2 ) {
-- 
GitLab


From 8c4a542476c0ddf788cf3810fda9277baf4d05d9 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 15:57:15 +0200
Subject: [PATCH 18/26] Converted FilterFillingScheme to use derived conditions

---
 Rec/LumiAlgs/src/FilterFillingScheme.cpp | 208 +++++------------------
 1 file changed, 40 insertions(+), 168 deletions(-)

diff --git a/Rec/LumiAlgs/src/FilterFillingScheme.cpp b/Rec/LumiAlgs/src/FilterFillingScheme.cpp
index defbdf130a6..8cd2818d26d 100644
--- a/Rec/LumiAlgs/src/FilterFillingScheme.cpp
+++ b/Rec/LumiAlgs/src/FilterFillingScheme.cpp
@@ -8,206 +8,78 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "DetDesc/Condition.h"
 #include "Event/ODIN.h"
-#include "GaudiAlg/FilterPredicate.h"
-#include "GaudiKernel/IDetDataSvc.h"
+#include "LHCbAlgs/FilterPredicate.h"
 
-//-----------------------------------------------------------------------------
-// Implementation file for class : FilterFillingScheme
-//
-// 2011-08-09 : Jaap Panman
-//-----------------------------------------------------------------------------
+#include <yaml-cpp/yaml.h>
 
-/** @class FilterFillingScheme FilterFillingScheme.h
- *
- *
+namespace {
+  struct Conditions {
+    /// magnet state (UP/DOWN)
+    std::string parMagnetState;
+    /// Condition for LHC filling scheme
+    std::string B1FillingScheme;
+    std::string B2FillingScheme;
+  };
+} // namespace
+
+/**
  *  @author Jaap Panman
  *  @date   2011-08-09
  */
-class FilterFillingScheme : public Gaudi::Functional::FilterPredicate<bool( const LHCb::ODIN& )> {
+class FilterFillingScheme : public LHCb::Algorithm::FilterPredicate<bool( LHCb::ODIN const&, Conditions const& ),
+                                                                    LHCb::DetDesc::usesConditions<Conditions>> {
 public:
-  /// Standard constructor
   FilterFillingScheme( const std::string& name, ISvcLocator* pSvcLocator );
-
-  StatusCode initialize() override;                          ///< Algorithm initialization
-  bool       operator()( const LHCb::ODIN& ) const override; ///< Algorithm execution
+  StatusCode initialize() override;
+  bool       operator()( const LHCb::ODIN&, Conditions const& ) const override;
 
 private:
-  StatusCode registerDB();                 ///< register DB conditions
-  bool       processDB( long bxid ) const; ///< DB checking code
-
-  StatusCode i_cacheFillingData(); ///< Function extracting data from Condition
-  StatusCode i_cacheMagnetData();  ///< Function extracting data from Condition
-
-  Gaudi::Property<std::string> m_beam{this, "Beam", "0"};                  ///< Beam looked at
-  Gaudi::Property<std::string> m_MagnetState{this, "MagnetState", "NONE"}; ///< Magnet state looked at (if empty: all)
-  Gaudi::Property<int>         m_BXOffset{this, "BXOffset", 0};            ///< bcid offset imspected
-
-  // database conditions and calibration factors
-  Condition*  m_condMagnet = nullptr; ///< Condition for magnet
-  std::string m_parMagnetState;       ///< magnet state (UP/DOWN)
-
-  Condition*  m_condFilling = nullptr; ///< Condition for LHC filling scheme
-  std::string m_B1FillingScheme;       ///< filled bunches 00101010....
-  std::string m_B2FillingScheme;       ///< filled bunches 00101010....
+  Gaudi::Property<std::string> m_beam{this, "Beam", "0", "Beam looked at"};
+  Gaudi::Property<std::string> m_MagnetState{this, "MagnetState", "NONE", "Magnet state looked at (if empty: all)"};
+  Gaudi::Property<int>         m_BXOffset{this, "BXOffset", 0, "bcid offset imspected"};
 };
 
 // Declaration of the Algorithm Factory
 DECLARE_COMPONENT( FilterFillingScheme )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
 FilterFillingScheme::FilterFillingScheme( const std::string& name, ISvcLocator* pSvcLocator )
-    : FilterPredicate( name, pSvcLocator, {KeyValue{"ODINLocation", LHCb::ODINLocation::Default}} ) {}
-//=============================================================================
-// Initialization
-//=============================================================================
+    : FilterPredicate(
+          name, pSvcLocator,
+          {KeyValue{"ODINLocation", LHCb::ODINLocation::Default}, KeyValue{"Conditions", name + "-Conditions"}} ) {}
+
 StatusCode FilterFillingScheme::initialize() {
-  return GaudiAlgorithm::initialize().andThen( [&] {
-    // register conditions for database acces
-    return registerDB();
+  return FilterPredicate::initialize().andThen( [&] {
+    addConditionDerivation( {"Conditions/Online/LHCb/LHCFillingScheme", "Conditions/Online/LHCb/Magnet/Measured"},
+                            inputLocation<Conditions>(),
+                            [&]( YAML::Node const& fillingScheme, YAML::Node const& magnetState ) -> Conditions {
+                              return {magnetState["State"].as<std::string>(),
+                                      fillingScheme["B1FillingScheme"].as<std::string>(),
+                                      fillingScheme["B2FillingScheme"].as<std::string>()};
+                            } );
+    return StatusCode::SUCCESS;
   } );
 }
 
-//=============================================================================
-// Main execution
-//=============================================================================
-bool FilterFillingScheme::operator()( const LHCb::ODIN& odin ) const {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
-
-  auto bxid = odin.bunchId();
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "ODIN BCID: " << bxid << endmsg;
-
+bool FilterFillingScheme::operator()( const LHCb::ODIN& odin, Conditions const& conds ) const {
   // combine all input for a decision
-  bool decision = processDB( bxid );
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Accept event : " << bxid << " : " << decision << endmsg;
-
-  return decision;
-}
-
-//=============================================================================
-// DB access
-//=============================================================================
-StatusCode FilterFillingScheme::registerDB() {
-  // register the DB conditions for the update maganer
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Register DB" << endmsg;
-
-  // register filling scheme data
-  const std::string lhcFS = "Conditions/Online/LHCb/LHCFillingScheme";
-  if ( this->existDet<Condition>( lhcFS ) ) {
-    registerCondition( lhcFS, m_condFilling, &FilterFillingScheme::i_cacheFillingData );
-    if ( msgLevel( MSG::DEBUG ) ) debug() << lhcFS << endmsg;
-  } else {
-    warning() << lhcFS << " not found, fall back to sampling data" << endmsg;
-  }
-
-  // register magnet data
-  const std::string magnet = "Conditions/Online/LHCb/Magnet/Measured";
-  if ( this->existDet<Condition>( magnet ) ) {
-    registerCondition( magnet, m_condMagnet, &FilterFillingScheme::i_cacheMagnetData );
-    if ( msgLevel( MSG::DEBUG ) ) debug() << magnet << endmsg;
-  } else {
-    warning() << magnet << " not found, fall back to sampling data" << endmsg;
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-//  Extract data from Filling scheme
-//=========================================================================
-StatusCode FilterFillingScheme::i_cacheFillingData() {
-  //  data from /Conditions/Online/LHCb/LHCFillingScheme
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "callback Filling:" << endmsg;
-
-  m_B1FillingScheme = m_condFilling->param<std::string>( "B1FillingScheme" );
-  m_B2FillingScheme = m_condFilling->param<std::string>( "B2FillingScheme" );
-
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-//  Extract data from Filling scheme
-//=========================================================================
-StatusCode FilterFillingScheme::i_cacheMagnetData() {
-  //  data from /Conditions/Online/LHCb/Magnet/Measured
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "callback Magnet:" << endmsg;
-
-  if ( m_condMagnet->exists( "State" ) ) {
-    m_parMagnetState = (std::string)m_condMagnet->param<std::string>( "State" );
-  } else {
-    warning() << "Magnet State condition not implemented for these data" << endmsg;
-    m_parMagnetState = "OFF";
-  }
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-// process DB parameters
-//=============================================================================
-bool FilterFillingScheme::processDB( long bxid ) const {
-
-  if ( msgLevel( MSG::DEBUG ) ) {
-    // odin data
-    debug() << "ODIN BXID :       " << bxid << " " << endmsg;
-    // magnet
-    debug() << "MagnetState :     " << m_parMagnetState << " " << endmsg;
-  }
-  if ( msgLevel( MSG::VERBOSE ) ) {
-    // filling scheme
-    verbose() << "B1FillingScheme : " << m_B1FillingScheme << " " << endmsg;
-    verbose() << "BeFillingScheme : " << m_B1FillingScheme << " " << endmsg;
-  }
-
+  auto bxid = odin.bunchId();
   // for some options do not look at the data
-  if ( m_beam == "0" || m_MagnetState == "None" ) {
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << "Do not look at the data with these options - return true"
-              << " " << endmsg;
-    return true;
-  }
-
+  if ( m_beam == "0" || m_MagnetState == "None" ) { return true; }
   // check if magnet state to be checked
-  if ( m_MagnetState != "" && m_MagnetState != m_parMagnetState ) {
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << "Do not look at the data - magnet state - return true"
-              << " " << endmsg;
-    return true;
-  }
-
+  if ( m_MagnetState != "" && m_MagnetState != conds.parMagnetState ) { return true; }
   // take the filling scheme corresponding to the requested beam
   std::string scheme = "";
   if ( m_beam == "1" ) {
-    scheme = m_B1FillingScheme;
+    scheme = conds.B1FillingScheme;
   } else if ( m_beam == "2" ) {
-    scheme = m_B2FillingScheme;
+    scheme = conds.B2FillingScheme;
   } else {
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << "Do not look at the data with this beam flag - return true"
-              << " " << endmsg;
     return true;
   }
-
   long max_buckets = scheme.size();
-  if ( max_buckets == 0 ) {
-    if ( msgLevel( MSG::DEBUG ) ) debug() << "invalid scheme - return true - size:" << max_buckets << " " << endmsg;
-    return true;
-  }
-
+  if ( max_buckets == 0 ) { return true; }
   // ODIN starts counting at 1 - so we have to subtract 1 always to index into the string
   long index = ( m_BXOffset + bxid + max_buckets - 1 ) % max_buckets;
-  if ( msgLevel( MSG::DEBUG ) ) {
-    if ( scheme[index] == '0' ) {
-      debug() << "empty bucket at tested location: " << index << " " << scheme[index] << " - return true " << endmsg;
-    } else {
-      debug() << "filled bucket at tested location: " << index << " " << scheme[index] << " - return false " << endmsg;
-    }
-  }
   return scheme[index] == '0';
 }
-
-//=============================================================================
-- 
GitLab


From 06cb43d6bd5b4ee921a0c64dc08fcc92d6af7ccc Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 16:23:52 +0200
Subject: [PATCH 19/26] Converted LumiAccounting to use derived conditions and
 yaml for conditions

---
 Rec/LumiAlgs/src/LumiAccounting.cpp       | 178 +++------------
 Rec/LumiAlgs/tests/refs/lumi3conftest.ref | 254 ++--------------------
 2 files changed, 58 insertions(+), 374 deletions(-)

diff --git a/Rec/LumiAlgs/src/LumiAccounting.cpp b/Rec/LumiAlgs/src/LumiAccounting.cpp
index c3a7553efff..e970dfaa50e 100644
--- a/Rec/LumiAlgs/src/LumiAccounting.cpp
+++ b/Rec/LumiAlgs/src/LumiAccounting.cpp
@@ -8,47 +8,41 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "DetDesc/Condition.h"
 #include "Event/HltLumiSummary.h"
 #include "Event/LumiCounters.h"
 #include "Event/LumiFSR.h"
 #include "Event/LumiMethods.h"
 #include "Event/ODIN.h"
 #include "Event/RawEvent.h"
-#include "GaudiAlg/Consumer.h"
+#include "Kernel/SynchronizedValue.h"
+#include "LHCbAlgs/Consumer.h"
+
 #include "GaudiKernel/GaudiException.h"
 #include "GaudiKernel/IDetDataSvc.h"
 #include "GaudiKernel/IOpaqueAddress.h"
 #include "GaudiKernel/IRegistry.h"
-#include "Kernel/SynchronizedValue.h"
 
-//-----------------------------------------------------------------------------
-// Implementation file for class : LumiAccounting
-//
-// 2009-01-19 : Jaap Panman
-//-----------------------------------------------------------------------------
+#include <yaml-cpp/yaml.h>
 
-/** @class LumiAccounting LumiAccounting.h
- *
- *
+namespace {
+  using CalibThresholds = std::vector<double>;
+} // namespace
+
+/**
  *  @author Jaap Panman
  *  @date   2009-01-19
  */
 class LumiAccounting
-    : public Gaudi::Functional::Consumer<void(
-          const LHCb::RawEvent& event, const LHCb::HltLumiSummary& the_hltLumiSummary, const LHCb::ODIN& odin )> {
+    : public LHCb::Algorithm::Consumer<void( const LHCb::RawEvent&       event,
+                                             const LHCb::HltLumiSummary& the_hltLumiSummary, const LHCb::ODIN& odin,
+                                             const CalibThresholds& calibThresholds ),
+                                       LHCb::DetDesc::usesConditions<CalibThresholds>> {
 public:
-  /// Standard constructor
   LumiAccounting( const std::string& name, ISvcLocator* pSvcLocator );
-
   StatusCode initialize() override; ///< Algorithm initialization
-  void       operator()( const LHCb::RawEvent& event, const LHCb::HltLumiSummary& the_hltLumiSummary,
-                   const LHCb::ODIN& odin ) const override; ///< Algorithm execution
-  StatusCode finalize() override;                                 ///< Algorithm finalization
-
-private:
-  StatusCode registerDB();           ///< register DB conditions
-  StatusCode i_cacheThresholdData(); ///< Function extracting data from Condition
+  void operator()( const LHCb::RawEvent& event, const LHCb::HltLumiSummary& the_hltLumiSummary, const LHCb::ODIN& odin,
+                   const CalibThresholds& calibThresholds ) const override;
+  StatusCode finalize() override;
 
 private:
   /// Reference to file records data service
@@ -58,12 +52,8 @@ private:
   LHCb::LumiFSRs* m_lumiFSRs = nullptr; ///< TDS container
   LHCb::LumiFSR*  m_lumiFSR  = nullptr; ///< FSR for current file
 
-  mutable LHCb::cxx::SynchronizedValue<std::unordered_set<std::string>> m_files; ///< files read
-
-  // database conditions and calibration factors
-  Condition*          m_condThresholds = nullptr; ///< Condition for relative calibration
-  std::vector<double> m_calibThresholds;          ///< relative calibration factors
-  int                 m_statusThresholds = 0;     ///<
+  /// files read
+  mutable LHCb::cxx::SynchronizedValue<std::unordered_set<std::string>> m_files;
 
   // it is assumed that we are only called for a single BXType and that the
   // output data container gets this name
@@ -74,56 +64,30 @@ private:
 // Declaration of the Algorithm Factory
 DECLARE_COMPONENT( LumiAccounting )
 
-//=============================================================================
-// Standard constructor, initializes variables
-//=============================================================================
 LumiAccounting::LumiAccounting( const std::string& name, ISvcLocator* pSvcLocator )
     : Consumer( name, pSvcLocator,
                 {KeyValue{"RawEventLocation", LHCb::RawEventLocation::Default},
                  KeyValue{"InputDataContainer", LHCb::HltLumiSummaryLocation::Default},
-                 KeyValue{"ODINLocation", LHCb::ODINLocation::Default}} ) {}
+                 KeyValue{"ODINLocation", LHCb::ODINLocation::Default},
+                 KeyValue{"CalibThresholds", name + "-CalibThresholds"}} ) {}
 
-//=============================================================================
-// Initialization
-//=============================================================================
 StatusCode LumiAccounting::initialize() {
-  StatusCode sc = Consumer::initialize(); // must be executed first
-  if ( sc.isFailure() ) return sc;        // error printed already by GaudiAlgorithm
-
-  sc = m_fileRecordSvc.retrieve();
-  if ( sc.isFailure() ) return sc;
-
-  // prepare TDS for FSR
-  m_lumiFSRs = new LHCb::LumiFSRs();
-  put( m_fileRecordSvc.get(), m_lumiFSRs, m_FSRName );
-  // create a new FSR and append to TDS
-  m_lumiFSR = new LHCb::LumiFSR();
-  m_lumiFSRs->insert( m_lumiFSR );
-
-  // initialize calibration factors
-  for ( int key = 0; key <= LHCb::LumiCounters::counterKey::Random; key++ ) {
-    std::string counterName = LHCb::LumiCounters::counterKeyToString( key );
-    m_calibThresholds.push_back( 0 );
-  }
-
-  // register conditions for database acces
-  sc = registerDB(); // must be executed first
-  if ( sc.isFailure() ) {
-    error() << "No thresholds defined for lumi counters (no registration)" << endmsg;
-    m_statusThresholds = 0; // no database
-  }
-
-  return sc;
+  return Consumer::initialize().andThen( [&] {
+    // prepare TDS for FSR
+    m_lumiFSRs = new LHCb::LumiFSRs();
+    m_fileRecordSvc->registerObject( this->fullTESLocation( m_FSRName, true ), m_lumiFSRs ).ignore();
+    // create a new FSR and append to TDS
+    m_lumiFSR = new LHCb::LumiFSR();
+    m_lumiFSRs->insert( m_lumiFSR );
+
+    addConditionDerivation( {"Conditions/Lumi/LHCb/ThresholdCalibration"}, inputLocation<CalibThresholds>(),
+                            [&]( YAML::Node const& cond ) { return cond["Thresholds"].as<std::vector<double>>(); } );
+    return StatusCode::SUCCESS;
+  } );
 }
 
-//=============================================================================
-// Main execution
-//=============================================================================
 void LumiAccounting::operator()( const LHCb::RawEvent& event, const LHCb::HltLumiSummary& the_hltLumiSummary,
-                                 const LHCb::ODIN& odin ) const {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
-
+                                 const LHCb::ODIN& odin, const CalibThresholds& calibThresholds ) const {
   // registry from raw data - only correct if file catalogue used
   IOpaqueAddress* eAddr = event.registry()->address();
   // obtain the fileID
@@ -131,12 +95,8 @@ void LumiAccounting::operator()( const LHCb::RawEvent& event, const LHCb::HltLum
     throw GaudiException( "Registry cannot be loaded from Event", "LumiAccounting::" + name(), StatusCode::SUCCESS );
   }
   std::string event_fname = eAddr->par()[0];
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "RunInfo record from Event: " << event_fname << endmsg;
-
   // obtain the run number from ODIN
   unsigned int run = odin.runNumber();
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "ODIN RunNumber: " << run << endmsg;
-
   // check if the file ID is new
   std::string fname = event_fname;
   m_files.with_lock( [&]( std::unordered_set<std::string>& f ) { f.insert( fname ); } );
@@ -153,19 +113,13 @@ void LumiAccounting::operator()( const LHCb::RawEvent& event, const LHCb::HltLum
     // increment!
     m_lumiFSR->incrementInfo( key, value );
     // check if over threshold and increment with offset
-    double threshold = m_calibThresholds[key];
+    double threshold = calibThresholds[key];
     int    binary    = value > threshold ? 1 : 0;
     m_lumiFSR->incrementInfo( key + LHCb::LumiMethods::methodKey::PoissonOffset, binary );
   }
 }
 
-//=============================================================================
-//  Finalize
-//=============================================================================
 StatusCode LumiAccounting::finalize() {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Finalize" << endmsg;
-
   // some printout of FSRs
   if ( msgLevel( MSG::INFO ) ) {
     info() << "number of files seen: " << m_files.with_lock( &std::unordered_set<std::string>::size ) << endmsg;
@@ -173,72 +127,8 @@ StatusCode LumiAccounting::finalize() {
     // sum up the information
     LHCb::LumiFSR sumFSR;
     for ( const auto& fsr : *m_lumiFSRs ) sumFSR += *fsr;
-    if ( msgLevel( MSG::VERBOSE ) ) {
-      // print the individual FSR
-      for ( const auto& fsr : *m_lumiFSRs ) { verbose() << "FSR: " << *fsr << endmsg; }
-    }
     // print the integral
     info() << "INTEGRAL: " << sumFSR << endmsg;
   }
-
-  // check if the FSRs can be retrieved from the TS
-  if ( msgLevel( MSG::DEBUG ) ) {
-    LHCb::LumiFSRs*          readFSRs = get<LHCb::LumiFSRs>( m_fileRecordSvc.get(), m_FSRName );
-    LHCb::LumiFSRs::iterator fsr;
-    for ( fsr = readFSRs->begin(); fsr != readFSRs->end(); fsr++ ) {
-      // print the FSR just retrieved from TS
-      debug() << "READ FSR: " << *( *fsr ) << endmsg;
-
-      // print also the contents using the builtin lookup tables
-      LHCb::LumiFSR::ExtraInfo::iterator infoIter;
-      LHCb::LumiFSR::ExtraInfo           fsrInfo = ( *fsr )->extraInfo();
-      for ( infoIter = fsrInfo.begin(); infoIter != fsrInfo.end(); infoIter++ ) {
-        // get the key and value of the input info
-        int                      key     = infoIter->first;
-        LHCb::LumiFSR::ValuePair values  = infoIter->second;
-        int                      incr    = values.first;
-        longlong                 count   = values.second;
-        const std::string        keyName = LHCb::LumiCounters::counterKeyToString( key );
-        int                      keyInt  = LHCb::LumiCounters::counterKeyToType( keyName );
-        debug() << "SUM: key: " << key << " name: " << keyName << " KeyInt: " << keyInt << " increment: " << incr
-                << " integral: " << count << endmsg;
-      }
-    }
-  }
   return Consumer::finalize(); // must be called after all other actions
 }
-
-//=============================================================================
-// DB access
-//=============================================================================
-StatusCode LumiAccounting::registerDB() {
-  // register the DB conditions for the update maganer
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Register DB" << endmsg;
-
-  // register thresholds
-  if ( this->existDet<Condition>( "Conditions/Lumi/LHCb/ThresholdCalibration" ) ) {
-    registerCondition( "Conditions/Lumi/LHCb/ThresholdCalibration", m_condThresholds,
-                       &LumiAccounting::i_cacheThresholdData );
-  } else {
-    error() << "Conditions/Lumi/LHCb/ThresholdCalibration not found" << endmsg;
-    m_statusThresholds = 0; // no thresholds
-    return StatusCode::SUCCESS;
-  }
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-//  Extract data from relativeCalibration
-//=========================================================================
-StatusCode LumiAccounting::i_cacheThresholdData() {
-
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "callback ThresholdCalibration:" << endmsg;
-  std::vector<double> cal = m_condThresholds->paramVect<double>( "Thresholds" );
-  if ( cal.size() == m_calibThresholds.size() ) {
-    m_calibThresholds = cal;
-    return StatusCode::SUCCESS;
-  }
-  fatal() << "inconsistent number of parameters in RelativeCalibration:" << cal.size() << endmsg;
-  m_statusThresholds = 0; // no thresholds
-  return StatusCode::SUCCESS;
-}
diff --git a/Rec/LumiAlgs/tests/refs/lumi3conftest.ref b/Rec/LumiAlgs/tests/refs/lumi3conftest.ref
index 92e51d70176..d42099f22a4 100644
--- a/Rec/LumiAlgs/tests/refs/lumi3conftest.ref
+++ b/Rec/LumiAlgs/tests/refs/lumi3conftest.ref
@@ -4,10 +4,6 @@ ApplicationMgr    SUCCESS
 ApplicationMgr       INFO Application Manager Configured successfully
 DetectorPersist...   INFO Added successfully Conversion service:XmlCnvSvc
 DetectorDataSvc   SUCCESS Detector description database: git:/lhcb.xml
-MagneticFieldGridReader INFO  Opened magnetic field file:  DBASE/FieldMap/vXrYpZ/cdf//field101.c1.down.cdf
-MagneticFieldGridReader INFO  Opened magnetic field file:  DBASE/FieldMap/vXrYpZ/cdf//field101.c2.down.cdf
-MagneticFieldGridReader INFO  Opened magnetic field file:  DBASE/FieldMap/vXrYpZ/cdf//field101.c3.down.cdf
-MagneticFieldGridReader INFO  Opened magnetic field file:  DBASE/FieldMap/vXrYpZ/cdf//field101.c4.down.cdf
 LumiSequence         INFO OR Member list: GaudiSequencer/LumiNoBeamSeq, GaudiSequencer/LumiBeamCrossingSeq, GaudiSequencer/LumiBeam1Seq, GaudiSequencer/LumiBeam2Seq, GaudiSequencer/TimeSpanSeq, EventAccounting/EventAccount
 RndmGenSvc.Engine    INFO Generator engine type:CLHEP::RanluxEngine
 RndmGenSvc.Engine    INFO Current Seed:1234567 Luxury:3
@@ -49,259 +45,91 @@ LumiFilter          DEBUG output handles: 0
 LumiFilter          DEBUG Changing Hlt/LumiSummary to /Event/Hlt/LumiSummary
 LumiFilter          DEBUG Data Deps for LumiFilter
   + INPUT  '/Event/Hlt/LumiSummary'
-LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
 LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-LumiCountNoBeam     DEBUG Initialize base class GaudiCommon<Algorithm>
-LumiCountNoBeam     DEBUG could not locate CounterSummarySvc, no counter summary will be made
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'AuditExecute':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'AuditFinalize':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'AuditInitialize':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'AuditStart':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'AuditStop':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'Cardinality':0
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'Context':
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'Enable':True
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'ErrorMax':1
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'FileRecordDataSvc':FileRecordDataSvc
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'InputDataContainer':Hlt/LumiSummary
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'OutputDataContainer':/FileRecords/LumiFSRNoBeam
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'OutputLevel':1
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'RawEventLocation':DAQ/RawEvent
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'RootInTES':
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'TypePrint':True
-LumiCountNoBeam     DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-LumiCountNoBeam     DEBUG LumiAccounting:: The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >' is registered in TS at address '/FileRecords/LumiFSRNoBeam'
-LumiCountNoBeam     DEBUG ==> Register DB
-LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-LumiCountNoBeam     DEBUG input handles: 3
+LumiCountNoBeam   VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+LumiCountNoBeam     DEBUG input handles: 4
 LumiCountNoBeam     DEBUG output handles: 0
 LumiCountNoBeam     DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
 LumiCountNoBeam     DEBUG Changing DAQ/RawEvent to /Event/DAQ/RawEvent
 LumiCountNoBeam     DEBUG Changing Hlt/LumiSummary to /Event/Hlt/LumiSummary
+LumiCountNoBeam     DEBUG Changing IOVLock to /Event/IOVLock
 LumiCountNoBeam     DEBUG Data Deps for LumiCountNoBeam
   + INPUT  '/Event/DAQ/ODIN'
   + INPUT  '/Event/DAQ/RawEvent'
   + INPUT  '/Event/Hlt/LumiSummary'
+  + INPUT  '/Event/IOVLock'
 LumiBeamCrossin...   INFO Member list: LoKi::ODINFilter/FilterBeamCrossing, HltLumiSummaryDecoder, FilterOnLumiSummary/LumiFilter, LumiAccounting/LumiCountBeamCrossing
-LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
 LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-LumiCountBeamCr...  DEBUG Initialize base class GaudiCommon<Algorithm>
-LumiCountBeamCr...  DEBUG could not locate CounterSummarySvc, no counter summary will be made
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'AuditExecute':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'AuditFinalize':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'AuditInitialize':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'AuditStart':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'AuditStop':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'Cardinality':0
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'Context':
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'Enable':True
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'ErrorMax':1
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'FileRecordDataSvc':FileRecordDataSvc
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'InputDataContainer':Hlt/LumiSummary
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'OutputDataContainer':/FileRecords/LumiFSRBeamCrossing
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'OutputLevel':1
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'RawEventLocation':DAQ/RawEvent
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'RootInTES':
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'TypePrint':True
-LumiCountBeamCr...  DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-LumiCountBeamCr...  DEBUG LumiAccounting:: The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >' is registered in TS at address '/FileRecords/LumiFSRBeamCrossing'
-LumiCountBeamCr...  DEBUG ==> Register DB
-LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-LumiCountBeamCr...  DEBUG input handles: 3
+LumiCountBeamCr...VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+LumiCountBeamCr...  DEBUG input handles: 4
 LumiCountBeamCr...  DEBUG output handles: 0
 LumiCountBeamCr...  DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
 LumiCountBeamCr...  DEBUG Changing DAQ/RawEvent to /Event/DAQ/RawEvent
 LumiCountBeamCr...  DEBUG Changing Hlt/LumiSummary to /Event/Hlt/LumiSummary
+LumiCountBeamCr...  DEBUG Changing IOVLock to /Event/IOVLock
 LumiCountBeamCr...  DEBUG Data Deps for LumiCountBeamCrossing
   + INPUT  '/Event/DAQ/ODIN'
   + INPUT  '/Event/DAQ/RawEvent'
   + INPUT  '/Event/Hlt/LumiSummary'
+  + INPUT  '/Event/IOVLock'
 LumiBeam1Seq         INFO Member list: LoKi::ODINFilter/FilterBeam1, HltLumiSummaryDecoder, FilterOnLumiSummary/LumiFilter, FilterFillingScheme/FillingBeam1, LumiAccounting/LumiCountBeam1
-FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
 FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-FillingBeam1        DEBUG Initialize base class GaudiCommon<Algorithm>
-FillingBeam1        DEBUG could not locate CounterSummarySvc, no counter summary will be made
-FillingBeam1        DEBUG Property ['Name': Value] =  'AuditExecute':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'AuditFinalize':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'AuditInitialize':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'AuditStart':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'AuditStop':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'BXOffset':-1
-FillingBeam1        DEBUG Property ['Name': Value] =  'Beam':2
-FillingBeam1        DEBUG Property ['Name': Value] =  'Cardinality':0
-FillingBeam1        DEBUG Property ['Name': Value] =  'Context':
-FillingBeam1        DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-FillingBeam1        DEBUG Property ['Name': Value] =  'Enable':True
-FillingBeam1        DEBUG Property ['Name': Value] =  'ErrorMax':1
-FillingBeam1        DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-FillingBeam1        DEBUG Property ['Name': Value] =  'MagnetState':ALL
-FillingBeam1        DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-FillingBeam1        DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-FillingBeam1        DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-FillingBeam1        DEBUG Property ['Name': Value] =  'OutputLevel':1
-FillingBeam1        DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-FillingBeam1        DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-FillingBeam1        DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-FillingBeam1        DEBUG Property ['Name': Value] =  'RootInTES':
-FillingBeam1        DEBUG Property ['Name': Value] =  'TypePrint':True
-FillingBeam1        DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-FillingBeam1        DEBUG ==> Register DB
-FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-FillingBeam1        DEBUG Conditions/Online/LHCb/LHCFillingScheme
-FillingBeam1        DEBUG Conditions/Online/LHCb/Magnet/Measured
-FillingBeam1        DEBUG input handles: 1
+FillingBeam1      VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+FillingBeam1        DEBUG input handles: 2
 FillingBeam1        DEBUG output handles: 0
 FillingBeam1        DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
+FillingBeam1        DEBUG Changing IOVLock to /Event/IOVLock
 FillingBeam1        DEBUG Data Deps for FillingBeam1
   + INPUT  '/Event/DAQ/ODIN'
-LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
+  + INPUT  '/Event/IOVLock'
 LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-LumiCountBeam1      DEBUG Initialize base class GaudiCommon<Algorithm>
-LumiCountBeam1      DEBUG could not locate CounterSummarySvc, no counter summary will be made
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'AuditExecute':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'AuditFinalize':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'AuditInitialize':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'AuditStart':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'AuditStop':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'Cardinality':0
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'Context':
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'Enable':True
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'ErrorMax':1
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'FileRecordDataSvc':FileRecordDataSvc
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'InputDataContainer':Hlt/LumiSummary
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'OutputDataContainer':/FileRecords/LumiFSRBeam1
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'OutputLevel':1
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'RawEventLocation':DAQ/RawEvent
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'RootInTES':
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'TypePrint':True
-LumiCountBeam1      DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-LumiCountBeam1      DEBUG LumiAccounting:: The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >' is registered in TS at address '/FileRecords/LumiFSRBeam1'
-LumiCountBeam1      DEBUG ==> Register DB
-LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-LumiCountBeam1      DEBUG input handles: 3
+LumiCountBeam1    VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+LumiCountBeam1      DEBUG input handles: 4
 LumiCountBeam1      DEBUG output handles: 0
 LumiCountBeam1      DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
 LumiCountBeam1      DEBUG Changing DAQ/RawEvent to /Event/DAQ/RawEvent
 LumiCountBeam1      DEBUG Changing Hlt/LumiSummary to /Event/Hlt/LumiSummary
+LumiCountBeam1      DEBUG Changing IOVLock to /Event/IOVLock
 LumiCountBeam1      DEBUG Data Deps for LumiCountBeam1
   + INPUT  '/Event/DAQ/ODIN'
   + INPUT  '/Event/DAQ/RawEvent'
   + INPUT  '/Event/Hlt/LumiSummary'
+  + INPUT  '/Event/IOVLock'
 LumiBeam2Seq         INFO Member list: LoKi::ODINFilter/FilterBeam2, HltLumiSummaryDecoder, FilterOnLumiSummary/LumiFilter, FilterFillingScheme/FillingBeam2, LumiAccounting/LumiCountBeam2
-FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
 FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-FillingBeam2        DEBUG Initialize base class GaudiCommon<Algorithm>
-FillingBeam2        DEBUG could not locate CounterSummarySvc, no counter summary will be made
-FillingBeam2        DEBUG Property ['Name': Value] =  'AuditExecute':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'AuditFinalize':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'AuditInitialize':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'AuditStart':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'AuditStop':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'BXOffset':-1
-FillingBeam2        DEBUG Property ['Name': Value] =  'Beam':1
-FillingBeam2        DEBUG Property ['Name': Value] =  'Cardinality':0
-FillingBeam2        DEBUG Property ['Name': Value] =  'Context':
-FillingBeam2        DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-FillingBeam2        DEBUG Property ['Name': Value] =  'Enable':True
-FillingBeam2        DEBUG Property ['Name': Value] =  'ErrorMax':1
-FillingBeam2        DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-FillingBeam2        DEBUG Property ['Name': Value] =  'MagnetState':ALL
-FillingBeam2        DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-FillingBeam2        DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-FillingBeam2        DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-FillingBeam2        DEBUG Property ['Name': Value] =  'OutputLevel':1
-FillingBeam2        DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-FillingBeam2        DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-FillingBeam2        DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-FillingBeam2        DEBUG Property ['Name': Value] =  'RootInTES':
-FillingBeam2        DEBUG Property ['Name': Value] =  'TypePrint':True
-FillingBeam2        DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-FillingBeam2        DEBUG ==> Register DB
-FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-FillingBeam2        DEBUG Conditions/Online/LHCb/LHCFillingScheme
-FillingBeam2        DEBUG Conditions/Online/LHCb/Magnet/Measured
-FillingBeam2        DEBUG input handles: 1
+FillingBeam2      VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+FillingBeam2        DEBUG input handles: 2
 FillingBeam2        DEBUG output handles: 0
 FillingBeam2        DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
+FillingBeam2        DEBUG Changing IOVLock to /Event/IOVLock
 FillingBeam2        DEBUG Data Deps for FillingBeam2
   + INPUT  '/Event/DAQ/ODIN'
-LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
+  + INPUT  '/Event/IOVLock'
 LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
 LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service TimelineSvc
 LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service EventDataSvc
-LumiCountBeam2      DEBUG Initialize base class GaudiCommon<Algorithm>
-LumiCountBeam2      DEBUG could not locate CounterSummarySvc, no counter summary will be made
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'AuditExecute':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'AuditFinalize':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'AuditInitialize':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'AuditStart':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'AuditStop':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'Cardinality':0
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'Context':
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'CounterList':[ '.*' ]
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'Enable':True
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'ErrorMax':1
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'ErrorsPrint':True
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'FileRecordDataSvc':FileRecordDataSvc
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'InputDataContainer':Hlt/LumiSummary
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'MonitorService':MonitorSvc
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'NeededResources':[  ]
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'ODINLocation':DAQ/ODIN
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'OutputDataContainer':/FileRecords/LumiFSRBeam2
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'OutputLevel':1
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'PropertiesPrint':False
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'RawEventLocation':DAQ/RawEvent
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'RegisterForContextService':True
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'RequireObjects':[  ]
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'RootInTES':
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'TypePrint':True
-LumiCountBeam2      DEBUG Property ['Name': Value] =  'VetoObjects':[  ]
-LumiCountBeam2      DEBUG LumiAccounting:: The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >' is registered in TS at address '/FileRecords/LumiFSRBeam2'
-LumiCountBeam2      DEBUG ==> Register DB
-LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service DetectorDataSvc
-LumiCountBeam2      DEBUG input handles: 3
+LumiCountBeam2    VERBOSE ServiceLocatorHelper::service: found service UpdateManagerSvc
+LumiCountBeam2      DEBUG input handles: 4
 LumiCountBeam2      DEBUG output handles: 0
 LumiCountBeam2      DEBUG Changing DAQ/ODIN to /Event/DAQ/ODIN
 LumiCountBeam2      DEBUG Changing DAQ/RawEvent to /Event/DAQ/RawEvent
 LumiCountBeam2      DEBUG Changing Hlt/LumiSummary to /Event/Hlt/LumiSummary
+LumiCountBeam2      DEBUG Changing IOVLock to /Event/IOVLock
 LumiCountBeam2      DEBUG Data Deps for LumiCountBeam2
   + INPUT  '/Event/DAQ/ODIN'
   + INPUT  '/Event/DAQ/RawEvent'
   + INPUT  '/Event/Hlt/LumiSummary'
+  + INPUT  '/Event/IOVLock'
 TimeSpanSeq          INFO Member list: LoKi::ODINFilter/TimeSpanFilter, TimeAccounting/TimeSpanAccounting
 TimeSpanAccountingVERBOSE ServiceLocatorHelper::service: found service AlgContextSvc
 TimeSpanAccountingVERBOSE ServiceLocatorHelper::service: found service EventDataSvc
@@ -358,48 +186,14 @@ ApplicationMgr       INFO Application Manager Stopped successfully
 LumiFilter          DEBUG Finalize base class GaudiAlgorithm
 LumiFilter          DEBUG Tools to release :
 LumiFilter          DEBUG Services to release :
-LumiCountNoBeam     DEBUG ==> Finalize
 LumiCountNoBeam      INFO number of files seen: 0
-LumiCountNoBeam   VERBOSE FSR: {  runs :  files :  info (key/incr/integral) :  }
 LumiCountNoBeam      INFO INTEGRAL: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountNoBeam     DEBUG The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >*' has been retrieved from TS at address '/FileRecords/LumiFSRNoBeam'
-LumiCountNoBeam     DEBUG READ FSR: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountNoBeam     DEBUG Finalize base class GaudiAlgorithm
-LumiCountNoBeam     DEBUG Tools to release :
-LumiCountNoBeam     DEBUG Services to release :
-LumiCountBeamCr...  DEBUG ==> Finalize
 LumiCountBeamCr...   INFO number of files seen: 0
-LumiCountBeamCr...VERBOSE FSR: {  runs :  files :  info (key/incr/integral) :  }
 LumiCountBeamCr...   INFO INTEGRAL: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeamCr...  DEBUG The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >*' has been retrieved from TS at address '/FileRecords/LumiFSRBeamCrossing'
-LumiCountBeamCr...  DEBUG READ FSR: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeamCr...  DEBUG Finalize base class GaudiAlgorithm
-LumiCountBeamCr...  DEBUG Tools to release :
-LumiCountBeamCr...  DEBUG Services to release :
-FillingBeam1        DEBUG Finalize base class GaudiAlgorithm
-FillingBeam1        DEBUG Tools to release :
-FillingBeam1        DEBUG Services to release :
-LumiCountBeam1      DEBUG ==> Finalize
 LumiCountBeam1       INFO number of files seen: 0
-LumiCountBeam1    VERBOSE FSR: {  runs :  files :  info (key/incr/integral) :  }
 LumiCountBeam1       INFO INTEGRAL: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeam1      DEBUG The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >*' has been retrieved from TS at address '/FileRecords/LumiFSRBeam1'
-LumiCountBeam1      DEBUG READ FSR: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeam1      DEBUG Finalize base class GaudiAlgorithm
-LumiCountBeam1      DEBUG Tools to release :
-LumiCountBeam1      DEBUG Services to release :
-FillingBeam2        DEBUG Finalize base class GaudiAlgorithm
-FillingBeam2        DEBUG Tools to release :
-FillingBeam2        DEBUG Services to release :
-LumiCountBeam2      DEBUG ==> Finalize
 LumiCountBeam2       INFO number of files seen: 0
-LumiCountBeam2    VERBOSE FSR: {  runs :  files :  info (key/incr/integral) :  }
 LumiCountBeam2       INFO INTEGRAL: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeam2      DEBUG The object of type 'KeyedContainer<LHCb::LumiFSR,Containers::KeyedObjectManager<Containers::hashmap> >*' has been retrieved from TS at address '/FileRecords/LumiFSRBeam2'
-LumiCountBeam2      DEBUG READ FSR: {  runs :  files :  info (key/incr/integral) :  }
-LumiCountBeam2      DEBUG Finalize base class GaudiAlgorithm
-LumiCountBeam2      DEBUG Tools to release :
-LumiCountBeam2      DEBUG Services to release :
 TimeSpanAccounting  DEBUG ==> Finalize
 TimeSpanAccounting   INFO number of files seen: 0
 TimeSpanAccounting   INFO FSR: {  earliest : 0 - latest : 0 }
-- 
GitLab


From 58a13ae4f9d0b1f0caf6c3e38e8c4eeba79f3c2e Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 16:33:06 +0200
Subject: [PATCH 20/26] Dropped unused Loki functor DistanceToBeamLine

---
 Phys/LoKiPhys/CMakeLists.txt                  |   1 -
 .../LoKiPhys/include/LoKi/BeamLineFunctions.h | 167 ------------------
 Phys/LoKiPhys/python/LoKiPhys/functions.py    |   1 -
 Phys/LoKiPhys/src/BeamLineFunctions.cpp       | 137 --------------
 4 files changed, 306 deletions(-)
 delete mode 100644 Phys/LoKiPhys/include/LoKi/BeamLineFunctions.h
 delete mode 100644 Phys/LoKiPhys/src/BeamLineFunctions.cpp

diff --git a/Phys/LoKiPhys/CMakeLists.txt b/Phys/LoKiPhys/CMakeLists.txt
index 85224cba71b..906b33f4b68 100644
--- a/Phys/LoKiPhys/CMakeLists.txt
+++ b/Phys/LoKiPhys/CMakeLists.txt
@@ -17,7 +17,6 @@ gaudi_add_library(LoKiPhysLib
     SOURCES
         src/AuxDTFBase.cpp
         src/AuxDesktopBase.cpp
-        src/BeamLineFunctions.cpp
         src/Child.cpp
         src/ChildSelector.cpp
         src/DecayChain.cpp
diff --git a/Phys/LoKiPhys/include/LoKi/BeamLineFunctions.h b/Phys/LoKiPhys/include/LoKi/BeamLineFunctions.h
deleted file mode 100644
index 3ac488409ac..00000000000
--- a/Phys/LoKiPhys/include/LoKi/BeamLineFunctions.h
+++ /dev/null
@@ -1,167 +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 LOKI_BEAMLINEFUNCTIONS_H
-#  define LOKI_BEAMLINEFUNCTIONS_H 1
-// ============================================================================
-// Include files
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-// Event
-// ============================================================================
-#  include "Event/Particle.h"
-#  include "Event/Track.h"
-#  include "Event/VertexBase.h"
-#  include "GaudiKernel/IUpdateManagerSvc.h"
-#  include "GaudiKernel/SmartRef.h"
-// ============================================================================
-// LoKi
-// ============================================================================
-#  include "LoKi/BasicFunctors.h"
-#  include "LoKi/BeamSpot.h"
-#  include "LoKi/Interface.h"
-#  include "LoKi/ParticleCuts.h"
-// ============================================================================
-/** @file
- *  Collection of "beam-line"-related functors
- *
- *  This file is part of LoKi project:
- *   ``C++ ToolKit for Smart and Friendly Physics Analysis''
- *
- *  The package has been designed with the kind help from
- *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
- *  contributions and advices from G.Raven, J.van Tilburg,
- *  A.Golutvin, P.Koppenburg have been used in the design.
- *
- *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
- *  @date   2011-03-10
- */
-// ============================================================================
-namespace LoKi {
-  // ==========================================================================
-  namespace Vertices {
-    // ========================================================================
-    /** @class BeamSpotRho
-     *
-     *  functor to evaluate the radial distance ("rho") with respect to
-     *  the middle of Velo as measured by the X and Y resolvers
-     *
-     *  @attention if the velo is opened return -1.
-     *
-     *  @see LoKi::Cuts::VX_BEAMSPOTRHO
-     *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
-     *  @author Victor COCO   Victor.Coco@cern.ch
-     *  @date   2011-03-10
-     */
-    class GAUDI_API BeamSpotRho : public LoKi::BeamSpot, public LoKi::BasicFunctors<const LHCb::VertexBase*>::Function {
-    public:
-      // ======================================================================
-      /// Constructor from resolver bouns
-      BeamSpotRho( const double bound );
-      /// Constructor from resolved bound and condition name
-      BeamSpotRho( const double bound, const std::string& condname );
-      /// MANDATORY: virtual destructor
-      virtual ~BeamSpotRho();
-      // ======================================================================
-    public:
-      // ======================================================================
-      /** MANDATORY: clone method ("virtual constructor")
-       *  @attention if the velo is opened return -1
-       */
-      BeamSpotRho* clone() const override;
-      /// MANDATORY: the only one essential method
-      result_type operator()( argument v ) const override;
-      /// OPTIONAL: nice printout
-      std::ostream& fillStream( std::ostream& s ) const override;
-      // ======================================================================
-    private:
-      // ======================================================================
-      /// default constructor is disabled
-      BeamSpotRho(); // default constructor is disabled
-      // ======================================================================
-    };
-    // ========================================================================
-  } // namespace Vertices
-  // ==========================================================================
-
-  // ==========================================================================
-  namespace Particles {
-    // ========================================================================
-    /** @class DistanceToBeamLine
-     *
-     *  functor to evaluate the signed distance with respect to the axis
-     *  through the middle of Velo as measured by the X and Y resolvers.
-     *
-     *  @attention returns the signed distance.
-     *
-     *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
-     *  @author Victor COCO   Victor.Coco@cern.ch
-     *  @author Wouter Hulsbergen
-     *  @date   2018-01-12
-     */
-    class GAUDI_API DistanceToBeamLine : public LoKi::BeamSpot,
-                                         public LoKi::BasicFunctors<const LHCb::Particle*>::Function {
-    public:
-      // ======================================================================
-      // ======================================================================
-      /// default constructor
-      DistanceToBeamLine();
-      /// MANDATORY: virtual destructor
-      virtual ~DistanceToBeamLine();
-      // ======================================================================
-    public:
-      // ======================================================================
-      /** MANDATORY: clone method ("virtual constructor")
-       *  @attention if the velo is opened return -1
-       */
-      DistanceToBeamLine* clone() const override;
-      /// MANDATORY: the only one essential method
-      result_type operator()( argument p ) const override;
-      /// OPTIONAL: nice printout
-      std::ostream& fillStream( std::ostream& s ) const override;
-      // ======================================================================
-    private:
-      /// Cut to select only particles with track daughters in tree
-      Types::Cut m_cut;
-      // ======================================================================
-    };
-    // ========================================================================
-  } // namespace Particles
-  // ==========================================================================
-  namespace Cuts {
-    // ========================================================================
-    /** @typedef  VX_BEAMSPOTRHO
-     *  functor to evaluate the radial distance ("rho") with respect to
-     *  the middle of Velo as measured by the X and Y resolvers
-     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
-     *  @author Victor COCO   Victor.Coco@cern.ch
-     *  @date 2011-03-11
-     */
-    typedef LoKi::Vertices::BeamSpotRho VX_BEAMSPOTRHO;
-    // ========================================================================
-    /** @typedef  BEAMLINEDOCA
-     *  functor to evaluate the signed distance with respect to the axis
-     *  through the middle of Velo as measured by the X and Y resolvers.
-     *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
-     *  @author Victor COCO   Victor.Coco@cern.ch
-     *  @author Wouter Hulsbergen
-     *  @date 2018-01-12
-     */
-    typedef LoKi::Particles::DistanceToBeamLine BEAMLINEDOCA;
-    // ========================================================================
-  } // namespace Cuts
-  // ==========================================================================
-} //                                                      end of namespace LoKi
-// ============================================================================
-//                                                                      The END
-// ============================================================================
-#endif // LOKI_BEAMLINEFUNCTIONS_H
-// ============================================================================
diff --git a/Phys/LoKiPhys/python/LoKiPhys/functions.py b/Phys/LoKiPhys/python/LoKiPhys/functions.py
index 1de9c9f660b..0a52832c3d1 100755
--- a/Phys/LoKiPhys/python/LoKiPhys/functions.py
+++ b/Phys/LoKiPhys/python/LoKiPhys/functions.py
@@ -796,7 +796,6 @@ MASSFIT = LoKi.Particles.MassFitter
 # =============================================================================
 BEAMSPOT = LoKi.BeamSpot
 VX_BEAMSPOTRHO = LoKi.Vertices.BeamSpotRho
-BEAMLINEDOCA = LoKi.Particles.DistanceToBeamLine
 
 # =============================================================================
 ## nodes & trees
diff --git a/Phys/LoKiPhys/src/BeamLineFunctions.cpp b/Phys/LoKiPhys/src/BeamLineFunctions.cpp
deleted file mode 100644
index 6286b05cf05..00000000000
--- a/Phys/LoKiPhys/src/BeamLineFunctions.cpp
+++ /dev/null
@@ -1,137 +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
-// ============================================================================
-// STD & STD
-// ============================================================================
-#include <cmath>
-// ============================================================================
-// LoKi
-// ============================================================================
-#include "LoKi/BeamLineFunctions.h"
-#include "LoKi/Constants.h"
-#include "LoKi/ILoKiSvc.h"
-// ============================================================================
-/** @file
- *  Collection of "beam-line"-related functors
- *
- *  This file is part of LoKi project:
- *   ``C++ ToolKit for Smart and Friendly Physics Analysis''
- *
- *  The package has been designed with the kind help from
- *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
- *  contributions and advices from G.Raven, J.van Tilburg,
- *  A.Golutvin, P.Koppenburg have been used in the design.
- *
- *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
- *  @date   2011-03-10
- */
-// ============================================================================
-// Constructor from bound
-// ============================================================================
-LoKi::Vertices::BeamSpotRho::BeamSpotRho( const double bound )
-    : LoKi::AuxFunBase( std::tie( bound ) )
-    , LoKi::BeamSpot( bound )
-    , LoKi::BasicFunctors<const LHCb::VertexBase*>::Function() {}
-// ============================================================================
-// Constructor from bound & condname
-// ============================================================================
-LoKi::Vertices::BeamSpotRho::BeamSpotRho( const double bound, const std::string& condname )
-    : LoKi::AuxFunBase( std::tie( bound, condname ) )
-    , LoKi::BeamSpot( bound, condname )
-    , LoKi::BasicFunctors<const LHCb::VertexBase*>::Function() {}
-// ============================================================================
-// MANDATORY: virtual destructor
-// ============================================================================
-LoKi::Vertices::BeamSpotRho::~BeamSpotRho() {}
-// ============================================================================
-// MANDATOTY: clone method ("virtual constructor")
-// ============================================================================
-LoKi::Vertices::BeamSpotRho* LoKi::Vertices::BeamSpotRho::clone() const {
-  return new LoKi::Vertices::BeamSpotRho( *this );
-}
-// ============================================================================
-// MANDATORY: the only one essential method
-// ============================================================================
-LoKi::Vertices::BeamSpotRho::result_type LoKi::Vertices::BeamSpotRho::
-                                         operator()( LoKi::Vertices::BeamSpotRho::argument v ) const {
-  if ( 0 == v ) {
-    Error( "invalid argument, return InvalidDistance" ).ignore();
-    return LoKi::Constants::InvalidDistance;
-  }
-  //
-  // if the velo is opened ( x resolver position > m_resolverBound ) return -1.
-  //
-  if ( !closed() ) { return -1; } // RETURN
-  //
-  // return radial distance from vertex to beam spot
-  //
-  const double x_diff = v->position().x() - x();
-  const double y_diff = v->position().y() - y();
-  //
-  return std::sqrt( x_diff * x_diff + y_diff * y_diff );
-}
-// ============================================================================
-// OPTIONAL: nice printout
-// ============================================================================
-std::ostream& LoKi::Vertices::BeamSpotRho::fillStream( std::ostream& s ) const {
-  s << "VX_BEAMSPOTRHO(" << resolverBound() << "";
-  s << ",'" << condName() << "'";
-  return s << ")";
-}
-// ============================================================================
-// The END
-// ============================================================================
-
-// ============================================================================
-// Default constructor
-// ============================================================================
-LoKi::Particles::DistanceToBeamLine::DistanceToBeamLine()
-    : LoKi::AuxFunBase( std::tie() )
-    , LoKi::BeamSpot( 0 )
-    , LoKi::BasicFunctors<const LHCb::Particle*>::Function()
-    , m_cut{Cuts::INTREE( Cuts::HASTRACK )} {}
-// ============================================================================
-// MANDATORY: virtual destructor
-// ============================================================================
-LoKi::Particles::DistanceToBeamLine::~DistanceToBeamLine() {}
-// ============================================================================
-// MANDATORY: clone method ("virtual constructor")
-// ============================================================================
-LoKi::Particles::DistanceToBeamLine* LoKi::Particles::DistanceToBeamLine::clone() const {
-  return new LoKi::Particles::DistanceToBeamLine( *this );
-}
-// ============================================================================
-// MANDATORY: the only one essential method
-// ============================================================================
-LoKi::Particles::DistanceToBeamLine::result_type LoKi::Particles::DistanceToBeamLine::
-                                                 operator()( LoKi::Particles::DistanceToBeamLine::argument p ) const {
-  if ( 0 == p ) {
-    Error( "invalid argument, return InvalidDistance" ).ignore();
-    return LoKi::Constants::InvalidDistance;
-  }
-  if ( !m_cut.fun( p ) ) return 0.0;
-
-  // return signed distance between particle trajectory and beam line
-  const auto tx = p->momentum().Px() /* / p->momentum().Pz() */;
-  const auto ty = p->momentum().Py() /*/ p->momentum().Pz() */;
-  const auto dx = p->referencePoint().x() - x();
-  const auto dy = p->referencePoint().y() - y();
-  return ( dx * ty - dy * tx ) / std::sqrt( tx * tx + ty * ty );
-}
-// ============================================================================
-// OPTIONAL: nice printout
-// ============================================================================
-std::ostream& LoKi::Particles::DistanceToBeamLine::fillStream( std::ostream& s ) const { return s << "BEAMLINEDOCA()"; }
-// ============================================================================
-// The END
-// ============================================================================
-- 
GitLab


From 9b3dd5f6690d358541619bdd3be61b3d2786ba1f Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Mon, 3 Oct 2022 16:37:04 +0200
Subject: [PATCH 21/26] Dropped unused Loki functors FastDOCAToBeamLine and
 BeamSpot

---
 Phys/LoKiPhys/include/LoKi/LoKiPhys.h         |   2 -
 Phys/LoKiPhys/include/LoKi/LoKiPhys_dct.h     |   1 -
 Phys/LoKiPhys/python/LoKiPhys/functions.py    |   6 -
 Phys/LoKiPhys/src/LoKiPhys.cpp                |   1 -
 Phys/LoKiTracks/include/LoKi/Tracks.h         |  98 ++-------
 .../LoKiTracks/python/LoKiTracks/functions.py |   3 -
 Phys/LoKiTracks/src/Tracks.cpp                |  41 ----
 Phys/LoKiUtils/CMakeLists.txt                 |   1 -
 Phys/LoKiUtils/dict/LoKiUtils.xml             |  10 +-
 Phys/LoKiUtils/dict/LoKiUtilsDict.h           |   1 -
 Phys/LoKiUtils/include/LoKi/BeamSpot.h        | 121 -----------
 Phys/LoKiUtils/src/BeamSpot.cpp               | 191 ------------------
 12 files changed, 16 insertions(+), 460 deletions(-)
 delete mode 100644 Phys/LoKiUtils/include/LoKi/BeamSpot.h
 delete mode 100644 Phys/LoKiUtils/src/BeamSpot.cpp

diff --git a/Phys/LoKiPhys/include/LoKi/LoKiPhys.h b/Phys/LoKiPhys/include/LoKi/LoKiPhys.h
index 1d7fea06e89..34be9051d78 100644
--- a/Phys/LoKiPhys/include/LoKi/LoKiPhys.h
+++ b/Phys/LoKiPhys/include/LoKi/LoKiPhys.h
@@ -78,8 +78,6 @@
 #  include "LoKi/Particles47.h"
 #  include "LoKi/Particles48.h"
 //
-#  include "LoKi/BeamLineFunctions.h"
-//
 //
 #  include "LoKi/Vertices.h"
 #  include "LoKi/Vertices0.h"
diff --git a/Phys/LoKiPhys/include/LoKi/LoKiPhys_dct.h b/Phys/LoKiPhys/include/LoKi/LoKiPhys_dct.h
index ddcd806481f..cf498bbd58a 100644
--- a/Phys/LoKiPhys/include/LoKi/LoKiPhys_dct.h
+++ b/Phys/LoKiPhys/include/LoKi/LoKiPhys_dct.h
@@ -54,7 +54,6 @@
 #  include "LoKi/PrintDecay.h"
 #  include "LoKi/Sections.h"
 // ============================================================================
-#  include "LoKi/BeamLineFunctions.h"
 #  include "LoKi/ParticleContextCuts.h"
 #  include "LoKi/PhysDump.h"
 #  include "LoKi/PhysSinks.h"
diff --git a/Phys/LoKiPhys/python/LoKiPhys/functions.py b/Phys/LoKiPhys/python/LoKiPhys/functions.py
index 0a52832c3d1..20678ea8f39 100755
--- a/Phys/LoKiPhys/python/LoKiPhys/functions.py
+++ b/Phys/LoKiPhys/python/LoKiPhys/functions.py
@@ -791,12 +791,6 @@ MASSFIT = LoKi.Particles.MassFitter
 ## @see LoKi::Cuts::DPCTAUSIGNIFICANCE
 ## DPCTAUSIGNIFICANCE = LoKi.Legacy.DaughterParticleCTauSignificance
 
-# =============================================================================
-# moved form LoKi-Trigger
-# =============================================================================
-BEAMSPOT = LoKi.BeamSpot
-VX_BEAMSPOTRHO = LoKi.Vertices.BeamSpotRho
-
 # =============================================================================
 ## nodes & trees
 # =============================================================================
diff --git a/Phys/LoKiPhys/src/LoKiPhys.cpp b/Phys/LoKiPhys/src/LoKiPhys.cpp
index 061997df60b..109e3fdc8e7 100644
--- a/Phys/LoKiPhys/src/LoKiPhys.cpp
+++ b/Phys/LoKiPhys/src/LoKiPhys.cpp
@@ -25,7 +25,6 @@
 #include "LoKi/ATypes.h"
 #include "LoKi/AuxDTFBase.h"
 #include "LoKi/AuxDesktopBase.h"
-#include "LoKi/BeamLineFunctions.h"
 #include "LoKi/Child.h"
 #include "LoKi/ChildSelector.h"
 #include "LoKi/CompareParticles.h"
diff --git a/Phys/LoKiTracks/include/LoKi/Tracks.h b/Phys/LoKiTracks/include/LoKi/Tracks.h
index 8ccac24beb0..922e27847d0 100644
--- a/Phys/LoKiTracks/include/LoKi/Tracks.h
+++ b/Phys/LoKiTracks/include/LoKi/Tracks.h
@@ -8,36 +8,22 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-// ============================================================================
-#ifndef LOKI_TRACKS_H
-#  define LOKI_TRACKS_H 1
-// ============================================================================
-// Include files
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-#  include "GaudiKernel/Kernel.h"
-// ============================================================================
-// Event
-// ============================================================================
-#  include "Event/Track.h"
-// ============================================================================
-// Track Interfaces
-// ============================================================================
-#  include "TrackInterfaces/ITrackSelector.h"
-// ============================================================================
-// LoKi
-// ============================================================================
-#  include "LoKi/BeamSpot.h"
-#  include "LoKi/ExtraInfo.h"
-#  include "LoKi/Interface.h"
-#  include "LoKi/Track.h"
-#  include "LoKi/TrackTypes.h"
-// ============================================================================
-#  include "KalmanFilter/FastVertex.h"
-// ============================================================================
+#pragma once
+
+#include "Event/Track.h"
+#include "TrackInterfaces/ITrackSelector.h"
+
+#include "LoKi/ExtraInfo.h"
+#include "LoKi/Interface.h"
+#include "LoKi/Track.h"
+#include "LoKi/TrackTypes.h"
+
+#include "KalmanFilter/FastVertex.h"
+
+#include "GaudiKernel/Kernel.h"
+
 namespace LoKi {
-  // ==========================================================================
+
   /** @namespace LoKi::Tracks Tracks.h LoKi/Tracks.h
    *  Namespace with few basic "track"-functors
    *  @see LHCb::Track
@@ -91,60 +77,6 @@ namespace LoKi {
       std::string m_nick; // the tool typename
       // ======================================================================
     };
-    // ========================================================================
-    /**
-     *  @class FastDOCAToBeamLine
-     *  use TTrDOCA and BEAMSPOT to evaluate the closest distance of a track to
-     *  the beam line, similar to BEAMSPOTRHO
-     *  @see LoKi::BeamSpot
-     *  @see LoKi::Cuts::VX_BEAMSPOTRHO
-     *  @author Pieter David pieter.david@cern.ch
-     *  @date 2012-02-24
-     */
-    class GAUDI_API FastDOCAToBeamLine : LoKi::BeamSpot, public LoKi::BasicFunctors<const LHCb::Track*>::Function {
-    public:
-      // =====================================================================
-      /// Constructor from resolver bound
-      FastDOCAToBeamLine( const double bound );
-      /// Constructor from resolved bound and condition name
-      FastDOCAToBeamLine( const double bound, const std::string& condname );
-      /// update the condition
-      StatusCode updateCondition() override;
-      /// MANDATORY: clone method ("virtual constructor")
-      FastDOCAToBeamLine* clone() const override { return new FastDOCAToBeamLine( *this ); }
-      /// MANDATORY: the only one essential method
-      result_type operator()( argument v ) const override;
-      /// OPTIONAL: nice printout
-      std::ostream& fillStream( std::ostream& s ) const override { return s << "Tr_FASTDOCATOBEAMLINE"; }
-
-    private:
-      /// beamline
-      LoKi::FastVertex::Line m_beamLine;
-    };
-    // ========================================================================
   } // namespace Tracks
-  namespace Cuts {
-    // ========================================================================
-    /** @typedef  Tr_FASTDOCATOBEAMLINE
-     *  Fast DOCA to beam line using TTrDOCA and BEAMSPOT, similar to the
-     *  BEAMSPOTRHO cut
-     *  @see LoKi::Cuts::TTrDOCA
-     *  @see HltUtils::closestDistanceMod
-     *  @see LoKi::Tracks::DistanceOfClosestApproach
-     *  @see LoKi::BeamSpot
-     *  @see LoKi::Cuts::BEAMSPOT
-     *  @see LoKi::Vertices::BeamSpotRho
-     *  @see LoKi::Cuts::BEAMSPOTRHO
-     *  @author Pieter David pieter.david@cern.ch
-     *  @date 2012-02-24
-     */
-    typedef LoKi::Tracks::FastDOCAToBeamLine Tr_FASTDOCATOBEAMLINE;
-    // ========================================================================
-  } // namespace Cuts
   // ==========================================================================
 } //                                                      end of namespace LoKi
-// ============================================================================
-// The END
-// ============================================================================
-#endif // LOKI_TRACKS_H
-// ============================================================================
diff --git a/Phys/LoKiTracks/python/LoKiTracks/functions.py b/Phys/LoKiTracks/python/LoKiTracks/functions.py
index d500b1ca0a2..e28fd8a2785 100644
--- a/Phys/LoKiTracks/python/LoKiTracks/functions.py
+++ b/Phys/LoKiTracks/python/LoKiTracks/functions.py
@@ -46,9 +46,6 @@ import LoKiCore.decorators as _LoKiCore
 from LoKiCore.basic import cpp, std, LoKi
 LHCb = cpp.LHCb
 
-## @see LoKi::Tracks::FastDOCAToBeamLine
-Tr_FASTDOCATOBEAMLINE = LoKi.Tracks.FastDOCAToBeamLine
-
 ## @see LoKi::Tracks::TrFILTER
 TrFILTER = LoKi.Tracks.Filter
 ## @see LoKi::Tracks::Tr_FILTER
diff --git a/Phys/LoKiTracks/src/Tracks.cpp b/Phys/LoKiTracks/src/Tracks.cpp
index 08ac19d2a6a..672dace133a 100644
--- a/Phys/LoKiTracks/src/Tracks.cpp
+++ b/Phys/LoKiTracks/src/Tracks.cpp
@@ -79,44 +79,3 @@ LoKi::Tracks::Filter::result_type LoKi::Tracks::Filter::operator()( LoKi::Tracks
 // ============================================================================
 std::ostream& LoKi::Tracks::Filter::fillStream( std::ostream& s ) const { return s << "TrFILTER('" << m_nick << "')"; }
 // ============================================================================
-
-// ============================================================================
-// Constructor from bound
-// ============================================================================
-LoKi::Tracks::FastDOCAToBeamLine::FastDOCAToBeamLine( const double bound )
-    : LoKi::AuxFunBase( std::tie( bound ) )
-    , LoKi::BeamSpot( bound )
-    , LoKi::BasicFunctors<const LHCb::Track*>::Function()
-    , m_beamLine() {}
-// ============================================================================
-// Constructor from bound & condname
-// ============================================================================
-LoKi::Tracks::FastDOCAToBeamLine::FastDOCAToBeamLine( const double bound, const std::string& condname )
-    : LoKi::AuxFunBase( std::tie( bound, condname ) )
-    , LoKi::BeamSpot( bound, condname )
-    , LoKi::BasicFunctors<const LHCb::Track*>::Function()
-    , m_beamLine() {}
-// ============================================================================
-// Update beamspot position
-// ============================================================================
-StatusCode LoKi::Tracks::FastDOCAToBeamLine::updateCondition() {
-  StatusCode sc = LoKi::BeamSpot::updateCondition();
-  if ( sc.isFailure() ) { return sc; } // RETURN
-  //
-  m_beamLine = LoKi::FastVertex::Line( Gaudi::XYZPoint( x(), y(), 0. ), Gaudi::XYZVector( 0., 0., 1. ) );
-  //
-  return sc;
-}
-// ============================================================================
-// MANDATORY: the only one essential method
-// ============================================================================
-LoKi::Tracks::FastDOCAToBeamLine::result_type LoKi::Tracks::FastDOCAToBeamLine::
-                                              operator()( LoKi::Tracks::FastDOCAToBeamLine::argument t ) const {
-  double doca;
-  LoKi::FastVertex::distance( t, m_beamLine, doca ).ignore();
-  return doca;
-}
-
-// ============================================================================
-// The END
-// ============================================================================
diff --git a/Phys/LoKiUtils/CMakeLists.txt b/Phys/LoKiUtils/CMakeLists.txt
index 90a300737d7..b6ae2883730 100644
--- a/Phys/LoKiUtils/CMakeLists.txt
+++ b/Phys/LoKiUtils/CMakeLists.txt
@@ -15,7 +15,6 @@ Phys/LoKiUtils
 
 gaudi_add_library(LoKiUtils
     SOURCES
-        src/BeamSpot.cpp
         src/GetTools.cpp
     LINK
         PUBLIC
diff --git a/Phys/LoKiUtils/dict/LoKiUtils.xml b/Phys/LoKiUtils/dict/LoKiUtils.xml
index b00d04666b2..fbcbc704ee9 100644
--- a/Phys/LoKiUtils/dict/LoKiUtils.xml
+++ b/Phys/LoKiUtils/dict/LoKiUtils.xml
@@ -31,14 +31,6 @@
 <lcgdict>
   
   <class name = "LoKi::GetTools" />
-  <class name = "LoKi::BeamSpot" />
-  
-  <exclusion>
-    <class    name = "LoKi::BeamSpot">
-      <method name = "="           />
-      <field  name = "m_condition" />
-    </class>
-  </exclusion>
   
 </lcgdict>
 
@@ -46,4 +38,4 @@
      * ========================================================================
      * The END 
      * ========================================================================
--->
\ No newline at end of file
+-->
diff --git a/Phys/LoKiUtils/dict/LoKiUtilsDict.h b/Phys/LoKiUtils/dict/LoKiUtilsDict.h
index c0cb908a6a6..87609ab1cca 100644
--- a/Phys/LoKiUtils/dict/LoKiUtilsDict.h
+++ b/Phys/LoKiUtils/dict/LoKiUtilsDict.h
@@ -16,7 +16,6 @@
 // ============================================================================
 // LoKi
 // ============================================================================
-#  include "LoKi/BeamSpot.h"
 #  include "LoKi/GetTools.h"
 // ============================================================================
 
diff --git a/Phys/LoKiUtils/include/LoKi/BeamSpot.h b/Phys/LoKiUtils/include/LoKi/BeamSpot.h
deleted file mode 100644
index 017c66255a1..00000000000
--- a/Phys/LoKiUtils/include/LoKi/BeamSpot.h
+++ /dev/null
@@ -1,121 +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 LOKI_BEAMSPOT_H
-#  define LOKI_BEAMSPOT_H 1
-// ============================================================================
-// Include files
-// ============================================================================
-// GaudiKernel
-#  include "GaudiKernel/IUpdateManagerSvc.h"
-#  include "GaudiKernel/SmartRef.h"
-// ============================================================================
-// Event
-// ============================================================================
-#  include "Event/Track.h"
-#  include "Event/VertexBase.h"
-// ============================================================================
-// LoKi
-// ============================================================================
-#  include "LoKi/BasicFunctors.h"
-#  include "LoKi/Interface.h"
-// ============================================================================
-// Condition
-// ============================================================================
-#  include "DetDesc/Condition.h"
-// ============================================================================
-/** @file
- *  Collection of "beam-line"-related functors
- *
- *  This file is part of LoKi project:
- *   ``C++ ToolKit for Smart and Friendly Physics Analysis''
- *
- *  The package has been designed with the kind help from
- *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
- *  contributions and advices from G.Raven, J.van Tilburg,
- *  A.Golutvin, P.Koppenburg have been used in the design.
- *
- *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
- *  @date   2011-03-10
- */
-// ============================================================================
-namespace LoKi {
-  // ========================================================================
-  /** @class BeamSpot
-   *
-   *  functor to pick up the beamspot position
-   *  the middle of Velo as measured by the X and Y resolvers
-   *
-   *  @see LoKi::Cuts::BEAMSPOT
-   *  @author Vanya Belyaev Ivan.Belyaev@cern.ch
-   *  @author Victor COCO   Victor.Coco@cern.ch
-   *  @date   2011-03-10
-   */
-  class GAUDI_API BeamSpot : virtual public LoKi::AuxFunBase {
-  public:
-    // ======================================================================
-    /// Constructor from bound
-    BeamSpot( const double bound );
-    /// Constructor from bound and condition name
-    BeamSpot( const double bound, const std::string& condname );
-    /// Copy constructor
-    BeamSpot( const BeamSpot& );
-    /// MANDATORY: virtual destructor
-    virtual ~BeamSpot();
-    // ======================================================================
-  public:
-    // ======================================================================
-    /// update the condition
-    virtual StatusCode updateCondition();
-    // ======================================================================
-  public:
-    // ======================================================================
-    double             resolverBound() const { return m_resolverBound; }
-    double             x() const { return m_beamSpotX; }
-    double             y() const { return m_beamSpotY; }
-    bool               closed() const { return m_veloClosed; }
-    const std::string& condName() const { return m_condName; }
-    // ======================================================================
-  private:
-    // ======================================================================
-    /// register condition
-    StatusCode registerCondition();
-    /// unregister condition
-    StatusCode unregisterCondition();
-    // ======================================================================
-  private:
-    // ======================================================================
-    /// default constructor
-    BeamSpot();
-    // ======================================================================
-  private:
-    // ======================================================================
-    /// resolver bound for closure
-    double m_resolverBound; // resolver bound for closure
-    /// velo closed condition
-    bool m_veloClosed = false; //      velo closed condition
-    /// beam spot-X
-    double m_beamSpotX = -1 * Gaudi::Units::km; //                beam spot-X
-    /// beam spot-Y
-    double m_beamSpotY = -1 * Gaudi::Units::km; //                beam spot-Y
-    /// condition name
-    std::string m_condName; //             condition name
-    /// the condition itself
-    LoKi::Interface<Condition> m_condition; //       the condition itself
-    // ======================================================================
-  };
-  // =========================================================================
-} //                                                      end of namespace LoKi
-// ============================================================================
-//                                                                      The END
-// ============================================================================
-#endif // LOKI_BEAMLINEFUNCTIONS_H
-// ============================================================================
diff --git a/Phys/LoKiUtils/src/BeamSpot.cpp b/Phys/LoKiUtils/src/BeamSpot.cpp
deleted file mode 100644
index 3f57355e7ee..00000000000
--- a/Phys/LoKiUtils/src/BeamSpot.cpp
+++ /dev/null
@@ -1,191 +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
-// ============================================================================
-// STD & STD
-// ============================================================================
-#include <cmath>
-// ============================================================================
-// GaudiKernel
-// ============================================================================
-#include "GaudiKernel/DataObject.h"
-#include "GaudiKernel/IDataProviderSvc.h"
-#include "GaudiKernel/IRegistry.h"
-#include "GaudiKernel/ISvcLocator.h"
-#include "GaudiKernel/IUpdateManagerSvc.h"
-#include "GaudiKernel/SmartDataPtr.h"
-#include "GaudiKernel/SmartIF.h"
-// ============================================================================
-// LoKi
-// ============================================================================
-#include "LoKi/BeamSpot.h"
-#include "LoKi/Constants.h"
-#include "LoKi/ILoKiSvc.h"
-// ============================================================================
-/** @file
- *  Collection of "beam-line"-related functors
- *
- *  This file is part of LoKi project:
- *   ``C++ ToolKit for Smart and Friendly Physics Analysis''
- *
- *  The package has been designed with the kind help from
- *  Galina PAKHLOVA and Sergey BARSUK.  Many bright ideas,
- *  contributions and advices from G.Raven, J.van Tilburg,
- *  A.Golutvin, P.Koppenburg have been used in the design.
- *
- *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
- *  @date   2011-03-10
- *
- */
-// ============================================================================
-namespace {
-  // ==========================================================================
-  /** @var s_CONDNAME
-   *  the default condition name for velo resolver
-   *  @author Vanya BELYAEV Ivan.Belyaev@cern.ch
-   *  @date   2011-06-03
-   */
-  static const std::string s_CONDNAME = "/dd/Conditions/Online/Velo/MotionSystem";
-  // ==========================================================================
-} // namespace
-// ============================================================================
-// Constructor from bound & condiname
-// ============================================================================
-LoKi::BeamSpot::BeamSpot( const double bound, const std::string& condname )
-    : LoKi::AuxFunBase{std::tie()}, m_resolverBound( bound ), m_condName( condname ) {
-  //
-  LoKi::ILoKiSvc* svc = lokiSvc();
-  //
-  Assert( 0 != svc, "Unable to reach LoKi Service!" );
-  SmartIF<ISvcLocator> loc( svc );
-  Assert( loc.isValid(), "Unable to reach ServiceLocator" );
-  //
-  SmartIF<IDataProviderSvc> det = loc->service<IDataProviderSvc>( "DetectorDataSvc", true );
-  Assert( det.isValid(), "Unable to reach Detector Service" );
-  //
-  if ( m_condName.empty() ) { m_condName = s_CONDNAME; }
-  SmartDataPtr<Condition> cond( det, condName() );
-  Assert( !( !cond ), "Unable to locate CONDITION='" + condName() + "'" );
-  //
-  m_condition = cond;
-  //
-  // update condition & register it
-  //
-  updateCondition().ignore();
-  registerCondition().ignore();
-  //
-}
-// ============================================================================
-// Constructor from bound
-// ============================================================================
-LoKi::BeamSpot::BeamSpot( const double bound )
-    : LoKi::AuxFunBase( std::tie() ), m_resolverBound( bound ), m_condName( s_CONDNAME ) {
-  //
-  LoKi::ILoKiSvc* svc = lokiSvc();
-  //
-  Assert( 0 != svc, "Unable to reach LoKi Service!" );
-  SmartIF<ISvcLocator> loc( svc );
-  Assert( loc.isValid(), "Unable to reach ServiceLocator" );
-  //
-  SmartIF<IDataProviderSvc> det = loc->service<IDataProviderSvc>( "DetectorDataSvc", true );
-  Assert( det.isValid(), "Unable to reach Detector Service" );
-  //
-  SmartDataPtr<Condition> cond( det, condName() );
-  Assert( !( !cond ), "Unable to locate CONDITION='" + condName() + "'" );
-  //
-  m_condition = cond;
-  //
-  // update condition & register it
-  //
-  updateCondition().ignore();
-  registerCondition().ignore();
-  //
-}
-// ============================================================================
-// Copy Constructor
-// ============================================================================
-LoKi::BeamSpot::BeamSpot( const LoKi::BeamSpot& right )
-    : LoKi::AuxFunBase( right )
-    , m_resolverBound( right.m_resolverBound )
-    , m_veloClosed( right.m_veloClosed )
-    , m_beamSpotX( right.m_beamSpotX )
-    , m_beamSpotY( right.m_beamSpotY )
-    , m_condName( right.m_condName )
-    , m_condition( right.m_condition ) {
-  //
-  // update condition & register it
-  //
-  updateCondition().ignore();
-  registerCondition().ignore();
-  //
-}
-// ============================================================================
-// MANDATORY: virtual destructor
-// ============================================================================
-LoKi::BeamSpot::~BeamSpot() { unregisterCondition().ignore(); }
-// ============================================================================
-// register the condition
-// ============================================================================
-StatusCode LoKi::BeamSpot::registerCondition() {
-  //
-  LoKi::ILoKiSvc* svc = lokiSvc();
-  Assert( 0 != svc, "Unable to reach LoKi Service!" );
-  //
-  SmartIF<IUpdateManagerSvc> upd( svc );
-  Assert( upd.isValid(), "Unable to reach Update Manager Service" );
-  //
-  LoKi::BeamSpot* this_ = this;
-  upd->registerCondition( this_, m_condName, &LoKi::BeamSpot::updateCondition );
-  //
-  return StatusCode::SUCCESS;
-}
-// ============================================================================
-// unregister the condition
-// ============================================================================
-StatusCode LoKi::BeamSpot::unregisterCondition() {
-  //
-  LoKi::ILoKiSvc* svc = lokiSvc();
-  if ( 0 == svc ) return StatusCode::SUCCESS;
-  //
-  SmartIF<IUpdateManagerSvc> upd( svc );
-  Assert( upd.isValid(), "Unable to reach Update Manager Service" );
-  //
-  LoKi::BeamSpot* this_ = this;
-  upd->unregister( this_ );
-  //
-  return StatusCode::SUCCESS;
-}
-// ============================================================================
-// update the condition
-// ============================================================================
-StatusCode LoKi::BeamSpot::updateCondition() {
-  //
-  Assert( !( !m_condition ), "Condition is invalid!" );
-  //
-  // Get the parameters
-  //
-  const double xRC = m_condition->paramAsDouble( "ResolPosRC" );
-  const double xLA = m_condition->paramAsDouble( "ResolPosLA" );
-  const double Y   = m_condition->paramAsDouble( "ResolPosY" );
-  //
-  m_beamSpotX = ( xRC + xLA ) / 2;
-  m_beamSpotY = Y;
-  //
-  // If resolver x position > bound, velo is considered as open
-  //
-  m_veloClosed = std::abs( xRC - m_beamSpotX ) < m_resolverBound && std::abs( xLA - m_beamSpotX ) < m_resolverBound;
-  //
-  return StatusCode::SUCCESS;
-}
-// ============================================================================
-// The END
-// ============================================================================
-- 
GitLab


From 9c423afe02ecf35dbd16b1ce7581f4620f2c14b9 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Tue, 11 Oct 2022 08:26:00 +0200
Subject: [PATCH 22/26] Do not compile Rec/LumiAlgs in DD4hep mode

---
 CMakeLists.txt | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 789c121fc36..4edf14dedbd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,6 +32,15 @@ if(ROOT_VERSION MATCHES "^6\\.2[2-4].*")
   message(STATUS "Generating dictionaries with additional flags: " ${REC_DICT_GEN_DEFAULT_OPTS})
 endif()
 
+if (NOT USE_DD4HEP)
+    set(VarName DetDescOnlySubDirs)
+else()
+    set(VarName LHCB_IGNORE_SUBDIRS)
+endif()
+set(${VarName}
+    Rec/LumiAlgs
+)
+
 # -- Subdirectories
 lhcb_add_subdirectories(
     Tr/TrackFitEvent
@@ -41,6 +50,7 @@ lhcb_add_subdirectories(
     CaloFuture/CaloFuturePIDs
     CaloFuture/CaloFutureReco
     CaloFuture/CaloFutureTools
+    ${DetDescOnlySubDirs}
     FT/FTMonitors
     MicroDST/MicroDSTAlgorithm
     MicroDST/MicroDSTBase
@@ -125,7 +135,6 @@ lhcb_add_subdirectories(
     Rec/ChargedProtoANNPID
     Rec/GlobalReco
     Rec/GlobalRecoMCTools
-    Rec/LumiAlgs
     Rec/RecAlgs
     Rich/RichRecUtils
     Rich/RichFutureRecEvent
-- 
GitLab


From e12faa179567e3b7f49fe344dc91da86571a0094 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Thu, 13 Oct 2022 16:31:00 +0200
Subject: [PATCH 23/26] Used meta_enum and namespaces in CaloFutureReco

---
 .../src/CaloFutureCorrectionBase.cpp          |  459 ++++----
 .../src/CaloFutureCorrectionBase.h            |  332 +++---
 .../src/CaloFutureECorrection.cpp             | 1039 ++++++++---------
 .../src/CaloFutureLCorrection.cpp             |  192 ++-
 .../src/CaloFutureSCorrection.cpp             |   32 +-
 .../src/CaloFutureShowerOverlapTool.cpp       |    9 +-
 .../src/FutureClusterCovarianceMatrixTool.cpp |   23 +-
 .../src/FutureClusterCovarianceMatrixTool.h   |    6 +-
 .../src/FutureSubClusterSelectorTool.cpp      |   16 +-
 .../src/FutureSubClusterSelectorTool.h        |    9 +-
 10 files changed, 1025 insertions(+), 1092 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index 5dbec9d5b6f..f3dadfe0704 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -32,280 +32,239 @@ namespace Gaudi::Parsers {
 //
 // 2010-05-07 : Olivier Deschamps
 //-----------------------------------------------------------------------------
-namespace CaloFutureCorrection {
-  namespace {
-    const auto typeName = std::array<std::string, nT>{"alphaG",
-                                                      "alphaE",
-                                                      "alphaB",
-                                                      "alphaX",
-                                                      "alphaY",
-                                                      "RESERVED(alphaP)",
-                                                      "RESERVED(beta)",
-                                                      "RESERVED(betaP)",
-                                                      "RESERVED(betaPR)",
-                                                      "RESERVED(betaC)",
-                                                      "RESERVED(betaCP)",
-                                                      "RESERVED(betaCPR)", // E-corrections
-                                                      "RESERVED(globalC)",
-                                                      "globalT",
-                                                      "offsetT",
-                                                      "offset",
-                                                      "RESERVED(offsetC)",
-                                                      "ClusterCovariance",
-                                                      "gamma0",
-                                                      "delta0",
-                                                      "gammaP",
-                                                      "deltaP", // L-Corrections
-                                                      "shapeX",
-                                                      "shapeY",
-                                                      "residual",
-                                                      "residualX",
-                                                      "residualY",
-                                                      "asymP",
-                                                      "asymM",
-                                                      "angularX",
-                                                      "angularY", // S-Corrections
-                                                      "profile",
-                                                      "RESERVED(profileC)", // Profile shape
-                                                      "EnergyMask",
-                                                      "PositionMask",
-                                                      "Unknown"};
-  }
-  const std::string& toString( Type t ) { return typeName.at( t ); }
-} // namespace CaloFutureCorrection
+namespace LHCb::Calo::Correction {
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::Polynomial::correction( float var ) const {
-  float cor = pars.front();
-  float v   = var;
-  for ( auto i = std::next( pars.begin() ); i != pars.end(); ++i ) {
-    cor += ( *i ) * v;
-    v *= var;
+  Result Polynomial::correction( float var ) const {
+    float cor = pars.front();
+    float v   = var;
+    for ( auto i = std::next( pars.begin() ); i != pars.end(); ++i ) {
+      cor += ( *i ) * v;
+      v *= var;
+    }
+    float derivative = 0.;
+    v                = 1.;
+    int cnt          = 1;
+    for ( auto i = std::next( pars.begin() ); i != pars.end(); ++i, ++cnt ) {
+      derivative += cnt * ( *i ) * v;
+      v *= var;
+    }
+    return {cor, derivative};
   }
-  float derivative = 0.;
-  v                = 1.;
-  int cnt          = 1;
-  for ( auto i = std::next( pars.begin() ); i != pars.end(); ++i, ++cnt ) {
-    derivative += cnt * ( *i ) * v;
-    v *= var;
+  Result InversePolynomial::correction( float var ) const {
+    auto cor = Polynomial::correction( var );
+    if ( cor.value != 0 ) cor.value = 1. / cor.value;
+    cor.derivative *= -cor.value * cor.value;
+    return cor;
   }
-  return {cor, derivative};
-}
-
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::InversePolynomial::correction( float var ) const {
-  auto cor = Polynomial::correction( var );
-  if ( cor.value != 0 ) cor.value = 1. / cor.value;
-  cor.derivative *= -cor.value * cor.value;
-  return cor;
-}
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::ExpPolynomial::correction( float var ) const {
-  auto cor = Polynomial::correction( var );
-  if ( cor.value != 0 ) { cor.value = ( var == 0. ? cached : vapprox_exp( cor.value ) ); }
-  cor.derivative *= cor.value;
-  return cor;
-}
+  Result ExpPolynomial::correction( float var ) const {
+    auto cor = Polynomial::correction( var );
+    if ( cor.value != 0 ) { cor.value = ( var == 0. ? cached : vapprox_exp( cor.value ) ); }
+    cor.derivative *= cor.value;
+    return cor;
+  }
 
-CaloFutureCorrectionBase::CorrectionResult
-CaloFutureCorrectionBase::ReciprocalPolynomial::correction( float var ) const {
-  if ( var == 0 ) return {pars[0], 0.}; // CHECKME
-  auto cor = Polynomial::correction( 1.0 / var );
-  cor.derivative *= -1.0 / ( var * var );
-  return cor;
-}
+  Result ReciprocalPolynomial::correction( float var ) const {
+    if ( var == 0 ) return {pars[0], 0.}; // CHECKME
+    auto cor = Polynomial::correction( 1.0 / var );
+    cor.derivative *= -1.0 / ( var * var );
+    return cor;
+  }
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::Sigmoid::correction( float var ) const {
-  auto mytanh = []( float x ) {
-    const float y = vapprox_exp( -2 * x );
-    return ( 1 - y ) / ( 1 + y );
-  };
-  float mytanh_val = mytanh( c * ( var + d ) );
-  return {a + b * mytanh_val, b * c * ( 1 - mytanh_val * mytanh_val )};
-}
+  Result Sigmoid::correction( float var ) const {
+    auto mytanh = []( float x ) {
+      const float y = vapprox_exp( -2 * x );
+      return ( 1 - y ) / ( 1 + y );
+    };
+    float mytanh_val = mytanh( c * ( var + d ) );
+    return {a + b * mytanh_val, b * c * ( 1 - mytanh_val * mytanh_val )};
+  }
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::Sshape::correction( float var ) const {
-  if ( b > 0 ) {
-    float arg  = cache * var / delta;
-    float sapo = approx_sqrt( arg * arg + 1.f );
-    return {b * LHCb::Math::Approx::approx_log( arg + sapo ), b / delta * cache / sapo};
+  Result Sshape::correction( float var ) const {
+    if ( b > 0 ) {
+      float arg  = cache * var / delta;
+      float sapo = approx_sqrt( arg * arg + 1.f );
+      return {b * LHCb::Math::Approx::approx_log( arg + sapo ), b / delta * cache / sapo};
+    }
+    return {0, 0}; // CHECKME
   }
-  return {0, 0}; // CHECKME
-}
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::Sinusoidal::correction( float var ) const {
-  constexpr float twopi = 2 * M_PI;
-  float           sin_val, cos_val;
-  LHCb::Math::fast_sincos( twopi * var, sin_val, cos_val );
-  return {A * sin_val, A * twopi * cos_val};
-}
+  Result Sinusoidal::correction( float var ) const {
+    constexpr float twopi = 2 * M_PI;
+    float           sin_val, cos_val;
+    LHCb::Math::fast_sincos( twopi * var, sin_val, cos_val );
+    return {A * sin_val, A * twopi * cos_val};
+  }
 
-CaloFutureCorrectionBase::CorrectionResult CaloFutureCorrectionBase::ShowerProfile::correction( float var ) const {
-  if ( var > 0.5 ) {
-    auto tmp1 = pars[0] * vapprox_exp( -pars[1] * var );
-    auto tmp2 = pars[2] * vapprox_exp( -pars[3] * var );
-    auto tmp3 = pars[4] * vapprox_exp( -pars[5] * var );
-    return {tmp1 + tmp2 + tmp3, -pars[1] * tmp1 - pars[3] * tmp2 - pars[5] * tmp3};
-  } else {
-    auto tmp1 = pars[6] * vapprox_exp( -pars[7] * var );
-    auto tmp2 = pars[8] * vapprox_exp( -pars[9] * var );
-    return {2 - tmp1 - tmp2, pars[7] * tmp1 + pars[9] * tmp2};
+  Result ShowerProfile::correction( float var ) const {
+    if ( var > 0.5 ) {
+      auto tmp1 = pars[0] * vapprox_exp( -pars[1] * var );
+      auto tmp2 = pars[2] * vapprox_exp( -pars[3] * var );
+      auto tmp3 = pars[4] * vapprox_exp( -pars[5] * var );
+      return {tmp1 + tmp2 + tmp3, -pars[1] * tmp1 - pars[3] * tmp2 - pars[5] * tmp3};
+    } else {
+      auto tmp1 = pars[6] * vapprox_exp( -pars[7] * var );
+      auto tmp2 = pars[8] * vapprox_exp( -pars[9] * var );
+      return {2 - tmp1 - tmp2, pars[7] * tmp1 + pars[9] * tmp2};
+    }
   }
-}
 
-DECLARE_COMPONENT( CaloFutureCorrectionBase )
+  DECLARE_COMPONENT_WITH_ID( Base, "CaloFutureCorrectionBase" )
 
-CaloFutureCorrectionBase::CaloFutureCorrectionBase( const std::string& type, const std::string& name,
-                                                    const IInterface* parent )
-    : ConditionAccessorHolder( type, name, parent ) {
-  declareInterface<CaloFutureCorrectionBase>( this );
-}
+  Base::Base( const std::string& type, const std::string& name, const IInterface* parent )
+      : ConditionAccessorHolder( type, name, parent ) {
+    declareInterface<Base>( this );
+  }
 
-StatusCode CaloFutureCorrectionBase::initialize() {
-  return ConditionAccessorHolder::initialize().andThen( [&]() -> StatusCode {
-    if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
-    addConditionDerivation( {m_conditionName}, m_params.key(), [&]( YAML::Node const& cond ) {
-      Parameters params;
-      for ( auto it = cond.begin(); it != cond.end(); it++ ) {
-        auto type = accept( it->first.as<std::string>() );
-        if ( !type ) continue;
-        const auto& parVec = it->second.as<std::vector<double>>();
-        if ( parVec.size() < 2 ) {
-          error() << " # of parameters is insufficient!!" << endmsg;
-          continue;
+  StatusCode Base::initialize() {
+    return ConditionAccessorHolder::initialize().andThen( [&]() -> StatusCode {
+      if ( m_hypos.empty() ) return Error( "Empty vector of allowed Calorimeter Hypotheses!" );
+      addConditionDerivation( {m_conditionName}, m_params.key(), [&]( YAML::Node const& cond ) {
+        Parameters params;
+        for ( auto it = cond.begin(); it != cond.end(); it++ ) {
+          auto type = accept( it->first.as<std::string>() );
+          if ( !type ) continue;
+          const auto& parVec = it->second.as<std::vector<double>>();
+          if ( parVec.size() < 2 ) {
+            error() << " # of parameters is insufficient!!" << endmsg;
+            continue;
+          }
+          constructParams( params[static_cast<int>( *type )], parVec );
         }
-        constructParams( params[*type], parVec );
-      }
-      return params;
+        return params;
+      } );
+      return StatusCode::SUCCESS;
     } );
-    return StatusCode::SUCCESS;
-  } );
-}
-
-StatusCode CaloFutureCorrectionBase::finalize() {
-  if ( m_corrections.size() > 1 || *( m_corrections.begin() ) != "All" ) {
-    for ( const auto& c : m_corrections ) { info() << "Accepted corrections :  '" << c << "'" << endmsg; }
   }
-  if ( m_corrections.empty() ) warning() << "All corrections have been disabled for " << name() << endmsg;
-  m_hypos.clear();
-  return ConditionAccessorHolder::finalize(); // must be called after all other actions
-}
 
-void CaloFutureCorrectionBase::constructParams( Functions& fun, LHCb::span<const double> params ) {
-  // NOTE: conversion from double (params) to float (ParamVector)
-  const auto func = static_cast<CaloFutureCorrection::Function>( std::lround( params[0] ) );
-  const auto dim  = static_cast<int>( std::lround( params[1] ) );
-  if ( func == CaloFutureCorrection::GlobalParamList ) {
-    if ( dim + 2 != static_cast<int>( params.size() ) ) {
-      warning() << "o Size of DB parameter vector does not match the expectation for the DB specified type." << endmsg;
-    }
-    for ( auto& i : fun ) i = ParamVector{{std::next( params.begin(), 2 ), params.end()}};
-  } else {
-    if ( 3 * dim + 2 != static_cast<int>( params.size() ) ) {
-      warning() << "o Size of DB parameter vector does not match the expectation for the DB specified type." << endmsg;
+  StatusCode Base::finalize() {
+    if ( m_corrections.size() > 1 || *( m_corrections.begin() ) != "All" ) {
+      for ( const auto& c : m_corrections ) { info() << "Accepted corrections :  '" << c << "'" << endmsg; }
     }
-    for ( unsigned int area = 0; area < fun.size(); ++area ) {
-      // transpose the parameters into the right order...
-      std::vector<float> p;
-      p.reserve( dim );
-      int pos = 2 + area;
-      for ( int i = 0; i < dim; ++i ) {
-        p.push_back( params[pos] );
-        pos += 3;
-      }
+    if ( m_corrections.empty() ) warning() << "All corrections have been disabled for " << name() << endmsg;
+    m_hypos.clear();
+    return ConditionAccessorHolder::finalize(); // must be called after all other actions
+  }
 
-      switch ( func ) {
-      case CaloFutureCorrection::Polynomial:
-        if ( !p.empty() ) {
-          fun[area] = Polynomial{{p.begin(), p.end()}};
-        } else {
-          error() << "Inconsistent # of parameters for " << func << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::InversPolynomial:
-        if ( !p.empty() ) {
-          fun[area] = CaloFutureCorrectionBase::InversePolynomial{p};
-        } else {
-          error() << "Inconsistent # of parameters for " << func << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::ExpPolynomial:
-        if ( !p.empty() ) {
-          fun[area] = CaloFutureCorrectionBase::ExpPolynomial{p};
-        } else {
-          error() << "Inconsistent # of parameters for " << func << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::ReciprocalPolynomial:
-        if ( !p.empty() ) {
-          fun[area] = CaloFutureCorrectionBase::ReciprocalPolynomial{p};
-        } else {
-          error() << "Inconsistent # of parameters for " << func << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::Sigmoid:
-        if ( p.size() == 4 ) {
-          fun[area] = CaloFutureCorrectionBase::Sigmoid{LHCb::make_span( p ).first<4>()};
-        } else {
-          error() << "Inconsistent # of parameters for sigmoid" << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::Sshape:
-        if ( p.size() == 1 ) {
-          fun[area] = CaloFutureCorrectionBase::Sshape{p[0]};
-        } else {
-          error() << "Inconsistent # of parameters for Sshape" << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::SshapeMod:
-        if ( p.size() == 1 ) {
-          fun[area] = CaloFutureCorrectionBase::SshapeMod{p[0]};
-        } else {
-          error() << "Inconsistent # of parameters for SshapeMod" << endmsg;
-        }
-        break;
-      case CaloFutureCorrection::ShowerProfile:
-        if ( p.size() == 10 ) {
-          fun[area] = CaloFutureCorrectionBase::ShowerProfile{LHCb::make_span( p ).first<10>()};
-        } else {
-          error() << "Inconsistent # of parameters for ShowerProfile" << endmsg;
+  void Base::constructParams( Functions& fun, LHCb::span<const double> params ) {
+    // NOTE: conversion from double (params) to float (ParamVector)
+    const auto func = static_cast<FunctionType>( std::lround( params[0] ) );
+    const auto dim  = static_cast<int>( std::lround( params[1] ) );
+    if ( func == FunctionType::GlobalParamList ) {
+      if ( dim + 2 != static_cast<int>( params.size() ) ) {
+        warning() << "o Size of DB parameter vector does not match the expectation for the DB specified type."
+                  << endmsg;
+      }
+      for ( auto& i : fun ) i = ParamVector{{std::next( params.begin(), 2 ), params.end()}};
+    } else {
+      if ( 3 * dim + 2 != static_cast<int>( params.size() ) ) {
+        warning() << "o Size of DB parameter vector does not match the expectation for the DB specified type."
+                  << endmsg;
+      }
+      for ( unsigned int area = 0; area < fun.size(); ++area ) {
+        // transpose the parameters into the right order...
+        std::vector<float> p;
+        p.reserve( dim );
+        int pos = 2 + area;
+        for ( int i = 0; i < dim; ++i ) {
+          p.push_back( params[pos] );
+          pos += 3;
         }
-        break;
-      case CaloFutureCorrection::Sinusoidal:
-        if ( p.size() == 1 ) {
-          fun[area] = CaloFutureCorrectionBase::Sinusoidal{p[0]};
-        } else {
-          error() << "Inconsistent # of parameters for Sinusoidal" << endmsg;
+
+        switch ( func ) {
+        case FunctionType::Polynomial:
+          if ( !p.empty() ) {
+            fun[area] = Polynomial{{p.begin(), p.end()}};
+          } else {
+            error() << "Inconsistent # of parameters for " << func << endmsg;
+          }
+          break;
+        case FunctionType::InversPolynomial:
+          if ( !p.empty() ) {
+            fun[area] = InversePolynomial{p};
+          } else {
+            error() << "Inconsistent # of parameters for " << func << endmsg;
+          }
+          break;
+        case FunctionType::ExpPolynomial:
+          if ( !p.empty() ) {
+            fun[area] = ExpPolynomial{p};
+          } else {
+            error() << "Inconsistent # of parameters for " << func << endmsg;
+          }
+          break;
+        case FunctionType::ReciprocalPolynomial:
+          if ( !p.empty() ) {
+            fun[area] = ReciprocalPolynomial{p};
+          } else {
+            error() << "Inconsistent # of parameters for " << func << endmsg;
+          }
+          break;
+        case FunctionType::Sigmoid:
+          if ( p.size() == 4 ) {
+            fun[area] = Sigmoid{LHCb::make_span( p ).first<4>()};
+          } else {
+            error() << "Inconsistent # of parameters for sigmoid" << endmsg;
+          }
+          break;
+        case FunctionType::Sshape:
+          if ( p.size() == 1 ) {
+            fun[area] = Sshape{p[0]};
+          } else {
+            error() << "Inconsistent # of parameters for Sshape" << endmsg;
+          }
+          break;
+        case FunctionType::SshapeMod:
+          if ( p.size() == 1 ) {
+            fun[area] = SshapeMod{p[0]};
+          } else {
+            error() << "Inconsistent # of parameters for SshapeMod" << endmsg;
+          }
+          break;
+        case FunctionType::ShowerProfile:
+          if ( p.size() == 10 ) {
+            fun[area] = ShowerProfile{LHCb::make_span( p ).first<10>()};
+          } else {
+            error() << "Inconsistent # of parameters for ShowerProfile" << endmsg;
+          }
+          break;
+        case FunctionType::Sinusoidal:
+          if ( p.size() == 1 ) {
+            fun[area] = Sinusoidal{p[0]};
+          } else {
+            error() << "Inconsistent # of parameters for Sinusoidal" << endmsg;
+          }
+          break;
+        case FunctionType::ParamList:
+          assert( !p.empty() );
+          fun[area] = ParamVector{{p.begin(), p.end()}};
+          break;
+        default:
+          error() << "got unknown function" << endmsg;
+          break;
         }
-        break;
-      case CaloFutureCorrection::ParamList:
-        assert( !p.empty() );
-        fun[area] = CaloFutureCorrectionBase::ParamVector{{p.begin(), p.end()}};
-        break;
-      default:
-        error() << "got unknown function" << endmsg;
-        break;
       }
     }
   }
-}
 
-std::optional<CaloFutureCorrectionBase::CorrectionResult>
-CaloFutureCorrectionBase::getCorrectionAndDerivative( const CaloFutureCorrection::Type   type,
-                                                      const LHCb::Detector::Calo::CellID id, const float var ) const {
-  return std::visit(
-      Gaudi::overload( [&]( const auto& data ) -> std::optional<CorrectionResult> { return data.correction( var ); },
-                       []( const ParamVector& ) -> std::optional<CorrectionResult> {
-                         return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
-                       } ),
-      m_params.get()[type][id.area()] );
-}
+  std::optional<Result> Base::getCorrectionAndDerivative( const Type type, const LHCb::Detector::Calo::CellID id,
+                                                          const float var ) const {
+    return std::visit(
+        Gaudi::overload( [&]( const auto& data ) -> std::optional<Result> { return data.correction( var ); },
+                         []( const ParamVector& ) -> std::optional<Result> {
+                           return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
+                         } ),
+        m_params.get()[static_cast<int>( type )][id.area()] );
+  }
+
+  std::optional<float> Base::getCorrection( const Type type, const LHCb::Detector::Calo::CellID id,
+                                            const float var ) const {
+    return std::visit(
+        Gaudi::overload( [&]( const auto& data ) -> std::optional<float> { return data.correction( var ).value; },
+                         []( const ParamVector& ) -> std::optional<float> {
+                           return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
+                         } ),
+        m_params.get()[static_cast<int>( type )][id.area()] );
+  }
 
-std::optional<float> CaloFutureCorrectionBase::getCorrection( const CaloFutureCorrection::Type   type,
-                                                              const LHCb::Detector::Calo::CellID id,
-                                                              const float                        var ) const {
-  return std::visit(
-      Gaudi::overload( [&]( const auto& data ) -> std::optional<float> { return data.correction( var ).value; },
-                       []( const ParamVector& ) -> std::optional<float> {
-                         return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
-                       } ),
-      m_params.get()[type][id.area()] );
-}
+} // namespace LHCb::Calo::Correction
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index 8d5f597636e..a029feaeb79 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -32,202 +32,78 @@
 static const InterfaceID IID_CaloFutureCorrectionBase( "CaloFutureCorrectionBase", 1,
                                                        0 ); // TODO: probably change IF version (?)
 
-/** @class CaloFutureCorrectionBase CaloFutureCorrectionBase.h
- *
- *
- *  @author Olivier Deschamps
- *  @date   2010-05-07
- */
-
-// DO NOT CHANGE THE FUNCTION ORDER FOR BACKWARD COMPATIBILITY WITH EXISTING CONDITIONS DB
-namespace CaloFutureCorrection {
-  enum Function {
-    InversPolynomial     = 0,
-    Polynomial           = 1,
-    ExpPolynomial        = 2,
-    ReciprocalPolynomial = 3,
-    Sigmoid              = 4,
-    Sshape               = 5,
-    ShowerProfile        = 6,
-    SshapeMod            = 7,
-    Sinusoidal           = 8,
-    ParamList            = 9,  // simple parameter access (by area)
-    GlobalParamList      = 10, // simple parameter access (ind. of area)
-    Unknown                    // type of correction from DB that is unspecified here. MUST be the last item.
-  };
-
-  enum Type {
-    // NB: numbering is not continuous due to removed PRS and SPD/Converted_photons -related parameters for Run 1-2
-    // CondDB compatibility
-    // E-Correction parameters
-    alphaG = 0,             // global alpha factor #0
-    alphaE,                 // alpha(E)    #1
-    alphaB,                 // alpha(Bary) #2
-    alphaX,                 // alpha(Dx)   #3
-    alphaY,                 // alpha(Dy)   #4
-    globalT = 13,           // global(DeltaTheta) function of incidence angle #13
-    offsetT,                // offset(DeltaTheta) function of incidence angle #14
-    offset,                 // offset( sinTheta ) energy (or ET ) offset #15
-    ClusterCovariance = 17, // parameters for cluster covariance estimation #17
-    // L-Correction parameters
-    gamma0, // #18
-    delta0, // #19
-    gammaP, // Prs-related L-correction (non-zero at ePrs = 0) #20
-    deltaP, // Prs-related L-correction (non-sero at ePrs = 0) #21
-    // S-correction parameters
-    shapeX,    // #22
-    shapeY,    // #23
-    residual,  // #24
-    residualX, // #25
-    residualY, // #26
-    asymP,     // #27
-    asymM,     // #28
-    angularX,  // #29
-    angularY,  // #30
-    // ShowerShape profile
-    profile, // #31
-    // Cluster masking
-    EnergyMask = 33, // #33
-    PositionMask,    // #34
-    lastType         // MUST BE THE LAST LINE
-  };
-
-  constexpr int        nT = lastType + 1;
-  constexpr int        nF = Unknown + 1;
-  const std::string&   toString( Type t );
-  inline std::ostream& operator<<( std::ostream& os, Type t ) { return os << toString( t ); }
-  inline Type          toCorrectionType( std::string_view type ) {
-    for ( int i = 0; i < CaloFutureCorrection::nT; ++i ) {
-      if ( auto t = static_cast<Type>( i ); toString( t ) == type ) return t;
-    }
-    return CaloFutureCorrection::lastType;
-  }
-} // namespace CaloFutureCorrection
-
-struct VectorOfHypothesesTypes : std::vector<LHCb::Event::Calo::Hypotheses::Type> {
-  using std::vector<LHCb::Event::Calo::Hypotheses::Type>::vector;
-  inline friend std::ostream& operator<<( std::ostream& os, const VectorOfHypothesesTypes& v ) {
-    return GaudiUtils::details::ostream_joiner(
-               os << "[ ", v, ", ",
-               []( std::ostream& s, LHCb::Event::Calo::Hypotheses::Type t ) -> std::ostream& {
-                 return s << std::quoted( LHCb::Event::Calo::Enum::toString( t ), '\'' );
-               } )
-           << " ]";
-  }
-};
-
 namespace Gaudi::Parsers {
   StatusCode parse( std::vector<LHCb::Event::Calo::Hypotheses::Type>& r, const std::string& s );
 } // namespace Gaudi::Parsers
 
-class CaloFutureCorrectionBase : public LHCb::DetDesc::ConditionAccessorHolder<GaudiTool> {
-
-public:
-  static const InterfaceID& interfaceID() { return IID_CaloFutureCorrectionBase; }
+// DO NOT CHANGE THE FUNCTION ORDER FOR BACKWARD COMPATIBILITY WITH EXISTING CONDITIONS DB
+namespace LHCb::Calo::Correction {
 
-  CaloFutureCorrectionBase( const std::string& type, const std::string& name, const IInterface* parent );
+  meta_enum_class( FunctionType, int, InversPolynomial = 0, Polynomial = 1, ExpPolynomial = 2, ReciprocalPolynomial = 3,
+                   Sigmoid = 4, Sshape = 5, ShowerProfile = 6, SshapeMod = 7, Sinusoidal = 8,
+                   ParamList       = 9,  // simple parameter access (by area)
+                   GlobalParamList = 10, // simple parameter access (ind. of area)
+                   Unknown )             // type of correction from DB that is unspecified here. MUST be the last item.
 
-  StatusCode initialize() override;
-  StatusCode finalize() override;
+      meta_enum_class( Type, int,
+                       // NB: numbering is not continuous due to removed PRS and SPD/Converted_photons -related
+                       // parameters for Run 1-2 CondDB compatibility E-Correction parameters
+                       alphaG = 0, // global alpha factor
+                       alphaE = 1, // alpha(E)
+                       alphaB = 2, // alpha(Bary)
+                       alphaX = 3, // alpha(Dx)
+                       alphaY = 4, // alpha(Dy)
+                       alphaP = 5, beta = 6, betaP = 7, betaPR = 8, betaC = 9, betaCP = 10, betaCPR = 11, globalC = 12,
+                       globalT           = 13, // global(DeltaTheta) function of incidence angle
+                       offsetT           = 14, // offset(DeltaTheta) function of incidence angle
+                       offset            = 15, // offset( sinTheta ) energy (or ET ) offset
+                       offsetC           = 16,
+                       ClusterCovariance = 17, // parameters for cluster covariance estimation
+                       // L-Correction parameters
+                       gamma0 = 18, delta0 = 19,
+                       gammaP = 20, // Prs-related L-correction (non-zero at ePrs = 0)
+                       deltaP = 21, // Prs-related L-correction (non-sero at ePrs = 0)
+                       // S-correction parameters
+                       shapeX = 22, shapeY = 23, residual = 24, residualX = 25, residualY = 26, asymP = 27, asymM = 28,
+                       angularX = 29, angularY = 30,
+                       // ShowerShape profile
+                       profile = 31, profileC = 32,
+                       // Cluster masking
+                       EnergyMask = 33, PositionMask = 34, Unknown )
 
-  struct CorrectionResult {
+          struct Result {
     float value;
     float derivative;
   };
 
-  std::optional<CorrectionResult> getCorrectionAndDerivative( const CaloFutureCorrection::Type   type,
-                                                              const LHCb::Detector::Calo::CellID id,
-                                                              const float                        var = 0. ) const;
-
-  std::optional<float> getCorrection( const CaloFutureCorrection::Type type, const LHCb::Detector::Calo::CellID id,
-                                      const float var = 0. ) const;
-
-  const std::vector<float>&
-  getParamVector( const CaloFutureCorrection::Type   type,
-                  const LHCb::Detector::Calo::CellID id = LHCb::Detector::Calo::CellID() ) const {
-    return std::get<ParamVector>( m_params.get()[type][id.area()] ).params;
-  }
-
-  std::optional<float> getParameter( CaloFutureCorrection::Type type, unsigned int i,
-                                     const LHCb::Detector::Calo::CellID id = LHCb::Detector::Calo::CellID() ) const {
-    const auto& data = getParamVector( type, id );
-    if ( i >= data.size() ) return std::nullopt;
-    return data[i];
-  }
-
-protected:
-  using IncCounter = Gaudi::Accumulators::Counter<>;
-  using ACounter   = Gaudi::Accumulators::AveragingCounter<>;
-  using SCounter   = Gaudi::Accumulators::StatCounter<>;
-
-  static constexpr int k_numOfCaloAreas{4};
-
-  template <typename P, typename COUNTER = SCounter>
-  static auto make_counters( P* parent, std::string_view prefix ) {
-    using namespace std::string_view_literals;
-    return std::apply(
-        [parent, prefix]( auto&&... args ) {
-          return std::array{COUNTER{parent, fmt::format( "{}{}", prefix, args )}...};
-        },
-        std::array{"Outer"sv, "Middle"sv, "Inner"sv, "PinArea"sv} );
-  }
-
-  LHCb::ClusterFunctors::ClusterArea       m_area;
-  Gaudi::Property<bool>                    m_correctCovariance{this, "CorrectCovariance", true};
-  Gaudi::Property<VectorOfHypothesesTypes> m_hypos{this,
-                                                   "Hypotheses",
-                                                   {
-                                                       LHCb::Event::Calo::Hypotheses::Type::Photon,
-                                                       LHCb::Event::Calo::Hypotheses::Type::PhotonFromMergedPi0,
-                                                       LHCb::Event::Calo::Hypotheses::Type::EmCharged,
-                                                   },
-                                                   "acceptable hypotheses"};
-
-private:
-  Gaudi::Property<std::string> m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
-  Gaudi::Property<std::vector<std::string>> m_corrections{this, "Corrections", {"All"}};
-
-  std::optional<CaloFutureCorrection::Type> accept( const std::string& name ) const {
-    auto b = std::any_of( m_corrections.begin(), m_corrections.end(),
-                          [&]( const auto& i ) { return i == name || i == "All"; } );
-    if ( !b ) return std::nullopt;
-    // check if known type
-    CaloFutureCorrection::Type type = CaloFutureCorrection::toCorrectionType( name );
-    if ( type != CaloFutureCorrection::lastType ) return type;
-    if ( CaloFutureCorrection::toCorrectionType( std::string{"RESERVED("}.append( name ).append( ")" ) ) ==
-         CaloFutureCorrection::lastType )
-      warning() << " o Type " << name << " is not known" << endmsg;
-    return std::nullopt;
-  }
-
   struct Polynomial {
     static constexpr const char*               name = "Polynomial";
     boost::container::static_vector<float, 10> pars; // FIXME: how do I know that 10 is enough? Seems to depend on the
                                                      // database contents... maybe use small_vector instead???
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct InversePolynomial final : private Polynomial {
     InversePolynomial( LHCb::span<const float> p ) : Polynomial{{p.begin(), p.end()}} {}
     static constexpr const char* name = "InversePolynomial";
-    CorrectionResult             correction( float var ) const;
+    Result                       correction( float var ) const;
   };
   struct ExpPolynomial final : private Polynomial {
     static constexpr const char* name = "ExpPolynomial";
     float                        cached;
     ExpPolynomial( LHCb::span<const float> p )
         : Polynomial{{p.begin(), p.end()}}, cached{LHCb::Math::Approx::vapprox_exp( (float)p[0] )} {}
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct ReciprocalPolynomial final : private Polynomial {
     static constexpr const char* name = "ReciprocalPolynomial";
     ReciprocalPolynomial( LHCb::span<const float> p ) : Polynomial{{p.begin(), p.end()}} {}
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct Sigmoid final {
     static constexpr const char* name = "Sigmoid";
     float                        a, b, c, d;
     Sigmoid( LHCb::span<const float, 4> p ) : a{p[0]}, b{p[1]}, c{p[2]}, d{p[3]} {}
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct Sshape {
     static float mysinh( float x ) {
@@ -241,7 +117,7 @@ private:
     Sshape( float b, bool modified = false ) : b{b}, cache{( b != 0 ) ? mysinh( delta / b ) : INFINITY} {
       if ( !modified ) cache = LHCb::Math::Approx::approx_sqrt( 1.f + cache * cache );
     }
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct SshapeMod final : Sshape {
     static constexpr const char* name = "SshapeMod";
@@ -251,28 +127,136 @@ private:
     static constexpr const char* name = "ShowerProfile";
     std::array<float, 10>        pars;
     ShowerProfile( LHCb::span<const float, 10> p ) { std::copy( p.begin(), p.end(), pars.begin() ); }
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct Sinusoidal final {
     static constexpr const char* name = "Sinusoidal";
     float                        A;
     Sinusoidal( float s ) : A{s} {}
-    CorrectionResult correction( float var ) const;
+    Result correction( float var ) const;
   };
   struct ParamVector final {
     static constexpr const char* name = "ParamVector";
     std::vector<float>           params;
   };
 
-  using Function = std::variant<ParamVector, InversePolynomial, Polynomial, ExpPolynomial, ReciprocalPolynomial,
+  using Function   = std::variant<ParamVector, InversePolynomial, Polynomial, ExpPolynomial, ReciprocalPolynomial,
                                 Sigmoid, Sshape, ShowerProfile, SshapeMod, Sinusoidal>;
+  using Functions  = std::array<Function, 3>; // Inner, middle and Outer
+  using Parameters = std::array<Functions, static_cast<int>( Type::Unknown ) + 1>;
+
+  struct VectorOfHypothesesTypes : std::vector<LHCb::Event::Calo::Hypotheses::Type> {
+    using std::vector<LHCb::Event::Calo::Hypotheses::Type>::vector;
+    inline friend std::ostream& operator<<( std::ostream& os, const VectorOfHypothesesTypes& v ) {
+      return GaudiUtils::details::ostream_joiner(
+                 os << "[ ", v, ", ",
+                 []( std::ostream& s, LHCb::Event::Calo::Hypotheses::Type t ) -> std::ostream& {
+                   return s << std::quoted( LHCb::Event::Calo::Enum::toString( t ), '\'' );
+                 } )
+             << " ]";
+    }
+  };
 
-  static const char* correctionName( const Function& cp ) {
-    return std::visit( []( const auto& i ) { return i.name; }, cp );
-  }
+  /**
+   *  @author Olivier Deschamps
+   *  @date   2010-05-07
+   */
+  class Base : public LHCb::DetDesc::ConditionAccessorHolder<GaudiTool> {
 
-  using Functions  = std::array<Function, 3>; // Inner, middle and Outer
-  using Parameters = std::array<Functions, CaloFutureCorrection::lastType + 1>;
-  void                          constructParams( Functions&, const LHCb::span<const double> );
-  ConditionAccessor<Parameters> m_params{this, name() + "-CaloFutureCorrectionBaseParameters"};
-};
+  public:
+    static const InterfaceID& interfaceID() { return IID_CaloFutureCorrectionBase; }
+
+    Base( const std::string& type, const std::string& name, const IInterface* parent );
+
+    StatusCode initialize() override;
+    StatusCode finalize() override;
+
+    std::optional<Result> getCorrectionAndDerivative( const Type type, const Detector::Calo::CellID id,
+                                                      const float var = 0. ) const;
+
+    std::optional<float> getCorrection( const Type type, const Detector::Calo::CellID id, const float var = 0. ) const;
+
+    const std::vector<float>& getParamVector( const Type                   type,
+                                              const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
+      return std::get<ParamVector>( m_params.get()[static_cast<int>( type )][id.area()] ).params;
+    }
+
+    const std::vector<float>& getParamVector( Parameters const& params, Type const type,
+                                              Detector::Calo::CellID const id = Detector::Calo::CellID() ) const {
+      return std::get<ParamVector>( params[static_cast<int>( type )][id.area()] ).params;
+    }
+
+    std::optional<float> getParameter( Type type, unsigned int i,
+                                       const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
+      const auto& data = getParamVector( type, id );
+      if ( i >= data.size() ) return std::nullopt;
+      return data[i];
+    }
+
+    std::optional<float> getParameter( Parameters const& params, Type type, unsigned int i,
+                                       const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
+      const auto& data = getParamVector( params, type, id );
+      if ( i >= data.size() ) return std::nullopt;
+      return data[i];
+    }
+
+  protected:
+    using IncCounter = Gaudi::Accumulators::Counter<>;
+    using ACounter   = Gaudi::Accumulators::AveragingCounter<>;
+    using SCounter   = Gaudi::Accumulators::StatCounter<>;
+
+    static constexpr int k_numOfCaloAreas{4};
+
+    template <typename P, typename COUNTER = SCounter>
+    static auto make_counters( P* parent, std::string_view prefix ) {
+      using namespace std::string_view_literals;
+      return std::apply(
+          [parent, prefix]( auto&&... args ) {
+            return std::array{COUNTER{parent, fmt::format( "{}{}", prefix, args )}...};
+          },
+          std::array{"Outer"sv, "Middle"sv, "Inner"sv, "PinArea"sv} );
+    }
+
+    LHCb::ClusterFunctors::ClusterArea       m_area;
+    Gaudi::Property<bool>                    m_correctCovariance{this, "CorrectCovariance", true};
+    Gaudi::Property<VectorOfHypothesesTypes> m_hypos{this,
+                                                     "Hypotheses",
+                                                     {
+                                                         LHCb::Event::Calo::Hypotheses::Type::Photon,
+                                                         LHCb::Event::Calo::Hypotheses::Type::PhotonFromMergedPi0,
+                                                         LHCb::Event::Calo::Hypotheses::Type::EmCharged,
+                                                     },
+                                                     "acceptable hypotheses"};
+
+  private:
+    Gaudi::Property<std::string> m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
+    Gaudi::Property<std::vector<std::string>> m_corrections{this, "Corrections", {"All"}};
+
+    std::optional<Type> accept( const std::string& name ) const {
+      auto b = std::any_of( m_corrections.begin(), m_corrections.end(),
+                            [&]( const auto& i ) { return i == name || i == "All"; } );
+      if ( !b ) return std::nullopt;
+      // check if known type
+      Type type;
+      if ( parse( type, name ).isSuccess() ) return type;
+      warning() << " o Type " << name << " is not known" << endmsg;
+      return std::nullopt;
+    }
+
+    static const char* correctionName( const Function& cp ) {
+      return std::visit( []( const auto& i ) { return i.name; }, cp );
+    }
+
+    ConditionAccessor<Parameters> m_params{this, name() + "-Parameters"};
+    void                          constructParams( Functions&, const LHCb::span<const double> );
+    Parameters                    constructParams( YAML::Node const& );
+
+  public:
+    // required by clients to retrieve internal condition m_param
+    // and use it directly when deriving their own conditions
+    // The original reason being that one cannot call get of a
+    // ConditionAccessor during condition derivation
+    std::string getParamConditionPath() { return m_params.key(); }
+  };
+
+} // namespace LHCb::Calo::Correction
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
index 2674350aaac..07ee3e4a204 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
@@ -1,12 +1,12 @@
 /*****************************************************************************\
-* (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.                                       *
+ * (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 "CaloFutureCorrectionBase.h"
 #include "CaloFutureInterfaces/ICaloFutureElectron.h"
@@ -29,16 +29,6 @@
  *  @author Deschamps Olivier
  */
 
-/** @namespace CaloFutureECorrection_Local
- */
-
-/** @class CaloFutureECorrection CaloFutureECorrection.h
- *
- *
- *  @author Deschamps Olivier
-
- *  @date   2003-03-10
- */
 namespace {
   int shiftAs( unsigned int cellIDColOrRow, LHCb::span<const int, 3> shift, unsigned int area ) {
     assert( area < 3 );
@@ -80,544 +70,547 @@ public:
   }
 };
 
-class CaloFutureECorrection : public extends<LHCb::DetDesc::ConditionAccessorHolder<CaloFutureCorrectionBase>,
-                                             LHCb::Calo::Interfaces::IProcessHypos> {
-
-public:
-  CaloFutureECorrection( const std::string& type, const std::string& name, const IInterface* parent );
-  StatusCode initialize() override;
-  StatusCode
-  process( const DeCalorimeter&, LHCb::Event::Calo::Hypotheses::Type,
-           LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous>&,
-           LHCb::CaloFuture2Track::ICluster2TrackTable2D const* ctable, IGeometryInfo const& geometry,
-           LHCb::Event::PV::PrimaryVertexContainer const& vertLoc ) const override;
-  StatusCode
-  process( const DeCalorimeter&, LHCb::Event::Calo::Hypotheses::Type,
-           LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous>&,
-           IGeometryInfo const& ) const override {
-    throw GaudiException( "process( Event::Calo::Hypotheses::Type, Event::Calo::Clusters::Range, IGeometryInfo const&, "
-                          "const EventContext& ) not implemented",
-                          name(), StatusCode::FAILURE );
-  }
+namespace LHCb::Calo {
 
-private:
-  // FIXME One should not use ConditionAccessors by hand in a Tool
-  // The Conditions should be declared at the algorithm level
-  // and be used transparently via the functional framework
-  LHCb::DetDesc::ConditionAccessor<DeCalorimeter>             m_calo{this, "DeCalo", DeCalorimeterLocation::Ecal};
-  LHCb::DetDesc::ConditionAccessor<LHCb::Detector::Calo::Map> m_offsets{this, "CaloMaps", "EcalMaps"};
-  ToolHandle<LHCb::Calo::Interfaces::IElectron> m_caloElectron{this, "ElectronTool", "CaloFutureElectron"};
-
-  struct ECorrInputParams {
-    LHCb::Detector::Calo::CellID cellID;
-    Gaudi::XYZPoint              seedPos;
-    float                        x      = 0;
-    float                        y      = 0;
-    float                        z      = 0;
-    float                        eEcal  = 0;
-    float                        dtheta = 0;
-    unsigned int                 area   = 0;
-  };
+  /**
+   *  @author Deschamps Olivier
+   *
+   *  @date   2003-03-10
+   */
+  class ECorrection : public extends<DetDesc::ConditionAccessorHolder<Correction::Base>, Interfaces::IProcessHypos> {
+
+  public:
+    ECorrection( const std::string& type, const std::string& name, const IInterface* parent );
+    StatusCode initialize() override;
+    StatusCode process( const DeCalorimeter&, Event::Calo::Hypotheses::Type,
+                        Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous>&,
+                        CaloFuture2Track::ICluster2TrackTable2D const* ctable, IGeometryInfo const& geometry,
+                        Event::PV::PrimaryVertexContainer const& vertLoc ) const override;
+    StatusCode process( const DeCalorimeter&, Event::Calo::Hypotheses::Type,
+                        Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous>&,
+                        IGeometryInfo const& ) const override {
+      throw GaudiException(
+          "process( Event::Calo::Hypotheses::Type, Event::Calo::Clusters::Range, IGeometryInfo const&, "
+          "const EventContext& ) not implemented",
+          name(), StatusCode::FAILURE );
+    }
 
-  struct ECorrOutputParams {
-    float eCor = 0;
-    // output Jacobian elements returned from calcECorrection() to process()
-    float dEcor_dXcl = 0;
-    float dEcor_dYcl = 0;
-    float dEcor_dEcl = 0;
+  private:
+    // FIXME One should not use ConditionAccessors by hand in a Tool
+    // The Conditions should be declared at the algorithm level
+    // and be used transparently via the functional framework
+    DetDesc::ConditionAccessor<DeCalorimeter>       m_calo{this, "DeCalo", DeCalorimeterLocation::Ecal};
+    DetDesc::ConditionAccessor<Detector::Calo::Map> m_offsets{this, "CaloMaps", "EcalMaps"};
+    ToolHandle<Interfaces::IElectron>               m_caloElectron{this, "ElectronTool", "CaloFutureElectron"};
+
+    struct ECorrInputParams {
+      Detector::Calo::CellID cellID;
+      Gaudi::XYZPoint        seedPos;
+      float                  x      = 0;
+      float                  y      = 0;
+      float                  z      = 0;
+      float                  eEcal  = 0;
+      float                  dtheta = 0;
+      unsigned int           area   = 0;
+    };
+
+    struct ECorrOutputParams {
+      float eCor = 0;
+      // output Jacobian elements returned from calcECorrection() to process()
+      float dEcor_dXcl = 0;
+      float dEcor_dYcl = 0;
+      float dEcor_dEcl = 0;
+
+      // intermediate variables calculated by calcECorrection() needed for debug printout inside process()
+      float alpha = 0;
+      float Asx   = 0;
+      float Asy   = 0;
+      float aG    = 0;
+      float aE    = 0;
+      float aB    = 0;
+      float aX    = 0;
+      float aY    = 0;
+      float gT    = 0;
+    };
+
+    ECorrOutputParams calcECorrection( const DeCalorimeter& calo, const ECorrInputParams& params ) const;
+
+    /// debugging necessary in case if any new corrections are added or their sequence is changed!
+    void debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
+                                      const ECorrOutputParams& outParams ) const;
+
+  private:
+    /**
+     * Update the covariance matrix of the calo hypothesis
+     * @param dEcor_dXcl jacobian element calculated for x
+     * @param dEcor_dycl jacobian element calculated for y
+     * @param dEcor_decl jacobian element calculated for energy
+     * @param hypo hypothesis to be modified
+     **/
+    void
+    updateCovariance( float dEcor_dXcl, float dEcor_dYcl, float dEcor_dEcl,
+                      Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous> ) const;
+    /**
+     * Update the position of the calo hypothesis
+     * @param Ecor corrected energy to be applied
+     * @param hypo hypothesis to be modified
+     **/
+    bool  isNotSeed( const CaloDigit* seed ) const;
+    float computeDTheta( const DeCalorimeter&                                                                  calo,
+                         Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous> cluster,
+                         CaloFuture2Track::ICluster2TrackTable2D const& ctable, IGeometryInfo const& geometry ) const;
+
+    mutable IncCounter m_counterSkippedNegativeEnergyCorrection{this, "Skip negative energy correction"};
+
+    mutable SCounter m_counterPileupOffset{this, "Pileup offset"};
+    mutable SCounter m_counterPileupSubstractedRatio{this, "Pileup subtracted ratio"};
+    mutable SCounter m_counterPileupScale{this, "Pileup scale"};
+
+    mutable IncCounter m_counterUnphysical{this, "Unphysical d(Ehypo)/d(Ecluster)"};
+
+    mutable IncCounter m_counterUnphysicalVariance{this, "Unphysical variance(Ehypo)"};
+
+    mutable std::array<SCounter, k_numOfCaloAreas> m_countersAlpha = make_counters( this, "<alpha> " );
+
+    ServiceHandle<IFileAccess> m_filesvc{this, "FileAccess", "ParamFileSvc"};
+    std::optional<PileupMap>   m_pileupMap;
+    void                       read_pileup_map() {
+      auto s = m_filesvc->read( m_pileupMapName.value() );
+      if ( !s ) throw std::runtime_error( "No PileUpCorrections found at " + m_pileupMapName.value() );
+      m_pileupMap.emplace( *s );
+    }
 
-    // intermediate variables calculated by calcECorrection() needed for debug printout inside process()
-    float alpha = 0;
-    float Asx   = 0;
-    float Asy   = 0;
-    float aG    = 0;
-    float aE    = 0;
-    float aB    = 0;
-    float aX    = 0;
-    float aY    = 0;
-    float gT    = 0;
+    Gaudi::Property<std::string> m_pileupMapName{this, "PileupMapFileName", "paramfile://data/PileUpOffset.json",
+                                                 [=]( auto& ) {
+                                                   if ( m_pileupMap ) read_pileup_map();
+                                                 }};
   };
 
-  ECorrOutputParams calcECorrection( const DeCalorimeter& calo, const ECorrInputParams& params ) const;
+  DECLARE_COMPONENT_WITH_ID( ECorrection, "CaloFutureECorrection" )
 
-  /// debugging necessary in case if any new corrections are added or their sequence is changed!
-  void debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
-                                    const ECorrOutputParams& outParams ) const;
+  namespace {
 
-private:
-  /**
-   * Update the covariance matrix of the calo hypothesis
-   * @param dEcor_dXcl jacobian element calculated for x
-   * @param dEcor_dycl jacobian element calculated for y
-   * @param dEcor_decl jacobian element calculated for energy
-   * @param hypo hypothesis to be modified
-   **/
-  void updateCovariance(
-      float dEcor_dXcl, float dEcor_dYcl, float dEcor_dEcl,
-      LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> ) const;
-  /**
-   * Update the position of the calo hypothesis
-   * @param Ecor corrected energy to be applied
-   * @param hypo hypothesis to be modified
-   **/
-  bool  isNotSeed( const LHCb::CaloDigit* seed ) const;
-  float computeDTheta(
-      const DeCalorimeter&                                                                              calo,
-      LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cluster,
-      LHCb::CaloFuture2Track::ICluster2TrackTable2D const& ctable, IGeometryInfo const& geometry ) const;
-
-  mutable IncCounter m_counterSkippedNegativeEnergyCorrection{this, "Skip negative energy correction"};
-
-  mutable SCounter m_counterPileupOffset{this, "Pileup offset"};
-  mutable SCounter m_counterPileupSubstractedRatio{this, "Pileup subtracted ratio"};
-  mutable SCounter m_counterPileupScale{this, "Pileup scale"};
-
-  mutable IncCounter m_counterUnphysical{this, "Unphysical d(Ehypo)/d(Ecluster)"};
-
-  mutable IncCounter m_counterUnphysicalVariance{this, "Unphysical variance(Ehypo)"};
-
-  mutable std::array<SCounter, k_numOfCaloAreas> m_countersAlpha = make_counters( this, "<alpha> " );
-
-  ServiceHandle<IFileAccess> m_filesvc{this, "FileAccess", "ParamFileSvc"};
-  std::optional<PileupMap>   m_pileupMap;
-  void                       read_pileup_map() {
-    auto s = m_filesvc->read( m_pileupMapName.value() );
-    if ( !s ) throw std::runtime_error( "No PileUpCorrections found at " + m_pileupMapName.value() );
-    m_pileupMap.emplace( *s );
-  }
-
-  Gaudi::Property<std::string> m_pileupMapName{this, "PileupMapFileName", "paramfile://data/PileUpOffset.json",
-                                               [=]( auto& ) {
-                                                 if ( m_pileupMap ) read_pileup_map();
-                                               }};
-};
-
-DECLARE_COMPONENT( CaloFutureECorrection )
-
-namespace {
-
-  LHCb::Detector::Calo::Map createMap( const DeCalorimeter& caloDet ) {
-    LHCb::Detector::Calo::Map map;
-    // fill the maps from the CaloFuture DetElem
-    for ( const auto& c : caloDet.cellParams() ) {
-      const auto id = c.cellID();
-      if ( !caloDet.valid( id ) || id.isPin() ) continue;
-      map[id] = c.pileUpOffset();
+    Detector::Calo::Map createMap( const DeCalorimeter& caloDet ) {
+      Detector::Calo::Map map;
+      // fill the maps from the CaloFuture DetElem
+      for ( const auto& c : caloDet.cellParams() ) {
+        const auto id = c.cellID();
+        if ( !caloDet.valid( id ) || id.isPin() ) continue;
+        map[id] = c.pileUpOffset();
+      }
+      return map;
     }
-    return map;
-  }
 
-  float computeOffset( DeCalorimeter const& calo, PileupMap const& pileupMap, LHCb::Detector::Calo::CellID id,
-                       int nPV ) {
-    if ( id.calo() != calo.index() ) { throw std::invalid_argument( "Wrong Calorimeter for this instance" ); }
-    float pileupParam = pileupMap.at( id );
-    return pileupParam * nPV;
-  }
-} // namespace
-
-CaloFutureECorrection::CaloFutureECorrection( const std::string& type, const std::string& name,
-                                              const IInterface* parent )
-    : extends( type, name, parent ) {
-
-  // define conditionName
-  const std::string uName( LHCb::CaloFutureAlgUtils::toUpper( name ) );
-  if ( uName.find( "ELECTRON" ) != std::string::npos ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/ElectronECorrection" ).ignore();
-  } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/SplitPhotonECorrection" ).ignore();
-  } else if ( uName.find( "PHOTON" ) ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/PhotonECorrection" ).ignore();
-  }
-}
-
-StatusCode CaloFutureECorrection::initialize() {
-  return extends::initialize().andThen( [&] {
-    this->addSharedConditionDerivation( {m_calo.key()}, m_offsets.key(), &createMap );
-    read_pileup_map();
-  } );
-}
-
-StatusCode CaloFutureECorrection::process(
-    const DeCalorimeter& calo, LHCb::Event::Calo::Hypotheses::Type hypo,
-    LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous>& cluster,
-    LHCb::CaloFuture2Track::ICluster2TrackTable2D const* ctable, IGeometryInfo const& geometry,
-    LHCb::Event::PV::PrimaryVertexContainer const& vertLoc ) const {
-
-  auto h = std::find( m_hypos.begin(), m_hypos.end(), hypo );
-  if ( m_hypos.end() == h ) { return Error( "Invalid hypothesis -> no correction applied", StatusCode::SUCCESS ); }
-
-  auto counterSkippedNegativeEnergyCorrection = m_counterSkippedNegativeEnergyCorrection.buffer();
-  auto counterPileupOffset                    = m_counterPileupOffset.buffer();
-  auto counterPileupSubstractedRatio          = m_counterPileupSubstractedRatio.buffer();
-  auto counterUnphysical                      = m_counterUnphysical.buffer();
-
-  int pileup_cache = vertLoc.size();
-  m_counterPileupScale += pileup_cache;
-
-  if ( cluster.e() < 0. ) {
-    ++counterSkippedNegativeEnergyCorrection;
-    return StatusCode::SUCCESS;
-  }
-
-  // Get position
-  const auto& position = cluster.position();
-  float       eEcal    = cluster.e();
-  const float xBar     = position.x();
-  const float yBar     = position.y();
-
-  // Cell ID for seed digit
-  LHCb::Detector::Calo::CellID cellID  = cluster.cellID();
-  Gaudi::XYZPoint              seedPos = calo.cellCenter( cellID );
-
-  float dtheta = ( ( LHCb::Event::Calo::Hypotheses::Type::EmCharged == hypo && ctable )
-                       ? computeDTheta( calo, cluster, *ctable, geometry )
-                       : 0. );
-
-  // Pileup subtraction at the digit level
-  float eEcalPUcorr = 0;
-  float offsettot   = 0;
-  for ( auto entry : cluster.entries() ) { /// Loop over calocluster::entries
-    float offset = computeOffset( calo, *m_pileupMap, entry.cellID(), pileup_cache );
-    if ( entry.status().test( LHCb::CaloDigitStatus::Mask::UseForEnergy ) ) {
-      float fraction = entry.fraction();
-      eEcalPUcorr += ( entry.energy() - offset ) * fraction;
-      offsettot += offset * fraction;
+    float computeOffset( DeCalorimeter const& calo, PileupMap const& pileupMap, Detector::Calo::CellID id, int nPV ) {
+      if ( id.calo() != calo.index() ) { throw std::invalid_argument( "Wrong Calorimeter for this instance" ); }
+      float pileupParam = pileupMap.at( id );
+      return pileupParam * nPV;
+    }
+  } // namespace
+
+  ECorrection::ECorrection( const std::string& type, const std::string& name, const IInterface* parent )
+      : extends( type, name, parent ) {
+
+    // define conditionName
+    const std::string uName( CaloFutureAlgUtils::toUpper( name ) );
+    if ( uName.find( "ELECTRON" ) != std::string::npos ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/ElectronECorrection" ).ignore();
+    } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/SplitPhotonECorrection" ).ignore();
+    } else if ( uName.find( "PHOTON" ) ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/PhotonECorrection" ).ignore();
     }
   }
-  if ( eEcalPUcorr < 0. ) {
-    ++counterSkippedNegativeEnergyCorrection;
-    return StatusCode::SUCCESS;
-  }
-  counterPileupOffset += offsettot;
-  counterPileupSubstractedRatio += eEcalPUcorr / eEcal;
-  eEcal = eEcalPUcorr;
 
-  /** here all information is available
-   *
-   *  (1) Ecal energy in 3x3     :    eEcal
-   *  ( ) Prs and Spd energies   :    ePrs, eSpd ( not used )
-   *  (3) weighted barycenter    :    xBar, yBar
-   *  (4) Zone/Area in Ecal      :    area
-   *  (5) SEED digit             :    seed    (NO for split!)
-   *  (6) CellID of seed digit   :    cellID  (OK for split!)
-   *  (7) Position of seed cell  :    seedPos (OK for split!)
-   *
-   */
-  ECorrInputParams params{cellID, seedPos, xBar, yBar, (float)position.z(), eEcal, dtheta, cellID.area()};
+  StatusCode ECorrection::initialize() {
+    return extends::initialize().andThen( [&] {
+      this->addSharedConditionDerivation( {m_calo.key()}, m_offsets.key(), &createMap );
+      read_pileup_map();
+    } );
+  }
 
-  /////////////////////////////////////////////////////////
+  StatusCode
+  ECorrection::process( const DeCalorimeter& calo, Event::Calo::Hypotheses::Type hypo,
+                        Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous>& cluster,
+                        CaloFuture2Track::ICluster2TrackTable2D const* ctable, IGeometryInfo const& geometry,
+                        Event::PV::PrimaryVertexContainer const& vertLoc ) const {
 
-  /* Calculate corrected energy in a separate function call. Necessary for debugging the Jacobian by calculating
-   * numeric derivatives w.r.t. (X, Y, E) in case of any changes in the correction code.
-   *
-   * Input positions and energies are passed as parameters for ease of numeric derivative calculation,
-   * all the other paramers and results of intermediate calculations are shared between the two methods
-   * using local ECorrInputParams _params, and [zero-initialized] ECorrOutputParams _results.
-   */
-  ECorrOutputParams results = calcECorrection( calo, params );
-  float             eCor    = results.eCor;
-
-  // results of semi-analytic derivative calculation
-  const float& dEcor_dXcl = results.dEcor_dXcl;
-  const float& dEcor_dYcl = results.dEcor_dYcl;
-  float&       dEcor_dEcl = results.dEcor_dEcl;
-
-  // protection against unphysical d(Ehypo)/d(Ecluster) == 0
-  if ( fabs( dEcor_dEcl ) < 1e-10 ) {
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << "unphysical d(Ehypo)/d(Ecluster) = " << dEcor_dEcl << " reset to 1 as if Ehypo = Ecluster" << endmsg;
-    ++counterUnphysical;
-    dEcor_dEcl = 1.;
-  }
+    auto h = std::find( m_hypos.begin(), m_hypos.end(), hypo );
+    if ( m_hypos.end() == h ) { return Error( "Invalid hypothesis -> no correction applied", StatusCode::SUCCESS ); }
 
-  // debugging necessary in case if any new corrections are added or their sequence is changed!
-  if ( msgLevel( MSG::DEBUG ) ) {
-    if ( m_correctCovariance ) debugDerivativesCalculation( calo, params, results );
-  }
+    auto counterSkippedNegativeEnergyCorrection = m_counterSkippedNegativeEnergyCorrection.buffer();
+    auto counterPileupOffset                    = m_counterPileupOffset.buffer();
+    auto counterPileupSubstractedRatio          = m_counterPileupSubstractedRatio.buffer();
+    auto counterUnphysical                      = m_counterUnphysical.buffer();
 
-  m_countersAlpha.at( cellID.area() ) += results.alpha;
+    int pileup_cache = vertLoc.size();
+    m_counterPileupScale += pileup_cache;
 
-  // update position
-  cluster.setEnergy( eCor );
+    if ( cluster.e() < 0. ) {
+      ++counterSkippedNegativeEnergyCorrection;
+      return StatusCode::SUCCESS;
+    }
 
-  // ----------------------------------------- apply semi-analytic cov.m. propagation due to the (X,Y,E) corrections
-  if ( m_correctCovariance ) { updateCovariance( dEcor_dXcl, dEcor_dYcl, dEcor_dEcl, cluster ); }
+    // Get position
+    const auto& position = cluster.position();
+    float       eEcal    = cluster.e();
+    const float xBar     = position.x();
+    const float yBar     = position.y();
+
+    // Cell ID for seed digit
+    Detector::Calo::CellID cellID  = cluster.cellID();
+    Gaudi::XYZPoint        seedPos = calo.cellCenter( cellID );
+
+    float dtheta = ( ( Event::Calo::Hypotheses::Type::EmCharged == hypo && ctable )
+                         ? computeDTheta( calo, cluster, *ctable, geometry )
+                         : 0. );
+
+    // Pileup subtraction at the digit level
+    float eEcalPUcorr = 0;
+    float offsettot   = 0;
+    for ( auto entry : cluster.entries() ) { /// Loop over calocluster::entries
+      float offset = computeOffset( calo, *m_pileupMap, entry.cellID(), pileup_cache );
+      if ( entry.status().test( CaloDigitStatus::Mask::UseForEnergy ) ) {
+        float fraction = entry.fraction();
+        eEcalPUcorr += ( entry.energy() - offset ) * fraction;
+        offsettot += offset * fraction;
+      }
+    }
+    if ( eEcalPUcorr < 0. ) {
+      ++counterSkippedNegativeEnergyCorrection;
+      return StatusCode::SUCCESS;
+    }
+    counterPileupOffset += offsettot;
+    counterPileupSubstractedRatio += eEcalPUcorr / eEcal;
+    eEcal = eEcalPUcorr;
+
+    /** here all information is available
+     *
+     *  (1) Ecal energy in 3x3     :    eEcal
+     *  ( ) Prs and Spd energies   :    ePrs, eSpd ( not used )
+     *  (3) weighted barycenter    :    xBar, yBar
+     *  (4) Zone/Area in Ecal      :    area
+     *  (5) SEED digit             :    seed    (NO for split!)
+     *  (6) CellID of seed digit   :    cellID  (OK for split!)
+     *  (7) Position of seed cell  :    seedPos (OK for split!)
+     *
+     */
+    ECorrInputParams params{cellID, seedPos, xBar, yBar, (float)position.z(), eEcal, dtheta, cellID.area()};
+
+    /////////////////////////////////////////////////////////
+
+    /* Calculate corrected energy in a separate function call. Necessary for debugging the Jacobian by calculating
+     * numeric derivatives w.r.t. (X, Y, E) in case of any changes in the correction code.
+     *
+     * Input positions and energies are passed as parameters for ease of numeric derivative calculation,
+     * all the other paramers and results of intermediate calculations are shared between the two methods
+     * using local ECorrInputParams _params, and [zero-initialized] ECorrOutputParams _results.
+     */
+    ECorrOutputParams results = calcECorrection( calo, params );
+    float             eCor    = results.eCor;
+
+    // results of semi-analytic derivative calculation
+    const float& dEcor_dXcl = results.dEcor_dXcl;
+    const float& dEcor_dYcl = results.dEcor_dYcl;
+    float&       dEcor_dEcl = results.dEcor_dEcl;
+
+    // protection against unphysical d(Ehypo)/d(Ecluster) == 0
+    if ( fabs( dEcor_dEcl ) < 1e-10 ) {
+      if ( msgLevel( MSG::DEBUG ) )
+        debug() << "unphysical d(Ehypo)/d(Ecluster) = " << dEcor_dEcl << " reset to 1 as if Ehypo = Ecluster" << endmsg;
+      ++counterUnphysical;
+      dEcor_dEcl = 1.;
+    }
 
-  return StatusCode::SUCCESS;
-}
+    // debugging necessary in case if any new corrections are added or their sequence is changed!
+    if ( msgLevel( MSG::DEBUG ) ) {
+      if ( m_correctCovariance ) debugDerivativesCalculation( calo, params, results );
+    }
 
-void CaloFutureECorrection::updateCovariance(
-    float dEcor_dXcl, float dEcor_dYcl, float dEcor_dEcl,
-    LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cluster ) const {
+    m_countersAlpha.at( cellID.area() ) += results.alpha;
 
-  auto                           counterUnphysicalVariance = m_counterUnphysicalVariance.buffer();
-  LHCb::CaloPosition::Covariance covariance                = cluster.covariance();
-  LHCb::LinAlg::MatSym<SIMDWrapper::scalar::float_v, 3> covarianceOut;
+    // update position
+    cluster.setEnergy( eCor );
 
-  if ( msgLevel( MSG::DEBUG ) ) { debug() << "before E-corr. cov.m. = \n" << covariance << endmsg; }
+    // ----------------------------------------- apply semi-analytic cov.m. propagation due to the (X,Y,E) corrections
+    if ( m_correctCovariance ) { updateCovariance( dEcor_dXcl, dEcor_dYcl, dEcor_dEcl, cluster ); }
 
-  // index numbering just follows ROOT::Math::SMatrix<double,3,3>::Array() for row/column indices (X:0, Y:1, E:2)
-  float c0[6], c1[6];
-  /*
-   * Indexing following ROOT::Math::SMatrix<double,3,3,ROOT::Math::MatRepSym<double,3> >::Array() :
-   *
-   * The iterators access the matrix element in the order how they are
-   * stored in memory. The C (row-major) convention is used, and in the
-   * case of symmetric matrices the iterator spans only the lower diagonal
-   * block. For example for a symmetric 3x3 matrices the order of the 6
-   * elements \f${a_0,...a_5}\f$ is:
-   * \f[
-   * M = \left( \begin{array}{ccc}
-   *     a_0 & a_1 & a_3  \\
-   *     a_1 & a_2  & a_4  \\
-   *     a_3 & a_4 & a_5   \end{array} \right)
-   * \f]
-   */
-  c0[0] = covariance( LHCb::CaloPosition::Index::X,
-                      LHCb::CaloPosition::Index::X ); // arr[0] not relying on LHCb::CaloFuturePosition::Index::X == 0
-  c0[1] = covariance( LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y ); // arr[1]
-  c0[2] = covariance( LHCb::CaloPosition::Index::Y,
-                      LHCb::CaloPosition::Index::Y ); // arr[2] not relying on LHCb::CaloFuturePosition::Index::Y == 1
-  c0[3] = covariance( LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E ); // arr[3]
-  c0[4] = covariance( LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E ); // arr[4]
-  c0[5] = covariance( LHCb::CaloPosition::Index::E,
-                      LHCb::CaloPosition::Index::E ); // arr[5] not relying on LHCb::CaloFuturePosition::Index::E == 2
-
-  // cov1 = (J * cov0 * J^T) for the special case of Jacobian for (X,Y,E) -> (X1=X, Y1=Y, E1=E(X,Y,E))
-  c1[0]     = c0[0];
-  c1[1]     = c0[1];
-  c1[2]     = c0[2];
-  c1[3]     = c0[0] * dEcor_dXcl + c0[1] * dEcor_dYcl + c0[3] * dEcor_dEcl;
-  c1[4]     = c0[1] * dEcor_dXcl + c0[2] * dEcor_dYcl + c0[4] * dEcor_dEcl;
-  float tmp = c0[3] * dEcor_dXcl + c0[4] * dEcor_dYcl + c0[5] * dEcor_dEcl;
-  c1[5]     = c1[3] * dEcor_dXcl + c1[4] * dEcor_dYcl + tmp * dEcor_dEcl;
-
-  // additional protection against cov.m.(E,E) <= 0 due to numerical effects
-  if ( c1[5] < 1.e-10 ) {
-    if ( msgLevel( MSG::DEBUG ) )
-      debug() << "unphysical variance(Ehypo) = " << c1[5]
-              << " reset cov.m.(Ehypo,*) = cov.m.(Ecluster,*) as if Ehypo = Ecluster" << endmsg;
-    ++counterUnphysicalVariance;
-    c1[5] = c0[5];
-    c1[3] = c0[3];
-    c1[4] = c0[4];
+    return StatusCode::SUCCESS;
   }
 
-  // finally update CaloHypo::position()->covariance()
-  covarianceOut( LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X ) = c1[0]; // cov1(0,0);
-  covarianceOut( LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y ) = c1[2]; // cov1(1,1);
-  covarianceOut( LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E ) = c1[5]; // cov1(2,2);
-  covarianceOut( LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y ) = c1[1]; // cov1(0,1);
-  covarianceOut( LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E ) = c1[3]; // cov1(0,2);
-  covarianceOut( LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E ) = c1[4]; // cov1(1,2);
-  cluster.setCovariance( covarianceOut );
-
-  if ( msgLevel( MSG::DEBUG ) ) { debug() << "after E-corr. cov.m. = \n" << covariance << endmsg; }
-}
-
-CaloFutureECorrection::ECorrOutputParams
-CaloFutureECorrection::calcECorrection( const DeCalorimeter& calo, const ECorrInputParams& _params ) const {
-  // local aliases for the input variables passed from process() to calcECorrection()
-  const LHCb::Detector::Calo::CellID& cellID  = _params.cellID;
-  const Gaudi::XYZPoint&              seedPos = _params.seedPos;
-  const float&                        dtheta  = _params.dtheta;
-  const unsigned int&                 area    = _params.area;
-  float                               xBar    = _params.x;
-  float                               yBar    = _params.y;
-  float                               eEcal   = _params.eEcal;
-
-  float CellSize = calo.cellSize( cellID );
-  float Asx      = ( xBar - seedPos.x() ) / CellSize; // Asx0
-  float Asy      = ( yBar - seedPos.y() ) / CellSize; // Asy0
-
-  const float Asx0 = Asx;
-  const float Asy0 = Asy;
-
-  float bDist = LHCb::Math::Approx::approx_sqrt( 2.f * ( Asx * Asx + Asy * Asy ) );
-
-  int signX = shiftAs( cellID.col(), std::array{0, 0, 8}, area );
-  int signY = shiftAs( cellID.row(), std::array{6, 12, 14}, area );
-  Asx *= signX; // Asx1
-  Asy *= signY; // Asy1
-
-  // analytic derivatives of the correction functions
-  float DaE( 0 ), DaB( 0 ), DaX( 0 ), DaY( 0 );
-
-  //
-  // apply corrections
-  // NB: numeric derivative calculation calls and printouts which are commented-out below
-  // are useful for debugging in case of changes in the correction function code
-  //
-  //// aG = const(X,Y,E), no need to calculate derivatives
-  float aG = getCorrection( CaloFutureCorrection::alphaG, cellID ).value_or( 1. ); // global Ecal factor
-  //// aE = alphaE(eEcal)
-  const auto aECorDer = getCorrectionAndDerivative( CaloFutureCorrection::alphaE, cellID, eEcal )
-                            .value_or( CorrectionResult{1., 0.} ); // longitudinal leakage
-  const auto aE       = aECorDer.value;
-  const auto aBCorDer = getCorrectionAndDerivative( CaloFutureCorrection::alphaB, cellID, bDist )
-                            .value_or( CorrectionResult{1., 0.} ); // lateral leakage
-  const auto aB = aBCorDer.value;
-  //// aX = alphaX(Asx1)
-  const auto aXCorDer = getCorrectionAndDerivative( CaloFutureCorrection::alphaX, cellID, Asx )
-                            .value_or( CorrectionResult{1., 0.} ); // module frame dead material X-direction
-  const auto aX = aXCorDer.value;
-  //// aY = alphaY(Asy1)
-  const auto aYCorDer = getCorrectionAndDerivative( CaloFutureCorrection::alphaY, cellID, Asy )
-                            .value_or( CorrectionResult{1., 0.} ); // module frame dead material Y-direction
-  const auto aY = aYCorDer.value;
-  if ( m_correctCovariance ) {
-    DaE = aECorDer.derivative;
-    DaB = aBCorDer.derivative;
-    DaX = aXCorDer.derivative;
-    DaY = aYCorDer.derivative;
-  }
+  void ECorrection::updateCovariance(
+      float dEcor_dXcl, float dEcor_dYcl, float dEcor_dEcl,
+      Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous> cluster ) const {
+
+    auto                                            counterUnphysicalVariance = m_counterUnphysicalVariance.buffer();
+    CaloPosition::Covariance                        covariance                = cluster.covariance();
+    LinAlg::MatSym<SIMDWrapper::scalar::float_v, 3> covarianceOut;
+
+    if ( msgLevel( MSG::DEBUG ) ) { debug() << "before E-corr. cov.m. = \n" << covariance << endmsg; }
+
+    // index numbering just follows ROOT::Math::SMatrix<double,3,3>::Array() for row/column indices (X:0, Y:1, E:2)
+    float c0[6], c1[6];
+    /*
+     * Indexing following ROOT::Math::SMatrix<double,3,3,ROOT::Math::MatRepSym<double,3> >::Array() :
+     *
+     * The iterators access the matrix element in the order how they are
+     * stored in memory. The C (row-major) convention is used, and in the
+     * case of symmetric matrices the iterator spans only the lower diagonal
+     * block. For example for a symmetric 3x3 matrices the order of the 6
+     * elements \f${a_0,...a_5}\f$ is:
+     * \f[
+     * M = \left( \begin{array}{ccc}
+     *     a_0 & a_1 & a_3  \\
+     *     a_1 & a_2  & a_4  \\
+     *     a_3 & a_4 & a_5   \end{array} \right)
+     * \f]
+     */
+    c0[0] = covariance( CaloPosition::Index::X,
+                        CaloPosition::Index::X ); // arr[0] not relying on CaloFuturePosition::Index::X == 0
+    c0[1] = covariance( CaloPosition::Index::X, CaloPosition::Index::Y ); // arr[1]
+    c0[2] = covariance( CaloPosition::Index::Y,
+                        CaloPosition::Index::Y ); // arr[2] not relying on CaloFuturePosition::Index::Y == 1
+    c0[3] = covariance( CaloPosition::Index::X, CaloPosition::Index::E ); // arr[3]
+    c0[4] = covariance( CaloPosition::Index::Y, CaloPosition::Index::E ); // arr[4]
+    c0[5] = covariance( CaloPosition::Index::E,
+                        CaloPosition::Index::E ); // arr[5] not relying on CaloFuturePosition::Index::E == 2
+
+    // cov1 = (J * cov0 * J^T) for the special case of Jacobian for (X,Y,E) -> (X1=X, Y1=Y, E1=E(X,Y,E))
+    c1[0]     = c0[0];
+    c1[1]     = c0[1];
+    c1[2]     = c0[2];
+    c1[3]     = c0[0] * dEcor_dXcl + c0[1] * dEcor_dYcl + c0[3] * dEcor_dEcl;
+    c1[4]     = c0[1] * dEcor_dXcl + c0[2] * dEcor_dYcl + c0[4] * dEcor_dEcl;
+    float tmp = c0[3] * dEcor_dXcl + c0[4] * dEcor_dYcl + c0[5] * dEcor_dEcl;
+    c1[5]     = c1[3] * dEcor_dXcl + c1[4] * dEcor_dYcl + tmp * dEcor_dEcl;
+
+    // additional protection against cov.m.(E,E) <= 0 due to numerical effects
+    if ( c1[5] < 1.e-10 ) {
+      if ( msgLevel( MSG::DEBUG ) )
+        debug() << "unphysical variance(Ehypo) = " << c1[5]
+                << " reset cov.m.(Ehypo,*) = cov.m.(Ecluster,*) as if Ehypo = Ecluster" << endmsg;
+      ++counterUnphysicalVariance;
+      c1[5] = c0[5];
+      c1[3] = c0[3];
+      c1[4] = c0[4];
+    }
 
-  // angular correction
-  // assume dtheta to be independent of X,Y,E, although it may still be implicitly a bit dependent on X,Y
-  float gT = getCorrection( CaloFutureCorrection::globalT, cellID, dtheta ).value_or( 1. ); // incidence angle (delta)
-  float dT = getCorrection( CaloFutureCorrection::offsetT, cellID, dtheta ).value_or( 0. ); // incidence angle (delta)
+    // finally update CaloHypo::position()->covariance()
+    covarianceOut( CaloPosition::Index::X, CaloPosition::Index::X ) = c1[0]; // cov1(0,0);
+    covarianceOut( CaloPosition::Index::Y, CaloPosition::Index::Y ) = c1[2]; // cov1(1,1);
+    covarianceOut( CaloPosition::Index::E, CaloPosition::Index::E ) = c1[5]; // cov1(2,2);
+    covarianceOut( CaloPosition::Index::X, CaloPosition::Index::Y ) = c1[1]; // cov1(0,1);
+    covarianceOut( CaloPosition::Index::X, CaloPosition::Index::E ) = c1[3]; // cov1(0,2);
+    covarianceOut( CaloPosition::Index::Y, CaloPosition::Index::E ) = c1[4]; // cov1(1,2);
+    cluster.setCovariance( covarianceOut );
 
-  // Energy offset
-  float sinT   = calo.cellSine( cellID );
-  float offset = getCorrection( CaloFutureCorrection::offset, cellID, sinT ).value_or( 0. );
+    if ( msgLevel( MSG::DEBUG ) ) { debug() << "after E-corr. cov.m. = \n" << covariance << endmsg; }
+  }
 
-  // Apply Ecal leakage corrections
-  float alpha = aG * aE * aB * aX * aY;
-  float eCor  = eEcal * alpha * gT + dT + offset;
+  ECorrection::ECorrOutputParams ECorrection::calcECorrection( const DeCalorimeter&    calo,
+                                                               const ECorrInputParams& _params ) const {
+    // local aliases for the input variables passed from process() to calcECorrection()
+    const Detector::Calo::CellID& cellID  = _params.cellID;
+    const Gaudi::XYZPoint&        seedPos = _params.seedPos;
+    const float&                  dtheta  = _params.dtheta;
+    const unsigned int&           area    = _params.area;
+    float                         xBar    = _params.x;
+    float                         yBar    = _params.y;
+    float                         eEcal   = _params.eEcal;
+
+    float CellSize = calo.cellSize( cellID );
+    float Asx      = ( xBar - seedPos.x() ) / CellSize; // Asx0
+    float Asy      = ( yBar - seedPos.y() ) / CellSize; // Asy0
+
+    const float Asx0 = Asx;
+    const float Asy0 = Asy;
+
+    float bDist = Math::Approx::approx_sqrt( 2.f * ( Asx * Asx + Asy * Asy ) );
+
+    int signX = shiftAs( cellID.col(), std::array{0, 0, 8}, area );
+    int signY = shiftAs( cellID.row(), std::array{6, 12, 14}, area );
+    Asx *= signX; // Asx1
+    Asy *= signY; // Asy1
+
+    // analytic derivatives of the correction functions
+    float DaE( 0 ), DaB( 0 ), DaX( 0 ), DaY( 0 );
+
+    //
+    // apply corrections
+    // NB: numeric derivative calculation calls and printouts which are commented-out below
+    // are useful for debugging in case of changes in the correction function code
+    //
+    //// aG = const(X,Y,E), no need to calculate derivatives
+    float aG = getCorrection( Correction::Type::alphaG, cellID ).value_or( 1. ); // global Ecal factor
+    //// aE = alphaE(eEcal)
+    const auto aECorDer = getCorrectionAndDerivative( Correction::Type::alphaE, cellID, eEcal )
+                              .value_or( Correction::Result{1., 0.} ); // longitudinal leakage
+    const auto aE       = aECorDer.value;
+    const auto aBCorDer = getCorrectionAndDerivative( Correction::Type::alphaB, cellID, bDist )
+                              .value_or( Correction::Result{1., 0.} ); // lateral leakage
+    const auto aB = aBCorDer.value;
+    //// aX = alphaX(Asx1)
+    const auto aXCorDer = getCorrectionAndDerivative( Correction::Type::alphaX, cellID, Asx )
+                              .value_or( Correction::Result{1., 0.} ); // module frame dead material X-direction
+    const auto aX = aXCorDer.value;
+    //// aY = alphaY(Asy1)
+    const auto aYCorDer = getCorrectionAndDerivative( Correction::Type::alphaY, cellID, Asy )
+                              .value_or( Correction::Result{1., 0.} ); // module frame dead material Y-direction
+    const auto aY = aYCorDer.value;
+    if ( m_correctCovariance ) {
+      DaE = aECorDer.derivative;
+      DaB = aBCorDer.derivative;
+      DaX = aXCorDer.derivative;
+      DaY = aYCorDer.derivative;
+    }
 
-  /* DG,20190421: derivative calculation simplified by removal of SPD and PRS
-   *
-   * Asx0  = (Xcluster-seedPos.x)/CellSize
-   * bDist = sqrt(2)*sqrt(Asx0**2+Asy0**2)
-   * signX = signX(cellID); // const(X,Y,Ecluster)
-   * Asx1  = signX*Asx0
-   * eEcal = Ecluster - pileup_offset(cellID, eSpd = 0); // => d(eEcal)/d(Ecluster) = 1
-   * aG    = alphaG(cellID); // const(X,Y, Ecluster)
-   * aE    = alphaE(eEcal)
-   * aB    = alphaB(bDist)
-   * aX    = alphaX(Asx1)
-   * aY    = alphaY(Asy1)
-   * gT    = globalT(dtheta); // const(X,Y,Ecluster) although dtheta may indirectly depend on (X,Y)
-   * dT    = offsetT(dtheta); // const(X,Y,Ecluster)
-   * sinT  = cellSince(cellID); // const(X,Y,Ecluster)
-   * offset= offset(cellID, sinT); // const(X,Y,Ecluster) at eSpd = 0
-   * gC    = 1; // at eSpd = 0
-   *
-   * d(Asx0)/dX       = +1/CellSize
-   * d(Asx1)/d(Asx0)  = signX
-   * d(bDist)/d(Asx0) = sqrt(2)*2*Asx0/2/sqrt(Asx0**2+Asy0**2) = 2*Asx0/bDist; // if bDist != 0, otherwise 0
-   *   if bDist=0 <=> (Asx=0,Asy=0), but for any Asy!=0 (if Asx=0 => d(bDist)/d(Asx) = 0)
-   *   => for continuity similarly define the same for Asy=0, i.e. if bDist=0 => d(bDist)/d(Asx) = 0
-   *
-   * d(aB)/dX             = d(aB)/d(bDist)*d(bDist)/d(Asx0)*d(Asx0)/dX = DalphpaB*(2*Asx0/bDist)*(1/CellSize)
-   * d(aX)/dX             = d(aX)/d(Asx1)*d(Asx1)/d(Asx0)*d(Asx0)/dX = DalphaX*signX*(1/CellSize)
-   * d(eEcal)/d(Ecluster) = 1
-   *
-   * alpha = aG * aE(eEcal) * aB(bDist) * aX(Asx1) * aY(Asy1);
-   * Ehypo = eCor = eEcal * alpha(eEcal, bDist, Asx1, Asy1) * (gC = 1) * gT + dT + offset;
-   *
-   * d(alpha)/d(eEcal) = (aG*aB*aX*aY) * d(aE)/d(eEcal) = (alpha/aE) * DalphaE; // if aE!=0, otherwise
-   * aG*aB*aX*aY*DalphaE
-   *
-   *
-   * d(Ehypo)/d(Ecluster) = gT*(eEcal*d(alpha)/d(eEcal) + alpha) = gT * alpha * (1. + DaE / aE * eEcal)
-   * d(Ehypo)/d(Xcluster) = gT*eEcal*d(alpha)/dX = gT*eEcal*aG*aE*aY*(d(aB)/dX*aX+d(aX)/dX*aB)
-   *                      = gT * eEcal * aG * aE * aY * (DaB*2.*Asx0/bDist*aX + signX*aB*DaX)/CellSize
-   * d(Ehypo)/d(Ycluster) = [ same as for d(Ehypo)/d(Xcluster) with ( X <-> Y ) ]
-   * 			  = gT * eEcal * aG * aE * aX * (DaB*2.*Asy0/bDist*aY + signY*aB*DaY)/CellSize
-   */
+    // angular correction
+    // assume dtheta to be independent of X,Y,E, although it may still be implicitly a bit dependent on X,Y
+    float gT = getCorrection( Correction::Type::globalT, cellID, dtheta ).value_or( 1. ); // incidence angle (delta)
+    float dT = getCorrection( Correction::Type::offsetT, cellID, dtheta ).value_or( 0. ); // incidence angle (delta)
+
+    // Energy offset
+    float sinT   = calo.cellSine( cellID );
+    float offset = getCorrection( Correction::Type::offset, cellID, sinT ).value_or( 0. );
+
+    // Apply Ecal leakage corrections
+    float alpha = aG * aE * aB * aX * aY;
+    float eCor  = eEcal * alpha * gT + dT + offset;
+
+    /* DG,20190421: derivative calculation simplified by removal of SPD and PRS
+     *
+     * Asx0  = (Xcluster-seedPos.x)/CellSize
+     * bDist = sqrt(2)*sqrt(Asx0**2+Asy0**2)
+     * signX = signX(cellID); // const(X,Y,Ecluster)
+     * Asx1  = signX*Asx0
+     * eEcal = Ecluster - pileup_offset(cellID, eSpd = 0); // => d(eEcal)/d(Ecluster) = 1
+     * aG    = alphaG(cellID); // const(X,Y, Ecluster)
+     * aE    = alphaE(eEcal)
+     * aB    = alphaB(bDist)
+     * aX    = alphaX(Asx1)
+     * aY    = alphaY(Asy1)
+     * gT    = globalT(dtheta); // const(X,Y,Ecluster) although dtheta may indirectly depend on (X,Y)
+     * dT    = offsetT(dtheta); // const(X,Y,Ecluster)
+     * sinT  = cellSince(cellID); // const(X,Y,Ecluster)
+     * offset= offset(cellID, sinT); // const(X,Y,Ecluster) at eSpd = 0
+     * gC    = 1; // at eSpd = 0
+     *
+     * d(Asx0)/dX       = +1/CellSize
+     * d(Asx1)/d(Asx0)  = signX
+     * d(bDist)/d(Asx0) = sqrt(2)*2*Asx0/2/sqrt(Asx0**2+Asy0**2) = 2*Asx0/bDist; // if bDist != 0, otherwise 0
+     *   if bDist=0 <=> (Asx=0,Asy=0), but for any Asy!=0 (if Asx=0 => d(bDist)/d(Asx) = 0)
+     *   => for continuity similarly define the same for Asy=0, i.e. if bDist=0 => d(bDist)/d(Asx) = 0
+     *
+     * d(aB)/dX             = d(aB)/d(bDist)*d(bDist)/d(Asx0)*d(Asx0)/dX = DalphpaB*(2*Asx0/bDist)*(1/CellSize)
+     * d(aX)/dX             = d(aX)/d(Asx1)*d(Asx1)/d(Asx0)*d(Asx0)/dX = DalphaX*signX*(1/CellSize)
+     * d(eEcal)/d(Ecluster) = 1
+     *
+     * alpha = aG * aE(eEcal) * aB(bDist) * aX(Asx1) * aY(Asy1);
+     * Ehypo = eCor = eEcal * alpha(eEcal, bDist, Asx1, Asy1) * (gC = 1) * gT + dT + offset;
+     *
+     * d(alpha)/d(eEcal) = (aG*aB*aX*aY) * d(aE)/d(eEcal) = (alpha/aE) * DalphaE; // if aE!=0, otherwise
+     * aG*aB*aX*aY*DalphaE
+     *
+     *
+     * d(Ehypo)/d(Ecluster) = gT*(eEcal*d(alpha)/d(eEcal) + alpha) = gT * alpha * (1. + DaE / aE * eEcal)
+     * d(Ehypo)/d(Xcluster) = gT*eEcal*d(alpha)/dX = gT*eEcal*aG*aE*aY*(d(aB)/dX*aX+d(aX)/dX*aB)
+     *                      = gT * eEcal * aG * aE * aY * (DaB*2.*Asx0/bDist*aX + signX*aB*DaX)/CellSize
+     * d(Ehypo)/d(Ycluster) = [ same as for d(Ehypo)/d(Xcluster) with ( X <-> Y ) ]
+     * 			  = gT * eEcal * aG * aE * aX * (DaB*2.*Asy0/bDist*aY + signY*aB*DaY)/CellSize
+     */
+
+    ECorrection::ECorrOutputParams results;
+    if ( m_correctCovariance ) {
+      float d_alpha_dE =
+          ( aE != 0 ) ? DaE * alpha / aE : DaE * aG * aB * aX * aY; // though in principle, aE should never be 0
+
+      results.dEcor_dEcl = gT * ( alpha + d_alpha_dE * eEcal );
+
+      results.dEcor_dXcl = gT * eEcal * aG * aE * aY *
+                           ( ( bDist == 0 ? 0. : DaB * 2. * Asx0 / bDist * aX ) + signX * aB * DaX ) / CellSize;
+
+      results.dEcor_dYcl = gT * eEcal * aG * aE * aX *
+                           ( ( bDist == 0 ? 0. : DaB * 2. * Asy0 / bDist * aY ) + signY * aB * DaY ) / CellSize;
+    }
 
-  CaloFutureECorrection::ECorrOutputParams results;
-  if ( m_correctCovariance ) {
-    float d_alpha_dE =
-        ( aE != 0 ) ? DaE * alpha / aE : DaE * aG * aB * aX * aY; // though in principle, aE should never be 0
+    results.alpha = alpha;
 
-    results.dEcor_dEcl = gT * ( alpha + d_alpha_dE * eEcal );
+    // intermediate variables calculated by calcECorrection() needed for debug printout inside process()
+    if ( msgLevel( MSG::DEBUG ) ) {
+      results.Asx = Asx; // Asx1
+      results.Asy = Asy; // Asy1
+      results.aG  = aG;
+      results.aE  = aE;
+      results.aB  = aB;
+      results.aX  = aX;
+      results.aY  = aY;
+      results.gT  = gT;
+    }
+    results.eCor = eCor;
+    return results;
+  }
 
-    results.dEcor_dXcl = gT * eEcal * aG * aE * aY *
-                         ( ( bDist == 0 ? 0. : DaB * 2. * Asx0 / bDist * aX ) + signX * aB * DaX ) / CellSize;
+  void ECorrection::debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
+                                                 const ECorrOutputParams& outParams ) const {
+    const float dx_rel( 1e-5 ), dy_rel( 1e-5 ), de_rel( 1e-3 ); // dx,dy ~ few*0.1*mm, de ~ few MeV
+    float       xBar       = inParams.x;
+    float       yBar       = inParams.y;
+    float       eEcal      = inParams.eEcal;
+    float       eCor       = outParams.eCor;
+    float       dEcor_dXcl = outParams.dEcor_dXcl;
+    float       dEcor_dYcl = outParams.dEcor_dYcl;
+    float       dEcor_dEcl = outParams.dEcor_dEcl;
+
+    debug() << "\n ------------------------ ECorrection(x+dx, y, e) calculation follows ------------------- " << endmsg;
+    ECorrInputParams inParams1( inParams );
+    inParams1.x      = inParams1.x * ( 1 + dx_rel );
+    auto  outParams1 = calcECorrection( calo, inParams1 );
+    float eCor_x     = outParams1.eCor;
+
+    debug() << "\n ------------------------ ECorrection(x, y+dy, e) calculation follows ------------------- " << endmsg;
+    ECorrInputParams inParams2( inParams );
+    inParams2.y      = inParams2.y * ( 1 + dy_rel );
+    auto  outParams2 = calcECorrection( calo, inParams2 );
+    float eCor_y     = outParams2.eCor;
+
+    debug() << "\n ------------------------ ECorrection(e, y, e+de) calculation follows ------------------- " << endmsg;
+    ECorrInputParams inParams3( inParams );
+    inParams3.eEcal  = inParams2.eEcal * ( 1 + de_rel );
+    auto  outParams3 = calcECorrection( calo, inParams3 );
+    float eCor_e     = outParams3.eCor;
+
+    float dn_eCor_dx = ( eCor_x - eCor ) / xBar / dx_rel;
+    float dn_eCor_dy = ( eCor_y - eCor ) / yBar / dy_rel;
+    float dn_eCor_de = ( eCor_e - eCor ) / eEcal / de_rel;
+
+    // avoid division in comparison for possible dE/dX == 0 or dE/dY == 0
+    if ( fabs( dEcor_dXcl - dn_eCor_dx ) > fabs( dEcor_dXcl ) * 0.1 ||
+         fabs( dEcor_dYcl - dn_eCor_dy ) > fabs( dEcor_dYcl ) * 0.1 ||
+         fabs( dEcor_dEcl - dn_eCor_de ) > fabs( dEcor_dEcl ) * 0.1 ) {
+      debug() << " some CaloFutureECorrection analytically-calculated Jacobian elements differ (by > 10%) from "
+                 "numerically-calculated ones! "
+              << endmsg;
+    }
 
-    results.dEcor_dYcl = gT * eEcal * aG * aE * aX *
-                         ( ( bDist == 0 ? 0. : DaB * 2. * Asy0 / bDist * aY ) + signY * aB * DaY ) / CellSize;
+    debug() << "********** Jacobian elements J(2,*) =" << endmsg;
+    debug() << "   semi-analytic dEcor_dXcl = " << dEcor_dXcl << " numeric dn_eCor_dx = " << dn_eCor_dx << endmsg;
+    debug() << "   semi-analytic dEcor_dYcl = " << dEcor_dYcl << " numeric dn_eCor_dy = " << dn_eCor_dy << endmsg;
+    debug() << "   semi-analytic dEcor_dEcl = " << dEcor_dEcl << " numeric dn_eCor_de = " << dn_eCor_de << endmsg;
   }
 
-  results.alpha = alpha;
-
-  // intermediate variables calculated by calcECorrection() needed for debug printout inside process()
-  if ( msgLevel( MSG::DEBUG ) ) {
-    results.Asx = Asx; // Asx1
-    results.Asy = Asy; // Asy1
-    results.aG  = aG;
-    results.aE  = aE;
-    results.aB  = aB;
-    results.aX  = aX;
-    results.aY  = aY;
-    results.gT  = gT;
+  float ECorrection::computeDTheta(
+      const DeCalorimeter&                                                                  calo,
+      Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous> cluster,
+      CaloFuture2Track::ICluster2TrackTable2D const& ctable, IGeometryInfo const& geometry ) const {
+
+    const auto range = ctable.relations( cluster.cellID() );
+    if ( range.empty() ) return 0;
+    //  incidence angle charged
+    const Track* ctrack    = range.front();
+    const auto   calostate = m_caloElectron->caloState( calo, *ctrack, geometry );
+    const float  incidence =
+        ( calostate.location() != State::Location::LocationUnknown ? calostate.momentum().Theta() : 0 );
+    auto cMomentum = Momentum( cluster );
+    return incidence - cMomentum.momentum().Theta();
   }
-  results.eCor = eCor;
-  return results;
-}
-
-void CaloFutureECorrection::debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
-                                                         const ECorrOutputParams& outParams ) const {
-  const float dx_rel( 1e-5 ), dy_rel( 1e-5 ), de_rel( 1e-3 ); // dx,dy ~ few*0.1*mm, de ~ few MeV
-  float       xBar       = inParams.x;
-  float       yBar       = inParams.y;
-  float       eEcal      = inParams.eEcal;
-  float       eCor       = outParams.eCor;
-  float       dEcor_dXcl = outParams.dEcor_dXcl;
-  float       dEcor_dYcl = outParams.dEcor_dYcl;
-  float       dEcor_dEcl = outParams.dEcor_dEcl;
-
-  debug() << "\n ------------------------ ECorrection(x+dx, y, e) calculation follows ------------------- " << endmsg;
-  ECorrInputParams inParams1( inParams );
-  inParams1.x      = inParams1.x * ( 1 + dx_rel );
-  auto  outParams1 = calcECorrection( calo, inParams1 );
-  float eCor_x     = outParams1.eCor;
-
-  debug() << "\n ------------------------ ECorrection(x, y+dy, e) calculation follows ------------------- " << endmsg;
-  ECorrInputParams inParams2( inParams );
-  inParams2.y      = inParams2.y * ( 1 + dy_rel );
-  auto  outParams2 = calcECorrection( calo, inParams2 );
-  float eCor_y     = outParams2.eCor;
-
-  debug() << "\n ------------------------ ECorrection(e, y, e+de) calculation follows ------------------- " << endmsg;
-  ECorrInputParams inParams3( inParams );
-  inParams3.eEcal  = inParams2.eEcal * ( 1 + de_rel );
-  auto  outParams3 = calcECorrection( calo, inParams3 );
-  float eCor_e     = outParams3.eCor;
-
-  float dn_eCor_dx = ( eCor_x - eCor ) / xBar / dx_rel;
-  float dn_eCor_dy = ( eCor_y - eCor ) / yBar / dy_rel;
-  float dn_eCor_de = ( eCor_e - eCor ) / eEcal / de_rel;
-
-  // avoid division in comparison for possible dE/dX == 0 or dE/dY == 0
-  if ( fabs( dEcor_dXcl - dn_eCor_dx ) > fabs( dEcor_dXcl ) * 0.1 ||
-       fabs( dEcor_dYcl - dn_eCor_dy ) > fabs( dEcor_dYcl ) * 0.1 ||
-       fabs( dEcor_dEcl - dn_eCor_de ) > fabs( dEcor_dEcl ) * 0.1 ) {
-    debug() << " some CaloFutureECorrection analytically-calculated Jacobian elements differ (by > 10%) from "
-               "numerically-calculated ones! "
-            << endmsg;
-  }
-
-  debug() << "********** Jacobian elements J(2,*) =" << endmsg;
-  debug() << "   semi-analytic dEcor_dXcl = " << dEcor_dXcl << " numeric dn_eCor_dx = " << dn_eCor_dx << endmsg;
-  debug() << "   semi-analytic dEcor_dYcl = " << dEcor_dYcl << " numeric dn_eCor_dy = " << dn_eCor_dy << endmsg;
-  debug() << "   semi-analytic dEcor_dEcl = " << dEcor_dEcl << " numeric dn_eCor_de = " << dn_eCor_de << endmsg;
-}
-
-float CaloFutureECorrection::computeDTheta(
-    const DeCalorimeter&                                                                              calo,
-    LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cluster,
-    LHCb::CaloFuture2Track::ICluster2TrackTable2D const& ctable, IGeometryInfo const& geometry ) const {
-
-  const auto range = ctable.relations( cluster.cellID() );
-  if ( range.empty() ) return 0;
-  //  incidence angle charged
-  const LHCb::Track* ctrack    = range.front();
-  const auto         calostate = m_caloElectron->caloState( calo, *ctrack, geometry );
-  const float        incidence =
-      ( calostate.location() != LHCb::State::Location::LocationUnknown ? calostate.momentum().Theta() : 0 );
-  auto cMomentum = LHCb::Calo::Momentum( cluster );
-  return incidence - cMomentum.momentum().Theta();
-}
+} // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
index 0cd716758dd..7f2d89ccb9c 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
@@ -16,105 +16,103 @@
 #include <cmath>
 #include <string>
 
-/** @class CaloFutureLCorrection CaloFutureLCorrection.h
- *
- *
- *  @author Deschamps Olivier
- *  @date   2003-03-10
- *  revised 2010
-
- *  Adam Szabelski
- *  date 2019-10-15
- */
-
-class CaloFutureLCorrection : public extends<CaloFutureCorrectionBase, LHCb::Calo::Interfaces::IProcessHypos> {
-public:
-  CaloFutureLCorrection( const std::string& type, const std::string& name, const IInterface* parent );
-  using LHCb::Calo::Interfaces::IProcessHypos::process;
-  StatusCode
-  process( const DeCalorimeter& calo, LHCb::Event::Calo::Hypotheses::Type,
-           LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous>&,
-           IGeometryInfo const& geometry ) const override;
-
-private:
-  Gaudi::XYZPoint m_origin = {0, 0, 0};
-
-  template <typename Point>
-  std::array<float, 4> compute( const DeCalorimeter& calo, const Point& pos, LHCb::Detector::Calo::CellID cellID,
-                                float energy ) const {
-    int area = cellID.area();
-    assert( area >= 0 && area <= 2 ); // TODO: comment assert out
-    // Account for the tilt
-    const auto   plane  = calo.plane( CaloPlane::Front ); // Ecal Front-Plane
-    const auto   normal = plane.Normal();
-    const double Hesse  = plane.HesseDistance();
-
-    const float xg = pos.x() - m_origin.X();
-    const float yg = pos.y() - m_origin.Y();
-    const float z0 = ( -Hesse - normal.X() * pos.x() - normal.Y() * pos.y() ) / normal.Z();
-    float       zg = z0 - m_origin.Z();
-
-    // hardcoded inner offset (+7.5 mm)
-    if ( area == 2 ) { zg += 7.5; }
-
-    // Uncorrected angle
-    float xy_offset  = LHCb::Math::Approx::approx_sqrt( xg * xg + yg * yg );
-    float xyz_offset = LHCb::Math::Approx::approx_sqrt( xg * xg + yg * yg + zg * zg );
-    float tan_theta  = xy_offset / zg;
-
-    // Corrected angle
-    float gamma0 = getCorrection( CaloFutureCorrection::gamma0, cellID ).value_or( 1 );
-    float delta0 = getCorrection( CaloFutureCorrection::delta0, cellID ).value_or( 1 );
-
-    // NB: gammaP(ePrs = 0) != 0, deltaP(ePrs = 0) != 0 and depend on cellID.area()
-    // get gammaP and deltaP parameters (depending on cellID.area() for each cluster
-    float gammaP = getCorrection( CaloFutureCorrection::gammaP, cellID, 0. ).value_or( 1 );
-    float deltaP = getCorrection( CaloFutureCorrection::deltaP, cellID, 0. ).value_or( 1 );
-    float g      = gamma0 - gammaP;
-    float d      = delta0 + deltaP;
-
-    float      tg_fps    = ( energy > 0.0 ? g * LHCb::Math::fast_log( energy / Gaudi::Units::GeV ) + d : 0.0 );
-    float      temp      = ( 1. + tg_fps / xyz_offset );
-    float      cos_theta = temp * LHCb::Math::fast_rsqrt( tan_theta * tan_theta + temp * temp );
-    const auto dz_fps    = cos_theta * tg_fps;
-    return {g, d, z0, dz_fps};
-  }
-};
-
-DECLARE_COMPONENT( CaloFutureLCorrection )
-
-CaloFutureLCorrection::CaloFutureLCorrection( const std::string& type, const std::string& name,
-                                              const IInterface* parent )
-    : extends( type, name, parent ) {
-  // define conditionName
-  const std::string uName( LHCb::CaloFutureAlgUtils::toUpper( name ) );
-  if ( uName.find( "ELECTRON" ) != std::string::npos ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/ElectronLCorrection" ).ignore();
-  } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/SplitPhotonLCorrection" ).ignore();
-  } else if ( uName.find( "PHOTON" ) ) {
-    setProperty( "ConditionName", "Conditions/Reco/Calo/PhotonLCorrection" ).ignore();
-  }
-}
-
-StatusCode CaloFutureLCorrection::process(
-    const DeCalorimeter& calo, LHCb::Event::Calo::Hypotheses::Type hypo,
-    LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous>& cluster,
-    IGeometryInfo const& ) const {
-  // check the Hypo
-  const auto h = std::find( m_hypos.begin(), m_hypos.end(), hypo );
-  if ( m_hypos.end() == h ) {
-    Error( "Invalid hypothesis -> no correction applied", StatusCode::SUCCESS ).ignore();
-    return StatusCode::FAILURE;
+namespace LHCb::Calo {
+
+  /**
+   *  @author Deschamps Olivier
+   *  @date   2003-03-10
+   *  revised 2010
+
+   *  Adam Szabelski
+   *  date 2019-10-15
+   */
+  class LCorrection : public extends<Correction::Base, Interfaces::IProcessHypos> {
+  public:
+    LCorrection( const std::string& type, const std::string& name, const IInterface* parent );
+    using Interfaces::IProcessHypos::process;
+    StatusCode process( const DeCalorimeter& calo, Event::Calo::Hypotheses::Type,
+                        Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous>&,
+                        IGeometryInfo const& geometry ) const override;
+
+  private:
+    Gaudi::XYZPoint m_origin = {0, 0, 0};
+
+    template <typename Point>
+    std::array<float, 4> compute( const DeCalorimeter& calo, const Point& pos, Detector::Calo::CellID cellID,
+                                  float energy ) const {
+      int area = cellID.area();
+      assert( area >= 0 && area <= 2 ); // TODO: comment assert out
+      // Account for the tilt
+      const auto   plane  = calo.plane( CaloPlane::Front ); // Ecal Front-Plane
+      const auto   normal = plane.Normal();
+      const double Hesse  = plane.HesseDistance();
+
+      const float xg = pos.x() - m_origin.X();
+      const float yg = pos.y() - m_origin.Y();
+      const float z0 = ( -Hesse - normal.X() * pos.x() - normal.Y() * pos.y() ) / normal.Z();
+      float       zg = z0 - m_origin.Z();
+
+      // hardcoded inner offset (+7.5 mm)
+      if ( area == 2 ) { zg += 7.5; }
+
+      // Uncorrected angle
+      float xy_offset  = Math::Approx::approx_sqrt( xg * xg + yg * yg );
+      float xyz_offset = Math::Approx::approx_sqrt( xg * xg + yg * yg + zg * zg );
+      float tan_theta  = xy_offset / zg;
+
+      // Corrected angle
+      float gamma0 = getCorrection( Correction::Type::gamma0, cellID ).value_or( 1 );
+      float delta0 = getCorrection( Correction::Type::delta0, cellID ).value_or( 1 );
+
+      // NB: gammaP(ePrs = 0) != 0, deltaP(ePrs = 0) != 0 and depend on cellID.area()
+      // get gammaP and deltaP parameters (depending on cellID.area() for each cluster
+      float gammaP = getCorrection( Correction::Type::gammaP, cellID, 0. ).value_or( 1 );
+      float deltaP = getCorrection( Correction::Type::deltaP, cellID, 0. ).value_or( 1 );
+      float g      = gamma0 - gammaP;
+      float d      = delta0 + deltaP;
+
+      float      tg_fps    = ( energy > 0.0 ? g * Math::fast_log( energy / Gaudi::Units::GeV ) + d : 0.0 );
+      float      temp      = ( 1. + tg_fps / xyz_offset );
+      float      cos_theta = temp * Math::fast_rsqrt( tan_theta * tan_theta + temp * temp );
+      const auto dz_fps    = cos_theta * tg_fps;
+      return {g, d, z0, dz_fps};
+    }
+  };
+
+  DECLARE_COMPONENT_WITH_ID( LCorrection, "CaloFutureLCorrection" )
+
+  LCorrection::LCorrection( const std::string& type, const std::string& name, const IInterface* parent )
+      : extends( type, name, parent ) {
+    // define conditionName
+    const std::string uName( CaloFutureAlgUtils::toUpper( name ) );
+    if ( uName.find( "ELECTRON" ) != std::string::npos ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/ElectronLCorrection" ).ignore();
+    } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/SplitPhotonLCorrection" ).ignore();
+    } else if ( uName.find( "PHOTON" ) ) {
+      setProperty( "ConditionName", "Conditions/Reco/Calo/PhotonLCorrection" ).ignore();
+    }
   }
 
-  // No correction for negative energy :
-  if ( cluster.e() < 0. ) { return StatusCode::SUCCESS; }
+  StatusCode
+  LCorrection::process( const DeCalorimeter& calo, Event::Calo::Hypotheses::Type hypo,
+                        Event::Calo::Clusters::reference<SIMDWrapper::Scalar, Pr::ProxyBehaviour::Contiguous>& cluster,
+                        IGeometryInfo const& ) const {
+    // check the Hypo
+    const auto h = std::find( m_hypos.begin(), m_hypos.end(), hypo );
+    if ( m_hypos.end() == h ) {
+      Error( "Invalid hypothesis -> no correction applied", StatusCode::SUCCESS ).ignore();
+      return StatusCode::FAILURE;
+    }
+
+    // No correction for negative energy :
+    if ( cluster.e() < 0. ) { return StatusCode::SUCCESS; }
 
-  auto [g, d, z0, dz_fps] = compute( calo, cluster.position(), cluster.cellID(), cluster.e() );
+    auto [g, d, z0, dz_fps] = compute( calo, cluster.position(), cluster.cellID(), cluster.e() );
 
-  // Recompute Z position and fill CaloPosition
-  cluster.template field<LHCb::Event::Calo::v2::ClusterTag::Position>().setZ( z0 + dz_fps );
+    // Recompute Z position and fill CaloPosition
+    cluster.template field<Event::Calo::v2::ClusterTag::Position>().setZ( z0 + dz_fps );
 
-  return StatusCode::SUCCESS;
-}
+    return StatusCode::SUCCESS;
+  }
+} // namespace LHCb::Calo
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
index c93ea587c34..82a689db4ce 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
@@ -58,7 +58,7 @@ namespace {
 
 namespace LHCb::Calo {
 
-  class SCorrection : public extends<CaloFutureCorrectionBase, LHCb::Calo::Interfaces::IProcessHypos> {
+  class SCorrection : public extends<LHCb::Calo::Correction::Base, LHCb::Calo::Interfaces::IProcessHypos> {
   public:
     SCorrection( const std::string& type, const std::string& name, const IInterface* parent );
 
@@ -193,11 +193,11 @@ namespace LHCb::Calo {
 
     // Sshape correction :
     auto AsxCorDer =
-        getCorrectionAndDerivative( CaloFutureCorrection::shapeX, cellID, Asx ).value_or( CorrectionResult{Asx, 1.} );
+        getCorrectionAndDerivative( Correction::Type::shapeX, cellID, Asx ).value_or( Correction::Result{Asx, 1.} );
     Asx                = AsxCorDer.value; // Asx1
     const auto DshapeX = AsxCorDer.derivative;
     auto       AsyCorDer =
-        getCorrectionAndDerivative( CaloFutureCorrection::shapeY, cellID, Asy ).value_or( CorrectionResult{Asy, 1.} );
+        getCorrectionAndDerivative( Correction::Type::shapeY, cellID, Asy ).value_or( Correction::Result{Asy, 1.} );
     Asy                = AsyCorDer.value; // Asy1
     const auto DshapeY = AsyCorDer.derivative;
 
@@ -207,30 +207,30 @@ namespace LHCb::Calo {
     const float thx = LHCb::Math::fast_atan2( xs, (float)z );
     const float thy = LHCb::Math::fast_atan2( ys, (float)z );
     const auto [daX, DangularX] =
-        getCorrectionAndDerivative( CaloFutureCorrection::angularX, cellID, thx ).value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( Correction::Type::angularX, cellID, thx ).value_or( Correction::Result{0., 0.} );
     const auto [daY, DangularY] =
-        getCorrectionAndDerivative( CaloFutureCorrection::angularY, cellID, thy ).value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( Correction::Type::angularY, cellID, thy ).value_or( Correction::Result{0., 0.} );
     Asx -= daX;
     Asy -= daY;
 
     // residual correction (if any):
     auto dcXCorDer =
-        getCorrectionAndDerivative( CaloFutureCorrection::residual, cellID, Asx ).value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( Correction::Type::residual, cellID, Asx ).value_or( Correction::Result{0., 0.} );
     auto dcX = dcXCorDer.value;
     if ( dcX == 0. ) {
       // check X-specific correction
-      dcXCorDer = getCorrectionAndDerivative( CaloFutureCorrection::residualX, cellID, Asx )
-                      .value_or( CorrectionResult{0., 0.} );
+      dcXCorDer =
+          getCorrectionAndDerivative( Correction::Type::residualX, cellID, Asx ).value_or( Correction::Result{0., 0.} );
       dcX = dcXCorDer.value;
     }
     const auto DresidualX = dcXCorDer.derivative;
     auto       dcYCorDer =
-        getCorrectionAndDerivative( CaloFutureCorrection::residual, cellID, Asy ).value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( Correction::Type::residual, cellID, Asy ).value_or( Correction::Result{0., 0.} );
     auto dcY = dcYCorDer.value;
     if ( dcY == 0. ) {
       // check Y-specific correction
-      dcYCorDer = getCorrectionAndDerivative( CaloFutureCorrection::residualY, cellID, Asy )
-                      .value_or( CorrectionResult{0., 0.} );
+      dcYCorDer =
+          getCorrectionAndDerivative( Correction::Type::residualY, cellID, Asy ).value_or( Correction::Result{0., 0.} );
       dcY = dcYCorDer.value;
     }
     const auto DresidualY = dcYCorDer.derivative;
@@ -239,13 +239,11 @@ namespace LHCb::Calo {
 
     // left/right - up/down asymmetries correction (if any) :
     const auto [ddcX, DasymX] =
-        getCorrectionAndDerivative( ( xBar < 0 ) ? CaloFutureCorrection::asymM : CaloFutureCorrection::asymP, cellID,
-                                    Asx )
-            .value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( ( xBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP, cellID, Asx )
+            .value_or( Correction::Result{0., 0.} );
     const auto [ddcY, DasymY] =
-        getCorrectionAndDerivative( ( yBar < 0 ) ? CaloFutureCorrection::asymM : CaloFutureCorrection::asymP, cellID,
-                                    Asy )
-            .value_or( CorrectionResult{0., 0.} );
+        getCorrectionAndDerivative( ( yBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP, cellID, Asy )
+            .value_or( Correction::Result{0., 0.} );
     Asx += ddcX; // Asx4
     Asy += ddcY; // Asy4
 
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
index 6c1563f160a..db349d3902d 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
@@ -70,8 +70,7 @@ namespace LHCb::Calo::Tools {
                                                   "CaloFutureSCorrection/" + correctionType( name() ) + "SCorrection"};
     ToolHandle<LHCb::Calo::Interfaces::IProcessHypos> m_ltool{
         this, "CaloFutureLCorrection", "CaloFutureLCorrection/" + correctionType( name() ) + "LCorrection"};
-    ToolHandle<CaloFutureCorrectionBase>   m_shape{this, "CaloFutureCorrectionBase",
-                                                 "CaloFutureCorrectionBase/ShowerProfile"};
+    ToolHandle<Correction::Base> m_shape{this, "CaloFutureCorrectionBase", "CaloFutureCorrectionBase/ShowerProfile"};
     mutable Gaudi::Accumulators::Counter<> m_skippedSize{this, "Overlap correction skipped due to cluster size"};
     mutable Gaudi::Accumulators::Counter<> m_skippedEnergy{this, "Overlap correction skipped due to cluster energy"};
     mutable Gaudi::Accumulators::Counter<> m_positionFailed{this, "Cluster position failed"};
@@ -84,13 +83,13 @@ namespace LHCb::Calo::Tools {
 
     using WeightMap = boost::container::flat_map<LHCb::Detector::Calo::CellID, float>;
 
-    float showerFraction( const CaloFutureCorrectionBase& shape, const float d3d, const unsigned int area ) {
+    float showerFraction( const Correction::Base& shape, const float d3d, const unsigned int area ) {
       LHCb::Detector::Calo::CellID cellID( Detector::Calo::CellCode::Index::EcalCalo, area, 0, 0 ); // fake cell
-      return std::clamp( shape.getCorrection( CaloFutureCorrection::profile, cellID, d3d ).value_or( 0. ), 0.f, 1.f );
+      return std::clamp( shape.getCorrection( Correction::Type::profile, cellID, d3d ).value_or( 0. ), 0.f, 1.f );
     }
 
     [[gnu::always_inline]] inline float
-    fraction( const CaloFutureCorrectionBase& shape, const DeCalorimeter& det,
+    fraction( const Correction::Base& shape, const DeCalorimeter& det,
               LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cluster,
               LHCb::Detector::Calo::CellID cellID, float ed, int area ) {
 
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
index 383b67664dd..ef2242e0fb4 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp
@@ -25,15 +25,16 @@
 namespace LHCb::Calo {
   DECLARE_COMPONENT_WITH_ID( ClusterCovarianceMatrixTool, "FutureClusterCovarianceMatrixTool" )
 
-  CovarianceMatrixTool::detail::ParameterMap ClusterCovarianceMatrixTool::getParams() {
+  CovarianceMatrixTool::detail::ParameterMap
+  ClusterCovarianceMatrixTool::getParams( Correction::Parameters const& baseParams ) {
     LHCb::Calo::CovarianceMatrixTool::detail::ParameterMap parameters;
     for ( unsigned int area = 0; area < 3; ++area ) { // loop over calo area
-      const auto& params = m_dbAccessor->getParamVector(
-          CaloFutureCorrection::ClusterCovariance,
-          Detector::Calo::CellID{LHCb::Detector::Calo::CellCode::Index::EcalCalo, area, 0, 0} );
+      const auto& params =
+          m_dbAccessor->getParamVector( baseParams, Correction::Type::ClusterCovariance,
+                                        Detector::Calo::CellID{Detector::Calo::CellCode::Index::EcalCalo, area, 0, 0} );
       // FIXME: read Calo index from DeCalorimeter
-      if ( params.size() > LHCb::Calo::CovarianceMatrixTool::detail::Parameter::Last ) ++m_parExceeded;
-      if ( params.size() < LHCb::Calo::CovarianceMatrixTool::detail::Parameter::Last ) {
+      if ( params.size() > CovarianceMatrixTool::detail::Parameter::Last ) ++m_parExceeded;
+      if ( params.size() < CovarianceMatrixTool::detail::Parameter::Last ) {
         throw GaudiException( "ClusterCovarianceMatrixTool::getParams",
                               "Not enough values found in DB for ClusterCovariance", StatusCode::FAILURE );
       }
@@ -43,9 +44,9 @@ namespace LHCb::Calo {
     }
     // info
     info() << " \t ==  Parameters for covariance estimation ==" << endmsg;
-    for ( auto index : LHCb::Calo::CovarianceMatrixTool::detail::Parameters{} ) {
-      info() << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::name( index ) << " \t : " << parameters[index]
-             << " " << LHCb::Calo::CovarianceMatrixTool::detail::Parameters::unit( index ) << endmsg;
+    for ( auto index : CovarianceMatrixTool::detail::Parameters{} ) {
+      info() << CovarianceMatrixTool::detail::Parameters::name( index ) << " \t : " << parameters[index] << " "
+             << CovarianceMatrixTool::detail::Parameters::unit( index ) << endmsg;
     }
     return parameters;
   }
@@ -53,7 +54,9 @@ namespace LHCb::Calo {
   StatusCode ClusterCovarianceMatrixTool::initialize() {
     return ConditionAccessorHolder::initialize().andThen( [&] {
       // depends on m_conditionName so that calls to m_dbAccessor give proper results
-      addConditionDerivation( {m_conditionName}, m_parameters.key(), [&]( YAML::Node const& ) { return getParams(); } );
+      addConditionDerivation(
+          {m_conditionName, m_dbAccessor->getParamConditionPath()}, m_parameters.key(),
+          [&]( YAML::Node const&, Correction::Parameters const& baseParams ) { return getParams( baseParams ); } );
       return StatusCode::SUCCESS;
     } );
   }
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index fb3c6277dca..d78bca3048a 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -455,11 +455,11 @@ namespace LHCb::Calo {
     }
 
   private:
-    CovarianceMatrixTool::detail::ParameterMap getParams();
+    CovarianceMatrixTool::detail::ParameterMap getParams( Correction::Parameters const& );
 
     ConditionAccessor<CovarianceMatrixTool::detail::ParameterMap> m_parameters{this, name() + "_Parameters"};
-    Gaudi::Property<std::string>         m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
-    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
+    Gaudi::Property<std::string> m_conditionName{this, "ConditionName", "Conditions/Reco/Calo/EcalCovariance"};
+    ToolHandle<Correction::Base> m_dbAccessor = {this, "CorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
 
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_negative_energy{this, "negative energy cluster"};
     mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_parExceeded{
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
index 1e12d9b8bd5..2e30a40da57 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp
@@ -44,12 +44,14 @@ namespace LHCb::Calo {
   StatusCode SubClusterSelectorTool::initialize() {
     return ConditionAccessorHolder::initialize().andThen( [&] {
       // depends on m_condition so that calls to m_dbAccessor give proper results
-      addConditionDerivation( {m_condition}, m_tags.key(), [&]( YAML::Node const& ) { return getParams(); } );
+      addConditionDerivation(
+          {m_condition, m_dbAccessor->getParamConditionPath()}, m_tags.key(),
+          [&]( YAML::Node const&, Correction::Parameters const& baseParams ) { return getParams( baseParams ); } );
       return StatusCode::SUCCESS;
     } );
   }
 
-  SubClusterSelectorTool::Tags SubClusterSelectorTool::getParams() {
+  SubClusterSelectorTool::Tags SubClusterSelectorTool::getParams( Correction::Parameters const& baseParams ) {
     Tags tags;
     // FIXME: get it from DeCalorimeter instead
     static constexpr int narea   = 3;
@@ -86,9 +88,8 @@ namespace LHCb::Calo {
         tags[0].push_back( tE );
       } else {
         sourceE = " (from DB) ";
-        Mask maskE =
-            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::EnergyMask, 0, id ).value_or( 0. ); // default is
-                                                                                                        // when no DB
+        // default is when no DB
+        Mask maskE = (Mask)m_dbAccessor->getParameter( baseParams, Correction::Type::EnergyMask, 0, id ).value_or( 0. );
         std::string name    = maskName[maskE];
         std::string taggerE = ( m_clusterTaggers.find( name ) != m_clusterTaggers.end() ) ? m_clusterTaggers[name] : "";
         if ( !taggerE.empty() ) {
@@ -117,10 +118,9 @@ namespace LHCb::Calo {
         tags[1].push_back( tP );
       } else {
         sourceP = " (from DB) ";
+        // default is 3x3 when no DB
         Mask maskP =
-            (Mask)m_dbAccessor->getParameter( CaloFutureCorrection::PositionMask, 0, id ).value_or( 0. ); // default is
-        // 3x3 when no
-        // DB
+            (Mask)m_dbAccessor->getParameter( baseParams, Correction::Type::PositionMask, 0, id ).value_or( 0. );
         std::string name    = maskName[maskP];
         std::string taggerP = ( m_clusterTaggers.find( name ) != m_clusterTaggers.end() ) ? m_clusterTaggers[name] : "";
         if ( !taggerP.empty() ) {
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
index f94aa1aafe1..dddf38b81bf 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
@@ -87,7 +87,7 @@ namespace LHCb::Calo {
     using Tags = std::array<std::vector<Interfaces::ISubClusterTag*>, 2>; // 0 -> Energy, 1 -> Position
     ConditionAccessor<Tags> m_tags{this, name() + "-SubClusterSelectorToolTags"};
 
-    Tags getParams();
+    Tags getParams( Correction::Parameters const& );
 
     // associate known cluster mask to tagger tool
     Gaudi::Property<std::map<std::string, std::string>> m_clusterTaggers{
@@ -102,10 +102,9 @@ namespace LHCb::Calo {
         },
         "associate known cluster mask to tagger tool"};
 
-    Gaudi::Property<std::string>         m_condition{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
-    ToolHandle<CaloFutureCorrectionBase> m_dbAccessor{this, "CaloFutureCorrectionBase",
-                                                      "CaloFutureCorrectionBase/DBAccessor"};
-    LHCb::CaloDigitStatus::Status        m_energyStatus = LHCb::CaloDigitStatus::Status{
+    Gaudi::Property<std::string>  m_condition{this, "ConditionName", "Conditions/Reco/Calo/EcalClusterMasks"};
+    ToolHandle<Correction::Base>  m_dbAccessor{this, "CaloFutureCorrectionBase", "CaloFutureCorrectionBase/DBAccessor"};
+    LHCb::CaloDigitStatus::Status m_energyStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForEnergy, LHCb::CaloDigitStatus::Mask::UseForCovariance};
     LHCb::CaloDigitStatus::Status m_positionStatus = LHCb::CaloDigitStatus::Status{
         LHCb::CaloDigitStatus::Mask::UseForPosition, LHCb::CaloDigitStatus::Mask::UseForCovariance};
-- 
GitLab


From 653177171cdd867dff8fec7c9a3ae35fb7c22ff7 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Wed, 5 Oct 2022 17:58:17 +0200
Subject: [PATCH 24/26] Fixed tests for DD4Hep mode, after the drop of DetDesc
 compilation in that mode

---
 .../python/CaloFutureReco/Reconstruction.py        | 14 +++++++-------
 FT/FTMonitors/options/nzs_cluster_monitoring.py    |  8 +++++---
 FT/FTMonitors/options/nzs_digit_monitoring.py      |  8 +++++---
 .../tests/options/nzs_cluster_monitoring.py        |  8 ++++----
 .../tests/options/nzs_digit_monitoring.py          |  8 ++++----
 .../tests/options/test_vector_functors.py          |  3 ++-
 Phys/PhysConf/python/PhysConf/Configuration.py     |  8 +++++---
 .../tests/options/test_mergelinksbykeystovector.py |  6 ++++--
 .../tests/options/test_mergerelationstables.py     |  2 +-
 .../tests/options/test_protoparticleassociator.py  |  2 +-
 .../ConfiguredRecoMonitors.py                      |  4 ++++
 Rich/RichFutureRecSys/tests/options/pmt-v3-data.py |  7 +++++--
 .../tests/options/rich-dst-reco.py                 |  3 +--
 .../tests/refs/rich-dst-reco-pmt-v3.ref.dd4hep     |  6 ------
 .../rich-dst-reco-pmt-v3.ref.x86_64_v3-dd4hep-opt  |  6 ------
 Tf/TrackSys/python/TrackSys/RecoUpgradeTracking.py |  9 ++++++---
 .../tests/options/test_extrapolators.py            |  8 +++++---
 17 files changed, 59 insertions(+), 51 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
index 9c73c034c64..b6aac717fd0 100644
--- a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
+++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py
@@ -85,9 +85,9 @@ def clusterFutureReco(enableRecoOnDemand,
     share.SubClusterSelector.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
     share.SubClusterSelector.CaloFutureCorrectionBase.ConditionName = share.EcalClusterTag.ConditionName
     share.OverlapTool = 'CaloFutureShowerOverlapTool/PhotonShowerOverlap'
-    share.OverlapTool.ConditionName = 'Conditions/Reco/Calo/PhotonShowerProfile'
+    share.OverlapTool.Profile = 'Conditions/Reco/Calo/PhotonShowerProfile'
     share.OverlapTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/ShowerProfile'
-    share.OverlapTool.CaloFutureCorrectionBase.ConditionName = share.SplitPhotonShowerOverlap.ConditionName
+    share.OverlapTool.CaloFutureCorrectionBase.ConditionName = share.OverlapTool.Profile
 
     covar = CaloFutureClusterCovarianceAlg("FutureEcalCovar")
     covar.CovarianceTool = 'FutureClusterCovarianceMatrixTool/EcalCovarTool'
@@ -95,9 +95,9 @@ def clusterFutureReco(enableRecoOnDemand,
     covar.CovarianceTool.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
     covar.CovarianceTool.CorrectionBase.ConditionName = covar.CovarianceTool.ConditionName
     covar.TaggerTool = 'FutureSubClusterSelectorTool/EcalClusterTag'
-    covar.TaggerTool.ConditionName = 'Conditions/Reco/Calo/EcalClusterMasks'
+    covar.TaggerTool.Profile = 'Conditions/Reco/Calo/EcalClusterMasks'
     covar.TaggerTool.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
-    covar.TaggerTool.CaloFutureCorrectionBase.ConditionName = covar.TaggerTool.ConditionName
+    covar.TaggerTool.CaloFutureCorrectionBase.ConditionName = covar.TaggerTool.Profile
 
     if masksE != []:
         share.EnergyTags = masksE
@@ -241,15 +241,15 @@ def mergedPi0FutureReco(enableRecoOnDemand,
     pi0.EcalCovariance = 'FutureClusterCovarianceMatrixTool/EcalCovariance'
     pi0.EcalCovariance.ConditionName = 'Conditions/Reco/Calo/EcalCovariance'
     pi0.EcalCovariance.CorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
-    pi0.EcalCovariance.CorrectionBase.ConditionName = i0.EcalCovariance.ConditionName
+    pi0.EcalCovariance.CorrectionBase.ConditionName = pi0.EcalCovariance.ConditionName
     pi0.EcalClusterTag = 'FutureSubClusterSelectorTool/EcalClusterTag'
     pi0.EcalClusterTag.ConditionName = 'Conditions/Reco/Calo/EcalClusterMasks'
     pi0.EcalClusterTag.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/DBAccessor'
     pi0.EcalClusterTag.CaloFutureCorrectionBase.ConditionName = pi0.EcalClusterTag.ConditionName
     pi0.SplitPhotonShowerOverlap = 'CaloFutureShowerOverlapTool/SplitPhotonShowerOverlap'
-    pi0.SplitPhotonShowerOverlap.ConditionName = 'Conditions/Reco/Calo/PhotonShowerProfile'
+    pi0.SplitPhotonShowerOverlap.Profile = 'Conditions/Reco/Calo/PhotonShowerProfile'
     pi0.SplitPhotonShowerOverlap.CaloFutureCorrectionBase = 'CaloFutureCorrectionBase/ShowerProfile'
-    pi0.SplitPhotonShowerOverlap.CaloFutureCorrectionBase.ConditionName = pi0.SplitPhotonShowerOverlap.ConditionName
+    pi0.SplitPhotonShowerOverlap.CaloFutureCorrectionBase.ConditionName = pi0.SplitPhotonShowerOverlap.Profile
 
     if masksE != []:
         pi0.EnergyTags = masksE
diff --git a/FT/FTMonitors/options/nzs_cluster_monitoring.py b/FT/FTMonitors/options/nzs_cluster_monitoring.py
index 05552af3d61..f4d0470c98e 100644
--- a/FT/FTMonitors/options/nzs_cluster_monitoring.py
+++ b/FT/FTMonitors/options/nzs_cluster_monitoring.py
@@ -9,7 +9,6 @@
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
 
-from Configurables import CondDB
 from Gaudi.Configuration import ApplicationMgr
 from Configurables import LHCbApp
 from Configurables import GaudiSequencer
@@ -28,14 +27,17 @@ from Configurables import EventSelector
 from os.path import basename
 from glob import glob
 from os import environ
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 side = "both"
 
 app = LHCbApp()
 app.DataType = "Upgrade"
 app.Simulation = True
-CondDB().Upgrade = True
-CondDB().IgnoreHeartBeat = True
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB().Upgrade = True
+    CondDB().IgnoreHeartBeat = True
 LoKiSvc().Welcome = False
 EventSelector().PrintFreq = 5000
 
diff --git a/FT/FTMonitors/options/nzs_digit_monitoring.py b/FT/FTMonitors/options/nzs_digit_monitoring.py
index 8ad2f964128..11ef6ffbda2 100644
--- a/FT/FTMonitors/options/nzs_digit_monitoring.py
+++ b/FT/FTMonitors/options/nzs_digit_monitoring.py
@@ -8,7 +8,6 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
-from Configurables import CondDB
 from Gaudi.Configuration import ApplicationMgr
 from Configurables import LHCbApp
 from Configurables import GaudiSequencer
@@ -28,14 +27,17 @@ from Configurables import LHCb__UnpackRawEvent
 from Configurables import EventSelector
 from glob import glob
 from os import environ
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 side = "C"
 
 app = LHCbApp()
 app.DataType = "Upgrade"
 app.Simulation = True
-CondDB().Upgrade = True
-CondDB().IgnoreHeartBeat = True
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB().Upgrade = True
+    CondDB().IgnoreHeartBeat = True
 LoKiSvc().Welcome = False
 MessageSvc().OutputLevel = INFO
 EventSelector().PrintFreq = 1000
diff --git a/FT/FTMonitors/tests/options/nzs_cluster_monitoring.py b/FT/FTMonitors/tests/options/nzs_cluster_monitoring.py
index 066e64f3572..faa54435564 100644
--- a/FT/FTMonitors/tests/options/nzs_cluster_monitoring.py
+++ b/FT/FTMonitors/tests/options/nzs_cluster_monitoring.py
@@ -11,7 +11,7 @@
 
 from os.path import basename
 from Gaudi.Configuration import ApplicationMgr, MessageSvc, INFO, ERROR
-from Configurables import CondDB, LHCbApp, GaudiSequencer
+from Configurables import LHCbApp, GaudiSequencer
 from GaudiConf import IOHelper
 from Configurables import Gaudi__Monitoring__JSONSink as JSONSink
 from Configurables import Gaudi__Monitoring__MessageSvcSink as MessageSvcSink
@@ -24,9 +24,9 @@ if not UseDD4Hep:
     app.DDDBtag = "upgrade/master"
     app.CondDBtag = "upgrade/master"
     app.Simulation = True
-
-CondDB().Upgrade = True
-CondDB().IgnoreHeartBeat = True
+    from Configurables import CondDB
+    CondDB().Upgrade = True
+    CondDB().IgnoreHeartBeat = True
 
 MessageSvc().OutputLevel = ERROR
 
diff --git a/FT/FTMonitors/tests/options/nzs_digit_monitoring.py b/FT/FTMonitors/tests/options/nzs_digit_monitoring.py
index c9c8f4a6042..3e5360f339b 100644
--- a/FT/FTMonitors/tests/options/nzs_digit_monitoring.py
+++ b/FT/FTMonitors/tests/options/nzs_digit_monitoring.py
@@ -11,7 +11,7 @@
 
 from os.path import basename
 from Gaudi.Configuration import ApplicationMgr, MessageSvc, INFO, ERROR
-from Configurables import CondDB, LHCbApp, GaudiSequencer
+from Configurables import LHCbApp, GaudiSequencer
 from Configurables import FTNZSRawBankDecoder, FTDigitMonitor
 from Configurables import Gaudi__Monitoring__JSONSink as JSONSink
 from Configurables import Gaudi__Monitoring__MessageSvcSink as MessageSvcSink
@@ -24,9 +24,9 @@ if not UseDD4Hep:
     app.DDDBtag = "upgrade/master"
     app.CondDBtag = "upgrade/master"
     app.Simulation = True
-
-CondDB().Upgrade = True
-CondDB().IgnoreHeartBeat = True
+    from Configurables import CondDB
+    CondDB().Upgrade = True
+    CondDB().IgnoreHeartBeat = True
 
 MessageSvc().OutputLevel = ERROR
 
diff --git a/Phys/FunctorCore/tests/options/test_vector_functors.py b/Phys/FunctorCore/tests/options/test_vector_functors.py
index 7ce560b6f97..e413ec2dc89 100644
--- a/Phys/FunctorCore/tests/options/test_vector_functors.py
+++ b/Phys/FunctorCore/tests/options/test_vector_functors.py
@@ -15,7 +15,7 @@ import GaudiKernel.Configurable
 from Gaudi.Configuration import (ApplicationMgr, DEBUG)
 from Functors import (ALL, FILTER, POD)
 from Functors.tests.categories import functors_for_class
-from Configurables import EvtStoreSvc, FunctorFactory, CondDB, DDDBConf
+from Configurables import EvtStoreSvc, FunctorFactory, DDDBConf
 from PyConf.Algorithms import UniqueIDGeneratorAlg, ProducePrFittedForwardTracks
 from DDDB.CheckDD4Hep import UseDD4Hep
 
@@ -38,6 +38,7 @@ ApplicationMgr().TopAlg = algs
 if not UseDD4Hep:
     # Need valid DB tags for particle name -> mass translation to work
     DDDBConf(DataType='Upgrade', Simulation=True)
+    from Configurables import CondDB
     CondDB(LatestGlobalTagByDataType='Upgrade', Upgrade=True)
 
 # Workaround for gaudi/Gaudi#117 that monkey patches gaudirun.py
diff --git a/Phys/PhysConf/python/PhysConf/Configuration.py b/Phys/PhysConf/python/PhysConf/Configuration.py
index 1eb04578618..599c1c64886 100755
--- a/Phys/PhysConf/python/PhysConf/Configuration.py
+++ b/Phys/PhysConf/python/PhysConf/Configuration.py
@@ -15,8 +15,9 @@ __author__ = "Patrick Koppenburg <Patrick.Koppenburg@cern.ch>"
 
 from LHCbKernel.Configuration import *
 import GaudiKernel.ProcessJobOptions
-from Configurables import (EventClockSvc, RecEventTime, TimeDecoderList,
-                           OdinTimeDecoder, DecodeRawEvent)
+from Configurables import (RecEventTime, TimeDecoderList, OdinTimeDecoder,
+                           DecodeRawEvent)
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 
 def configureEventTime():
@@ -26,6 +27,7 @@ def configureEventTime():
     Returns EventClockSvs()
     Author: Marco Clemencic.
     """
+    from Configurables import EventClockSvc
     #turn off setting that's done in DecodeRawEvent first
     DecodeRawEvent().EvtClockBank = ""
     ecs = EventClockSvc()
@@ -299,6 +301,6 @@ class PhysConf(LHCbConfigurableUser):
         """
         log.info("Applying Phys configuration")
         self.dataOnDemand()
-        if 'DST' in self.getProp('InputType').upper():
+        if not UseDD4Hep and 'DST' in self.getProp('InputType').upper():
             log.info('PhysConf: Configuring EventClockSvc to use RecHeader')
             configureEventTime()
diff --git a/Rec/GlobalRecoMCTools/tests/options/test_mergelinksbykeystovector.py b/Rec/GlobalRecoMCTools/tests/options/test_mergelinksbykeystovector.py
index 9b095744e89..f10d32238c5 100644
--- a/Rec/GlobalRecoMCTools/tests/options/test_mergelinksbykeystovector.py
+++ b/Rec/GlobalRecoMCTools/tests/options/test_mergelinksbykeystovector.py
@@ -17,12 +17,12 @@ from __future__ import print_function
 
 from Configurables import (
     ApplicationMgr,
-    CondDB,
     LHCbApp,
     MergeLinksByKeysToVector,
 )
 import GaudiPython as GP
 from PRConfig.TestFileDB import test_file_db
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 
 def compare(links_vec, original_link_paths):
@@ -41,7 +41,9 @@ def compare(links_vec, original_link_paths):
 
 app = LHCbApp(EvtMax=100)
 test_file_db["upgrade_minbias_hlt1_filtered"].run(configurable=app)
-CondDB(Upgrade=True)
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB(Upgrade=True)
 
 charged_merger = MergeLinksByKeysToVector(
     "ChargedMergeLinksByKeysToVector",
diff --git a/Rec/GlobalRecoMCTools/tests/options/test_mergerelationstables.py b/Rec/GlobalRecoMCTools/tests/options/test_mergerelationstables.py
index d4f11499b15..2c91311708e 100644
--- a/Rec/GlobalRecoMCTools/tests/options/test_mergerelationstables.py
+++ b/Rec/GlobalRecoMCTools/tests/options/test_mergerelationstables.py
@@ -22,7 +22,6 @@ import random
 
 from Configurables import (
     ApplicationMgr,
-    CondDB,
     LHCbApp,
     MergeRelationsTablesPP2MCP,
     UnpackMCParticle,
@@ -110,6 +109,7 @@ if UseDD4Hep:
     # GaudiPython.AppMgr
     cond_algs = [alg.getFullJobOptName() for alg in cond_algs]
 else:
+    from Configurables import CondDB
     CondDB(Upgrade=True)
     cond_algs = []
 
diff --git a/Rec/GlobalRecoMCTools/tests/options/test_protoparticleassociator.py b/Rec/GlobalRecoMCTools/tests/options/test_protoparticleassociator.py
index e22b1618a68..54eb891fd1d 100644
--- a/Rec/GlobalRecoMCTools/tests/options/test_protoparticleassociator.py
+++ b/Rec/GlobalRecoMCTools/tests/options/test_protoparticleassociator.py
@@ -29,7 +29,6 @@ from __future__ import print_function
 from Configurables import (
     ApplicationMgr,
     ChargedProtoParticleAssociator,
-    CondDB,
     LHCbApp,
     MergeLinksByKeysToVector,
     NeutralProtoParticleAssociator,
@@ -93,6 +92,7 @@ if UseDD4Hep:
             SliceLocation="IOVLockDD4hep"),
     ]
 else:
+    from Configurables import CondDB
     CondDB(Upgrade=True)
     cond_algs = []
 
diff --git a/Rich/RichFutureRecMonitors/python/RichFutureRecMonitors/ConfiguredRecoMonitors.py b/Rich/RichFutureRecMonitors/python/RichFutureRecMonitors/ConfiguredRecoMonitors.py
index 52159a31171..f594fa33843 100644
--- a/Rich/RichFutureRecMonitors/python/RichFutureRecMonitors/ConfiguredRecoMonitors.py
+++ b/Rich/RichFutureRecMonitors/python/RichFutureRecMonitors/ConfiguredRecoMonitors.py
@@ -8,6 +8,7 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 
 # Returns a configured monitoring (MC free) sequence.
@@ -107,6 +108,9 @@ def RichRecMonitors(
     algprops["Radiators"] = radsF
     # Detectors
     algprops["Detectors"] = (radsF[0] or radsF[1], radsF[2])
+    # change TransportSvc in case of DD4hep
+    if UseDD4Hep:
+        algprops["TransportSvc"] = "TGeoTransportSvc"
 
     # Units
     GeV = 1000
diff --git a/Rich/RichFutureRecSys/tests/options/pmt-v3-data.py b/Rich/RichFutureRecSys/tests/options/pmt-v3-data.py
index e7e003dbda1..d8f9760485e 100644
--- a/Rich/RichFutureRecSys/tests/options/pmt-v3-data.py
+++ b/Rich/RichFutureRecSys/tests/options/pmt-v3-data.py
@@ -11,9 +11,12 @@
 
 from Gaudi.Configuration import *
 
-from Configurables import CondDB, DDDBConf
+from Configurables import DDDBConf
+from DDDB.CheckDD4Hep import UseDD4Hep
 
-CondDB().setProp("Upgrade", True)
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB().setProp("Upgrade", True)
 
 # Timestamps in messages
 from Configurables import LHCbApp
diff --git a/Rich/RichFutureRecSys/tests/options/rich-dst-reco.py b/Rich/RichFutureRecSys/tests/options/rich-dst-reco.py
index 6a5b901e5d0..23aa316e674 100644
--- a/Rich/RichFutureRecSys/tests/options/rich-dst-reco.py
+++ b/Rich/RichFutureRecSys/tests/options/rich-dst-reco.py
@@ -13,7 +13,7 @@
 
 from Gaudi.Configuration import *
 from GaudiConfig.ControlFlow import seq
-from Configurables import CondDB, LHCbApp, GaudiSequencer, DDDBConf
+from Configurables import LHCbApp, GaudiSequencer, DDDBConf
 from Configurables import FPEAuditor
 import os
 
@@ -21,7 +21,6 @@ import os
 
 # Just to initialise
 DDDBConf()
-CondDB()
 LHCbApp()
 
 # Event numbers
diff --git a/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.dd4hep b/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.dd4hep
index 6acaa9413bc..0b09902f6ed 100644
--- a/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.dd4hep
+++ b/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.dd4hep
@@ -41,8 +41,6 @@ ApplicationMgr                   INFO Application Manager Started successfully
 EventSelector                 SUCCESS Reading Event record 1. Record number within stream 1: 1
 DeMagnetConditionCall            INFO Loading mag field from DBASE/FieldMap/vXrYpZ/cdf
 MagneticFieldExtension           INFO Scale factor: 1.000000
-TransportSvc                     INFO Initialize the static pointer to DetDesc::IGeometryErrorSvc
-TransportSvc                     INFO Recovery of geometry errors is  ENABLED
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_2 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_101.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_3 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_102.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_4 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_103.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
@@ -150,10 +148,6 @@ EventSelector                    INFO Stream:EventSelector.DataStreamTool_50 Def
 RootCnvSvc                       INFO Removed disconnected IO  stream:00000000-0000-0000-0000-000000000000 [root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_146.xdst]
 ApplicationMgr                   INFO Application Manager Stopped successfully
 EventLoopMgr                     INFO Histograms converted successfully according to request.
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Skip'     map has the size 0
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Recover'  map has the size 0
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Codes'    map has the size 0
-TransportSvc                     INFO Reset the static pointer to DetDesc::IGeometyrErrorSvc
 ApplicationMgr                   INFO Application Manager Finalized successfully
 ApplicationMgr                   INFO Application Manager Terminated successfully
 RichDLLsDown                     INFO Number of counters : 4
diff --git a/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.x86_64_v3-dd4hep-opt b/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.x86_64_v3-dd4hep-opt
index 75deddbdb4e..d13ad046880 100644
--- a/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.x86_64_v3-dd4hep-opt
+++ b/Rich/RichFutureRecSys/tests/refs/rich-dst-reco-pmt-v3.ref.x86_64_v3-dd4hep-opt
@@ -41,8 +41,6 @@ ApplicationMgr                   INFO Application Manager Started successfully
 EventSelector                 SUCCESS Reading Event record 1. Record number within stream 1: 1
 DeMagnetConditionCall            INFO Loading mag field from DBASE/FieldMap/vXrYpZ/cdf
 MagneticFieldExtension           INFO Scale factor: 1.000000
-TransportSvc                     INFO Initialize the static pointer to DetDesc::IGeometryErrorSvc
-TransportSvc                     INFO Recovery of geometry errors is  ENABLED
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_2 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_101.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_3 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_102.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
 EventSelector                    INFO Stream:EventSelector.DataStreamTool_4 Def:DATAFILE='PFN:root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_103.xdst' SVC='Gaudi::RootEvtSelector' OPT='READ'
@@ -150,10 +148,6 @@ EventSelector                    INFO Stream:EventSelector.DataStreamTool_50 Def
 RootCnvSvc                       INFO Removed disconnected IO  stream:00000000-0000-0000-0000-000000000000 [root://eoslhcb.cern.ch//eos/lhcb/user/j/jonrob/data/MC/Run3/BM-20220111-DDDB/30000000/XDST/Brunel_146.xdst]
 ApplicationMgr                   INFO Application Manager Stopped successfully
 EventLoopMgr                     INFO Histograms converted successfully according to request.
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Skip'     map has the size 0
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Recover'  map has the size 0
-TransportSvc                  SUCCESS  GEOMETRY ERRORS: 'Codes'    map has the size 0
-TransportSvc                     INFO Reset the static pointer to DetDesc::IGeometyrErrorSvc
 ApplicationMgr                   INFO Application Manager Finalized successfully
 ApplicationMgr                   INFO Application Manager Terminated successfully
 RichDLLsDown                     INFO Number of counters : 4
diff --git a/Tf/TrackSys/python/TrackSys/RecoUpgradeTracking.py b/Tf/TrackSys/python/TrackSys/RecoUpgradeTracking.py
index d84422671af..df9ec1396e1 100755
--- a/Tf/TrackSys/python/TrackSys/RecoUpgradeTracking.py
+++ b/Tf/TrackSys/python/TrackSys/RecoUpgradeTracking.py
@@ -15,9 +15,12 @@ from TrackSys.Configuration import *
 from GaudiKernel.SystemOfUnits import mm
 from GaudiKernel.SystemOfUnits import GeV
 
+transportSvcName = 'TransportSvc'
+
 from DDDB.CheckDD4Hep import UseDD4Hep
 if UseDD4Hep:
     from Configurables import LHCb__Det__LbDD4hep__IOVProducer as IOVProducer
+    transportSvcName = 'TGeoTransportSvc'
 
 from Configurables import LHCb__UnpackRawEvent
 
@@ -420,7 +423,7 @@ def RecoFastTrackingStage(defTracks={},
     defTracks = deepcopy(defTracks)
 
     ## Start TransportSvc, needed by track fit  ???
-    ApplicationMgr().ExtSvc.append("TransportSvc")
+    ApplicationMgr().ExtSvc.append(transportSvcName)
     subDets = GetSubDets()
     if trackTypes is None:
         trackTypes = TrackSys().getProp("TrackTypes")
@@ -494,7 +497,7 @@ def RecoMuonMatchTrackingStage(defTracks={},
     defTracks = deepcopy(defTracks)
 
     ## Start TransportSvc, needed by track fit  ???
-    ApplicationMgr().ExtSvc.append("TransportSvc")
+    ApplicationMgr().ExtSvc.append(transportSvcName)
 
     ### Do the decoding of the detectors
     decoding_algs = DecodeTracking(GetSubDets())
@@ -556,7 +559,7 @@ def RecoBestTrackingStage(tracklists=[],
     defTracks = deepcopy(defTracks)
 
     ## Start TransportSvc, needed by track fit  ???
-    ApplicationMgr().ExtSvc.append("TransportSvc")
+    ApplicationMgr().ExtSvc.append(transportSvcName)
     subDets = GetSubDets()
     if trackTypes is None:
         trackTypes = TrackSys().getProp("TrackTypes")
diff --git a/Tr/TrackExtrapolators/tests/options/test_extrapolators.py b/Tr/TrackExtrapolators/tests/options/test_extrapolators.py
index d05672dee13..b1b3b2eabf6 100644
--- a/Tr/TrackExtrapolators/tests/options/test_extrapolators.py
+++ b/Tr/TrackExtrapolators/tests/options/test_extrapolators.py
@@ -8,7 +8,7 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
-from Configurables import (CondDB, LHCbApp, ExtrapolatorTester, ApplicationMgr,
+from Configurables import (LHCbApp, ExtrapolatorTester, ApplicationMgr,
                            TrackRungeKuttaExtrapolator, TrackKiselExtrapolator,
                            TrackHerabExtrapolator, TrackMasterExtrapolator,
                            TrackSimpleExtraSelector)
@@ -19,10 +19,12 @@ app = LHCbApp()
 app.EvtMax = 1
 app.DataType = "Upgrade"
 app.Simulation = True
-CondDB().Upgrade = True
 all = []
 
-if UseDD4Hep:
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB().Upgrade = True
+else:
     from Configurables import LHCb__Tests__FakeRunNumberProducer as FET
     from Configurables import LHCb__Det__LbDD4hep__IOVProducer as IOVProducer
     odin_path = '/Event/DummyODIN'
-- 
GitLab


From 3981a1ed952b19602184e53dac31b5c525b48c54 Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Thu, 20 Oct 2022 08:52:10 +0200
Subject: [PATCH 25/26] Fixed recent 2022-data test that was not DD4hep
 compliant

---
 Rich/RichFutureRecSys/tests/options/2022-data.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Rich/RichFutureRecSys/tests/options/2022-data.py b/Rich/RichFutureRecSys/tests/options/2022-data.py
index f820a5b4165..8ab4ed3e8a5 100644
--- a/Rich/RichFutureRecSys/tests/options/2022-data.py
+++ b/Rich/RichFutureRecSys/tests/options/2022-data.py
@@ -12,7 +12,8 @@ from __future__ import print_function
 
 from Gaudi.Configuration import *
 from GaudiConf import IOHelper
-from Configurables import CondDB, LHCbApp, DDDBConf
+from Configurables import LHCbApp, DDDBConf
+from DDDB.CheckDD4Hep import UseDD4Hep
 
 data = [
     "mdf:root://eoslhcb.cern.ch//eos/lhcb/hlt2/LHCb/0000248711/Run_0000248711_HLT20840_20221011-113809-426.mdf"
@@ -21,7 +22,9 @@ IOHelper('MDF').inputFiles(data, clear=True)
 
 LHCbApp().Simulation = True
 LHCbApp().DataType = "Upgrade"
-CondDB().setProp("Upgrade", True)
+if not UseDD4Hep:
+    from Configurables import CondDB
+    CondDB().setProp("Upgrade", True)
 from DDDB.CheckDD4Hep import UseDD4Hep
 if not UseDD4Hep:
     LHCbApp().DDDBtag = "upgrade/master"
-- 
GitLab


From 1107d16d446ab2f3ad4a97399e9565fb55e55caa Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Fri, 21 Oct 2022 10:57:38 +0200
Subject: [PATCH 26/26] Optimized usgae of derived conditions by only
 retrieving them once per event

---
 .../src/CaloFutureClusterCovarianceAlg.cpp    |  9 ++-
 .../src/CaloFutureCorrectionBase.cpp          | 13 +--
 .../src/CaloFutureCorrectionBase.h            | 19 ++---
 .../src/CaloFutureECorrection.cpp             | 48 ++++++-----
 .../src/CaloFutureLCorrection.cpp             | 11 ++-
 .../src/CaloFutureMergedPi0.cpp               | 25 +++---
 .../src/CaloFutureSCorrection.cpp             | 79 +++++++++++--------
 .../src/CaloFutureShowerOverlap.cpp           | 14 ++--
 .../src/CaloFutureShowerOverlapTool.cpp       | 21 +++--
 .../src/FutureClusterCovarianceMatrixTool.h   | 65 ++++++++-------
 .../src/FutureSubClusterSelectorTool.h        | 19 +++--
 .../src/TrackParametrizedExtrapolator.cpp     | 12 ++-
 12 files changed, 193 insertions(+), 142 deletions(-)

diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
index e6a200aa821..92f22261d39 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp
@@ -81,20 +81,25 @@ namespace LHCb::Calo::Algorithms {
     Event::Calo::Clusters outputClusters{Zipping::generateZipIdentifier(), LHCb::getMemResource( evtCtx )};
     outputClusters.reserve( clusters.size() );
 
+    // get parameters from m_cov and m_tagger, this is basically a local cache
+    // of conditions so that we are not retrieving them n times
+    auto const& params = m_cov->getParameters();
+    auto const& tags   = m_tagger->getTags();
+
     // copy clusters to new container, and apply corrections on the way...
     for ( const auto cluster : clusters.scalar() ) {
       outputClusters.copy_back<SIMDWrapper::InstructionSet::Scalar>( cluster );
       auto newcluster = outputClusters.scalar()[outputClusters.size() - 1];
 
       // == APPLY TAGGER
-      if ( m_tagger->tag( calo, newcluster.cellID(), newcluster.entries() ).isFailure() ) {
+      if ( m_tagger->tag( tags, calo, newcluster.cellID(), newcluster.entries() ).isFailure() ) {
         ++m_tagger_error;
         outputClusters.resize( outputClusters.size() - 1 );
         continue;
       }
 
       // == APPLY COVARIANCE ESTIMATOR
-      if ( ( *m_cov ).compute( calo, newcluster ).isFailure() ) {
+      if ( ( *m_cov ).compute( params, calo, newcluster ).isFailure() ) {
         ++m_cov_error;
         outputClusters.resize( outputClusters.size() - 1 );
         continue;
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
index f3dadfe0704..40737e5192c 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp
@@ -247,24 +247,25 @@ namespace LHCb::Calo::Correction {
     }
   }
 
-  std::optional<Result> Base::getCorrectionAndDerivative( const Type type, const LHCb::Detector::Calo::CellID id,
-                                                          const float var ) const {
+  std::optional<Result> Base::getCorrectionAndDerivative( Parameters const& params, const Type type,
+                                                          const LHCb::Detector::Calo::CellID id,
+                                                          const float                        var ) const {
     return std::visit(
         Gaudi::overload( [&]( const auto& data ) -> std::optional<Result> { return data.correction( var ); },
                          []( const ParamVector& ) -> std::optional<Result> {
                            return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
                          } ),
-        m_params.get()[static_cast<int>( type )][id.area()] );
+        params[static_cast<int>( type )][id.area()] );
   }
 
-  std::optional<float> Base::getCorrection( const Type type, const LHCb::Detector::Calo::CellID id,
-                                            const float var ) const {
+  std::optional<float> Base::getCorrection( Parameters const& params, const Type type,
+                                            const LHCb::Detector::Calo::CellID id, const float var ) const {
     return std::visit(
         Gaudi::overload( [&]( const auto& data ) -> std::optional<float> { return data.correction( var ).value; },
                          []( const ParamVector& ) -> std::optional<float> {
                            return std::nullopt; // FIXME: throw exception instead? (and drop the use of optional)
                          } ),
-        m_params.get()[static_cast<int>( type )][id.area()] );
+        params[static_cast<int>( type )][id.area()] );
   }
 
 } // namespace LHCb::Calo::Correction
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
index a029feaeb79..fa456ef8a48 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h
@@ -171,28 +171,19 @@ namespace LHCb::Calo::Correction {
     StatusCode initialize() override;
     StatusCode finalize() override;
 
-    std::optional<Result> getCorrectionAndDerivative( const Type type, const Detector::Calo::CellID id,
-                                                      const float var = 0. ) const;
+    Parameters const& getParameters() const { return m_params.get(); }
 
-    std::optional<float> getCorrection( const Type type, const Detector::Calo::CellID id, const float var = 0. ) const;
+    std::optional<Result> getCorrectionAndDerivative( Parameters const& params, const Type type,
+                                                      const Detector::Calo::CellID id, const float var = 0. ) const;
 
-    const std::vector<float>& getParamVector( const Type                   type,
-                                              const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
-      return std::get<ParamVector>( m_params.get()[static_cast<int>( type )][id.area()] ).params;
-    }
+    std::optional<float> getCorrection( Parameters const& params, const Type type, const Detector::Calo::CellID id,
+                                        const float var = 0. ) const;
 
     const std::vector<float>& getParamVector( Parameters const& params, Type const type,
                                               Detector::Calo::CellID const id = Detector::Calo::CellID() ) const {
       return std::get<ParamVector>( params[static_cast<int>( type )][id.area()] ).params;
     }
 
-    std::optional<float> getParameter( Type type, unsigned int i,
-                                       const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
-      const auto& data = getParamVector( type, id );
-      if ( i >= data.size() ) return std::nullopt;
-      return data[i];
-    }
-
     std::optional<float> getParameter( Parameters const& params, Type type, unsigned int i,
                                        const Detector::Calo::CellID id = Detector::Calo::CellID() ) const {
       const auto& data = getParamVector( params, type, id );
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
index 07ee3e4a204..090b5d5b031 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp
@@ -133,11 +133,12 @@ namespace LHCb::Calo {
       float gT    = 0;
     };
 
-    ECorrOutputParams calcECorrection( const DeCalorimeter& calo, const ECorrInputParams& params ) const;
+    ECorrOutputParams calcECorrection( Correction::Parameters const& baseParams, const DeCalorimeter& calo,
+                                       const ECorrInputParams& params ) const;
 
     /// debugging necessary in case if any new corrections are added or their sequence is changed!
-    void debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
-                                      const ECorrOutputParams& outParams ) const;
+    void debugDerivativesCalculation( Correction::Parameters const& baseParams, DeCalorimeter const& calo,
+                                      ECorrInputParams const& inParams, ECorrOutputParams const& outParams ) const;
 
   private:
     /**
@@ -297,7 +298,8 @@ namespace LHCb::Calo {
      */
     ECorrInputParams params{cellID, seedPos, xBar, yBar, (float)position.z(), eEcal, dtheta, cellID.area()};
 
-    /////////////////////////////////////////////////////////
+    // get parameters from base class, needed to call getCorrection*
+    Correction::Parameters const& baseParams = getParameters();
 
     /* Calculate corrected energy in a separate function call. Necessary for debugging the Jacobian by calculating
      * numeric derivatives w.r.t. (X, Y, E) in case of any changes in the correction code.
@@ -306,7 +308,7 @@ namespace LHCb::Calo {
      * all the other paramers and results of intermediate calculations are shared between the two methods
      * using local ECorrInputParams _params, and [zero-initialized] ECorrOutputParams _results.
      */
-    ECorrOutputParams results = calcECorrection( calo, params );
+    ECorrOutputParams results = calcECorrection( baseParams, calo, params );
     float             eCor    = results.eCor;
 
     // results of semi-analytic derivative calculation
@@ -324,7 +326,7 @@ namespace LHCb::Calo {
 
     // debugging necessary in case if any new corrections are added or their sequence is changed!
     if ( msgLevel( MSG::DEBUG ) ) {
-      if ( m_correctCovariance ) debugDerivativesCalculation( calo, params, results );
+      if ( m_correctCovariance ) debugDerivativesCalculation( baseParams, calo, params, results );
     }
 
     m_countersAlpha.at( cellID.area() ) += results.alpha;
@@ -407,8 +409,9 @@ namespace LHCb::Calo {
     if ( msgLevel( MSG::DEBUG ) ) { debug() << "after E-corr. cov.m. = \n" << covariance << endmsg; }
   }
 
-  ECorrection::ECorrOutputParams ECorrection::calcECorrection( const DeCalorimeter&    calo,
-                                                               const ECorrInputParams& _params ) const {
+  ECorrection::ECorrOutputParams ECorrection::calcECorrection( Correction::Parameters const& baseParams,
+                                                               DeCalorimeter const&          calo,
+                                                               ECorrInputParams const&       _params ) const {
     // local aliases for the input variables passed from process() to calcECorrection()
     const Detector::Calo::CellID& cellID  = _params.cellID;
     const Gaudi::XYZPoint&        seedPos = _params.seedPos;
@@ -441,20 +444,20 @@ namespace LHCb::Calo {
     // are useful for debugging in case of changes in the correction function code
     //
     //// aG = const(X,Y,E), no need to calculate derivatives
-    float aG = getCorrection( Correction::Type::alphaG, cellID ).value_or( 1. ); // global Ecal factor
+    float aG = getCorrection( baseParams, Correction::Type::alphaG, cellID ).value_or( 1. ); // global Ecal factor
     //// aE = alphaE(eEcal)
-    const auto aECorDer = getCorrectionAndDerivative( Correction::Type::alphaE, cellID, eEcal )
+    const auto aECorDer = getCorrectionAndDerivative( baseParams, Correction::Type::alphaE, cellID, eEcal )
                               .value_or( Correction::Result{1., 0.} ); // longitudinal leakage
     const auto aE       = aECorDer.value;
-    const auto aBCorDer = getCorrectionAndDerivative( Correction::Type::alphaB, cellID, bDist )
+    const auto aBCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::alphaB, cellID, bDist )
                               .value_or( Correction::Result{1., 0.} ); // lateral leakage
     const auto aB = aBCorDer.value;
     //// aX = alphaX(Asx1)
-    const auto aXCorDer = getCorrectionAndDerivative( Correction::Type::alphaX, cellID, Asx )
+    const auto aXCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::alphaX, cellID, Asx )
                               .value_or( Correction::Result{1., 0.} ); // module frame dead material X-direction
     const auto aX = aXCorDer.value;
     //// aY = alphaY(Asy1)
-    const auto aYCorDer = getCorrectionAndDerivative( Correction::Type::alphaY, cellID, Asy )
+    const auto aYCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::alphaY, cellID, Asy )
                               .value_or( Correction::Result{1., 0.} ); // module frame dead material Y-direction
     const auto aY = aYCorDer.value;
     if ( m_correctCovariance ) {
@@ -466,12 +469,14 @@ namespace LHCb::Calo {
 
     // angular correction
     // assume dtheta to be independent of X,Y,E, although it may still be implicitly a bit dependent on X,Y
-    float gT = getCorrection( Correction::Type::globalT, cellID, dtheta ).value_or( 1. ); // incidence angle (delta)
-    float dT = getCorrection( Correction::Type::offsetT, cellID, dtheta ).value_or( 0. ); // incidence angle (delta)
+    float gT = getCorrection( baseParams, Correction::Type::globalT, cellID, dtheta ).value_or( 1. ); // incidence angle
+                                                                                                      // (delta)
+    float dT = getCorrection( baseParams, Correction::Type::offsetT, cellID, dtheta ).value_or( 0. ); // incidence angle
+                                                                                                      // (delta)
 
     // Energy offset
     float sinT   = calo.cellSine( cellID );
-    float offset = getCorrection( Correction::Type::offset, cellID, sinT ).value_or( 0. );
+    float offset = getCorrection( baseParams, Correction::Type::offset, cellID, sinT ).value_or( 0. );
 
     // Apply Ecal leakage corrections
     float alpha = aG * aE * aB * aX * aY;
@@ -550,8 +555,9 @@ namespace LHCb::Calo {
     return results;
   }
 
-  void ECorrection::debugDerivativesCalculation( const DeCalorimeter& calo, const ECorrInputParams& inParams,
-                                                 const ECorrOutputParams& outParams ) const {
+  void ECorrection::debugDerivativesCalculation( Correction::Parameters const& baseParams, DeCalorimeter const& calo,
+                                                 ECorrInputParams const&  inParams,
+                                                 ECorrOutputParams const& outParams ) const {
     const float dx_rel( 1e-5 ), dy_rel( 1e-5 ), de_rel( 1e-3 ); // dx,dy ~ few*0.1*mm, de ~ few MeV
     float       xBar       = inParams.x;
     float       yBar       = inParams.y;
@@ -564,19 +570,19 @@ namespace LHCb::Calo {
     debug() << "\n ------------------------ ECorrection(x+dx, y, e) calculation follows ------------------- " << endmsg;
     ECorrInputParams inParams1( inParams );
     inParams1.x      = inParams1.x * ( 1 + dx_rel );
-    auto  outParams1 = calcECorrection( calo, inParams1 );
+    auto  outParams1 = calcECorrection( baseParams, calo, inParams1 );
     float eCor_x     = outParams1.eCor;
 
     debug() << "\n ------------------------ ECorrection(x, y+dy, e) calculation follows ------------------- " << endmsg;
     ECorrInputParams inParams2( inParams );
     inParams2.y      = inParams2.y * ( 1 + dy_rel );
-    auto  outParams2 = calcECorrection( calo, inParams2 );
+    auto  outParams2 = calcECorrection( baseParams, calo, inParams2 );
     float eCor_y     = outParams2.eCor;
 
     debug() << "\n ------------------------ ECorrection(e, y, e+de) calculation follows ------------------- " << endmsg;
     ECorrInputParams inParams3( inParams );
     inParams3.eEcal  = inParams2.eEcal * ( 1 + de_rel );
-    auto  outParams3 = calcECorrection( calo, inParams3 );
+    auto  outParams3 = calcECorrection( baseParams, calo, inParams3 );
     float eCor_e     = outParams3.eCor;
 
     float dn_eCor_dx = ( eCor_x - eCor ) / xBar / dx_rel;
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
index 7f2d89ccb9c..68c14c2c1f8 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp
@@ -60,14 +60,17 @@ namespace LHCb::Calo {
       float xyz_offset = Math::Approx::approx_sqrt( xg * xg + yg * yg + zg * zg );
       float tan_theta  = xy_offset / zg;
 
+      // get parameters from base class, needed to call getCorrection*
+      Correction::Parameters const& baseParams = getParameters();
+
       // Corrected angle
-      float gamma0 = getCorrection( Correction::Type::gamma0, cellID ).value_or( 1 );
-      float delta0 = getCorrection( Correction::Type::delta0, cellID ).value_or( 1 );
+      float gamma0 = getCorrection( baseParams, Correction::Type::gamma0, cellID ).value_or( 1 );
+      float delta0 = getCorrection( baseParams, Correction::Type::delta0, cellID ).value_or( 1 );
 
       // NB: gammaP(ePrs = 0) != 0, deltaP(ePrs = 0) != 0 and depend on cellID.area()
       // get gammaP and deltaP parameters (depending on cellID.area() for each cluster
-      float gammaP = getCorrection( Correction::Type::gammaP, cellID, 0. ).value_or( 1 );
-      float deltaP = getCorrection( Correction::Type::deltaP, cellID, 0. ).value_or( 1 );
+      float gammaP = getCorrection( baseParams, Correction::Type::gammaP, cellID, 0. ).value_or( 1 );
+      float deltaP = getCorrection( baseParams, Correction::Type::deltaP, cellID, 0. ).value_or( 1 );
       float g      = gamma0 - gammaP;
       float d      = delta0 + deltaP;
 
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp
index 78fbb047f60..1cd3f1e2bd0 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp
@@ -77,9 +77,9 @@ namespace LHCb::Calo::Algorithm {
 
   private:
     template <typename Entries, typename FloatE, typename FloatZ>
-    decltype( auto ) addSubCluster( Clusters& clusters, LHCb::Detector::Calo::CellID seed,
-                                    LHCb::Detector::Calo::CellID seed2, FloatE seede, FloatE seed2e, Entries&& entries,
-                                    FloatZ z, const DeCalorimeter& det ) const {
+    decltype( auto ) addSubCluster( SubClusterSelectorTool::Tags const& tags, Clusters& clusters,
+                                    LHCb::Detector::Calo::CellID seed, LHCb::Detector::Calo::CellID seed2, FloatE seede,
+                                    FloatE seed2e, Entries&& entries, FloatZ z, DeCalorimeter const& det ) const {
 
       constexpr auto used   = LHCb::CaloDigitStatus::Status{LHCb::CaloDigitStatus::Mask::UseForEnergy,
                                                           LHCb::CaloDigitStatus::Mask::UseForPosition,
@@ -107,7 +107,7 @@ namespace LHCb::Calo::Algorithm {
       // --  apply position tagger (possibly replacing the 3x3 already set)
       // --  needed to apply hypo S/L-corrections with correct parameters internally
       // --  keep the 3x3 energy tag for the time being (to be applied after the overlap subtraction)
-      m_tagger->tagPosition( det, seed, cluster.entries() ).orElse( [&] { ++m_tag_failed; } ).ignore();
+      m_tagger->tagPosition( tags, det, seed, cluster.entries() ).orElse( [&] { ++m_tag_failed; } ).ignore();
 
       auto r = LHCb::CaloDataFunctor::calculateClusterEXY( cluster.entries(), &det );
 
@@ -209,6 +209,11 @@ namespace LHCb::Calo::Algorithm {
     auto cntFailsToTagECluster1 = m_cntFailsToTagECluster1.buffer();
     auto cntFailsToTagECluster2 = m_cntFailsToTagECluster2.buffer();
 
+    // get parameters from m_cov and m_tagger, this is basically a local cache
+    // of conditions so that we are not retrieving them n times
+    auto const& params = m_cov->getParameters();
+    auto const& tags   = m_tagger->getTags();
+
     // ============ loop over all clusters ==============
     for ( auto&& cluster : clusters.scalar() ) {
       if ( 0 < m_etCut && m_etCut > eT( &cluster ) ) continue;
@@ -242,8 +247,8 @@ namespace LHCb::Calo::Algorithm {
       if ( !seed2 ) continue;
 
       // -- create and fill sub-clusters
-      auto cl1 = addSubCluster( splitClusters, seed, seed2, seede, seed2e, entries, zNominal, det );
-      auto cl2 = addSubCluster( splitClusters, seed2, seed, seed2e, seede, entries, zNominal, det );
+      auto cl1 = addSubCluster( tags, splitClusters, seed, seed2, seede, seed2e, entries, zNominal, det );
+      auto cl2 = addSubCluster( tags, splitClusters, seed2, seed, seed2e, seede, entries, zNominal, det );
 
       // == apply the mergedPi0 tool : subtract shower overlap
       m_oTool->process( det, cl1, cl2, geometry, m_iter,
@@ -266,13 +271,13 @@ namespace LHCb::Calo::Algorithm {
       // == APPLY CLUSTER TOOLS : Energy tagger,  covariance & spread (position tagger already applied):
       // to reduce branching, unconditionally increment all counter buffers
       // cluster energy tag
-      cntFailsToTagECluster1 += m_tagger->tagEnergy( det, cl1.cellID(), cl1.entries() ).isFailure();
-      cntFailsToTagECluster2 += m_tagger->tagEnergy( det, cl2.cellID(), cl2.entries() ).isFailure();
+      cntFailsToTagECluster1 += m_tagger->tagEnergy( tags, det, cl1.cellID(), cl1.entries() ).isFailure();
+      cntFailsToTagECluster2 += m_tagger->tagEnergy( tags, det, cl2.cellID(), cl2.entries() ).isFailure();
 
       //-- apply cluster covariance and spread tools...
-      m_cntFailsToSetCovariance += ( *m_cov ).compute( det, cl1 ).isFailure();
+      m_cntFailsToSetCovariance += ( *m_cov ).compute( params, det, cl1 ).isFailure();
       m_cntFailsToSetSpread += ( *m_spread ).compute( det, cl1 ).isFailure();
-      m_cntFailsToSetCovariance += ( *m_cov ).compute( det, cl2 ).isFailure();
+      m_cntFailsToSetCovariance += ( *m_cov ).compute( params, det, cl2 ).isFailure();
       m_cntFailsToSetSpread += ( *m_spread ).compute( det, cl2 ).isFailure();
     }
 
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
index 82a689db4ce..51835d1d55f 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp
@@ -85,10 +85,11 @@ namespace LHCb::Calo {
     };
 
     /// calculate corrected CaloHypo position depending on CaloCluster position
-    SCorrResults calculateSCorrections( const DeCalorimeter& calo, const SCorrInputParams& params ) const;
+    SCorrResults calculateSCorrections( Correction::Parameters const&, DeCalorimeter const&,
+                                        SCorrInputParams const& ) const;
 
-    void debugDerivativesCalculation( const DeCalorimeter& calo, const SCorrInputParams& inParams,
-                                      const SCorrResults& outParams ) const;
+    void debugDerivativesCalculation( Correction::Parameters const&, DeCalorimeter const&, SCorrInputParams const&,
+                                      SCorrResults const& ) const;
 
   private:
     std::array<float, 4> compute( const DeCalorimeter& calo, SCorrInputParams params ) const {
@@ -103,7 +104,10 @@ namespace LHCb::Calo {
        *  (7) Position of seed cell  :    seedPos
        */
 
-      SCorrResults results = calculateSCorrections( calo, params );
+      // get parameters from base class, needed to call getCorrection*
+      Correction::Parameters const& baseParams = getParameters();
+
+      SCorrResults results = calculateSCorrections( baseParams, calo, params );
       float        xCor    = results.xCor;
       float        yCor    = results.yCor;
 
@@ -122,7 +126,8 @@ namespace LHCb::Calo {
         dYhy_dYcl = 1.;
       }
 
-      if ( msgLevel( MSG::DEBUG ) && m_correctCovariance ) debugDerivativesCalculation( calo, params, results );
+      if ( msgLevel( MSG::DEBUG ) && m_correctCovariance )
+        debugDerivativesCalculation( baseParams, calo, params, results );
 
       return {xCor, yCor, dXhy_dXcl, dYhy_dYcl};
     }
@@ -178,8 +183,9 @@ namespace LHCb::Calo {
 
   // ============================================================================
 
-  SCorrection::SCorrResults SCorrection::calculateSCorrections( const DeCalorimeter&    calo,
-                                                                const SCorrInputParams& params ) const {
+  SCorrection::SCorrResults SCorrection::calculateSCorrections( Correction::Parameters const& baseParams,
+                                                                DeCalorimeter const&          calo,
+                                                                SCorrInputParams const&       params ) const {
     SCorrResults                        results{0, 0, 0, 0};
     const LHCb::Detector::Calo::CellID& cellID  = params.cellID;
     const Gaudi::XYZPoint&              seedPos = params.seedPos;
@@ -192,45 +198,45 @@ namespace LHCb::Calo {
     float Asy      = -( yBar - seedPos.y() ) / CellSize;
 
     // Sshape correction :
-    auto AsxCorDer =
-        getCorrectionAndDerivative( Correction::Type::shapeX, cellID, Asx ).value_or( Correction::Result{Asx, 1.} );
-    Asx                = AsxCorDer.value; // Asx1
-    const auto DshapeX = AsxCorDer.derivative;
-    auto       AsyCorDer =
-        getCorrectionAndDerivative( Correction::Type::shapeY, cellID, Asy ).value_or( Correction::Result{Asy, 1.} );
+    auto AsxCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::shapeX, cellID, Asx )
+                         .value_or( Correction::Result{Asx, 1.} );
+    Asx                  = AsxCorDer.value; // Asx1
+    const auto DshapeX   = AsxCorDer.derivative;
+    auto       AsyCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::shapeY, cellID, Asy )
+                         .value_or( Correction::Result{Asy, 1.} );
     Asy                = AsyCorDer.value; // Asy1
     const auto DshapeY = AsyCorDer.derivative;
 
     // Angular correction (if any) [ NEW  - inserted between Sshape and residual correction ]
-    const float xs  = seedPos.x() - Asx * CellSize; // xscor
-    const float ys  = seedPos.y() - Asy * CellSize; // yscor
-    const float thx = LHCb::Math::fast_atan2( xs, (float)z );
-    const float thy = LHCb::Math::fast_atan2( ys, (float)z );
-    const auto [daX, DangularX] =
-        getCorrectionAndDerivative( Correction::Type::angularX, cellID, thx ).value_or( Correction::Result{0., 0.} );
-    const auto [daY, DangularY] =
-        getCorrectionAndDerivative( Correction::Type::angularY, cellID, thy ).value_or( Correction::Result{0., 0.} );
+    const float xs              = seedPos.x() - Asx * CellSize; // xscor
+    const float ys              = seedPos.y() - Asy * CellSize; // yscor
+    const float thx             = LHCb::Math::fast_atan2( xs, (float)z );
+    const float thy             = LHCb::Math::fast_atan2( ys, (float)z );
+    const auto [daX, DangularX] = getCorrectionAndDerivative( baseParams, Correction::Type::angularX, cellID, thx )
+                                      .value_or( Correction::Result{0., 0.} );
+    const auto [daY, DangularY] = getCorrectionAndDerivative( baseParams, Correction::Type::angularY, cellID, thy )
+                                      .value_or( Correction::Result{0., 0.} );
     Asx -= daX;
     Asy -= daY;
 
     // residual correction (if any):
-    auto dcXCorDer =
-        getCorrectionAndDerivative( Correction::Type::residual, cellID, Asx ).value_or( Correction::Result{0., 0.} );
+    auto dcXCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::residual, cellID, Asx )
+                         .value_or( Correction::Result{0., 0.} );
     auto dcX = dcXCorDer.value;
     if ( dcX == 0. ) {
       // check X-specific correction
-      dcXCorDer =
-          getCorrectionAndDerivative( Correction::Type::residualX, cellID, Asx ).value_or( Correction::Result{0., 0.} );
+      dcXCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::residualX, cellID, Asx )
+                      .value_or( Correction::Result{0., 0.} );
       dcX = dcXCorDer.value;
     }
     const auto DresidualX = dcXCorDer.derivative;
-    auto       dcYCorDer =
-        getCorrectionAndDerivative( Correction::Type::residual, cellID, Asy ).value_or( Correction::Result{0., 0.} );
+    auto       dcYCorDer  = getCorrectionAndDerivative( baseParams, Correction::Type::residual, cellID, Asy )
+                         .value_or( Correction::Result{0., 0.} );
     auto dcY = dcYCorDer.value;
     if ( dcY == 0. ) {
       // check Y-specific correction
-      dcYCorDer =
-          getCorrectionAndDerivative( Correction::Type::residualY, cellID, Asy ).value_or( Correction::Result{0., 0.} );
+      dcYCorDer = getCorrectionAndDerivative( baseParams, Correction::Type::residualY, cellID, Asy )
+                      .value_or( Correction::Result{0., 0.} );
       dcY = dcYCorDer.value;
     }
     const auto DresidualY = dcYCorDer.derivative;
@@ -239,10 +245,12 @@ namespace LHCb::Calo {
 
     // left/right - up/down asymmetries correction (if any) :
     const auto [ddcX, DasymX] =
-        getCorrectionAndDerivative( ( xBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP, cellID, Asx )
+        getCorrectionAndDerivative( baseParams, ( xBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP,
+                                    cellID, Asx )
             .value_or( Correction::Result{0., 0.} );
     const auto [ddcY, DasymY] =
-        getCorrectionAndDerivative( ( yBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP, cellID, Asy )
+        getCorrectionAndDerivative( baseParams, ( yBar < 0 ) ? Correction::Type::asymM : Correction::Type::asymP,
+                                    cellID, Asy )
             .value_or( Correction::Result{0., 0.} );
     Asx += ddcX; // Asx4
     Asy += ddcY; // Asy4
@@ -298,21 +306,22 @@ namespace LHCb::Calo {
     return results;
   }
 
-  void SCorrection::debugDerivativesCalculation( const DeCalorimeter& calo, const SCorrInputParams& inParams,
-                                                 const SCorrResults& outParams ) const {
+  void SCorrection::debugDerivativesCalculation( Correction::Parameters const& baseParams, DeCalorimeter const& calo,
+                                                 SCorrInputParams const& inParams,
+                                                 SCorrResults const&     outParams ) const {
     const float d_rel( 1.e-5 ); // dx ~ 0.1 mm for numeric derivative calculation
 
     debug() << " ---------- calculation of numeric derivative dXhypo/dXcluster follows -----------" << endmsg;
     SCorrInputParams inParams1( inParams );
     inParams1.x     = inParams1.x * ( 1 + d_rel );
     inParams1.y     = inParams1.y;
-    auto outParams1 = calculateSCorrections( calo, inParams1 );
+    auto outParams1 = calculateSCorrections( baseParams, calo, inParams1 );
 
     debug() << " ---------- calculation of numeric derivative dYhypo/dYcluster follows -----------" << endmsg;
     SCorrInputParams inParams2( inParams );
     inParams2.x     = inParams2.x;
     inParams2.y     = inParams2.y * ( 1 + d_rel );
-    auto outParams2 = calculateSCorrections( calo, inParams2 );
+    auto outParams2 = calculateSCorrections( baseParams, calo, inParams2 );
 
     float xCor_x = outParams1.xCor;
     float yCor_x = outParams1.yCor;
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp
index 1de6b0a07fe..3acec39f9db 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp
@@ -57,7 +57,7 @@ namespace LHCb::Calo {
 
   private:
     void correctForOverlap(
-        const DeCalorimeter&                                                                              calo,
+        SubClusterSelectorTool::Tags const& tags, DeCalorimeter const& calo,
         LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> c1,
         LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> c2,
         IGeometryInfo const& geometry ) const;
@@ -121,6 +121,10 @@ namespace LHCb::Calo {
         std::partition_point( outputClustersScalar.begin(), last,
                               [&eT, m = std::max( m_etMin, m_etMin2 )]( const auto& c ) { return eT( &c ) > m; } );
 
+    // get tags from m_tagger, this is basically a local cache
+    // of conditions so that we are not retrieving them n times
+    auto const& tags = m_tagger->getTags();
+
     // loop over new clusters and correct them
     auto counterDeltaZ = m_counterDeltaZ.buffer();
     auto counterDeltaX = m_counterDeltaX.buffer();
@@ -134,7 +138,7 @@ namespace LHCb::Calo {
         auto position2 = i2->position();
         auto e1        = i1->e();
         auto e2        = i2->e();
-        correctForOverlap( det, *i1, *i2, geometry );
+        correctForOverlap( tags, det, *i1, *i2, geometry );
         counterDeltaX += i1->position().x() + i2->position().x() - position1.x() - position2.x();
         counterDeltaY += i1->position().y() + i2->position().y() - position1.y() - position2.y();
         counterDeltaZ += i1->position().z() + i2->position().z() - position1.z() - position2.z();
@@ -150,7 +154,7 @@ namespace LHCb::Calo {
   }
 
   void ShowerOverlap::correctForOverlap(
-      const DeCalorimeter&                                                                              calo,
+      SubClusterSelectorTool::Tags const& tags, DeCalorimeter const& calo,
       LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> c1,
       LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> c2,
       IGeometryInfo const& geometry ) const {
@@ -167,8 +171,8 @@ namespace LHCb::Calo {
     }
 
     // tag the cluster position to have correct corrections
-    m_tagger->tagPosition( calo, c1.cellID(), c1.entries() )
-        .andThen( [&] { return m_tagger->tagPosition( calo, c2.cellID(), c2.entries() ); } )
+    m_tagger->tagPosition( tags, calo, c1.cellID(), c1.entries() )
+        .andThen( [&] { return m_tagger->tagPosition( tags, calo, c2.cellID(), c2.entries() ); } )
         .orElse( [&] { ++m_cluster_tagging_failed; } )
         .ignore();
     // correct entry weight for shower overlap (assuming EM cluster)
diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
index db349d3902d..ed11a49cc42 100644
--- a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
+++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp
@@ -83,13 +83,15 @@ namespace LHCb::Calo::Tools {
 
     using WeightMap = boost::container::flat_map<LHCb::Detector::Calo::CellID, float>;
 
-    float showerFraction( const Correction::Base& shape, const float d3d, const unsigned int area ) {
+    float showerFraction( Correction::Parameters const& baseParams, Correction::Base const& shape, float d3d,
+                          unsigned int area ) {
       LHCb::Detector::Calo::CellID cellID( Detector::Calo::CellCode::Index::EcalCalo, area, 0, 0 ); // fake cell
-      return std::clamp( shape.getCorrection( Correction::Type::profile, cellID, d3d ).value_or( 0. ), 0.f, 1.f );
+      return std::clamp( shape.getCorrection( baseParams, Correction::Type::profile, cellID, d3d ).value_or( 0. ), 0.f,
+                         1.f );
     }
 
     [[gnu::always_inline]] inline float
-    fraction( const Correction::Base& shape, const DeCalorimeter& det,
+    fraction( Correction::Parameters const& baseParams, Correction::Base const& shape, DeCalorimeter const& det,
               LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> cluster,
               LHCb::Detector::Calo::CellID cellID, float ed, int area ) {
 
@@ -102,7 +104,7 @@ namespace LHCb::Calo::Tools {
       auto d3d2 = (float)( ( xd - xc ) * ( xd - xc ) + ( yd - yc ) * ( yd - yc ) + ( zd - zc ) * ( zd - zc ) );
       auto size = det.cellSize( cellID );
       auto d3d  = LHCb::Math::Approx::approx_sqrt( d3d2 ) / size;
-      auto f    = showerFraction( shape, d3d, area );
+      auto f    = showerFraction( baseParams, shape, d3d, area );
       auto ec   = f * cluster.e();
       return ( ed > ec ) ? ( ed - ec ) / ed : 0.;
     }
@@ -254,6 +256,9 @@ namespace LHCb::Calo::Tools {
       verbose() << " >> E  : " << cl1.e() << " / " << cl2.e() << endmsg;
     }
 
+    // get parameters from base class, needed to call getCorrection*
+    Correction::Parameters const& baseParams = m_shape->getParameters();
+
     const auto evaluate_ = [this, applyCorrections, &geometry, &calo]( auto& cluster ) {
       return this->evaluate( calo, cluster, geometry, bool( applyCorrections ) );
     };
@@ -264,10 +269,12 @@ namespace LHCb::Calo::Tools {
       return it != weights.end() ? it->second : 1.;
     };
     const auto fraction_ =
-        [shape = std::cref( *m_shape ), det = std::cref( calo ), a1 = cl1.cellID().area(), a2 = cl2.cellID().area()](
+        [shape = std::cref( *m_shape ), det = std::cref( calo ), a1 = cl1.cellID().area(), a2 = cl2.cellID().area(),
+         &baseParams](
             LHCb::Event::Calo::Clusters::reference<SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous> c,
-            const auto&                                                                                       entry,
-            int flag ) { return fraction( shape, det, c, entry.cellID(), entry.energy(), flag == 1 ? a1 : a2 ); };
+            const auto& entry, int flag ) {
+          return fraction( baseParams, shape, det, c, entry.cellID(), entry.energy(), flag == 1 ? a1 : a2 );
+        };
     // 1 - determine the energy fractions of each entry
     // if niter < 0, stop if the tolerance criteria is satisfied (see definition),
     // perform maximum -niter iterations
diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
index d78bca3048a..1748922ef37 100644
--- a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h
@@ -273,8 +273,11 @@ namespace LHCb::Calo {
       return StatusCode::FAILURE;
     }
 
+    CovarianceMatrixTool::detail::ParameterMap const& getParameters() const { return m_parameters.get(); }
+
     template <typename ClusterType>
-    [[gnu::always_inline]] StatusCode compute( const DeCalorimeter& calo, ClusterType cluster ) const {
+    [[gnu::always_inline]] StatusCode compute( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                               DeCalorimeter const& calo, ClusterType cluster ) const {
 
       /// apply the estimator
 
@@ -303,16 +306,16 @@ namespace LHCb::Calo {
 
       const LHCb::Detector::Calo::CellID seedID = cluster.cellID();
       // the matrices:
-      auto See   = s2E( seedID ); // add constant term to global cov(EE)
+      auto See   = s2E( params, seedID ); // add constant term to global cov(EE)
       auto Sex   = 0.0f;
-      auto Sxx   = s2X( seedID ); // cov(XX)_0
+      auto Sxx   = s2X( params, seedID ); // cov(XX)_0
       auto Sey   = 0.0f;
       auto Sxy   = 0.0f;
-      auto Syy   = s2Y( seedID ); // cov(YY)_0
-      auto SeeP  = s2E( seedID );
+      auto Syy   = s2Y( params, seedID ); // cov(YY)_0
+      auto SeeP  = s2E( params, seedID );
       auto SexEP = 0.0f;
       auto SeyEP = 0.0f;
-      auto SeeEP = s2E( seedID );
+      auto SeeEP = s2E( params, seedID );
       using namespace LHCb::CaloDigitStatus;
 
       for ( auto&& [i, entry] : LHCb::range::enumerate( entries ) ) {
@@ -335,13 +338,13 @@ namespace LHCb::Calo {
         const auto             y_i = pos.y();
 
         // intrinsic resolution
-        auto s2 = std::abs( energy ) * a2GeV( id );
+        auto s2 = std::abs( energy ) * a2GeV( params, id );
         //  gain fluctuation
-        if ( auto s2g = s2gain( id ); s2g != 0 ) s2 += energy * energy * s2g;
+        if ( auto s2g = s2gain( params, id ); s2g != 0 ) s2 += energy * energy * s2g;
 
         //  noise (both coherent and incoherent)
         double g = 0;
-        if ( auto noise = s2noise( id ); noise != 0 ) {
+        if ( auto noise = s2noise( params, id ); noise != 0 ) {
           g = calo.cellGain( id );
           s2 += noise * g * g;
         }
@@ -376,7 +379,7 @@ namespace LHCb::Calo {
         }
 
         // second loop if there exist correlations
-        if ( 0 == s2coherent( id ) ) { continue; } ///<  CONTINUE
+        if ( 0 == s2coherent( params, id ) ) { continue; } ///<  CONTINUE
         x[i]    = x_i;
         y[i]    = y_i;
         gain[i] = g;
@@ -389,7 +392,7 @@ namespace LHCb::Calo {
           const auto y_j = y[j];
 
           // covariance between cell "i" and "j"
-          const auto s_ij = s2coherent( id ) * gain[i] * gain[j];
+          const auto s_ij = s2coherent( params, id ) * gain[i] * gain[j];
 
           bool jforE  = jt.status().test( LHCb::CaloDigitStatus::Mask::UseForEnergy );
           bool jforP  = jt.status().test( LHCb::CaloDigitStatus::Mask::UseForPosition );
@@ -468,8 +471,9 @@ namespace LHCb::Calo {
     /** calorimeter resolution (A*A*GeV)
      *  @return A*A*GeV resolution parameter
      */
-    [[nodiscard]] double a2GeV( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::Stochastic );
+    [[nodiscard]] double a2GeV( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::Stochastic );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()] * Gaudi::Units::GeV;
     }
@@ -477,8 +481,9 @@ namespace LHCb::Calo {
     /** get dispersion  of relative gain error
      *  @return dispersion of relative gain error
      */
-    [[nodiscard]] double s2gain( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::GainError );
+    [[nodiscard]] double s2gain( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                 LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::GainError );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
@@ -486,15 +491,17 @@ namespace LHCb::Calo {
     /** get  dispersion of noise (both coherent and incoherent
      *  @return overall noise dispersion
      */
-    [[nodiscard]] double s2noise( const LHCb::Detector::Calo::CellID id ) const {
-      return s2incoherent( id ) + s2coherent( id );
+    [[nodiscard]] double s2noise( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                  LHCb::Detector::Calo::CellID const                id ) const {
+      return s2incoherent( params, id ) + s2coherent( params, id );
     }
 
     /** get the dispersion of incoherent noise
      *  @return dispersion of incoherent noise
      */
-    [[nodiscard]] double s2incoherent( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::IncoherentNoise );
+    [[nodiscard]] double s2incoherent( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                       LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::IncoherentNoise );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
@@ -502,26 +509,30 @@ namespace LHCb::Calo {
     /**  dispersion of coherent  noise
      *  @return dispersion of coherent noise
      */
-    [[nodiscard]] double s2coherent( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::CoherentNoise );
+    [[nodiscard]] double s2coherent( CovarianceMatrixTool::detail::ParameterMap const& params,
+                                     LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::CoherentNoise );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
-    [[nodiscard]] double s2E( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantE );
+    [[nodiscard]] double s2E( CovarianceMatrixTool::detail::ParameterMap const& params,
+                              LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantE );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
-    [[nodiscard]] double s2X( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantX );
+    [[nodiscard]] double s2X( CovarianceMatrixTool::detail::ParameterMap const& params,
+                              LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantX );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
 
-    [[nodiscard]] double s2Y( const LHCb::Detector::Calo::CellID id ) const {
-      const auto& param = m_parameters.get().at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantY );
+    [[nodiscard]] double s2Y( CovarianceMatrixTool::detail::ParameterMap const& params,
+                              LHCb::Detector::Calo::CellID const                id ) const {
+      const auto& param = params.at( LHCb::Calo::CovarianceMatrixTool::detail::ConstantY );
       if ( id.area() >= param.size() ) return 0.;
       return param[id.area()] * param[id.area()];
     }
diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
index dddf38b81bf..4cfa0a7eebe 100644
--- a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
+++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h
@@ -43,6 +43,8 @@ namespace LHCb::Calo {
 
   class SubClusterSelectorTool : public LHCb::DetDesc::ConditionAccessorHolder<GaudiTool> {
   public:
+    using Tags = std::array<std::vector<Interfaces::ISubClusterTag*>, 2>; // 0 -> Energy, 1 -> Position
+
     // Return the interface ID
     static const InterfaceID& interfaceID() { return IID_FutureSubClusterSelectorTool; }
 
@@ -51,11 +53,13 @@ namespace LHCb::Calo {
 
     StatusCode initialize() override;
 
+    Tags const& getTags() const { return m_tags.get(); }
+
     template <SIMDWrapper::InstructionSet simd, LHCb::Pr::ProxyBehaviour behaviour>
-    StatusCode tagEnergy( const DeCalorimeter& calo, LHCb::Detector::Calo::CellID id,
+    StatusCode tagEnergy( Tags const& tags, DeCalorimeter const& calo, LHCb::Detector::Calo::CellID id,
                           LHCb::Event::Calo::Clusters::Entries<simd, behaviour> entries ) const {
       // get the tagger
-      auto* tagger = ( id.area() < m_tags.get()[0].size() ) ? m_tags.get()[0][id.area()] : nullptr;
+      auto* tagger = ( id.area() < tags[0].size() ) ? tags[0][id.area()] : nullptr;
       if ( !tagger ) {
         ++m_no_tagger;
         return StatusCode::FAILURE;
@@ -64,10 +68,10 @@ namespace LHCb::Calo {
     }
 
     template <SIMDWrapper::InstructionSet simd, LHCb::Pr::ProxyBehaviour behaviour>
-    StatusCode tagPosition( const DeCalorimeter& calo, LHCb::Detector::Calo::CellID id,
+    StatusCode tagPosition( Tags const& tags, DeCalorimeter const& calo, LHCb::Detector::Calo::CellID id,
                             LHCb::Event::Calo::Clusters::Entries<simd, behaviour> entries ) const {
       // get the tagger
-      auto* tagger = ( id.area() < m_tags.get()[1].size() ) ? m_tags.get()[1][id.area()] : nullptr;
+      auto* tagger = ( id.area() < tags[1].size() ) ? tags[1][id.area()] : nullptr;
       if ( !tagger ) {
         ++m_no_tagger;
         return StatusCode::FAILURE;
@@ -76,16 +80,15 @@ namespace LHCb::Calo {
     }
 
     template <SIMDWrapper::InstructionSet simd, LHCb::Pr::ProxyBehaviour behaviour>
-    StatusCode tag( const DeCalorimeter& calo, LHCb::Detector::Calo::CellID id,
+    StatusCode tag( Tags const& tags, DeCalorimeter const& calo, LHCb::Detector::Calo::CellID id,
                     LHCb::Event::Calo::Clusters::Entries<simd, behaviour> entries ) const {
-      return tagEnergy( calo, id, entries ).andThen( [&] { return tagPosition( calo, id, entries ); } );
+      return tagEnergy( tags, calo, id, entries ).andThen( [&] { return tagPosition( tags, calo, id, entries ); } );
     }
 
   private:
     Gaudi::Property<std::vector<std::string>> m_taggerE{this, "EnergyTags", {}};
     Gaudi::Property<std::vector<std::string>> m_taggerP{this, "PositionTags", {}};
-    using Tags = std::array<std::vector<Interfaces::ISubClusterTag*>, 2>; // 0 -> Energy, 1 -> Position
-    ConditionAccessor<Tags> m_tags{this, name() + "-SubClusterSelectorToolTags"};
+    ConditionAccessor<Tags>                   m_tags{this, name() + "-SubClusterSelectorToolTags"};
 
     Tags getParams( Correction::Parameters const& );
 
diff --git a/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp b/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
index 6acd18c6f6c..1aef7619e59 100644
--- a/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
+++ b/Tr/TrackExtrapolators/src/TrackParametrizedExtrapolator.cpp
@@ -395,12 +395,18 @@ StatusCode TrackParametrizedExtrapolator::propagate( Gaudi::TrackVector& in, dou
                                                      Gaudi::TrackMatrix* m, IGeometryInfo const& geometry,
                                                      LHCb::Tr::PID /*pid*/,
                                                      const LHCb::Magnet::MagneticFieldGrid* ) const {
+  // FIXME getting back this derived condition at each call of propagate will be
+  // extremely slow. This should be cached by the caller and passed to propagate.
+  // Now this would mean a change of API in all propagate methods of ITrackExtrapolator
+  // so a major code change. And on the other side this TrackParametrizedExtrapolator
+  // is not used at all at the moment. So let's keep it like this for the moment
+  auto const& params = m_parameters.get();
   // new approach: we take the interplane-extrapolator that has the
   // largest overlap in z. for now we only use it if it is fully
   // contained.
-  StatusCode sc        = StatusCode::SUCCESS;
-  int        direction = z1 < z2 ? +1 : -1;
-  auto&      container = direction == +1 ? m_parameters.get().forwardpars : m_parameters.get().backwardpars;
+  StatusCode                       sc        = StatusCode::SUCCESS;
+  int                              direction = z1 < z2 ? +1 : -1;
+  auto&                            container = direction == +1 ? params.forwardpars : params.backwardpars;
   const InterPlaneParametrization* thepar( 0 );
   for ( auto& par : container ) {
     // check that it is contained
-- 
GitLab