From c6d19c7796cc24d42a44e85cfa930d53364d20db Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Fri, 6 Dec 2024 16:35:25 +0100
Subject: [PATCH 01/14] Changes for making MuonStandaloneRec to work with muon
 hits and clusters, clean MuonStandaloneTrack

---
 .../include/MuonInterfaces/MuonCluster.h      |   9 +
 Muon/MuonTools/CMakeLists.txt                 |   1 +
 .../src/MuonHitContainerToCommonMuonHits.cpp  |  51 ++++++
 Tr/TrackTools/src/StandaloneMuonRec.cpp       | 171 ++++++++++--------
 Tr/TrackTools/src/StandaloneMuonTrack.h       | 145 ++++++++-------
 5 files changed, 238 insertions(+), 139 deletions(-)
 create mode 100644 Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp

diff --git a/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h b/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
index 21df944cbab..b7c7a7ad1e3 100644
--- a/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
+++ b/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
@@ -97,8 +97,11 @@ public:
   int              npads() const { return m_pads.size(); }
   int              clsizeX() const { return m_xsize; } /// cluster size in X
   int              clsizeY() const { return m_ysize; } /// cluster size in Y
+  double           dx() const { return m_dx; }         /// error on X position
   double           dX() const { return m_dx; }         /// error on X position
+  double           dy() const { return m_dy; }         /// error on Y position
   double           dY() const { return m_dy; }         /// error on Y position
+  double           dz() const { return m_dz; }         /// error on Z position
   double           dZ() const { return m_dz; }         /// error on Z position
   double           minX() const { return m_hit_minx; }
   double           maxX() const { return m_hit_maxx; }
@@ -106,9 +109,13 @@ public:
   double           maxY() const { return m_hit_maxy; }
   double           minZ() const { return m_hit_minz; }
   double           maxZ() const { return m_hit_maxz; }
+  double           x() const { return m_position.X(); }
   double           X() const { return m_position.X(); }
+  double           y() const { return m_position.Y(); }
   double           Y() const { return m_position.Y(); }
+  double           z() const { return m_position.Z(); }
   double           Z() const { return m_position.Z(); }
+
   Gaudi::XYZVector pos() const { return m_position; }
   MuonCluster&     SetXYZ( double x, double y, double z ) {
     m_position = { x, y, z };
@@ -151,3 +158,5 @@ using MuonClusters = std::vector<MuonCluster, LHCb::Allocators::EventLocal<MuonC
 typedef std::vector<const MuonCluster*>        ConstMuonClusters;
 typedef const Gaudi::Range_<MuonClusters>      MuonClusterRange;
 typedef const Gaudi::Range_<ConstMuonClusters> ConstMuonClusterRange;
+
+
diff --git a/Muon/MuonTools/CMakeLists.txt b/Muon/MuonTools/CMakeLists.txt
index 4b32be5ba62..856eec278b1 100644
--- a/Muon/MuonTools/CMakeLists.txt
+++ b/Muon/MuonTools/CMakeLists.txt
@@ -21,6 +21,7 @@ gaudi_add_module(MuonTools
         src/MuonPIDV2ToMuonTracks.cpp
         src/MergeMuonPIDs.cpp
         src/MergeMuonPIDsV1.cpp
+	src/MuonHitContainerToCommonMuonHits.cpp
     LINK
         Gaudi::GaudiAlgLib
         Gaudi::GaudiKernel
diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
new file mode 100644
index 00000000000..cf17159f7c2
--- /dev/null
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -0,0 +1,51 @@
+/*****************************************************************************\
+* (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.                                       *
+\*****************************************************************************/
+
+// Gaudi
+#include "LHCbAlgs/Transformer.h"
+
+// LHCb
+#include "MuonDAQ/CommonMuonHit.h"
+#include "MuonDAQ/MuonHitContainer.h"
+#include "Event/PrHits.h"
+
+namespace LHCb {
+
+  /**
+   * Converter from MuonPIDs to MuonTracks so that alignment can work
+   *
+   * This has been developed as a work around after the replacement of MuonIDAlgLite by
+   * MuonIDHlt2Alg, as the former one was creating a list of MuonTracks while the later
+   * does not.
+   */
+
+  using CommonMuonHits = std::vector<CommonMuonHit, LHCb::Allocators::EventLocal<CommonMuonHit>>;
+
+  class MuonHitContainerToCommonMuonHits : public Algorithm::Transformer<CommonMuonHits( const MuonHitContainer& )> {
+
+  public:
+    MuonHitContainerToCommonMuonHits( const std::string& name, ISvcLocator* pSvcLocator )
+        : Transformer( name, pSvcLocator, KeyValue{"Input", ""}, KeyValue{"Output", ""} ) {}
+
+    CommonMuonHits operator()( const MuonHitContainer& hitContainer ) const override {
+      CommonMuonHits out;
+      out.reserve( hitContainer.hits( 0 ).size()*4 );
+      for ( int s = 0 ; s < 4 ; ++s) {
+	auto hits = hitContainer.hits( s );
+	for( auto hit : hits ) out.push_back( hit );
+      }
+      return out;
+    }
+  };
+
+  DECLARE_COMPONENT_WITH_ID( MuonHitContainerToCommonMuonHits, "MuonHitContainerToCommonMuonHits" )
+
+} // namespace LHCb
diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 7d40d979d5e..9ccf44fd9b8 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -29,6 +29,7 @@
 #include "MuonDet/DeMuonDetector.h"
 #include "MuonDet/MuonNamespace.h"
 #include "vdt/vdtMath.h"
+#include "MuonInterfaces/MuonCluster.h"
 
 #include "StandaloneMuonTrack.h"
 
@@ -82,63 +83,70 @@ namespace {
   };
 } // namespace
 
-class StandaloneMuonRec : public LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonHitContainer&, const Cache& ),
+template<class MuonPosition>
+class StandaloneMuonRec : public LHCb::Algorithm::Transformer<LHCb::Tracks( const std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>&, const Cache& ),
                                                               LHCb::Algorithm::Traits::usesConditions<Cache>> {
 
 public:
-  using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonHitContainer&, const Cache& ),
+
+  typedef std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>> MuonPositionContainer;
+  typedef std::array<std::vector<MuonPosition>,4> PositionsInStations;
+  
+  using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonPositionContainer&, const Cache& ),
                                                     LHCb::Algorithm::Traits::usesConditions<Cache>>;
   using base_class_t::addConditionDerivation;
 
   /// Standard constructor
   StandaloneMuonRec( const std::string& name, ISvcLocator* pSvcLocator )
       : base_class_t( name, pSvcLocator,
-                      { KeyValue{ "MuonHitsLocation", MuonHitContainerLocation::Default },
-                        KeyValue{ "ConditionsCache", "StandaloneMuonAlg-" + name + "-ConditionsCache" } },
-                      KeyValue{ "OutputMuonTracks", "Rec/Track/Muon" } ) {}
+                      {typename base_class_t::KeyValue{"MuonHitsLocation", MuonHitContainerLocation::Default},
+                       typename base_class_t::KeyValue{"ConditionsCache", "StandaloneMuonAlg-" + name + "-ConditionsCache"}},
+                      typename base_class_t::KeyValue{"OutputMuonTracks", "Rec/Track/Muon"} ) {}
 
   StatusCode initialize() override {
     return base_class_t::initialize().andThen( [&] {
-      this->addConditionDerivation( { DeMuonLocation::Default, LHCb::Det::Magnet::det_path },
-                                    this->inputLocation<Cache>(),
-                                    [&]( const DeMuonDetector& det, const DeMagnet& magnet ) {
-                                      Cache                 cache{ det };
-                                      const Gaudi::XYZPoint begin( 0., 0., 0. );
-                                      const Gaudi::XYZPoint end( 0., 0., cache.stationZ[M2] );
-                                      m_bIntegrator->calculateBdlAndCenter( magnet.fieldGrid(), begin, end, 0.0001, 0.,
-                                                                            cache.zCenter, cache.bdl );
-                                      cache.fieldPolarity = magnet.isDown() ? -1 : 1;
-                                      debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
-                                              << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
-                                              << " with polarity " << cache.fieldPolarity << endmsg;
-                                      return cache;
-                                    } );
+      this->template addConditionDerivation( {DeMuonLocation::Default, LHCb::Det::Magnet::det_path},
+					     this->template inputLocation<Cache>(),
+					     [&]( const DeMuonDetector& det, const DeMagnet& magnet ) {
+					       Cache                 cache{det};
+					       const Gaudi::XYZPoint begin( 0., 0., 0. );
+					       const Gaudi::XYZPoint end( 0., 0., cache.stationZ[M2] );
+					       m_bIntegrator->calculateBdlAndCenter( magnet.fieldGrid(), begin, end, 0.0001, 0.,
+										     cache.zCenter, cache.bdl );
+					       cache.fieldPolarity = magnet.isDown() ? -1 : 1;
+					       this->template debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
+						       << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
+						       << " with polarity " << cache.fieldPolarity << endmsg;
+					       return cache;
+					     } );
     } );
   }
 
-  LHCb::Tracks operator()( const MuonHitContainer& hitContainer, const Cache& cache ) const override;
+  
+  LHCb::Tracks operator()( const MuonPositionContainer& hitContainer, const Cache& cache ) const override;
 
   ToolHandle<IBIntegrator> m_bIntegrator{ this, "BIntegrator", "BIntegrator" };
 
 private:
   enum { M2 = 0, M3, M4, M5 };
