From bee44b88e16c339544b2294e85bae07928dfdc2a Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Sat, 27 Jan 2024 12:15:19 +0000
Subject: [PATCH 01/15] Cleaning commit history in development of
 BeamSpotMonitor.cpp

---
 Tr/TrackMonitors/CMakeLists.txt          |   1 +
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 297 +++++++++++++++++++++++
 2 files changed, 298 insertions(+)
 create mode 100644 Tr/TrackMonitors/src/BeamSpotMonitor.cpp

diff --git a/Tr/TrackMonitors/CMakeLists.txt b/Tr/TrackMonitors/CMakeLists.txt
index 2fb7950cae1..fd9bf5b5cda 100644
--- a/Tr/TrackMonitors/CMakeLists.txt
+++ b/Tr/TrackMonitors/CMakeLists.txt
@@ -37,6 +37,7 @@ gaudi_add_module(TrackMonitors
         src/UTTrackMonitor.cpp
         src/VPTrackMonitor.cpp
         src/VertexCompare.cpp
+        src/BeamSpotMonitor.cpp
     LINK
         AIDA::aida
         Gaudi::GaudiAlgLib
diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
new file mode 100644
index 00000000000..75086f0be73
--- /dev/null
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -0,0 +1,297 @@
+/*****************************************************************************\
+* (c) Copyright 2023 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 "Event/ODIN.h"
+#include "Event/PrimaryVertices.h"
+#include "Event/RecVertex.h"
+
+#include "GaudiAlg/GaudiHistoAlg.h"
+#include "LHCbAlgs/Consumer.h"
+#include <Gaudi/Accumulators/Histogram.h>
+
+#include <mutex>
+#include <sstream>
+
+namespace {
+  using PVView = LHCb::Event::PV::PrimaryVertexContainer;
+
+  template <typename X, typename XX>
+  auto calculate_spread_offdiag( X const& x, X const& y, XX const& xy ) {
+    return ( xy.sum() - xy.nEntries() * x.mean() * y.mean() ) / ( xy.nEntries() - 1 );
+  }
+} // namespace
+
+class BeamSpotMonitor : public LHCb::Algorithm::Consumer<void( LHCb::ODIN const&, PVView const& )> {
+
+public:
+  /** Standard constructor */
+  BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLocator );
+
+  /** Algorithm execute */
+  void operator()( LHCb::ODIN const&, PVView const& pvcontainer ) const override;
+
+private:
+  // Conditions for checking validity of PVs
+  bool check_pv( PVView::value_type const& ) const;
+
+  // Conditions for and implementation of copying accumulating counters to cache
+  bool check_cache_counters( void ) const;
+  void cache_counters( void ) const;
+
+  // Conditions for and implementation of publication of cached conditions
+  bool check_publish( void ) const;
+  void ymlWriter( void ) const;
+
+  // Conditions for value drifts
+  bool is_accum_delta_pos_over_thresh( void ) const {
+    return ( std::abs( m_pvXPosCtr.mean() - m_c_pvXPosCtr.mean() ) > m_maxDeltaX ) ||
+           ( std::abs( m_pvYPosCtr.mean() - m_c_pvYPosCtr.mean() ) > m_maxDeltaY ) ||
+           ( std::abs( m_pvZPosCtr.mean() - m_c_pvZPosCtr.mean() ) > m_maxDeltaZ );
+  }
+  bool is_accum_delta_spread_over_thresh( void ) const;
+
+  // Reset the accumulators
+  bool check_reset_accumulators( const unsigned ) const;
+  void reset_accumulators( const unsigned ) const;
+
+  // Lock for main event processing
+  mutable std::mutex m_mutex;
+
+  Gaudi::Property<long unsigned> m_minPVsForCalib{this, "MinPVsForCalib", 100ul,
+                                                  "Minumum number of accumulated PVs for a calibration"};
+  Gaudi::Property<int> m_minNTracks{this, "MinPVnTracks", 15, "Minumum number of tracks in a PVs for processing"};
+
+  // Histogram limits
+  Gaudi::Property<double> m_histMaxXPV{this, "HistMaxXPV", 2 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMaxYPV{this, "HistMaxYPV", 1 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMinZPV{this, "HistMinZPV", -20 * Gaudi::Units::cm};
+  Gaudi::Property<double> m_histMaxZPV{this, "HistMaxZPV", 20 * Gaudi::Units::cm};
+  Gaudi::Property<double> m_histMinZPV_wide{this, "HistMinZPV_Wide", -150 * Gaudi::Units::cm,
+                                            "Wide z window for PV plot"};
+  Gaudi::Property<double> m_histMaxZPV_wide{this, "HistMaxZPV_Wide", 150 * Gaudi::Units::cm,
+                                            "Wide z window for PV plot"};
+
+  // Thresholds triggering updated publication
+  Gaudi::Property<double> m_maxDeltaX{this, "DeltaXMax", 2 * Gaudi::Units::mm,
+                                      "Maximum allowed absolute difference in mean X from cached value"};
+  Gaudi::Property<double> m_maxDeltaY{this, "DeltaYMax", 2 * Gaudi::Units::mm,
+                                      "Maximum allowed absolute difference in mean Y from cached value"};
+  Gaudi::Property<double> m_maxDeltaZ{this, "DeltaZMax", 20 * Gaudi::Units::mm,
+                                      "Maximum allowed absolute difference in mean Z from cached value"};
+
+  Gaudi::Property<double> m_maxDeltaXX{this, "DeltaXXMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix X^2 from cached value"};
+  Gaudi::Property<double> m_maxDeltaXY{this, "DeltaXYMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix XY from cached value"};
+  Gaudi::Property<double> m_maxDeltaYY{this, "DeltaYYMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix Y^2 from cached value"};
+  Gaudi::Property<double> m_maxDeltaZX{this, "DeltaZXMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix ZX from cached value"};
+  Gaudi::Property<double> m_maxDeltaYZ{this, "DeltaYZMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix YZ from cached value"};
+  Gaudi::Property<double> m_maxDeltaZZ{this, "DeltaZZMax", 2 * Gaudi::Units::mm2,
+                                       "Maximum allowed absolute difference in spread-matrix Z^2 from cached value"};
+
+  // Accumulating statistics counters
+  mutable unsigned                                m_accRunNumber{0}; // Run number of last processed event
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_pvXPosCtr{this, "PV x position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_pvYPosCtr{this, "PV y position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_pvZPosCtr{this, "PV z position"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_pvXYProdCtr{this, "PV x * y for covariance"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_pvYZProdCtr{this, "PV y * z for covariance"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_pvZXProdCtr{this, "PV z * x for covariance"};
+
+  // Cached statistics counters
+  mutable unsigned                                m_c_accRunNumber{0}; // Run number of last cached event
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvXPosCtr{this, "Cached PV x position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvYPosCtr{this, "Cached PV y position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvZPosCtr{this, "Cached PV z position"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvXYProdCtr{this, "Cached PV x * y for covariance"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvYZProdCtr{this, "Cached PV y * z for covariance"};
+  mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvZXProdCtr{this, "Cached PV z * x for covariance"};
+
+  // Histograms
+  mutable Gaudi::Accumulators::Histogram<1> m_numPrimaryVertices{
+      this, "NumPrimaryVertices", "NumPrimaryVertices", {11, -0.5, 10.5}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvNTracks{this, "NumTracks", "NumTracks", {101, -0.5, 100.5}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvXPosition{
+      this, "PV x position", "PV x position", {200, -m_histMaxXPV, m_histMaxXPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvYPosition{
+      this, "PV y position", "PV y position", {200, -m_histMaxYPV, m_histMaxYPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvZPosition{
+      this, "PV z position", "PV z position", {200, m_histMinZPV, m_histMaxZPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvZPositionWide{
+      this, "PV z position (wide)", "PV z position (wide)", {200, m_histMinZPV_wide, m_histMaxZPV_wide}};
+};
+
+// Declaration of the Algorithm Factory
+DECLARE_COMPONENT( BeamSpotMonitor )
+
+//=============================================================================
+// Standard constructor, initializes variables
+//=============================================================================
+BeamSpotMonitor::BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLocator )
+    : Consumer{name,
+               pSvcLocator,
+               {KeyValue{"ODINLocation", LHCb::ODINLocation::Default},
+                KeyValue{"PVContainer", LHCb::RecVertexLocation::Primary}}} {}
+
+//=============================================================================
+// Algorithm execution
+//=============================================================================
+void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontainer ) const {
+  // Only one thread can be running from this point on
+  std::scoped_lock lock{m_mutex};
+
+  // Skip this event if it is from a run prior to the one we are accumulating.
+  const auto curRunNumber = odin.runNumber();
+  if ( curRunNumber < m_accRunNumber ) return;
+
+  // Handle cacheing and publication before processing the event.
+  if ( check_reset_accumulators( curRunNumber ) ) {
+    if ( check_cache_counters() ) {
+      // Copy values of accumulating counters to cache
+      cache_counters();
+
+      if ( check_publish() ) ymlWriter();
+    }
+    // Reset accumulators
+    reset_accumulators( curRunNumber );
+  }
+
+  // number of primary vertices
+  ++m_numPrimaryVertices[pvcontainer.size()];
+
+  // info() << "RN: " << odin.runNumber() << endmsg;
+
+  for ( const auto& pv : pvcontainer ) {
+    if ( check_pv( pv ) ) {
+      // info() << "pvx " << pv.position().x() << endmsg;
+      m_pvXPosCtr += pv.position().x();
+      m_pvYPosCtr += pv.position().y();
+      m_pvZPosCtr += pv.position().z();
+      m_pvXYProdCtr += pv.position().x() * pv.position().y();
+      m_pvYZProdCtr += pv.position().y() * pv.position().z();
+      m_pvZXProdCtr += pv.position().z() * pv.position().x();
+
+      ++m_pvNTracks[pv.nTracks()];
+      ++m_pvXPosition[pv.position().x()];
+      ++m_pvYPosition[pv.position().y()];
+      ++m_pvZPosition[pv.position().z()];
+      ++m_pvZPositionWide[pv.position().z()];
+    }
+  }
+}
+
+//=============================================================================
+// Conditions for validity of PVs and inclusion in statistics
+// TODO:  replace this with external input filtering.
+//=============================================================================
+bool BeamSpotMonitor::check_pv( PVView::value_type const& pv ) const { return pv.nTracks() >= m_minNTracks; }
+
+//=============================================================================
+// Check for cacheing the counters
+//=============================================================================
+bool BeamSpotMonitor::check_cache_counters( void ) const {
+  return ( m_pvXPosCtr.nEntries() >= m_minPVsForCalib ) &&
+         ( m_c_pvXPosCtr.nEntries() == 0 || is_accum_delta_pos_over_thresh() || is_accum_delta_spread_over_thresh() );
+}
+
+//=============================================================================
+// Check whether to publish the cached counters
+//=============================================================================
+bool BeamSpotMonitor::check_publish( void ) const { return m_c_pvXPosCtr.nEntries() >= m_minPVsForCalib; }
+
+//=============================================================================
+// Check whether to reset the accumulators
+// Reset when
+// - Accumulated at least the target number of PVs
+// - Processing an event from a new, subsequent run.
+//=============================================================================
+bool BeamSpotMonitor::check_reset_accumulators( const unsigned curRunNumber ) const {
+  return ( m_pvXPosCtr.nEntries() >= m_minPVsForCalib ) || ( m_accRunNumber < curRunNumber );
+}
+
+//=============================================================================
+// Cache the counters
+//=============================================================================
+void BeamSpotMonitor::cache_counters( void ) const {
+  m_c_pvXPosCtr.reset();
+  m_c_pvYPosCtr.reset();
+  m_c_pvZPosCtr.reset();
+  m_c_pvXYProdCtr.reset();
+  m_c_pvYZProdCtr.reset();
+  m_c_pvZXProdCtr.reset();
+
+  m_c_pvXPosCtr.mergeAndReset( m_pvXPosCtr );
+  m_c_pvYPosCtr.mergeAndReset( m_pvYPosCtr );
+  m_c_pvZPosCtr.mergeAndReset( m_pvZPosCtr );
+  m_c_pvXYProdCtr.mergeAndReset( m_pvXYProdCtr );
+  m_c_pvYZProdCtr.mergeAndReset( m_pvYZProdCtr );
+  m_c_pvZXProdCtr.mergeAndReset( m_pvZXProdCtr );
+  m_c_accRunNumber = m_accRunNumber;
+}
+
+//=============================================================================
+// Check whether deltas of the spread matrix have exceeded thresholds.
+//=============================================================================
+bool BeamSpotMonitor::is_accum_delta_spread_over_thresh( void ) const {
+  return ( std::abs( m_c_pvXPosCtr.unbiased_sample_variance() - m_pvXPosCtr.unbiased_sample_variance() ) >
+           m_maxDeltaXX ) ||
+         ( std::abs( m_c_pvYPosCtr.unbiased_sample_variance() - m_pvYPosCtr.unbiased_sample_variance() ) >
+           m_maxDeltaYY ) ||
+         ( std::abs( m_c_pvZPosCtr.unbiased_sample_variance() - m_pvZPosCtr.unbiased_sample_variance() ) >
+           m_maxDeltaZZ ) ||
+         ( std::abs( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) -
+                     calculate_spread_offdiag( m_pvXPosCtr, m_pvYPosCtr, m_pvXYProdCtr ) ) > m_maxDeltaXY ) ||
+         ( std::abs( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) -
+                     calculate_spread_offdiag( m_pvZPosCtr, m_pvXPosCtr, m_pvZXProdCtr ) ) > m_maxDeltaZX ) ||
+         ( std::abs( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) -
+                     calculate_spread_offdiag( m_pvYPosCtr, m_pvZPosCtr, m_pvYZProdCtr ) ) > m_maxDeltaYZ );
+}
+
+//=============================================================================
+// Reset the accumulators
+//=============================================================================
+void BeamSpotMonitor::reset_accumulators( const unsigned curRunNumber ) const {
+  m_pvXPosCtr.reset();
+  m_pvYPosCtr.reset();
+  m_pvZPosCtr.reset();
+  m_pvXYProdCtr.reset();
+  m_pvYZProdCtr.reset();
+  m_pvZXProdCtr.reset();
+  m_accRunNumber = curRunNumber;
+}
+
+//=============================================================================
+// YML formatter
+//=============================================================================
+void BeamSpotMonitor::ymlWriter( void ) const {
+  //
+  if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
+    warning() << "Not enough entries to compute IR statistics" << endmsg;
+    return;
+  }
+
+  std::ostringstream ymlbuff;
+  ymlbuff << "InteractionRegion:\n";
+  ymlbuff << "  position: [ \"" << m_c_pvXPosCtr.mean() / Gaudi::Units::mm << "*mm\", \""
+          << m_c_pvYPosCtr.mean() / Gaudi::Units::mm << "*mm\", \"" << m_c_pvZPosCtr.mean() / Gaudi::Units::mm
+          << "*mm\" ]\n";
+  ymlbuff << "  spread: [ \"" << m_c_pvXPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\", \""
+          << calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) / Gaudi::Units::mm2
+          << "*mm2\", \"" << m_c_pvYPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\", \""
+          << calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) / Gaudi::Units::mm2
+          << "*mm2\", \""
+          << calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) / Gaudi::Units::mm2
+          << "*mm2\", \"" << m_c_pvZPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\" ]\n";
+
+  info() << ymlbuff.str() << endmsg;
+}
-- 
GitLab


From 0b4c9724079bafa0b3718edc914d6326846d1c1c Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Thu, 8 Feb 2024 23:20:51 +0100
Subject: [PATCH 02/15] Work toward using better YAML tools

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 116 ++++++++++++++++++++---
 1 file changed, 102 insertions(+), 14 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 75086f0be73..30d171f5cab 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -12,12 +12,12 @@
 #include "Event/PrimaryVertices.h"
 #include "Event/RecVertex.h"
 
-#include "GaudiAlg/GaudiHistoAlg.h"
 #include "LHCbAlgs/Consumer.h"
 #include <Gaudi/Accumulators/Histogram.h>
 
 #include <mutex>
 #include <sstream>
+#include <yaml-cpp/yaml.h>
 
 namespace {
   using PVView = LHCb::Event::PV::PrimaryVertexContainer;
@@ -46,8 +46,10 @@ private:
   void cache_counters( void ) const;
 
   // Conditions for and implementation of publication of cached conditions
-  bool check_publish( void ) const;
-  void ymlWriter( void ) const;
+  bool       check_publish( void ) const;
+  void       ymlWriter( void ) const;
+  void       ymlWriter( YAML::Emitter& ) const;
+  YAML::Node ymlBuildTest( void ) const;
 
   // Conditions for value drifts
   bool is_accum_delta_pos_over_thresh( void ) const {
@@ -160,7 +162,15 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
       // Copy values of accumulating counters to cache
       cache_counters();
 
-      if ( check_publish() ) ymlWriter();
+      if ( check_publish() ) {
+        ymlWriter();
+        info() << "--------------" << endmsg;
+        YAML::Emitter yout;
+        ymlWriter( yout );
+        info() << yout.c_str() << endmsg;
+        info() << "--------------" << endmsg;
+        info() << ymlBuildTest() << endmsg;
+      }
     }
     // Reset accumulators
     reset_accumulators( curRunNumber );
@@ -272,6 +282,21 @@ void BeamSpotMonitor::reset_accumulators( const unsigned curRunNumber ) const {
 
 //=============================================================================
 // YML formatter
+//
+// Format of example condition
+// lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml/0/200
+//
+// From its comments, the ordering of elements should be
+// InteractionRegion:
+//     position: <avg_position_x_y_z: [float x3]>
+//     spread: <spread_matrix_xx_xy_yy_xz_yz_zz: [float x6]>
+//
+// The example conditions are
+// InteractionRegion:
+//     position: [ "0.0*mm", "0.0*mm", "0.0*mm" ]
+//     spread: [ "0.0064*mm2", "0.0*mm2", "0.0064*mm2", "0.0*mm2", "0.0*mm2", "2809.0*mm2" ]
+//
+// Note that the numeric values and their units are enclosed in double quotes.
 //=============================================================================
 void BeamSpotMonitor::ymlWriter( void ) const {
   //
@@ -280,18 +305,81 @@ void BeamSpotMonitor::ymlWriter( void ) const {
     return;
   }
 
+  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
+  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
+
   std::ostringstream ymlbuff;
   ymlbuff << "InteractionRegion:\n";
-  ymlbuff << "  position: [ \"" << m_c_pvXPosCtr.mean() / Gaudi::Units::mm << "*mm\", \""
-          << m_c_pvYPosCtr.mean() / Gaudi::Units::mm << "*mm\", \"" << m_c_pvZPosCtr.mean() / Gaudi::Units::mm
-          << "*mm\" ]\n";
-  ymlbuff << "  spread: [ \"" << m_c_pvXPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\", \""
-          << calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) / Gaudi::Units::mm2
-          << "*mm2\", \"" << m_c_pvYPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\", \""
-          << calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) / Gaudi::Units::mm2
-          << "*mm2\", \""
-          << calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) / Gaudi::Units::mm2
-          << "*mm2\", \"" << m_c_pvZPosCtr.unbiased_sample_variance() / Gaudi::Units::mm2 << "*mm2\" ]\n";
+  ymlbuff << "  position: [ \"" << fmtPos( m_c_pvXPosCtr.mean() ) << "\", \"" << fmtPos( m_c_pvYPosCtr.mean() )
+          << "\", \"" << fmtPos( m_c_pvZPosCtr.mean() ) << "\" ]\n";
+  ymlbuff << "  spread: [ \"" << fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) << "\", \""
+          << fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) << "\", \""
+          << fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) << "\", \""
+          << fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) << "\", \""
+          << fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) << "\", \""
+          << fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) << "\" ]\n";
 
   info() << ymlbuff.str() << endmsg;
 }
