diff --git a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp index ecf6852bf0b7e5d03d528cfb8b3b36b9800b5150..ce3958431460bfed583e8c385ebec74314bb19b0 100644 --- a/Tr/TrackMonitors/src/BeamSpotMonitor.cpp +++ b/Tr/TrackMonitors/src/BeamSpotMonitor.cpp @@ -11,12 +11,14 @@ #include "Event/ODIN.h" #include "Event/RecVertex.h" +#include "LHCbDet/InteractionRegion.h" #include #include #include #include #include +#include #include #include #include @@ -34,6 +36,9 @@ namespace { /// Meta-enum for directing how to handle inconceivably large differences meta_enum_class( IncHandType, int, Unknown = 0, WarnUpdate, WarnSkip, ExceptionThrow ); + /// Meta-enum for handling initialization and external updates of IRConditions + meta_enum_class( IRCondInitStrat, int, Unknown = 0, Autonomous, FromDBFile, FromCond ); + /// Unbiased sample covariance calculator for off-diagonals template auto calculate_spread_offdiag( X const& x, X const& y, XX const& xy ) { @@ -79,7 +84,10 @@ namespace { } // namespace -class BeamSpotMonitor : public LHCb::Algorithm::Consumer { +class BeamSpotMonitor + : public LHCb::Algorithm::Consumer> { public: SmartIF m_publishSvc; @@ -88,7 +96,8 @@ public: BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLocator ); /// Algorithm execute - void operator()( LHCb::ODIN const&, PVView const& pvcontainer ) const override; + void operator()( LHCb::ODIN const&, PVView const& pvcontainer, + LHCb::Conditions::InteractionRegion const& ) const override; /// Initialization and finalization StatusCode initialize() override; @@ -105,6 +114,7 @@ public: /// Cache variables unsigned nPVs{ 0 }; unsigned runNumber{ 0 }; + int dbFileVer{ -1 }; std::array position{ 0.0, 0.0, 0.0 }; std::array spread{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; @@ -121,8 +131,13 @@ private: /// Initialize histograms that have configuration properties, like axis limts void init_configurable_histos() const; + /// Initialize/update cache from the external sources + bool init_cache_from_dbfile( bool log = false ) const; + bool init_cache_from_ircond( LHCb::Conditions::InteractionRegion const&, unsigned runnum = 0, + bool log = false ) const; + /// Non-thread-safe part of the event loop --- resetting and publishing - void check_and_publish_reset( LHCb::ODIN const& ) const; + void check_and_publish_reset( LHCb::ODIN const&, LHCb::Conditions::InteractionRegion const& ) const; /// Conditions for and implementation of copying accumulating ctrs to cache bool check_cache_counters( LHCb::ODIN const& ) const; @@ -222,6 +237,14 @@ private: // Output configuration properties //........................................................................... + /// Initialization strategy. Also controls interactions with independent + /// producers of IRConditions + // meta_enum_class( IRCondInitStrat, int, Unknown = 0, Autonomous, FromDBFile, FromCond); + Gaudi::Property m_initStrat{ + this, "IRCondInitStrategy", IRCondInitStrat::Autonomous, + "How to initialize internal IR conditions reference and track independent producers of IR conditions. Allowed " + "values are 'Autonomous', 'FromDBFile', and 'FromCond'" }; + /// Report conditions to log (INFO) Gaudi::Property m_condToLog{ this, "LogConditions", false, "Write conditions to logfile with level INFO when updating" }; @@ -418,13 +441,18 @@ BeamSpotMonitor::BeamSpotMonitor( const std::string& name, ISvcLocator* pSvcLoca : Consumer{ name, pSvcLocator, { KeyValue{ "ODINLocation", LHCb::ODINLocation::Default }, - KeyValue{ "PVContainer", LHCb::RecVertexLocation::Primary } } } {} + KeyValue{ "PVContainer", LHCb::RecVertexLocation::Primary }, + KeyValue{ "InteractionRegionCache", "AlgorithmSpecific-" + name + "-InteractionRegion" } } } {} //============================================================================= /// Initialization //============================================================================= StatusCode BeamSpotMonitor::initialize() { return Consumer::initialize().andThen( [&] { + // This is only needed to have a fallback in case the IR condition does not exist. + LHCb::Conditions::InteractionRegion::addConditionDerivation( this, + inputLocation() ); + init_configurable_histos(); // Check configured threshold @@ -475,18 +503,6 @@ StatusCode BeamSpotMonitor::initialize() { if ( !std::filesystem::exists( conditions_dir ) ) { std::filesystem::create_directories( conditions_dir ); if ( msgLevel( MSG::DEBUG ) ) debug() << "Created " << conditions_dir.string() << endmsg; - } else { // Try to initialize cache from most recent conditions - const auto max_version_nr = find_max_version_number( conditions_dir ); - if ( max_version_nr >= 0 ) { - const std::filesystem::path conditions_file = conditions_dir / ( "v" + std::to_string( max_version_nr ) ); - - info() << "Initializing cache from conditions file " << conditions_file.string() << endmsg; - m_cache.loadYAMLFile( conditions_file ); - - YAML::Emitter condEmi; - m_cache.emitYAML( condEmi ); - info() << "Cache initialized from file with contents:\n" << condEmi.c_str() << endmsg; - } } } catch ( const std::filesystem::filesystem_error& expt ) { // TODO: consider whether this is a recoverable condition. @@ -504,6 +520,10 @@ StatusCode BeamSpotMonitor::initialize() { m_publishSvc->declarePubItem( m_pubErrorTo, m_pub_error ); } } + + if ( m_initStrat == IRCondInitStrat::FromDBFile && !init_cache_from_dbfile( true ) ) { + warning() << "Attempt to initialize cached reference conditions from DB file failed" << endmsg; + } } ); } @@ -516,7 +536,7 @@ StatusCode BeamSpotMonitor::stop() { return StatusCode::SUCCESS; } -/// Initialize histograms that depende on properties +/// Initialize histograms that depend on properties void BeamSpotMonitor::init_configurable_histos() const { using axis1D = Gaudi::Accumulators::Axis; @@ -644,11 +664,65 @@ void BeamSpotMonitor::init_configurable_histos() const { ( m_histIRCondSpreadZZMax - m_histIRCondSpreadZZMin ) / 2 } ); } +/// Initialize/update cache from the most recent DB file +bool BeamSpotMonitor::init_cache_from_dbfile( bool log ) const { + 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 ); + if ( max_version_nr >= 0 ) { + // Reload if DB v number has changed. + if ( max_version_nr != m_cache.dbFileVer ) { + const std::filesystem::path conditions_file = conditions_dir / ( "v" + std::to_string( max_version_nr ) ); + + if ( log ) info() << "Initializing cache from conditions file " << conditions_file.string() << endmsg; + + m_cache.loadYAMLFile( conditions_file ); + m_cache.dbFileVer = max_version_nr; + + if ( log ) { + YAML::Emitter condEmi; + m_cache.emitYAML( condEmi ); + + info() << "Cache initialized from file with contents:\n" << condEmi.c_str() << endmsg; + } + } + return true; + } + return false; +} + +/// Initialize/update cache from InteractionRegion conditions +bool BeamSpotMonitor::init_cache_from_ircond( LHCb::Conditions::InteractionRegion const& ircond, unsigned runnum, + bool log ) const { + + if ( log ) info() << "Initializing cache from run-time conditions" << endmsg; + + ircond.avgPosition.GetCoordinates( m_cache.position.begin(), m_cache.position.end() ); + std::copy( ircond.spread.begin(), ircond.spread.end(), m_cache.spread.begin() ); + m_cache.runNumber = runnum; + m_cache.nPVs = 1; + m_cache.dbFileVer = -1; + + if ( log ) { + YAML::Emitter condEmi; + m_cache.emitYAML( condEmi ); + + info() << "Cache initialized from run-time conditions with values:\n" << condEmi.c_str() << endmsg; + } + return true; +} + //============================================================================= // Algorithm execution //============================================================================= -void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontainer ) const { - check_and_publish_reset( odin ); +void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontainer, + LHCb::Conditions::InteractionRegion const& ircond ) const { + std::scoped_lock lock{ m_mutex }; + // Initialize the cache, if it has not been done yet. + if ( m_cache.nPVs == 0 && m_initStrat == IRCondInitStrat::FromCond ) { + init_cache_from_ircond( ircond, odin.runNumber(), true ); + } + check_and_publish_reset( odin, ircond ); // Skip this event if it is from a run prior to the one we are accumulating. if ( odin.runNumber() < m_accRunNumber ) return; @@ -696,12 +770,18 @@ void BeamSpotMonitor::operator()( LHCb::ODIN const& odin, PVView const& pvcontai //============================================================================= // Non-thread-safe resetting and publishing //============================================================================= -void BeamSpotMonitor::check_and_publish_reset( LHCb::ODIN const& odin ) const { - std::scoped_lock lock{ m_mutex }; - +void BeamSpotMonitor::check_and_publish_reset( LHCb::ODIN const& odin, + LHCb::Conditions::InteractionRegion const& ircond ) const { // Handle cacheing and publication before processing the event. const auto curRunNumber = odin.runNumber(); if ( check_reset_accumulators( curRunNumber ) ) { + // Update the cache from external source + if ( m_initStrat == IRCondInitStrat::FromDBFile ) { + init_cache_from_dbfile(); + } else if ( m_initStrat == IRCondInitStrat::FromCond ) { + init_cache_from_ircond( ircond, odin.runNumber() ); + } + if ( check_cache_counters( odin ) ) { // Copy values of accumulating counters to cache cache_counters(); @@ -757,6 +837,7 @@ bool BeamSpotMonitor::check_reset_accumulators( const unsigned curRunNumber ) co // Cache the counters //============================================================================= void BeamSpotMonitor::cache_counters() const { + m_cache.dbFileVer = -1; // Not based on a file. m_cache.nPVs = m_pvXPosCtr.nEntries(); m_cache.runNumber = m_accRunNumber; @@ -1018,6 +1099,7 @@ bool BeamSpotMonitor::ymlWriter() const { info() << "Writing new conditions file " << full_conditions_path.string() << endmsg; // Outfile. + m_cache.dbFileVer = max_version_nr + 1; std::ofstream logging( full_conditions_path.string().c_str() ); logging << ymlBuff.c_str() << std::endl; logging.close();