-  Gaudi::Property<bool>               m_cloneKiller{ this, "CloneKiller", true };
-  Gaudi::Property<bool>               m_chi2Cut{ this, "Chi2Cut", false };
-  Gaudi::Property<float>              m_maxchi2Cut{ this, "MaxChi2Cut", 1.0 };
-  Gaudi::Property<bool>               m_strongCloneKiller{ this, "StrongCloneKiller", false };
-  Gaudi::Property<bool>               m_secondLoop{ this, "SecondLoop", false };
-  Gaudi::Property<std::vector<float>> m_ParabolicCorrection{ this, "ParabolicCorrection", { 1.04, 0.14 } };
-  Gaudi::Property<std::vector<float>> m_resParams{ this, "m_resParams", { 0.015, 0.29 } };
-  Gaudi::Property<float>              m_Constant{ this, "ConstantCorrection", 0., "In MeV" };
-
-  std::vector<StandaloneMuonTrack> muonSearch( const MuonHitContainer& hitContainer, const Cache& cache ) const;
+  Gaudi::Property<bool>               m_cloneKiller{this, "CloneKiller", true};
+  Gaudi::Property<bool>               m_chi2Cut{this, "Chi2Cut", false};
+  Gaudi::Property<float>              m_maxchi2Cut{this, "MaxChi2Cut", 1.0};
+  Gaudi::Property<bool>               m_strongCloneKiller{this, "StrongCloneKiller", false};
+  Gaudi::Property<bool>               m_secondLoop{this, "SecondLoop", false};
+  Gaudi::Property<std::vector<float>> m_ParabolicCorrection{this, "ParabolicCorrection", {1.04, 0.14}};
+  Gaudi::Property<std::vector<float>> m_resParams{this, "m_resParams", {0.015, 0.29}};
+  Gaudi::Property<float>              m_Constant{this, "ConstantCorrection", 0., "In MeV"};
+  Gaudi::Property<float>              m_yAt0Error{this, "yAt0Error", 20.0, "Error on y constraint to point to 0/0/0"};
+
+  std::vector<StandaloneMuonTrack<MuonPosition>> muonSearch( const PositionsInStations& hitContainer, const Cache& cache ) const;
   bool findCoincidence( const float x, const float y, const unsigned int station, const unsigned int regionBefore,
-                        const CommonMuonHitRange& hits, CommonMuonHit& hitcand ) const;
-  void findmuonTrack( const MuonHitContainer& hitContainer, const Cache& cache,
-                      std::array<CommonMuonHit, 4>& bestCandidates, const int seed,
-                      std::vector<StandaloneMuonTrack>& muonTracks ) const;
-  void recMomentum( StandaloneMuonTrack& muonTrack, const Cache& cache, LHCb::Track& track ) const;
-  void detectClone( std::vector<StandaloneMuonTrack>& muonTracks, const Cache& cache ) const;
+                        const std::vector<MuonPosition>& hits, MuonPosition& hitcand ) const;
+  void findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
+                      std::array<MuonPosition, 4>& bestCandidates, const int seed,
+                      std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const;
+  void recMomentum( StandaloneMuonTrack<MuonPosition>& muonTrack, const Cache& cache, LHCb::Track& track ) const;
+  void detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks, const Cache& cache ) const;
 
   // counters
   mutable Gaudi::Accumulators::Counter<>                    m_countEvents{ this, "nEvents" };
@@ -148,26 +156,34 @@ private:
   mutable Gaudi::Accumulators::MsgCounter<MSG::INFO> m_error_zeroBint{ this, "B integral is 0!!" };
 };
 
-DECLARE_COMPONENT( StandaloneMuonRec )
+DECLARE_COMPONENT_WITH_ID( StandaloneMuonRec<CommonMuonHit>, "StandaloneMuonRec" )
+DECLARE_COMPONENT_WITH_ID( StandaloneMuonRec<MuonCluster>, "StandaloneMuonRecWithClusters" )
 
 //=============================================================================
 // Main execution
 //=============================================================================