+
+void BeamSpotMonitor::ymlWriter( YAML::Emitter& yout ) const {
+  //
+  if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
+    warning() << "Not enough entries to compute IR statistics" << endmsg;
+    return;
+  }
+
+  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
+  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
+
+  yout.SetSeqFormat( YAML::Flow );
+
+  yout << YAML::BeginMap;
+  yout << YAML::Key << "InteractionRegion";
+  yout << YAML::Value << YAML::BeginMap;
+  yout << YAML::Key << "position";
+  yout << YAML::Value << YAML::BeginSeq;
+  yout << YAML::DoubleQuoted << fmtPos( m_c_pvXPosCtr.mean() ) << YAML::DoubleQuoted << fmtPos( m_c_pvYPosCtr.mean() )
+       << YAML::DoubleQuoted << fmtPos( m_c_pvZPosCtr.mean() ) << YAML::EndSeq;
+  yout << YAML::Key << "spread";
+  yout << YAML::Value << YAML::BeginSeq;
+  yout << YAML::DoubleQuoted << fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
+       << fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) << YAML::DoubleQuoted
+       << fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
+       << fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) << YAML::DoubleQuoted
+       << fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) << YAML::DoubleQuoted
+       << fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) << YAML::EndSeq;
+  yout << YAML::EndMap << YAML::EndMap;
+}
+
+YAML::Node BeamSpotMonitor::ymlBuildTest( void ) const {
+  //
+  // if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
+  //  warning() << "Not enough entries to compute IR statistics" << endmsg;
+  //  return;
+  //}
+
+  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
+  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
+
+  constexpr char irkey[] = "InteractionRegion";
+  constexpr char pkey[]  = "position";
+  constexpr char skey[]  = "spread";
+
+  YAML::Node ir;
+  ir[irkey][pkey].push_back( fmtPos( m_c_pvXPosCtr.mean() ) );
+  ir[irkey][pkey].push_back( fmtPos( m_c_pvYPosCtr.mean() ) );
+  ir[irkey][pkey].push_back( fmtPos( m_c_pvZPosCtr.mean() ) );
+
+  ir[irkey][skey].push_back( fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) );
+  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) );
+  ir[irkey][skey].push_back( fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) );
+  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) );
+  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) );
+  ir[irkey][skey].push_back( fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) );
+
+  ir[irkey][pkey].SetStyle( YAML::EmitterStyle::Flow );
+  ir[irkey][skey].SetStyle( YAML::EmitterStyle::Flow );
+
+  return ir;
+}
-- 
GitLab


