diff --git a/fcl/utilities/dump_tpc_channelstatus_latest_icarus.fcl b/fcl/utilities/dump_tpc_channelstatus_latest_icarus.fcl new file mode 100644 index 000000000..49e538fde --- /dev/null +++ b/fcl/utilities/dump_tpc_channelstatus_latest_icarus.fcl @@ -0,0 +1,57 @@ +# +# File: dump_tpc_channelstatus_latest_icarus.fcl +# Purpose: Dumps the channel status database for the most recent events. +# Author: Gianluca Petrillo (petrillo@slac.stanford.edu) +# Date: March 11, 2025 +# +# This job prints into a file `TPCchannelStatus-ICARUS.log` the status of +# all TPC channels in the detector. +# It uses the default timestamp "far into the future" to print the latest +# states available. +# + +#include "geometry_icarus.fcl" +#include "database_icarus.fcl" +#include "messages_icarus.fcl" + + +process_name: TPCchState + +services: { + @table::icarus_geometry_services + message: @local::icarus_message_services_interactive +} # services +services.AuxDetGeometry: @erase + +source: { + module_type: EmptyEvent + maxEvents: 0 +} + +physics: { + analyzers: { + dumpTPCstatus: { + module_type: DumpTPCchannelStatusDB + ProviderConfiguration: @local::icarus_siov_channelstatus_service.ChannelStatusProvider # from database_icarus.fcl + LogCategory: DumpTPCchannelStatusDB + } + } + + dumpers: [ dumpTPCstatus ] +} + + +# +# divert the message category "DumpTPCchannelStatusDB" from standard output +# into "TPCchannelStatus-ICARUS.log" file: +# +services.message.destinations.LogStandardOut.categories.DumpTPCchannelStatusDB: { limit: 0 } +services.message.destinations.DumpLog: { + @table::message_infofile_icarus + filename: "TPCchannelStatus-ICARUS.log" + categories: { + DumpTPCchannelStatusDB: { limit: -1 } + default: { limit: 0 } + } +} # services.message.destinations.DumpLog + diff --git a/icaruscode/TPC/Utilities/CMakeLists.txt b/icaruscode/TPC/Utilities/CMakeLists.txt index c54120393..4708f48a7 100644 --- a/icaruscode/TPC/Utilities/CMakeLists.txt +++ b/icaruscode/TPC/Utilities/CMakeLists.txt @@ -50,6 +50,17 @@ cet_build_plugin(SignalShapingICARUSService art::service LIBRARIES ${icarus_util cet_build_plugin(SIOVChannelStatusICARUSService art::service LIBRARIES ${icarus_util_lib_list}) cet_build_plugin(TFileMetadataICARUS art::service LIBRARIES ${icarus_util_lib_list}) +cet_build_plugin(DumpTPCchannelStatusDB art::producer + LIBRARIES + icaruscode::TPC_Utilities + larevt::CalibrationDBI_Providers + larevt::CalibrationDBI_IOVData + larcore::headers + larcorealg::Geometry + larcorealg::headers + larcoreobj::headers + ) + install_headers() install_source() diff --git a/icaruscode/TPC/Utilities/DumpTPCchannelStatusDB_module.cc b/icaruscode/TPC/Utilities/DumpTPCchannelStatusDB_module.cc new file mode 100644 index 000000000..b100ac988 --- /dev/null +++ b/icaruscode/TPC/Utilities/DumpTPCchannelStatusDB_module.cc @@ -0,0 +1,217 @@ +/** + * @file icaruscode/TPC/Utilities/DumpTPCchannelStatusDB_module.cc + * @brief Provides the `DumpTPCchannelStatusDB` module. + * @author Gianluca Petrillo (petrillo@slac.stanfird.edu) + * @date March 11, 2025 + * + */ + +// SBN/ICARUS libraries +#include "icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h" + +// LArSoft libraries +#include "larevt/CalibrationDBI/Providers/SIOVChannelStatusProvider.h" +#include "larevt/CalibrationDBI/IOVData/IOVDataError.h" +#include "larevt/CalibrationDBI/Interface/CalibrationDBIFwd.h" // lariov::DBTimeStamp_t + +#include "larcore/Geometry/WireReadout.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() + +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcorealg/CoreUtils/counter.h" + +#include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t + +// framework libraries +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "canvas/Utilities/Exception.h" + +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "fhiclcpp/types/Atom.h" +#include "fhiclcpp/types/DelegatedParameter.h" +#include "fhiclcpp/types/Sequence.h" +#include "fhiclcpp/types/OptionalTable.h" + + +// C/C++ standard libraries +#include // std::setw() +#include +#include + + +/** + * @brief Dumps on screen the state of all channels at specified times. + * + * Dump the content of the channel status database interfaced with + * `SIOVChannelStatusProvider`, for a series of timestamps specified in the + * configuration. + * + * The dump format is a header in the form: + * ``` + * Status of XXXX channels for N timestamps: + * ``` + * (`XXX` the total number of channels in the geometry, N the number of + * timestamps in the configuration) and then, for each timestamp: + * ``` + * === BEGIN TIMESTAMP: xxxxxxxxxxxxxxxxxxx ======================================= + * CH=0: status + * CH=1: status + * [...] + * + * Counting B BAD channels: BadCH BadCH [...] + * Counting N NOISY channels: NoisyCH NoisyCh [...] + * Counting G good channels. + * === END TIMESTAMP: xxxxxxxxxxxxxxxxxxx ======================================= + * ``` + * + * + * Timestamp format + * ----------------- + * + * The timestamp format is really defined by the database conventions. + * In ICARUS database, for example, that is in nanoseconds and in UTC. + * + * + * Dependencies + * ------------- + * + * The following services must be configured: + * * `WireReadout` (to discover the number of TPC channels in the detector). + * + * @note This module does not use the `ChannelStatusService` configured + * in the _art_ job. The reason is that it does not offer any control on + * the timestamp, but rather it binds it to the one of the input event. + * Here we need control on the timestamp, which would complicate a lot + * the workflow (we would need to generate empty events with specific + * timestamps, which should be delegated to `EmptyEvent` with a custom + * timestamp plugin where the timestamps should be inserted). + * + * + * Configuration + * -------------- + * + * * `Timestamps` (sequence of integers, default: [ `2000000000000000000` ]): + * sequence of timestamps to query about. To dump the latest settings, a safe + * timestamp is a large one like `2'000'000'000'000'000'000` (2e18, which + * is also the only timestamp in the default value). + * * `PrintIndividualChannels` (flag, default: `false`): if set, one line will + * be printed for each channel, showing its status. + * * `PrintSummary` (flag, default: `true`): if set, the list of noisy and of + * bad channels will be printed, together with a count of good channels. + * * `SIOVChannelStatusProviderConfig` (parameter table): configuration of the + * service provider of type `lariov::SIOVChannelStatusProvider` used to + * access the database. It can be copied from the official experiment one + * if the experiment normally uses that provider. + * * `LogCategory` (string, default: `DumpTPCchannelStatusDB`): messagefacility + * category stream where the information is written (`mf::LogInfo` level). + * + */ +class DumpTPCchannelStatusDB: public art::EDAnalyzer { + + public: + + using DBTimeStamp_t = lariov::DBTimeStamp_t; + + struct Config { + + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Sequence Timestamps { + Name{ "Timestamps" }, + Comment{ "timestamps to query about" }, + std::vector{ DBTimeStamp_t{ 2'000'000'000'000'000'000 } } + }; + + fhicl::OptionalTable DumperSettings { + Name{ "DumperSettings" }, + Comment{ "configuration of the dumping algorithm" } + }; + + fhicl::DelegatedParameter SIOVChannelStatusProviderConfig { + Name{ "ProviderConfiguration" }, + Comment{ "full configuration of a service provider" } + }; + + fhicl::Atom LogCategory { + Name{ "LogCategory" }, + Comment{ "name of the messagefacility category to send output to" }, + "DumpTPCchannelStatusDB" + }; + + }; // Config + + using Parameters = art::EDAnalyzer::Table; + + + DumpTPCchannelStatusDB(Parameters const& params); + + + /// Dumps the content of the channel status database. + virtual void beginJob() override; + + /// Does nothing (but it is required). + virtual void analyze(art::Event const&) override {} + + + private: + + // --- BEGIN --- Configuration parameters ---------------------------------- + + std::vector const fTimestamps; ///< Timestamps to query. + + std::string const fLogCategory; ///< Messagefacility category to write into. + + // --- END ----- Configuration parameters ---------------------------------- + + // --- BEGIN --- Cached service information -------------------------------- + + /// Channel status service provider. + lariov::SIOVChannelStatusProvider fChannelStatus; + + // --- END --- Cached service information -------------------------------- + + lariov::TPCSIOVchannelStatusDBdumper fDumper; ///< The dumping algorithm. + +}; // class DumpTPCchannelStatusDB + + +// ----------------------------------------------------------------------------- +// --- Implementation +// ----------------------------------------------------------------------------- +DumpTPCchannelStatusDB::DumpTPCchannelStatusDB(Parameters const& params) + : art::EDAnalyzer{ params } + , fTimestamps{ params().Timestamps() } + , fLogCategory{ params().LogCategory() } + , fChannelStatus + { params().SIOVChannelStatusProviderConfig.get() } + , fDumper{ + params().DumperSettings().value_or(lariov::TPCSIOVchannelStatusDBdumper::Config{}), + fChannelStatus, + art::ServiceHandle()->Get().Nchannels() + } +{ +} + + +// ----------------------------------------------------------------------------- +void DumpTPCchannelStatusDB::beginJob() { + + mf::LogVerbatim{ fLogCategory } + << "Status of " << fDumper.nChannels() << " channels for " + << fTimestamps.size() << " timestamps:"; + + for (DBTimeStamp_t const timestamp: fTimestamps) { + mf::LogVerbatim{ fLogCategory } << fDumper.timestampToStream(timestamp); + } + +} // DumpTPCchannelStatusDB::beginJob() + + +// ----------------------------------------------------------------------------- +DEFINE_ART_MODULE(DumpTPCchannelStatusDB) + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.cxx b/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.cxx new file mode 100644 index 000000000..cd4089c8a --- /dev/null +++ b/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.cxx @@ -0,0 +1,70 @@ +/** + * @file icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.cxx + * @brief Provides the `TPCSIOVchannelStatusDBdumper` algorithm. + * @author Gianluca Petrillo (petrillo@slac.stanfird.edu) + * @date March 11, 2025 + * @see icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h + * + */ + +// library header +#include "icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h" + +// LArSoft libraries +#include "larevt/CalibrationDBI/IOVData/IOVDataError.h" + +// C/C++ standard libraries +#include +#include + + +// ----------------------------------------------------------------------------- +// --- lariov::TPCSIOVchannelStatusDBdumper +// ----------------------------------------------------------------------------- +lariov::TPCSIOVchannelStatusDBdumper::TPCSIOVchannelStatusDBdumper( + Config const& config, + lariov::SIOVChannelStatusProvider& channelStatus, unsigned int nChannels +) + : fChannelStatus{ channelStatus } + , fDumper{ config.TPCchannelStatusDBdumperConfig(), channelStatus, nChannels } +{ +} + + +// ----------------------------------------------------------------------------- +void lariov::TPCSIOVchannelStatusDBdumper::dumpTimestamp + (std::ostream& out, DBTimeStamp_t timestamp) const +{ + fChannelStatus.UpdateTimeStamp(timestamp); + + out << "=== BEGIN TIMESTAMP: " + << std::setw(19) << timestamp << " " << std::string(39, '='); + + dumpCurrentTimestamp(out); + + out << "\n=== END TIMESTAMP: " + << std::setw(19) << timestamp << " " << std::string(39, '='); + +} // TPCSIOVchannelStatusDBdumper::dumpTimestamp() + + +// ----------------------------------------------------------------------------- +void lariov::TPCSIOVchannelStatusDBdumper::dumpCurrentTimestamp + (std::ostream& out) const +{ + + fDumper.dump(out); + +} // TPCSIOVchannelStatusDBdumper::dumpCurrentTimestamp() + + +// ----------------------------------------------------------------------------- +std::ostream& lariov::operator<< + (std::ostream& out, TPCSIOVchannelStatusDBdumper::timestampDump dumpInfo) +{ + dumpInfo.dump(out); + return out; +} + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h b/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h new file mode 100644 index 000000000..8b2c3855d --- /dev/null +++ b/icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h @@ -0,0 +1,186 @@ +/** + * @file icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.h + * @brief Defines the `lariov::TPCSIOVchannelStatusDBdumper` algorithm. + * @author Gianluca Petrillo (petrillo@slac.stanfird.edu) + * @date March 11, 2025 + * @see icaruscode/TPC/Utilities/TPCSIOVchannelStatusDBdumper.cxx + * + */ + +#ifndef ICARUSCODE_TPC_UTILITIES_TPCSIOVCHANNELSTATUSDBDUMPER_H +#define ICARUSCODE_TPC_UTILITIES_TPCSIOVCHANNELSTATUSDBDUMPER_H + +// SBN/ICARUS libraries +#include "icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h" + +// LArSoft libraries +#include "larevt/CalibrationDBI/Providers/SIOVChannelStatusProvider.h" +#include "larevt/CalibrationDBI/Interface/CalibrationDBIFwd.h" // lariov::DBTimeStamp_t + +// framework libraries +#include "fhiclcpp/types/TableFragment.h" + +// C/C++ standard libraries +#include + + +// ----------------------------------------------------------------------------- +namespace lariov { class TPCSIOVchannelStatusDBdumper; } +/** + * @brief Dumps on screen the state of all channels at specified times. + * + * Dumps the content of the channel status database interfaced with + * `SIOVChannelStatusProvider`, for a series of timestamps specified in the + * configuration. + * + * The dump is format is a header in the form: + * ``` + * Status of XXXX channels for N timestamps: + * ``` + * (`XXX` the total number of channels in the geometry, N the number of + * timestamps in the configuration) and then, for each timestamp: + * ``` + * === BEGIN TIMESTAMP: xxxxxxxxxxxxxxxxxxx ======================================= + * CH=0: status + * CH=1: status + * [...] + * + * Counting B BAD channels: BadCH BadCH [...] + * Counting N NOISY channels: NoisyCH NoisyCh [...] + * Counting G good channels. + * === END TIMESTAMP: xxxxxxxxxxxxxxxxxxx ======================================= + * ``` + * + * + * Timestamp format + * ----------------- + * + * The timestamp format is really defined by the database conventions. + * In ICARUS database, for example, that is in nanoseconds and in UTC. + * + * + * Configuration + * -------------- + * + * + * * `PrintIndividualChannels` (flag, default: `false`): if set, one line will + * be printed for each channel, showing its status. + * * `PrintSummary` (flag, default: `true`): if set, the list of noisy and of + * bad channels will be printed, together with a count of good channels. + * + */ +class lariov::TPCSIOVchannelStatusDBdumper { + + public: + + using DBTimeStamp_t = lariov::DBTimeStamp_t; + + struct Config { + + // using Name = fhicl::Name; + // using Comment = fhicl::Comment; + + fhicl::TableFragment + TPCchannelStatusDBdumperConfig; + + // no further configuration so far + + }; // Config + + + /// Configures and sets up the algorithm. + TPCSIOVchannelStatusDBdumper( + Config const& config, + lariov::SIOVChannelStatusProvider& channelStatus, unsigned int nChannels + ); + + /// Returns the configured number of channels. + unsigned int nChannels() const { return fDumper.nChannels(); } + + /** + * @brief Dumps all the information on channels at the given `timestamp`. + * @param out the output stream to write information into + * @param timestamp the timestamp to snapshot the channel status at + * + * @note While this method is `const` and does not change this object, it may + * (and usually does) change the state of the service provider that it + * was passed at construction. + * + */ + void dumpTimestamp(std::ostream& out, DBTimeStamp_t timestamp) const; + + /// Dumps all the information on channels at the timestamp set in the provider. + void dumpCurrentTimestamp(std::ostream& out) const; + + + /** + * @brief Enables dumps into `std::ostream`. + * @param timestamp the timestamp to dump the channel status at + * @return an opaque object that will trigger the dump + * + * Example (with `dumper` an instance of `TPCSIOVchannelStatusDBdumper`): + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * std::cout << dumper.timestampToStream(1'650'000'000'000'000'000); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * It is equivalent to `dumpTimestamp()`: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * dumper.dumpTimestamp(std::cout, 1'650'000'000'000'000'000); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + auto timestampToStream(DBTimeStamp_t timestamp) const; + + + private: + + // --- BEGIN --- Configuration parameters ---------------------------------- + + // --- END ----- Configuration parameters ---------------------------------- + + // --- BEGIN --- Cached service information -------------------------------- + + /// Channel status service provider. + lariov::SIOVChannelStatusProvider& fChannelStatus; + + // --- END --- Cached service information -------------------------------- + + lariov::TPCchannelStatusDBdumper const fDumper; ///< Inner dumper algorithm. + + + /// Helper structure for insertion in `std::ostream`. + struct timestampDump { + TPCSIOVchannelStatusDBdumper const* dumper = nullptr; + DBTimeStamp_t timestamp = 0; + + void dump(std::ostream& out) const { dumper->dumpTimestamp(out, timestamp); } + }; + + friend std::ostream& operator<< + (std::ostream&, TPCSIOVchannelStatusDBdumper::timestampDump); + +}; // class lariov::TPCSIOVchannelStatusDBdumper + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +namespace lariov { + + /// Helper function for insertion. + /// @see `lariov::TPCSIOVchannelStatusDBdumper::timestampToStream()` + std::ostream& operator<< + (std::ostream&, TPCSIOVchannelStatusDBdumper::timestampDump); + +} // namespace lariov + + +// ----------------------------------------------------------------------------- +// --- Inline definitions +// ----------------------------------------------------------------------------- +inline auto lariov::TPCSIOVchannelStatusDBdumper::timestampToStream + (DBTimeStamp_t timestamp) const +{ + return timestampDump{ this, timestamp }; +} + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_TPC_UTILITIES_TPCSIOVCHANNELSTATUSDBDUMPER_H diff --git a/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.cxx b/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.cxx new file mode 100644 index 000000000..91ed47e4f --- /dev/null +++ b/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.cxx @@ -0,0 +1,125 @@ +/** + * @file icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.cxx + * @brief Provides the `TPCchannelStatusDBdumper` algorithm. + * @author Gianluca Petrillo (petrillo@slac.stanfird.edu) + * @date March 11, 2025 + * @see icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h + * + */ + +// library header +#include "icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h" + +// LArSoft libraries +#include "larevt/CalibrationDBI/IOVData/IOVDataError.h" + +#include "larcorealg/CoreUtils/counter.h" + +#include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t + +// framework libraries +#include "canvas/Utilities/Exception.h" + +// C/C++ standard libraries +#include + + +// ----------------------------------------------------------------------------- +// --- lariov::TPCchannelStatusDBdumper +// ----------------------------------------------------------------------------- +lariov::TPCchannelStatusDBdumper::TPCchannelStatusDBdumper( + Config const& config, + lariov::ChannelStatusProvider& channelStatus, unsigned int nChannels +) + : fPrintChannels{ config.PrintIndividualChannels() } + , fPrintSummary { config.PrintSummary() } + , fNChannels { nChannels } + , fChannelStatus{ channelStatus } +{ + if (!fPrintSummary && !fPrintChannels) { + throw art::Exception{ art::errors::Configuration } + << "All printing options have been disabled."; + } +} + + +// ----------------------------------------------------------------------------- +void lariov::TPCchannelStatusDBdumper::dump(std::ostream& out) const { + unsigned int nErrors = 0; + if (fPrintChannels) { + for (raw::ChannelID_t const channel: util::counter(fNChannels)) { + + out << "\nCH=" << channel << ": "; + try { + if (!fChannelStatus.IsPresent(channel)) out << "NOT PRESENT"; + else if (fChannelStatus.IsBad (channel)) out << "BAD"; + else if (fChannelStatus.IsNoisy (channel)) out << "NOISY"; + else if (fChannelStatus.IsGood (channel)) out << "good"; + else + out << "UNKNOWN STATUS (code=" << fChannelStatus.Status(channel) << ")"; + } + catch(lariov::IOVDataError const& e) { + out << "ERROR: " << e.what(); + ++nErrors; + } + } + } // if print channels + + if (fPrintSummary) { + if (fPrintChannels) out << "\n"; + + try { + lariov::ChannelStatusProvider::ChannelSet_t const& badChannels + = fChannelStatus.BadChannels(); + out << "\nCounting " << badChannels.size() << " BAD channels"; + if (badChannels.empty()) out << "."; + else { + out << ":"; + for (raw::ChannelID_t const channel: badChannels) out << " " << channel; + } + } + catch(lariov::IOVDataError const&) { + out << "\nCount of NOISY channels not available."; + } + + try { + lariov::ChannelStatusProvider::ChannelSet_t const& noisyChannels + = fChannelStatus.NoisyChannels(); + out << "\nCounting " << noisyChannels.size() << " NOISY channels"; + if (noisyChannels.empty()) out << "."; + else { + out << ":"; + for (raw::ChannelID_t const channel: noisyChannels) out << " " << channel; + } + } + catch(lariov::IOVDataError const&) { + out << "\nCount of BAD channels not available."; + } + + try { + lariov::ChannelStatusProvider::ChannelSet_t const& goodChannels + = fChannelStatus.GoodChannels(); + out << "\nCounting " << goodChannels.size() << " good channels."; + } + catch(lariov::IOVDataError const&) { + out << "\nCount of good channels not available."; + } + + if (nErrors > 0) { + out << "\nEncountered errors querying " << nErrors << "/" << fNChannels + << " channels."; + } + } // if print summary + +} // TPCchannelStatusDBdumper::dumpCurrentTimestamp() + + +// ----------------------------------------------------------------------------- +std::ostream& lariov::operator<< + (std::ostream& out, TPCchannelStatusDBdumper::dumpStruct dumpInfo) +{ + dumpInfo.dump(out); + return out; +} + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h b/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h new file mode 100644 index 000000000..2377d552c --- /dev/null +++ b/icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h @@ -0,0 +1,168 @@ +/** + * @file icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.h + * @brief Defines the `lariov::TPCchannelStatusDBdumper` algorithm. + * @author Gianluca Petrillo (petrillo@slac.stanfird.edu) + * @date March 11, 2025 + * @see icaruscode/TPC/Utilities/TPCchannelStatusDBdumper.cxx + * + */ + +#ifndef ICARUSCODE_TPC_UTILITIES_TPCCHANNELSTATUSDBDUMPER_H +#define ICARUSCODE_TPC_UTILITIES_TPCCHANNELSTATUSDBDUMPER_H + +// LArSoft libraries +#include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h" + +// framework libraries +#include "fhiclcpp/types/Atom.h" + +// C/C++ standard libraries +#include + + +// ----------------------------------------------------------------------------- +namespace lariov { class TPCchannelStatusDBdumper; } +/** + * @brief Dumps on screen the state of all channels at specified times. + * + * Dumps the content of the channel status database interfaced with + * `ChannelStatusProvider`. + * + * This algorithm dumps the status at the time previously selected in the + * service provider. It may be used with `ChannelStatusService` service managed + * by _art_. + * If control on which timestamp to dump is needed, and the service provider in + * use is derived from `lariov::SIOVChannelStatusProvider`, then the algorithm + * `lariov::TPCSIOVchannelStatusDBdumper` can be used instead. + * + * The dump format is in the form: + * ``` + * CH=0: status + * CH=1: status + * [...] + * + * Counting B BAD channels: BadCH BadCH [...] + * Counting N NOISY channels: NoisyCH NoisyCh [...] + * Counting G good channels. + * ``` + * where the first part is printed if `PrintIndividualChannels` is set, while + * the second part is printed if `PrintSummary` is set. + * + * + * Configuration + * -------------- + * + * * `PrintIndividualChannels` (flag, default: `false`): if set, one line will + * be printed for each channel, showing its status. + * * `PrintSummary` (flag, default: `true`): if set, the list of noisy and of + * bad channels will be printed, together with a count of good channels. + * + */ +class lariov::TPCchannelStatusDBdumper { + + public: + + struct Config { + + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Atom PrintIndividualChannels { + Name{ "PrintIndividualChannels" }, + Comment{ "print one status line per channel" }, + false + }; + + fhicl::Atom PrintSummary { + Name{ "PrintSummary" }, + Comment{ "print a summary with the list of non-good channels" }, + true + }; + + }; // Config + + + /// Configures and sets up the algorithm. + TPCchannelStatusDBdumper( + Config const& config, + lariov::ChannelStatusProvider& channelStatus, unsigned int nChannels + ); + + /// Returns the configured number of channels. + unsigned int nChannels() const { return fNChannels; } + + /// Dumps all the information on channels at the timestamp set in the provider. + void dump(std::ostream& out) const; + + + /** + * @brief Enables dumps into `std::ostream`. + * @return an opaque object that will trigger the dump + * + * Example (with `dumper` an instance of `TPCchannelStatusDBdumper`): + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * std::cout << dumper.toStream(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * It is equivalent to `dumpTimestamp()`: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * dumper.dumpTimestamp(std::cout); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * (but the latter will not work with other loggers like `mf::LogInfo`). + */ + auto toStream() const; + + + private: + + // --- BEGIN --- Configuration parameters ---------------------------------- + + bool const fPrintChannels; ///< Print individual channels. + + bool const fPrintSummary; ///< Print non-good channel summary. + + // --- END ----- Configuration parameters ---------------------------------- + + // --- BEGIN --- Cached service information -------------------------------- + unsigned int const fNChannels; ///< Number of TPC channels in the detector. + + /// Channel status service provider. + lariov::ChannelStatusProvider const& fChannelStatus; + + // --- END --- Cached service information -------------------------------- + + /// Helper structure for insertion in `std::ostream`. + struct dumpStruct { + TPCchannelStatusDBdumper const* dumper = nullptr; + + void dump(std::ostream& out) const { dumper->dump(out); } + }; + + friend std::ostream& operator<< + (std::ostream&, TPCchannelStatusDBdumper::dumpStruct); + +}; // class lariov::TPCchannelStatusDBdumper + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +namespace lariov { + + /// Helper function for insertion. + /// @see `lariov::TPCchannelStatusDBdumper::toStream()` + std::ostream& operator<< + (std::ostream&, TPCchannelStatusDBdumper::dumpStruct); + +} // namespace lariov + + +// ----------------------------------------------------------------------------- +// --- Inline definitions +// ----------------------------------------------------------------------------- +inline auto lariov::TPCchannelStatusDBdumper::toStream() const +{ + return dumpStruct{ this }; +} + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_TPC_UTILITIES_TPCCHANNELSTATUSDBDUMPER_H