-LHCb::Tracks StandaloneMuonRec::operator()( const MuonHitContainer& hitContainer, const Cache& cache ) const {
+template<typename MuonPosition>
+LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionContainer& hitContainer, const Cache& cache ) const {
+
+  if ( this-> template msgLevel( MSG::DEBUG ) ) this-> template debug() << "==> Execute" << endmsg;
 
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
+  PositionsInStations posInStations;
+  for( auto hit : hitContainer ){
+    posInStations[hit.station()].push_back( hit );
+  }
 
   LHCb::Tracks outputTracks;
   outputTracks.reserve( 1024 );
 
   ++m_countEvents;
 
-  auto muonTracks = muonSearch( hitContainer, cache );
+  auto muonTracks = muonSearch( posInStations, cache );
   if ( m_cloneKiller ) { detectClone( muonTracks, cache ); }
 
   for ( auto& muTrack : muonTracks ) {
     if ( muTrack.isClone() ) continue;
 
+    muTrack.setYAt0Err( m_yAt0Error );
     auto sc = muTrack.linearFit();
     if ( !sc ) {
       ++m_failed_linearfit;
@@ -181,15 +197,15 @@ LHCb::Tracks StandaloneMuonRec::operator()( const MuonHitContainer& hitContainer
   }
   m_countMuCandidates += outputTracks.size();
 
-  if ( msgLevel( MSG::DEBUG ) ) debug() << " stored candidates " << outputTracks.size() << endmsg;
+  if ( this -> template msgLevel( MSG::DEBUG ) ) this-> template debug() << " stored candidates " << outputTracks.size() << endmsg;
 
   return outputTracks;
 }
-
-bool StandaloneMuonRec::findCoincidence( const float x, const float y, const unsigned int station,
-                                         const unsigned int regionBefore, const CommonMuonHitRange& hits,
-                                         CommonMuonHit& hitcand ) const {
-
+template<typename MuonPosition>
+bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const float y, const unsigned int station,
+						       const unsigned int regionBefore, const std::vector<MuonPosition>& hits,
+						       MuonPosition& hitcand ) const {
+  
   const auto tol       = m_tolForRegion[regionBefore];
   float      deltaYmin = 9999.;
   float      deltaXmin = 9999.;
@@ -209,9 +225,10 @@ bool StandaloneMuonRec::findCoincidence( const float x, const float y, const uns
   }
   return findCand;
 }
-void StandaloneMuonRec::findmuonTrack( const MuonHitContainer& hitContainer, const Cache& cache,
-                                       std::array<CommonMuonHit, 4>& bestCandidates, const int seed,
-                                       std::vector<StandaloneMuonTrack>& muonTracks ) const {
+template<typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
+						     std::array<MuonPosition, 4>& bestCandidates, const int seed,
+						     std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const {
   float        xseed      = bestCandidates[seed].x();
   float        yseed      = bestCandidates[seed].y();
   unsigned int hit_region = bestCandidates[seed].region();
@@ -220,7 +237,7 @@ void StandaloneMuonRec::findmuonTrack( const MuonHitContainer& hitContainer, con
 
   bool findAll = false;
   for ( int ista = seed - 1; ista > -1; ista-- ) {
-    auto findCandidate = findCoincidence( x, y, ista, hit_region, hitContainer.hits( ista ), bestCandidates[ista] );
+    auto findCandidate = findCoincidence( x, y, ista, hit_region, hitContainer.at(ista), bestCandidates[ ista ] );
     if ( !findCandidate && ( !m_secondLoop || ista < M4 ) ) break;
     if ( findCandidate && ista == M2 ) {
       findAll = true;
@@ -243,34 +260,33 @@ void StandaloneMuonRec::findmuonTrack( const MuonHitContainer& hitContainer, con
   }
   if ( findAll ) {
     // create the muon track
-    StandaloneMuonTrack muon;
-    muon.setPoint( 0, bestCandidates[M2] );
-    muon.setPoint( 1, bestCandidates[M3] );
+    StandaloneMuonTrack<MuonPosition> muon;
+    muon.addPoint( bestCandidates[M2] );
+    muon.addPoint( bestCandidates[M3] );
     if ( m_secondLoop && bestCandidates[M4].station() == bestCandidates[M5].station() ) {
-      muon.setPoint( 2, bestCandidates[M4] );
-      muon.setnHits( 3 );
+      muon.addPoint( bestCandidates[M4] );
     } else {
-      muon.setPoint( 2, bestCandidates[M4] );
-      muon.setPoint( 3, bestCandidates[M5] );
-      muon.setnHits( 4 );
+      muon.addPoint( bestCandidates[M4] );
+      muon.addPoint( bestCandidates[M5] );
     }
     muonTracks.push_back( muon );
   }
 }
-std::vector<StandaloneMuonTrack> StandaloneMuonRec::muonSearch( const MuonHitContainer& hitContainer,
-                                                                const Cache&            cache ) const {
-  std::vector<StandaloneMuonTrack> muonTracks;
+template<typename MuonPosition>
+std::vector<StandaloneMuonTrack<MuonPosition>> StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitContainer,
+												     const Cache&            cache ) const {
+  std::vector<StandaloneMuonTrack<MuonPosition>> muonTracks;
   muonTracks.reserve( 48 );
 
-  const auto&                  hitsM5 = hitContainer.hits( M5 );
-  std::array<CommonMuonHit, 4> bestCandidates;
+  const auto&                  hitsM5 = hitContainer.at(M5);
+  std::array<MuonPosition, 4> bestCandidates;
   for ( auto& hit : hitsM5 ) {
     bestCandidates[3] = hit;
     findmuonTrack( hitContainer, cache, bestCandidates, M5, muonTracks );
   }
   ///---second loop from M4
   if ( m_secondLoop ) {
-    const auto& hitsM4 = hitContainer.hits( M4 );
+    const auto& hitsM4 = hitContainer[M4];
     for ( auto& hit : hitsM4 ) {
       // To remove these hits of M4 used in the first round of search
       auto used = std::find_if( muonTracks.begin(), muonTracks.end(),
@@ -285,7 +301,8 @@ std::vector<StandaloneMuonTrack> StandaloneMuonRec::muonSearch( const MuonHitCon
 }
 
 // estimate the momentum of muonTrack
-void StandaloneMuonRec::recMomentum( StandaloneMuonTrack& track, const Cache& cache, LHCb::Track& lbtrack ) const {
+template<typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosition>& track, const Cache& cache, LHCb::Track& lbtrack ) const {
 
   const float bdlX          = cache.bdl.x();
   const float fieldPolarity = cache.fieldPolarity;
@@ -353,25 +370,37 @@ void StandaloneMuonRec::recMomentum( StandaloneMuonTrack& track, const Cache& ca
   state.setLocation( LHCb::State::Location::Muon );
   endstate.setLocation( LHCb::State::Location::LastMeasurement );
 
-  debug() << "Muon state = " << state << endmsg;
+  this-> template debug() << "Muon state = " << state << endmsg;
 
   lbtrack.clearStates();
   lbtrack.addToStates( state );
   lbtrack.addToStates( endstate );
   lbtrack.setChi2PerDoF( track.chi2x() + track.chi2y() );
-  lbtrack.setNDoF( track.nHits() - 2 );
+  const int DoFForPointAtZero = m_yAt0Error < std::numeric_limits<float>::max();
+  lbtrack.setNDoF( track.nHits() - 2 + DoFForPointAtZero ); // add one degree of freedom for the point at 0/0/0
 
   for ( int i = 0; i < track.nHits(); i++ ) {
-    const auto Tile = track.point( i ).tile();
-    lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( Tile ) );
-    debug() << " Muon Hit " << i << " tile " << Tile << " tiles in station " << track.point( i ).station() << endmsg;
+    if constexpr(std::is_same_v<MuonPosition,CommonMuonHit>){
+      const auto tile = track.point( i ).tile();
+      lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
+      this-> template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station() << endmsg;
+    }else if constexpr( std::is_same_v<MuonPosition,MuonCluster>){
+      const auto tiles = track.point(i).getPadTiles();
+      for( const auto tile : tiles){
+	lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
+	this-> template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station() << endmsg;
+      }
+    }else{
+      this-> template error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
+    }
   }
 
   lbtrack.setPatRecStatus( LHCb::Track::PatRecStatus::PatRecIDs );
   lbtrack.setType( LHCb::Track::Types::Muon );
 }
 
-void StandaloneMuonRec::detectClone( std::vector<StandaloneMuonTrack>& muonTracks, const Cache& cache ) const {
+template<typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks, const Cache& cache ) const {
 
   for ( auto itMuonTrackFirst = muonTracks.begin(); itMuonTrackFirst < muonTracks.end(); itMuonTrackFirst++ ) {
     for ( auto itMuonTrackSecond = itMuonTrackFirst + 1; itMuonTrackSecond < muonTracks.end(); itMuonTrackSecond++ ) {
diff --git a/Tr/TrackTools/src/StandaloneMuonTrack.h b/Tr/TrackTools/src/StandaloneMuonTrack.h
index 77df068d551..e938075e8a9 100644
--- a/Tr/TrackTools/src/StandaloneMuonTrack.h
+++ b/Tr/TrackTools/src/StandaloneMuonTrack.h
@@ -17,6 +17,7 @@
 #include "GaudiKernel/Vector3DTypes.h"
 
 #include <string>
+#include <boost/container/small_vector.hpp>
 
 /** @class StandaloneMuonTrack StandaloneMuonTrack.h
  *
@@ -29,18 +30,35 @@
  *  @date   2011-03-03
  */
 namespace {
-  void LinearFitXZ( bool XZ, std::array<CommonMuonHit, 4>& m_points, int nHits, float& slope, float& trunc,
-                    float& chi2ndof, float& err_slope, float& err_trunc, float& cov ) {
+
+  enum class FitMode { XZ, YZ };
+  
+  struct FitResult{
+    float slope = -1e6;
+    float trunc = -1e6;
+    float chi2ndof = -1e6;
+    float err_slope = -1e6;
+    float err_trunc = -1e6;
+    float cov = -1e6;
+  };
+
+
+  
+  template<typename MuonPositionClass, FitMode fitMode>
+  FitResult linearFitImpl( boost::container::small_vector<MuonPositionClass, 4>& points, float yAt0Err = std::numeric_limits<float>::max()){
     float sz2, sz, s0, sxz, sx, sx2;
     sz2 = sz = s0 = sxz = sx = sx2 = 0;
-    for ( int i = 0; i < nHits; i++ ) {
-      const auto hit  = m_points[i];
-      const auto z    = hit.z();
-      auto       x    = hit.x();
-      auto       xerr = 2. * hit.dx();
-      if ( !XZ ) {
-        x    = hit.y();
-        xerr = 2 * hit.dy();
+
+    FitResult result;
+        
+    for ( const auto& point : points ) {
+      const auto z    = point.z();
+      auto       x    = point.x();
+      auto       xerr = 2. * point.dx();
+      if ( fitMode == FitMode::YZ ) {
+        x    = point.y();
+        xerr = 2 * point.dy();
+	
       }
       sz2 += z * z / xerr / xerr;
       sz += z / xerr / xerr;
@@ -49,91 +67,82 @@ namespace {
       sx += x / xerr / xerr;
       sx2 += x * x / xerr / xerr;
     }
-    float xdet = sz2 * s0 - sz * sz;
+
+    if( yAt0Err < std::numeric_limits<float>::max() ) s0 += 1.0 / ( yAt0Err*yAt0Err); // this applies a constraint to 0/0/0
+    
+    const float xdet = sz2 * s0 - sz * sz;
     if ( !LHCb::essentiallyZero( xdet ) ) {
-      slope = ( sxz * s0 - sx * sz ) / xdet;
-      trunc = ( sx * sz2 - sxz * sz ) / xdet;
+      result.slope = ( sxz * s0 - sx * sz ) / xdet; 
+      result.trunc = ( sx * sz2 - sxz * sz ) / xdet;
 
-      err_trunc = sqrt( sz2 / xdet );
-      err_slope = sqrt( s0 / xdet );
-      cov       = -sz / xdet;
+      result.err_trunc = sqrt( sz2 / xdet );
+      result.err_slope = sqrt( s0 / xdet );
+      result.cov       = -sz / xdet;
 
-      chi2ndof = ( sx2 + slope * slope * sz2 + trunc * trunc * s0 - 2. * slope * sxz - 2. * trunc * sx +
-                   2 * slope * trunc * sz ) /
-                 ( nHits - 2 );
+      result.chi2ndof = ( sx2 + result.slope * result.slope * sz2 + result.trunc * result.trunc * s0 - 2. * result.slope * sxz - 2. * result.trunc * sx +
+			  2 * result.slope * result.trunc * sz ) /
+	( points.size() - 2 + (yAt0Err < std::numeric_limits<float>::max()) ); // add one degree of freedom if we add the "point" at 0/0/0
     }
+
+    return result;
+    
   }
 } // namespace
 
+template<typename MuonPositionClass>
 class StandaloneMuonTrack final {
 public:
   /// Standard constructor
-  StandaloneMuonTrack() { m_clone = 0; };
+  StandaloneMuonTrack() { m_clone = false; m_points.reserve(4); };
 
   virtual ~StandaloneMuonTrack(){}; ///< Destructor
-  void setPoint( unsigned int station, CommonMuonHit point ) { m_points[station] = point; };
+  void setPoint( unsigned int station, MuonPositionClass point ) { m_points[station] = point; };
+  void addPoint( MuonPositionClass point ) { m_points.push_back(point); };
 
-  CommonMuonHit point( unsigned int station ) const { return m_points[station]; };
+  MuonPositionClass point( unsigned int station ) const { return m_points[station]; };
 
-  void setClone() { m_clone = 1; };
-  bool isClone() const { return m_clone > 0; }
-
-  double slopeX( int stationFirst, int stationSecond, double zFirst, double zSecond ) const {
-    return ( m_points[stationFirst].x() - m_points[stationSecond].x() ) / ( zFirst - zSecond );
-  };
-  double slopeY( int stationFirst, int stationSecond, double zFirst, double zSecond ) const {
-    return ( m_points[stationFirst].y() - m_points[stationSecond].y() ) / ( zFirst - zSecond );
-  };
+  void setClone() { m_clone = true; };
+  bool isClone() const { return m_clone; }
 
+  // -- used to constrain the straight line fit in y to 0/0/0
+  void setYAt0Err(const float yAt0Err){ m_yAt0Err = yAt0Err; }
+  
   // Fit with a min chi^2 in the 2 projections xz and yz
   bool linearFit() {
-    double dof = nHits() - 2.;
+    const double dof = nHits() - 2.;
     if ( dof < 0 ) return false;
-    LinearFitXZ( true, m_points, nHits(), m_sx, m_bx, m_chi2x, m_errsx, m_errbx, m_covbsx );
-    LinearFitXZ( false, m_points, nHits(), m_sy, m_by, m_chi2y, m_errsy, m_errby, m_covbsy );
-    if ( m_chi2x > -1.f && m_chi2y > -1.f )
-      return true;
-    else
-      return false;
+    m_resultXZ = linearFitImpl<MuonPositionClass, FitMode::XZ>( m_points );
+    m_resultYZ = linearFitImpl<MuonPositionClass, FitMode::YZ>( m_points, m_yAt0Err );
+    return m_resultXZ.chi2ndof > -1.f && m_resultYZ.chi2ndof > -1.f;
   };
 
-  inline double chi2x() const { return m_chi2x; } /// chi2/dof XZ
-  inline double chi2y() const { return m_chi2y; } /// chi2/dof YZ
+  inline double chi2x() const { return m_resultXZ.chi2ndof; } /// chi2/dof XZ
+  inline double chi2y() const { return m_resultYZ.chi2ndof; } /// chi2/dof YZ
   // slope XZ
-  inline double sx() const { return m_sx; }
+  inline double sx() const { return m_resultXZ.slope; }
   // intercept XZ
-  inline double bx() const { return m_bx; }
+  inline double bx() const { return m_resultYZ.trunc; }
   // slope YZ
-  inline double sy() const { return m_sy; }
+  inline double sy() const { return m_resultXZ.slope; }
   // intercept YZ
-  inline double by() const { return m_by; }
+  inline double by() const { return m_resultYZ.trunc; }
 
   // errors on the above parameters
-  inline double errsx() const { return m_errsx; }
-  inline double errbx() const { return m_errbx; }
-  inline double covbsx() const { return m_covbsx; }
-  inline double errsy() const { return m_errsy; }
-  inline double errby() const { return m_errby; }
-  inline double covbsy() const { return m_covbsy; }
+  inline double errsx() const { return m_resultXZ.err_slope; }
+  inline double errbx() const { return m_resultXZ.err_trunc; }
+  inline double covbsx() const { return m_resultXZ.cov; }
+  inline double errsy() const { return m_resultYZ.err_slope; }
+  inline double errby() const { return m_resultYZ.err_trunc; }
+  inline double covbsy() const { return m_resultYZ.cov; }
 
-  inline void setnHits( int n ) { m_nHits = n; }
-  inline int  nHits() const { return m_nHits; }
+  inline int  nHits() const { return m_points.size(); }
 
 private:
-  std::array<CommonMuonHit, 4> m_points;
-  unsigned int                 m_clone;
-  unsigned int                 m_nHits;
-
-  float m_chi2x  = -1.f;
-  float m_chi2y  = -1.f;
-  float m_sx     = -1.f;
-  float m_bx     = -1.f;
-  float m_sy     = -1.f;
-  float m_by     = -1.f;
-  float m_errsx  = -1.f;
-  float m_errbx  = -1.f;
-  float m_covbsx = -1.f;
-  float m_errsy  = -1.f;
-  float m_errby  = -1.f;
-  float m_covbsy = -1.f;
+  boost::container::small_vector<MuonPositionClass,4> m_points;
+  bool                          m_clone;
+  float           m_yAt0Err = std::numeric_limits<float>::max();
+  
+  FitResult m_resultXZ;
+  FitResult m_resultYZ;
+
 };
-- 
GitLab


From 341f19672b755eb8e6372d12032878a4dbd62d11 Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Sat, 7 Dec 2024 22:19:00 +0100
Subject: [PATCH 02/14] fix wrong return values for XZ and YZ fit

---
 Tr/TrackTools/src/StandaloneMuonTrack.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonTrack.h b/Tr/TrackTools/src/StandaloneMuonTrack.h
index e938075e8a9..8cc1b07028b 100644
--- a/Tr/TrackTools/src/StandaloneMuonTrack.h
+++ b/Tr/TrackTools/src/StandaloneMuonTrack.h
@@ -121,9 +121,9 @@ public:
   // slope XZ
   inline double sx() const { return m_resultXZ.slope; }
   // intercept XZ
-  inline double bx() const { return m_resultYZ.trunc; }
+  inline double bx() const { return m_resultXZ.trunc; }
   // slope YZ
-  inline double sy() const { return m_resultXZ.slope; }
+  inline double sy() const { return m_resultYZ.slope; }
   // intercept YZ
   inline double by() const { return m_resultYZ.trunc; }
 
-- 
GitLab


From 3f649d9aaf84da0e4e870f4133332aa647aa7d48 Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Sun, 8 Dec 2024 20:35:25 +0100
Subject: [PATCH 03/14] replace harded 4 with constant for number of muon
 stations, reduce number of tracks to reserve

---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 22 +++++++++++-----------
 Tr/TrackTools/src/StandaloneMuonTrack.h |  5 +++--
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 9ccf44fd9b8..465d43ec7eb 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -68,11 +68,11 @@ namespace {
                                                60., 120., 240., 480. } }; // M4
 
   // -- Set tolerances for hit search in region
-  constexpr std::array<float, 4> m_tolForRegion{ { 2.0, 4.0, 8.0, 10.0 } };
+  constexpr std::array<float, LHCb::Detector::Muon::nRegions> m_tolForRegion{{2.0, 4.0, 8.0, 10.0}};
 
   class Cache {
   public:
-    std::array<float, 4> stationZ{};
+    std::array<float, LHCb::Detector::Muon::nStations> stationZ{};
     Gaudi::XYZVector     bdl;
     double               zCenter{};
     int                  fieldPolarity{};
@@ -90,7 +90,7 @@ class StandaloneMuonRec : public LHCb::Algorithm::Transformer<LHCb::Tracks( cons
 public:
 
   typedef std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>> MuonPositionContainer;
-  typedef std::array<std::vector<MuonPosition>,4> PositionsInStations;
+  typedef std::array<std::vector<MuonPosition>,LHCb::Detector::Muon::nStations> PositionsInStations;
   
   using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonPositionContainer&, const Cache& ),
                                                     LHCb::Algorithm::Traits::usesConditions<Cache>>;
@@ -137,13 +137,13 @@ private:
   Gaudi::Property<std::vector<float>> m_ParabolicCorrection{this, "ParabolicCorrection", {1.04, 0.14}};
   Gaudi::Property<std::vector<float>> m_resParams{this, "m_resParams", {0.015, 0.29}};
   Gaudi::Property<float>              m_Constant{this, "ConstantCorrection", 0., "In MeV"};
-  Gaudi::Property<float>              m_yAt0Error{this, "yAt0Error", 20.0, "Error on y constraint to point to 0/0/0"};
+  Gaudi::Property<float>              m_yAt0Error{this, "yAt0Error", std::numeric_limits<float>::max(), "Error on y constraint to point to 0/0/0"};
 
   std::vector<StandaloneMuonTrack<MuonPosition>> muonSearch( const PositionsInStations& hitContainer, const Cache& cache ) const;
   bool findCoincidence( const float x, const float y, const unsigned int station, const unsigned int regionBefore,
                         const std::vector<MuonPosition>& hits, MuonPosition& hitcand ) const;
   void findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
-                      std::array<MuonPosition, 4>& bestCandidates, const int seed,
+                      std::array<MuonPosition, LHCb::Detector::Muon::nStations>& bestCandidates, const int seed,
                       std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const;
   void recMomentum( StandaloneMuonTrack<MuonPosition>& muonTrack, const Cache& cache, LHCb::Track& track ) const;
   void detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks, const Cache& cache ) const;
@@ -173,7 +173,7 @@ LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionCont
   }
 
   LHCb::Tracks outputTracks;
-  outputTracks.reserve( 1024 );
+  outputTracks.reserve( 10 );
 
   ++m_countEvents;
 
@@ -214,7 +214,7 @@ bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const floa
     float deltaX = fabs( x - hit.x() );
     float deltaY = fabs( y - hit.y() );
     //-- Check if the hit is within the FOI (copy from MuonCombRec); in any case a xFOI >1000 is not considered
-    if ( deltaX < m_Xmax[station * 4 + regionBefore] && deltaY < m_Ymax[station * 4 + regionBefore] &&
+    if ( deltaX < m_Xmax[station * LHCb::Detector::Muon::nStations + regionBefore] && deltaY < m_Ymax[station * LHCb::Detector::Muon::nStations + regionBefore] &&
          ( deltaY < deltaYmin - tol ||
            ( deltaY < deltaYmin + tol && ( deltaX < deltaXmin - tol || fabs( deltaXmin - deltaX ) < 0.1 ) ) ) ) {
       deltaXmin = deltaX;
@@ -227,7 +227,7 @@ bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const floa
 }
 template<typename MuonPosition>
 void StandaloneMuonRec<MuonPosition>::findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
-						     std::array<MuonPosition, 4>& bestCandidates, const int seed,
+						     std::array<MuonPosition, LHCb::Detector::Muon::nStations>& bestCandidates, const int seed,
 						     std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const {
   float        xseed      = bestCandidates[seed].x();
   float        yseed      = bestCandidates[seed].y();
@@ -276,10 +276,10 @@ template<typename MuonPosition>
 std::vector<StandaloneMuonTrack<MuonPosition>> StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitContainer,
 												     const Cache&            cache ) const {
   std::vector<StandaloneMuonTrack<MuonPosition>> muonTracks;
-  muonTracks.reserve( 48 );
+  muonTracks.reserve( 12 );
 
   const auto&                  hitsM5 = hitContainer.at(M5);
-  std::array<MuonPosition, 4> bestCandidates;
+  std::array<MuonPosition, LHCb::Detector::Muon::nStations> bestCandidates;
   for ( auto& hit : hitsM5 ) {
     bestCandidates[3] = hit;
     findmuonTrack( hitContainer, cache, bestCandidates, M5, muonTracks );
@@ -371,7 +371,7 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   endstate.setLocation( LHCb::State::Location::LastMeasurement );
 
   this-> template debug() << "Muon state = " << state << endmsg;
-
+  
   lbtrack.clearStates();
   lbtrack.addToStates( state );
   lbtrack.addToStates( endstate );
diff --git a/Tr/TrackTools/src/StandaloneMuonTrack.h b/Tr/TrackTools/src/StandaloneMuonTrack.h
index 8cc1b07028b..0f86109c532 100644
--- a/Tr/TrackTools/src/StandaloneMuonTrack.h
+++ b/Tr/TrackTools/src/StandaloneMuonTrack.h
@@ -13,6 +13,7 @@
 #include "Core/FloatComparison.h"
 #include "MuonDAQ/CommonMuonHit.h"
 
+#include "Detector/Muon/MuonConstants.h"
 #include "GaudiKernel/Point3DTypes.h"
 #include "GaudiKernel/Vector3DTypes.h"
 
@@ -45,7 +46,7 @@ namespace {
 
   
   template<typename MuonPositionClass, FitMode fitMode>
-  FitResult linearFitImpl( boost::container::small_vector<MuonPositionClass, 4>& points, float yAt0Err = std::numeric_limits<float>::max()){
+  FitResult linearFitImpl( boost::container::small_vector<MuonPositionClass, LHCb::Detector::Muon::nStations>& points, float yAt0Err = std::numeric_limits<float>::max()){
     float sz2, sz, s0, sxz, sx, sx2;
     sz2 = sz = s0 = sxz = sx = sx2 = 0;
 
@@ -138,7 +139,7 @@ public:
   inline int  nHits() const { return m_points.size(); }
 
 private:
-  boost::container::small_vector<MuonPositionClass,4> m_points;
+  boost::container::small_vector<MuonPositionClass,LHCb::Detector::Muon::nStations> m_points;
   bool                          m_clone;
   float           m_yAt0Err = std::numeric_limits<float>::max();
   
-- 
GitLab


From 21f009039041adcdd51a5da53a02fdf50827969f Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Sun, 8 Dec 2024 20:37:25 +0100
Subject: [PATCH 04/14] fix (old) bug where position for last state was wrongly
 calculated

---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 465d43ec7eb..4b4fdad71e8 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -313,7 +313,7 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   LHCb::State     state( LHCb::StateVector( trackPos, Gaudi::XYZVector( track.sx(), track.sy(), 1.0 ), 1. / 10000. ) );
 
   const auto      Zend = cache.stationZ[M5];
-  Gaudi::XYZPoint endtrackPos( track.bx() + track.sx() * Zfirst, track.by() + track.sy() * Zend, Zend );
+  Gaudi::XYZPoint endtrackPos( track.bx() + track.sx() * Zend, track.by() + track.sy() * Zend, Zend );
   LHCb::State     endstate(
       LHCb::StateVector( endtrackPos, Gaudi::XYZVector( track.sx(), track.sy(), 1.0 ), 1. / 10000. ) );
 
-- 
GitLab


From 89545b8b21b5f191db3aaa24f5b262cb9e77f33a Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Wed, 12 Feb 2025 17:05:57 +0100
Subject: [PATCH 05/14] replace more hardcoded 4s with meaningful expression

---
 Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
index cf17159f7c2..b7240bb3bd7 100644
--- a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -37,8 +37,8 @@ namespace LHCb {
 
     CommonMuonHits operator()( const MuonHitContainer& hitContainer ) const override {
       CommonMuonHits out;
-      out.reserve( hitContainer.hits( 0 ).size()*4 );
-      for ( int s = 0 ; s < 4 ; ++s) {
+      out.reserve( hitContainer.hits( 0 ).size()*LHCb::Detector::Muon::nStations );
+      for ( int s = 0 ; s < LHCb::Detector::Muon::nStations ; ++s) {
 	auto hits = hitContainer.hits( s );
 	for( auto hit : hits ) out.push_back( hit );
       }
-- 
GitLab


From ffc07d41a748f5eec2c108cb3e3e9b004577cb04 Mon Sep 17 00:00:00 2001
From: Gitlab CI <noreply@cern.ch>
Date: Wed, 12 Feb 2025 16:06:41 +0000
Subject: [PATCH 06/14] pre-commit fixes

patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50886445
---
 .../include/MuonInterfaces/MuonCluster.h      |  44 +++--
 .../src/MuonHitContainerToCommonMuonHits.cpp  |  12 +-
 Tr/TrackTools/src/StandaloneMuonRec.cpp       | 164 ++++++++++--------
 Tr/TrackTools/src/StandaloneMuonTrack.h       |  64 +++----
 4 files changed, 147 insertions(+), 137 deletions(-)

diff --git a/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h b/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
index b7c7a7ad1e3..d25b8171331 100644
--- a/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
+++ b/Muon/MuonInterfaces/include/MuonInterfaces/MuonCluster.h
@@ -94,27 +94,27 @@ public:
   /// return the MuonTileIDs of the logical pads used for this cluster
   std::vector<LHCb::Detector::Muon::TileID> getPadTiles() const;
   /// number of logical pads in this hit
-  int              npads() const { return m_pads.size(); }
-  int              clsizeX() const { return m_xsize; } /// cluster size in X
-  int              clsizeY() const { return m_ysize; } /// cluster size in Y
-  double           dx() const { return m_dx; }         /// error on X position
-  double           dX() const { return m_dx; }         /// error on X position
-  double           dy() const { return m_dy; }         /// error on Y position
-  double           dY() const { return m_dy; }         /// error on Y position
-  double           dz() const { return m_dz; }         /// error on Z position
-  double           dZ() const { return m_dz; }         /// error on Z position
-  double           minX() const { return m_hit_minx; }
-  double           maxX() const { return m_hit_maxx; }
-  double           minY() const { return m_hit_miny; }
-  double           maxY() const { return m_hit_maxy; }
-  double           minZ() const { return m_hit_minz; }
-  double           maxZ() const { return m_hit_maxz; }
-  double           x() const { return m_position.X(); }
-  double           X() const { return m_position.X(); }
-  double           y() const { return m_position.Y(); }
-  double           Y() const { return m_position.Y(); }
-  double           z() const { return m_position.Z(); }
-  double           Z() const { return m_position.Z(); }
+  int    npads() const { return m_pads.size(); }
+  int    clsizeX() const { return m_xsize; } /// cluster size in X
+  int    clsizeY() const { return m_ysize; } /// cluster size in Y
+  double dx() const { return m_dx; }         /// error on X position
+  double dX() const { return m_dx; }         /// error on X position
+  double dy() const { return m_dy; }         /// error on Y position
+  double dY() const { return m_dy; }         /// error on Y position
+  double dz() const { return m_dz; }         /// error on Z position
+  double dZ() const { return m_dz; }         /// error on Z position
+  double minX() const { return m_hit_minx; }
+  double maxX() const { return m_hit_maxx; }
+  double minY() const { return m_hit_miny; }
+  double maxY() const { return m_hit_maxy; }
+  double minZ() const { return m_hit_minz; }
+  double maxZ() const { return m_hit_maxz; }
+  double x() const { return m_position.X(); }
+  double X() const { return m_position.X(); }
+  double y() const { return m_position.Y(); }
+  double Y() const { return m_position.Y(); }
+  double z() const { return m_position.Z(); }
+  double Z() const { return m_position.Z(); }
 
   Gaudi::XYZVector pos() const { return m_position; }
   MuonCluster&     SetXYZ( double x, double y, double z ) {
@@ -158,5 +158,3 @@ using MuonClusters = std::vector<MuonCluster, LHCb::Allocators::EventLocal<MuonC
 typedef std::vector<const MuonCluster*>        ConstMuonClusters;
 typedef const Gaudi::Range_<MuonClusters>      MuonClusterRange;
 typedef const Gaudi::Range_<ConstMuonClusters> ConstMuonClusterRange;
-
-
diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
index b7240bb3bd7..86ce8741ab3 100644
--- a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -13,9 +13,9 @@
 #include "LHCbAlgs/Transformer.h"
 
 // LHCb
+#include "Event/PrHits.h"
 #include "MuonDAQ/CommonMuonHit.h"
 #include "MuonDAQ/MuonHitContainer.h"
-#include "Event/PrHits.h"
 
 namespace LHCb {
 
@@ -33,14 +33,14 @@ namespace LHCb {
 
   public:
     MuonHitContainerToCommonMuonHits( const std::string& name, ISvcLocator* pSvcLocator )
-        : Transformer( name, pSvcLocator, KeyValue{"Input", ""}, KeyValue{"Output", ""} ) {}
+        : Transformer( name, pSvcLocator, KeyValue{ "Input", "" }, KeyValue{ "Output", "" } ) {}
 
     CommonMuonHits operator()( const MuonHitContainer& hitContainer ) const override {
       CommonMuonHits out;
-      out.reserve( hitContainer.hits( 0 ).size()*LHCb::Detector::Muon::nStations );
-      for ( int s = 0 ; s < LHCb::Detector::Muon::nStations ; ++s) {
-	auto hits = hitContainer.hits( s );
-	for( auto hit : hits ) out.push_back( hit );
+      out.reserve( hitContainer.hits( 0 ).size() * LHCb::Detector::Muon::nStations );
+      for ( int s = 0; s < LHCb::Detector::Muon::nStations; ++s ) {
+        auto hits = hitContainer.hits( s );
+        for ( auto hit : hits ) out.push_back( hit );
       }
       return out;
     }
diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 4b4fdad71e8..392cab03d60 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -28,8 +28,8 @@
 #include "Magnet/DeMagnet.h"
 #include "MuonDet/DeMuonDetector.h"
 #include "MuonDet/MuonNamespace.h"
-#include "vdt/vdtMath.h"
 #include "MuonInterfaces/MuonCluster.h"
+#include "vdt/vdtMath.h"
 
 #include "StandaloneMuonTrack.h"
 
@@ -68,14 +68,14 @@ namespace {
                                                60., 120., 240., 480. } }; // M4
 
   // -- Set tolerances for hit search in region
-  constexpr std::array<float, LHCb::Detector::Muon::nRegions> m_tolForRegion{{2.0, 4.0, 8.0, 10.0}};
+  constexpr std::array<float, LHCb::Detector::Muon::nRegions> m_tolForRegion{ { 2.0, 4.0, 8.0, 10.0 } };
 
   class Cache {
   public:
     std::array<float, LHCb::Detector::Muon::nStations> stationZ{};
-    Gaudi::XYZVector     bdl;
-    double               zCenter{};
-    int                  fieldPolarity{};
+    Gaudi::XYZVector                                   bdl;
+    double                                             zCenter{};
+    int                                                fieldPolarity{};
     Cache(){};
     Cache( DeMuonDetector const& det ) {
       for ( int s = 0; s != det.stations(); ++s ) { stationZ[s] = det.getStationZ( s ); }
@@ -83,63 +83,66 @@ namespace {
   };
 } // namespace
 
-template<class MuonPosition>
-class StandaloneMuonRec : public LHCb::Algorithm::Transformer<LHCb::Tracks( const std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>&, const Cache& ),
-                                                              LHCb::Algorithm::Traits::usesConditions<Cache>> {
+template <class MuonPosition>
+class StandaloneMuonRec
+    : public LHCb::Algorithm::Transformer<
+          LHCb::Tracks( const std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>&, const Cache& ),
+          LHCb::Algorithm::Traits::usesConditions<Cache>> {
 
 public:
+  typedef std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>  MuonPositionContainer;
+  typedef std::array<std::vector<MuonPosition>, LHCb::Detector::Muon::nStations> PositionsInStations;
 
-  typedef std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>> MuonPositionContainer;
-  typedef std::array<std::vector<MuonPosition>,LHCb::Detector::Muon::nStations> PositionsInStations;
-  
   using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonPositionContainer&, const Cache& ),
                                                     LHCb::Algorithm::Traits::usesConditions<Cache>>;
   using base_class_t::addConditionDerivation;
 
   /// Standard constructor
   StandaloneMuonRec( const std::string& name, ISvcLocator* pSvcLocator )
-      : base_class_t( name, pSvcLocator,
-                      {typename base_class_t::KeyValue{"MuonHitsLocation", MuonHitContainerLocation::Default},
-                       typename base_class_t::KeyValue{"ConditionsCache", "StandaloneMuonAlg-" + name + "-ConditionsCache"}},
-                      typename base_class_t::KeyValue{"OutputMuonTracks", "Rec/Track/Muon"} ) {}
+      : base_class_t(
+            name, pSvcLocator,
+            { typename base_class_t::KeyValue{ "MuonHitsLocation", MuonHitContainerLocation::Default },
+              typename base_class_t::KeyValue{ "ConditionsCache", "StandaloneMuonAlg-" + name + "-ConditionsCache" } },
+            typename base_class_t::KeyValue{ "OutputMuonTracks", "Rec/Track/Muon" } ) {}
 
   StatusCode initialize() override {
     return base_class_t::initialize().andThen( [&] {
-      this->template addConditionDerivation( {DeMuonLocation::Default, LHCb::Det::Magnet::det_path},
-					     this->template inputLocation<Cache>(),
-					     [&]( const DeMuonDetector& det, const DeMagnet& magnet ) {
-					       Cache                 cache{det};
-					       const Gaudi::XYZPoint begin( 0., 0., 0. );
-					       const Gaudi::XYZPoint end( 0., 0., cache.stationZ[M2] );
-					       m_bIntegrator->calculateBdlAndCenter( magnet.fieldGrid(), begin, end, 0.0001, 0.,
-										     cache.zCenter, cache.bdl );
-					       cache.fieldPolarity = magnet.isDown() ? -1 : 1;
-					       this->template debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
-						       << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
-						       << " with polarity " << cache.fieldPolarity << endmsg;
-					       return cache;
-					     } );
+      this->template addConditionDerivation(
+          { DeMuonLocation::Default, LHCb::Det::Magnet::det_path }, this->template inputLocation<Cache>(),
+          [&]( const DeMuonDetector& det, const DeMagnet& magnet ) {
+            Cache                 cache{ det };
+            const Gaudi::XYZPoint begin( 0., 0., 0. );
+            const Gaudi::XYZPoint end( 0., 0., cache.stationZ[M2] );
+            m_bIntegrator->calculateBdlAndCenter( magnet.fieldGrid(), begin, end, 0.0001, 0., cache.zCenter,
+                                                  cache.bdl );
+            cache.fieldPolarity = magnet.isDown() ? -1 : 1;
+            this->template debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
+                                   << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
+                                   << " with polarity " << cache.fieldPolarity << endmsg;
+            return cache;
+          } );
     } );
   }
 
-  
   LHCb::Tracks operator()( const MuonPositionContainer& hitContainer, const Cache& cache ) const override;
 
   ToolHandle<IBIntegrator> m_bIntegrator{ this, "BIntegrator", "BIntegrator" };
 
 private:
   enum { M2 = 0, M3, M4, M5 };
-  Gaudi::Property<bool>               m_cloneKiller{this, "CloneKiller", true};
-  Gaudi::Property<bool>               m_chi2Cut{this, "Chi2Cut", false};
-  Gaudi::Property<float>              m_maxchi2Cut{this, "MaxChi2Cut", 1.0};
-  Gaudi::Property<bool>               m_strongCloneKiller{this, "StrongCloneKiller", false};
-  Gaudi::Property<bool>               m_secondLoop{this, "SecondLoop", false};
-  Gaudi::Property<std::vector<float>> m_ParabolicCorrection{this, "ParabolicCorrection", {1.04, 0.14}};
-  Gaudi::Property<std::vector<float>> m_resParams{this, "m_resParams", {0.015, 0.29}};
-  Gaudi::Property<float>              m_Constant{this, "ConstantCorrection", 0., "In MeV"};
-  Gaudi::Property<float>              m_yAt0Error{this, "yAt0Error", std::numeric_limits<float>::max(), "Error on y constraint to point to 0/0/0"};
-
-  std::vector<StandaloneMuonTrack<MuonPosition>> muonSearch( const PositionsInStations& hitContainer, const Cache& cache ) const;
+  Gaudi::Property<bool>               m_cloneKiller{ this, "CloneKiller", true };
+  Gaudi::Property<bool>               m_chi2Cut{ this, "Chi2Cut", false };
+  Gaudi::Property<float>              m_maxchi2Cut{ this, "MaxChi2Cut", 1.0 };
+  Gaudi::Property<bool>               m_strongCloneKiller{ this, "StrongCloneKiller", false };
+  Gaudi::Property<bool>               m_secondLoop{ this, "SecondLoop", false };
+  Gaudi::Property<std::vector<float>> m_ParabolicCorrection{ this, "ParabolicCorrection", { 1.04, 0.14 } };
+  Gaudi::Property<std::vector<float>> m_resParams{ this, "m_resParams", { 0.015, 0.29 } };
+  Gaudi::Property<float>              m_Constant{ this, "ConstantCorrection", 0., "In MeV" };
+  Gaudi::Property<float>              m_yAt0Error{ this, "yAt0Error", std::numeric_limits<float>::max(),
+                                      "Error on y constraint to point to 0/0/0" };
+
+  std::vector<StandaloneMuonTrack<MuonPosition>> muonSearch( const PositionsInStations& hitContainer,
+                                                             const Cache&               cache ) const;
   bool findCoincidence( const float x, const float y, const unsigned int station, const unsigned int regionBefore,
                         const std::vector<MuonPosition>& hits, MuonPosition& hitcand ) const;
   void findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
@@ -162,15 +165,14 @@ DECLARE_COMPONENT_WITH_ID( StandaloneMuonRec<MuonCluster>, "StandaloneMuonRecWit
 //=============================================================================
 // Main execution
 //=============================================================================
-template<typename MuonPosition>
-LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionContainer& hitContainer, const Cache& cache ) const {
+template <typename MuonPosition>
+LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionContainer& hitContainer,
+                                                          const Cache&                 cache ) const {
 
-  if ( this-> template msgLevel( MSG::DEBUG ) ) this-> template debug() << "==> Execute" << endmsg;
+  if ( this->template msgLevel( MSG::DEBUG ) ) this->template debug() << "==> Execute" << endmsg;
 
   PositionsInStations posInStations;
-  for( auto hit : hitContainer ){
-    posInStations[hit.station()].push_back( hit );
-  }
+  for ( auto hit : hitContainer ) { posInStations[hit.station()].push_back( hit ); }
 
   LHCb::Tracks outputTracks;
   outputTracks.reserve( 10 );
@@ -197,15 +199,17 @@ LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionCont
   }
   m_countMuCandidates += outputTracks.size();
 
-  if ( this -> template msgLevel( MSG::DEBUG ) ) this-> template debug() << " stored candidates " << outputTracks.size() << endmsg;
+  if ( this->template msgLevel( MSG::DEBUG ) )
+    this->template debug() << " stored candidates " << outputTracks.size() << endmsg;
 
   return outputTracks;
 }
-template<typename MuonPosition>
+template <typename MuonPosition>
 bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const float y, const unsigned int station,
-						       const unsigned int regionBefore, const std::vector<MuonPosition>& hits,
-						       MuonPosition& hitcand ) const {
-  
+                                                       const unsigned int               regionBefore,
+                                                       const std::vector<MuonPosition>& hits,
+                                                       MuonPosition&                    hitcand ) const {
+
   const auto tol       = m_tolForRegion[regionBefore];
   float      deltaYmin = 9999.;
   float      deltaXmin = 9999.;
@@ -214,7 +218,8 @@ bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const floa
     float deltaX = fabs( x - hit.x() );
     float deltaY = fabs( y - hit.y() );
     //-- Check if the hit is within the FOI (copy from MuonCombRec); in any case a xFOI >1000 is not considered
-    if ( deltaX < m_Xmax[station * LHCb::Detector::Muon::nStations + regionBefore] && deltaY < m_Ymax[station * LHCb::Detector::Muon::nStations + regionBefore] &&
+    if ( deltaX < m_Xmax[station * LHCb::Detector::Muon::nStations + regionBefore] &&
+         deltaY < m_Ymax[station * LHCb::Detector::Muon::nStations + regionBefore] &&
          ( deltaY < deltaYmin - tol ||
            ( deltaY < deltaYmin + tol && ( deltaX < deltaXmin - tol || fabs( deltaXmin - deltaX ) < 0.1 ) ) ) ) {
       deltaXmin = deltaX;
@@ -225,10 +230,11 @@ bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const floa
   }
   return findCand;
 }
-template<typename MuonPosition>
-void StandaloneMuonRec<MuonPosition>::findmuonTrack( const PositionsInStations& hitContainer, const Cache& cache,
-						     std::array<MuonPosition, LHCb::Detector::Muon::nStations>& bestCandidates, const int seed,
-						     std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const {
+template <typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::findmuonTrack(
+    const PositionsInStations& hitContainer, const Cache& cache,
+    std::array<MuonPosition, LHCb::Detector::Muon::nStations>& bestCandidates, const int seed,
+    std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks ) const {
   float        xseed      = bestCandidates[seed].x();
   float        yseed      = bestCandidates[seed].y();
   unsigned int hit_region = bestCandidates[seed].region();
@@ -237,7 +243,7 @@ void StandaloneMuonRec<MuonPosition>::findmuonTrack( const PositionsInStations&
 
   bool findAll = false;
   for ( int ista = seed - 1; ista > -1; ista-- ) {
-    auto findCandidate = findCoincidence( x, y, ista, hit_region, hitContainer.at(ista), bestCandidates[ ista ] );
+    auto findCandidate = findCoincidence( x, y, ista, hit_region, hitContainer.at( ista ), bestCandidates[ista] );
     if ( !findCandidate && ( !m_secondLoop || ista < M4 ) ) break;
     if ( findCandidate && ista == M2 ) {
       findAll = true;
@@ -272,13 +278,13 @@ void StandaloneMuonRec<MuonPosition>::findmuonTrack( const PositionsInStations&
     muonTracks.push_back( muon );
   }
 }
-template<typename MuonPosition>
-std::vector<StandaloneMuonTrack<MuonPosition>> StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitContainer,
-												     const Cache&            cache ) const {
+template <typename MuonPosition>
+std::vector<StandaloneMuonTrack<MuonPosition>>
+StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitContainer, const Cache& cache ) const {
   std::vector<StandaloneMuonTrack<MuonPosition>> muonTracks;
   muonTracks.reserve( 12 );
 
-  const auto&                  hitsM5 = hitContainer.at(M5);
+  const auto&                                               hitsM5 = hitContainer.at( M5 );
   std::array<MuonPosition, LHCb::Detector::Muon::nStations> bestCandidates;
   for ( auto& hit : hitsM5 ) {
     bestCandidates[3] = hit;
@@ -301,8 +307,9 @@ std::vector<StandaloneMuonTrack<MuonPosition>> StandaloneMuonRec<MuonPosition>::
 }
 
 // estimate the momentum of muonTrack
-template<typename MuonPosition>
-void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosition>& track, const Cache& cache, LHCb::Track& lbtrack ) const {
+template <typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosition>& track, const Cache& cache,
+                                                   LHCb::Track& lbtrack ) const {
 
   const float bdlX          = cache.bdl.x();
   const float fieldPolarity = cache.fieldPolarity;
@@ -370,8 +377,8 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   state.setLocation( LHCb::State::Location::Muon );
   endstate.setLocation( LHCb::State::Location::LastMeasurement );
 
-  this-> template debug() << "Muon state = " << state << endmsg;
-  
+  this->template debug() << "Muon state = " << state << endmsg;
+
   lbtrack.clearStates();
   lbtrack.addToStates( state );
   lbtrack.addToStates( endstate );
@@ -380,18 +387,20 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   lbtrack.setNDoF( track.nHits() - 2 + DoFForPointAtZero ); // add one degree of freedom for the point at 0/0/0
 
   for ( int i = 0; i < track.nHits(); i++ ) {
-    if constexpr(std::is_same_v<MuonPosition,CommonMuonHit>){
+    if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
       lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-      this-> template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station() << endmsg;
-    }else if constexpr( std::is_same_v<MuonPosition,MuonCluster>){
-      const auto tiles = track.point(i).getPadTiles();
-      for( const auto tile : tiles){
-	lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-	this-> template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station() << endmsg;
+      this->template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
+                             << track.point( i ).station() << endmsg;
+    } else if constexpr ( std::is_same_v<MuonPosition, MuonCluster> ) {
+      const auto tiles = track.point( i ).getPadTiles();
+      for ( const auto tile : tiles ) {
+        lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
+        this->template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
+                               << track.point( i ).station() << endmsg;
       }
-    }else{
-      this-> template error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
+    } else {
+      this->template error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
     }
   }
 
@@ -399,8 +408,9 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   lbtrack.setType( LHCb::Track::Types::Muon );
 }
 
-template<typename MuonPosition>
-void StandaloneMuonRec<MuonPosition>::detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks, const Cache& cache ) const {
+template <typename MuonPosition>
+void StandaloneMuonRec<MuonPosition>::detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks,
+                                                   const Cache&                                    cache ) const {
 
   for ( auto itMuonTrackFirst = muonTracks.begin(); itMuonTrackFirst < muonTracks.end(); itMuonTrackFirst++ ) {
     for ( auto itMuonTrackSecond = itMuonTrackFirst + 1; itMuonTrackSecond < muonTracks.end(); itMuonTrackSecond++ ) {
diff --git a/Tr/TrackTools/src/StandaloneMuonTrack.h b/Tr/TrackTools/src/StandaloneMuonTrack.h
index 0f86109c532..1e6c92c531a 100644
--- a/Tr/TrackTools/src/StandaloneMuonTrack.h
+++ b/Tr/TrackTools/src/StandaloneMuonTrack.h
@@ -17,8 +17,8 @@
 #include "GaudiKernel/Point3DTypes.h"
 #include "GaudiKernel/Vector3DTypes.h"
 
-#include <string>
 #include <boost/container/small_vector.hpp>
+#include <string>
 
 /** @class StandaloneMuonTrack StandaloneMuonTrack.h
  *
@@ -33,25 +33,24 @@
 namespace {
 
   enum class FitMode { XZ, YZ };
-  
-  struct FitResult{
-    float slope = -1e6;
-    float trunc = -1e6;
-    float chi2ndof = -1e6;
+
+  struct FitResult {
+    float slope     = -1e6;
+    float trunc     = -1e6;
+    float chi2ndof  = -1e6;
     float err_slope = -1e6;
     float err_trunc = -1e6;
-    float cov = -1e6;
+    float cov       = -1e6;
   };
 
-
-  
-  template<typename MuonPositionClass, FitMode fitMode>
-  FitResult linearFitImpl( boost::container::small_vector<MuonPositionClass, LHCb::Detector::Muon::nStations>& points, float yAt0Err = std::numeric_limits<float>::max()){
+  template <typename MuonPositionClass, FitMode fitMode>
+  FitResult linearFitImpl( boost::container::small_vector<MuonPositionClass, LHCb::Detector::Muon::nStations>& points,
+                           float yAt0Err = std::numeric_limits<float>::max() ) {
     float sz2, sz, s0, sxz, sx, sx2;
     sz2 = sz = s0 = sxz = sx = sx2 = 0;
 
     FitResult result;
-        
+
     for ( const auto& point : points ) {
       const auto z    = point.z();
       auto       x    = point.x();
@@ -59,7 +58,6 @@ namespace {
       if ( fitMode == FitMode::YZ ) {
         x    = point.y();
         xerr = 2 * point.dy();
-	
       }
       sz2 += z * z / xerr / xerr;
       sz += z / xerr / xerr;
@@ -69,36 +67,41 @@ namespace {
       sx2 += x * x / xerr / xerr;
     }
 
-    if( yAt0Err < std::numeric_limits<float>::max() ) s0 += 1.0 / ( yAt0Err*yAt0Err); // this applies a constraint to 0/0/0
-    
+    if ( yAt0Err < std::numeric_limits<float>::max() )
+      s0 += 1.0 / ( yAt0Err * yAt0Err ); // this applies a constraint to 0/0/0
+
     const float xdet = sz2 * s0 - sz * sz;
     if ( !LHCb::essentiallyZero( xdet ) ) {
-      result.slope = ( sxz * s0 - sx * sz ) / xdet; 
+      result.slope = ( sxz * s0 - sx * sz ) / xdet;
       result.trunc = ( sx * sz2 - sxz * sz ) / xdet;
 
       result.err_trunc = sqrt( sz2 / xdet );
       result.err_slope = sqrt( s0 / xdet );
       result.cov       = -sz / xdet;
 
-      result.chi2ndof = ( sx2 + result.slope * result.slope * sz2 + result.trunc * result.trunc * s0 - 2. * result.slope * sxz - 2. * result.trunc * sx +
-			  2 * result.slope * result.trunc * sz ) /
-	( points.size() - 2 + (yAt0Err < std::numeric_limits<float>::max()) ); // add one degree of freedom if we add the "point" at 0/0/0
+      result.chi2ndof =
+          ( sx2 + result.slope * result.slope * sz2 + result.trunc * result.trunc * s0 - 2. * result.slope * sxz -
+            2. * result.trunc * sx + 2 * result.slope * result.trunc * sz ) /
+          ( points.size() - 2 + ( yAt0Err < std::numeric_limits<float>::max() ) ); // add one degree of freedom if we
+                                                                                   // add the "point" at 0/0/0
     }
 
     return result;
-    
   }
 } // namespace
 
-template<typename MuonPositionClass>
+template <typename MuonPositionClass>
 class StandaloneMuonTrack final {
 public:
   /// Standard constructor
-  StandaloneMuonTrack() { m_clone = false; m_points.reserve(4); };
+  StandaloneMuonTrack() {
+    m_clone = false;
+    m_points.reserve( 4 );
+  };
 
   virtual ~StandaloneMuonTrack(){}; ///< Destructor
   void setPoint( unsigned int station, MuonPositionClass point ) { m_points[station] = point; };
-  void addPoint( MuonPositionClass point ) { m_points.push_back(point); };
+  void addPoint( MuonPositionClass point ) { m_points.push_back( point ); };
 
   MuonPositionClass point( unsigned int station ) const { return m_points[station]; };
 
@@ -106,8 +109,8 @@ public:
   bool isClone() const { return m_clone; }
 
   // -- used to constrain the straight line fit in y to 0/0/0
-  void setYAt0Err(const float yAt0Err){ m_yAt0Err = yAt0Err; }
-  
+  void setYAt0Err( const float yAt0Err ) { m_yAt0Err = yAt0Err; }
+
   // Fit with a min chi^2 in the 2 projections xz and yz
   bool linearFit() {
     const double dof = nHits() - 2.;
@@ -136,14 +139,13 @@ public:
   inline double errby() const { return m_resultYZ.err_trunc; }
   inline double covbsy() const { return m_resultYZ.cov; }
 
-  inline int  nHits() const { return m_points.size(); }
+  inline int nHits() const { return m_points.size(); }
 
 private:
-  boost::container::small_vector<MuonPositionClass,LHCb::Detector::Muon::nStations> m_points;
-  bool                          m_clone;
-  float           m_yAt0Err = std::numeric_limits<float>::max();
-  
+  boost::container::small_vector<MuonPositionClass, LHCb::Detector::Muon::nStations> m_points;
+  bool                                                                               m_clone;
+  float m_yAt0Err = std::numeric_limits<float>::max();
+
   FitResult m_resultXZ;
   FitResult m_resultYZ;
-
 };
-- 
GitLab


From fceab0da857391da1bf40a15035c4a22d2d0558a Mon Sep 17 00:00:00 2001
From: Michel De Cian <michel.de.cian@cern.ch>
Date: Thu, 13 Feb 2025 08:49:35 +0000
Subject: [PATCH 07/14] use `insert` instead of `push_back`

---
 Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
index 86ce8741ab3..10cd83545ac 100644
--- a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -39,8 +39,8 @@ namespace LHCb {
       CommonMuonHits out;
       out.reserve( hitContainer.hits( 0 ).size() * LHCb::Detector::Muon::nStations );
       for ( int s = 0; s < LHCb::Detector::Muon::nStations; ++s ) {
-        auto hits = hitContainer.hits( s );
-        for ( auto hit : hits ) out.push_back( hit );
+        auto const& hits = hitContainer.hits( s );
+        out.insert( out.end(), hits.begin(), hits.end() );
       }
       return out;
     }
-- 
GitLab


From 3fca5ede405a8696cf9943c3c701317690d44e7b Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Thu, 13 Feb 2025 10:30:00 +0100
Subject: [PATCH 08/14] use using instead of typedef, fix signed unsigned
 comparison

---
 Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp | 2 +-
 Tr/TrackTools/src/StandaloneMuonRec.cpp                 | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
index 10cd83545ac..c66128b731b 100644
--- a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -38,7 +38,7 @@ namespace LHCb {
     CommonMuonHits operator()( const MuonHitContainer& hitContainer ) const override {
       CommonMuonHits out;
       out.reserve( hitContainer.hits( 0 ).size() * LHCb::Detector::Muon::nStations );
-      for ( int s = 0; s < LHCb::Detector::Muon::nStations; ++s ) {
+      for ( std::size_t s = 0; s < LHCb::Detector::Muon::nStations; ++s ) {
         auto const& hits = hitContainer.hits( s );
         out.insert( out.end(), hits.begin(), hits.end() );
       }
diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 392cab03d60..71357b9b4ca 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -90,8 +90,8 @@ class StandaloneMuonRec
           LHCb::Algorithm::Traits::usesConditions<Cache>> {
 
 public:
-  typedef std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>  MuonPositionContainer;
-  typedef std::array<std::vector<MuonPosition>, LHCb::Detector::Muon::nStations> PositionsInStations;
+  using MuonPositionContainer = std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>;
+  using PositionsInStations = std::array<std::vector<MuonPosition>, LHCb::Detector::Muon::nStations>;
 
   using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonPositionContainer&, const Cache& ),
                                                     LHCb::Algorithm::Traits::usesConditions<Cache>>;
-- 
GitLab


From 1590fb55d9a38d8ea6c15cada218db83ac9cab1c Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Thu, 13 Feb 2025 11:15:07 +0100
Subject: [PATCH 09/14] include header with muon constant explicitly

---
 Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp | 1 +
 Tr/TrackTools/src/StandaloneMuonRec.cpp                 | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
index c66128b731b..46eb1d5197e 100644
--- a/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
+++ b/Muon/MuonTools/src/MuonHitContainerToCommonMuonHits.cpp
@@ -16,6 +16,7 @@
 #include "Event/PrHits.h"
 #include "MuonDAQ/CommonMuonHit.h"
 #include "MuonDAQ/MuonHitContainer.h"
+#include <Detector/Muon/MuonConstants.h>
 
 namespace LHCb {
 
diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index 71357b9b4ca..c382fe1ad1d 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -29,6 +29,7 @@
 #include "MuonDet/DeMuonDetector.h"
 #include "MuonDet/MuonNamespace.h"
 #include "MuonInterfaces/MuonCluster.h"
+#include <Detector/Muon/MuonConstants.h>
 #include "vdt/vdtMath.h"
 
 #include "StandaloneMuonTrack.h"
-- 
GitLab


From ba72429a7384cd027a034609fcbce7b87373bd97 Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Thu, 13 Feb 2025 15:43:04 +0100
Subject: [PATCH 10/14] remove template keyword which caused trouble with clang

---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index c382fe1ad1d..f67f71ab766 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -117,9 +117,9 @@ public:
             m_bIntegrator->calculateBdlAndCenter( magnet.fieldGrid(), begin, end, 0.0001, 0., cache.zCenter,
                                                   cache.bdl );
             cache.fieldPolarity = magnet.isDown() ? -1 : 1;
-            this->template debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
-                                   << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
-                                   << " with polarity " << cache.fieldPolarity << endmsg;
+            this->debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
+			  << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
+			  << " with polarity " << cache.fieldPolarity << endmsg;
             return cache;
           } );
     } );
@@ -170,7 +170,7 @@ template <typename MuonPosition>
 LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionContainer& hitContainer,
                                                           const Cache&                 cache ) const {
 
-  if ( this->template msgLevel( MSG::DEBUG ) ) this->template debug() << "==> Execute" << endmsg;
+  if ( this->msgLevel( MSG::DEBUG ) ) this->debug() << "==> Execute" << endmsg;
 
   PositionsInStations posInStations;
   for ( auto hit : hitContainer ) { posInStations[hit.station()].push_back( hit ); }
@@ -200,8 +200,8 @@ LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionCont
   }
   m_countMuCandidates += outputTracks.size();
 
-  if ( this->template msgLevel( MSG::DEBUG ) )
-    this->template debug() << " stored candidates " << outputTracks.size() << endmsg;
+  if ( this->msgLevel( MSG::DEBUG ) )
+    this->debug() << " stored candidates " << outputTracks.size() << endmsg;
 
   return outputTracks;
 }
@@ -378,7 +378,7 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   state.setLocation( LHCb::State::Location::Muon );
   endstate.setLocation( LHCb::State::Location::LastMeasurement );
 
-  this->template debug() << "Muon state = " << state << endmsg;
+  this->debug() << "Muon state = " << state << endmsg;
 
   lbtrack.clearStates();
   lbtrack.addToStates( state );
@@ -391,17 +391,17 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
     if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
       lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-      this->template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
+      this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
                              << track.point( i ).station() << endmsg;
     } else if constexpr ( std::is_same_v<MuonPosition, MuonCluster> ) {
       const auto tiles = track.point( i ).getPadTiles();
       for ( const auto tile : tiles ) {
         lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-        this->template debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
+        this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
                                << track.point( i ).station() << endmsg;
       }
     } else {
-      this->template error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
+      this->error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
     }
   }
 
-- 
GitLab


From b8404c5b8b9e7d2da9a4a6aa1602172356e7b83d Mon Sep 17 00:00:00 2001
From: Gitlab CI <noreply@cern.ch>
Date: Thu, 13 Feb 2025 14:59:50 +0000
Subject: [PATCH 11/14] pre-commit fixes

patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50967694
---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index f67f71ab766..ed3037045a3 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -29,8 +29,8 @@
 #include "MuonDet/DeMuonDetector.h"
 #include "MuonDet/MuonNamespace.h"
 #include "MuonInterfaces/MuonCluster.h"
-#include <Detector/Muon/MuonConstants.h>
 #include "vdt/vdtMath.h"
+#include <Detector/Muon/MuonConstants.h>
 
 #include "StandaloneMuonTrack.h"
 
@@ -92,7 +92,7 @@ class StandaloneMuonRec
 
 public:
   using MuonPositionContainer = std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>;
-  using PositionsInStations = std::array<std::vector<MuonPosition>, LHCb::Detector::Muon::nStations>;
+  using PositionsInStations   = std::array<std::vector<MuonPosition>, LHCb::Detector::Muon::nStations>;
 
   using base_class_t = LHCb::Algorithm::Transformer<LHCb::Tracks( const MuonPositionContainer&, const Cache& ),
                                                     LHCb::Algorithm::Traits::usesConditions<Cache>>;
@@ -118,8 +118,8 @@ public:
                                                   cache.bdl );
             cache.fieldPolarity = magnet.isDown() ? -1 : 1;
             this->debug() << "Integrated B field is " << cache.bdl.x() << " Tm"
-			  << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
-			  << " with polarity " << cache.fieldPolarity << endmsg;
+                          << "  centered at Z=" << cache.zCenter / Gaudi::Units::m << " m"
+                          << " with polarity " << cache.fieldPolarity << endmsg;
             return cache;
           } );
     } );
@@ -200,8 +200,7 @@ LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionCont
   }
   m_countMuCandidates += outputTracks.size();
 
-  if ( this->msgLevel( MSG::DEBUG ) )
-    this->debug() << " stored candidates " << outputTracks.size() << endmsg;
+  if ( this->msgLevel( MSG::DEBUG ) ) this->debug() << " stored candidates " << outputTracks.size() << endmsg;
 
   return outputTracks;
 }
@@ -391,14 +390,14 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
     if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
       lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-      this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
-                             << track.point( i ).station() << endmsg;
+      this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station()
+                    << endmsg;
     } else if constexpr ( std::is_same_v<MuonPosition, MuonCluster> ) {
       const auto tiles = track.point( i ).getPadTiles();
       for ( const auto tile : tiles ) {
         lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
-        this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station "
-                               << track.point( i ).station() << endmsg;
+        this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station()
+                      << endmsg;
       }
     } else {
       this->error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
-- 
GitLab


From 95ac896e67aaaecb2a9491ee00b44e73acc409a4 Mon Sep 17 00:00:00 2001
From: decianm <michel.de.cian@.cern.ch>
Date: Tue, 18 Feb 2025 12:33:01 +0100
Subject: [PATCH 12/14] Added a static assert to check the possible muon
 position classes at compile time

---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index ed3037045a3..b8a1a96d9af 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -386,21 +386,22 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   const int DoFForPointAtZero = m_yAt0Error < std::numeric_limits<float>::max();
   lbtrack.setNDoF( track.nHits() - 2 + DoFForPointAtZero ); // add one degree of freedom for the point at 0/0/0
 
+  static_assert(  std::is_same_v<MuonPosition, CommonMuonHit>  ||
+		  std::is_same_v<MuonPosition, MuonCluster> , "Muon position must either be a CommonMuonHit or a MuonCluster");
+  
   for ( int i = 0; i < track.nHits(); i++ ) {
     if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
       lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
       this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station()
                     << endmsg;
-    } else if constexpr ( std::is_same_v<MuonPosition, MuonCluster> ) {
+    } else {
       const auto tiles = track.point( i ).getPadTiles();
       for ( const auto tile : tiles ) {
         lbtrack.addToLhcbIDs( ( LHCb::LHCbID )( tile ) );
         this->debug() << " Muon Hit " << i << " tile " << tile << " tiles in station " << track.point( i ).station()
                       << endmsg;
       }
-    } else {
-      this->error() << "Incompatible muon position class. Will not add LHCbIDs to the track" << endmsg;
     }
   }
 
-- 
GitLab


From 7d0e1beca55afcf10bd2c7a8c960f73988916fb3 Mon Sep 17 00:00:00 2001
From: Gitlab CI <noreply@cern.ch>
Date: Tue, 18 Feb 2025 11:33:45 +0000
Subject: [PATCH 13/14] pre-commit fixes

patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/51218383
---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index b8a1a96d9af..e13c0f3ced9 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -386,9 +386,9 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   const int DoFForPointAtZero = m_yAt0Error < std::numeric_limits<float>::max();
   lbtrack.setNDoF( track.nHits() - 2 + DoFForPointAtZero ); // add one degree of freedom for the point at 0/0/0
 
-  static_assert(  std::is_same_v<MuonPosition, CommonMuonHit>  ||
-		  std::is_same_v<MuonPosition, MuonCluster> , "Muon position must either be a CommonMuonHit or a MuonCluster");
-  
+  static_assert( std::is_same_v<MuonPosition, CommonMuonHit> || std::is_same_v<MuonPosition, MuonCluster>,
+                 "Muon position must either be a CommonMuonHit or a MuonCluster" );
+
   for ( int i = 0; i < track.nHits(); i++ ) {
     if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
-- 
GitLab


From 55f5247969bac758e1e82f28d044e6fccfd51ecf Mon Sep 17 00:00:00 2001
From: Sebastien Ponce <sebastien.ponce@cern.ch>
Date: Tue, 18 Feb 2025 15:06:19 +0100
Subject: [PATCH 14/14] Use concepts to enforce MuonPosition being either
 CommonMuonhit or MuonCluster

---
 Tr/TrackTools/src/StandaloneMuonRec.cpp | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/Tr/TrackTools/src/StandaloneMuonRec.cpp b/Tr/TrackTools/src/StandaloneMuonRec.cpp
index e13c0f3ced9..5372c690203 100644
--- a/Tr/TrackTools/src/StandaloneMuonRec.cpp
+++ b/Tr/TrackTools/src/StandaloneMuonRec.cpp
@@ -84,7 +84,12 @@ namespace {
   };
 } // namespace
 
-template <class MuonPosition>
+/// MuonPositionConcept makes sure we are dealing either with CommonMuonHit or with MuonCluster
+template <typename MuonPosition>
+concept MuonPositionConcept =
+    requires { requires std::is_same_v<MuonPosition, CommonMuonHit> || std::is_same_v<MuonPosition, MuonCluster>; };
+
+template <MuonPositionConcept MuonPosition>
 class StandaloneMuonRec
     : public LHCb::Algorithm::Transformer<
           LHCb::Tracks( const std::vector<MuonPosition, LHCb::Allocators::EventLocal<MuonPosition>>&, const Cache& ),
@@ -166,7 +171,7 @@ DECLARE_COMPONENT_WITH_ID( StandaloneMuonRec<MuonCluster>, "StandaloneMuonRecWit
 //=============================================================================
 // Main execution
 //=============================================================================
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionContainer& hitContainer,
                                                           const Cache&                 cache ) const {
 
@@ -204,7 +209,7 @@ LHCb::Tracks StandaloneMuonRec<MuonPosition>::operator()( const MuonPositionCont
 
   return outputTracks;
 }
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const float y, const unsigned int station,
                                                        const unsigned int               regionBefore,
                                                        const std::vector<MuonPosition>& hits,
@@ -230,7 +235,7 @@ bool StandaloneMuonRec<MuonPosition>::findCoincidence( const float x, const floa
   }
   return findCand;
 }
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 void StandaloneMuonRec<MuonPosition>::findmuonTrack(
     const PositionsInStations& hitContainer, const Cache& cache,
     std::array<MuonPosition, LHCb::Detector::Muon::nStations>& bestCandidates, const int seed,
@@ -278,7 +283,7 @@ void StandaloneMuonRec<MuonPosition>::findmuonTrack(
     muonTracks.push_back( muon );
   }
 }
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 std::vector<StandaloneMuonTrack<MuonPosition>>
 StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitContainer, const Cache& cache ) const {
   std::vector<StandaloneMuonTrack<MuonPosition>> muonTracks;
@@ -307,7 +312,7 @@ StandaloneMuonRec<MuonPosition>::muonSearch( const PositionsInStations& hitConta
 }
 
 // estimate the momentum of muonTrack
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosition>& track, const Cache& cache,
                                                    LHCb::Track& lbtrack ) const {
 
@@ -386,9 +391,6 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   const int DoFForPointAtZero = m_yAt0Error < std::numeric_limits<float>::max();
   lbtrack.setNDoF( track.nHits() - 2 + DoFForPointAtZero ); // add one degree of freedom for the point at 0/0/0
 
-  static_assert( std::is_same_v<MuonPosition, CommonMuonHit> || std::is_same_v<MuonPosition, MuonCluster>,
-                 "Muon position must either be a CommonMuonHit or a MuonCluster" );
-
   for ( int i = 0; i < track.nHits(); i++ ) {
     if constexpr ( std::is_same_v<MuonPosition, CommonMuonHit> ) {
       const auto tile = track.point( i ).tile();
@@ -409,7 +411,7 @@ void StandaloneMuonRec<MuonPosition>::recMomentum( StandaloneMuonTrack<MuonPosit
   lbtrack.setType( LHCb::Track::Types::Muon );
 }
 
-template <typename MuonPosition>
+template <MuonPositionConcept MuonPosition>
 void StandaloneMuonRec<MuonPosition>::detectClone( std::vector<StandaloneMuonTrack<MuonPosition>>& muonTracks,
                                                    const Cache&                                    cache ) const {
 
-- 
GitLab