From 0b141050699f3c6f77369ffcc4d0103b66b6ffde Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Sat, 10 Feb 2024 17:29:58 +0100
Subject: [PATCH 03/15] Rudimentary file writing

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 220 ++++++++++++++++-------
 1 file changed, 153 insertions(+), 67 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 30d171f5cab..24b8acc92b8 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -15,6 +15,8 @@
 #include "LHCbAlgs/Consumer.h"
 #include <Gaudi/Accumulators/Histogram.h>
 
+#include <boost/filesystem.hpp>
+
 #include <mutex>
 #include <sstream>
 #include <yaml-cpp/yaml.h>
@@ -22,21 +24,65 @@
 namespace {
   using PVView = LHCb::Event::PV::PrimaryVertexContainer;
 
+  /// Unbiased sample covariance calculator for off-diagonals
   template <typename X, typename XX>
   auto calculate_spread_offdiag( X const& x, X const& y, XX const& xy ) {
     return ( xy.sum() - xy.nEntries() * x.mean() * y.mean() ) / ( xy.nEntries() - 1 );
   }
+
+  /// Format position condition "<value>*mm"
+  template <typename T>
+  inline std::string format_position( T x ) {
+    return std::to_string( x / Gaudi::Units::mm ) + "*mm";
+  }
+
+  /// Format spread condition "<value>*mm2"
+  template <typename T>
+  inline std::string format_spread( T x ) {
+    return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2";
+  };
 } // namespace
 
 class BeamSpotMonitor : public LHCb::Algorithm::Consumer<void( LHCb::ODIN const&, PVView const& )> {
 
 public:
-  /** Standard constructor */
+  /// Standard constructor
   BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLocator );
 
-  /** Algorithm execute */
+  /// Algorithm execute
   void operator()( LHCb::ODIN const&, PVView const& pvcontainer ) const override;
 
+  /// Initialization
+  StatusCode initialize() override {
+    return Consumer::initialize().andThen( [&] {
+      // Conditions writing path safety imitating RICH RefIndexCalib
+      const auto curPath = boost::filesystem::current_path().string();
+      if ( m_writeDBFiles ) {
+        try {
+          if ( !boost::filesystem::exists( m_conditionsDbPath.value() ) ) {
+            boost::filesystem::create_directories( m_conditionsDbPath.value() );
+            if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << m_conditionsDbPath.value() << endmsg;
+          }
+        } catch ( const boost::filesystem::filesystem_error& expt ) {
+          warning() << "Cannot write to '" << m_conditionsDbPath.value() << "' -> Resetting Db path to '" << curPath
+                    << "/conditions'" << endmsg;
+          m_conditionsDbPath = curPath + "/conditions";
+        }
+
+        const boost::filesystem::path conditions_dir( m_conditionsDbPath.value() + "/" + m_conditionsPathInDb.value() );
+        try {
+          if ( !boost::filesystem::exists( conditions_dir ) ) {
+            boost::filesystem::create_directories( conditions_dir );
+            if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << conditions_dir.string() << endmsg;
+          }
+        } catch ( const boost::filesystem::filesystem_error& expt ) {
+          // TODO:  further consider what to do in this condition
+          error() << "Cannot write to '" << conditions_dir.string() << "'" << endmsg;
+        }
+      }
+    } );
+  }
+
 private:
   // Conditions for checking validity of PVs
   bool check_pv( PVView::value_type const& ) const;
@@ -47,9 +93,10 @@ private:
 
   // Conditions for and implementation of publication of cached conditions
   bool       check_publish( void ) const;
-  void       ymlWriter( void ) const;
-  void       ymlWriter( YAML::Emitter& ) const;
-  YAML::Node ymlBuildTest( void ) const;
+  bool       ymlFormatter( std::ostringstream& ) const;
+  bool       ymlFormatter( YAML::Emitter& ) const;
+  YAML::Node yamlNode( void ) const;
+  bool       ymlWriter( void ) const;
 
   // Conditions for value drifts
   bool is_accum_delta_pos_over_thresh( void ) const {
@@ -101,6 +148,19 @@ private:
   Gaudi::Property<double> m_maxDeltaZZ{this, "DeltaZZMax", 2 * Gaudi::Units::mm2,
                                        "Maximum allowed absolute difference in spread-matrix Z^2 from cached value"};
 
+  /// Report conditions to log (INFO)
+  Gaudi::Property<bool> m_condToLog{this, "LogConditions", true,
+                                    "Write conditions to logfile with level INFO when updating"};
+
+  /// Create direct run conditions
+  Gaudi::Property<bool> m_writeDBFiles{this, "MakeDBRunFile", false};
+
+  /// LHCB DB to write to path
+  // Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
+  Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
+  Gaudi::Property<std::string> m_conditionsPathInDb{
+      this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml"};
+
   // Accumulating statistics counters
   mutable unsigned                                m_accRunNumber{0}; // Run number of last processed event
   mutable Gaudi::Accumulators::SigmaCounter<>     m_pvXPosCtr{this, "PV x position"};
@@ -111,10 +171,11 @@ private:
   mutable Gaudi::Accumulators::AveragingCounter<> m_pvZXProdCtr{this, "PV z * x for covariance"};
 
   // Cached statistics counters
-  mutable unsigned                                m_c_accRunNumber{0}; // Run number of last cached event
-  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvXPosCtr{this, "Cached PV x position"};
-  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvYPosCtr{this, "Cached PV y position"};
-  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvZPosCtr{this, "Cached PV z position"};
+  mutable unsigned                            m_c_accRunNumber{0};     // Run number of last cached event
+  mutable unsigned                            m_c_revThisRunNumber{0}; // Number of revisions for the current run number
+  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvXPosCtr{this, "Cached PV x position"};
+  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvYPosCtr{this, "Cached PV y position"};
+  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvZPosCtr{this, "Cached PV z position"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvXYProdCtr{this, "Cached PV x * y for covariance"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvYZProdCtr{this, "Cached PV y * z for covariance"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvZXProdCtr{this, "Cached PV z * x for covariance"};
@@ -162,15 +223,7 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
       // Copy values of accumulating counters to cache
       cache_counters();
 
-      if ( check_publish() ) {
-        ymlWriter();
-        info() << "--------------" << endmsg;
-        YAML::Emitter yout;
-        ymlWriter( yout );
-        info() << yout.c_str() << endmsg;
-        info() << "--------------" << endmsg;
-        info() << ymlBuildTest() << endmsg;
-      }
+      if ( check_publish() ) { ymlWriter(); }
     }
     // Reset accumulators
     reset_accumulators( curRunNumber );
@@ -246,6 +299,10 @@ void BeamSpotMonitor::cache_counters( void ) const {
   m_c_pvXYProdCtr.mergeAndReset( m_pvXYProdCtr );
   m_c_pvYZProdCtr.mergeAndReset( m_pvYZProdCtr );
   m_c_pvZXProdCtr.mergeAndReset( m_pvZXProdCtr );
+  if ( m_c_accRunNumber == m_accRunNumber )
+    ++m_c_revThisRunNumber;
+  else
+    m_c_revThisRunNumber = 0;
   m_c_accRunNumber = m_accRunNumber;
 }
 
@@ -298,40 +355,33 @@ void BeamSpotMonitor::reset_accumulators( const unsigned curRunNumber ) const {
 //
 // Note that the numeric values and their units are enclosed in double quotes.
 //=============================================================================
-void BeamSpotMonitor::ymlWriter( void ) const {
+bool BeamSpotMonitor::ymlFormatter( std::ostringstream& ymlbuff ) const {
   //
   if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
     warning() << "Not enough entries to compute IR statistics" << endmsg;
-    return;
+    return false;
   }
 
-  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
-  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
-
-  std::ostringstream ymlbuff;
   ymlbuff << "InteractionRegion:\n";
-  ymlbuff << "  position: [ \"" << fmtPos( m_c_pvXPosCtr.mean() ) << "\", \"" << fmtPos( m_c_pvYPosCtr.mean() )
-          << "\", \"" << fmtPos( m_c_pvZPosCtr.mean() ) << "\" ]\n";
-  ymlbuff << "  spread: [ \"" << fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) << "\", \""
-          << fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) << "\", \""
-          << fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) << "\", \""
-          << fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) << "\", \""
-          << fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) << "\", \""
-          << fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) << "\" ]\n";
-
-  info() << ymlbuff.str() << endmsg;
+  ymlbuff << "  position: [ \"" << format_position( m_c_pvXPosCtr.mean() ) << "\", \""
+          << format_position( m_c_pvYPosCtr.mean() ) << "\", \"" << format_position( m_c_pvZPosCtr.mean() ) << "\" ]\n";
+  ymlbuff << "  spread: [ \"" << format_spread( m_c_pvXPosCtr.unbiased_sample_variance() ) << "\", \""
+          << format_spread( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) << "\", \""
+          << format_spread( m_c_pvYPosCtr.unbiased_sample_variance() ) << "\", \""
+          << format_spread( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) << "\", \""
+          << format_spread( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) << "\", \""
+          << format_spread( m_c_pvZPosCtr.unbiased_sample_variance() ) << "\" ]\n";
+
+  return true;
 }
 
