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