-void BeamSpotMonitor::ymlWriter( YAML::Emitter& yout ) const {
+bool BeamSpotMonitor::ymlFormatter( YAML::Emitter& yout ) const {
   //
   if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
     warning() << "Not enough entries to compute IR statistics" << endmsg;
-    return;
+    return false;
   }
 
-  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
-  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
-
   yout.SetSeqFormat( YAML::Flow );
 
   yout << YAML::BeginMap;
@@ -339,47 +389,83 @@ void BeamSpotMonitor::ymlWriter( YAML::Emitter& yout ) const {
   yout << YAML::Value << YAML::BeginMap;
   yout << YAML::Key << "position";
   yout << YAML::Value << YAML::BeginSeq;
-  yout << YAML::DoubleQuoted << fmtPos( m_c_pvXPosCtr.mean() ) << YAML::DoubleQuoted << fmtPos( m_c_pvYPosCtr.mean() )
-       << YAML::DoubleQuoted << fmtPos( m_c_pvZPosCtr.mean() ) << YAML::EndSeq;
+  yout << YAML::DoubleQuoted << format_position( m_c_pvXPosCtr.mean() ) << YAML::DoubleQuoted
+       << format_position( m_c_pvYPosCtr.mean() ) << YAML::DoubleQuoted << format_position( m_c_pvZPosCtr.mean() )
+       << YAML::EndSeq;
   yout << YAML::Key << "spread";
   yout << YAML::Value << YAML::BeginSeq;
-  yout << YAML::DoubleQuoted << fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
-       << fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) << YAML::DoubleQuoted
-       << fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
-       << fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) << YAML::DoubleQuoted
-       << fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) << YAML::DoubleQuoted
-       << fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) << YAML::EndSeq;
+  yout << YAML::DoubleQuoted << format_spread( m_c_pvXPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
+       << format_spread( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) )
+       << YAML::DoubleQuoted << format_spread( m_c_pvYPosCtr.unbiased_sample_variance() ) << YAML::DoubleQuoted
+       << format_spread( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) )
+       << YAML::DoubleQuoted
+       << format_spread( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) )
+       << YAML::DoubleQuoted << format_spread( m_c_pvZPosCtr.unbiased_sample_variance() ) << YAML::EndSeq;
   yout << YAML::EndMap << YAML::EndMap;
-}
-
-YAML::Node BeamSpotMonitor::ymlBuildTest( void ) const {
-  //
-  // if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
-  //  warning() << "Not enough entries to compute IR statistics" << endmsg;
-  //  return;
-  //}
 
-  auto fmtPos = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm ) + "*mm"; };
-  auto fmtSpr = []( auto const& x ) { return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2"; };
+  return true;
+}
 
+//=============================================================================
+// Experimental construction of YAML::Node
+// Ultimately, the format of InteractionRegion.yml, with double quoted
+//   string values but unquoted string keys, requires a custom emitter method
+//   using the current yaml-cpp interface.
+//
+// This can be a more robuse way of construction the YAML if the formatting
+// complications are resolved or determined to be irrelevant.
+//=============================================================================
+YAML::Node BeamSpotMonitor::yamlNode( void ) const {
   constexpr char irkey[] = "InteractionRegion";
   constexpr char pkey[]  = "position";
   constexpr char skey[]  = "spread";
 
   YAML::Node ir;
-  ir[irkey][pkey].push_back( fmtPos( m_c_pvXPosCtr.mean() ) );
-  ir[irkey][pkey].push_back( fmtPos( m_c_pvYPosCtr.mean() ) );
-  ir[irkey][pkey].push_back( fmtPos( m_c_pvZPosCtr.mean() ) );
-
-  ir[irkey][skey].push_back( fmtSpr( m_c_pvXPosCtr.unbiased_sample_variance() ) );
-  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) );
-  ir[irkey][skey].push_back( fmtSpr( m_c_pvYPosCtr.unbiased_sample_variance() ) );
-  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) );
-  ir[irkey][skey].push_back( fmtSpr( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) );
-  ir[irkey][skey].push_back( fmtSpr( m_c_pvZPosCtr.unbiased_sample_variance() ) );
+  ir[irkey][pkey].push_back( format_position( m_c_pvXPosCtr.mean() ) );
+  ir[irkey][pkey].push_back( format_position( m_c_pvYPosCtr.mean() ) );
+  ir[irkey][pkey].push_back( format_position( m_c_pvZPosCtr.mean() ) );
+
+  ir[irkey][skey].push_back( format_spread( m_c_pvXPosCtr.unbiased_sample_variance() ) );
+  ir[irkey][skey].push_back(
+      format_spread( calculate_spread_offdiag( m_c_pvXPosCtr, m_c_pvYPosCtr, m_c_pvXYProdCtr ) ) );
+  ir[irkey][skey].push_back( format_spread( m_c_pvYPosCtr.unbiased_sample_variance() ) );
+  ir[irkey][skey].push_back(
+      format_spread( calculate_spread_offdiag( m_c_pvZPosCtr, m_c_pvXPosCtr, m_c_pvZXProdCtr ) ) );
+  ir[irkey][skey].push_back(
+      format_spread( calculate_spread_offdiag( m_c_pvYPosCtr, m_c_pvZPosCtr, m_c_pvYZProdCtr ) ) );
+  ir[irkey][skey].push_back( format_spread( m_c_pvZPosCtr.unbiased_sample_variance() ) );
 
   ir[irkey][pkey].SetStyle( YAML::EmitterStyle::Flow );
   ir[irkey][skey].SetStyle( YAML::EmitterStyle::Flow );
 
   return ir;
 }
+
+bool BeamSpotMonitor::ymlWriter( void ) const {
+  std::ostringstream ymlBuff;
+  if ( !ymlFormatter( ymlBuff ) ) {
+    warning() << "YAML formatting of conditions failed." << endmsg;
+    return false;
+  }
+
+  if ( m_condToLog ) info() << ymlBuff.str() << endmsg;
+
+  if ( m_writeDBFiles ) {
+    // Adapting file handling from RICH RefIndexCalib
+    const boost::filesystem::path conditions_dir( m_conditionsDbPath.value() + "/" + m_conditionsPathInDb.value() );
+
+    // TODO:  Understand the necessary filenaming
+    // For now, adding a serial counter to the run number
+    const boost::filesystem::path conditions_file( std::to_string( m_c_accRunNumber ) + "_" +
+                                                   std::to_string( m_c_revThisRunNumber ) );
+    const boost::filesystem::path full_conditions_path = conditions_dir / conditions_file;
+
+    // Outfile.
+    // TODO:  Consdier adapt the use of a temporary file in RefIndexCalib::ymlWriter
+    std::ofstream logging( full_conditions_path.string().c_str() );
+    logging << ymlBuff.str();
+    logging.close();
+  }
+
+  return true;
+}
-- 
GitLab


From e7d5fd17828385c68f4ede25e1c26fbb578a0580 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Sun, 11 Feb 2024 12:22:44 +0100
Subject: [PATCH 04/15] Added histograms for off-diagonal elements of spread
 matrix.

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 24b8acc92b8..80f64a7ff2f 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -126,6 +126,9 @@ private:
                                             "Wide z window for PV plot"};
   Gaudi::Property<double> m_histMaxZPV_wide{this, "HistMaxZPV_Wide", 150 * Gaudi::Units::cm,
                                             "Wide z window for PV plot"};
+  Gaudi::Property<double> m_histMaxXYPV{this, "HistMaxXYPV", 0.1 * Gaudi::Units::mm2};
+  Gaudi::Property<double> m_histMaxYZPV{this, "HistMaxYZPV", 2 * Gaudi::Units::mm2};
+  Gaudi::Property<double> m_histMaxZXPV{this, "HistMaxZXPV", 0.1 * Gaudi::Units::cm2};
 
   // Thresholds triggering updated publication
   Gaudi::Property<double> m_maxDeltaX{this, "DeltaXMax", 2 * Gaudi::Units::mm,
@@ -192,6 +195,12 @@ private:
       this, "PV z position", "PV z position", {200, m_histMinZPV, m_histMaxZPV}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvZPositionWide{
       this, "PV z position (wide)", "PV z position (wide)", {200, m_histMinZPV_wide, m_histMaxZPV_wide}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvXYPosCov{
+      this, "PV (x - x_mean)*(y - y_mean)", "PV (x - x_mean)*(y - y_mean)", {200, -m_histMaxXYPV, m_histMaxXYPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvYZPosCov{
+      this, "PV (y - y_mean)*(z - z_mean)", "PV (y - y_mean)*(z - z_mean)", {200, -m_histMaxYZPV, m_histMaxYZPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvZXPosCov{
+      this, "PV (z - z_mean)*(x - x_mean)", "PV (z - z_mean)*(x - x_mean)", {200, -m_histMaxZXPV, m_histMaxZXPV}};
 };
 
 // Declaration of the Algorithm Factory
@@ -249,6 +258,10 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
       ++m_pvYPosition[pv.position().y()];
       ++m_pvZPosition[pv.position().z()];
       ++m_pvZPositionWide[pv.position().z()];
+      /// Must be incremented after accumulators to avoid excursion on first PV.
+      ++m_pvXYPosCov[( pv.position().x() - m_pvXPosCtr.mean() ) * ( pv.position().y() - m_pvYPosCtr.mean() )];
+      ++m_pvYZPosCov[( pv.position().y() - m_pvYPosCtr.mean() ) * ( pv.position().z() - m_pvZPosCtr.mean() )];
+      ++m_pvZXPosCov[( pv.position().z() - m_pvZPosCtr.mean() ) * ( pv.position().x() - m_pvXPosCtr.mean() )];
     }
   }
 }
-- 
GitLab


From 5495f7bc4a42e9a3131354422737068873c75f43 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Tue, 13 Feb 2024 12:11:02 +0100
Subject: [PATCH 05/15] Organization of private data members; improved
 histogram labels.

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 115 ++++++++++++++---------
 1 file changed, 71 insertions(+), 44 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 80f64a7ff2f..40ac860d7c4 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -84,21 +84,23 @@ public:
   }
 
 private:
-  // Conditions for checking validity of PVs
+  // Methods
+  //---------------------------------------------------------------------------
+  /// Conditions for checking validity of PVs
   bool check_pv( PVView::value_type const& ) const;
 
-  // Conditions for and implementation of copying accumulating counters to cache
+  /// Conditions for and implementation of copying accumulating ctrs to cache
   bool check_cache_counters( void ) const;
   void cache_counters( void ) const;
 
-  // Conditions for and implementation of publication of cached conditions
+  /// Conditions for and implementation of publication of cached conditions
   bool       check_publish( void ) const;
   bool       ymlFormatter( std::ostringstream& ) const;
   bool       ymlFormatter( YAML::Emitter& ) const;
   YAML::Node yamlNode( void ) const;
   bool       ymlWriter( void ) const;
 
-  // Conditions for value drifts
+  /// Conditions for value drifts
   bool is_accum_delta_pos_over_thresh( void ) const {
     return ( std::abs( m_pvXPosCtr.mean() - m_c_pvXPosCtr.mean() ) > m_maxDeltaX ) ||
            ( std::abs( m_pvYPosCtr.mean() - m_c_pvYPosCtr.mean() ) > m_maxDeltaY ) ||
@@ -106,31 +108,36 @@ private:
   }
   bool is_accum_delta_spread_over_thresh( void ) const;
 
-  // Reset the accumulators
+  /// Reset the accumulators
   bool check_reset_accumulators( const unsigned ) const;
   void reset_accumulators( const unsigned ) const;
 
-  // Lock for main event processing
-  mutable std::mutex m_mutex;
+  // Properties
+  //---------------------------------------------------------------------------
+
+  // Output configuration properties
+  //...........................................................................
+  /// Report conditions to log (INFO)
+  Gaudi::Property<bool> m_condToLog{this, "LogConditions", true,
+                                    "Write conditions to logfile with level INFO when updating"};
 
+  /// Create direct run conditions
+  Gaudi::Property<bool> m_writeDBFiles{this, "MakeDBRunFile", false};
+
+  /// LHCB DB to write to path
+  // Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
+  Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
+  Gaudi::Property<std::string> m_conditionsPathInDb{
+      this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml"};
+
+  // Accumulation configuration properties
+  //...........................................................................
   Gaudi::Property<long unsigned> m_minPVsForCalib{this, "MinPVsForCalib", 100ul,
                                                   "Minumum number of accumulated PVs for a calibration"};
-  Gaudi::Property<int> m_minNTracks{this, "MinPVnTracks", 15, "Minumum number of tracks in a PVs for processing"};
 
-  // Histogram limits
-  Gaudi::Property<double> m_histMaxXPV{this, "HistMaxXPV", 2 * Gaudi::Units::mm};
-  Gaudi::Property<double> m_histMaxYPV{this, "HistMaxYPV", 1 * Gaudi::Units::mm};
-  Gaudi::Property<double> m_histMinZPV{this, "HistMinZPV", -20 * Gaudi::Units::cm};
-  Gaudi::Property<double> m_histMaxZPV{this, "HistMaxZPV", 20 * Gaudi::Units::cm};
-  Gaudi::Property<double> m_histMinZPV_wide{this, "HistMinZPV_Wide", -150 * Gaudi::Units::cm,
-                                            "Wide z window for PV plot"};
-  Gaudi::Property<double> m_histMaxZPV_wide{this, "HistMaxZPV_Wide", 150 * Gaudi::Units::cm,
-                                            "Wide z window for PV plot"};
-  Gaudi::Property<double> m_histMaxXYPV{this, "HistMaxXYPV", 0.1 * Gaudi::Units::mm2};
-  Gaudi::Property<double> m_histMaxYZPV{this, "HistMaxYZPV", 2 * Gaudi::Units::mm2};
-  Gaudi::Property<double> m_histMaxZXPV{this, "HistMaxZXPV", 0.1 * Gaudi::Units::cm2};
+  Gaudi::Property<int> m_minNTracks{this, "MinPVnTracks", 15, "Minumum number of tracks in a PVs for processing"};
 
-  // Thresholds triggering updated publication
+  /// Thresholds triggering updated publication
   Gaudi::Property<double> m_maxDeltaX{this, "DeltaXMax", 2 * Gaudi::Units::mm,
                                       "Maximum allowed absolute difference in mean X from cached value"};
   Gaudi::Property<double> m_maxDeltaY{this, "DeltaYMax", 2 * Gaudi::Units::mm,
@@ -151,20 +158,21 @@ private:
   Gaudi::Property<double> m_maxDeltaZZ{this, "DeltaZZMax", 2 * Gaudi::Units::mm2,
                                        "Maximum allowed absolute difference in spread-matrix Z^2 from cached value"};
 
-  /// Report conditions to log (INFO)
-  Gaudi::Property<bool> m_condToLog{this, "LogConditions", true,
-                                    "Write conditions to logfile with level INFO when updating"};
-
-  /// Create direct run conditions
-  Gaudi::Property<bool> m_writeDBFiles{this, "MakeDBRunFile", false};
-
-  /// LHCB DB to write to path
-  // Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
-  Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
-  Gaudi::Property<std::string> m_conditionsPathInDb{
-      this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml"};
+  /// Histogram limits
+  Gaudi::Property<double> m_histMaxXPV{this, "HistMaxXPV", 2 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMaxYPV{this, "HistMaxYPV", 2 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMinZPV{this, "HistMinZPV", -200 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMaxZPV{this, "HistMaxZPV", 200 * Gaudi::Units::mm};
+  Gaudi::Property<double> m_histMinZPV_wide{this, "HistMinZPV_Wide", -1.5e3 * Gaudi::Units::mm,
+                                            "Wide z window for PV plot"};
+  Gaudi::Property<double> m_histMaxZPV_wide{this, "HistMaxZPV_Wide", 1.5e3 * Gaudi::Units::mm,
+                                            "Wide z window for PV plot"};
+  Gaudi::Property<double> m_histMaxXYPV{this, "HistMaxXYPV", 0.1 * Gaudi::Units::mm2};
+  Gaudi::Property<double> m_histMaxYZPV{this, "HistMaxYZPV", 20 * Gaudi::Units::mm2};
+  Gaudi::Property<double> m_histMaxZXPV{this, "HistMaxZXPV", 10.0 * Gaudi::Units::mm2};
 
   // Accumulating statistics counters
+  //---------------------------------------------------------------------------
   mutable unsigned                                m_accRunNumber{0}; // Run number of last processed event
   mutable Gaudi::Accumulators::SigmaCounter<>     m_pvXPosCtr{this, "PV x position"};
   mutable Gaudi::Accumulators::SigmaCounter<>     m_pvYPosCtr{this, "PV y position"};
@@ -173,7 +181,8 @@ private:
   mutable Gaudi::Accumulators::AveragingCounter<> m_pvYZProdCtr{this, "PV y * z for covariance"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_pvZXProdCtr{this, "PV z * x for covariance"};
 
-  // Cached statistics counters
+  // Cached statistics counters and variables
+  //---------------------------------------------------------------------------
   mutable unsigned                            m_c_accRunNumber{0};     // Run number of last cached event
   mutable unsigned                            m_c_revThisRunNumber{0}; // Number of revisions for the current run number
   mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvXPosCtr{this, "Cached PV x position"};
@@ -184,23 +193,41 @@ private:
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvZXProdCtr{this, "Cached PV z * x for covariance"};
 
   // Histograms
+  //---------------------------------------------------------------------------
   mutable Gaudi::Accumulators::Histogram<1> m_numPrimaryVertices{
-      this, "NumPrimaryVertices", "NumPrimaryVertices", {11, -0.5, 10.5}};
-  mutable Gaudi::Accumulators::Histogram<1> m_pvNTracks{this, "NumTracks", "NumTracks", {101, -0.5, 100.5}};
+      this, "NumPrimaryVertices", "Primary vertices per event;Number of PVs;Entries", {11, -0.5, 10.5}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvNTracks{
+      this, "NumTracks", "Number of tracks per primary vertex;Number of tracks;Entries", {101, -0.5, 100.5}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvXPosition{
-      this, "PV x position", "PV x position", {200, -m_histMaxXPV, m_histMaxXPV}};
+      this, "PVPosX", "Primary vertex X position;PV X [mm];Entries", {200, -m_histMaxXPV, m_histMaxXPV}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvYPosition{
-      this, "PV y position", "PV y position", {200, -m_histMaxYPV, m_histMaxYPV}};
+      this, "PVPosY", "Primary vertex Y position;PV Y [mm];Entries", {200, -m_histMaxYPV, m_histMaxYPV}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvZPosition{
-      this, "PV z position", "PV z position", {200, m_histMinZPV, m_histMaxZPV}};
-  mutable Gaudi::Accumulators::Histogram<1> m_pvZPositionWide{
-      this, "PV z position (wide)", "PV z position (wide)", {200, m_histMinZPV_wide, m_histMaxZPV_wide}};
+      this, "PVPosZ", "Primary vertex Z position;PV Z [mm];Entries", {200, m_histMinZPV, m_histMaxZPV}};
+  mutable Gaudi::Accumulators::Histogram<1> m_pvZPositionWide{this,
+                                                              "PVPosZWide",
+                                                              "Primary vertex Z position (wide);PV Z [mm];Entries",
+                                                              {200, m_histMinZPV_wide, m_histMaxZPV_wide}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvXYPosCov{
-      this, "PV (x - x_mean)*(y - y_mean)", "PV (x - x_mean)*(y - y_mean)", {200, -m_histMaxXYPV, m_histMaxXYPV}};
+      this,
+      "PVCovXY",
+      "Interaction region covariance X-Y;PV (X - X_mean)*(Y - Y_mean) [mm2];Entries",
+      {200, -m_histMaxXYPV, m_histMaxXYPV}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvYZPosCov{
-      this, "PV (y - y_mean)*(z - z_mean)", "PV (y - y_mean)*(z - z_mean)", {200, -m_histMaxYZPV, m_histMaxYZPV}};
+      this,
+      "PVCovYZ",
+      "Interaction region covariance Y-Z;PV (Y - Y_mean)*(Z - Z_mean) [mm2];Entries",
+      {200, -m_histMaxYZPV, m_histMaxYZPV}};
   mutable Gaudi::Accumulators::Histogram<1> m_pvZXPosCov{
-      this, "PV (z - z_mean)*(x - x_mean)", "PV (z - z_mean)*(x - x_mean)", {200, -m_histMaxZXPV, m_histMaxZXPV}};
+      this,
+      "PVCovZX",
+      "Interaction region covariance Z-X;PV (Z - Z_mean)*(X - X_mean) [mm2];Entries",
+      {200, -m_histMaxZXPV, m_histMaxZXPV}};
+
+  // Other data members
+  //---------------------------------------------------------------------------
+  /// Lock for main event processing
+  mutable std::mutex m_mutex;
 };
 
 // Declaration of the Algorithm Factory
-- 
GitLab


From d7923e054d77dcbdbd5f937269e3bd03487b716d Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Wed, 14 Feb 2024 12:17:06 +0100
Subject: [PATCH 06/15] Changed input type to LHCb::RecVertex::Range.  Removed
 check of PV number of tracks---this and other PV selection is to be done with
 a VertexListRefiner

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 50 +++++++++---------------
 1 file changed, 18 insertions(+), 32 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 40ac860d7c4..c870f2d892e 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -9,7 +9,6 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 #include "Event/ODIN.h"
-#include "Event/PrimaryVertices.h"
 #include "Event/RecVertex.h"
 
 #include "LHCbAlgs/Consumer.h"
@@ -22,7 +21,7 @@
 #include <yaml-cpp/yaml.h>
 
 namespace {
-  using PVView = LHCb::Event::PV::PrimaryVertexContainer;
+  using PVView = LHCb::RecVertex::Range;
 
   /// Unbiased sample covariance calculator for off-diagonals
   template <typename X, typename XX>
@@ -86,9 +85,6 @@ public:
 private:
   // Methods
   //---------------------------------------------------------------------------
-  /// Conditions for checking validity of PVs
-  bool check_pv( PVView::value_type const& ) const;
-
   /// Conditions for and implementation of copying accumulating ctrs to cache
   bool check_cache_counters( void ) const;
   void cache_counters( void ) const;
@@ -135,8 +131,6 @@ private:
   Gaudi::Property<long unsigned> m_minPVsForCalib{this, "MinPVsForCalib", 100ul,
                                                   "Minumum number of accumulated PVs for a calibration"};
 
-  Gaudi::Property<int> m_minNTracks{this, "MinPVnTracks", 15, "Minumum number of tracks in a PVs for processing"};
-
   /// Thresholds triggering updated publication
   Gaudi::Property<double> m_maxDeltaX{this, "DeltaXMax", 2 * Gaudi::Units::mm,
                                       "Maximum allowed absolute difference in mean X from cached value"};
@@ -271,34 +265,26 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
   // info() << "RN: " << odin.runNumber() << endmsg;
 
   for ( const auto& pv : pvcontainer ) {
-    if ( check_pv( pv ) ) {
-      // info() << "pvx " << pv.position().x() << endmsg;
-      m_pvXPosCtr += pv.position().x();
-      m_pvYPosCtr += pv.position().y();
-      m_pvZPosCtr += pv.position().z();
-      m_pvXYProdCtr += pv.position().x() * pv.position().y();
-      m_pvYZProdCtr += pv.position().y() * pv.position().z();
-      m_pvZXProdCtr += pv.position().z() * pv.position().x();
-
-      ++m_pvNTracks[pv.nTracks()];
-      ++m_pvXPosition[pv.position().x()];
-      ++m_pvYPosition[pv.position().y()];
-      ++m_pvZPosition[pv.position().z()];
-      ++m_pvZPositionWide[pv.position().z()];
-      /// Must be incremented after accumulators to avoid excursion on first PV.
-      ++m_pvXYPosCov[( pv.position().x() - m_pvXPosCtr.mean() ) * ( pv.position().y() - m_pvYPosCtr.mean() )];
-      ++m_pvYZPosCov[( pv.position().y() - m_pvYPosCtr.mean() ) * ( pv.position().z() - m_pvZPosCtr.mean() )];
-      ++m_pvZXPosCov[( pv.position().z() - m_pvZPosCtr.mean() ) * ( pv.position().x() - m_pvXPosCtr.mean() )];
-    }
+    // info() << "pvx " << pv->position().x() << endmsg;
+    m_pvXPosCtr += pv->position().x();
+    m_pvYPosCtr += pv->position().y();
+    m_pvZPosCtr += pv->position().z();
+    m_pvXYProdCtr += pv->position().x() * pv->position().y();
+    m_pvYZProdCtr += pv->position().y() * pv->position().z();
+    m_pvZXProdCtr += pv->position().z() * pv->position().x();
+
+    ++m_pvNTracks[pv->tracks().size()];
+    ++m_pvXPosition[pv->position().x()];
+    ++m_pvYPosition[pv->position().y()];
+    ++m_pvZPosition[pv->position().z()];
+    ++m_pvZPositionWide[pv->position().z()];
+    // Must be incremented after accumulators to avoid excursion on first PV.
+    ++m_pvXYPosCov[( pv->position().x() - m_pvXPosCtr.mean() ) * ( pv->position().y() - m_pvYPosCtr.mean() )];
+    ++m_pvYZPosCov[( pv->position().y() - m_pvYPosCtr.mean() ) * ( pv->position().z() - m_pvZPosCtr.mean() )];
+    ++m_pvZXPosCov[( pv->position().z() - m_pvZPosCtr.mean() ) * ( pv->position().x() - m_pvXPosCtr.mean() )];
   }
 }
 
-//=============================================================================
-// Conditions for validity of PVs and inclusion in statistics
-// TODO:  replace this with external input filtering.
-//=============================================================================
-bool BeamSpotMonitor::check_pv( PVView::value_type const& pv ) const { return pv.nTracks() >= m_minNTracks; }
-
 //=============================================================================
 // Check for cacheing the counters
 //=============================================================================
-- 
GitLab


From 41b5ea3bae15d68b40d2788151de3218e2929f56 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Tue, 5 Mar 2024 13:55:46 +0100
Subject: [PATCH 07/15] Updated output file writing

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 77 ++++++++++++++----------
 1 file changed, 46 insertions(+), 31 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index c870f2d892e..69bf1e74cb0 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -14,10 +14,11 @@
 #include "LHCbAlgs/Consumer.h"
 #include <Gaudi/Accumulators/Histogram.h>
 
-#include <boost/filesystem.hpp>
-
+#include <filesystem>
 #include <mutex>
+#include <regex>
 #include <sstream>
+#include <string>
 #include <yaml-cpp/yaml.h>
 
 namespace {
@@ -39,7 +40,25 @@ namespace {
   template <typename T>
   inline std::string format_spread( T x ) {
     return std::to_string( x / Gaudi::Units::mm2 ) + "*mm2";
-  };
+  }
+
+  /// Find largest version number in a directory
+  /// Adapted from AlignOnlineYMLCopier::AlignOnlineYMLCopier
+  template <typename T>
+  int find_max_version_number( T dir ) {
+    int        max_version_nr = -1;
+    std::regex regex_version_file( "^v([0-9]+)$" );
+    for ( const auto& entry : std::filesystem::directory_iterator( dir ) ) {
+      auto        version_file_name = entry.path().stem().string();
+      std::smatch matches;
+      if ( std::regex_search( version_file_name, matches, regex_version_file ) && matches.size() > 1 &&
+           matches[1].matched ) {
+        int version_nr = std::stoi( matches[1] );
+        if ( version_nr > max_version_nr ) max_version_nr = version_nr;
+      }
+    }
+    return max_version_nr;
+  }
 } // namespace
 
 class BeamSpotMonitor : public LHCb::Algorithm::Consumer<void( LHCb::ODIN const&, PVView const& )> {
@@ -55,26 +74,27 @@ public:
   StatusCode initialize() override {
     return Consumer::initialize().andThen( [&] {
       // Conditions writing path safety imitating RICH RefIndexCalib
-      const auto curPath = boost::filesystem::current_path().string();
+      const auto curPath = std::filesystem::current_path();
       if ( m_writeDBFiles ) {
         try {
-          if ( !boost::filesystem::exists( m_conditionsDbPath.value() ) ) {
-            boost::filesystem::create_directories( m_conditionsDbPath.value() );
+          if ( !std::filesystem::exists( m_conditionsDbPath.value() ) ) {
+            std::filesystem::create_directories( m_conditionsDbPath.value() );
             if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << m_conditionsDbPath.value() << endmsg;
           }
-        } catch ( const boost::filesystem::filesystem_error& expt ) {
-          warning() << "Cannot write to '" << m_conditionsDbPath.value() << "' -> Resetting Db path to '" << curPath
-                    << "/conditions'" << endmsg;
-          m_conditionsDbPath = curPath + "/conditions";
+        } catch ( const std::filesystem::filesystem_error& expt ) {
+          warning() << "Cannot write to '" << m_conditionsDbPath.value() << "' -> Resetting Db path to '"
+                    << curPath.string() << "/conditions'" << endmsg;
+          m_conditionsDbPath = curPath.string() + "/conditions";
         }
 
-        const boost::filesystem::path conditions_dir( m_conditionsDbPath.value() + "/" + m_conditionsPathInDb.value() );
+        const std::filesystem::path conditions_dir =
+            std::filesystem::path( m_conditionsDbPath.value() ) / std::filesystem::path( m_conditionsPathInDb.value() );
         try {
-          if ( !boost::filesystem::exists( conditions_dir ) ) {
-            boost::filesystem::create_directories( conditions_dir );
+          if ( !std::filesystem::exists( conditions_dir ) ) {
+            std::filesystem::create_directories( conditions_dir );
             if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << conditions_dir.string() << endmsg;
           }
-        } catch ( const boost::filesystem::filesystem_error& expt ) {
+        } catch ( const std::filesystem::filesystem_error& expt ) {
           // TODO:  further consider what to do in this condition
           error() << "Cannot write to '" << conditions_dir.string() << "'" << endmsg;
         }
@@ -124,7 +144,7 @@ private:
   // Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
   Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
   Gaudi::Property<std::string> m_conditionsPathInDb{
-      this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml"};
+      this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml/.pool"};
 
   // Accumulation configuration properties
   //...........................................................................
@@ -132,6 +152,7 @@ private:
                                                   "Minumum number of accumulated PVs for a calibration"};
 
   /// Thresholds triggering updated publication
+  // TODO: Fix the implementation---histograms must be defined after config
   Gaudi::Property<double> m_maxDeltaX{this, "DeltaXMax", 2 * Gaudi::Units::mm,
                                       "Maximum allowed absolute difference in mean X from cached value"};
   Gaudi::Property<double> m_maxDeltaY{this, "DeltaYMax", 2 * Gaudi::Units::mm,
@@ -177,11 +198,10 @@ private:
 
   // Cached statistics counters and variables
   //---------------------------------------------------------------------------
-  mutable unsigned                            m_c_accRunNumber{0};     // Run number of last cached event
-  mutable unsigned                            m_c_revThisRunNumber{0}; // Number of revisions for the current run number
-  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvXPosCtr{this, "Cached PV x position"};
-  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvYPosCtr{this, "Cached PV y position"};
-  mutable Gaudi::Accumulators::SigmaCounter<> m_c_pvZPosCtr{this, "Cached PV z position"};
+  mutable unsigned                                m_c_accRunNumber{0}; // Run number of last cached event
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvXPosCtr{this, "Cached PV x position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvYPosCtr{this, "Cached PV y position"};
+  mutable Gaudi::Accumulators::SigmaCounter<>     m_c_pvZPosCtr{this, "Cached PV z position"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvXYProdCtr{this, "Cached PV x * y for covariance"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvYZProdCtr{this, "Cached PV y * z for covariance"};
   mutable Gaudi::Accumulators::AveragingCounter<> m_c_pvZXProdCtr{this, "Cached PV z * x for covariance"};
@@ -325,10 +345,6 @@ void BeamSpotMonitor::cache_counters( void ) const {
   m_c_pvXYProdCtr.mergeAndReset( m_pvXYProdCtr );
   m_c_pvYZProdCtr.mergeAndReset( m_pvYZProdCtr );
   m_c_pvZXProdCtr.mergeAndReset( m_pvZXProdCtr );
-  if ( m_c_accRunNumber == m_accRunNumber )
-    ++m_c_revThisRunNumber;
-  else
-    m_c_revThisRunNumber = 0;
   m_c_accRunNumber = m_accRunNumber;
 }
 
@@ -478,16 +494,15 @@ bool BeamSpotMonitor::ymlWriter( void ) const {
 
   if ( m_writeDBFiles ) {
     // Adapting file handling from RICH RefIndexCalib
-    const boost::filesystem::path conditions_dir( m_conditionsDbPath.value() + "/" + m_conditionsPathInDb.value() );
+    const std::filesystem::path conditions_dir =
+        std::filesystem::path( m_conditionsDbPath.value() ) / std::filesystem::path( m_conditionsPathInDb.value() );
+
+    const auto max_version_nr = find_max_version_number( conditions_dir );
 
-    // TODO:  Understand the necessary filenaming
-    // For now, adding a serial counter to the run number
-    const boost::filesystem::path conditions_file( std::to_string( m_c_accRunNumber ) + "_" +
-                                                   std::to_string( m_c_revThisRunNumber ) );
-    const boost::filesystem::path full_conditions_path = conditions_dir / conditions_file;
+    const std::filesystem::path conditions_file( "v" + std::to_string( max_version_nr + 1 ) );
+    const std::filesystem::path full_conditions_path = conditions_dir / conditions_file;
 
     // Outfile.
-    // TODO:  Consdier adapt the use of a temporary file in RefIndexCalib::ymlWriter
     std::ofstream logging( full_conditions_path.string().c_str() );
     logging << ymlBuff.str();
     logging.close();
-- 
GitLab


From 021fc3fb6f1dbf8642f44927aea437f7a0e0f5f9 Mon Sep 17 00:00:00 2001
From: Andre Gunther <p.gunther@cern.ch>
Date: Wed, 6 Mar 2024 18:56:18 +0100
Subject: [PATCH 08/15] Apply 1 suggestion(s) to 1 file(s)

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 69bf1e74cb0..217a14336f4 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -141,7 +141,6 @@ private:
   Gaudi::Property<bool> m_writeDBFiles{this, "MakeDBRunFile", false};
 
   /// LHCB DB to write to path
-  // Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
   Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
   Gaudi::Property<std::string> m_conditionsPathInDb{
       this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml/.pool"};
-- 
GitLab


From e223d3ca3beccfcea2179def74931ce8cf80b040 Mon Sep 17 00:00:00 2001
From: Andre Gunther <p.gunther@cern.ch>
Date: Wed, 6 Mar 2024 19:02:28 +0100
Subject: [PATCH 09/15] Apply 1 suggestion(s) to 1 file(s)

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 217a14336f4..4827daacaf1 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -281,7 +281,6 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
   // number of primary vertices
   ++m_numPrimaryVertices[pvcontainer.size()];
 
-  // info() << "RN: " << odin.runNumber() << endmsg;
 
   for ( const auto& pv : pvcontainer ) {
     // info() << "pvx " << pv->position().x() << endmsg;
-- 
GitLab


From 6183ec822f3f04357a104961540bf6f9f5195d71 Mon Sep 17 00:00:00 2001
From: Andre Gunther <p.gunther@cern.ch>
Date: Wed, 6 Mar 2024 19:02:35 +0100
Subject: [PATCH 10/15] Apply 1 suggestion(s) to 1 file(s)

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 4827daacaf1..c034e8ffb01 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -283,7 +283,6 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
 
 
   for ( const auto& pv : pvcontainer ) {
-    // info() << "pvx " << pv->position().x() << endmsg;
     m_pvXPosCtr += pv->position().x();
     m_pvYPosCtr += pv->position().y();
     m_pvZPosCtr += pv->position().z();
-- 
GitLab


From 0974edd7783725715b93401dad3eee90e9c551f3 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Wed, 6 Mar 2024 19:29:11 +0100
Subject: [PATCH 11/15] Fixed formatting.

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index c034e8ffb01..dc071e7eb55 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -141,7 +141,7 @@ private:
   Gaudi::Property<bool> m_writeDBFiles{this, "MakeDBRunFile", false};
 
   /// LHCB DB to write to path
-  Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "."};
+  Gaudi::Property<std::string> m_conditionsDbPath{this, "conditionsDbPath", "/group/online/hlt/conditions.run3"};
   Gaudi::Property<std::string> m_conditionsPathInDb{
       this, "conditionsPathInDb", "lhcb-conditions-database/Conditions/LHCb/Online/InteractionRegion.yml/.pool"};
 
@@ -281,7 +281,6 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
   // number of primary vertices
   ++m_numPrimaryVertices[pvcontainer.size()];
 
-
   for ( const auto& pv : pvcontainer ) {
     m_pvXPosCtr += pv->position().x();
     m_pvYPosCtr += pv->position().y();
-- 
GitLab


From 53dc25cfad8b7513a8c6c7d66413e2f405509ebd Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Wed, 6 Mar 2024 19:38:35 +0100
Subject: [PATCH 12/15] Changed type of hard-coded YAML keys from 'constexpr
 char[]' to 'const std::string'

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index dc071e7eb55..645659522c3 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -454,9 +454,9 @@ bool BeamSpotMonitor::ymlFormatter( YAML::Emitter& yout ) const {
 // complications are resolved or determined to be irrelevant.
 //=============================================================================
 YAML::Node BeamSpotMonitor::yamlNode( void ) const {
-  constexpr char irkey[] = "InteractionRegion";
-  constexpr char pkey[]  = "position";
-  constexpr char skey[]  = "spread";
+  const std::string irkey = "InteractionRegion";
+  const std::string pkey  = "position";
+  const std::string skey  = "spread";
 
   YAML::Node ir;
   ir[irkey][pkey].push_back( format_position( m_c_pvXPosCtr.mean() ) );
-- 
GitLab


From c8d5176b339677b84226dc9829b925e5a21f06b5 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Wed, 6 Mar 2024 20:06:45 +0100
Subject: [PATCH 13/15] Reworked event-loop messaging

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 645659522c3..f4eb548e428 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -237,6 +237,10 @@ private:
       "Interaction region covariance Z-X;PV (Z - Z_mean)*(X - X_mean) [mm2];Entries",
       {200, -m_histMaxZXPV, m_histMaxZXPV}};
 
+  // Warning counters
+  //---------------------------------------------------------------------------
+  mutable Gaudi::Accumulators::MsgCounter<MSG::ERROR> m_badPVCount{this, "Too few PVs to produce IR conditions"};
+
   // Other data members
   //---------------------------------------------------------------------------
   /// Lock for main event processing
@@ -396,7 +400,7 @@ void BeamSpotMonitor::reset_accumulators( const unsigned curRunNumber ) const {
 bool BeamSpotMonitor::ymlFormatter( std::ostringstream& ymlbuff ) const {
   //
   if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
-    warning() << "Not enough entries to compute IR statistics" << endmsg;
+    ++m_badPVCount;
     return false;
   }
 
@@ -416,7 +420,7 @@ bool BeamSpotMonitor::ymlFormatter( std::ostringstream& ymlbuff ) const {
 bool BeamSpotMonitor::ymlFormatter( YAML::Emitter& yout ) const {
   //
   if ( m_c_pvXPosCtr.nEntries() < m_minPVsForCalib ) {
-    warning() << "Not enough entries to compute IR statistics" << endmsg;
+    ++m_badPVCount;
     return false;
   }
 
@@ -482,8 +486,8 @@ YAML::Node BeamSpotMonitor::yamlNode( void ) const {
 bool BeamSpotMonitor::ymlWriter( void ) const {
   std::ostringstream ymlBuff;
   if ( !ymlFormatter( ymlBuff ) ) {
-    warning() << "YAML formatting of conditions failed." << endmsg;
-    return false;
+    throw GaudiException( "YAML formatting of conditions failed - unable to write new conditions", name(),
+                          StatusCode::FAILURE );
   }
 
   if ( m_condToLog ) info() << ymlBuff.str() << endmsg;
-- 
GitLab


From 6dc3c2bc0586c1a763c2d4ae287d9856778e12d6 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Thu, 7 Mar 2024 12:13:51 +0100
Subject: [PATCH 14/15] Encapsulated non-thread-safe operations in a locked
 method

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 46 ++++++++++++++----------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index f4eb548e428..6841920ec79 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -95,8 +95,9 @@ public:
             if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << conditions_dir.string() << endmsg;
           }
         } catch ( const std::filesystem::filesystem_error& expt ) {
-          // TODO:  further consider what to do in this condition
-          error() << "Cannot write to '" << conditions_dir.string() << "'" << endmsg;
+          // TODO:  consider whether this is a recoverable condition.
+          throw GaudiException( "Conditions directory does not exist and cannot be created", name(),
+                                StatusCode::FAILURE );
         }
       }
     } );
@@ -105,6 +106,9 @@ public:
 private:
   // Methods
   //---------------------------------------------------------------------------
+  /// Non-thread-safe part of the event loop --- resetting and publishing
+  void check_and_publish_reset( unsigned ) const;
+
   /// Conditions for and implementation of copying accumulating ctrs to cache
   bool check_cache_counters( void ) const;
   void cache_counters( void ) const;
@@ -134,7 +138,7 @@ private:
   // Output configuration properties
   //...........................................................................
   /// Report conditions to log (INFO)
-  Gaudi::Property<bool> m_condToLog{this, "LogConditions", true,
+  Gaudi::Property<bool> m_condToLog{this, "LogConditions", false,
                                     "Write conditions to logfile with level INFO when updating"};
 
   /// Create direct run conditions
@@ -263,25 +267,12 @@ BeamSpotMonitor::BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLoca
 // Algorithm execution
 //=============================================================================
 void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontainer ) const {
-  // Only one thread can be running from this point on
-  std::scoped_lock lock{m_mutex};
+  const auto curRunNumber = odin.runNumber();
+  check_and_publish_reset( curRunNumber );
 
   // Skip this event if it is from a run prior to the one we are accumulating.
-  const auto curRunNumber = odin.runNumber();
   if ( curRunNumber < m_accRunNumber ) return;
 
-  // Handle cacheing and publication before processing the event.
-  if ( check_reset_accumulators( curRunNumber ) ) {
-    if ( check_cache_counters() ) {
-      // Copy values of accumulating counters to cache
-      cache_counters();
-
-      if ( check_publish() ) { ymlWriter(); }
-    }
-    // Reset accumulators
-    reset_accumulators( curRunNumber );
-  }
-
   // number of primary vertices
   ++m_numPrimaryVertices[pvcontainer.size()];
 
@@ -305,6 +296,25 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai
   }
 }
 
+//=============================================================================
+// Non-thread-safe resetting and publishing
+//=============================================================================
+void BeamSpotMonitor::check_and_publish_reset( unsigned curRunNumber ) const {
+  std::scoped_lock lock{m_mutex};
+
+  // Handle cacheing and publication before processing the event.
+  if ( check_reset_accumulators( curRunNumber ) ) {
+    if ( check_cache_counters() ) {
+      // Copy values of accumulating counters to cache
+      cache_counters();
+
+      if ( check_publish() ) { ymlWriter(); }
+    }
+    // Reset accumulators
+    reset_accumulators( curRunNumber );
+  }
+}
+
 //=============================================================================
 // Check for cacheing the counters
 //=============================================================================
-- 
GitLab


From 326a489d523fb30624910818b3fc9c2813b3d4a6 Mon Sep 17 00:00:00 2001
From: Patrick Spradlin <patrick.spradlin@cern.ch>
Date: Thu, 7 Mar 2024 13:45:39 +0100
Subject: [PATCH 15/15] Removed explicit 'void' argument in declarations and
 definitions of functions that take no argumnents.

---
 Tr/TrackMonitors/src/BeamSpotMonitor.cpp | 26 ++++++++++++------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
index 6841920ec79..440b07bc4b3 100644
--- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
+++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp
@@ -110,23 +110,23 @@ private:
   void check_and_publish_reset( unsigned ) const;
 
   /// Conditions for and implementation of copying accumulating ctrs to cache
-  bool check_cache_counters( void ) const;
-  void cache_counters( void ) const;
+  bool check_cache_counters() const;
+  void cache_counters() const;
 
   /// Conditions for and implementation of publication of cached conditions
-  bool       check_publish( void ) const;
+  bool       check_publish() const;
   bool       ymlFormatter( std::ostringstream& ) const;
   bool       ymlFormatter( YAML::Emitter& ) const;
-  YAML::Node yamlNode( void ) const;
-  bool       ymlWriter( void ) const;
+  YAML::Node yamlNode() const;
+  bool       ymlWriter() const;
 
   /// Conditions for value drifts
-  bool is_accum_delta_pos_over_thresh( void ) const {
+  bool is_accum_delta_pos_over_thresh() const {
     return ( std::abs( m_pvXPosCtr.mean() - m_c_pvXPosCtr.mean() ) > m_maxDeltaX ) ||
            ( std::abs( m_pvYPosCtr.mean() - m_c_pvYPosCtr.mean() ) > m_maxDeltaY ) ||
            ( std::abs( m_pvZPosCtr.mean() - m_c_pvZPosCtr.mean() ) > m_maxDeltaZ );
   }
-  bool is_accum_delta_spread_over_thresh( void ) const;
+  bool is_accum_delta_spread_over_thresh() const;
 
   /// Reset the accumulators
   bool check_reset_accumulators( const unsigned ) const;
@@ -318,7 +318,7 @@ void BeamSpotMonitor::check_and_publish_reset( unsigned curRunNumber ) const {
 //=============================================================================
 // Check for cacheing the counters
 //=============================================================================
-bool BeamSpotMonitor::check_cache_counters( void ) const {
+bool BeamSpotMonitor::check_cache_counters() const {
   return ( m_pvXPosCtr.nEntries() >= m_minPVsForCalib ) &&
          ( m_c_pvXPosCtr.nEntries() == 0 || is_accum_delta_pos_over_thresh() || is_accum_delta_spread_over_thresh() );
 }
@@ -326,7 +326,7 @@ bool BeamSpotMonitor::check_cache_counters( void ) const {
 //=============================================================================
 // Check whether to publish the cached counters
 //=============================================================================
-bool BeamSpotMonitor::check_publish( void ) const { return m_c_pvXPosCtr.nEntries() >= m_minPVsForCalib; }
+bool BeamSpotMonitor::check_publish() const { return m_c_pvXPosCtr.nEntries() >= m_minPVsForCalib; }
 
 //=============================================================================
 // Check whether to reset the accumulators
@@ -341,7 +341,7 @@ bool BeamSpotMonitor::check_reset_accumulators( const unsigned curRunNumber ) co
 //=============================================================================
 // Cache the counters
 //=============================================================================
-void BeamSpotMonitor::cache_counters( void ) const {
+void BeamSpotMonitor::cache_counters() const {
   m_c_pvXPosCtr.reset();
   m_c_pvYPosCtr.reset();
   m_c_pvZPosCtr.reset();
@@ -361,7 +361,7 @@ void BeamSpotMonitor::cache_counters( void ) const {
 //=============================================================================
 // Check whether deltas of the spread matrix have exceeded thresholds.
 //=============================================================================
-bool BeamSpotMonitor::is_accum_delta_spread_over_thresh( void ) const {
+bool BeamSpotMonitor::is_accum_delta_spread_over_thresh() const {
   return ( std::abs( m_c_pvXPosCtr.unbiased_sample_variance() - m_pvXPosCtr.unbiased_sample_variance() ) >
            m_maxDeltaXX ) ||
          ( std::abs( m_c_pvYPosCtr.unbiased_sample_variance() - m_pvYPosCtr.unbiased_sample_variance() ) >
@@ -467,7 +467,7 @@ bool BeamSpotMonitor::ymlFormatter( YAML::Emitter& yout ) const {
 // This can be a more robuse way of construction the YAML if the formatting
 // complications are resolved or determined to be irrelevant.
 //=============================================================================
-YAML::Node BeamSpotMonitor::yamlNode( void ) const {
+YAML::Node BeamSpotMonitor::yamlNode() const {
   const std::string irkey = "InteractionRegion";
   const std::string pkey  = "position";
   const std::string skey  = "spread";
@@ -493,7 +493,7 @@ YAML::Node BeamSpotMonitor::yamlNode( void ) const {
   return ir;
 }
 
-bool BeamSpotMonitor::ymlWriter( void ) const {
+bool BeamSpotMonitor::ymlWriter() const {
   std::ostringstream ymlBuff;
   if ( !ymlFormatter( ymlBuff ) ) {
     throw GaudiException( "YAML formatting of conditions failed - unable to write new conditions", name(),
-- 
GitLab