From 8456f718a0550d7613df17dfe7801d5b2b5b66d3 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Tue, 20 Feb 2024 20:35:39 -0600 Subject: [PATCH 01/19] Decoder channel mapping: added interface documentation and full mapping dump Except for CRT calibration information. --- .../Decode/ChannelMapping/IICARUSChannelMap.h | 124 ++++++++++--- .../ChannelMapping/PMTChannelMapDumper.cxx | 170 ++++++++++++++++-- 2 files changed, 253 insertions(+), 41 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h b/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h index 6374422b3..378a6fd1a 100644 --- a/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h +++ b/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h @@ -1,23 +1,20 @@ -/////////////////////////////////////////////////////////////////////// -/// -/// \file IICARUSChannelMap -/// -/// \brief Interface class for hardware/software channel mapping -/// for ICARUS -/// -/// \author T. Usher -/// -//////////////////////////////////////////////////////////////////////// - -#ifndef IICARUSChannelMap_H -#define IICARUSChannelMap_H +/** + * @file icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h + * @brief Interface class for hardware/software channel mapping for ICARUS. + * @author T. Usher + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAP_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAP_H #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" #include "art/Framework/Services/Registry/ServiceDeclarationMacros.h" #include +#include #include +#include namespace icarusDB { @@ -39,41 +36,110 @@ class IICARUSChannelMap //: private lar::EnsureOnlyOneSchedule virtual ~IICARUSChannelMap() noexcept = default; + /// --- BEGIN --- Data period selection ------------------------------------ + /// @name Data period selection + /// @{ + /// Loads the mapping for `run`, returns whether a new mapping was loaded. virtual bool forRun(int run) = 0; /// Loads the mapping for `period`, returns whether a new mapping was loaded. virtual bool forPeriod(icarusDB::RunPeriod period) = 0; - // Section to access fragment to board mapping - virtual bool hasFragmentID(const unsigned int) const = 0; + /// @} + /// --- END ----- Data period selection ------------------------------------ + + + /// --- BEGIN --- TPC information ------------------------------------------ + /// @name TPC information + /// @{ + + /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - + /// @name TPC fragment information + /// @{ + + /// Returns whether the specified `ID` is a known TPC fragment ID. + virtual bool hasFragmentID(const unsigned int ID) const = 0; /// Returns the number of TPC fragment IDs known to the service. + + /// Returns the number of known TPC fragments. virtual unsigned int nTPCfragmentIDs() const = 0; - virtual const std::string& getCrateName(const unsigned int) const = 0; - virtual const ReadoutIDVec& getReadoutBoardVec(const unsigned int) const = 0; + + /// Returns the name of the crate served by the specified `fragmentID`. + virtual const std::string& getCrateName(const unsigned int fragmentID) const = 0; + + /// Returns the list of board IDs included in the specified `fragmentID`. + virtual const ReadoutIDVec& getReadoutBoardVec(const unsigned int fragmentID) const = 0; + + /// @} + /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - + + /** + * @brief Returns the full TPC channel mapping. + * + * The returned mapping is an associative container, associating each board + * ID (`boardID`) to the following information (in a `std::tuple`): + * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) + * * `[1]` list of channels served by the board, and their plane + * (like `getChannelPlanePair(boardID)`) + * + */ virtual const TPCReadoutBoardToChannelMap& getReadoutBoardToChannelMap() const = 0; - - // Section to access channel information for a given board - virtual bool hasBoardID(const unsigned int) const = 0; + + /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - + /// @name TPC board information + /// @{ + + /// Returns whether there is a board with the specified `ID`. + virtual bool hasBoardID(const unsigned int ID) const = 0; /// Returns the number of TPC board IDs known to the service. virtual unsigned int nTPCboardIDs() const = 0; - virtual unsigned int getBoardSlot(const unsigned int) const = 0; - virtual const ChannelPlanePairVec& getChannelPlanePair(const unsigned int) const = 0; + /// Returns the number of slot the `boardID` is on. + virtual unsigned int getBoardSlot(const unsigned int boardID) const = 0; + /// Returns a list of channels served by the `boardID` and for each the plane it is on (`0` to `2`). + virtual const ChannelPlanePairVec& getChannelPlanePair(const unsigned int boardID) const = 0; - // Section for recovering PMT information - virtual bool hasPMTDigitizerID(const unsigned int) const = 0; - /// Returns the number of PMT fragment IDs known to the service. + /// @} + /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - + + + /// --- BEGIN --- PMT information ------------------------------------------ + /// @name PMT information + /// @{ + + /// Returns whether the specified fragment `ID` is known to the mapping. + virtual bool hasPMTDigitizerID(const unsigned int ID) const = 0; + + /// Returns the number of PMT fragment IDs known to the mapping. virtual unsigned int nPMTfragmentIDs() const = 0; + + /// Returns a list of triplets: virtual const DigitizerChannelChannelIDPairVec& getChannelIDPairVec(const unsigned int) const = 0; + + /// @} + /// --- END ----- PMT information ------------------------------------------ + - virtual unsigned int getSimMacAddress(const unsigned int) const = 0; + /// --- BEGIN --- CRT information ------------------------------------------ + /// @name CRT information + /// @{ + + /// Returns the sim Mac address corresponding to the specified side CRT hardware address. + virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const = 0; + /// Returns the sim Mac address corresponding to the specified top CRT hardware address. virtual unsigned int gettopSimMacAddress(const unsigned int) const = 0; + /// Returns the Gain and Pedestal for Side CRT. virtual std::pair getSideCRTCalibrationMap(int mac5, int chan) const = 0; -}; + + /// @} + /// --- END ----- CRT information ------------------------------------------ + +}; // IICARUSChannelMap -} // end of namespace +} // namespace icarusDB DECLARE_ART_SERVICE_INTERFACE(icarusDB::IICARUSChannelMap, SHARED) -#endif + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAP_H diff --git a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx index 7c4e31c0b..68a40f832 100644 --- a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx @@ -4,7 +4,7 @@ * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * * This utility can be run with any configuration file including a configuration - * for `IICARUSChannel` service. + * for `IICARUSChannelMap` service. * * It is using _art_ facilities for tool loading, but it does not run in _art_ * environment. So it may break without warning and without solution. @@ -18,6 +18,7 @@ // LArSoft and framework libraries #include "larcorealg/CoreUtils/enumerate.h" +#include "larcorealg/CoreUtils/counter.h" #include "larcorealg/TestUtils/unit_test_base.h" #include "messagefacility/MessageLogger/MessageLogger.h" @@ -48,49 +49,194 @@ struct SortByElement { // ----------------------------------------------------------------------------- -void dumpMapping(icarusDB::ICARUSChannelMapProvider const& channelMapping) { +/// Helper to split text in rows. +class Pager { + unsigned int fLinesPerPage; + + unsigned int fLinesLeft = 1; + + public: + Pager(unsigned int linesPerPage): fLinesPerPage{ linesPerPage } {} + + /// Increments the number of line and says if it starts on a new page. + bool nextHasNewLine() + { + if (--fLinesLeft) return false; + fLinesLeft = fLinesPerPage; + return true; + } + bool operator() () { return nextHasNewLine(); } + +}; // Pager + + +// ----------------------------------------------------------------------------- +void dumpTPCmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { + + // TODO + + constexpr unsigned int FragmentIDoffset = 0x1000; + + mf::LogVerbatim log("PMTchannelMappingDumper"); + + // by fragment + unsigned int nFragmentIDs = mapping.nTPCfragmentIDs(); + log << "Reported " << nFragmentIDs << " TPC fragment IDs."; + unsigned int nFragmentsFound = 0; + for ( + unsigned int fragmentID = FragmentIDoffset; + nFragmentsFound < nFragmentIDs; + ++fragmentID + ) { + + if (!mapping.hasFragmentID(fragmentID)) continue; + ++nFragmentsFound; + + icarusDB::ReadoutIDVec const& boardIDs + = mapping.getReadoutBoardVec(fragmentID); + + log << "\nFragment ID 0x" << std::hex << fragmentID << std::dec + << " on crate " << mapping.getCrateName(fragmentID) << " has " + << boardIDs.size() << " boards:"; + for (unsigned int boardID: boardIDs) log << " " << boardID; + + } // for fragment + + // by board + unsigned int const nBoards = mapping.nTPCboardIDs(); + log << "\n\nReported " << nBoards << " TPC readout board IDs."; + unsigned int nFoundBoards = 0; + for (unsigned int boardID = 0; nFoundBoards < nBoards; ++boardID) { + + if (!mapping.hasBoardID(boardID)) continue; + ++nFoundBoards; + + /// Returns the number of TPC board IDs known to the service. + unsigned int const slot = mapping.getBoardSlot(boardID); + + icarusDB::ChannelPlanePairVec const& channelPlanes + = mapping.getChannelPlanePair(boardID); + log << "\nBoard " << boardID << " on slot #" << slot << " has " + << channelPlanes.size() << " channels:"; + Pager pager{ 4 }; + for (auto [ channel, plane ]: channelPlanes) { + if (pager.nextHasNewLine()) log << "\n "; + log << " CH=" << channel << " (P:" << plane << ")"; + } + + } // for board + + // full mapping + icarusDB::TPCReadoutBoardToChannelMap const& boardChannelMap + = mapping.getReadoutBoardToChannelMap(); // map + log << "\n\nReported " << nBoards << " TPC boards in the mapping:"; + + // board (unsigned int), SlotChannelVecPair = pair: + for (auto const& [ board, slotInfo ]: boardChannelMap) { + + auto const& [ slot, channelPlanes ] = slotInfo; + + log << "\nBoard " << board << " on slot #" << slot + << " has " << channelPlanes.size() << " channels:"; + + Pager pager{ 4 }; + for (auto [ channel, plane ]: channelPlanes) { + if (pager.nextHasNewLine()) log << "\n "; + log << " CH=" << channel << " (P:" << plane << ")"; + } + + } // for board channel map + +} // dumpTPCmapping() + + +// ----------------------------------------------------------------------------- +void dumpPMTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { + + mf::LogVerbatim log("PMTchannelMappingDumper"); + unsigned int nFragmentIDs = mapping.nPMTfragmentIDs(); + log << "Reported " << nFragmentIDs << " PMT fragment IDs."; // hard-coded list of fragment ID; don't like it? // ask for an extension of the channel mapping features. std::array FragmentIDs; std::iota(FragmentIDs.begin(), FragmentIDs.end(), 0x2000); - mf::LogVerbatim("PMTchannelMappingDumper") << "Fragment IDs:"; + log << "\nPMT fragment IDs:"; for (auto const [ iFragment, fragmentID]: util::enumerate(FragmentIDs)) { unsigned int const effFragmentID = fragmentID & 0xFF; - if (!channelMapping.hasPMTDigitizerID(effFragmentID)) { - mf::LogVerbatim("PMTchannelMappingDumper") - << "[" << iFragment << "] " << std::hex << fragmentID << std::dec + if (!mapping.hasPMTDigitizerID(effFragmentID)) { + log << "\n[" << iFragment << "] " << std::hex << fragmentID << std::dec << " not found in the database (as " << std::hex << effFragmentID << std::dec << ")"; continue; } icarusDB::DigitizerChannelChannelIDPairVec digitizerChannels - = channelMapping.getChannelIDPairVec(effFragmentID); + = mapping.getChannelIDPairVec(effFragmentID); std::sort (digitizerChannels.begin(), digitizerChannels.end(), SortByElement<1U>{}); - mf::LogVerbatim log("PMTchannelMappingDumper"); log - << "[" << iFragment << "] " << std::hex << fragmentID << std::dec + << "\n[" << iFragment << "] 0x" << std::hex << fragmentID << std::dec << " includes " << digitizerChannels.size() << " LArSoft channels between " << std::get<1U>( digitizerChannels.front() ) << " and " << std::get<1U>( digitizerChannels.back() ) << " [board channel index in brackets]:"; - constexpr unsigned int Cols = 8U; - unsigned int n = 0; + Pager pager{ 8 }; for(auto const & [ digitizerChannel, channelID, laserChannel ]: digitizerChannels) { - if (n-- == 0) { log << "\n "; n = Cols - 1U; } + if (pager.nextHasNewLine()) log << "\n "; log << " " << std::setw(3) << channelID << " [" << std::setw(3) << digitizerChannel << "]"; } // for channel } // for fragment +} // dumpPMTmapping() + + +// ----------------------------------------------------------------------------- +void dumpCRTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { + + mf::LogVerbatim log("PMTchannelMappingDumper"); + + constexpr unsigned int MaxHWmac = 1000; + + log << "CRT address mapping:"; + for (unsigned int const HWaddress: util::counter(MaxHWmac)) { + unsigned int const simMac = mapping.getSimMacAddress(HWaddress); + if (simMac == 0) continue; // not present + log << "\nSide CRT HW=" << HWaddress << " -> sim=" << simMac; + } + for (unsigned int const HWaddress: util::counter(MaxHWmac)) { + unsigned int const simMac = mapping.gettopSimMacAddress(HWaddress); + if (simMac == 0) continue; // not present + log << "\nTop CRT HW=" << HWaddress << " -> sim=" << simMac; + } + + // the interface does not provide any clue on which mac5 and chan values are + // available, so we have to skip this + // std::pair const = mapping.getSideCRTCalibrationMap(mac5, chan); + +} // dumpCRTmapping() + + +// ----------------------------------------------------------------------------- +void dumpMapping(icarusDB::ICARUSChannelMapProvider const& channelMapping) { + + mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + dumpTPCmapping(channelMapping); + + mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + dumpPMTmapping(channelMapping); + + mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + dumpCRTmapping(channelMapping); + + mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); } From 8ed8514a6701a362327d6a0e11213d4c98021f19 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Wed, 21 Feb 2024 19:18:57 -0600 Subject: [PATCH 02/19] ChannelMapping service refactoring. The code of SQLite tool to access the database has been untoolised and it is now used directly by a new service `ICARUSChannelMapSQLite`. The service provider `ICARUSChannelMapSQLiteProvider` is completely art-independent. --- .../Decode/ChannelMapping/CMakeLists.txt | 25 +- .../ChannelMapping/ChannelMapPostGres_tool.cc | 585 --------------- .../ChannelMapping/ChannelMapSQLite.cxx | 699 ++++++++++++++++++ .../Decode/ChannelMapping/ChannelMapSQLite.h | 230 ++++++ .../ChannelMapping/ChannelMapSQLite_tool.cc | 624 ---------------- .../ICARUSChannelMapSQLiteProvider.cxx | 438 +++++++++++ .../ICARUSChannelMapSQLiteProvider.h | 243 ++++++ .../ICARUSChannelMapSQLite_service.cc | 72 ++ .../Decode/ChannelMapping/IChannelMapping.h | 40 +- .../Legacy/ChannelMapPostGres_tool.cc | 52 ++ .../Legacy/ChannelMapSQLite_tool.cc | 54 ++ .../ChannelMapping/PMTChannelMapDumper.cxx | 15 +- 12 files changed, 1857 insertions(+), 1220 deletions(-) delete mode 100755 icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc create mode 100644 icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx create mode 100644 icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h delete mode 100755 icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc create mode 100644 icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc create mode 100755 icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index c9dc94ca4..73b822ec0 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -10,6 +10,17 @@ art_make_library( cetlib_except::cetlib_except cetlib::cetlib larcorealg::CoreUtils + + # for SQLite algorithms (includes duplicates above) + icarusalg::Utilities + larevt::CalibrationDBI_Providers + larcorealg::CoreUtils + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib::cetlib + cetlib_except::cetlib_except + SQLite::SQLite3 + ) set( SERVICE_LIBRARIES @@ -58,9 +69,21 @@ set( TOOL_LIBRARIES ) cet_build_plugin(ChannelMapPostGres art::tool LIBRARIES ${TOOL_LIBRARIES}) -cet_build_plugin(ChannelMapSQLite art::tool LIBRARIES ${TOOL_LIBRARIES}) +# cet_build_plugin(ChannelMapSQLite art::tool LIBRARIES ${TOOL_LIBRARIES}) cet_build_plugin(ICARUSChannelMap art::service LIBRARIES ${SERVICE_LIBRARIES}) +cet_build_plugin(ICARUSChannelMapSQLite art::service + LIBRARIES + icaruscode::Decode_ChannelMapping + art::Framework_Principal + messagefacility::MF_MessageLogger + messagefacility::headers + ) + +cet_build_plugin(ChannelMapSQLite art::tool + LIBRARIES + icaruscode::Decode_ChannelMapping + ) cet_make_exec(NAME "PMTChannelMapDumper" LIBRARIES diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc deleted file mode 100755 index 1f4333f3c..000000000 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc +++ /dev/null @@ -1,585 +0,0 @@ -/** - * @file ChannelMapPostGres_tool.cc - * - * @brief This tool converts from daq to LArSoft format with noise filtering - * - */ - -// ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "art/Utilities/make_tool.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "wda.h" - -// LArSoft includes -#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" - -// std includes -#include -#include -#include -#include -#include - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace icarusDB { -/** - * @brief ChannelMapPostGres class definiton - */ -class ChannelMapPostGres : virtual public IChannelMapping -{ -public: - /** - * @brief Constructor - * - * @param pset - */ - explicit ChannelMapPostGres(fhicl::ParameterSet const &pset); - - /** - * @brief Prepares the object for queries pertaining the specified period. - * @param period the period to be prepared for - * @return whether values cached from the previous period are invalidated - * - * Periods are defined in `icarusDB::RunPeriods` class. - * - * If the return value is `true`, caller should follow by rebuilding all the - * maps they need to use. - * If the return value is `false`, all maps built after the previous call to - * `SelectPeriod()` are still current for `period`: building new ones is not - * necessary, but it's not harmful either (at most, wasteful). - */ - virtual bool SelectPeriod(RunPeriod period) override; - - /** - * @brief Define the returned data structures for a mapping between TPC Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const override; - - /** - * @brief Define the returned data structures for a mapping between TPC readout boards - * and the channel information - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const override; - - /** - * @brief Define the returned data structures for a mapping between PMT Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; - - - /** - * @brief Define the returned data structures for a mapping between CRT hardware mac_address - * to the simulated mac_address. - * Then define the function interface to fill these data structures - */ - virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const override; - virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const override; - - /** - * @brief Define the returned data structures for a mapping between Side CRT Channels and - * their calibration values. - * Then define the function interface to fill these data structures - */ - virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const override; - -private: - - // Recover data from postgres database - int GetDataset(const std::string&, const std::string&, const std::string&, Dataset&) const; - int GetCRTCaldata(const std::string&, const std::string&, Dataset&) const; - uint32_t fNothing; //< Nothing - - /// The PMT timestamp being served. Chosen by `SelectPeriod()`. - std::string fCurrentPMTTimestamp = ""; - - /// The list of available PMT timestamps. - static std::array const PMTTimestampSet; - -}; - -//------------------------------------------------------------------------------------------------------------------------------------------ -std::array const -ChannelMapPostGres::PMTTimestampSet{ - "start" - ,"23aug2023" - ,"29aug2023" -}; - -//------------------------------------------------------------------------------------------------------------------------------------------ -ChannelMapPostGres::ChannelMapPostGres(fhicl::ParameterSet const &pset) -{ - fNothing = pset.get("Nothing"); - - return; -} - -//------------------------------------------------------------------------------------------------------------------------------------------ -bool ChannelMapPostGres::SelectPeriod(RunPeriod period) { - - auto const iPeriod = static_cast(period); - std::string newPMTTimestamp = PMTTimestampSet.at(iPeriod); - - if (fCurrentPMTTimestamp == newPMTTimestamp) { - mf::LogDebug("ChannelMapPostGres") - << "Period " << newPMTTimestamp << " already selected"; - } - else if ( !fCurrentPMTTimestamp.empty() ) { - mf::LogDebug("ChannelMapPostGres") << "Switched from period " - << fCurrentPMTTimestamp << " to " << newPMTTimestamp; - } - else { - mf::LogDebug("ChannelMapPostGres") << "Switching to period " << newPMTTimestamp; - } - - if (fCurrentPMTTimestamp == newPMTTimestamp) return false; - - fCurrentPMTTimestamp = newPMTTimestamp; - return true; - -} - -//------------------------------------------------------------------------------------------------------------------------------------------ - -// ----------------------------------------------------- -// This Function does the basic information retrieval -// One passes in the type of data requested and a reference to the data holder -// The function connects via the libwda function to recover the -// data and checks to insure there were not connection errors. -// The function returns the error status, if null then success -//----------------------------------------------------- -int ChannelMapPostGres::GetDataset(const std::string& name, const std::string& url, const std::string& dataType, Dataset& dataSet) const -{ - const int timeout(200); - std::string dburl = url + "&t=" + dataType; - int error(0); - dataSet = getDataWithTimeout(dburl.data(),name.data(),timeout,&error); - if (error) - { - std::string errorMsg = "Database access GetDataset failed with error " + std::to_string(error) + "\nDB url: " - + dburl + ", name: " + name + ", type: " + dataType; - std::cout << "****> Database retrieval error, code: " << error << std::endl; - throw std::runtime_error(errorMsg); - } - - return error; -} - - //Adding this so I can control how this workflow goes -TB - int ChannelMapPostGres::GetCRTCaldata(const std::string& name, const std::string& url, Dataset& dataSet) const - { - const int timeout(200); - int error(0); - dataSet = getDataWithTimeout(url.c_str(),name.c_str(),timeout,&error); - if (error) - { - std::string errorMsg = "Database access GetDataset failed with error " + std::to_string(error) + "\nurl: " - + url + ", name: " + name; - std::cout << "****> Database retrieval error, code: " << error << std::endl; - throw std::runtime_error(errorMsg); - } - - return error; - } - - -// ----------------------------------------------------- -// The aim of this function is to build a map between the -// TPC Fragment IDs and the readout board IDs. Here we -// expect there will be some number of boards per Fragment -//----------------------------------------------------- -int ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const -{ - const unsigned int tpcIdentifier(0x00001000); - const std::string name("icarus_hw_readoutboard"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd"); - const std::string dataType("readout_boards"); - Dataset dataset; - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - // Include a by hand mapping of fragement ID to crate - using FlangeIDToCrateMap = std::map; - FlangeIDToCrateMap flangeIDToCrateMap; - flangeIDToCrateMap[19] = "WW01T"; - flangeIDToCrateMap[68] = "WW01M"; - flangeIDToCrateMap[41] = "WW01B"; - flangeIDToCrateMap[11] = "WW02"; - flangeIDToCrateMap[17] = "WW03"; - flangeIDToCrateMap[36] = "WW04"; - flangeIDToCrateMap[18] = "WW05"; - flangeIDToCrateMap[58] = "WW06"; - flangeIDToCrateMap[71] = "WW07"; - flangeIDToCrateMap[14] = "WW08"; - flangeIDToCrateMap[25] = "WW09"; - flangeIDToCrateMap[34] = "WW10"; - flangeIDToCrateMap[67] = "WW11"; - flangeIDToCrateMap[33] = "WW12"; - flangeIDToCrateMap[87] = "WW13"; - flangeIDToCrateMap[10] = "WW14"; - flangeIDToCrateMap[59] = "WW15"; - flangeIDToCrateMap[95] = "WW16"; - flangeIDToCrateMap[22] = "WW17"; - flangeIDToCrateMap[91] = "WW18"; - flangeIDToCrateMap[61] = "WW19"; - flangeIDToCrateMap[55] = "WW20T"; - flangeIDToCrateMap[97] = "WW20M"; - flangeIDToCrateMap[100] = "WW20B"; - flangeIDToCrateMap[83] = "WE01T"; - flangeIDToCrateMap[85] = "WE01M"; - flangeIDToCrateMap[7] = "WE01B"; - flangeIDToCrateMap[80] = "WE02"; - flangeIDToCrateMap[52] = "WE03"; - flangeIDToCrateMap[32] = "WE04"; - flangeIDToCrateMap[70] = "WE05"; - flangeIDToCrateMap[74] = "WE06"; - flangeIDToCrateMap[46] = "WE07"; - flangeIDToCrateMap[81] = "WE08"; - flangeIDToCrateMap[63] = "WE09"; - flangeIDToCrateMap[30] = "WE10"; - flangeIDToCrateMap[51] = "WE11"; - flangeIDToCrateMap[90] = "WE12"; - flangeIDToCrateMap[23] = "WE13"; - flangeIDToCrateMap[93] = "WE14"; - flangeIDToCrateMap[92] = "WE15"; - flangeIDToCrateMap[88] = "WE16"; - flangeIDToCrateMap[73] = "WE17"; - flangeIDToCrateMap[1] = "WE18"; - flangeIDToCrateMap[66] = "WE19"; - flangeIDToCrateMap[48] = "WE20T"; - flangeIDToCrateMap[13] = "WE20M"; - flangeIDToCrateMap[56] = "WE20B"; - flangeIDToCrateMap[94] = "EW01T"; - flangeIDToCrateMap[77] = "EW01M"; - flangeIDToCrateMap[72] = "EW01B"; - flangeIDToCrateMap[65] = "EW02"; - flangeIDToCrateMap[4] = "EW03"; - flangeIDToCrateMap[89] = "EW04"; - flangeIDToCrateMap[37] = "EW05"; - flangeIDToCrateMap[76] = "EW06"; - flangeIDToCrateMap[49] = "EW07"; - flangeIDToCrateMap[60] = "EW08"; - flangeIDToCrateMap[21] = "EW09"; - flangeIDToCrateMap[6] = "EW10"; - flangeIDToCrateMap[62] = "EW11"; - flangeIDToCrateMap[2] = "EW12"; - flangeIDToCrateMap[29] = "EW13"; - flangeIDToCrateMap[44] = "EW14"; - flangeIDToCrateMap[9] = "EW15"; - flangeIDToCrateMap[31] = "EW16"; - flangeIDToCrateMap[98] = "EW17"; - flangeIDToCrateMap[38] = "EW18"; - flangeIDToCrateMap[99] = "EW19"; - flangeIDToCrateMap[53] = "EW20T"; - flangeIDToCrateMap[82] = "EW20M"; - flangeIDToCrateMap[35] = "EW20B"; - flangeIDToCrateMap[96] = "EE01T"; - flangeIDToCrateMap[28] = "EE01M"; - flangeIDToCrateMap[16] = "EE01T"; - flangeIDToCrateMap[69] = "EE02"; - flangeIDToCrateMap[20] = "EE02"; - flangeIDToCrateMap[79] = "EE02"; - flangeIDToCrateMap[50] = "EE02"; - flangeIDToCrateMap[45] = "EE02"; - flangeIDToCrateMap[84] = "EE02"; - flangeIDToCrateMap[42] = "EE02"; - flangeIDToCrateMap[39] = "EE02"; - flangeIDToCrateMap[26] = "EE02"; - flangeIDToCrateMap[64] = "EE02"; - flangeIDToCrateMap[43] = "EE02"; - flangeIDToCrateMap[47] = "EE02"; - flangeIDToCrateMap[15] = "EE02"; - flangeIDToCrateMap[3] = "EE02"; - flangeIDToCrateMap[27] = "EE02"; - flangeIDToCrateMap[24] = "EE02"; - flangeIDToCrateMap[40] = "EE02"; - flangeIDToCrateMap[75] = "EE02"; - flangeIDToCrateMap[86] = "EE20T"; - flangeIDToCrateMap[54] = "EE20M"; - flangeIDToCrateMap[8] = "EE20B"; - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - // Loop through the data to recover the channels - // NOTE that we skip the first row because that is just the labels - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - if (tuple != NULL) - { - // Note that the fragment ID is stored in the database as a string which reads as a hex number - // Meaning we have to read back as a string and decode to get the numerical value. - char fragmentBuffer[16]; - getStringValue(tuple, 8, fragmentBuffer, sizeof(fragmentBuffer), &error); - if (error) throw std::runtime_error("Encountered error in trying to recover FragmentID from database"); - std::string fragmentIDString(fragmentBuffer,4); - unsigned int fragmentID = std::stol(fragmentIDString,nullptr,16); - if (!(fragmentID & tpcIdentifier)) continue; - if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) - { - unsigned int flangeID = getLongValue(tuple, 1, &error); - if (error) throw std::runtime_error("Encountered error in trying to recover Board Flange ID from database"); - fragmentBoardMap[fragmentID].first = flangeIDToCrateMap[flangeID]; - } - unsigned int readoutID = getLongValue(tuple, 0, &error); - if (error) throw std::runtime_error("Encountered error in trying to recover Board ReadoutID from database"); - fragmentBoardMap[fragmentID].second.emplace_back(readoutID); - releaseTuple(tuple); - } - } - - return error; -} - -// ----------------------------------------------------- -// The aim of this function is to build a map between the -// TPC readout board IDs and the associated channels. So for -// each readout board ID we expect a number of channels back -// from the data base. So the returned data structure will -// be a map of readout ID to a vector of channels -//----------------------------------------------------- -const unsigned int CHANNELSPERBOARD = 64; -int ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap& rbChanMap) const -{ - const std::string name("icarus_hardware_prd"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd"); - const std::string dataType("daq_channels"); - Dataset dataset; - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - // If there was an error the function above would have printed a message so bail out - if (error) throw std::runtime_error("Encountered error accessing the database with GetDataset"); - // Loop through the data to recover the channels, making sure to skip the first (header) row - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - if (tuple != NULL) - { - unsigned int readoutBoardID = getLongValue(tuple, 2, &error); - if (error) throw std::runtime_error("Encountered error when trying to read Board ReadoutID"); - if (rbChanMap.find(readoutBoardID) == rbChanMap.end()) - { - unsigned int readoutBoardSlot = getLongValue(tuple, 4, &error); - if (error) throw std::runtime_error("Encountered error when trying to read Board Readout slot"); - rbChanMap[readoutBoardID].first = readoutBoardSlot; - rbChanMap[readoutBoardID].second.resize(CHANNELSPERBOARD); - } - unsigned int channelNum = getLongValue(tuple, 5, &error); - if (error) throw std::runtime_error("Encountered error when trying to read channel number"); - unsigned int channelID = getLongValue(tuple, 0, &error); - if (error) throw std::runtime_error("Encountered error when recovering the channel ID list"); - // Recover the plane identifier - char fragmentBuffer[16]; - getStringValue(tuple, 10, fragmentBuffer, sizeof(fragmentBuffer), &error); - if (error) throw std::runtime_error("Encountered error when trying to read plane type"); - // Make sure lower case... (sigh...) - for(size_t charIdx = 0; charIdx < sizeof(fragmentBuffer); charIdx++) fragmentBuffer[charIdx] = tolower(fragmentBuffer[charIdx]); - unsigned int plane(3); - if (strstr(fragmentBuffer,"collection")) plane = 2; - else if (strstr(fragmentBuffer,"induction 2")) plane = 1; - else if (strstr(fragmentBuffer,"induction 1")) plane = 0; - if (plane > 2) std::cout << "YIKES!!! Plane is " << plane << " for channel " << channelID << " with type " << std::string(fragmentBuffer) << std::endl; - rbChanMap[readoutBoardID].second[channelNum] = ChannelPlanePair(channelID,plane); - } - } - - return error; -} - -//******************* PMT Channel Mapping *********************** -int ChannelMapPostGres::BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const -{ - assert( !fCurrentPMTTimestamp.empty() ); - // clearing is cleansing - fragmentToDigitizerChannelMap.clear(); - // Recover the information from the database on the mapping - const std::string name("Pmt_placement"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd"); - const std::string period_query("&w=period_active:eq:"+fCurrentPMTTimestamp); - const std::string dataType("pmt_placements"); - Dataset dataset; - // Recover the data from the database - int error = GetDataset(name,dburl+period_query,dataType,dataset); - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - // Ok, now we can start extracting the information - // We do this by looping through the database and building the map from that - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - if (tuple != NULL) - { - - char digitizerBuffer[10]; - // Recover the digitizer label first - getStringValue(tuple, 11, digitizerBuffer, sizeof(digitizerBuffer), &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT digitizer label"); - std::string digitizerLabel(digitizerBuffer, 8); //sizeof(digitizerBuffer)); - // Recover the fragment id - unsigned fragmentID = getLongValue(tuple, 15, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT fragment id"); - // Now recover the digitizer channel number - unsigned int digitizerChannelNo = getLongValue(tuple, 12, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT digitizer channel number"); - // Get the LArsoft channel ID - unsigned int channelID = getLongValue(tuple, 3, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT channel ID"); - // Get the laserChannelNumber - char laserChannelBuffer[10]; - getStringValue(tuple, 10, laserChannelBuffer, sizeof(laserChannelBuffer), &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT laser channel label"); - std::string laserChannelLabel(laserChannelBuffer, 2, sizeof(laserChannelBuffer)); //sizeof(digitizerBuffer)); - unsigned int laserChannel = std::stol(laserChannelLabel); // try-catch syntax for stol or not necessary ? - - // Fill the map - fragmentToDigitizerChannelMap[fragmentID].emplace_back(digitizerChannelNo,channelID,laserChannel); - releaseTuple(tuple); - } - } - - return error; -} - - -//******************* CRT Channel Mapping *********************** - - int ChannelMapPostGres::BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap) const - { - // clearing is cleansing - crtChannelIDToHWtoSimMacAddressPairMap.clear(); - // Recover the information from the database on the mapping - const std::string name("Feb_channels"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd"); - const std::string dataType("feb_channels"); - Dataset dataset; - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - // Ok, now we can start extracting the information - // We do this by looping through the database and building the map from that - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - if (tuple != NULL) - { - // Recover the simmacaddress - unsigned int simmacaddress = getLongValue(tuple, 11, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the CRT simmacaddress"); - // Now recover the hwmacaddress - unsigned int hwmacaddress = getLongValue(tuple, 12, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the CRT hwmacaddress"); - // Finally, get the LArsoft channel ID - unsigned int channelID = getLongValue(tuple, 10, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the CRT channel ID"); - // Fill the map - crtChannelIDToHWtoSimMacAddressPairMap[channelID]=std::make_pair(hwmacaddress,simmacaddress); - releaseTuple(tuple); - } - } - - return error; - } - - - /// Top CRT harware mac5 to software mac5 relation - //---------------------------------------------------- - int ChannelMapPostGres::BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap& topcrtHWtoSimMacAddressPairMap) const - { - // clearing is cleansing - topcrtHWtoSimMacAddressPairMap.clear(); - // Recover the information from the database on the mapping - const std::string name("topcrt_febs"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd"); - const std::string dataType("crtfeb"); - Dataset dataset; - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - // Ok, now we can start extracting the information - // We do this by looping through the database and building the map from that - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - if (tuple != NULL) - { - // Recover the simmacaddress - unsigned int simmacaddress = getLongValue(tuple, 41, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the CRT simmacaddress"); - // Now recover the hwmacaddress - unsigned int hwmacaddress = getLongValue(tuple, 3, &error); - if (error) throw std::runtime_error("Encountered error when trying to recover the CRT hwmacaddress"); - - // Fill the map - topcrtHWtoSimMacAddressPairMap[hwmacaddress] = simmacaddress; - releaseTuple(tuple); - } - } - - return error; - } - - - /// Accesing the Side CRT charge calibration from the postgresql database - //------------------------------------------------------------------------ - - int ChannelMapPostGres::BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap& sideCRTChannelToCalibrationMap) const { - // sideCRTChannelToCalibrationMap.clear(); - const std::string name("SideCRT_calibration_data"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/icarus_con_prod/app/data?f=crt_gain_reco_data&t=1638918270"); - Dataset ds; - // Recover the data from the database - int error = GetCRTCaldata(name,dburl,ds); - if (error) - { fprintf(stderr, "error code=%d\n", error); perror("error message"); } - if (getHTTPstatus(ds) != 200) - { fprintf(stderr, "HTTP code=%ld, message: '%s'\n", getHTTPstatus(ds), getHTTPmessage(ds)); } - int mac5, chan; - double gain, ped; - int err; - int nrows = getNtuples(ds); - int ncols; - Tuple tup; - for (int rows = 0; rows < nrows; rows++ ){ - tup = getTuple(ds, rows); // Get the row with double array - ncols = getNfields(tup);//check number of columns - if(ncols <5) continue;//first few rows aren't actual data and have ncols==1, this excludes those - if (tup != NULL)/*check that the tup is not empty before proceeding*/ { - //assign values from the database to variables so we can use them - mac5 = (int)getDoubleValue(tup,1,&err); - chan = (int)getDoubleValue(tup,2,&err); - gain = getDoubleValue(tup,3,&err); - ped = getDoubleValue(tup,4,&err); - //This line adds the association between the two pairs to the map object - sideCRTChannelToCalibrationMap.insert(std::make_pair(std::make_pair(mac5,chan), std::make_pair(gain,ped))); - - releaseTuple(tup); - }//end if(tup != NULL) - else releaseTuple(tup); - }//end loop over rows - - return error; - } - - -DEFINE_ART_CLASS_TOOL(ChannelMapPostGres) -} // namespace lar_cluster3d diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx new file mode 100644 index 000000000..2e7f9329e --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -0,0 +1,699 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h + */ + +// library header +#include "icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h" + +// ICARUS libraries + +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" +// #include "wda.h" + +// LArSoft libraries +#include "larevt/CalibrationDBI/Providers/DBFolder.h" +#include "larcorealg/CoreUtils/counter.h" +#include "cetlib/search_path.h" + +// SQLite +#include + +// C++ standard libraries +#include // std::transform() +#include +#include +#include // std::tolower() + + +// ----------------------------------------------------------------------------- +namespace { + + /// Tracks a SQLite resource object and frees it on destruction (RAII). + template + class SQLiteResource { + + PTR fResource = nullptr; ///< Pointer to the resource data. + + public: + + using ResourcePtr_t = PTR; ///< Type of the resource data pointer. + + /// Constructor: acquires and manages the specified `resource`. + SQLiteResource(ResourcePtr_t resource = nullptr): fResource{ resource } {} + + // do not copy + SQLiteResource(SQLiteResource const&) = delete; + SQLiteResource& operator= (SQLiteResource&) = delete; + + /// Move constructor: `from` loses the ownership of its resource. + SQLiteResource(SQLiteResource&& from): fResource{ from.fResource } + { from.fResource = nullptr; } + + /// Move assignment: the current resource is released. + SQLiteResource& operator= (SQLiteResource&& from) + { + if (from.fResource != fResource) + { free(); std::swap(fResource, from.fResource); } + return *this; + } + + /// Destructor: releases the resource. + ~SQLiteResource() { free(); } + + //@{ + /// Returns the pointer to the resource data. + ResourcePtr_t resource() const { return fResource; } + ResourcePtr_t const* constReference() const { return &fResource; } + ResourcePtr_t operator() () const { return fResource; } + operator ResourcePtr_t() const { return resource(); } + //@} + + //@{ + /// Returns _the_ pointer to the address of the resource. + /// @note The value pointed to is the actual address that this object + /// tracks; this allows using this object with functions which set + /// the address, but also provides a route to circumvent RAII, + /// since the resource pointed by the overwritten value won't be + /// freed. + ResourcePtr_t* reference() { return &fResource; } + ResourcePtr_t const* reference() const { return constReference(); } + ResourcePtr_t* operator& () const { return &fResource; } + ResourcePtr_t* operator& () { return &fResource; } + //@} + + /// Acquires the specified `resource` after freeing the current one. + SQLiteResource& operator= (ResourcePtr_t resource) + { + if (resource != fResource) { free(); fResource = resource; } + return *this; + } + + /// Releases the currently tracked resource, and stops the tracking. + void free() + { if (fResource) { sqlite3_free(fResource); fResource = nullptr; } } + + }; // SQLiteResource + + + /// Tracks a SQLite database object and closes it on destruction (RAII). + class SQLiteConnection { + + sqlite3* fDatabase = nullptr; ///< Pointer to the database object. + + public: + SQLiteConnection(sqlite3* database): fDatabase{ database } {} + + // this resource handle can't be copied + SQLiteConnection(SQLiteConnection const&) = delete; + SQLiteConnection& operator= (SQLiteConnection&) = delete; + + /// Move constructor: steals the database `from` the specified handle. + SQLiteConnection(SQLiteConnection&& from): fDatabase{ from.fDatabase } + { from.fDatabase = nullptr; } + /// Move assignment: closes the current database and steals the `from` one. + SQLiteConnection& operator= (SQLiteConnection&& from) + { + if (from.fDatabase != fDatabase) + { close(); std::swap(fDatabase, from.fDatabase); } + return *this; + } + + /// Destructor: closes the tracked database, if any. No reaction to failure. + ~SQLiteConnection() { close(); } + + //@{ + /// Returns a pointer to the database object. + sqlite3* database() const { return fDatabase; } + operator sqlite3*() const { return database(); } + //@} + + /// Closes the tracked database, if any. No reaction to failure. + void close() + { if (fDatabase) { sqlite3_close(fDatabase); fDatabase = nullptr; } } + + }; // SQLiteConnection + + + /// Debug SQLite callback: prints the content of the row to console. + int datadump_callback [[maybe_unused]] + (void*, int argc, char **argv, char **azColName) + { + for(int const i: util::counter(argc)) { + std::cout << "column: '" << azColName[i] << "' - value: " + << (argv[i] ? argv[i] : "") << " "; + } + std::cout << "\n" << std::endl; + return 0; + } // datadump_callback() + +} // local namespace + + +// ----------------------------------------------------------------------------- +std::array + +const icarusDB::ChannelMapSQLite::TableNameSets{ + TableNames_t{ + "readout_boards" // TPCfragmentMap + , "daq_channels" // TPCreadoutBoardMap + , "pmt_placements" // PMTfragmentMap + , "feb_channels" // CRTsideMap + , "crtfeb" // CRTtopMap + }, + TableNames_t{ + "readout_boards" // TPCfragmentMap + , "daq_channels" // TPCreadoutBoardMap + , "pmt_placements_23Aug2023" // PMTfragmentMap + , "feb_channels" // CRTsideMap + , "crtfeb" // CRTtopMap + }, + TableNames_t{ + "readout_boards" // TPCfragmentMap + , "daq_channels" // TPCreadoutBoardMap + , "pmt_placements_29Aug2023" // PMTfragmentMap + , "feb_channels" // CRTsideMap + , "crtfeb" // CRTtopMap + } +}; // icarusDB::ChannelMapSQLite::TableNameSets + + +// ----------------------------------------------------------------------------- +icarusDB::ChannelMapSQLite::ChannelMapSQLite(Config const& config) + : icarus::ns::util::mfLoggingClass{ config.LogCategory() } + , fDBFileName { config.DBFileName() } + , fCalibDBFileName{ config.CalibDBFileName() } + , fTag { config.Tag() } +{ +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ChannelMapSQLite::SelectPeriod(RunPeriod period) { + + auto const iPeriod = static_cast(period); + TableNames_t const* newSet = &(TableNameSets.at(iPeriod)); + + if (fCurrentTable == newSet) { + mfLogDebug() << "Period #" << iPeriod << " already selected"; + } + else if (fCurrentTable) { + mfLogDebug() << "Switched from period #" + << (fCurrentTable - &(TableNameSets[0])) << " to #" << iPeriod; + } + else { + mfLogDebug() << "Switching to period #" << iPeriod; + } + + if (fCurrentTable == newSet) return false; + + fCurrentTable = newSet; + return true; + +} // icarusDB::ChannelMapSQLite::SelectPeriod() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::GetDataset + (std::string const& table, SQLiteCallbackFunc_t func, void* data) const +{ + + // find the SQLite database file + std::string fullFileName; + cet::search_path searchPath("FW_SEARCH_PATH"); + if (!searchPath.find_file(fDBFileName, fullFileName)) { + throw cet::exception{ "ChannelMapSQLite" } + << "GetDataset(): can't find input file: '" << fDBFileName << "'\n"; + } + mfLogDebug() << "Database file: '" << fullFileName << "'."; + + // set up to open the database + sqlite3* database = nullptr; + int rc = sqlite3_open(fullFileName.c_str(), &database); + if (rc) { + throw cet::exception{ "ChannelMapSQLite" } + << "GetDataset(): can't open the database, return code:" + << sqlite3_errmsg(database) << "'\n"; + } + SQLiteConnection const DBguard{ database }; + + // read the full table (SQLite will also call func after fetching the data) + std::string const select = "SELECT * FROM " + table; + SQLiteResource zErrMsg; + rc = sqlite3_exec(database, select.c_str(), func, data, &zErrMsg); + if (rc != SQLITE_OK) { + mfLogError() << "GetDataset(): SQL error: " << zErrMsg; + } + else { + mfLogDebug() << "GetDataset(): successfully read SQLite database table '" + << table << "'"; + } + + return rc; +} // icarusDB::ChannelMapSQLite::GetDataset() + + +// ----------------------------------------------------------------------------- +// The aim of this function is to build a map between the +// TPC Fragment IDs and the readout board IDs. Here we +// expect there will be some number of boards per Fragment +//----------------------------------------------------- +int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback + (void* dataOut, int argc, char**argv, char** azColName) +{ + const unsigned int tpcIdentifier(0x00001000); + + auto& fragmentBoardMap = *static_cast + (dataOut); + + // Include a by hand mapping of fragment ID to crate + // Note that we now know we can get this from the "flanges" table... so an upgrade coming soon... + static std::map const flangeIDToCrateMap = { + { 19, "WW01T" }, + { 68, "WW01M" }, + { 41, "WW01B" }, + { 11, "WW02" }, + { 17, "WW03" }, + { 36, "WW04" }, + { 18, "WW05" }, + { 58, "WW06" }, + { 71, "WW07" }, + { 14, "WW08" }, + { 25, "WW09" }, + { 34, "WW10" }, + { 67, "WW11" }, + { 33, "WW12" }, + { 87, "WW13" }, + { 10, "WW14" }, + { 59, "WW15" }, + { 95, "WW16" }, + { 22, "WW17" }, + { 91, "WW18" }, + { 61, "WW19" }, + { 55, "WW20T" }, + { 97, "WW20M" }, + { 100, "WW20B" }, + { 83, "WE01T" }, + { 85, "WE01M" }, + { 7, "WE01B" }, + { 80, "WE02" }, + { 52, "WE03" }, + { 32, "WE04" }, + { 70, "WE05" }, + { 74, "WE06" }, + { 46, "WE07" }, + { 81, "WE08" }, + { 63, "WE09" }, + { 30, "WE10" }, + { 51, "WE11" }, + { 90, "WE12" }, + { 23, "WE13" }, + { 93, "WE14" }, + { 92, "WE15" }, + { 88, "WE16" }, + { 73, "WE17" }, + { 1, "WE18" }, + { 66, "WE19" }, + { 48, "WE20T" }, + { 13, "WE20M" }, + { 56, "WE20B" }, + { 94, "EW01T" }, + { 77, "EW01M" }, + { 72, "EW01B" }, + { 65, "EW02" }, + { 4, "EW03" }, + { 89, "EW04" }, + { 37, "EW05" }, + { 76, "EW06" }, + { 49, "EW07" }, + { 60, "EW08" }, + { 21, "EW09" }, + { 6, "EW10" }, + { 62, "EW11" }, + { 2, "EW12" }, + { 29, "EW13" }, + { 44, "EW14" }, + { 9, "EW15" }, + { 31, "EW16" }, + { 98, "EW17" }, + { 38, "EW18" }, + { 99, "EW19" }, + { 53, "EW20T" }, + { 82, "EW20M" }, + { 35, "EW20B" }, + { 96, "EE01T" }, + { 28, "EE01M" }, + { 16, "EE01T" }, + { 69, "EE02" }, + { 20, "EE03" }, + { 79, "EE04" }, + { 50, "EE05" }, + { 45, "EE06" }, + { 84, "EE07" }, + { 42, "EE08" }, + { 39, "EE09" }, + { 26, "EE10" }, + { 64, "EE11" }, + { 43, "EE12" }, + { 47, "EE13" }, + { 15, "EE14" }, + { 3, "EE15" }, + { 27, "EE16" }, + { 24, "EE17" }, + { 40, "EE18" }, + { 75, "EE19" }, + { 86, "EE20T" }, + { 54, "EE20M" }, + { 8, "EE20B" } + }; // flangeIDToCrateMap[] + + constexpr std::size_t ReadoutBoardIDcolumn = 0; + constexpr std::size_t FlangeIDcolumn = 1; + constexpr std::size_t FragmentIDcolumn = 8; + + unsigned int const fragmentID + = std::stol(argv[FragmentIDcolumn], nullptr, 16); + + if (fragmentID & tpcIdentifier) { + if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) { + unsigned int const flangeID = std::stol(argv[FlangeIDcolumn]); + fragmentBoardMap[fragmentID].first = flangeIDToCrateMap.at(flangeID); + } + + unsigned int const readoutID = std::stol(argv[ReadoutBoardIDcolumn]); + fragmentBoardMap[fragmentID].second.emplace_back(readoutID); + } + + return 0; +} // icarusDB::buildTPCReadoutBoardToChannelMap_callback() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildTPCFragmentIDToReadoutIDMap + (TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const +{ + assert(fCurrentTable); + const std::string dataType(fCurrentTable->TPCfragmentMap); + + // Recover the data from the database + int error = GetDataset + (dataType, buildTPCFragmentIDToReadoutIDMap_callback, &fragmentBoardMap); + + // If there was an error the function above would have printed a message + // so bail out + if (error) { + throw cet::exception("ChannelMapSQLite") + << "BuildTPCFragmentIDToReadoutIDMap(): error " << error + << " in reading the database.\n"; + } + + return error; +} // icarusDB::ChannelMapSQLite::BuildTPCFragmentIDToReadoutIDMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::buildTPCReadoutBoardToChannelMap_callback + (void* dataOut, int argc, char**argv, char** azColName) +{ + constexpr std::size_t ChannelIDcolumn = 0; + constexpr std::size_t ReadoutBoardIDcolumn = 2; + constexpr std::size_t ReadoutBoardSlotColumn = 4; + constexpr std::size_t ChannelNumberColumn = 5; + constexpr std::size_t FragmentBufferColumn = 10; + + auto& rbChanMap + = *static_cast(dataOut); + + unsigned int readoutBoardID = std::stol(argv[ReadoutBoardIDcolumn]); + + if (rbChanMap.find(readoutBoardID) == rbChanMap.end()) { + unsigned int readoutBoardSlot = std::stol(argv[ReadoutBoardSlotColumn]); + + rbChanMap[readoutBoardID].first = readoutBoardSlot; + rbChanMap[readoutBoardID].second.resize(ChannelsPerTPCreadoutBoard); + } + + unsigned int channelNum = std::stol(argv[ChannelNumberColumn]); + unsigned int channelID = std::stol(argv[ChannelIDcolumn]); + + std::string const fragmentBuffer = argv[FragmentBufferColumn]; + unsigned int const plane = TPCplaneIdentifierToPlane(fragmentBuffer); + if (plane >= 3) { + mf::LogError{ "ChannelMapSQLite" } << "YIKES!!! Plane is " << plane + << " for channel " << channelID << " with type " << fragmentBuffer; + } + + rbChanMap[readoutBoardID].second[channelNum] = { channelID, plane }; + + return 0; +} // icarusDB::ChannelMapSQLite::buildTPCReadoutBoardToChannelMap_callback() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap + (TPCReadoutBoardToChannelMap& rbChanMap) const +{ + assert(fCurrentTable); + const std::string dataType(fCurrentTable->TPCreadoutBoardMap); + + // Recover the data from the database + int error = GetDataset + (dataType, buildTPCReadoutBoardToChannelMap_callback, &rbChanMap); + + // If there was an error the function above would have printed a message + // so bail out + if (error) { + throw cet::exception{ "ChannelMapSQLite" } + << "BuildTPCReadoutBoardToChannelMap(): error " << error + << " in reading the database!\n"; + } + + return error; +} // icarusDB::ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback + (void* dataOut, int argc, char**argv, char** azColName) +{ + constexpr std::size_t LaserChannelColumn = 7; + constexpr std::size_t DigitizerChannelColumn = 9; + constexpr std::size_t ChannelIDcolumn = 17; + constexpr std::size_t FragmentIDcolumn = 18; + + auto& fragmentToDigitizerChannelMap + = *static_cast(dataOut); + + // Start extracting info + unsigned int const fragmentID = std::stol(argv[FragmentIDcolumn]); + unsigned int const digitizerChannelNo = std::stol(argv[DigitizerChannelColumn]); + unsigned int const channelID = std::stol(argv[ChannelIDcolumn]); + + // Read the laser channel; format is `L-`. is int from [1-41] + std::string const laserChannelLabel = argv[LaserChannelColumn]; + unsigned int laserChannel; + try { + laserChannel = std::stol(laserChannelLabel.substr(2)); + } + catch(...) { + throw cet::exception{ "ChannelMapSQLite" } + << "Failed to convert laser channel '" << laserChannelLabel + << "' into a channel number for channel " << channelID << "!\n"; + } + + // Fill the map + fragmentToDigitizerChannelMap[fragmentID].emplace_back + (digitizerChannelNo, channelID, laserChannel); + + return 0; +} // icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap + (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const +{ + // clearing is cleansing + fragmentToDigitizerChannelMap.clear(); + + // Recover the information from the database on the mapping + assert(fCurrentTable); + const std::string dataType(fCurrentTable->PMTfragmentMap); + + // Recover the data from the database + int error = GetDataset( + dataType, buildFragmentToDigitizerChannelMap_callback, + &fragmentToDigitizerChannelMap + ); + + // If there was an error the function above would have printed a message + // so bail out + if (error) { + throw cet::exception{ "ChannelMapSQLite" } + << "BuildFragmentToDigitizerChannelMap(): encountered error (code: " + << error << ") in reading the database\n"; + } + + return error; +} // icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::buildCRTChannelIDToHWtoSimMacAddressPairMap_callback + (void* dataOut, int argc, char**argv, char** azColName) +{ + constexpr std::size_t ChannelIDcolumn = 10; + constexpr std::size_t SimMACaddressColumn = 11; + constexpr std::size_t HWaddressColumn = 12; + + auto& crtChannelIDToHWtoSimMacAddressPairMap + = *static_cast + (dataOut); + + // extracting info + auto const valueOrNone + = [](const char* s){ return std::strcmp(s, "None") == 0? 0: std::stol(s); }; + + unsigned int const channelID = valueOrNone(argv[ChannelIDcolumn]); + unsigned int const simmacaddress = valueOrNone(argv[SimMACaddressColumn]); + unsigned int const hwmacaddress = valueOrNone(argv[HWaddressColumn]); + + // fill the map + crtChannelIDToHWtoSimMacAddressPairMap[channelID] + = std::make_pair(hwmacaddress, simmacaddress); + + return 0; +} // ...::ChannelMapSQLite::buildCRTChannelIDToHWtoSimMacAddressPairMap_callback + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildCRTChannelIDToHWtoSimMacAddressPairMap + (CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap) + const +{ + // clearing is cleansing + crtChannelIDToHWtoSimMacAddressPairMap.clear(); + + // Recover the information from the database on the mapping + assert(fCurrentTable); + const std::string dataType(fCurrentTable->CRTsideMap); + + // Recover the data from the database + int error = GetDataset( + dataType, + buildCRTChannelIDToHWtoSimMacAddressPairMap_callback, + &crtChannelIDToHWtoSimMacAddressPairMap + ); + + // If there was an error the function above would have printed a message + // so bail out + if (error) { + throw cet::exception{ "ChannelMapSQLite" } + << "BuildCRTChannelIDToHWtoSimMacAddressPairMap(): error " << error + << " reading the database!\n"; + } + + return error; +} // icarusDB::ChannelMapSQLite::BuildCRTChannelIDToHWtoSimMacAddressPairMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::buildTopCRTHWtoSimMacAddressPairMap_callback + (void* dataOut, int argc, char**argv, char** azColName) +{ + constexpr std::size_t SimMACaddressColumn = 41; + constexpr std::size_t HWaddressColumn = 3; + + auto& topcrtHWtoSimMacAddressPairMap + = *static_cast(dataOut); + + auto const valueOrNone + = [](const char* s){ return std::strcmp(s, "None") == 0? 0: std::stol(s); }; + + // start extracting info + unsigned int const simmacaddress = valueOrNone(argv[SimMACaddressColumn]); + unsigned int const hwmacaddress = valueOrNone(argv[HWaddressColumn]); + + // fill the map + topcrtHWtoSimMacAddressPairMap[hwmacaddress] = simmacaddress; + + return 0; +} // icarusDB::ChannelMapSQLite::buildTopCRTHWtoSimMacAddressPairMap_callback() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildTopCRTHWtoSimMacAddressPairMap + (TopCRTHWtoSimMacAddressPairMap& topcrtHWtoSimMacAddressPairMap) const +{ + // clearing is cleansing + topcrtHWtoSimMacAddressPairMap.clear(); + + // Recover the information from the database on the mapping + assert(fCurrentTable); + const std::string dataType(fCurrentTable->CRTtopMap); + + // Recover the data from the database + int error = GetDataset( + dataType, + buildTopCRTHWtoSimMacAddressPairMap_callback, + &topcrtHWtoSimMacAddressPairMap + ); + + // If there was an error the function above would have printed a message + // so bail out + if (error) { + throw cet::exception{ "ChannelMapSQLite" } + << "BuildTopCRTHWtoSimMacAddressPairMap(): error " << error + << " reading the database!\n"; + } + + return error; +} // icarusDB::ChannelMapSQLite::BuildTopCRTHWtoSimMacAddressPairMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapSQLite::BuildSideCRTCalibrationMap + (SideCRTChannelToCalibrationMap& sideCRTChannelToCalibrationMap) const +{ + // clearing is cleansing + sideCRTChannelToCalibrationMap.clear(); + + std::string fullFileName; + cet::search_path searchPath("FW_SEARCH_PATH"); + if (!searchPath.find_file(fCalibDBFileName + ".db", fullFileName)) { + throw cet::exception{ "ChannelMapSQLite" } + << "BuildSideCRTCalibrationMap(): can't find calibration input file: '" + << fCalibDBFileName << "'\n"; + } + mfLogDebug() << "Found calibration input file: '" << fCalibDBFileName << "'"; + + lariov::DBFolder database(fCalibDBFileName, "", "", fTag, true, false); + + database.UpdateData(1'638'918'271'000'000'000ULL); + + std::vector channels; + database.GetChannelList(channels); + + for (unsigned int const channel: channels) { + + long mac5, chan; + double gain, ped; + + // extracting info + database.GetNamedChannelData(channel, "mac5", mac5); + database.GetNamedChannelData(channel, "localchannel", chan); + database.GetNamedChannelData(channel, "gain", gain); + database.GetNamedChannelData(channel, "pedestal", ped); + + // fill the map + sideCRTChannelToCalibrationMap.emplace + (std::make_pair((int) mac5, (int) chan), std::make_pair(gain, ped)); + } // for + + return 0; +} // icarusDB::ChannelMapSQLite::BuildSideCRTCalibrationMap() + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h new file mode 100644 index 000000000..3d177d16f --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h @@ -0,0 +1,230 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPSQLITE_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPSQLITE_H + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icarusalg/Utilities/mfLoggingClass.h" + +// framework libraries +#include "fhiclcpp/types/Table.h" +#include "fhiclcpp/types/Atom.h" + +// C++ standard libraries +#include +#include + + +namespace icarusDB { class ChannelMapSQLite; }; + +/** + * @brief Interface with ICARUS channel mapping SQLite database. + * + * This interface fills "standard" data structures from a SQLite database. + * These data structures are then managed by a ICARUS service provider + * (`icarusDB::IICARUSChannelMap`). + * + */ +class icarusDB::ChannelMapSQLite + : public IChannelMapping, private icarus::ns::util::mfLoggingClass +{ + /// Tells `fhicl::Table` to ignore the parameter for _art_ tool configuration. + struct IgnoreArtToolConfig + { std::set operator()() { return { "tool_type" }; } }; + + public: + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Atom DBFileName { + Name{ "DBFileName" }, + Comment{ "name of the channel mapping database SQLite file" } + }; + + fhicl::Atom CalibDBFileName { + Name{ "CalibDBFileName" }, + Comment{ "name of the CRT calibration database SQLite file" } + }; + + fhicl::Atom Tag { + Name{ "Tag" }, + Comment{ "tag/version of the database to load" } + }; + + fhicl::Atom LogCategory { + Name{ "LogCategory" }, + Comment{ "name of the streams to send console messages to" }, + "ChannelMapSQLite" // default + }; + + }; // Config + + + /// Constructor: configures the object. + explicit ChannelMapSQLite(Config const& config); + + + /** + * @brief Prepares the object for queries pertaining the specified period. + * @param period the period to be prepared for + * @return whether values cached from the previous period are invalidated + * + * Periods are defined in `icarusDB::RunPeriods` class. + * + * If the return value is `true`, caller should follow by rebuilding all the + * maps they need to use. + * If the return value is `false`, all maps built after the previous call to + * `SelectPeriod()` are still current for `period`: building new ones is not + * necessary, but it's not harmful either (at most, wasteful). + */ + virtual bool SelectPeriod(RunPeriod period) override; + + + /** + * @brief Define the returned data structures for a mapping between TPC Fragment IDs + * and the related crate and readout information. + * Then define the function interface to fill these data structures + */ + virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const override; + + /** + * @brief Define the returned data structures for a mapping between TPC readout boards + * and the channel information + * Then define the function interface to fill these data structures + */ + virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const override; + + /** + * @brief Define the returned data structures for a mapping between PMT Fragment IDs + * and the related crate and readout information. + * Then define the function interface to fill these data structures + */ + virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; + + + /** + * @brief Define the returned data structures for a mapping between CRT hardware mac_address + * to the simulated mac_address. + * Then define the function interface to fill these data structures + */ + virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const override; + virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const override; + + virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const override; + + private: + + /// Record of all relevant table names. + struct TableNames_t { + std::string TPCfragmentMap; + std::string TPCreadoutBoardMap; + std::string PMTfragmentMap; + std::string CRTsideMap; + std::string CRTtopMap; + // NOTE: CRT side calibration is is a different type of database which uses a timestamp + }; + + /// SQLite callback function: SQLite will call this including `argc` arguments + /// each from a column named from `colNames` with the value in `argv`. + using SQLiteCallbackFunc_t = int(*)(void* data, int argc, char** argv, char** colNames); + + + // --- BEGIN --- Configuration parameters ------------------------------------ + + std::string const fDBFileName; ///< File name of our SQLite database. + std::string const fCalibDBFileName; ///< File name of our side CRT calibration SQLite database. + std::string const fTag; ///< Tag for conditioned database. + + std::string const fLogCategory; ///< Message facility category name. + + // --- END ----- Configuration parameters ------------------------------------ + + /// The set of tables being served. Chosen by `SelectRun()`. + TableNames_t const* fCurrentTable = nullptr; + + /** + * @brief Reads a full `table` from the database and process data with `func`. + * @param table name of the table to read + * @param func callback function to be called to process the fetched data + * @param data pointer to a memory data region + * @return an error code, `SQLITE_OK` on success + * + * The full content of the table named `table` is read from the configured + * database. A connection to the database is opened, used and finally closed. + * + * The callback function `func` is executed with the newly loaded data. + * The pointer `data` is passed to that function, which can reinterpret it + * and modify it in the usual untyped C-style data transfer. + */ + int GetDataset + (std::string const& table, SQLiteCallbackFunc_t func, void* data) const; + + + /// The list of names of tables. + static std::array const TableNameSets; + + + // --- BEGIN --- SQLite callback functions ----------------------------------- + /** + * @name SQLite callback functions + * + * These (static) functions are executed during SQLite calls (in + * `GetDataset()`) to translate the data from a table into something we can + * use. + * They all adhere to the prototype `SQLiteCallbackFunc_t`, with: + * + * @param[out] dataOut a pointer to a data area; this pointer can be casted + * to the actual data type and then filled + * @param argc the number of columns in the table + * @param argv the values on columns in one database row (`argc` in count) + * @param azColName the names of the columns (`argc` in count) + */ + /// @{ + + /** + * @brief Builds a map between the TPC Fragment IDs and the readout board IDs. + * + * Here we expect there will be some number of boards per Fragment. + */ + static int buildTPCFragmentIDToReadoutIDMap_callback + (void* dataOut, int argc, char**argv, char** azColName); + + /** + * @brief Builds a map between the TPC readout board IDs and the associated + * channels. + * + * For each readout board ID we expect a number of channels back from the data + * base. So the returned data structure will be a map of readout ID to a + * vector of channels. + */ + static int buildTPCReadoutBoardToChannelMap_callback + (void* dataOut, int argc, char**argv, char** azColName); + + /// Fills the PMT fragment map with the information from one channel. + static int buildFragmentToDigitizerChannelMap_callback + (void* dataOut, int argc, char**argv, char** azColName); + + /// Fills the channel mapping for side CRT. + static int buildCRTChannelIDToHWtoSimMacAddressPairMap_callback + (void* dataOut, int argc, char**argv, char** azColName); + + /// Fills the channel mapping for top CRT. + static int buildTopCRTHWtoSimMacAddressPairMap_callback + (void* dataOut, int argc, char**argv, char** azColName); + + /// @} + // --- END ----- SQLite callback functions ----------------------------------- + + +}; // icarusDB::ChannelMapSQLite + + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPSQLITE_H diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc deleted file mode 100755 index 955fb195f..000000000 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc +++ /dev/null @@ -1,624 +0,0 @@ -/** - * @file ChannelMapSQLite_tool.cc - * - * @brief This tool converts from daq to LArSoft format with noise filtering - * - */ - -// ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "art/Utilities/make_tool.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "wda.h" - -// LArSoft includes -#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" -#include "larevt/CalibrationDBI/Providers/DBFolder.h" - -// std includes -#include -#include -#include -#include -#include - - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace icarusDB { -/** - * @brief ChannelMapSQLite class definiton - */ -class ChannelMapSQLite : virtual public IChannelMapping -{ -public: - /** - * @brief Constructor - * - * @param pset - */ - explicit ChannelMapSQLite(fhicl::ParameterSet const &pset); - - /** - * @brief Prepares the object for queries pertaining the specified period. - * @param period the period to be prepared for - * @return whether values cached from the previous period are invalidated - * - * Periods are defined in `icarusDB::RunPeriods` class. - * - * If the return value is `true`, caller should follow by rebuilding all the - * maps they need to use. - * If the return value is `false`, all maps built after the previous call to - * `SelectPeriod()` are still current for `period`: building new ones is not - * necessary, but it's not harmful either (at most, wasteful). - */ - virtual bool SelectPeriod(RunPeriod period) override; - - - /** - * @brief Define the returned data structures for a mapping between TPC Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const override; - - /** - * @brief Define the returned data structures for a mapping between TPC readout boards - * and the channel information - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const override; - - /** - * @brief Define the returned data structures for a mapping between PMT Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; - - - /** - * @brief Define the returned data structures for a mapping between CRT hardware mac_address - * to the simulated mac_address. - * Then define the function interface to fill these data structures - */ - virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const override; - virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const override; - - virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const override; - -private: - - /// Record of all relevant table names. - struct TableNames_t { - std::string TPCfragmentMap; - std::string TPCreadoutBoardMap; - std::string PMTfragmentMap; - std::string CRTsideMap; - std::string CRTtopMap; - // NOTE: CRT side calibration is is a different type of database which uses a timestamp - }; - - // Recover data from postgres database - int GetDataset(const std::string&, int func(void*,int,char**,char**), void*) const; - - - std::string fDBFileName; //< File name of our sqlite database - std::string fCalibDBFileName; //< File name of our side crt calibration sqlite database - std::string fTag; //< Tag for conditioned database - - /// The set of tables being served. Chosen by `SelectRun()`. - TableNames_t const* fCurrentTable = nullptr; - - /// The list of names of tables. - static std::array const TableNameSets; - -}; - -ChannelMapSQLite::ChannelMapSQLite(fhicl::ParameterSet const &pset) -{ - fDBFileName = pset.get("DBFileName"); - fCalibDBFileName = pset.get("CalibDBFileName"); - fTag = pset.get("Tag"); - - return; -} - -//------------------------------------------------------------------------------------------------------------------------------------------ -std::array const -ChannelMapSQLite::TableNameSets{ - TableNames_t{ - "readout_boards" // TPCfragmentMap - , "daq_channels" // TPCreadoutBoardMap - , "pmt_placements" // PMTfragmentMap - , "feb_channels" // CRTsideMap - , "crtfeb" // CRTtopMap - }, - TableNames_t{ - "readout_boards" // TPCfragmentMap - , "daq_channels" // TPCreadoutBoardMap - , "pmt_placements_23Aug2023" // PMTfragmentMap - , "feb_channels" // CRTsideMap - , "crtfeb" // CRTtopMap - }, - TableNames_t{ - "readout_boards" // TPCfragmentMap - , "daq_channels" // TPCreadoutBoardMap - , "pmt_placements_29Aug2023" // PMTfragmentMap - , "feb_channels" // CRTsideMap - , "crtfeb" // CRTtopMap - } -}; - - -//------------------------------------------------------------------------------------------------------------------------------------------ -bool ChannelMapSQLite::SelectPeriod(RunPeriod period) { - - auto const iPeriod = static_cast(period); - TableNames_t const* newSet = &(TableNameSets.at(iPeriod)); - - if (fCurrentTable == newSet) { - mf::LogDebug("ChannelMapSQLite") - << "Period #" << iPeriod << " already selected"; - } - else if (fCurrentTable) { - mf::LogDebug("ChannelMapSQLite") << "Switched from period #" - << (fCurrentTable - &(TableNameSets[0])) << " to #" << iPeriod; - } - else { - mf::LogDebug("ChannelMapSQLite") << "Switching to period #" << iPeriod; - } - - if (fCurrentTable == newSet) return false; - - fCurrentTable = newSet; - return true; - -} - - -//------------------------------------------------------------------------------------------------------------------------------------------ - -int callback(void *data, int argc, char **argv, char **azColName) -{ - int i; - - for(i = 0; i; - FlangeIDToCrateMap flangeIDToCrateMap; - flangeIDToCrateMap[19] = "WW01T"; - flangeIDToCrateMap[68] = "WW01M"; - flangeIDToCrateMap[41] = "WW01B"; - flangeIDToCrateMap[11] = "WW02"; - flangeIDToCrateMap[17] = "WW03"; - flangeIDToCrateMap[36] = "WW04"; - flangeIDToCrateMap[18] = "WW05"; - flangeIDToCrateMap[58] = "WW06"; - flangeIDToCrateMap[71] = "WW07"; - flangeIDToCrateMap[14] = "WW08"; - flangeIDToCrateMap[25] = "WW09"; - flangeIDToCrateMap[34] = "WW10"; - flangeIDToCrateMap[67] = "WW11"; - flangeIDToCrateMap[33] = "WW12"; - flangeIDToCrateMap[87] = "WW13"; - flangeIDToCrateMap[10] = "WW14"; - flangeIDToCrateMap[59] = "WW15"; - flangeIDToCrateMap[95] = "WW16"; - flangeIDToCrateMap[22] = "WW17"; - flangeIDToCrateMap[91] = "WW18"; - flangeIDToCrateMap[61] = "WW19"; - flangeIDToCrateMap[55] = "WW20T"; - flangeIDToCrateMap[97] = "WW20M"; - flangeIDToCrateMap[100] = "WW20B"; - flangeIDToCrateMap[83] = "WE01T"; - flangeIDToCrateMap[85] = "WE01M"; - flangeIDToCrateMap[7] = "WE01B"; - flangeIDToCrateMap[80] = "WE02"; - flangeIDToCrateMap[52] = "WE03"; - flangeIDToCrateMap[32] = "WE04"; - flangeIDToCrateMap[70] = "WE05"; - flangeIDToCrateMap[74] = "WE06"; - flangeIDToCrateMap[46] = "WE07"; - flangeIDToCrateMap[81] = "WE08"; - flangeIDToCrateMap[63] = "WE09"; - flangeIDToCrateMap[30] = "WE10"; - flangeIDToCrateMap[51] = "WE11"; - flangeIDToCrateMap[90] = "WE12"; - flangeIDToCrateMap[23] = "WE13"; - flangeIDToCrateMap[93] = "WE14"; - flangeIDToCrateMap[92] = "WE15"; - flangeIDToCrateMap[88] = "WE16"; - flangeIDToCrateMap[73] = "WE17"; - flangeIDToCrateMap[1] = "WE18"; - flangeIDToCrateMap[66] = "WE19"; - flangeIDToCrateMap[48] = "WE20T"; - flangeIDToCrateMap[13] = "WE20M"; - flangeIDToCrateMap[56] = "WE20B"; - flangeIDToCrateMap[94] = "EW01T"; - flangeIDToCrateMap[77] = "EW01M"; - flangeIDToCrateMap[72] = "EW01B"; - flangeIDToCrateMap[65] = "EW02"; - flangeIDToCrateMap[4] = "EW03"; - flangeIDToCrateMap[89] = "EW04"; - flangeIDToCrateMap[37] = "EW05"; - flangeIDToCrateMap[76] = "EW06"; - flangeIDToCrateMap[49] = "EW07"; - flangeIDToCrateMap[60] = "EW08"; - flangeIDToCrateMap[21] = "EW09"; - flangeIDToCrateMap[6] = "EW10"; - flangeIDToCrateMap[62] = "EW11"; - flangeIDToCrateMap[2] = "EW12"; - flangeIDToCrateMap[29] = "EW13"; - flangeIDToCrateMap[44] = "EW14"; - flangeIDToCrateMap[9] = "EW15"; - flangeIDToCrateMap[31] = "EW16"; - flangeIDToCrateMap[98] = "EW17"; - flangeIDToCrateMap[38] = "EW18"; - flangeIDToCrateMap[99] = "EW19"; - flangeIDToCrateMap[53] = "EW20T"; - flangeIDToCrateMap[82] = "EW20M"; - flangeIDToCrateMap[35] = "EW20B"; - flangeIDToCrateMap[96] = "EE01T"; - flangeIDToCrateMap[28] = "EE01M"; - flangeIDToCrateMap[16] = "EE01T"; - flangeIDToCrateMap[69] = "EE02"; - flangeIDToCrateMap[20] = "EE02"; - flangeIDToCrateMap[79] = "EE02"; - flangeIDToCrateMap[50] = "EE02"; - flangeIDToCrateMap[45] = "EE02"; - flangeIDToCrateMap[84] = "EE02"; - flangeIDToCrateMap[42] = "EE02"; - flangeIDToCrateMap[39] = "EE02"; - flangeIDToCrateMap[26] = "EE02"; - flangeIDToCrateMap[64] = "EE02"; - flangeIDToCrateMap[43] = "EE02"; - flangeIDToCrateMap[47] = "EE02"; - flangeIDToCrateMap[15] = "EE02"; - flangeIDToCrateMap[3] = "EE02"; - flangeIDToCrateMap[27] = "EE02"; - flangeIDToCrateMap[24] = "EE02"; - flangeIDToCrateMap[40] = "EE02"; - flangeIDToCrateMap[75] = "EE02"; - flangeIDToCrateMap[86] = "EE20T"; - flangeIDToCrateMap[54] = "EE20M"; - flangeIDToCrateMap[8] = "EE20B"; - - unsigned int fragmentID = std::stol(argv[8],nullptr,16); - - if (fragmentID & tpcIdentifier) - { - if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) - { - unsigned int flangeID = std::stol(argv[1]); - fragmentBoardMap[fragmentID].first = flangeIDToCrateMap[flangeID]; - } - - unsigned int readoutID = std::stol(argv[0]); - fragmentBoardMap[fragmentID].second.emplace_back(readoutID); - - } - - return 0; -} - - // ----------------------------------------------------- - // The aim of this function is to build a map between the - // TPC Fragment IDs and the readout board IDs. Here we - // expect there will be some number of boards per Fragment - //----------------------------------------------------- - int ChannelMapSQLite::BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const - { - assert(fCurrentTable); - const std::string dataType(fCurrentTable->TPCfragmentMap); - - // Recover the data from the database - int error = GetDataset(dataType,buildTPCFragmentIDToReadoutIDMap_callback,&fragmentBoardMap); - - // If there was an error the function above would have printed a message so bail out - if (error) - throw cet::exception("ChannelMapSQLite::BuildTPCFragmentIDToReadoutIDMap") << "Encountered error in reading the database: '" << error << "'\n"; - - return error; - } - - // ----------------------------------------------------- - // The aim of this function is to build a map between the - // TPC readout board IDs and the associated channels. So for - // each readout board ID we expect a number of channels back - // from the data base. So the returned data structure will - // be a map of readout ID to a vector of channels - //----------------------------------------------------- - const unsigned int CHANNELSPERBOARD = 64; - int buildTPCReadoutBoardToChannelMap_callback(void* dataIn, int argc, char**argv, char** azColName) - { - IChannelMapping::TPCReadoutBoardToChannelMap& rbChanMap = *(IChannelMapping::TPCReadoutBoardToChannelMap*)dataIn; - - unsigned int readoutBoardID = std::stol(argv[2]); - - if (rbChanMap.find(readoutBoardID) == rbChanMap.end()) - { - unsigned int readoutBoardSlot = std::stol(argv[4]); - - rbChanMap[readoutBoardID].first = readoutBoardSlot; - rbChanMap[readoutBoardID].second.resize(CHANNELSPERBOARD); - } - - unsigned int channelNum = std::stol(argv[5]); - unsigned int channelID = std::stol(argv[0]); - - std::string fragmentBuffer = argv[10]; - - // Make sure lower case... (sigh...) - std::transform(fragmentBuffer.begin(),fragmentBuffer.end(),fragmentBuffer.begin(),[](char c){return std::tolower(c);}); - - unsigned int plane(3); - - if (fragmentBuffer.find("collection") != std::string::npos) plane = 2; - else if (fragmentBuffer.find("induction 2") != std::string::npos) plane = 1; - else if (fragmentBuffer.find("induction 1") != std::string::npos) plane = 0; - - if (plane > 2) std::cout << "YIKES!!! Plane is " << plane << " for channel " << channelID << " with type " << std::string(fragmentBuffer) << std::endl; - - rbChanMap[readoutBoardID].second[channelNum] = IChannelMapping::ChannelPlanePair(channelID,plane); - - return 0; - } - - int ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap& rbChanMap) const - { - assert(fCurrentTable); - const std::string dataType(fCurrentTable->TPCreadoutBoardMap); - - // Recover the data from the database - int error = GetDataset(dataType,buildTPCReadoutBoardToChannelMap_callback,&rbChanMap); - - // If there was an error the function above would have printed a message so bail out - if (error) - throw cet::exception("ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap") << "Encountered error in reading the database: '" << error << "'\n"; - - return error; - } - - //******************* PMT Channel Mapping *********************** - int buildFragmentToDigitizerChannelMap_callback(void* dataIn, int argc, char**argv, char** azColName) - { - IChannelMapping::FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap = *(IChannelMapping::FragmentToDigitizerChannelMap*)dataIn; - - // Start extracting info - // std::string digitizerBuffer = argv[8]; - unsigned int fragmentID = std::stol(argv[18]); - unsigned int digitizerChannelNo = std::stol(argv[9]); - unsigned int channelID = std::stol(argv[17]); - - // Read the laser channel - std::string laserChannelLabel = argv[7]; // format is L- . is int from [1-41] - unsigned int laserChannel = std::stol(laserChannelLabel.substr(2,4)); // try-catch syntax for stol or not necessary ? - - - // Fill the map - fragmentToDigitizerChannelMap[fragmentID].emplace_back(digitizerChannelNo,channelID,laserChannel); - - return 0; - } - - int ChannelMapSQLite::BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const - { - // clearing is cleansing - fragmentToDigitizerChannelMap.clear(); - // Recover the information from the database on the mapping - assert(fCurrentTable); - const std::string dataType(fCurrentTable->PMTfragmentMap); - - // Recover the data from the database - int error = GetDataset(dataType,buildFragmentToDigitizerChannelMap_callback,&fragmentToDigitizerChannelMap); - - // If there was an error the function above would have printed a message so bail out - if (error) - throw cet::exception("ChannelMapSQLite::BuildFragmentToDigitizerChannelMap") - << "Encountered error (code: " << error << ") in reading the database\n"; - - return error; - } - - - //******************* CRT Channel Mapping *********************** - - int buildCRTChannelIDToHWtoSimMacAddressPairMap_callback(void* dataIn, int argc, char**argv, char** azColName) - { - IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap = *(IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap*)dataIn; - - /* - // Start extracting info - unsigned int channelID = std::stol(argv[10]); - unsigned int simmacaddress = std::stol(argv[11]); - unsigned int hwmacaddress = std::stol(argv[12]); - */ - - unsigned int channelID = strcmp(argv[10],"None")==0 ? 0 : std::stol(argv[10]); - unsigned int simmacaddress = strcmp(argv[11],"None")==0 ? 0 : std::stol(argv[11]); - unsigned int hwmacaddress = strcmp(argv[12],"None")==0 ? 0 : std::stol(argv[12]); - - // Fill the map - crtChannelIDToHWtoSimMacAddressPairMap[channelID]=std::make_pair(hwmacaddress, simmacaddress); - - return 0; - } - - int ChannelMapSQLite::BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap) const - { - // clearing is cleansing - crtChannelIDToHWtoSimMacAddressPairMap.clear(); - // Recover the information from the database on the mapping - assert(fCurrentTable); - const std::string dataType(fCurrentTable->CRTsideMap); - - // Recover the data from the database - int error = GetDataset(dataType,buildCRTChannelIDToHWtoSimMacAddressPairMap_callback,&crtChannelIDToHWtoSimMacAddressPairMap); - - // If there was an error the function above would have printed a message so bail out - if (error) - throw cet::exception("ChannelMapSQLite::BuildCRTChannelIDToHWtoSimMacAddressPairMap") << "Encountered error in reading the database: '" << error << "'\n"; - - return error; - } - - // Top CRT - //---------------------------------- - int buildTopCRTHWtoSimMacAddressPairMap_callback(void* dataIn, int argc, char**argv, char** azColName) - { - IChannelMapping::TopCRTHWtoSimMacAddressPairMap& topcrtHWtoSimMacAddressPairMap = *(IChannelMapping::TopCRTHWtoSimMacAddressPairMap*)dataIn; - - // Start extracting info - unsigned int simmacaddress = strcmp(argv[41],"None")==0 ? 0 : std::stol(argv[41]); - unsigned int hwmacaddress = strcmp(argv[3], "None")==0 ? 0 : std::stol(argv[3]); - - // Fill the map - topcrtHWtoSimMacAddressPairMap[hwmacaddress] = simmacaddress; - - return 0; - } - - int ChannelMapSQLite::BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap& topcrtHWtoSimMacAddressPairMap) const - { - // clearing is cleansing - topcrtHWtoSimMacAddressPairMap.clear(); - // Recover the information from the database on the mapping - assert(fCurrentTable); - const std::string dataType(fCurrentTable->CRTtopMap); - - // Recover the data from the database - int error = GetDataset(dataType,buildTopCRTHWtoSimMacAddressPairMap_callback,&topcrtHWtoSimMacAddressPairMap); - - // If there was an error the function above would have printed a message so bail out - if (error) - throw cet::exception("ChannelMapSQLite::BuildTopCRTHWtoSimMacAddressPairMap") << "Encountered error in reading the database: '" << error << "'\n"; - - return error; - } - - - //******************* Accessing Side CRT Calibration Database *********************** - - int ChannelMapSQLite::BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap& sideCRTChannelToCalibrationMap) const - { - // clearing is cleansing - sideCRTChannelToCalibrationMap.clear(); - - std::string fullFileName; - cet::search_path searchPath("FW_SEARCH_PATH"); - - - if (!searchPath.find_file(fCalibDBFileName+".db", fullFileName)){ - std::cout << "******* Succesfully found calibration input file: " << fCalibDBFileName << std::endl; - throw cet::exception("ChannelMapSQLite::GetDataset") << "Can't find calibration input file: '" << fCalibDBFileName << "'\n"; - } - - lariov::DBFolder database(fCalibDBFileName, "", "", fTag, true, false); - - database.UpdateData(1638918271*1e9); - - std::vector channels; - database.GetChannelList(channels); - - for (auto it = channels.begin(); it != channels.end(); ++it) { - - long mac5, chan; - double gain, ped; - - // Start extracting info - database.GetNamedChannelData(*it, "mac5", mac5); - database.GetNamedChannelData(*it, "localchannel", chan); - database.GetNamedChannelData(*it, "gain", gain); - database.GetNamedChannelData(*it, "pedestal", ped); - - // Fill the map - sideCRTChannelToCalibrationMap.insert(std::make_pair(std::make_pair((int)mac5,(int)chan), std::make_pair(gain,ped))); - } - - return 0; - } - - - DEFINE_ART_CLASS_TOOL(ChannelMapSQLite) -} // namespace lar_cluster3d diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx new file mode 100644 index 000000000..bd4ecf39d --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx @@ -0,0 +1,438 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h + */ + +// library header +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "larcorealg/CoreUtils/values.h" // util::const_values() + +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "fhiclcpp/ParameterSet.h" +#include "cetlib_except/exception.h" +#include "cetlib/cpu_timer.h" + +// C++ standard libraries +#include +#include +#include + + + +// ----------------------------------------------------------------------------- +icarusDB::ICARUSChannelMapSQLiteProvider::ICARUSChannelMapSQLiteProvider + (Config const& config) + : fDiagnosticOutput{ config.DiagnosticOutput() } + , fLogCategory{ config.LogCategory() } + , fChannelMappingAlg + { std::make_unique(config.ChannelMappingTool()) } +{ +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapSQLiteProvider::forRun(int run) { + + RunPeriod period = RunPeriod::NPeriods; + try { + period = RunPeriods::withRun(run); + } catch (...) { + mf::LogError{ fLogCategory } + << "Failed to associate a run period number to run " << run << "."; + throw; + } + + if (period == RunPeriod::NPeriods) { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "forRun(): can't determine the period of run " << run << "!\n"; + } + + return forPeriod(period); + +} // icarusDB::ICARUSChannelMapSQLiteProvider::forRun() + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapSQLiteProvider::forPeriod + (icarusDB::RunPeriod period) +{ + + // if cache is not invalidated, we don't refresh it + if (!fChannelMappingAlg->SelectPeriod(period)) return false; + + readFromDatabase(); + return true; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapSQLiteProvider::hasFragmentID + (const unsigned int fragmentID) const +{ + return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nTPCfragmentIDs() const { + return fFragmentToReadoutMap.size(); +} + + +// ----------------------------------------------------------------------------- +std::string const& icarusDB::ICARUSChannelMapSQLiteProvider::getCrateName + (const unsigned int fragmentID) const +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking up crate name \n"; + } + + return fragToReadoutItr->second.first; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::getReadoutBoardVec + (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking up board vector.\n"; + } + + return fragToReadoutItr->second.second; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::getReadoutBoardToChannelMap() + const -> const TPCReadoutBoardToChannelMap& +{ + return fReadoutBoardToChannelMap; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapSQLiteProvider::hasBoardID + (const unsigned int boardID) const +{ + return + fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nTPCboardIDs() const { + return fReadoutBoardToChannelMap.size(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::getBoardSlot + (const unsigned int boardID) const +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Board ID " << boardID + << " not found in lookup map when looking up board slot.\n"; + } + + return readoutBoardItr->second.first; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::getChannelPlanePair + (const unsigned int boardID) const -> ChannelPlanePairVec const& +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Board ID " << boardID + << " not found in lookup map when looking up channel/plane pair.\n"; + } + + return readoutBoardItr->second.second; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapSQLiteProvider::hasPMTDigitizerID + (const unsigned int fragmentID) const +{ + return findPMTfragmentEntry(fragmentID) != nullptr; +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nPMTfragmentIDs() const { + return fFragmentToDigitizerMap.size(); +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::getChannelIDPairVec + (const unsigned int fragmentID) const + -> DigitizerChannelChannelIDPairVec const& +{ + mf::LogTrace{ "ICARUSChannelMapSQLiteProvider" } + << "Call to: ICARUSChannelMapSQLiteProvider::getChannelIDPairVec(" + << fragmentID << ")"; + + DigitizerChannelChannelIDPairVec const* digitizerPair + = findPMTfragmentEntry(fragmentID); + + if (digitizerPair) return *digitizerPair; + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking for PMT channel info.\n"; + +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::getSimMacAddress + (const unsigned int hwmacaddress) const +{ + for(auto const& [ hw, sim ] + : util::const_values(fCRTChannelIDToHWtoSimMacAddressPairMap) + ) { + if (hw == hwmacaddress) return sim; + } + + return 0; +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::gettopSimMacAddress + (const unsigned int hwmacaddress) const +{ +#if 0 // FIXME + unsigned int simmacaddress = 0; + + for(const auto& pair : fTopCRTHWtoSimMacAddressPairMap){ + if (pair.first == hwmacaddress) +simmacaddress = pair.second; + } + + return simmacaddress; +#else + // untested: + auto const it = fTopCRTHWtoSimMacAddressPairMap.find(hwmacaddress); + return (it == fTopCRTHWtoSimMacAddressPairMap.end())? 0: it->second; + +#endif +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::getSideCRTCalibrationMap + (int mac5, int chan) const -> std::pair +{ + auto const itGainAndPedestal + = fSideCRTChannelToCalibrationMap.find({ mac5, chan }); + return (itGainAndPedestal == fSideCRTChannelToCalibrationMap.cend()) + ? std::pair{ -99., -99. }: itGainAndPedestal->second; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapSQLiteProvider::findPMTfragmentEntry + (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* +{ + auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); + return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); +} + + +// ----------------------------------------------------------------------------- +void icarusDB::ICARUSChannelMapSQLiteProvider::readFromDatabase() { + + mf::LogInfo{ fLogCategory } << "Building the channel mapping"; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC fragment-based mapping + cet::cpu_timer theClockFragmentIDs; + theClockFragmentIDs.start(); + fFragmentToReadoutMap.clear(); + if (fChannelMappingAlg->BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) + { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Cannot recover the TPC fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + + mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; + log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() + << " elements"; + for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " + << crateAndBoards.first << ", # boards: " + << crateAndBoards.second.size(); + } + } + theClockFragmentIDs.stop(); + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC readout-board-based mapping + double fragmentIDsTime = theClockFragmentIDs.accumulated_real_time(); + + cet::cpu_timer theClockReadoutIDs; + theClockReadoutIDs.start(); + + fReadoutBoardToChannelMap.clear(); + if (fChannelMappingAlg->BuildTPCReadoutBoardToChannelMap(fReadoutBoardToChannelMap)) + { + mf::LogError{ "ICARUSChannelMapSQLiteProvider" } + << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Failed to read the database.\n"; + } + + theClockReadoutIDs.stop(); + double readoutIDsTime = theClockReadoutIDs.accumulated_real_time(); + + mf::LogInfo{ "ICARUSChannelMapSQLiteProvider" } + << "==> FragmentID map time: " << fragmentIDsTime << ", Readout IDs time: " + << readoutIDsTime; + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // PMT channel mapping + fFragmentToDigitizerMap.clear(); + if (fChannelMappingAlg->BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) + { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Cannot recover the PMT fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; + log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() + << " Fragment IDs"; + + for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec + << ", # pairs: " << digitizers.size(); + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Side CRT channel mapping + fCRTChannelIDToHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg->BuildCRTChannelIDToHWtoSimMacAddressPairMap(fCRTChannelIDToHWtoSimMacAddressPairMap)) + { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Cannot recover the HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; + log << "ChannelID to MacAddress map has " + << fCRTChannelIDToHWtoSimMacAddressPairMap.size() << " Channel IDs"; + for(auto const& [ channel, addresses ]: fCRTChannelIDToHWtoSimMacAddressPairMap) { + log <<"\n ChannelID: "<< channel + << ", hw mac address: " << addresses.first + << ", sim mac address: " << addresses.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Top CRT channel mapping + fTopCRTHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg->BuildTopCRTHWtoSimMacAddressPairMap(fTopCRTHWtoSimMacAddressPairMap)) + { + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Cannot recover the Top CRT HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; + log << "Top CRT MacAddress map has " << fTopCRTHWtoSimMacAddressPairMap.size() << " rows"; + for(auto const [ hwaddress, simaddress ]: fTopCRTHWtoSimMacAddressPairMap) { + log << "\n hw mac address: " << hwaddress + << ", sim mac address: " << simaddress; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // CRT Charge Calibration initialization + fSideCRTChannelToCalibrationMap.clear(); + if (fChannelMappingAlg->BuildSideCRTCalibrationMap(fSideCRTChannelToCalibrationMap)) + { + mf::LogError{ "ICARUSChannelMapSQLiteProvider" } + << "******* FAILED TO CONFIGURE CRT Calibration ********"; + throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } + << "Cannot recover the CRT charge calibration information from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; + log << "side crt calibration map has " + << fSideCRTChannelToCalibrationMap.size() << " list of rows"; + + for(auto const& [ key, calib ]: fSideCRTChannelToCalibrationMap) { + log << "\n mac5: "<< key.first << ", chan: " << key.second + << ", Gain: " << calib.first << ", Pedestal: " << calib.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +} // icarusDB::ICARUSChannelMapSQLiteProvider::readFromDatabase() + + +// ----------------------------------------------------------------------------- +constexpr unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey + (unsigned int fragmentID) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert(((fragmentID & ~0xFF) == 0x00) || ((fragmentID & ~0xFF) == 0x20)); + + return fragmentID & 0xFF; + +} // ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- +constexpr unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::DBkeyToPMTfragmentID + (unsigned int DBkey) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert((DBkey & 0xFF) < 24); + + return (DBkey & 0xFF) | 0x2000; + +} // icarusDB::ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h new file mode 100644 index 000000000..2eb6604fa --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h @@ -0,0 +1,243 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPSQLITEPROVIDER_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPSQLITEPROVIDER_H + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" +#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h" + +// framework libraries +#include "fhiclcpp/types/Table.h" +#include "fhiclcpp/types/Atom.h" +#include "cetlib_except/exception.h" + +// C/C++ standard libraries +#include +#include // std::unique_ptr<> + + +// ----------------------------------------------------------------------------- +namespace icarusDB { class ICARUSChannelMapSQLiteProvider; } +/** + * @brief Interface to the SQLite ICARUS channel mapping database. + * + * The database is normally distributed as a file in `icarus_data`. + * + * + * Configuration parameters + * ========================= + * + * * `ChannelMappingTool` ( + * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters + * and in general prints more messages to console + * + * + */ +class icarusDB::ICARUSChannelMapSQLiteProvider: public IICARUSChannelMap { + + public: + /// The helper used to extract data from the database. + using ChannelMappingAlg_t = icarusDB::ChannelMapSQLite; + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Table ChannelMappingTool { + Name{ "ChannelMappingTool" }, + Comment{ "parameters for the channel mapping algorithm" } + }; + + fhicl::Atom DiagnosticOutput{ + Name{ "DiagnosticOutput" }, + Comment{ "enables verbose output to console" }, + false // default + }; + + fhicl::Atom LogCategory{ + Name{ "LogCategory" }, + Comment{ "name of the console stream to send messages to" }, + "ICARUSChannelMapSQLiteProvider" // default + }; + + }; // Config + + using Parameters = fhicl::Table; + + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapSQLiteProvider(Config const& config); + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapSQLiteProvider(Parameters const& params) + : ICARUSChannelMapSQLiteProvider{ params() } + {} + + + /// --- BEGIN --- Data period selection ------------------------------------ + /// @name Data period selection + /// @{ + + /// Loads the mapping for `run`, returns whether a new mapping was loaded. + virtual bool forRun(int run) override; + + /// Loads the mapping for `period`, returns whether a new mapping was loaded. + virtual bool forPeriod(icarusDB::RunPeriod period) override; + + /// @} + /// --- END ----- Data period selection ------------------------------------ + + + /// --- BEGIN --- TPC information ------------------------------------------ + /// @name TPC information + /// @{ + + /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - + /// @name TPC fragment information + /// @{ + + /// Returns whether the specified `ID` is a known TPC fragment ID. + virtual bool hasFragmentID(const unsigned int ID) const override; + /// Returns the number of TPC fragment IDs known to the service. + + /// Returns the number of known TPC fragments. + virtual unsigned int nTPCfragmentIDs() const override; + + /// Returns the name of the crate served by the specified `fragmentID`. + virtual std::string const& getCrateName + (const unsigned int fragmentID) const override; + + /// Returns the list of board IDs included in the specified `fragmentID`. + virtual ReadoutIDVec const& getReadoutBoardVec + (const unsigned int fragmentID) const override; + + /// @} + /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - + + /** + * @brief Returns the full TPC channel mapping. + * + * The returned mapping is an associative container, associating each board + * ID (`boardID`) to the following information (in a `std::tuple`): + * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) + * * `[1]` list of channels served by the board, and their plane + * (like `getChannelPlanePair(boardID)`) + * + */ + virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const + override; + + /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - + /// @name TPC board information + /// @{ + + /// Returns whether there is a board with the specified `ID`. + virtual bool hasBoardID(const unsigned int ID) const override; + /// Returns the number of TPC board IDs known to the service. + virtual unsigned int nTPCboardIDs() const override; + /// Returns the number of slot the `boardID` is on. + virtual unsigned int getBoardSlot(const unsigned int boardID) const override; + /// Returns a list of channels served by the `boardID` and for each the plane + /// it is on (`0` to `2`). + virtual ChannelPlanePairVec const& getChannelPlanePair + (const unsigned int boardID) const override; + + /// @} + /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - + + + /// --- BEGIN --- PMT information ------------------------------------------ + /// @name PMT information + /// @{ + + /// Returns whether the specified fragment `ID` is known to the mapping. + virtual bool hasPMTDigitizerID(const unsigned int ID) const override; + + /// Returns the number of PMT fragment IDs known to the mapping. + virtual unsigned int nPMTfragmentIDs() const override; + + /// Returns a list of triplets: + virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec + (const unsigned int) const override; + + /// @} + /// --- END ----- PMT information ------------------------------------------ + + + /// --- BEGIN --- CRT information ------------------------------------------ + /// @name CRT information + /// @{ + + /// Returns the sim Mac address corresponding to the specified side CRT hardware address. + virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const override; + /// Returns the sim Mac address corresponding to the specified top CRT hardware address. + virtual unsigned int gettopSimMacAddress(const unsigned int) const override; + + /// Returns the Gain and Pedestal for Side CRT. + virtual std::pair getSideCRTCalibrationMap + (int mac5, int chan) const override; + + /// @} + /// --- END ----- CRT information ------------------------------------------ + + /// Returns the channel mapping database key for the specified PMT fragment ID. + static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); + + /// Returns the PMT fragment ID for the specified channel mapping database key. + static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); + + + private: + + // --- BEGIN --- Configuration parameters ------------------------------------ + + bool const fDiagnosticOutput; + + std::string const fLogCategory; + + // --- END ----- Configuration parameters ------------------------------------ + + + // --- BEGIN --- Cache ------------------------------------------------------- + IChannelMapping::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; + + IChannelMapping::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; + + IChannelMapping::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + + IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; + + IChannelMapping::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; + + IChannelMapping::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; + + // --- END ----- Cache ------------------------------------------------------- + + /// The helper extracting information from the database. + std::unique_ptr fChannelMappingAlg; + + + /// Has the channel mapping tool fill the mapping caches. + virtual void readFromDatabase(); + + + /// Returns the list of board channel-to-PMT channel ID mapping within the + /// specified fragment. + /// + /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment + DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry + (unsigned int fragmentID) const; + + +}; // icarusDB::ICARUSChannelMapSQLiteProvider + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPSQLITEPROVIDER_H diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc new file mode 100644 index 000000000..fb670900a --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc @@ -0,0 +1,72 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc + * @brief Wrapper service for `icarusDB::ICARUSChannelMapProvider`. + * @author Gianluca Petrillo (petrillo@slac.stanford.edu) + */ + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" + +// framework libraries +#include "art/Framework/Services/Registry/ActivityRegistry.h" +#include "art/Framework/Services/Registry/ServiceDefinitionMacros.h" +#include "art/Framework/Services/Registry/ServiceDeclarationMacros.h" +#include "art/Framework/Services/Registry/ServiceTable.h" +#include "art/Framework/Principal/Run.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "fhiclcpp/ParameterSet.h" +#include "cetlib_except/exception.h" + + +// ----------------------------------------------------------------------------- +namespace icarusDB { class ICARUSChannelMapSQLite; } +class icarusDB::ICARUSChannelMapSQLite: public ICARUSChannelMapSQLiteProvider { + + /// Prepares the mapping for the specified run. + void preBeginRun(art::Run const& run); + + public: + + using provider_type = icarusDB::ICARUSChannelMapSQLiteProvider; + + using Parameters = art::ServiceTable; + + /// Constructor: configures the provider and hooks to the framework. + ICARUSChannelMapSQLite(Parameters const& params, art::ActivityRegistry& reg); + + /// Returns the service provider (for use with `lar::providerFrom()`). + provider_type const* provider() const { return this; } + +}; // class icarusDB::ICARUSChannelMapSQLite + + +// ----------------------------------------------------------------------------- +// --- Implementation +// ----------------------------------------------------------------------------- +icarusDB::ICARUSChannelMapSQLite::ICARUSChannelMapSQLite + (Parameters const& params, art::ActivityRegistry& reg) + : provider_type(params()) +{ + reg.sPreBeginRun.watch(this, &ICARUSChannelMapSQLite::preBeginRun); + forPeriod(RunPeriod::Runs0to2); // prepare for some run, in case anybody asks +} + + +// ----------------------------------------------------------------------------- +void icarusDB::ICARUSChannelMapSQLite::preBeginRun(art::Run const& run) { + if (forRun(run.run())) { + mf::LogDebug{ "ICARUSChannelMapSQLite" } + << "Loaded mapping for run " << run.run(); + } +} + + +// ----------------------------------------------------------------------------- +DECLARE_ART_SERVICE_INTERFACE_IMPL + (icarusDB::ICARUSChannelMapSQLite, icarusDB::IICARUSChannelMap, SHARED) +DEFINE_ART_SERVICE_INTERFACE_IMPL + (icarusDB::ICARUSChannelMapSQLite, icarusDB::IICARUSChannelMap) + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/IChannelMapping.h b/icaruscode/Decode/ChannelMapping/IChannelMapping.h index 44af000ca..65532fd84 100755 --- a/icaruscode/Decode/ChannelMapping/IChannelMapping.h +++ b/icaruscode/Decode/ChannelMapping/IChannelMapping.h @@ -13,8 +13,18 @@ // ICARUS libraries #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" -// Framework Includes -#include "fhiclcpp/ParameterSet.h" +// LArSoft libraries +#include "larcorealg/CoreUtils/enumerate.h" + +// C/C++ standard libraries +#include // std::transform() +#include +#include +#include +#include +#include +#include // std::tolower() + //------------------------------------------------------------------------------------------------------------------------------------------ @@ -100,6 +110,32 @@ namespace icarusDB virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const = 0; + // --- BEGIN --- Utility functions for the implementation ------------------ + + static constexpr unsigned int ChannelsPerTPCreadoutBoard = 64; + + /// Turns and returns a string into lowercase. + template + static void makeLowerCase(String& s) { + using std::cbegin, std::cend, std::begin, std::end; + std::transform(cbegin(s), cend(s), begin(s), + [](unsigned char c){ return std::tolower(c); }); + } + + /// Returns the plane identified by `planeStr`: `0` to `2`; `3` if invalid. + static unsigned int TPCplaneIdentifierToPlane(std::string planeStr) + { + using namespace std::string_literals; + makeLowerCase(planeStr); // Make sure lower case... (sigh...) + static std::array const PlaneNames + = { "induction 1"s, "induction 2"s, "collection"s }; + for (auto const& [ plane, planeName ]: util::enumerate(PlaneNames)) + if (planeStr.find(planeName) != std::string::npos) return plane; + return PlaneNames.size(); + } + + // --- BEGIN --- Utility functions for the implementation ------------------ + }; } // namespace lar_cluster3d diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc new file mode 100644 index 000000000..e184e87bd --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc @@ -0,0 +1,52 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc + * @brief _art_ tool wrapping ICARUS channel mapping PostGres database helper. + * @author Gianluca Petrillo (petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx + * + * This tool is a bit unusual in _art_ standards in that the name of the tool + * class, `ChannelMapPostGresTool`, does not match the name of the file, + * `ChannelMapPostGres_tool.cc` (normally it would be + * `ChannelMapPostGresTool_tool.cc`). + * The choice of this source file name is for backward compatibility, + * since before this refactoring a tool called `ChannelMapPostGres` existed. + * The choice to change the name to _the class_ is that in the refactoring + * `icarusDB::ChannelMapPostGres` still exists but it's not an _art_ tool any + * more but rather a plain algorithm. + * + * When choosing a tool, the configuration parameter `tool_type` is used to + * put together the name expected for the library, and by default than name is + * based on the name of the source file without suffix, i.e. + * `ChannelMapPostGres`: so, `tool_type: ChannelMapPostGres` will be enough to + * find the library. Once in the library, _art_ uses as the tool object the one + * specified by the `DEFINE_ART_CLASS_TOOL()` macro, which is + * `icarusDB::ChannelMapPostGresTool`. So everything works. + */ + +#include "icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h" +#include "art/Utilities/ToolMacros.h" +#include "art/Utilities/ToolConfigTable.h" +#include "fhiclcpp/types/TableFragment.h" + + +namespace icarusDB { class ChannelMapPostGresTool; } + +/// Toolification of `icarusDB::ChannelMapPostGres`. +struct icarusDB::ChannelMapPostGresTool: public icarusDB::ChannelMapPostGres { + + struct Config { + + fhicl::TableFragment ChannelMapPostGresConfig; + + }; + + using Parameters = art::ToolConfigTable; + + ChannelMapPostGresTool(Parameters const& params) + : icarusDB::ChannelMapPostGres{ params().ChannelMapPostGresConfig() } + {} + +}; // icarusDB::ChannelMapPostGresTool + + +DEFINE_ART_CLASS_TOOL(icarusDB::ChannelMapPostGresTool) diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc new file mode 100755 index 000000000..aa76fde99 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc @@ -0,0 +1,54 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc + * @brief _art_ tool wrapping ICARUS channel mapping SQLite database helper. + * @author Gianluca Petrillo (petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx + * + * This tool is a bit unusual in _art_ standards in that the name of the tool + * class, `ChannelMapSQLiteTool`, does not match the name of the file, + * `ChannelMapSQLite_tool.cc` (normally it would be + * `ChannelMapSQLiteTool_tool.cc`). + * The choice of this source file name is for backward compatibility, + * since before this refactoring a tool called `ChannelMapSQLite` existed. + * The choice to change the name to _the class_ is that in the refactoring + * `icarusDB::ChannelMapSQLite` still exists but it's not an _art_ tool any more + * but rather a plain algorithm. + * + * When choosing a tool, the configuration parameter `tool_type` is used to + * put together the name expected for the library, and by default than name is + * based on the name of the source file without suffix, i.e. `ChannelMapSQLite`: + * so, `tool_type: ChannelMapSQLite` will be enough to find the library. + * Once in the library, _art_ uses as the tool object the one specified by the + * `DEFINE_ART_CLASS_TOOL()` macro, which is `icarusDB::ChannelMapSQLiteTool`. + * So everything works. + */ + +#include "icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h" +#include "art/Utilities/ToolMacros.h" +#include "art/Utilities/ToolConfigTable.h" +#include "fhiclcpp/types/TableFragment.h" + + +namespace icarusDB { class ChannelMapSQLiteTool; } + +/// Toolification of `icarusDB::ChannelMapSQLite`. +struct icarusDB::ChannelMapSQLiteTool: public icarusDB::ChannelMapSQLite { + + struct Config { + + fhicl::TableFragment ChannelMapSQLiteConfig; + + }; + + using Parameters = art::ToolConfigTable; + + ChannelMapSQLiteTool(Parameters const& params) + : icarusDB::ChannelMapSQLite{ params().ChannelMapSQLiteConfig() } + {} + +}; // icarusDB::ChannelMapSQLiteTool + + +DEFINE_ART_CLASS_TOOL(icarusDB::ChannelMapSQLiteTool) + + diff --git a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx index 68a40f832..944c6ddd4 100644 --- a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx @@ -13,7 +13,8 @@ // ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // LArSoft and framework libraries @@ -71,9 +72,7 @@ class Pager { // ----------------------------------------------------------------------------- -void dumpTPCmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { - - // TODO +void dumpTPCmapping(icarusDB::IICARUSChannelMap const& mapping) { constexpr unsigned int FragmentIDoffset = 0x1000; @@ -151,7 +150,7 @@ void dumpTPCmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- -void dumpPMTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { +void dumpPMTmapping(icarusDB::IICARUSChannelMap const& mapping) { mf::LogVerbatim log("PMTchannelMappingDumper"); unsigned int nFragmentIDs = mapping.nPMTfragmentIDs(); @@ -199,7 +198,7 @@ void dumpPMTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- -void dumpCRTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { +void dumpCRTmapping(icarusDB::IICARUSChannelMap const& mapping) { mf::LogVerbatim log("PMTchannelMappingDumper"); @@ -225,7 +224,7 @@ void dumpCRTmapping(icarusDB::ICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- -void dumpMapping(icarusDB::ICARUSChannelMapProvider const& channelMapping) { +void dumpMapping(icarusDB::IICARUSChannelMap const& channelMapping) { mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); dumpTPCmapping(channelMapping); @@ -264,7 +263,7 @@ int main(int argc, char** argv) { Environment const Env { config }; - icarusDB::ICARUSChannelMapProvider channelMapping + icarusDB::ICARUSChannelMapSQLiteProvider channelMapping { Env.ServiceParameters("IICARUSChannelMap") }; for (icarusDB::RunPeriod const period: icarusDB::RunPeriods::All) From 876de6d168f6e58007d40debe04a1378065b0bb6 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Fri, 23 Feb 2024 17:20:57 -0600 Subject: [PATCH 03/19] fixup --- .../Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h index 2eb6604fa..03b0e0ec9 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h @@ -33,10 +33,13 @@ namespace icarusDB { class ICARUSChannelMapSQLiteProvider; } * Configuration parameters * ========================= * - * * `ChannelMappingTool` ( + * * `ChannelMappingTool` (algorithm configuration): see + * `icarusDB::ChannelMapSQLite` configuration. * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters * and in general prints more messages to console - * + * * `LogCategory` (string, default: `"ICARUSChannelMapSQLiteProvider"`): + * name of the messagefacility category used to send messages to console, + * useful for filtering messages. * */ class icarusDB::ICARUSChannelMapSQLiteProvider: public IICARUSChannelMap { From e65a3892ef40d45a07f6dcc58939ec4294caaf4d Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Fri, 23 Feb 2024 17:19:03 -0600 Subject: [PATCH 04/19] Moved ChannelMapSQLite tool to "Legacy" directory --- icaruscode/Decode/ChannelMapping/CMakeLists.txt | 6 +----- .../Decode/ChannelMapping/Legacy/CMakeLists.txt | 16 ++++++++++++++++ .../Legacy/ChannelMapSQLite_tool.cc | 0 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt mode change 100755 => 100644 icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index 73b822ec0..bac61df2b 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -80,11 +80,6 @@ cet_build_plugin(ICARUSChannelMapSQLite art::service messagefacility::headers ) -cet_build_plugin(ChannelMapSQLite art::tool - LIBRARIES - icaruscode::Decode_ChannelMapping - ) - cet_make_exec(NAME "PMTChannelMapDumper" LIBRARIES icaruscode::Decode_ChannelMapping @@ -100,3 +95,4 @@ install_headers() install_fhicl() install_source() +add_subdirectory("Legacy") diff --git a/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt new file mode 100644 index 000000000..536ee3f23 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt @@ -0,0 +1,16 @@ +cet_enable_asserts() + +cet_build_plugin(ChannelMapSQLite art::tool + LIBRARIES + icaruscode::Decode_ChannelMapping + ) + +cet_build_plugin(ChannelMapPostGres art::tool + LIBRARIES + icaruscode::Decode_ChannelMapping + ) + +install_headers() +install_fhicl() +install_source() + diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc old mode 100755 new mode 100644 From 4bcd4f76425860b7190b8814d5d04475004b2a09 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Fri, 23 Feb 2024 17:23:34 -0600 Subject: [PATCH 05/19] Refactoring of PostgreSQL access to channel map DB --- .../Decode/ChannelMapping/CMakeLists.txt | 11 +- .../ChannelMapping/ChannelMapPostGres.cxx | 657 ++++++++++++++++++ .../ChannelMapping/ChannelMapPostGres.h | 238 +++++++ .../ICARUSChannelMapPostGresProvider.cxx | 438 ++++++++++++ .../ICARUSChannelMapPostGresProvider.h | 247 +++++++ .../ICARUSChannelMapPostGres_service.cc | 104 +++ 6 files changed, 1693 insertions(+), 2 deletions(-) create mode 100644 icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx create mode 100644 icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index bac61df2b..0cf1b60e1 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -11,6 +11,15 @@ art_make_library( cetlib::cetlib larcorealg::CoreUtils + # for PostGres algorithms (includes duplicates above) + icarusalg::Utilities + larcorealg::CoreUtils + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib::cetlib + cetlib_except::cetlib_except + wda::wda + # for SQLite algorithms (includes duplicates above) icarusalg::Utilities larevt::CalibrationDBI_Providers @@ -68,8 +77,6 @@ set( TOOL_LIBRARIES larevt::CalibrationDBI_Providers ) -cet_build_plugin(ChannelMapPostGres art::tool LIBRARIES ${TOOL_LIBRARIES}) -# cet_build_plugin(ChannelMapSQLite art::tool LIBRARIES ${TOOL_LIBRARIES}) cet_build_plugin(ICARUSChannelMap art::service LIBRARIES ${SERVICE_LIBRARIES}) cet_build_plugin(ICARUSChannelMapSQLite art::service diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx new file mode 100644 index 000000000..4ab4479bc --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx @@ -0,0 +1,657 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx + * @brief Interface with ICARUS channel mapping PostGres database. + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h + */ + +// library header +#include "icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h" + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/PositionFinder.h" + +// LArSoft libraries +#include "larcorealg/CoreUtils/counter.h" + +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "cetlib_except/exception.h" +#include "wda.h" // getDataWithTimeout(), getTuple(), getStringValue(), ... + +// C/C++ standard libraries +#include +#include +#include +#include +#include + + +// ----------------------------------------------------------------------------- +namespace icarusDB::details { + + struct WDADatasetDeleter + { void operator() (Dataset dataset) { releaseDataset(dataset); } }; + struct WDATupleDeleter + { void operator() (Tuple tuple) { releaseTuple(tuple); } }; + + struct WDADataset: std::unique_ptr { + WDADataset(Dataset dataset) + : std::unique_ptr{ dataset } {} + operator Dataset() const { return get(); } + }; + + struct WDATuple: std::unique_ptr { + WDATuple(Tuple tuple): std::unique_ptr{ tuple } {} + operator Tuple() const { return get(); } + }; + +} // local namespace + + +// ----------------------------------------------------------------------------- +std::array const +icarusDB::ChannelMapPostGres::PMTTimestampSet{ + "start" + ,"23aug2023" + ,"29aug2023" +}; + + +// ----------------------------------------------------------------------------- +icarusDB::ChannelMapPostGres::ChannelMapPostGres(Config const& config) + : icarus::ns::util::mfLoggingClass{ config.LogCategory() } + , fDBURL { config.DatabaseURL() } + , fCRTcalibrationDBURL { config.CRTcalibrationDatabaseURL() } + , fDatabaseAccessTimeout{ config.DatabaseAccessTimeout() } + {} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ChannelMapPostGres::SelectPeriod(RunPeriod period) { + + auto const iPeriod = static_cast(period); + std::string newPMTTimestamp = PMTTimestampSet.at(iPeriod); + + if (fCurrentPMTTimestamp == newPMTTimestamp) { + mfLogDebug() << "Period " << newPMTTimestamp << " already selected"; + } + else if ( !fCurrentPMTTimestamp.empty() ) { + mfLogDebug() << "Switched from period " << fCurrentPMTTimestamp + << " to " << newPMTTimestamp; + } + else { + mfLogDebug() << "Switching to period " << newPMTTimestamp; + } + + if (fCurrentPMTTimestamp == newPMTTimestamp) return false; + + fCurrentPMTTimestamp = newPMTTimestamp; + return true; + +} // icarusDB::ChannelMapPostGres::SelectPeriod() + + +// ----------------------------------------------------------------------------- +icarusDB::details::WDADataset icarusDB::ChannelMapPostGres::GetDataset + (std::string const& name, std::string url, std::string const& dataType) const +{ + if (!dataType.empty()) url += "&t=" + dataType; + int error{ 0 }; + details::WDADataset dataPtr{ + getDataWithTimeout + (url.c_str(), name.c_str(), fDatabaseAccessTimeout, &error) + }; + int const status = getHTTPstatus(dataPtr); + if (status != 200) { + mfLogError() << "libwda error: HTTP code=" << status << ": '" + << getHTTPmessage(dataPtr) << "'"; + } + if (error) { + auto e = myException() + << "GetDataset(): database access failed with error " << error + << "\nDatabase URL: '" << url << "', table: '" << name << "', type: '" + << dataType << "'\n"; + if (status != 200) { + e << "\nlibwda error: HTTP code=" << status << ": '" + << getHTTPmessage(dataPtr) << "'"; + } + throw e; + } + return dataPtr; +} // icarusDB::ChannelMapPostGres::GetDataset() + + +// ----------------------------------------------------------------------------- +icarusDB::details::WDADataset icarusDB::ChannelMapPostGres::GetCRTCaldata + (std::string const& name, std::string url) const +{ + + return GetDataset(name, std::move(url), ""); + +} + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap + (TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const +{ + const unsigned int tpcIdentifier(0x00001000); + + // Recover the data from the database + std::string const name { "icarus_hw_readoutboard" }; + std::string const dataType { "readout_boards" }; + details::WDADataset dataset = GetDataset(name, fDBURL, dataType); + + // Include a by hand mapping of fragment ID to crate + static std::map const flangeIDToCrateMap = { + { 19, "WW01T" }, + { 68, "WW01M" }, + { 41, "WW01B" }, + { 11, "WW02" }, + { 17, "WW03" }, + { 36, "WW04" }, + { 18, "WW05" }, + { 58, "WW06" }, + { 71, "WW07" }, + { 14, "WW08" }, + { 25, "WW09" }, + { 34, "WW10" }, + { 67, "WW11" }, + { 33, "WW12" }, + { 87, "WW13" }, + { 10, "WW14" }, + { 59, "WW15" }, + { 95, "WW16" }, + { 22, "WW17" }, + { 91, "WW18" }, + { 61, "WW19" }, + { 55, "WW20T" }, + { 97, "WW20M" }, + { 100, "WW20B" }, + { 83, "WE01T" }, + { 85, "WE01M" }, + { 7, "WE01B" }, + { 80, "WE02" }, + { 52, "WE03" }, + { 32, "WE04" }, + { 70, "WE05" }, + { 74, "WE06" }, + { 46, "WE07" }, + { 81, "WE08" }, + { 63, "WE09" }, + { 30, "WE10" }, + { 51, "WE11" }, + { 90, "WE12" }, + { 23, "WE13" }, + { 93, "WE14" }, + { 92, "WE15" }, + { 88, "WE16" }, + { 73, "WE17" }, + { 1, "WE18" }, + { 66, "WE19" }, + { 48, "WE20T" }, + { 13, "WE20M" }, + { 56, "WE20B" }, + { 94, "EW01T" }, + { 77, "EW01M" }, + { 72, "EW01B" }, + { 65, "EW02" }, + { 4, "EW03" }, + { 89, "EW04" }, + { 37, "EW05" }, + { 76, "EW06" }, + { 49, "EW07" }, + { 60, "EW08" }, + { 21, "EW09" }, + { 6, "EW10" }, + { 62, "EW11" }, + { 2, "EW12" }, + { 29, "EW13" }, + { 44, "EW14" }, + { 9, "EW15" }, + { 31, "EW16" }, + { 98, "EW17" }, + { 38, "EW18" }, + { 99, "EW19" }, + { 53, "EW20T" }, + { 82, "EW20M" }, + { 35, "EW20B" }, + { 96, "EE01T" }, + { 28, "EE01M" }, + { 16, "EE01T" }, + { 69, "EE02" }, + { 20, "EE03" }, + { 79, "EE04" }, + { 50, "EE05" }, + { 45, "EE06" }, + { 84, "EE07" }, + { 42, "EE08" }, + { 39, "EE09" }, + { 26, "EE10" }, + { 64, "EE11" }, + { 43, "EE12" }, + { 47, "EE13" }, + { 15, "EE14" }, + { 3, "EE15" }, + { 27, "EE16" }, + { 24, "EE17" }, + { 40, "EE18" }, + { 75, "EE19" }, + { 86, "EE20T" }, + { 54, "EE20M" }, + { 8, "EE20B" } + }; // flangeIDToCrateMap[] + + constexpr std::size_t ReadoutBoardIDcolumn = 0; + constexpr std::size_t FlangeIDcolumn = 1; + constexpr std::size_t FragmentIDcolumn = 8; + + // Loop through the data to recover the channels + // NOTE that we skip the first row because that is just the labels + for (int const row: util::counter(1, getNtuples(dataset))) { + // Recover the row + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + + int error = 0; + + // Note that the fragment ID is stored in the database as a string which + // reads as a hex number, meaning we have to read back as a string and + // decode to get the numerical value + Expected const fragmentIDString + = getStringFromTuple(tuple, FragmentIDcolumn); + if (!fragmentIDString) { + throw myException() << "Error (code: " << fragmentIDString.code() + << " on row " << row + << ") retrieving TPC fragment ID from channel mapping database\n"; + } + + unsigned int const fragmentID = std::stol(fragmentIDString, nullptr, 16); + if (!(fragmentID & tpcIdentifier)) continue; + + if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) { + unsigned int const flangeID + = getLongValue(tuple, FlangeIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") retrieving TPC flange ID from channel mapping database\n"; + } + fragmentBoardMap[fragmentID].first = flangeIDToCrateMap.at(flangeID); + } + + unsigned int const readoutID + = getLongValue(tuple, ReadoutBoardIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") retrieving TPC readout board ID from channel mapping database\n"; + } + + fragmentBoardMap[fragmentID].second.emplace_back(readoutID); + + } // for rows + + return 0; +} // icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap + (TPCReadoutBoardToChannelMap& rbChanMap) const +{ + // Recover the data from the database + std::string const name { "icarus_hardware_prd" }; + std::string const dataType { "daq_channels" }; + details::WDADataset dataset = GetDataset(name, fDBURL, dataType); + + constexpr std::size_t ChannelIDcolumn = 0; + constexpr std::size_t ReadoutBoardIDcolumn = 2; + constexpr std::size_t ReadoutBoardSlotColumn = 4; + constexpr std::size_t ChannelNumberColumn = 5; + constexpr std::size_t PlaneIdentifierColumn = 10; + + // Loop through the data to recover the channels, + // making sure to skip the first (header) row + for(int const row: util::counter(1, getNtuples(dataset))) { + // Recover the row + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + int error = 0; + + unsigned int const readoutBoardID + = getLongValue(tuple, ReadoutBoardIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading TPC readout board ID\n"; + } + + if (rbChanMap.find(readoutBoardID) == rbChanMap.end()) { + unsigned int const readoutBoardSlot + = getLongValue(tuple, ReadoutBoardSlotColumn, &error); + + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading TPC readout board slot\n"; + } + + rbChanMap[readoutBoardID].first = readoutBoardSlot; + rbChanMap[readoutBoardID].second.resize(ChannelsPerTPCreadoutBoard); + } // if new board ID + + unsigned int const channelNum + = getLongValue(tuple, ChannelNumberColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading TPC channel number\n"; + } + + unsigned int const channelID = getLongValue(tuple, ChannelIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading TPC channel ID\n"; + } + + // Recover the plane identifier + Expected const fragmentBuffer + = getStringFromTuple(tuple, PlaneIdentifierColumn); + if (!fragmentBuffer) { + throw myException() << "Error (code: " << fragmentBuffer.code() + << " on row " << row << ") reading plane type\n"; + } + // Make sure lower case... (sigh...) + unsigned int const plane = TPCplaneIdentifierToPlane(fragmentBuffer); + if (plane >= 3) { + mf::LogError{ "ChannelMapSQLite" } << "YIKES!!! Plane is " << plane + << " for channel " << channelID << " with type " + << fragmentBuffer.value(); + } + + rbChanMap[readoutBoardID].second[channelNum] + = std::make_pair(channelID, plane); + } // for rows + + return 0; // on error, an exception was thrown + +} // icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildFragmentToDigitizerChannelMap + (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const +{ + assert( !fCurrentPMTTimestamp.empty() ); + + // clearing is cleansing + fragmentToDigitizerChannelMap.clear(); + + // Recover the information from the database on the mapping + std::string const name { "Pmt_placement" }; + std::string const dataType { "pmt_placements" }; + std::string const period_query + { "&w=period_active:eq:" + fCurrentPMTTimestamp }; + details::WDADataset dataset + = GetDataset(name, fDBURL + period_query, dataType); + + // Ok, now we can start extracting the information + // We do this by looping through the database and building the map from that + // NOTE that we skip the first row because that is just the labels + for (int const row: util::counter(1, getNtuples(dataset))) { + // Recover the row + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + + constexpr std::size_t ChannelIDcolumn = 3; + constexpr std::size_t LaserChannelColumn = 10; + constexpr std::size_t DigitizerColumn = 11; + constexpr std::size_t DigitizerChannelNoColumn = 12; + constexpr std::size_t FragmentIDcolumn = 15; + + int error = 0; + + // nice... and currently unused + Expected const digitizerLabel = getStringFromTuple(tuple, DigitizerColumn); + if (!digitizerLabel) { + throw myException() << "Error (code: " << digitizerLabel.code() + << " on row " << row + << ") retrieving PMT digitizer from channel mapping database\n"; + } + + // fragment id + unsigned long const fragmentID + = getLongValue(tuple, FragmentIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading PMT fragment ID\n"; + } + + // digitizer channel number + unsigned int const digitizerChannelNo + = getLongValue(tuple, DigitizerChannelNoColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading PMT readout board channel number\n"; + } + + // LArsoft channel ID + unsigned int const channelID = getLongValue(tuple, ChannelIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading PMT channel ID\n"; + } + // laser channel number + Expected laserChannelLabel = getStringFromTuple(tuple, LaserChannelColumn); + if (!laserChannelLabel) { + throw myException() << "Error (code: " << laserChannelLabel.code() + << " on row " << row + << ") retrieving PMT laser channel from channel mapping database\n"; + } + // will throw on error: + unsigned int const laserChannel + = std::stol(laserChannelLabel.value().substr(2)); + + // fill the map + fragmentToDigitizerChannelMap[fragmentID].emplace_back + (digitizerChannelNo, channelID, laserChannel); + + } // for + + return 0; +} // icarusDB::ChannelMapPostGres::BuildFragmentToDigitizerChannelMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildCRTChannelIDToHWtoSimMacAddressPairMap + (CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap) + const +{ + // clearing is cleansing + crtChannelIDToHWtoSimMacAddressPairMap.clear(); + + // Recover the information from the database on the mapping + std::string const name { "Feb_channels" }; + std::string const dataType { "feb_channels" }; + details::WDADataset dataset = GetDataset(name, fDBURL, dataType); + + constexpr std::size_t ChannelIDcolumn = 10; + constexpr std::size_t SimMacAddressColumn = 11; + constexpr std::size_t HWMacAddressColumn = 12; + + // Ok, now we can start extracting the information + // We do this by looping through the database and building the map from that + for(int const row: util::counter(1, getNtuples(dataset))) { + // Recover the row + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + + int error = 0; + + // Recover the simmacaddress + unsigned int const simmacaddress + = getLongValue(tuple, SimMacAddressColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading side CRT SimMac address\n"; + } + + // Now recover the hwmacaddress + unsigned int const hwmacaddress + = getLongValue(tuple, HWMacAddressColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading side CRT hardware Mac address\n"; + } + + // Finally, get the LArsoft channel ID + unsigned int const channelID = getLongValue(tuple, ChannelIDcolumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading side CRT channel ID\n"; + } + + // Fill the map + crtChannelIDToHWtoSimMacAddressPairMap[channelID] + = std::make_pair(hwmacaddress,simmacaddress); + + } // for + + return 0; +} // icarusDB::ChannelMapPostGres::BuildCRTChannelIDToHWtoSimMacAddressPairMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildTopCRTHWtoSimMacAddressPairMap + (TopCRTHWtoSimMacAddressPairMap& topcrtHWtoSimMacAddressPairMap) const +{ + // clearing is cleansing + topcrtHWtoSimMacAddressPairMap.clear(); + + // Recover the information from the database on the mapping + std::string const name { "topcrt_febs" }; + std::string const dataType { "crtfeb" }; + + details::WDADataset dataset = GetDataset(name, fDBURL, dataType); + + constexpr std::size_t SimMacAddressColumn = 41; + constexpr std::size_t HWMacAddressColumn = 3; + + // Ok, now we can start extracting the information + // We do this by looping through the database and building the map from that + for(int const row: util::counter(1, getNtuples(dataset))) { + // Recover the row + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + int error = 0; + + // Recover the simmacaddress + unsigned int const simmacaddress + = getLongValue(tuple, SimMacAddressColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading top CRT SimMac address\n"; + } + + // Now recover the hwmacaddress + unsigned int const hwmacaddress + = getLongValue(tuple, HWMacAddressColumn, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading top CRT hardware Mac address\n"; + } + + // Fill the map + topcrtHWtoSimMacAddressPairMap[hwmacaddress] = simmacaddress; + } // for + + return 0; +} // icarusDB::ChannelMapPostGres::BuildTopCRTHWtoSimMacAddressPairMap() + + +// ----------------------------------------------------------------------------- +int icarusDB::ChannelMapPostGres::BuildSideCRTCalibrationMap + (SideCRTChannelToCalibrationMap& sideCRTChannelToCalibrationMap) const +{ + + std::string const name { "SideCRT_calibration_data" }; + + details::WDADataset dataset = GetCRTCaldata(name, fCRTcalibrationDBURL); + printDatasetError(dataset); // probably never prints since on error throws + + for (int const row: util::counter(getNtuples(dataset))) { + + // Get the row with an array of double + details::WDATuple tuple { getTuple(dataset, row) }; + if (!tuple) continue; + + int const ncols = getNfields(tuple);//check number of columns + + // first few rows aren't actual data and have ncols==1: exclude those + if (ncols < 5) continue; + + // assign values from the database to variables so we can use them + int error = 0; + + int const mac5 = static_cast(getDoubleValue(tuple, 1, &error)); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading CRT calibration Mac5 address\n"; + } + + int const channel = static_cast(getDoubleValue(tuple, 2, &error)); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading CRT calibration channel\n"; + } + + double const gain = getDoubleValue(tuple, 3, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading CRT calibration gain for channel " << channel << "\n"; + } + + double const ped = getDoubleValue(tuple, 4, &error); + if (error) { + throw myException() << "Error (code: " << error << " on row " << row + << ") reading CRT calibration pedestal for channel " << channel << "\n"; + } + + // add the association between the two pairs to the map object + sideCRTChannelToCalibrationMap.emplace + (std::make_pair(mac5, channel), std::make_pair(gain, ped)); + + } // for rows + + return 0; + +} // icarusDB::ChannelMapPostGres::BuildSideCRTCalibrationMap() + + +// ----------------------------------------------------------------------------- +bool icarusDB::ChannelMapPostGres::printDatasetError + (details::WDADataset const& dataset) const +{ + int const status = getHTTPstatus(dataset); + if (status == 200) return false; + + mfLogError() << "libwda error: HTTP code=" << status << ": '" + << getHTTPmessage(dataset) << "'"; + return true; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ChannelMapPostGres::getStringFromTuple + (details::WDATuple const& tuple, std::size_t column) -> Expected +{ + int error = 0; + std::string buffer(BufferSize, '\0'); + std::size_t const length + = getStringValue(tuple, column, buffer.data(), buffer.size(), &error); + if (error) return error; + buffer.erase(length); + return buffer; +} // icarusDB::ChannelMapPostGres::getStringFromTuple<>() + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h new file mode 100644 index 000000000..e77a13e33 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h @@ -0,0 +1,238 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h + * @brief Interface with ICARUS channel mapping PostGres database. + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPPOSTGRES_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPPOSTGRES_H + + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "icarusalg/Utilities/mfLoggingClass.h" + +// framework libraries +#include "fhiclcpp/types/Atom.h" + +// C/C++ standard libraries +#include +#include +#include // std::uint32_t + + +namespace icarusDB { + class ChannelMapPostGres; + + namespace details { + struct WDADataset; + struct WDATuple; + } + +} // namespace icarusDB + +/** + * @brief Helper to extract mapping information from ICARUS PostGres database. + * + * This helper fills "standard" data structures from a PostGres database. + * These data structures are then managed by a ICARUS service provider + * (`icarusDB::IICARUSChannelMap`). + */ +class icarusDB::ChannelMapPostGres + : public IChannelMapping, private icarus::ns::util::mfLoggingClass +{ + public: + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Atom DatabaseURL { + Name{ "DatabaseURL" }, + Comment{ "full URL of the database to be accessed" }, + R"(https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd)" + }; + + fhicl::Atom CRTcalibrationDatabaseURL { + Name{ "CRTcalibrationDatabaseURL" }, + Comment{ "full URL of the CRT calibration database to be accessed" }, + R"(https://dbdata0vm.fnal.gov:9443/icarus_con_prod/app/data?f=crt_gain_reco_data&t=1638918270)" + }; + + fhicl::Atom DatabaseAccessTimeout { + Name{ "DatabaseAccessTimeout" }, + Comment{ "timeout for database accesses [s]" }, + 200 // default + }; + + fhicl::Atom LogCategory { + Name{ "LogCategory" }, + Comment{ "name of the streams to send console messages to" }, + "ChannelMapPostGres" // default + }; + + }; // Config + + + /// Constructor: configuration via FHiCL. + explicit ChannelMapPostGres(Config const& config); + + /** + * @brief Prepares the object for queries pertaining the specified period. + * @param period the period to be prepared for + * @return whether values cached from the previous period are invalidated + * + * Periods are defined in `icarusDB::RunPeriods` class. + * + * If the return value is `true`, caller should follow by rebuilding all the + * maps they need to use. + * If the return value is `false`, all maps built after the previous call to + * `SelectPeriod()` are still current for `period`: building new ones is not + * necessary, but it's not harmful either (at most, wasteful). + */ + virtual bool SelectPeriod(RunPeriod period) override; + + /** + * @brief Define the returned data structures for a mapping between TPC Fragment IDs + * and the related crate and readout information. + * Then define the function interface to fill these data structures + */ + virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const override; + + /** + * @brief Define the returned data structures for a mapping between TPC readout boards + * and the channel information + * Then define the function interface to fill these data structures + */ + virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const override; + + /** + * @brief Define the returned data structures for a mapping between PMT Fragment IDs + * and the related crate and readout information. + * Then define the function interface to fill these data structures + */ + virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; + + + /** + * @brief Define the returned data structures for a mapping between CRT hardware mac_address + * to the simulated mac_address. + * Then define the function interface to fill these data structures + */ + virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const override; + virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const override; + + /** + * @brief Define the returned data structures for a mapping between Side CRT Channels and + * their calibration values. + * Then define the function interface to fill these data structures + */ + virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const override; + + private: + + /// Loosely based on C++-20 `std::expected`. + template + class Expected { + std::variant fValue; + public: + constexpr Expected(E e = E{}): fValue{ std::move(e) } {} + constexpr Expected(T t): fValue{ std::move(t) } {} + + Expected& operator= (E e) { fValue = std::move(e); return *this; } + Expected& operator= (T t) { fValue = std::move(t); return *this; } + template + T& emplace(Args&&... args) + { return fValue.emplace(std::forward(args)...); } + + bool has_value() const { return std::holds_alternative(fValue); } + + E code() const { return std::get(fValue); } + T const& value() const { return std::get(fValue); } + + operator T const& () const { return value(); } + T const& operator*() const { return value(); } + + explicit operator bool() const { return has_value(); } + + }; // Expected + + + // --- BEGIN --- Configuration parameters ------------------------------------ + + std::string const fDBURL; ///< Complete URL for hardware database access. + + /// Complete URL for CRT calibration database access. + std::string const fCRTcalibrationDBURL; + + unsigned int const fDatabaseAccessTimeout; ///< In seconds. + + // --- END ----- Configuration parameters ------------------------------------ + + + // --- BEGIN --- Cache ------------------------------------------------------- + + /// The PMT timestamp being served. Chosen by `SelectPeriod()`. + std::string fCurrentPMTTimestamp = ""; + + // --- END ----- Cache ------------------------------------------------------- + + /** + * @brief Reads a full table from the specified database table. + * @param name name of the database table to read data from + * @param url URL of the database to be accessed requested + * @param dataType type of data being requested + * @param[out] dataSet where the fetch data will be saved + * @return a "smart" pointer to the data + * @throw cet::exception (category: `"ChannelMapPostGres"`) on DB access error + * + * Database access is performed via Fermilab's libwda. + */ + details::WDADataset GetDataset + (std::string const& name, std::string url, std::string const& dataType) + const; + + + /** + * @brief Reads a full table from the specified database table. + * @param name name of the database table to read data from + * @param url URL of the database to be accessed requested + * @param[out] dataSet where the fetch data will be saved + * @return a "smart" pointer to the data + * @throw cet::exception (category: `"ChannelMapPostGres"`) on DB access error + * @see `GetDataset()` + * + * Function used specifically for accessing CRT calibration data. + * + * @note [Tyler Boone] Adding this so I can control how this workflow goes + */ + /// Fetches CRT calibration data from the database. + details::WDADataset GetCRTCaldata + (std::string const& name, std::string url) const; + + + /// Emits an error message if libwda dataset contains one. + /// @return whether the dataset was in an error state + bool printDatasetError(details::WDADataset const& dataset) const; + + + /// The list of available PMT timestamps. + static std::array const PMTTimestampSet; + + /// Returns the string on the specified `column` of the `tuple`. + /// @return the requested string, or an error code from libwda on error + template + static Expected getStringFromTuple + (details::WDATuple const& tuple, std::size_t column); + + /// Returns an exception object pre-approved with our signature. + static cet::exception myException() + { return cet::exception{ "ChannelMapPostGres" }; } + +}; // icarusDB::ChannelMapPostGres + + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_CHANNELMAPPOSTGRES_H + diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx new file mode 100644 index 000000000..feaab52d4 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx @@ -0,0 +1,438 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx + * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h + */ + +// library header +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "larcorealg/CoreUtils/values.h" // util::const_values() + +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "fhiclcpp/ParameterSet.h" +#include "cetlib_except/exception.h" +#include "cetlib/cpu_timer.h" + +// C++ standard libraries +#include +#include +#include + + + +// ----------------------------------------------------------------------------- +icarusDB::ICARUSChannelMapPostGresProvider::ICARUSChannelMapPostGresProvider + (Config const& config) + : fDiagnosticOutput{ config.DiagnosticOutput() } + , fLogCategory{ config.LogCategory() } + , fChannelMappingAlg + { std::make_unique(config.ChannelMappingTool()) } +{ +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapPostGresProvider::forRun(int run) { + + RunPeriod period = RunPeriod::NPeriods; + try { + period = RunPeriods::withRun(run); + } catch (...) { + mf::LogError{ fLogCategory } + << "Failed to associate a run period number to run " << run << "."; + throw; + } + + if (period == RunPeriod::NPeriods) { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "forRun(): can't determine the period of run " << run << "!\n"; + } + + return forPeriod(period); + +} // icarusDB::ICARUSChannelMapPostGresProvider::forRun() + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapPostGresProvider::forPeriod + (icarusDB::RunPeriod period) +{ + + // if cache is not invalidated, we don't refresh it + if (!fChannelMappingAlg->SelectPeriod(period)) return false; + + readFromDatabase(); + return true; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapPostGresProvider::hasFragmentID + (const unsigned int fragmentID) const +{ + return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nTPCfragmentIDs() const { + return fFragmentToReadoutMap.size(); +} + + +// ----------------------------------------------------------------------------- +std::string const& icarusDB::ICARUSChannelMapPostGresProvider::getCrateName + (const unsigned int fragmentID) const +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking up crate name \n"; + } + + return fragToReadoutItr->second.first; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::getReadoutBoardVec + (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking up board vector.\n"; + } + + return fragToReadoutItr->second.second; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::getReadoutBoardToChannelMap() + const -> const TPCReadoutBoardToChannelMap& +{ + return fReadoutBoardToChannelMap; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapPostGresProvider::hasBoardID + (const unsigned int boardID) const +{ + return + fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nTPCboardIDs() const { + return fReadoutBoardToChannelMap.size(); +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::getBoardSlot + (const unsigned int boardID) const +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Board ID " << boardID + << " not found in lookup map when looking up board slot.\n"; + } + + return readoutBoardItr->second.first; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::getChannelPlanePair + (const unsigned int boardID) const -> ChannelPlanePairVec const& +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Board ID " << boardID + << " not found in lookup map when looking up channel/plane pair.\n"; + } + + return readoutBoardItr->second.second; +} + + +// ----------------------------------------------------------------------------- +bool icarusDB::ICARUSChannelMapPostGresProvider::hasPMTDigitizerID + (const unsigned int fragmentID) const +{ + return findPMTfragmentEntry(fragmentID) != nullptr; +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nPMTfragmentIDs() const { + return fFragmentToDigitizerMap.size(); +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::getChannelIDPairVec + (const unsigned int fragmentID) const + -> DigitizerChannelChannelIDPairVec const& +{ + mf::LogTrace{ "ICARUSChannelMapPostGresProvider" } + << "Call to: ICARUSChannelMapPostGresProvider::getChannelIDPairVec(" + << fragmentID << ")"; + + DigitizerChannelChannelIDPairVec const* digitizerPair + = findPMTfragmentEntry(fragmentID); + + if (digitizerPair) return *digitizerPair; + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Fragment ID " << fragmentID + << " not found in lookup map when looking for PMT channel info.\n"; + +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::getSimMacAddress + (const unsigned int hwmacaddress) const +{ + for(auto const& [ hw, sim ] + : util::const_values(fCRTChannelIDToHWtoSimMacAddressPairMap) + ) { + if (hw == hwmacaddress) return sim; + } + + return 0; +} + + +// ----------------------------------------------------------------------------- +unsigned int icarusDB::ICARUSChannelMapPostGresProvider::gettopSimMacAddress + (const unsigned int hwmacaddress) const +{ +#if 0 // FIXME + unsigned int simmacaddress = 0; + + for(const auto& pair : fTopCRTHWtoSimMacAddressPairMap){ + if (pair.first == hwmacaddress) +simmacaddress = pair.second; + } + + return simmacaddress; +#else + // untested: + auto const it = fTopCRTHWtoSimMacAddressPairMap.find(hwmacaddress); + return (it == fTopCRTHWtoSimMacAddressPairMap.end())? 0: it->second; + +#endif +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::getSideCRTCalibrationMap + (int mac5, int chan) const -> std::pair +{ + auto const itGainAndPedestal + = fSideCRTChannelToCalibrationMap.find({ mac5, chan }); + return (itGainAndPedestal == fSideCRTChannelToCalibrationMap.cend()) + ? std::pair{ -99., -99. }: itGainAndPedestal->second; +} + + +// ----------------------------------------------------------------------------- +auto icarusDB::ICARUSChannelMapPostGresProvider::findPMTfragmentEntry + (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* +{ + auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); + return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); +} + + +// ----------------------------------------------------------------------------- +void icarusDB::ICARUSChannelMapPostGresProvider::readFromDatabase() { + + mf::LogInfo{ fLogCategory } << "Building the channel mapping"; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC fragment-based mapping + cet::cpu_timer theClockFragmentIDs; + theClockFragmentIDs.start(); + fFragmentToReadoutMap.clear(); + if (fChannelMappingAlg->BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) + { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Cannot recover the TPC fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + + mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; + log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() + << " elements"; + for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " + << crateAndBoards.first << ", # boards: " + << crateAndBoards.second.size(); + } + } + theClockFragmentIDs.stop(); + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC readout-board-based mapping + double fragmentIDsTime = theClockFragmentIDs.accumulated_real_time(); + + cet::cpu_timer theClockReadoutIDs; + theClockReadoutIDs.start(); + + fReadoutBoardToChannelMap.clear(); + if (fChannelMappingAlg->BuildTPCReadoutBoardToChannelMap(fReadoutBoardToChannelMap)) + { + mf::LogError{ "ICARUSChannelMapPostGresProvider" } + << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Failed to read the database.\n"; + } + + theClockReadoutIDs.stop(); + double readoutIDsTime = theClockReadoutIDs.accumulated_real_time(); + + mf::LogInfo{ "ICARUSChannelMapPostGresProvider" } + << "==> FragmentID map time: " << fragmentIDsTime << ", Readout IDs time: " + << readoutIDsTime; + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // PMT channel mapping + fFragmentToDigitizerMap.clear(); + if (fChannelMappingAlg->BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) + { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Cannot recover the PMT fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; + log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() + << " Fragment IDs"; + + for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec + << ", # pairs: " << digitizers.size(); + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Side CRT channel mapping + fCRTChannelIDToHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg->BuildCRTChannelIDToHWtoSimMacAddressPairMap(fCRTChannelIDToHWtoSimMacAddressPairMap)) + { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Cannot recover the HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; + log << "ChannelID to MacAddress map has " + << fCRTChannelIDToHWtoSimMacAddressPairMap.size() << " Channel IDs"; + for(auto const& [ channel, addresses ]: fCRTChannelIDToHWtoSimMacAddressPairMap) { + log <<"\n ChannelID: "<< channel + << ", hw mac address: " << addresses.first + << ", sim mac address: " << addresses.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Top CRT channel mapping + fTopCRTHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg->BuildTopCRTHWtoSimMacAddressPairMap(fTopCRTHWtoSimMacAddressPairMap)) + { + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Cannot recover the Top CRT HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; + log << "Top CRT MacAddress map has " << fTopCRTHWtoSimMacAddressPairMap.size() << " rows"; + for(auto const [ hwaddress, simaddress ]: fTopCRTHWtoSimMacAddressPairMap) { + log << "\n hw mac address: " << hwaddress + << ", sim mac address: " << simaddress; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // CRT Charge Calibration initialization + fSideCRTChannelToCalibrationMap.clear(); + if (fChannelMappingAlg->BuildSideCRTCalibrationMap(fSideCRTChannelToCalibrationMap)) + { + mf::LogError{ "ICARUSChannelMapPostGresProvider" } + << "******* FAILED TO CONFIGURE CRT Calibration ********"; + throw cet::exception{ "ICARUSChannelMapPostGresProvider" } + << "Cannot recover the CRT charge calibration information from the database.\n"; + } + else if (fDiagnosticOutput) { + mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; + log << "side crt calibration map has " + << fSideCRTChannelToCalibrationMap.size() << " list of rows"; + + for(auto const& [ key, calib ]: fSideCRTChannelToCalibrationMap) { + log << "\n mac5: "<< key.first << ", chan: " << key.second + << ", Gain: " << calib.first << ", Pedestal: " << calib.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +} // icarusDB::ICARUSChannelMapPostGresProvider::readFromDatabase() + + +// ----------------------------------------------------------------------------- +constexpr unsigned int icarusDB::ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey + (unsigned int fragmentID) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert(((fragmentID & ~0xFF) == 0x00) || ((fragmentID & ~0xFF) == 0x20)); + + return fragmentID & 0xFF; + +} // ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- +constexpr unsigned int icarusDB::ICARUSChannelMapPostGresProvider::DBkeyToPMTfragmentID + (unsigned int DBkey) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert((DBkey & 0xFF) < 24); + + return (DBkey & 0xFF) | 0x2000; + +} // icarusDB::ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h new file mode 100644 index 000000000..d075df994 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h @@ -0,0 +1,247 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h + * @author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPOSTGRESPROVIDER_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPOSTGRESPROVIDER_H + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" +#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h" + +// framework libraries +#include "fhiclcpp/types/Table.h" +#include "fhiclcpp/types/Atom.h" +#include "cetlib_except/exception.h" + +// C/C++ standard libraries +#include +#include // std::unique_ptr<> + + +// ----------------------------------------------------------------------------- +namespace icarusDB { class ICARUSChannelMapPostGresProvider; } +/** + * @brief Interface to the PostgreSQL ICARUS channel mapping database. + * @see icarusDB::ICARUSChannelMapPostGres + * + * + * + * Configuration parameters + * ========================= + * + * * `ChannelMappingTool` (algorithm configuration): see + * `icarusDB::ChannelMapPostGres` configuration. + * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters + * and in general prints more messages to console + * * `LogCategory` (string, default: `"ICARUSChannelMapPostGresProvider"`): + * name of the messagefacility category used to send messages to console, + * useful for filtering messages. + * + * + */ +class icarusDB::ICARUSChannelMapPostGresProvider: public IICARUSChannelMap { + + public: + /// The helper used to extract data from the database. + using ChannelMappingAlg_t = icarusDB::ChannelMapPostGres; + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Table ChannelMappingTool { + Name{ "ChannelMappingTool" }, + Comment{ "parameters for the channel mapping algorithm" } + }; + + fhicl::Atom DiagnosticOutput{ + Name{ "DiagnosticOutput" }, + Comment{ "enables verbose output to console" }, + false // default + }; + + fhicl::Atom LogCategory{ + Name{ "LogCategory" }, + Comment{ "name of the console stream to send messages to" }, + "ICARUSChannelMapPostGresProvider" // default + }; + + }; // Config + + using Parameters = fhicl::Table; + + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapPostGresProvider(Config const& config); + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapPostGresProvider(Parameters const& params) + : ICARUSChannelMapPostGresProvider{ params() } + {} + + + /// --- BEGIN --- Data period selection ------------------------------------ + /// @name Data period selection + /// @{ + + /// Loads the mapping for `run`, returns whether a new mapping was loaded. + virtual bool forRun(int run) override; + + /// Loads the mapping for `period`, returns whether a new mapping was loaded. + virtual bool forPeriod(icarusDB::RunPeriod period) override; + + /// @} + /// --- END ----- Data period selection ------------------------------------ + + + /// --- BEGIN --- TPC information ------------------------------------------ + /// @name TPC information + /// @{ + + /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - + /// @name TPC fragment information + /// @{ + + /// Returns whether the specified `ID` is a known TPC fragment ID. + virtual bool hasFragmentID(const unsigned int ID) const override; + /// Returns the number of TPC fragment IDs known to the service. + + /// Returns the number of known TPC fragments. + virtual unsigned int nTPCfragmentIDs() const override; + + /// Returns the name of the crate served by the specified `fragmentID`. + virtual std::string const& getCrateName + (const unsigned int fragmentID) const override; + + /// Returns the list of board IDs included in the specified `fragmentID`. + virtual ReadoutIDVec const& getReadoutBoardVec + (const unsigned int fragmentID) const override; + + /// @} + /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - + + /** + * @brief Returns the full TPC channel mapping. + * + * The returned mapping is an associative container, associating each board + * ID (`boardID`) to the following information (in a `std::tuple`): + * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) + * * `[1]` list of channels served by the board, and their plane + * (like `getChannelPlanePair(boardID)`) + * + */ + virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const + override; + + /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - + /// @name TPC board information + /// @{ + + /// Returns whether there is a board with the specified `ID`. + virtual bool hasBoardID(const unsigned int ID) const override; + /// Returns the number of TPC board IDs known to the service. + virtual unsigned int nTPCboardIDs() const override; + /// Returns the number of slot the `boardID` is on. + virtual unsigned int getBoardSlot(const unsigned int boardID) const override; + /// Returns a list of channels served by the `boardID` and for each the plane + /// it is on (`0` to `2`). + virtual ChannelPlanePairVec const& getChannelPlanePair + (const unsigned int boardID) const override; + + /// @} + /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - + + + /// --- BEGIN --- PMT information ------------------------------------------ + /// @name PMT information + /// @{ + + /// Returns whether the specified fragment `ID` is known to the mapping. + virtual bool hasPMTDigitizerID(const unsigned int ID) const override; + + /// Returns the number of PMT fragment IDs known to the mapping. + virtual unsigned int nPMTfragmentIDs() const override; + + /// Returns a list of triplets: + virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec + (const unsigned int) const override; + + /// @} + /// --- END ----- PMT information ------------------------------------------ + + + /// --- BEGIN --- CRT information ------------------------------------------ + /// @name CRT information + /// @{ + + /// Returns the sim Mac address corresponding to the specified side CRT hardware address. + virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const override; + /// Returns the sim Mac address corresponding to the specified top CRT hardware address. + virtual unsigned int gettopSimMacAddress(const unsigned int) const override; + + /// Returns the Gain and Pedestal for Side CRT. + virtual std::pair getSideCRTCalibrationMap + (int mac5, int chan) const override; + + /// @} + /// --- END ----- CRT information ------------------------------------------ + + /// Returns the channel mapping database key for the specified PMT fragment ID. + static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); + + /// Returns the PMT fragment ID for the specified channel mapping database key. + static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); + + + private: + + // --- BEGIN --- Configuration parameters ------------------------------------ + + bool const fDiagnosticOutput; + + std::string const fLogCategory; + + // --- END ----- Configuration parameters ------------------------------------ + + + // --- BEGIN --- Cache ------------------------------------------------------- + IChannelMapping::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; + + IChannelMapping::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; + + IChannelMapping::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + + IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; + + IChannelMapping::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; + + IChannelMapping::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; + + // --- END ----- Cache ------------------------------------------------------- + + /// The helper extracting information from the database. + std::unique_ptr fChannelMappingAlg; + + + /// Has the channel mapping tool fill the mapping caches. + virtual void readFromDatabase(); + + + /// Returns the list of board channel-to-PMT channel ID mapping within the + /// specified fragment. + /// + /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment + DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry + (unsigned int fragmentID) const; + + +}; // icarusDB::ICARUSChannelMapPostGresProvider + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPOSTGRESPROVIDER_H diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc new file mode 100644 index 000000000..be711c3f9 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc @@ -0,0 +1,104 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc + * @brief Wrapper service for `icarusDB::ICARUSChannelMapPostGresProvider`. + * @author Gianluca Petrillo (petrillo@slac.stanford.edu) + */ + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" + +// framework libraries +#include "art/Framework/Services/Registry/ActivityRegistry.h" +#include "art/Framework/Services/Registry/ServiceDefinitionMacros.h" +#include "art/Framework/Services/Registry/ServiceDeclarationMacros.h" +#include "art/Framework/Services/Registry/ServiceTable.h" +#include "art/Framework/Principal/Run.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "fhiclcpp/ParameterSet.h" +#include "cetlib_except/exception.h" + + +// ----------------------------------------------------------------------------- +namespace icarusDB { class ICARUSChannelMapPostGres; } +/** + * @brief LArSoft service for ICARUS channel mapping (PostgreSQL DB backend). + * + * This service provides access to ICARUS channel mapping database, using the + * PostgreSQL database. + * + * This service implements the generic channel mapping access service provider + * interface `icarusDB::ICARUSChannelMap`. + * To use the channel mapping, include in your code the header of + * `icarusDB::ICARUSChannelMap`, and access the service provider via: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMap const& channelMapping + * = *lar::providerFrom(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * or similar (`lar::providerFrom()` is in `larcore/CoreUtils/ServiceUtils.h`) + * or directly the service via + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::ICARUSChannelMap const& channelMapping + * = *art::ServiceHandle(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * For details on the interface, see `icarusDB::IICARUSChannelMap`. + * For details on the implementation, see `icarusDB::ICARUSChannelMap`. + * + * @note For production and processes that need robustness, using the SQLite + * database and backend (`icarusDB::ICARUSChannelMapSQLite`) is suggested + * instead. That database is local to the process and not subject to + * network interruptions. + * + */ +class icarusDB::ICARUSChannelMapPostGres + : public ICARUSChannelMapPostGresProvider +{ + + /// Prepares the mapping for the specified run. + void preBeginRun(art::Run const& run); + + public: + + using provider_type = icarusDB::ICARUSChannelMapPostGresProvider; + + using Parameters = art::ServiceTable; + + /// Constructor: configures the provider and hooks to the framework. + ICARUSChannelMapPostGres(Parameters const& params, art::ActivityRegistry& reg); + + /// Returns the service provider (for use with `lar::providerFrom()`). + provider_type const* provider() const { return this; } + +}; // class icarusDB::ICARUSChannelMapPostGres + + +// ----------------------------------------------------------------------------- +// --- Implementation +// ----------------------------------------------------------------------------- +icarusDB::ICARUSChannelMapPostGres::ICARUSChannelMapPostGres + (Parameters const& params, art::ActivityRegistry& reg) + : provider_type(params()) +{ + reg.sPreBeginRun.watch(this, &ICARUSChannelMapPostGres::preBeginRun); + forPeriod(RunPeriod::Runs0to2); // prepare for some run, in case anybody asks +} + + +// ----------------------------------------------------------------------------- +void icarusDB::ICARUSChannelMapPostGres::preBeginRun(art::Run const& run) { + if (forRun(run.run())) { + mf::LogDebug{ "ICARUSChannelMapPostGres" } + << "Loaded mapping for run " << run.run(); + } +} + + +// ----------------------------------------------------------------------------- +DECLARE_ART_SERVICE_INTERFACE_IMPL + (icarusDB::ICARUSChannelMapPostGres, icarusDB::IICARUSChannelMap, SHARED) +DEFINE_ART_SERVICE_INTERFACE_IMPL + (icarusDB::ICARUSChannelMapPostGres, icarusDB::IICARUSChannelMap) + + +// ----------------------------------------------------------------------------- From 44d83cb3b85c0ee8c1b43148b8bc1efa9a66cdea Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Fri, 23 Feb 2024 23:45:04 -0600 Subject: [PATCH 06/19] Completed the refactoring of IICARUSChannelMap service Now instead of chooising a service (one option) and a tool (two options) we choose just the service (two options, plus a legacy one). --- .../ChannelMapping/ChannelMapSQLite.cxx | 20 +- .../Decode/ChannelMapping/ChannelMapSQLite.h | 56 ++- .../ICARUSChannelMapDataTypes.h | 123 +++++ .../ICARUSChannelMapPostGresProvider.cxx | 432 +---------------- .../ICARUSChannelMapPostGresProvider.h | 229 +-------- .../ICARUSChannelMapPostGres_service.cc | 23 +- .../ICARUSChannelMapProvider.cxx | 8 +- .../ChannelMapping/ICARUSChannelMapProvider.h | 12 +- .../ICARUSChannelMapProviderBase.h | 287 ++++++++++++ .../ICARUSChannelMapProviderBase.txx | 440 ++++++++++++++++++ .../ICARUSChannelMapSQLiteProvider.cxx | 430 +---------------- .../ICARUSChannelMapSQLiteProvider.h | 228 +-------- .../ICARUSChannelMapSQLite_service.cc | 43 +- .../ICARUSChannelMap_service.cc | 31 ++ .../Decode/ChannelMapping/IChannelMapping.h | 238 +++++----- .../Decode/ChannelMapping/IICARUSChannelMap.h | 178 +++---- .../IICARUSChannelMapProvider.h | 168 +++++++ .../ChannelMapping/PMTChannelMapDumper.cxx | 68 ++- .../Decode/ChannelMapping/PositionFinder.h | 106 +++++ .../ChannelMapping/channelmapping_icarus.fcl | 91 +++- 20 files changed, 1589 insertions(+), 1622 deletions(-) create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h create mode 100644 icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx mode change 100755 => 100644 icaruscode/Decode/ChannelMapping/IChannelMapping.h create mode 100644 icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h create mode 100644 icaruscode/Decode/ChannelMapping/PositionFinder.h diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx index 2e7f9329e..b5e966dd6 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -9,13 +9,12 @@ // ICARUS libraries -// framework libraries -#include "messagefacility/MessageLogger/MessageLogger.h" -// #include "wda.h" - // LArSoft libraries #include "larevt/CalibrationDBI/Providers/DBFolder.h" #include "larcorealg/CoreUtils/counter.h" + +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" #include "cetlib/search_path.h" // SQLite @@ -265,8 +264,8 @@ int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback { const unsigned int tpcIdentifier(0x00001000); - auto& fragmentBoardMap = *static_cast - (dataOut); + auto& fragmentBoardMap + = *static_cast(dataOut); // Include a by hand mapping of fragment ID to crate // Note that we now know we can get this from the "flanges" table... so an upgrade coming soon... @@ -423,8 +422,7 @@ int icarusDB::ChannelMapSQLite::buildTPCReadoutBoardToChannelMap_callback constexpr std::size_t ChannelNumberColumn = 5; constexpr std::size_t FragmentBufferColumn = 10; - auto& rbChanMap - = *static_cast(dataOut); + auto& rbChanMap= *static_cast(dataOut); unsigned int readoutBoardID = std::stol(argv[ReadoutBoardIDcolumn]); @@ -484,7 +482,7 @@ int icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback constexpr std::size_t FragmentIDcolumn = 18; auto& fragmentToDigitizerChannelMap - = *static_cast(dataOut); + = *static_cast(dataOut); // Start extracting info unsigned int const fragmentID = std::stol(argv[FragmentIDcolumn]); @@ -549,7 +547,7 @@ int icarusDB::ChannelMapSQLite::buildCRTChannelIDToHWtoSimMacAddressPairMap_call constexpr std::size_t HWaddressColumn = 12; auto& crtChannelIDToHWtoSimMacAddressPairMap - = *static_cast + = *static_cast (dataOut); // extracting info @@ -607,7 +605,7 @@ int icarusDB::ChannelMapSQLite::buildTopCRTHWtoSimMacAddressPairMap_callback constexpr std::size_t HWaddressColumn = 3; auto& topcrtHWtoSimMacAddressPairMap - = *static_cast(dataOut); + = *static_cast(dataOut); auto const valueOrNone = [](const char* s){ return std::strcmp(s, "None") == 0? 0: std::stol(s); }; diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h index 3d177d16f..d1bc3ad56 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h @@ -88,37 +88,34 @@ class icarusDB::ChannelMapSQLite virtual bool SelectPeriod(RunPeriod period) override; - /** - * @brief Define the returned data structures for a mapping between TPC Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const override; + /// Fill mapping between TPC Fragment IDs and the related crate and readout + /// information. + virtual int BuildTPCFragmentIDToReadoutIDMap + (TPCFragmentIDToReadoutIDMap&) const override; - /** - * @brief Define the returned data structures for a mapping between TPC readout boards - * and the channel information - * Then define the function interface to fill these data structures - */ - virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const override; + /// Fill mapping between TPC readout boards and the channel information. + virtual int BuildTPCReadoutBoardToChannelMap + (TPCReadoutBoardToChannelMap&) const override; - /** - * @brief Define the returned data structures for a mapping between PMT Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; + /// Fill mapping between PMT fragment IDs and the related crate and readout + /// information. + virtual int BuildFragmentToDigitizerChannelMap + (FragmentToDigitizerChannelMap&) const override; - /** - * @brief Define the returned data structures for a mapping between CRT hardware mac_address - * to the simulated mac_address. - * Then define the function interface to fill these data structures - */ - virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const override; - virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const override; - - virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const override; + /// Fill mapping between side CRT hardware mac_address and the simulated + /// mac_address. + virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap + (CRTChannelIDToHWtoSimMacAddressPairMap&) const override; + + /// Fill mapping between top CRT channel ID and the simulated mac_address. + virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const + override; + + /// Fill CRT calibration information. + virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const + override; + private: @@ -129,12 +126,13 @@ class icarusDB::ChannelMapSQLite std::string PMTfragmentMap; std::string CRTsideMap; std::string CRTtopMap; - // NOTE: CRT side calibration is is a different type of database which uses a timestamp + // NOTE: CRT side calibration is is a different type of database which uses a (currently hard-coded) timestamp }; /// SQLite callback function: SQLite will call this including `argc` arguments /// each from a column named from `colNames` with the value in `argv`. - using SQLiteCallbackFunc_t = int(*)(void* data, int argc, char** argv, char** colNames); + using SQLiteCallbackFunc_t + = int(*)(void* data, int argc, char** argv, char** colNames); // --- BEGIN --- Configuration parameters ------------------------------------ diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h new file mode 100644 index 000000000..5d3622c91 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h @@ -0,0 +1,123 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h + * @brief Data types used for caching channel maps. + * @author T. Usher (refactoring by G. Petrillo, petrillo@slac.stanford.edu) + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPDATATYPES_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPDATATYPES_H + +// C/C++ standard libraries +#include +#include +#include +#include +#include // std::size_t + + +namespace icarusDB { + + // --- BEGIN --- ICARUS channel mapping data definitions --------------------- + /// @name ICARUS channel mapping data definitions. + /// @{ + + + /// @name Data structures for mapping between TPC fragment IDs and the related + /// crate and readout information. + /// @{ + + /// Sequence of TPC readout board ID. + using ReadoutIDVec = std::vector; + + /// Name of the TPC readout crate, and list of IDs of hosted readout boards. + using CrateNameReadoutIDPair = std::pair; + + /// Map from fragment ID to crate information (name and readout board IDs). + using TPCFragmentIDToReadoutIDMap + = std::map; + + /// @} + + + /// @name Data structures for mapping between TPC readout board IDs and the + /// related crate and readout information. + /// @{ + + /// A TPC channel ID/TPC plane number pair. + using ChannelPlanePair = std::pair; + + /// A sequence of TPC channel IDs paired with their TPC plane number. + using ChannelPlanePairVec = std::vector; + + /// TPC readout board slot number and all channels in the board with plane. + using SlotChannelVecPair = std::pair; + + /// Map from TPC readout board ID to board information (slot and channels). + using TPCReadoutBoardToChannelMap + = std::map; + + /// @} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + /// @name Data structures for PMT channel mapping. + /// @{ + + /// A pair of tree: PMT digitizer channel number, LArSoft channel ID + /// and laser channel. + using DigitizerChannelChannelIDPair + = std::tuple; + + /// A sequence of PMT channel information for a single digitizer. + using DigitizerChannelChannelIDPairVec + = std::vector; + + /// Map from PMT fragment ID to information on all its digitizer channels. + using FragmentToDigitizerChannelMap + = std::map; + + /// @} + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + /// @name Data structures for CRT channel mapping. + /// @{ + + /// Hardware and Sim Mac addresses. + using CRTHWtoSimMacAddressPair = std::pair; + + /// Map of channel ID to Mac address pair for side CRT. + using CRTChannelIDToHWtoSimMacAddressPairMap + = std::map; + + /// Map of hardware Mac address to Sim Mac address for top CRT. + using TopCRTHWtoSimMacAddressPairMap = std::map; + + // @} + + + /// @name Data structures for CRT calibration information. + /// @{ + + /// Pair of channel ID and hardware Mac address for CRT. + using SideCRTMac5ToChannelPair = std::pair; + + /// CRT channel calibration information: gain and pedestal. + using SideCRTGainToPedPair = std::pair; + + /// Map of channel/hardware address to its calibration information. + using SideCRTChannelToCalibrationMap + = std::map; + + /// @} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + /// @} + // --- END ----- ICARUS channel mapping data definitions --------------------- + +} // namespace icarusDB + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPDATATYPES_H diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx index feaab52d4..3f37aa06e 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx @@ -1,438 +1,10 @@ /** * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.cxx - * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h */ // library header #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" -// ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" -#include "larcorealg/CoreUtils/values.h" // util::const_values() - -// framework libraries -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "fhiclcpp/ParameterSet.h" -#include "cetlib_except/exception.h" -#include "cetlib/cpu_timer.h" - -// C++ standard libraries -#include -#include -#include - - - -// ----------------------------------------------------------------------------- -icarusDB::ICARUSChannelMapPostGresProvider::ICARUSChannelMapPostGresProvider - (Config const& config) - : fDiagnosticOutput{ config.DiagnosticOutput() } - , fLogCategory{ config.LogCategory() } - , fChannelMappingAlg - { std::make_unique(config.ChannelMappingTool()) } -{ -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapPostGresProvider::forRun(int run) { - - RunPeriod period = RunPeriod::NPeriods; - try { - period = RunPeriods::withRun(run); - } catch (...) { - mf::LogError{ fLogCategory } - << "Failed to associate a run period number to run " << run << "."; - throw; - } - - if (period == RunPeriod::NPeriods) { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "forRun(): can't determine the period of run " << run << "!\n"; - } - - return forPeriod(period); - -} // icarusDB::ICARUSChannelMapPostGresProvider::forRun() - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapPostGresProvider::forPeriod - (icarusDB::RunPeriod period) -{ - - // if cache is not invalidated, we don't refresh it - if (!fChannelMappingAlg->SelectPeriod(period)) return false; - - readFromDatabase(); - return true; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapPostGresProvider::hasFragmentID - (const unsigned int fragmentID) const -{ - return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nTPCfragmentIDs() const { - return fFragmentToReadoutMap.size(); -} - - -// ----------------------------------------------------------------------------- -std::string const& icarusDB::ICARUSChannelMapPostGresProvider::getCrateName - (const unsigned int fragmentID) const -{ - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); - - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking up crate name \n"; - } - - return fragToReadoutItr->second.first; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::getReadoutBoardVec - (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& -{ - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); - - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking up board vector.\n"; - } - - return fragToReadoutItr->second.second; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::getReadoutBoardToChannelMap() - const -> const TPCReadoutBoardToChannelMap& -{ - return fReadoutBoardToChannelMap; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapPostGresProvider::hasBoardID - (const unsigned int boardID) const -{ - return - fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nTPCboardIDs() const { - return fReadoutBoardToChannelMap.size(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::getBoardSlot - (const unsigned int boardID) const -{ - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); - - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Board ID " << boardID - << " not found in lookup map when looking up board slot.\n"; - } - - return readoutBoardItr->second.first; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::getChannelPlanePair - (const unsigned int boardID) const -> ChannelPlanePairVec const& -{ - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); - - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Board ID " << boardID - << " not found in lookup map when looking up channel/plane pair.\n"; - } - - return readoutBoardItr->second.second; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapPostGresProvider::hasPMTDigitizerID - (const unsigned int fragmentID) const -{ - return findPMTfragmentEntry(fragmentID) != nullptr; -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::nPMTfragmentIDs() const { - return fFragmentToDigitizerMap.size(); -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::getChannelIDPairVec - (const unsigned int fragmentID) const - -> DigitizerChannelChannelIDPairVec const& -{ - mf::LogTrace{ "ICARUSChannelMapPostGresProvider" } - << "Call to: ICARUSChannelMapPostGresProvider::getChannelIDPairVec(" - << fragmentID << ")"; - - DigitizerChannelChannelIDPairVec const* digitizerPair - = findPMTfragmentEntry(fragmentID); - - if (digitizerPair) return *digitizerPair; - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking for PMT channel info.\n"; - -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::getSimMacAddress - (const unsigned int hwmacaddress) const -{ - for(auto const& [ hw, sim ] - : util::const_values(fCRTChannelIDToHWtoSimMacAddressPairMap) - ) { - if (hw == hwmacaddress) return sim; - } - - return 0; -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapPostGresProvider::gettopSimMacAddress - (const unsigned int hwmacaddress) const -{ -#if 0 // FIXME - unsigned int simmacaddress = 0; - - for(const auto& pair : fTopCRTHWtoSimMacAddressPairMap){ - if (pair.first == hwmacaddress) -simmacaddress = pair.second; - } - - return simmacaddress; -#else - // untested: - auto const it = fTopCRTHWtoSimMacAddressPairMap.find(hwmacaddress); - return (it == fTopCRTHWtoSimMacAddressPairMap.end())? 0: it->second; - -#endif -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::getSideCRTCalibrationMap - (int mac5, int chan) const -> std::pair -{ - auto const itGainAndPedestal - = fSideCRTChannelToCalibrationMap.find({ mac5, chan }); - return (itGainAndPedestal == fSideCRTChannelToCalibrationMap.cend()) - ? std::pair{ -99., -99. }: itGainAndPedestal->second; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapPostGresProvider::findPMTfragmentEntry - (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* -{ - auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); - return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); -} - - -// ----------------------------------------------------------------------------- -void icarusDB::ICARUSChannelMapPostGresProvider::readFromDatabase() { - - mf::LogInfo{ fLogCategory } << "Building the channel mapping"; - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // TPC fragment-based mapping - cet::cpu_timer theClockFragmentIDs; - theClockFragmentIDs.start(); - fFragmentToReadoutMap.clear(); - if (fChannelMappingAlg->BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) - { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Cannot recover the TPC fragment ID channel map from the database.\n"; - } - else if (fDiagnosticOutput) { - - mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; - log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() - << " elements"; - for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { - log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " - << crateAndBoards.first << ", # boards: " - << crateAndBoards.second.size(); - } - } - theClockFragmentIDs.stop(); - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // TPC readout-board-based mapping - double fragmentIDsTime = theClockFragmentIDs.accumulated_real_time(); - - cet::cpu_timer theClockReadoutIDs; - theClockReadoutIDs.start(); - - fReadoutBoardToChannelMap.clear(); - if (fChannelMappingAlg->BuildTPCReadoutBoardToChannelMap(fReadoutBoardToChannelMap)) - { - mf::LogError{ "ICARUSChannelMapPostGresProvider" } - << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Failed to read the database.\n"; - } - - theClockReadoutIDs.stop(); - double readoutIDsTime = theClockReadoutIDs.accumulated_real_time(); - - mf::LogInfo{ "ICARUSChannelMapPostGresProvider" } - << "==> FragmentID map time: " << fragmentIDsTime << ", Readout IDs time: " - << readoutIDsTime; - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PMT channel mapping - fFragmentToDigitizerMap.clear(); - if (fChannelMappingAlg->BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) - { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Cannot recover the PMT fragment ID channel map from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; - log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() - << " Fragment IDs"; - - for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { - log << "\n Frag: " << std::hex << fragmentID << std::dec - << ", # pairs: " << digitizers.size(); - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Side CRT channel mapping - fCRTChannelIDToHWtoSimMacAddressPairMap.clear(); - if (fChannelMappingAlg->BuildCRTChannelIDToHWtoSimMacAddressPairMap(fCRTChannelIDToHWtoSimMacAddressPairMap)) - { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Cannot recover the HW MAC Address from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; - log << "ChannelID to MacAddress map has " - << fCRTChannelIDToHWtoSimMacAddressPairMap.size() << " Channel IDs"; - for(auto const& [ channel, addresses ]: fCRTChannelIDToHWtoSimMacAddressPairMap) { - log <<"\n ChannelID: "<< channel - << ", hw mac address: " << addresses.first - << ", sim mac address: " << addresses.second; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Top CRT channel mapping - fTopCRTHWtoSimMacAddressPairMap.clear(); - if (fChannelMappingAlg->BuildTopCRTHWtoSimMacAddressPairMap(fTopCRTHWtoSimMacAddressPairMap)) - { - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Cannot recover the Top CRT HW MAC Address from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; - log << "Top CRT MacAddress map has " << fTopCRTHWtoSimMacAddressPairMap.size() << " rows"; - for(auto const [ hwaddress, simaddress ]: fTopCRTHWtoSimMacAddressPairMap) { - log << "\n hw mac address: " << hwaddress - << ", sim mac address: " << simaddress; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // CRT Charge Calibration initialization - fSideCRTChannelToCalibrationMap.clear(); - if (fChannelMappingAlg->BuildSideCRTCalibrationMap(fSideCRTChannelToCalibrationMap)) - { - mf::LogError{ "ICARUSChannelMapPostGresProvider" } - << "******* FAILED TO CONFIGURE CRT Calibration ********"; - throw cet::exception{ "ICARUSChannelMapPostGresProvider" } - << "Cannot recover the CRT charge calibration information from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapPostGresProvider" }; - log << "side crt calibration map has " - << fSideCRTChannelToCalibrationMap.size() << " list of rows"; - - for(auto const& [ key, calib ]: fSideCRTChannelToCalibrationMap) { - log << "\n mac5: "<< key.first << ", chan: " << key.second - << ", Gain: " << calib.first << ", Pedestal: " << calib.second; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} // icarusDB::ICARUSChannelMapPostGresProvider::readFromDatabase() - - -// ----------------------------------------------------------------------------- -constexpr unsigned int icarusDB::ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey - (unsigned int fragmentID) -{ - /* - * PMT channel mapping database stores the board number (0-23) as key. - * Fragment ID are currently in the pattern 0x20xx, with xx the board number. - */ - - // protest if this is a fragment not from the PMT; - // but make an exception for old PMT fragment IDs (legacy) - assert(((fragmentID & ~0xFF) == 0x00) || ((fragmentID & ~0xFF) == 0x20)); - - return fragmentID & 0xFF; - -} // ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey() - - -// ----------------------------------------------------------------------------- -constexpr unsigned int icarusDB::ICARUSChannelMapPostGresProvider::DBkeyToPMTfragmentID - (unsigned int DBkey) -{ - /* - * PMT channel mapping database stores the board number (0-23) as key. - * Fragment ID are currently in the pattern 0x20xx, with xx the board number. - */ - - // protest if this is a fragment not from the PMT; - // but make an exception for old PMT fragment IDs (legacy) - assert((DBkey & 0xFF) < 24); - - return (DBkey & 0xFF) | 0x2000; - -} // icarusDB::ICARUSChannelMapPostGresProvider::PMTfragmentIDtoDBkey() - - -// ----------------------------------------------------------------------------- +// nothing else diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h index d075df994..0fd7ef3ba 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h @@ -8,238 +8,37 @@ #define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPOSTGRESPROVIDER_H // ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" -#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h" #include "icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h" -// framework libraries -#include "fhiclcpp/types/Table.h" -#include "fhiclcpp/types/Atom.h" -#include "cetlib_except/exception.h" - -// C/C++ standard libraries -#include -#include // std::unique_ptr<> - // ----------------------------------------------------------------------------- namespace icarusDB { class ICARUSChannelMapPostGresProvider; } /** * @brief Interface to the PostgreSQL ICARUS channel mapping database. - * @see icarusDB::ICARUSChannelMapPostGres + * + * The database is normally deployed on the network. * * + * The implementation is fully delegated to + * `icarusDB::ICARUSChannelMapProviderBase`. + * * * Configuration parameters * ========================= * + * See `icarusDB::ICARUSChannelMapProviderBase`, except for: + * * * `ChannelMappingTool` (algorithm configuration): see * `icarusDB::ChannelMapPostGres` configuration. - * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters - * and in general prints more messages to console - * * `LogCategory` (string, default: `"ICARUSChannelMapPostGresProvider"`): - * name of the messagefacility category used to send messages to console, - * useful for filtering messages. - * * */ -class icarusDB::ICARUSChannelMapPostGresProvider: public IICARUSChannelMap { - - public: - /// The helper used to extract data from the database. - using ChannelMappingAlg_t = icarusDB::ChannelMapPostGres; - - struct Config { - using Name = fhicl::Name; - using Comment = fhicl::Comment; - - fhicl::Table ChannelMappingTool { - Name{ "ChannelMappingTool" }, - Comment{ "parameters for the channel mapping algorithm" } - }; - - fhicl::Atom DiagnosticOutput{ - Name{ "DiagnosticOutput" }, - Comment{ "enables verbose output to console" }, - false // default - }; - - fhicl::Atom LogCategory{ - Name{ "LogCategory" }, - Comment{ "name of the console stream to send messages to" }, - "ICARUSChannelMapPostGresProvider" // default - }; - - }; // Config - - using Parameters = fhicl::Table; - - - /// Constructor: configures the service provider via FHiCL configuration. - ICARUSChannelMapPostGresProvider(Config const& config); - - /// Constructor: configures the service provider via FHiCL configuration. - ICARUSChannelMapPostGresProvider(Parameters const& params) - : ICARUSChannelMapPostGresProvider{ params() } - {} - - - /// --- BEGIN --- Data period selection ------------------------------------ - /// @name Data period selection - /// @{ - - /// Loads the mapping for `run`, returns whether a new mapping was loaded. - virtual bool forRun(int run) override; - - /// Loads the mapping for `period`, returns whether a new mapping was loaded. - virtual bool forPeriod(icarusDB::RunPeriod period) override; - - /// @} - /// --- END ----- Data period selection ------------------------------------ - - - /// --- BEGIN --- TPC information ------------------------------------------ - /// @name TPC information - /// @{ - - /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - - /// @name TPC fragment information - /// @{ - - /// Returns whether the specified `ID` is a known TPC fragment ID. - virtual bool hasFragmentID(const unsigned int ID) const override; - /// Returns the number of TPC fragment IDs known to the service. - - /// Returns the number of known TPC fragments. - virtual unsigned int nTPCfragmentIDs() const override; - - /// Returns the name of the crate served by the specified `fragmentID`. - virtual std::string const& getCrateName - (const unsigned int fragmentID) const override; - - /// Returns the list of board IDs included in the specified `fragmentID`. - virtual ReadoutIDVec const& getReadoutBoardVec - (const unsigned int fragmentID) const override; - - /// @} - /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - - - /** - * @brief Returns the full TPC channel mapping. - * - * The returned mapping is an associative container, associating each board - * ID (`boardID`) to the following information (in a `std::tuple`): - * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) - * * `[1]` list of channels served by the board, and their plane - * (like `getChannelPlanePair(boardID)`) - * - */ - virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const - override; - - /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - - /// @name TPC board information - /// @{ - - /// Returns whether there is a board with the specified `ID`. - virtual bool hasBoardID(const unsigned int ID) const override; - /// Returns the number of TPC board IDs known to the service. - virtual unsigned int nTPCboardIDs() const override; - /// Returns the number of slot the `boardID` is on. - virtual unsigned int getBoardSlot(const unsigned int boardID) const override; - /// Returns a list of channels served by the `boardID` and for each the plane - /// it is on (`0` to `2`). - virtual ChannelPlanePairVec const& getChannelPlanePair - (const unsigned int boardID) const override; - - /// @} - /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - - - - /// --- BEGIN --- PMT information ------------------------------------------ - /// @name PMT information - /// @{ - - /// Returns whether the specified fragment `ID` is known to the mapping. - virtual bool hasPMTDigitizerID(const unsigned int ID) const override; - - /// Returns the number of PMT fragment IDs known to the mapping. - virtual unsigned int nPMTfragmentIDs() const override; - - /// Returns a list of triplets: - virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec - (const unsigned int) const override; - - /// @} - /// --- END ----- PMT information ------------------------------------------ - - - /// --- BEGIN --- CRT information ------------------------------------------ - /// @name CRT information - /// @{ - - /// Returns the sim Mac address corresponding to the specified side CRT hardware address. - virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const override; - /// Returns the sim Mac address corresponding to the specified top CRT hardware address. - virtual unsigned int gettopSimMacAddress(const unsigned int) const override; - - /// Returns the Gain and Pedestal for Side CRT. - virtual std::pair getSideCRTCalibrationMap - (int mac5, int chan) const override; - - /// @} - /// --- END ----- CRT information ------------------------------------------ - - /// Returns the channel mapping database key for the specified PMT fragment ID. - static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); - - /// Returns the PMT fragment ID for the specified channel mapping database key. - static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); - - - private: - - // --- BEGIN --- Configuration parameters ------------------------------------ - - bool const fDiagnosticOutput; - - std::string const fLogCategory; - - // --- END ----- Configuration parameters ------------------------------------ - - - // --- BEGIN --- Cache ------------------------------------------------------- - IChannelMapping::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; - - IChannelMapping::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; - - IChannelMapping::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; - - IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; - - IChannelMapping::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; - - IChannelMapping::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; - - // --- END ----- Cache ------------------------------------------------------- - - /// The helper extracting information from the database. - std::unique_ptr fChannelMappingAlg; - - - /// Has the channel mapping tool fill the mapping caches. - virtual void readFromDatabase(); - - - /// Returns the list of board channel-to-PMT channel ID mapping within the - /// specified fragment. - /// - /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment - DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry - (unsigned int fragmentID) const; - - -}; // icarusDB::ICARUSChannelMapPostGresProvider +class icarusDB::ICARUSChannelMapPostGresProvider + : public icarusDB::ICARUSChannelMapProviderBase +{ + using Base_t = ICARUSChannelMapProviderBase; + using Base_t::Base_t; +}; // ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc index be711c3f9..bb559c025 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc @@ -15,8 +15,6 @@ #include "art/Framework/Services/Registry/ServiceTable.h" #include "art/Framework/Principal/Run.h" #include "messagefacility/MessageLogger/MessageLogger.h" -#include "fhiclcpp/ParameterSet.h" -#include "cetlib_except/exception.h" // ----------------------------------------------------------------------------- @@ -28,22 +26,23 @@ namespace icarusDB { class ICARUSChannelMapPostGres; } * PostgreSQL database. * * This service implements the generic channel mapping access service provider - * interface `icarusDB::ICARUSChannelMap`. - * To use the channel mapping, include in your code the header of - * `icarusDB::ICARUSChannelMap`, and access the service provider via: + * interface `icarusDB::IICARUSChannelMapProvider`. + * To use the channel mapping, include in your code the header of the service + * interface `icarusDB::IICARUSChannelMap`, and access the service provider via: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} - * icarusDB::IICARUSChannelMap const& channelMapping - * = *lar::providerFrom(); + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *lar::providerFrom(); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * or similar (`lar::providerFrom()` is in `larcore/CoreUtils/ServiceUtils.h`) * or directly the service via * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} - * icarusDB::ICARUSChannelMap const& channelMapping - * = *art::ServiceHandle(); + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *art::ServiceHandle(); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * For details on the interface, see `icarusDB::IICARUSChannelMap`. - * For details on the implementation, see `icarusDB::ICARUSChannelMap`. + * For details on the interface, see `icarusDB::IICARUSChannelMapProvider`. + * For details on the implementation, see + * `icarusDB::ICARUSChannelMapPostGresProvider`. * * @note For production and processes that need robustness, using the SQLite * database and backend (`icarusDB::ICARUSChannelMapSQLite`) is suggested @@ -52,7 +51,7 @@ namespace icarusDB { class ICARUSChannelMapPostGres; } * */ class icarusDB::ICARUSChannelMapPostGres - : public ICARUSChannelMapPostGresProvider + : public IICARUSChannelMap, public ICARUSChannelMapPostGresProvider, { /// Prepares the mapping for the specified run. diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx index 866f10c51..2d0a672ef 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx @@ -193,7 +193,7 @@ unsigned int ICARUSChannelMapProvider::nTPCfragmentIDs() const { const std::string& ICARUSChannelMapProvider::getCrateName(const unsigned int fragmentID) const { - IChannelMapping::TPCFragmentIDToReadoutIDMap::const_iterator fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + TPCFragmentIDToReadoutIDMap::const_iterator fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); if (fragToReadoutItr == fFragmentToReadoutMap.end()) throw cet::exception("ICARUSChannelMapProvider") << "Fragment ID " << fragmentID << " not found in lookup map when looking up crate name \n"; @@ -203,7 +203,7 @@ const std::string& ICARUSChannelMapProvider::getCrateName(const unsigned int fr const ReadoutIDVec& ICARUSChannelMapProvider::getReadoutBoardVec(const unsigned int fragmentID) const { - IChannelMapping::TPCFragmentIDToReadoutIDMap::const_iterator fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + TPCFragmentIDToReadoutIDMap::const_iterator fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); if (fragToReadoutItr == fFragmentToReadoutMap.end()) throw cet::exception("ICARUSChannelMapProvider") << "Fragment ID " << fragmentID << " not found in lookup map when looking up board vector \n"; @@ -231,7 +231,7 @@ unsigned int ICARUSChannelMapProvider::nTPCboardIDs() const { unsigned int ICARUSChannelMapProvider::getBoardSlot(const unsigned int boardID) const { - IChannelMapping::TPCReadoutBoardToChannelMap::const_iterator readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + TPCReadoutBoardToChannelMap::const_iterator readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); if (readoutBoardItr == fReadoutBoardToChannelMap.end()) throw cet::exception("ICARUSChannelMapProvider") << "Board ID " << boardID << " not found in lookup map when looking up board slot \n"; @@ -241,7 +241,7 @@ unsigned int ICARUSChannelMapProvider::getBoardSlot(const unsigned int boardID) const ChannelPlanePairVec& ICARUSChannelMapProvider::getChannelPlanePair(const unsigned int boardID) const { - IChannelMapping::TPCReadoutBoardToChannelMap::const_iterator readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + TPCReadoutBoardToChannelMap::const_iterator readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); if (readoutBoardItr == fReadoutBoardToChannelMap.end()) throw cet::exception("ICARUSChannelMapProvider") << "Board ID " << boardID << " not found in lookup map when looking up channel/plane pair \n"; diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h index 83965f171..63e2c82c0 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h @@ -83,17 +83,17 @@ class icarusDB::ICARUSChannelMapProvider: public IICARUSChannelMap bool fDiagnosticOutput; - IChannelMapping::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; + TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; - IChannelMapping::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; + TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; - IChannelMapping::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + FragmentToDigitizerChannelMap fFragmentToDigitizerMap; - IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; + CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; - IChannelMapping::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; + TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; - IChannelMapping::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; + SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; std::unique_ptr fChannelMappingTool; diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h new file mode 100644 index 000000000..a04c863a6 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h @@ -0,0 +1,287 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h + * @author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.cxx + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDERBASE_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDERBASE_H + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h" +#include "icarusalg/Utilities/mfLoggingClass.h" + +// framework libraries +#include "fhiclcpp/types/Table.h" +#include "fhiclcpp/types/OptionalAtom.h" +#include "fhiclcpp/types/Atom.h" +#include "cetlib_except/exception.h" + +// C/C++ standard libraries +#include +#include // std::unique_ptr<> + + +// ----------------------------------------------------------------------------- +namespace icarusDB { + template class ICARUSChannelMapProviderBase; +} +/** + * @brief Base implementation of ICARUS channel mapping database interface. + * @tparam ChMapAlg type of channel mapping helper to be used + * + * + * Configuration parameters + * ========================= + * + * * `ChannelMappingTool` (algorithm configuration): see the configuration + * of the database backend access helper (`ChMapAlg`) + * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters + * and in general prints more messages to console + * * `LogCategory` (string, default: same as `ChannelMappingTool.LogCategory`): + * name of the messagefacility category used to send messages to console, + * useful for filtering messages. + * + * + * Implementation details + * ======================= + * + * The only reason for the existence of this base class is that due to their + * original form the two service providers implementing access to SQLite and to + * PostgreSQL database share most of the code. + * So that code is collected in a base class. + * + * In fact, the main difference between the previous factor form and the current + * one is that then the database backend was selected via _art_ tool within a + * single provider, while now each provider has its backend statically coded in + * and the choice happens at service level (the service level choice was dummy + * since there was a single service and a single provider). + * + * The service provider interface is inherited with virtual inheritance, because + * it is foreseen that the service interface also inherits from the service + * provider interface, and virtual inheritance guarantees that there is only + * one underlying interface class (and ultimately it is this one which provides + * the actual implementation of the interface). + * + */ +template +class icarusDB::ICARUSChannelMapProviderBase + : virtual public IICARUSChannelMapProvider + , private icarus::ns::util::mfLoggingClass +{ + + public: + /// The helper used to extract data from the database. + using ChannelMappingAlg_t = ChMapAlg; + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Table ChannelMappingTool { + Name{ "ChannelMappingTool" }, + Comment{ "parameters for the channel mapping algorithm" } + }; + + fhicl::Atom DiagnosticOutput{ + Name{ "DiagnosticOutput" }, + Comment{ "enables verbose output to console" }, + false // default + }; + + fhicl::OptionalAtom LogCategory{ + Name{ "LogCategory" }, + Comment{ "name of the console stream to send messages to" } + }; + + }; // Config + + using Parameters = fhicl::Table; + + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapProviderBase(Config const& config); + + /// Constructor: configures the service provider via FHiCL configuration. + ICARUSChannelMapProviderBase(Parameters const& params) + : ICARUSChannelMapProviderBase{ params() } + {} + + + /// --- BEGIN --- Data period selection ------------------------------------ + /// @name Data period selection + /// @{ + + /// Loads the mapping for `run`, returns whether a new mapping was loaded. + virtual bool forRun(int run) override; + + /// Loads the mapping for `period`, returns whether a new mapping was loaded. + virtual bool forPeriod(icarusDB::RunPeriod period) override; + + /// @} + /// --- END ----- Data period selection ------------------------------------ + + + /// --- BEGIN --- TPC information ------------------------------------------ + /// @name TPC information + /// @{ + + /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - + /// @name TPC fragment information + /// @{ + + /// Returns whether the specified `ID` is a known TPC fragment ID. + virtual bool hasFragmentID(unsigned int ID) const override; + /// Returns the number of TPC fragment IDs known to the service. + + /// Returns the number of known TPC fragments. + virtual unsigned int nTPCfragmentIDs() const override; + + /// Returns the name of the crate served by the specified `fragmentID`. + virtual std::string const& getCrateName (unsigned int fragmentID) const + override; + + /// Returns the list of board IDs included in the specified `fragmentID`. + virtual ReadoutIDVec const& getReadoutBoardVec(unsigned int fragmentID) const + override; + + /// @} + /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - + + /** + * @brief Returns the full TPC channel mapping. + * + * The returned mapping is an associative container, associating each board + * ID (`boardID`) to the following information (in a `std::tuple`): + * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) + * * `[1]` list of channels served by the board, and their plane + * (like `getChannelPlanePair(boardID)`) + * + */ + virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const + override; + + /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - + /// @name TPC board information + /// @{ + + /// Returns whether there is a board with the specified `ID`. + virtual bool hasBoardID(unsigned int ID) const override; + + /// Returns the number of TPC board IDs known to the service. + virtual unsigned int nTPCboardIDs() const override; + + /// Returns the number of slot the `boardID` is on. + virtual unsigned int getBoardSlot(unsigned int boardID) const override; + + /// Returns a list of channels served by the `boardID` and for each the plane + /// it is on (`0` to `2`). + virtual ChannelPlanePairVec const& getChannelPlanePair + (unsigned int boardID) const override; + + /// @} + /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - + + + /// --- BEGIN --- PMT information ------------------------------------------ + /// @name PMT information + /// @{ + + /// Returns whether the specified fragment `ID` is known to the mapping. + virtual bool hasPMTDigitizerID(unsigned int ID) const override; + + /// Returns the number of PMT fragment IDs known to the mapping. + virtual unsigned int nPMTfragmentIDs() const override; + + /// Returns a list of triplets: digitizer channel number, channel ID and + /// laser channel. + virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec + (unsigned int) const override; + + /// @} + /// --- END ----- PMT information ------------------------------------------ + + + /// --- BEGIN --- CRT information ------------------------------------------ + /// @name CRT information + /// @{ + + /// Returns the sim Mac address corresponding to the specified side CRT hardware address. + virtual unsigned int getSimMacAddress(unsigned int hwmacaddress) const + override; + + /// Returns the sim Mac address corresponding to the specified top CRT hardware address. + virtual unsigned int gettopSimMacAddress(unsigned int) const override; + + /// Returns the Gain and Pedestal for Side CRT. + virtual std::pair getSideCRTCalibrationMap + (int mac5, int chan) const override; + + /// @} + /// --- END ----- CRT information ------------------------------------------ + + /// Returns the channel mapping database key for the specified PMT fragment ID. + static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); + + /// Returns the PMT fragment ID for the specified channel mapping database key. + static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); + + + protected: + + // --- BEGIN --- Configuration parameters ------------------------------------ + + bool const fDiagnosticOutput; + + std::string const fLogCategory; + + // --- END ----- Configuration parameters ------------------------------------ + + + /// The helper extracting information from the database. + ChannelMappingAlg_t fChannelMappingAlg; + + + // --- BEGIN --- Cache ------------------------------------------------------- + + icarusDB::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; + + icarusDB::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; + + icarusDB::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + + icarusDB::CRTChannelIDToHWtoSimMacAddressPairMap + fCRTChannelIDToHWtoSimMacAddressPairMap; + + icarusDB::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; + + icarusDB::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; + + // --- END ----- Cache ------------------------------------------------------- + + + /// Has the channel mapping tool fill the mapping caches. + void readFromDatabase(); + + /// Returns the list of board channel-to-PMT channel ID mapping within the + /// specified fragment. + /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment + icarusDB::DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry + (unsigned int fragmentID) const; + + /// Returns an exception signed by this object. + cet::exception myException() const + { return cet::exception{ "ICARUSChannelMapProviderBase" }; } + +}; // icarusDB::ICARUSChannelMapProviderBase + + +// ----------------------------------------------------------------------------- +// --- template implementation +// ----------------------------------------------------------------------------- + +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx" + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDERBASE_H diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx new file mode 100644 index 000000000..3515ab691 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx @@ -0,0 +1,440 @@ +/** + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx + * @author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) + * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h + */ + +// library header +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h" + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "larcorealg/CoreUtils/values.h" // util::const_values() + +// framework libraries +#include "cetlib_except/exception.h" +#include "cetlib/cpu_timer.h" + +// C++ standard libraries +#include +#include + + +// ----------------------------------------------------------------------------- +template +icarusDB::ICARUSChannelMapProviderBase::ICARUSChannelMapProviderBase + (Config const& config) + : icarus::ns::util::mfLoggingClass + { config.LogCategory().value_or(config.ChannelMappingTool().LogCategory()) } + , fDiagnosticOutput { config.DiagnosticOutput() } + , fChannelMappingAlg { config.ChannelMappingTool() } +{ +} + + +// ----------------------------------------------------------------------------- +template +bool icarusDB::ICARUSChannelMapProviderBase::forRun(int run) { + + RunPeriod period = RunPeriod::NPeriods; + try { + period = RunPeriods::withRun(run); + } catch (...) { + mfLogError() + << "Failed to associate a run period number to run " << run << "."; + throw; + } + + if (period == RunPeriod::NPeriods) { + throw myException() + << "forRun(): can't determine the period of run " << run << "!\n"; + } + + return forPeriod(period); + +} // icarusDB::ICARUSChannelMapProviderBase<>::forRun() + + +// ----------------------------------------------------------------------------- +template +bool icarusDB::ICARUSChannelMapProviderBase::forPeriod + (icarusDB::RunPeriod period) +{ + + // if cache is not invalidated, we don't refresh it + if (!fChannelMappingAlg.SelectPeriod(period)) return false; + + readFromDatabase(); + return true; +} + + +// ----------------------------------------------------------------------------- +template +bool icarusDB::ICARUSChannelMapProviderBase::hasFragmentID + (const unsigned int fragmentID) const +{ + return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); +} + + +// ----------------------------------------------------------------------------- +template +unsigned int icarusDB::ICARUSChannelMapProviderBase::nTPCfragmentIDs() const { + return fFragmentToReadoutMap.size(); +} + + +// ----------------------------------------------------------------------------- +template +std::string const& icarusDB::ICARUSChannelMapProviderBase::getCrateName + (const unsigned int fragmentID) const +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw myException() << "Fragment ID " << fragmentID + << " not found in lookup map when looking up crate name \n"; + } + + return fragToReadoutItr->second.first; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::getReadoutBoardVec + (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& +{ + auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + + if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + throw myException() << "Fragment ID " << fragmentID + << " not found in lookup map when looking up board vector.\n"; + } + + return fragToReadoutItr->second.second; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::getReadoutBoardToChannelMap() + const -> const TPCReadoutBoardToChannelMap& +{ + return fReadoutBoardToChannelMap; +} + + +// ----------------------------------------------------------------------------- +template +bool icarusDB::ICARUSChannelMapProviderBase::hasBoardID + (const unsigned int boardID) const +{ + return + fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); +} + + +// ----------------------------------------------------------------------------- +template +unsigned int icarusDB::ICARUSChannelMapProviderBase::nTPCboardIDs() const { + return fReadoutBoardToChannelMap.size(); +} + + +// ----------------------------------------------------------------------------- +template +unsigned int icarusDB::ICARUSChannelMapProviderBase::getBoardSlot + (const unsigned int boardID) const +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw myException() << "Board ID " << boardID + << " not found in lookup map when looking up board slot.\n"; + } + + return readoutBoardItr->second.first; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::getChannelPlanePair + (const unsigned int boardID) const -> ChannelPlanePairVec const& +{ + auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + + if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + throw myException() << "Board ID " << boardID + << " not found in lookup map when looking up channel/plane pair.\n"; + } + + return readoutBoardItr->second.second; +} + + +// ----------------------------------------------------------------------------- +template +bool icarusDB::ICARUSChannelMapProviderBase::hasPMTDigitizerID + (const unsigned int fragmentID) const +{ + return findPMTfragmentEntry(fragmentID) != nullptr; +} + + +// ----------------------------------------------------------------------------- +template +unsigned int icarusDB::ICARUSChannelMapProviderBase::nPMTfragmentIDs() + const +{ + return fFragmentToDigitizerMap.size(); +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::getChannelIDPairVec + (const unsigned int fragmentID) const + -> DigitizerChannelChannelIDPairVec const& +{ + mfLogTrace() + << "Call to: ICARUSChannelMapProviderBase::getChannelIDPairVec(" + << fragmentID << ")"; + + DigitizerChannelChannelIDPairVec const* digitizerPair + = findPMTfragmentEntry(fragmentID); + + if (digitizerPair) return *digitizerPair; + throw myException() << "Fragment ID " << fragmentID + << " not found in lookup map when looking for PMT channel info.\n"; + +} + + +// ----------------------------------------------------------------------------- +template +unsigned int icarusDB::ICARUSChannelMapProviderBase::getSimMacAddress + (const unsigned int hwmacaddress) const +{ + for(auto const& [ hw, sim ] + : util::const_values(fCRTChannelIDToHWtoSimMacAddressPairMap) + ) { + if (hw == hwmacaddress) return sim; + } + + return 0; +} + + +// ----------------------------------------------------------------------------- +template +unsigned int +icarusDB::ICARUSChannelMapProviderBase::gettopSimMacAddress + (const unsigned int hwmacaddress) const +{ + auto const it = fTopCRTHWtoSimMacAddressPairMap.find(hwmacaddress); + return (it == fTopCRTHWtoSimMacAddressPairMap.end())? 0: it->second; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::getSideCRTCalibrationMap + (int mac5, int chan) const -> std::pair +{ + auto const itGainAndPedestal + = fSideCRTChannelToCalibrationMap.find({ mac5, chan }); + return (itGainAndPedestal == fSideCRTChannelToCalibrationMap.cend()) + ? std::pair{ -99., -99. }: itGainAndPedestal->second; +} + + +// ----------------------------------------------------------------------------- +template +auto icarusDB::ICARUSChannelMapProviderBase::findPMTfragmentEntry + (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* +{ + auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); + return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); +} + + +// ----------------------------------------------------------------------------- +template +void icarusDB::ICARUSChannelMapProviderBase::readFromDatabase() { + + mfLogInfo() << "Building the channel mapping"; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC fragment-based mapping + cet::cpu_timer theClockFragmentIDs; + theClockFragmentIDs.start(); + fFragmentToReadoutMap.clear(); + if (fChannelMappingAlg.BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) + { + throw myException() + << "Cannot recover the TPC fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + + auto log = mfLogVerbatim(); + log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() + << " elements"; + for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " + << crateAndBoards.first << ", # boards: " + << crateAndBoards.second.size(); + } + } + theClockFragmentIDs.stop(); + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TPC readout-board-based mapping + double fragmentIDsTime = theClockFragmentIDs.accumulated_real_time(); + + cet::cpu_timer theClockReadoutIDs; + theClockReadoutIDs.start(); + + fReadoutBoardToChannelMap.clear(); + if (fChannelMappingAlg.BuildTPCReadoutBoardToChannelMap + (fReadoutBoardToChannelMap) + ) { + mfLogError() << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; + throw myException() << "Failed to read the database.\n"; + } + + theClockReadoutIDs.stop(); + double readoutIDsTime = theClockReadoutIDs.accumulated_real_time(); + + mfLogInfo() << "==> FragmentID map time: " << fragmentIDsTime + << ", Readout IDs time: " << readoutIDsTime; + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // PMT channel mapping + fFragmentToDigitizerMap.clear(); + if (fChannelMappingAlg.BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) + { + throw myException() + << "Cannot recover the PMT fragment ID channel map from the database.\n"; + } + else if (fDiagnosticOutput) { + auto log = mfLogVerbatim(); + log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() + << " Fragment IDs"; + + for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { + log << "\n Frag: " << std::hex << fragmentID << std::dec + << ", # pairs: " << digitizers.size(); + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Side CRT channel mapping + fCRTChannelIDToHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg.BuildCRTChannelIDToHWtoSimMacAddressPairMap(fCRTChannelIDToHWtoSimMacAddressPairMap)) + { + throw myException() + << "Cannot recover the HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + auto log = mfLogVerbatim(); + log << "ChannelID to MacAddress map has " + << fCRTChannelIDToHWtoSimMacAddressPairMap.size() << " Channel IDs"; + for(auto const& [ channel, addresses ]: fCRTChannelIDToHWtoSimMacAddressPairMap) { + log <<"\n ChannelID: "<< channel + << ", hw mac address: " << addresses.first + << ", sim mac address: " << addresses.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Top CRT channel mapping + fTopCRTHWtoSimMacAddressPairMap.clear(); + if (fChannelMappingAlg.BuildTopCRTHWtoSimMacAddressPairMap(fTopCRTHWtoSimMacAddressPairMap)) + { + throw myException() + << "Cannot recover the Top CRT HW MAC Address from the database.\n"; + } + else if (fDiagnosticOutput) { + auto log = mfLogVerbatim(); + log << "Top CRT MacAddress map has " << fTopCRTHWtoSimMacAddressPairMap.size() << " rows"; + for(auto const [ hwaddress, simaddress ]: fTopCRTHWtoSimMacAddressPairMap) { + log << "\n hw mac address: " << hwaddress + << ", sim mac address: " << simaddress; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // CRT Charge Calibration initialization + fSideCRTChannelToCalibrationMap.clear(); + if (fChannelMappingAlg.BuildSideCRTCalibrationMap + (fSideCRTChannelToCalibrationMap) + ) { + mfLogError() << "******* FAILED TO CONFIGURE CRT Calibration ********"; + throw myException() + << "Cannot recover the CRT charge calibration information from the database.\n"; + } + else if (fDiagnosticOutput) { + auto log = mfLogVerbatim(); + log << "side crt calibration map has " + << fSideCRTChannelToCalibrationMap.size() << " list of rows"; + + for(auto const& [ key, calib ]: fSideCRTChannelToCalibrationMap) { + log << "\n mac5: "<< key.first << ", chan: " << key.second + << ", Gain: " << calib.first << ", Pedestal: " << calib.second; + } + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +} // icarusDB::ICARUSChannelMapProviderBase<>::readFromDatabase() + + +// ----------------------------------------------------------------------------- +template +constexpr unsigned int icarusDB::ICARUSChannelMapProviderBase::PMTfragmentIDtoDBkey + (unsigned int fragmentID) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert(((fragmentID & ~0xFF) == 0x00) || ((fragmentID & ~0xFF) == 0x20)); + + return fragmentID & 0xFF; + +} // ICARUSChannelMapProviderBase<>::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- +template +constexpr unsigned int +icarusDB::ICARUSChannelMapProviderBase::DBkeyToPMTfragmentID + (unsigned int DBkey) +{ + /* + * PMT channel mapping database stores the board number (0-23) as key. + * Fragment ID are currently in the pattern 0x20xx, with xx the board number. + */ + + // protest if this is a fragment not from the PMT; + // but make an exception for old PMT fragment IDs (legacy) + assert((DBkey & 0xFF) < 24); + + return (DBkey & 0xFF) | 0x2000; + +} // icarusDB::ICARUSChannelMapProviderBase<>::PMTfragmentIDtoDBkey() + + +// ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx index bd4ecf39d..242c3c4fe 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx @@ -7,432 +7,4 @@ // library header #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" -// ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" -#include "larcorealg/CoreUtils/values.h" // util::const_values() - -// framework libraries -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "fhiclcpp/ParameterSet.h" -#include "cetlib_except/exception.h" -#include "cetlib/cpu_timer.h" - -// C++ standard libraries -#include -#include -#include - - - -// ----------------------------------------------------------------------------- -icarusDB::ICARUSChannelMapSQLiteProvider::ICARUSChannelMapSQLiteProvider - (Config const& config) - : fDiagnosticOutput{ config.DiagnosticOutput() } - , fLogCategory{ config.LogCategory() } - , fChannelMappingAlg - { std::make_unique(config.ChannelMappingTool()) } -{ -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapSQLiteProvider::forRun(int run) { - - RunPeriod period = RunPeriod::NPeriods; - try { - period = RunPeriods::withRun(run); - } catch (...) { - mf::LogError{ fLogCategory } - << "Failed to associate a run period number to run " << run << "."; - throw; - } - - if (period == RunPeriod::NPeriods) { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "forRun(): can't determine the period of run " << run << "!\n"; - } - - return forPeriod(period); - -} // icarusDB::ICARUSChannelMapSQLiteProvider::forRun() - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapSQLiteProvider::forPeriod - (icarusDB::RunPeriod period) -{ - - // if cache is not invalidated, we don't refresh it - if (!fChannelMappingAlg->SelectPeriod(period)) return false; - - readFromDatabase(); - return true; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapSQLiteProvider::hasFragmentID - (const unsigned int fragmentID) const -{ - return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nTPCfragmentIDs() const { - return fFragmentToReadoutMap.size(); -} - - -// ----------------------------------------------------------------------------- -std::string const& icarusDB::ICARUSChannelMapSQLiteProvider::getCrateName - (const unsigned int fragmentID) const -{ - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); - - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking up crate name \n"; - } - - return fragToReadoutItr->second.first; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::getReadoutBoardVec - (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& -{ - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); - - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking up board vector.\n"; - } - - return fragToReadoutItr->second.second; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::getReadoutBoardToChannelMap() - const -> const TPCReadoutBoardToChannelMap& -{ - return fReadoutBoardToChannelMap; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapSQLiteProvider::hasBoardID - (const unsigned int boardID) const -{ - return - fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nTPCboardIDs() const { - return fReadoutBoardToChannelMap.size(); -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::getBoardSlot - (const unsigned int boardID) const -{ - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); - - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Board ID " << boardID - << " not found in lookup map when looking up board slot.\n"; - } - - return readoutBoardItr->second.first; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::getChannelPlanePair - (const unsigned int boardID) const -> ChannelPlanePairVec const& -{ - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); - - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Board ID " << boardID - << " not found in lookup map when looking up channel/plane pair.\n"; - } - - return readoutBoardItr->second.second; -} - - -// ----------------------------------------------------------------------------- -bool icarusDB::ICARUSChannelMapSQLiteProvider::hasPMTDigitizerID - (const unsigned int fragmentID) const -{ - return findPMTfragmentEntry(fragmentID) != nullptr; -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::nPMTfragmentIDs() const { - return fFragmentToDigitizerMap.size(); -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::getChannelIDPairVec - (const unsigned int fragmentID) const - -> DigitizerChannelChannelIDPairVec const& -{ - mf::LogTrace{ "ICARUSChannelMapSQLiteProvider" } - << "Call to: ICARUSChannelMapSQLiteProvider::getChannelIDPairVec(" - << fragmentID << ")"; - - DigitizerChannelChannelIDPairVec const* digitizerPair - = findPMTfragmentEntry(fragmentID); - - if (digitizerPair) return *digitizerPair; - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Fragment ID " << fragmentID - << " not found in lookup map when looking for PMT channel info.\n"; - -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::getSimMacAddress - (const unsigned int hwmacaddress) const -{ - for(auto const& [ hw, sim ] - : util::const_values(fCRTChannelIDToHWtoSimMacAddressPairMap) - ) { - if (hw == hwmacaddress) return sim; - } - - return 0; -} - - -// ----------------------------------------------------------------------------- -unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::gettopSimMacAddress - (const unsigned int hwmacaddress) const -{ -#if 0 // FIXME - unsigned int simmacaddress = 0; - - for(const auto& pair : fTopCRTHWtoSimMacAddressPairMap){ - if (pair.first == hwmacaddress) -simmacaddress = pair.second; - } - - return simmacaddress; -#else - // untested: - auto const it = fTopCRTHWtoSimMacAddressPairMap.find(hwmacaddress); - return (it == fTopCRTHWtoSimMacAddressPairMap.end())? 0: it->second; - -#endif -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::getSideCRTCalibrationMap - (int mac5, int chan) const -> std::pair -{ - auto const itGainAndPedestal - = fSideCRTChannelToCalibrationMap.find({ mac5, chan }); - return (itGainAndPedestal == fSideCRTChannelToCalibrationMap.cend()) - ? std::pair{ -99., -99. }: itGainAndPedestal->second; -} - - -// ----------------------------------------------------------------------------- -auto icarusDB::ICARUSChannelMapSQLiteProvider::findPMTfragmentEntry - (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* -{ - auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); - return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); -} - - -// ----------------------------------------------------------------------------- -void icarusDB::ICARUSChannelMapSQLiteProvider::readFromDatabase() { - - mf::LogInfo{ fLogCategory } << "Building the channel mapping"; - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // TPC fragment-based mapping - cet::cpu_timer theClockFragmentIDs; - theClockFragmentIDs.start(); - fFragmentToReadoutMap.clear(); - if (fChannelMappingAlg->BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) - { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Cannot recover the TPC fragment ID channel map from the database.\n"; - } - else if (fDiagnosticOutput) { - - mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; - log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() - << " elements"; - for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { - log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " - << crateAndBoards.first << ", # boards: " - << crateAndBoards.second.size(); - } - } - theClockFragmentIDs.stop(); - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // TPC readout-board-based mapping - double fragmentIDsTime = theClockFragmentIDs.accumulated_real_time(); - - cet::cpu_timer theClockReadoutIDs; - theClockReadoutIDs.start(); - - fReadoutBoardToChannelMap.clear(); - if (fChannelMappingAlg->BuildTPCReadoutBoardToChannelMap(fReadoutBoardToChannelMap)) - { - mf::LogError{ "ICARUSChannelMapSQLiteProvider" } - << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Failed to read the database.\n"; - } - - theClockReadoutIDs.stop(); - double readoutIDsTime = theClockReadoutIDs.accumulated_real_time(); - - mf::LogInfo{ "ICARUSChannelMapSQLiteProvider" } - << "==> FragmentID map time: " << fragmentIDsTime << ", Readout IDs time: " - << readoutIDsTime; - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PMT channel mapping - fFragmentToDigitizerMap.clear(); - if (fChannelMappingAlg->BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) - { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Cannot recover the PMT fragment ID channel map from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; - log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() - << " Fragment IDs"; - - for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { - log << "\n Frag: " << std::hex << fragmentID << std::dec - << ", # pairs: " << digitizers.size(); - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Side CRT channel mapping - fCRTChannelIDToHWtoSimMacAddressPairMap.clear(); - if (fChannelMappingAlg->BuildCRTChannelIDToHWtoSimMacAddressPairMap(fCRTChannelIDToHWtoSimMacAddressPairMap)) - { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Cannot recover the HW MAC Address from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; - log << "ChannelID to MacAddress map has " - << fCRTChannelIDToHWtoSimMacAddressPairMap.size() << " Channel IDs"; - for(auto const& [ channel, addresses ]: fCRTChannelIDToHWtoSimMacAddressPairMap) { - log <<"\n ChannelID: "<< channel - << ", hw mac address: " << addresses.first - << ", sim mac address: " << addresses.second; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Top CRT channel mapping - fTopCRTHWtoSimMacAddressPairMap.clear(); - if (fChannelMappingAlg->BuildTopCRTHWtoSimMacAddressPairMap(fTopCRTHWtoSimMacAddressPairMap)) - { - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Cannot recover the Top CRT HW MAC Address from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; - log << "Top CRT MacAddress map has " << fTopCRTHWtoSimMacAddressPairMap.size() << " rows"; - for(auto const [ hwaddress, simaddress ]: fTopCRTHWtoSimMacAddressPairMap) { - log << "\n hw mac address: " << hwaddress - << ", sim mac address: " << simaddress; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // CRT Charge Calibration initialization - fSideCRTChannelToCalibrationMap.clear(); - if (fChannelMappingAlg->BuildSideCRTCalibrationMap(fSideCRTChannelToCalibrationMap)) - { - mf::LogError{ "ICARUSChannelMapSQLiteProvider" } - << "******* FAILED TO CONFIGURE CRT Calibration ********"; - throw cet::exception{ "ICARUSChannelMapSQLiteProvider" } - << "Cannot recover the CRT charge calibration information from the database.\n"; - } - else if (fDiagnosticOutput) { - mf::LogVerbatim log{ "ICARUSChannelMapSQLiteProvider" }; - log << "side crt calibration map has " - << fSideCRTChannelToCalibrationMap.size() << " list of rows"; - - for(auto const& [ key, calib ]: fSideCRTChannelToCalibrationMap) { - log << "\n mac5: "<< key.first << ", chan: " << key.second - << ", Gain: " << calib.first << ", Pedestal: " << calib.second; - } - } - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} // icarusDB::ICARUSChannelMapSQLiteProvider::readFromDatabase() - - -// ----------------------------------------------------------------------------- -constexpr unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey - (unsigned int fragmentID) -{ - /* - * PMT channel mapping database stores the board number (0-23) as key. - * Fragment ID are currently in the pattern 0x20xx, with xx the board number. - */ - - // protest if this is a fragment not from the PMT; - // but make an exception for old PMT fragment IDs (legacy) - assert(((fragmentID & ~0xFF) == 0x00) || ((fragmentID & ~0xFF) == 0x20)); - - return fragmentID & 0xFF; - -} // ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey() - - -// ----------------------------------------------------------------------------- -constexpr unsigned int icarusDB::ICARUSChannelMapSQLiteProvider::DBkeyToPMTfragmentID - (unsigned int DBkey) -{ - /* - * PMT channel mapping database stores the board number (0-23) as key. - * Fragment ID are currently in the pattern 0x20xx, with xx the board number. - */ - - // protest if this is a fragment not from the PMT; - // but make an exception for old PMT fragment IDs (legacy) - assert((DBkey & 0xFF) < 24); - - return (DBkey & 0xFF) | 0x2000; - -} // icarusDB::ICARUSChannelMapSQLiteProvider::PMTfragmentIDtoDBkey() - - -// ----------------------------------------------------------------------------- +// nothing else diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h index 03b0e0ec9..7cc940f1a 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h @@ -1,6 +1,6 @@ /** * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h - * @author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) + * @author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) * @see icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.cxx */ @@ -8,19 +8,9 @@ #define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPSQLITEPROVIDER_H // ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" -#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h" #include "icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h" -// framework libraries -#include "fhiclcpp/types/Table.h" -#include "fhiclcpp/types/Atom.h" -#include "cetlib_except/exception.h" - -// C/C++ standard libraries -#include -#include // std::unique_ptr<> - // ----------------------------------------------------------------------------- namespace icarusDB { class ICARUSChannelMapSQLiteProvider; } @@ -30,215 +20,25 @@ namespace icarusDB { class ICARUSChannelMapSQLiteProvider; } * The database is normally distributed as a file in `icarus_data`. * * + * The implementation is fully delegated to + * `icarusDB::ICARUSChannelMapProviderBase`. + * + * * Configuration parameters * ========================= * + * See `icarusDB::ICARUSChannelMapProviderBase`, except for: + * * * `ChannelMappingTool` (algorithm configuration): see * `icarusDB::ChannelMapSQLite` configuration. - * * `DiagnosticOutput` (flag, default: `false`): verbosely load parameters - * and in general prints more messages to console - * * `LogCategory` (string, default: `"ICARUSChannelMapSQLiteProvider"`): - * name of the messagefacility category used to send messages to console, - * useful for filtering messages. * */ -class icarusDB::ICARUSChannelMapSQLiteProvider: public IICARUSChannelMap { - - public: - /// The helper used to extract data from the database. - using ChannelMappingAlg_t = icarusDB::ChannelMapSQLite; - - struct Config { - using Name = fhicl::Name; - using Comment = fhicl::Comment; - - fhicl::Table ChannelMappingTool { - Name{ "ChannelMappingTool" }, - Comment{ "parameters for the channel mapping algorithm" } - }; - - fhicl::Atom DiagnosticOutput{ - Name{ "DiagnosticOutput" }, - Comment{ "enables verbose output to console" }, - false // default - }; - - fhicl::Atom LogCategory{ - Name{ "LogCategory" }, - Comment{ "name of the console stream to send messages to" }, - "ICARUSChannelMapSQLiteProvider" // default - }; - - }; // Config - - using Parameters = fhicl::Table; - - - /// Constructor: configures the service provider via FHiCL configuration. - ICARUSChannelMapSQLiteProvider(Config const& config); - - /// Constructor: configures the service provider via FHiCL configuration. - ICARUSChannelMapSQLiteProvider(Parameters const& params) - : ICARUSChannelMapSQLiteProvider{ params() } - {} - - - /// --- BEGIN --- Data period selection ------------------------------------ - /// @name Data period selection - /// @{ - - /// Loads the mapping for `run`, returns whether a new mapping was loaded. - virtual bool forRun(int run) override; - - /// Loads the mapping for `period`, returns whether a new mapping was loaded. - virtual bool forPeriod(icarusDB::RunPeriod period) override; - - /// @} - /// --- END ----- Data period selection ------------------------------------ - - - /// --- BEGIN --- TPC information ------------------------------------------ - /// @name TPC information - /// @{ - - /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - - /// @name TPC fragment information - /// @{ - - /// Returns whether the specified `ID` is a known TPC fragment ID. - virtual bool hasFragmentID(const unsigned int ID) const override; - /// Returns the number of TPC fragment IDs known to the service. - - /// Returns the number of known TPC fragments. - virtual unsigned int nTPCfragmentIDs() const override; - - /// Returns the name of the crate served by the specified `fragmentID`. - virtual std::string const& getCrateName - (const unsigned int fragmentID) const override; - - /// Returns the list of board IDs included in the specified `fragmentID`. - virtual ReadoutIDVec const& getReadoutBoardVec - (const unsigned int fragmentID) const override; - - /// @} - /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - - - /** - * @brief Returns the full TPC channel mapping. - * - * The returned mapping is an associative container, associating each board - * ID (`boardID`) to the following information (in a `std::tuple`): - * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) - * * `[1]` list of channels served by the board, and their plane - * (like `getChannelPlanePair(boardID)`) - * - */ - virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const - override; - - /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - - /// @name TPC board information - /// @{ - - /// Returns whether there is a board with the specified `ID`. - virtual bool hasBoardID(const unsigned int ID) const override; - /// Returns the number of TPC board IDs known to the service. - virtual unsigned int nTPCboardIDs() const override; - /// Returns the number of slot the `boardID` is on. - virtual unsigned int getBoardSlot(const unsigned int boardID) const override; - /// Returns a list of channels served by the `boardID` and for each the plane - /// it is on (`0` to `2`). - virtual ChannelPlanePairVec const& getChannelPlanePair - (const unsigned int boardID) const override; - - /// @} - /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - - - - /// --- BEGIN --- PMT information ------------------------------------------ - /// @name PMT information - /// @{ - - /// Returns whether the specified fragment `ID` is known to the mapping. - virtual bool hasPMTDigitizerID(const unsigned int ID) const override; - - /// Returns the number of PMT fragment IDs known to the mapping. - virtual unsigned int nPMTfragmentIDs() const override; - - /// Returns a list of triplets: - virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec - (const unsigned int) const override; - - /// @} - /// --- END ----- PMT information ------------------------------------------ - - - /// --- BEGIN --- CRT information ------------------------------------------ - /// @name CRT information - /// @{ - - /// Returns the sim Mac address corresponding to the specified side CRT hardware address. - virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const override; - /// Returns the sim Mac address corresponding to the specified top CRT hardware address. - virtual unsigned int gettopSimMacAddress(const unsigned int) const override; - - /// Returns the Gain and Pedestal for Side CRT. - virtual std::pair getSideCRTCalibrationMap - (int mac5, int chan) const override; - - /// @} - /// --- END ----- CRT information ------------------------------------------ - - /// Returns the channel mapping database key for the specified PMT fragment ID. - static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); - - /// Returns the PMT fragment ID for the specified channel mapping database key. - static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); - - - private: - - // --- BEGIN --- Configuration parameters ------------------------------------ - - bool const fDiagnosticOutput; - - std::string const fLogCategory; - - // --- END ----- Configuration parameters ------------------------------------ - - - // --- BEGIN --- Cache ------------------------------------------------------- - IChannelMapping::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; - - IChannelMapping::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; - - IChannelMapping::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; - - IChannelMapping::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; - - IChannelMapping::TopCRTHWtoSimMacAddressPairMap fTopCRTHWtoSimMacAddressPairMap; - - IChannelMapping::SideCRTChannelToCalibrationMap fSideCRTChannelToCalibrationMap; - - // --- END ----- Cache ------------------------------------------------------- - - /// The helper extracting information from the database. - std::unique_ptr fChannelMappingAlg; - - - /// Has the channel mapping tool fill the mapping caches. - virtual void readFromDatabase(); - - - /// Returns the list of board channel-to-PMT channel ID mapping within the - /// specified fragment. - /// - /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment - DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry - (unsigned int fragmentID) const; - - -}; // icarusDB::ICARUSChannelMapSQLiteProvider +class icarusDB::ICARUSChannelMapSQLiteProvider + : public icarusDB::ICARUSChannelMapProviderBase +{ + using Base_t = ICARUSChannelMapProviderBase; + using Base_t::Base_t; +}; // ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc index fb670900a..d1d420c7e 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc @@ -1,11 +1,12 @@ /** - * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc - * @brief Wrapper service for `icarusDB::ICARUSChannelMapProvider`. + * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLite_service.cc + * @brief Wrapper service for `icarusDB::ICARUSChannelMapSQLiteProvider`. * @author Gianluca Petrillo (petrillo@slac.stanford.edu) */ // ICARUS libraries #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // framework libraries @@ -15,13 +16,45 @@ #include "art/Framework/Services/Registry/ServiceTable.h" #include "art/Framework/Principal/Run.h" #include "messagefacility/MessageLogger/MessageLogger.h" -#include "fhiclcpp/ParameterSet.h" -#include "cetlib_except/exception.h" // ----------------------------------------------------------------------------- namespace icarusDB { class ICARUSChannelMapSQLite; } -class icarusDB::ICARUSChannelMapSQLite: public ICARUSChannelMapSQLiteProvider { +/** + * @brief LArSoft service for ICARUS channel mapping (SQLite database backend). + * + * This service provides access to ICARUS channel mapping database, using the + * SQLite database. ICARUS channel mapping SQLite database is distributed + * as a file in `icarus_data` package. + * + * This service implements the generic channel mapping access service provider + * interface `icarusDB::IICARUSChannelMapProvider`. + * To use the channel mapping, include in your code the header of the service + * interface `icarusDB::IICARUSChannelMap`, and access the service provider via: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *lar::providerFrom(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * or similar (`lar::providerFrom()` is in `larcore/CoreUtils/ServiceUtils.h`) + * or directly the service via + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *art::ServiceHandle(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * For details on the interface, see `icarusDB::IICARUSChannelMapProvider`. + * For details on the implementation, see + * `icarusDB::ICARUSChannelMapPostGresProvider`. + * + * @note For production and processes that need robustness, using the SQLite + * database and backend (`icarusDB::ICARUSChannelMapSQLite`) is suggested + * instead. That database is local to the process and not subject to + * network interruptions. + * + */ +class icarusDB::ICARUSChannelMapSQLite + : public IICARUSChannelMap, public ICARUSChannelMapSQLiteProvider +{ /// Prepares the mapping for the specified run. void preBeginRun(art::Run const& run); diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc index 6bed48770..8093d8205 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc @@ -19,6 +19,37 @@ // ----------------------------------------------------------------------------- namespace icarusDB { class ICARUSChannelMap; } +/** + * @brief LArSoft service for ICARUS channel mapping (legacy implementation). + * + * This service provides access to ICARUS channel mapping database, using a + * backend in a _art_ tool chosen by the configuration. + * + * This service implements the generic channel mapping access service provider + * interface `icarusDB::IICARUSChannelMapProvider`. + * To use the channel mapping, include in your code the header of the service + * interface `icarusDB::IICARUSChannelMap`, and access the service provider via: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *lar::providerFrom(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * or similar (`lar::providerFrom()` is in `larcore/CoreUtils/ServiceUtils.h`) + * or directly the service via + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *art::ServiceHandle(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * For details on the interface, see `icarusDB::IICARUSChannelMapProvider`. + * For details on the implementation, see + * `icarusDB::ICARUSChannelMapProvider`. + * + * @note For production and processes that need robustness, using the SQLite + * database and backend (`icarusDB::ICARUSChannelMapSQLite`) is suggested + * instead. That database is local to the process and not subject to + * network interruptions. + * + */ class icarusDB::ICARUSChannelMap: public ICARUSChannelMapProvider { /// Prepares the mapping for the specified run. diff --git a/icaruscode/Decode/ChannelMapping/IChannelMapping.h b/icaruscode/Decode/ChannelMapping/IChannelMapping.h old mode 100755 new mode 100644 index 65532fd84..4fa794569 --- a/icaruscode/Decode/ChannelMapping/IChannelMapping.h +++ b/icaruscode/Decode/ChannelMapping/IChannelMapping.h @@ -1,17 +1,15 @@ /** - * @file IChannelMapping.h - * - * @brief This provides an art tool interface definition for tools handle the channel mapping - * The idea is to be able to switch between postgres and sqlite implementations - * - * @author usher@slac.stanford.edu - * + * @file icaruscode/Decode/ChannelMapping/IChannelMapping.h + * @brief Interface definition for helpers handling the channel mapping. + * @author T. Usher (usher@slac.stanford.edu) */ -#ifndef IChannelMapping_h -#define IChannelMapping_h + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICHANNELMAPPING_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_ICHANNELMAPPING_H // ICARUS libraries -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // icarusDB::RunPeriod +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h" // LArSoft libraries #include "larcorealg/CoreUtils/enumerate.h" @@ -19,124 +17,120 @@ // C/C++ standard libraries #include // std::transform() #include -#include -#include #include -#include #include // std::tolower() -//------------------------------------------------------------------------------------------------------------------------------------------ - -namespace icarusDB -{ +// ----------------------------------------------------------------------------- +namespace icarusDB { class IChannelMapping; } +/** + * @brief Interface for helper classes extracting channel mapping from database. + * + * This is currently used by both SQLite and PostgreSQL database backends, + * and the service provider implementations take advantage of the similar + * interface. + */ +class icarusDB::IChannelMapping { + public: /** - * @brief IChannelMapping interface class definiton + * @brief Virtual Destructor */ - class IChannelMapping - { - public: - /** - * @brief Virtual Destructor - */ - virtual ~IChannelMapping() noexcept = default; - - /** - * @brief Prepares the tool to serve information about the specified run period. - * @param period the run period to be served - * @return whether the served values are going to be different than before - * - * If this method returns `false`, the values from the previous call to it - * are still current. - * - * Run periods are defined in `icarusDB::RunPeriods`. - */ - virtual bool SelectPeriod(icarusDB::RunPeriod period) = 0; - - /** - * @brief Define the returned data structures for a mapping between TPC Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - using ReadoutIDVec = std::vector; - using CrateNameReadoutIDPair = std::pair; - using TPCFragmentIDToReadoutIDMap = std::map; - - virtual int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap&) const = 0; - - /** - * @brief Define the returned data structures for a mapping between TPC readout boards - * and the channel information - * Then define the function interface to fill these data structures - */ - using ChannelPlanePair = std::pair; - using ChannelPlanePairVec = std::vector; - using SlotChannelVecPair = std::pair; - using TPCReadoutBoardToChannelMap = std::map; - - virtual int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap&) const = 0; - - /** - * @brief Define the returned data structures for a mapping between PMT Fragment IDs - * and the related crate and readout information. - * Then define the function interface to fill these data structures - */ - using DigitizerChannelChannelIDPair = std::tuple; // std::tuple - using DigitizerChannelChannelIDPairVec = std::vector; - using FragmentToDigitizerChannelMap = std::map; - - virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const = 0; - - /** - * @brief Define the returned data structures for a mapping between CRT hardware mac_address - * to the simulated mac_address. - * Then define the function interface to fill these data structures - */ - - using CRTHWtoSimMacAddressPair = std::pair; - using CRTChannelIDToHWtoSimMacAddressPairMap = std::map; - - virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap(CRTChannelIDToHWtoSimMacAddressPairMap&) const = 0; - - - using TopCRTHWtoSimMacAddressPairMap = std::map; - - virtual int BuildTopCRTHWtoSimMacAddressPairMap(TopCRTHWtoSimMacAddressPairMap&) const = 0; - - - using SideCRTMac5ToChannelPair = std::pair; - using SideCRTGainToPedPair = std::pair; - using SideCRTChannelToCalibrationMap = std::map< SideCRTMac5ToChannelPair, SideCRTGainToPedPair >; + virtual ~IChannelMapping() noexcept = default; + + /** + * @brief Prepares the tool to serve information about the specified run period. + * @param period the run period to be served + * @return whether the served values are going to be different than before + * + * If this method returns `false`, the values from the previous call to it + * are still current. + * + * Run periods are defined in `icarusDB::RunPeriods`. + */ + virtual bool SelectPeriod(icarusDB::RunPeriod period) = 0; + + + // --- BEGIN --- TPC mapping ------------------------------------------------- + /// @name TPC mapping. + /// @{ + + /// Fill mapping between TPC Fragment IDs and the related crate and readout + /// information. + + virtual int BuildTPCFragmentIDToReadoutIDMap + (TPCFragmentIDToReadoutIDMap&) const = 0; + + /// Fill mapping between TPC readout boards and the channel information. + virtual int BuildTPCReadoutBoardToChannelMap + (TPCReadoutBoardToChannelMap&) const = 0; + + /// @} + // --- END ----- TPC mapping ------------------------------------------------- + + + // --- BEGIN --- PMT mapping ------------------------------------------------- + /// @name PMT mapping. + /// @{ + + /// Fill the mapping between PMT Fragment IDs and the related crate and + /// readout information. + virtual int BuildFragmentToDigitizerChannelMap + (FragmentToDigitizerChannelMap&) const = 0; + + /// @} + // --- END ----- PMT mapping ------------------------------------------------- + + + // --- BEGIN --- CRT mapping ------------------------------------------------- + /// @name CRT mapping. + /// @{ + + /// Fill mapping between side CRT hardware mac_address and the simulated + /// mac_address. + virtual int BuildCRTChannelIDToHWtoSimMacAddressPairMap + (CRTChannelIDToHWtoSimMacAddressPairMap&) const = 0; + + /// Fill mapping between top CRT channel ID and the simulated mac_address. + virtual int BuildTopCRTHWtoSimMacAddressPairMap + (TopCRTHWtoSimMacAddressPairMap&) const = 0; + + /// Fill CRT calibration information. + virtual int BuildSideCRTCalibrationMap + (SideCRTChannelToCalibrationMap&) const = 0; + + /// @} + // --- END ----- CRT mapping ------------------------------------------------- + + + // --- BEGIN --- Utility functions for the implementation -------------------- + + static constexpr unsigned int ChannelsPerTPCreadoutBoard = 64; + + /// Turns and returns a string into lowercase. + template + static void makeLowerCase(String& s) { + using std::cbegin, std::cend, std::begin, std::end; + std::transform(cbegin(s), cend(s), begin(s), + [](unsigned char c){ return std::tolower(c); }); + } + + /// Returns the plane identified by `planeStr`: `0` to `2`; `3` if invalid. + static unsigned int TPCplaneIdentifierToPlane(std::string planeStr) + { + using namespace std::string_literals; + makeLowerCase(planeStr); // Make sure lower case... (sigh...) + static std::array const PlaneNames + = { "induction 1"s, "induction 2"s, "collection"s }; + for (auto const& [ plane, planeName ]: util::enumerate(PlaneNames)) + if (planeStr.find(planeName) != std::string::npos) return plane; + return PlaneNames.size(); + } + + // --- END ----- Utility functions for the implementation -------------------- + +}; // icarusDB::IChannelMapping - virtual int BuildSideCRTCalibrationMap(SideCRTChannelToCalibrationMap&) const = 0; - // --- BEGIN --- Utility functions for the implementation ------------------ - - static constexpr unsigned int ChannelsPerTPCreadoutBoard = 64; - - /// Turns and returns a string into lowercase. - template - static void makeLowerCase(String& s) { - using std::cbegin, std::cend, std::begin, std::end; - std::transform(cbegin(s), cend(s), begin(s), - [](unsigned char c){ return std::tolower(c); }); - } - - /// Returns the plane identified by `planeStr`: `0` to `2`; `3` if invalid. - static unsigned int TPCplaneIdentifierToPlane(std::string planeStr) - { - using namespace std::string_literals; - makeLowerCase(planeStr); // Make sure lower case... (sigh...) - static std::array const PlaneNames - = { "induction 1"s, "induction 2"s, "collection"s }; - for (auto const& [ plane, planeName ]: util::enumerate(PlaneNames)) - if (planeStr.find(planeName) != std::string::npos) return plane; - return PlaneNames.size(); - } - - // --- BEGIN --- Utility functions for the implementation ------------------ - -}; +// ----------------------------------------------------------------------------- -} // namespace lar_cluster3d -#endif +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICHANNELMAPPING_H diff --git a/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h b/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h index 378a6fd1a..4735c2098 100644 --- a/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h +++ b/icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h @@ -7,137 +7,67 @@ #ifndef ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAP_H #define ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAP_H -#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h" +// framework libraries #include "art/Framework/Services/Registry/ServiceDeclarationMacros.h" -#include -#include -#include -#include -namespace icarusDB { +namespace icarusDB { class IICARUSChannelMap; }; -using ReadoutIDVec = std::vector; -using ChannelPlanePair = std::pair; -using ChannelPlanePairVec = std::vector; - -using DigitizerChannelChannelIDPair = std::tuple; -using DigitizerChannelChannelIDPairVec = std::vector; - -using ChannelPlanePair = std::pair; -using ChannelPlanePairVec = std::vector; -using SlotChannelVecPair = std::pair; -using TPCReadoutBoardToChannelMap = std::map; - -class IICARUSChannelMap //: private lar::EnsureOnlyOneSchedule +/** + * @brief Interface for ICARUS channel mapping service. + * @see icarusDB::IICARUSChannelMapProvider + * + * This class represents the interface of the _art_ service to access ICARUS + * channel mapping. The exposed interface is the same as the service provider + * interface, `icarusDB::IICARUSChannelMapProvider`. + * + * The only reason for the existence of this object is the overhead to make any + * class a framework service. + * + * To use the channel mapping, include in your code the header of this service + * interface and access the service provider via: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *lar::providerFrom(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * or similar (`lar::providerFrom()` is in `larcore/CoreUtils/ServiceUtils.h`) + * or directly the service via + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * icarusDB::IICARUSChannelMapProvider const& channelMapping + * = *art::ServiceHandle(); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * The FHiCL configuration will route the service interface to the correct + * implementation. + * + * For details on the interface, see `icarusDB::IICARUSChannelMapProvider`. + * For details on the implementation, see the chosen service implementation. + * + * For use in environments other than _art_, use directly the service provider + * implementation of your choice (any implementation of + * `icarusDB::IICARUSChannelMapProvider`, for example + * `icarusDB::IICARUSChannelMapProviderSQLite`). + * + * + * Implementation details + * ----------------------- + * + * This interface directly exposes the interface of the service provider, + * deriving from it. It is foreseen that the implementations of this service + * derive directly from their framework-independent service provider, + * and therefore they expose the provider interface already. For this reason + * both the service provider and the service interface need to have virtual + * inheritance from the service provider interface, to make sure that there is + * only one underlying interface object. + * + */ +class icarusDB::IICARUSChannelMap + : virtual public icarusDB::IICARUSChannelMapProvider { -public: - virtual ~IICARUSChannelMap() noexcept = default; - - - /// --- BEGIN --- Data period selection ------------------------------------ - /// @name Data period selection - /// @{ - - /// Loads the mapping for `run`, returns whether a new mapping was loaded. - virtual bool forRun(int run) = 0; - - /// Loads the mapping for `period`, returns whether a new mapping was loaded. - virtual bool forPeriod(icarusDB::RunPeriod period) = 0; - - /// @} - /// --- END ----- Data period selection ------------------------------------ - - - /// --- BEGIN --- TPC information ------------------------------------------ - /// @name TPC information - /// @{ - - /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - - /// @name TPC fragment information - /// @{ - - /// Returns whether the specified `ID` is a known TPC fragment ID. - virtual bool hasFragmentID(const unsigned int ID) const = 0; - /// Returns the number of TPC fragment IDs known to the service. - - /// Returns the number of known TPC fragments. - virtual unsigned int nTPCfragmentIDs() const = 0; - - /// Returns the name of the crate served by the specified `fragmentID`. - virtual const std::string& getCrateName(const unsigned int fragmentID) const = 0; - - /// Returns the list of board IDs included in the specified `fragmentID`. - virtual const ReadoutIDVec& getReadoutBoardVec(const unsigned int fragmentID) const = 0; - - /// @} - /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - - - /** - * @brief Returns the full TPC channel mapping. - * - * The returned mapping is an associative container, associating each board - * ID (`boardID`) to the following information (in a `std::tuple`): - * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) - * * `[1]` list of channels served by the board, and their plane - * (like `getChannelPlanePair(boardID)`) - * - */ - virtual const TPCReadoutBoardToChannelMap& getReadoutBoardToChannelMap() const = 0; - - /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - - /// @name TPC board information - /// @{ - - /// Returns whether there is a board with the specified `ID`. - virtual bool hasBoardID(const unsigned int ID) const = 0; - /// Returns the number of TPC board IDs known to the service. - virtual unsigned int nTPCboardIDs() const = 0; - /// Returns the number of slot the `boardID` is on. - virtual unsigned int getBoardSlot(const unsigned int boardID) const = 0; - /// Returns a list of channels served by the `boardID` and for each the plane it is on (`0` to `2`). - virtual const ChannelPlanePairVec& getChannelPlanePair(const unsigned int boardID) const = 0; - - /// @} - /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - - - - /// --- BEGIN --- PMT information ------------------------------------------ - /// @name PMT information - /// @{ - - /// Returns whether the specified fragment `ID` is known to the mapping. - virtual bool hasPMTDigitizerID(const unsigned int ID) const = 0; - - /// Returns the number of PMT fragment IDs known to the mapping. - virtual unsigned int nPMTfragmentIDs() const = 0; - - /// Returns a list of triplets: - virtual const DigitizerChannelChannelIDPairVec& getChannelIDPairVec(const unsigned int) const = 0; - - /// @} - /// --- END ----- PMT information ------------------------------------------ - - - /// --- BEGIN --- CRT information ------------------------------------------ - /// @name CRT information - /// @{ - - /// Returns the sim Mac address corresponding to the specified side CRT hardware address. - virtual unsigned int getSimMacAddress(const unsigned int hwmacaddress) const = 0; - /// Returns the sim Mac address corresponding to the specified top CRT hardware address. - virtual unsigned int gettopSimMacAddress(const unsigned int) const = 0; - - /// Returns the Gain and Pedestal for Side CRT. - virtual std::pair getSideCRTCalibrationMap(int mac5, int chan) const = 0; - - /// @} - /// --- END ----- CRT information ------------------------------------------ - -}; // IICARUSChannelMap +}; -} // namespace icarusDB DECLARE_ART_SERVICE_INTERFACE(icarusDB::IICARUSChannelMap, SHARED) diff --git a/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h b/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h new file mode 100644 index 000000000..4319fc65d --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h @@ -0,0 +1,168 @@ +/** + * @file icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h + * @brief Interface class for hardware/software channel mapping for ICARUS. + * @author T. Usher + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAPPROVIDER_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAPPROVIDER_H + +// ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/RunPeriods.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h" + +// C/C++ standard libraries +#include +#include +#include +#include +#include // std::size_t + + +// ----------------------------------------------------------------------------- + +namespace icarusDB { class IICARUSChannelMapProvider; } +/** + * @brief Interface of ICARUS channel mapping service provider. + * + * The service providers implementing this interface provide access to ICARUS + * channel mapping. + * + * The mapping organization reflects what was needed at the time of inception. + * + * The service provider is expected to have status and to be compatible with + * multithreading only within the same run period. In fact, a current run + * (`forRun()`) or run period (`forPeriod()`) must be selected and all the + * provided information will pertain the selected run period. + * + * Also, given that the interface yields complex structures by reference, it is + * expected that implementations cache results in their final form and provide + * direct access to that cache. + * + * + */ +class icarusDB::IICARUSChannelMapProvider { + + public: + + virtual ~IICARUSChannelMapProvider() noexcept = default; + + + /// --- BEGIN --- Data period selection -------------------------------------- + /// @name Data period selection + /// @{ + + /// Loads the mapping for `run`, returns whether a new mapping was loaded. + virtual bool forRun(int run) = 0; + + /// Loads the mapping for `period`, returns whether a new mapping was loaded. + virtual bool forPeriod(icarusDB::RunPeriod period) = 0; + + /// @} + /// --- END ----- Data period selection -------------------------------------- + + + /// --- BEGIN --- TPC information -------------------------------------------- + /// @name TPC information + /// @{ + + /// --- BEGIN - - TPC fragment information - - - - - - - - - - - - - - - - - - + /// @name TPC fragment information + /// @{ + + /// Returns whether the specified `ID` is a known TPC fragment ID. + virtual bool hasFragmentID(unsigned int ID) const = 0; + + /// Returns the number of TPC fragment IDs known to the service. + virtual unsigned int nTPCfragmentIDs() const = 0; + + /// Returns the name of the crate served by the specified `fragmentID`. + virtual std::string const& getCrateName(unsigned int fragmentID) const = 0; + + /// Returns the list of board IDs included in the specified `fragmentID`. + virtual ReadoutIDVec const& getReadoutBoardVec(unsigned int fragmentID) const + = 0; + + /// @} + /// --- END - - - TPC fragment information - - - - - - - - - - - - - - - - - - + + /** + * @brief Returns the full TPC channel mapping. + * + * The returned mapping is an associative container, associating each board + * ID (`boardID`) to the following information (in a `std::tuple`): + * * `[0]` slot number the board is on (like `getBoardSlot(boardID)`) + * * `[1]` list of channels served by the board, and their plane + * (like `getChannelPlanePair(boardID)`) + * + */ + virtual TPCReadoutBoardToChannelMap const& getReadoutBoardToChannelMap() const + = 0; + + /// --- BEGIN - - TPC board information - - - - - - - - - - - - - - - - - - - + /// @name TPC board information + /// @{ + + /// Returns whether there is a board with the specified `ID`. + virtual bool hasBoardID(unsigned int ID) const = 0; + + /// Returns the number of TPC board IDs known to the service. + virtual unsigned int nTPCboardIDs() const = 0; + + /// Returns the number of slot the `boardID` is on. + virtual unsigned int getBoardSlot(unsigned int boardID) const = 0; + + /// Returns a list of channels served by the `boardID` and for each the plane + /// it is on (`0` to `2`). + virtual ChannelPlanePairVec const& getChannelPlanePair + (unsigned int boardID) const = 0; + + /// @} + /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - - + + + /// --- BEGIN --- PMT information -------------------------------------------- + /// @name PMT information + /// @{ + + /// Returns whether the specified fragment `ID` is known to the mapping. + virtual bool hasPMTDigitizerID(unsigned int ID) const = 0; + + /// Returns the number of PMT fragment IDs known to the mapping. + virtual unsigned int nPMTfragmentIDs() const = 0; + + /// Returns a list of triplets: digitizer channel number, channel ID and + /// laser channel. + virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec + (unsigned int) const = 0; + + /// @} + /// --- END ----- PMT information -------------------------------------------- + + + /// --- BEGIN --- CRT information -------------------------------------------- + /// @name CRT information + /// @{ + + /// Returns the Sim Mac address corresponding to the specified side CRT + /// hardware address. + virtual unsigned int getSimMacAddress(unsigned int hwmacaddress) const + = 0; + + /// Returns the sim Mac address corresponding to the specified top CRT + /// hardware address. + virtual unsigned int gettopSimMacAddress(unsigned int) const = 0; + + /// Returns the gain and pedestal for Side CRT. + virtual std::pair getSideCRTCalibrationMap + (int mac5, int chan) const = 0; + + /// @} + /// --- END ----- CRT information -------------------------------------------- + +}; // icarusDB::IICARUSChannelMapProvider + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_IICARUSCHANNELMAPPROVIDER_H diff --git a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx index 944c6ddd4..1f3752e2e 100644 --- a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx @@ -4,7 +4,7 @@ * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * * This utility can be run with any configuration file including a configuration - * for `IICARUSChannelMap` service. + * for `IICARUSChannelMap` service featuring SQLite backend. * * It is using _art_ facilities for tool loading, but it does not run in _art_ * environment. So it may break without warning and without solution. @@ -14,7 +14,9 @@ // ICARUS libraries #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" -#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // LArSoft and framework libraries @@ -27,6 +29,7 @@ #include // std::setw() #include #include +#include #include // std::iota() #include @@ -72,7 +75,7 @@ class Pager { // ----------------------------------------------------------------------------- -void dumpTPCmapping(icarusDB::IICARUSChannelMap const& mapping) { +void dumpTPCmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { constexpr unsigned int FragmentIDoffset = 0x1000; @@ -150,7 +153,7 @@ void dumpTPCmapping(icarusDB::IICARUSChannelMap const& mapping) { // ----------------------------------------------------------------------------- -void dumpPMTmapping(icarusDB::IICARUSChannelMap const& mapping) { +void dumpPMTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { mf::LogVerbatim log("PMTchannelMappingDumper"); unsigned int nFragmentIDs = mapping.nPMTfragmentIDs(); @@ -158,7 +161,7 @@ void dumpPMTmapping(icarusDB::IICARUSChannelMap const& mapping) { // hard-coded list of fragment ID; don't like it? // ask for an extension of the channel mapping features. - std::array FragmentIDs; + std::vector FragmentIDs(nFragmentIDs); std::iota(FragmentIDs.begin(), FragmentIDs.end(), 0x2000); log << "\nPMT fragment IDs:"; @@ -198,7 +201,7 @@ void dumpPMTmapping(icarusDB::IICARUSChannelMap const& mapping) { // ----------------------------------------------------------------------------- -void dumpCRTmapping(icarusDB::IICARUSChannelMap const& mapping) { +void dumpCRTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { mf::LogVerbatim log("PMTchannelMappingDumper"); @@ -224,7 +227,7 @@ void dumpCRTmapping(icarusDB::IICARUSChannelMap const& mapping) { // ----------------------------------------------------------------------------- -void dumpMapping(icarusDB::IICARUSChannelMap const& channelMapping) { +void dumpMapping(icarusDB::IICARUSChannelMapProvider const& channelMapping) { mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); dumpTPCmapping(channelMapping); @@ -260,19 +263,54 @@ int main(int argc, char** argv) { << std::endl; return 1; } - + Environment const Env { config }; - icarusDB::ICARUSChannelMapSQLiteProvider channelMapping - { Env.ServiceParameters("IICARUSChannelMap") }; + // + // create the service provider object + // + // limited selection of available service providers, hard-coded + // + std::unique_ptr channelMapping; + fhicl::ParameterSet channelMapConfig + = Env.ServiceParameters("IICARUSChannelMap"); + std::string const serviceType = channelMapConfig.get + ("service_provider", "ICARUSChannelMapSQLite"); + channelMapConfig.erase("service_provider"); // if not present, still friends + mf::LogVerbatim("PMTChannelMapDumper") + << "Initializing a provider of type '" << serviceType << "'"; + mf::LogTrace("PMTChannelMapDumper") + << "with configuration:\n{" << channelMapConfig.to_indented_string(1) + << "\n}"; + if (serviceType == "ICARUSChannelMapSQLite") { + channelMapping = std::make_unique + (channelMapConfig); + } + else if (serviceType == "ICARUSChannelMapPostGres") { + channelMapping + = std::make_unique + (channelMapConfig); + } + else if (serviceType == "ICARUSChannelMap") { // legacy + channelMapping = std::make_unique + (channelMapConfig); + } + else { + mf::LogError("PMTChannelMapDumper") + << "Fatal: don't know what to do with IICARUSChannelMap.service_type: '" + << serviceType << "'."; + return 1; + } - for (icarusDB::RunPeriod const period: icarusDB::RunPeriods::All) - { - mf::LogVerbatim("PMTchannelMappingDumper") + // + // dump + // + for (icarusDB::RunPeriod const period: icarusDB::RunPeriods::All) { + mf::LogVerbatim("PMTchannelMapDumper") << std::string(80, '=') << "\nRun period #" << static_cast(period) << ":\n"; - channelMapping.forPeriod(period); - dumpMapping(channelMapping); + channelMapping->forPeriod(period); + dumpMapping(*channelMapping); } mf::LogVerbatim("PMTchannelMappingDumper") diff --git a/icaruscode/Decode/ChannelMapping/PositionFinder.h b/icaruscode/Decode/ChannelMapping/PositionFinder.h new file mode 100644 index 000000000..40f39ce25 --- /dev/null +++ b/icaruscode/Decode/ChannelMapping/PositionFinder.h @@ -0,0 +1,106 @@ +/** + * @file icaruscode/Decode/ChannelMapping/PositionFinder.h + * @brief Simple utility for finding multiple keys with a single code line. + * @author Gianluca Petrillo (petrillo@slac.stanford.edu) + */ + +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_POSITIONFINDER_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_POSITIONFINDER_H + +// LArSoft libraries +#include "larcorealg/CoreUtils/enumerate.h" + +// C++ standard libraries +#include +#include // std::numeric_limits<> +#include // std::size_t + + +// ----------------------------------------------------------------------------- +namespace icarus::ns::util { template class PositionFinder; } +/** + * @brief Returns the index of strings in a set collection. + * @tparam Coll type of collection of keys being parsed + * + * Example: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + * PositionFinder const namePositions{ Names }; + * auto const [ L1, L5, L3 ] = namePositions("one", "five", "three"); + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * will set `L1`, `L5` and `L3` to `0`, `4` and `2` respectively. + * Indices of names that are not present are returned as `NotAvailable`. + */ +template +class icarus::ns::util::PositionFinder { + + Coll const& fKeys; ///< Reference to an external pool of keys. + + /// Inserts the position of `first` and `others...` starting at `*position`. + template + void fillPositions( + std::size_t* position, String const& first, OtherStrings const&... others + ) const; + + public: + + /// Special value used as "index" for targets that are not in the pool. + static constexpr std::size_t NotAvailable + = std::numeric_limits::max(); + + /// Constructor: uses `keys` as pool to find elements from. + PositionFinder(Coll const& keys): fKeys{ keys } {} + + /// Returns the position in the pool of `target` or `NotAvailable`. + template + std::size_t find(String const& target) const; + + /// Returns in an array the position of all targets specified in `selection`. + template + std::array operator() + (Strings const&... selection) const; + +}; // icarus::ns::util::PositionFinder<> + + +// ----------------------------------------------------------------------------- +// --- icarus::ns::util::PositionFinder implementation +// ----------------------------------------------------------------------------- +template +template +void icarus::ns::util::PositionFinder::fillPositions( + std::size_t* position, String const& first, OtherStrings const&... others +) const { + *position = find(first); + if constexpr(sizeof...(OtherStrings) > 0) + fillPositions(++position, others...); +} // icarus::ns::util::PositionFinder::fillPositions() + + +// ----------------------------------------------------------------------------- +template +template +std::size_t icarus::ns::util::PositionFinder::find + (String const& target) const +{ + for (auto const& [ index, key ]: ::util::enumerate(fKeys)) + if (key == target) return index; + return NotAvailable; +} // icarus::ns::util::PositionFinder::find() + + +// ----------------------------------------------------------------------------- +template +template +std::array +icarus::ns::util::PositionFinder::operator() + (Strings const&... selection) const +{ + std::array positions; + fillPositions(positions.data(), selection...); + return positions; +} // icarus::ns::util::PositionFinder::operator() + + +// ----------------------------------------------------------------------------- + +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_POSITIONFINDER_H diff --git a/icaruscode/Decode/ChannelMapping/channelmapping_icarus.fcl b/icaruscode/Decode/ChannelMapping/channelmapping_icarus.fcl index a69ab3091..215f2953e 100644 --- a/icaruscode/Decode/ChannelMapping/channelmapping_icarus.fcl +++ b/icaruscode/Decode/ChannelMapping/channelmapping_icarus.fcl @@ -2,25 +2,104 @@ BEGIN_PROLOG +################################################################################ +### Database access parameters +### +# for icarusDB::ChannelMapPostGres: ChannelMappingPostGres: { - tool_type: ChannelMapPostGres - Nothing: 0 + DatabaseURL: "https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_prd" + CRTcalibrationDatabaseURL: "https://dbdata0vm.fnal.gov:9443/icarus_con_prod/app/data?f=crt_gain_reco_data&t=1638918270" } +# for icarusDB::ChannelMapSQLite: ChannelMappingSQLite: { - tool_type: ChannelMapSQLite DBFileName: "ChannelMapICARUS_20230829.db" CalibDBFileName: "crt_gain_reco_data" Tag: @local::ICARUS_Calibration_GlobalTags.crt_gain_reco_data - } -icarus_channelmappinggservice: +################################################################################ +### art service configuration +################################################################################ +# +# Available configurations: +# * icarus_channelmappinggservice_sqlite +# * icarus_channelmappinggservice_postgres +# * icarus_channelmappinggservice_legacy +# + +### +### SQLite backend +### +# +# Use it with: +# +# services.IICARUSChannelMap: @local::icarus_channelmappinggservice_sqlite +# +# +# For direct configuration of the service providers, use this table but @erase +# the art-specific `service_provider` key. +# +icarus_channelmappinggservice_sqlite: { - service_provider: ICARUSChannelMap + service_provider: ICARUSChannelMapSQLite DiagnosticOutput: false ChannelMappingTool: @local::ChannelMappingSQLite } +### +### PostgreSQL backend +### +# +# Use it with: +# +# services.IICARUSChannelMap: @local::icarus_channelmappinggservice_postgres +# +# +# For direct configuration of the service providers, use this table but @erase +# the art-specific `service_provider` key. +# +icarus_channelmappinggservice_postgres: +{ + service_provider: ICARUSChannelMapPostGres + DiagnosticOutput: false + ChannelMappingTool: @local::ChannelMappingPostGres +} + +### +### Legacy service +### +# +# Use it, if you really have to, with: +# +# services.IICARUSChannelMap: @local::icarus_channelmappinggservice_legacy +# +# +# This service still uses the double-choice pattern, where one has to choose +# both which service and which database backend to use. +# Prefer the new services above. +# + +icarus_channelmappinggservice_legacy: +{ + service_provider: ICARUSChannelMap + DiagnosticOutput: false + ChannelMappingTool: { + @table::ChannelMappingSQLite + tool_type: ChannelMapSQLite + } +} + + +################################################################################ +### Default ICARUS configuration +### +# +# Use this configuration unless there are specific reasons not to. +# +icarus_channelmappinggservice: @local::icarus_channelmappinggservice_sqlite + +################################################################################ + END_PROLOG From ed386628242ab3dfed9425140c37662ba704fd7f Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 24 Feb 2024 00:34:06 -0600 Subject: [PATCH 07/19] Moved legacy channel mapping services and tools in their own plane --- icaruscode/CRT/CRTUtils/CRTHitRecoAlg.h | 2 - .../Decode/ChannelMapping/CMakeLists.txt | 139 ++-- .../ChannelMapping/Legacy/CMakeLists.txt | 19 + .../Legacy/ChannelMapPostGres_tool.cc | 2 +- .../Legacy/ChannelMapSQLite_tool.cc | 2 +- .../{ => Legacy}/ICARUSChannelMapProvider.cxx | 8 +- .../{ => Legacy}/ICARUSChannelMapProvider.h | 10 +- .../{ => Legacy}/ICARUSChannelMap_service.cc | 4 +- .../ChannelMapping/PMTChannelMapDumper.cxx | 8 +- .../Decode/ChannelMapping/TPCChannelmapping.h | 596 ------------------ 10 files changed, 82 insertions(+), 708 deletions(-) rename icaruscode/Decode/ChannelMapping/{ => Legacy}/ICARUSChannelMapProvider.cxx (97%) rename icaruscode/Decode/ChannelMapping/{ => Legacy}/ICARUSChannelMapProvider.h (92%) rename icaruscode/Decode/ChannelMapping/{ => Legacy}/ICARUSChannelMap_service.cc (95%) delete mode 100644 icaruscode/Decode/ChannelMapping/TPCChannelmapping.h diff --git a/icaruscode/CRT/CRTUtils/CRTHitRecoAlg.h b/icaruscode/CRT/CRTUtils/CRTHitRecoAlg.h index 349f9cd0e..651f5db0e 100644 --- a/icaruscode/CRT/CRTUtils/CRTHitRecoAlg.h +++ b/icaruscode/CRT/CRTUtils/CRTHitRecoAlg.h @@ -41,8 +41,6 @@ #include "sbnobj/Common/CRT/CRTHit.hh" #include "sbnobj/ICARUS/CRT/CRTData.hh" -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" -#include "icaruscode/Decode/ChannelMapping/IChannelMapping.h" #include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" // c++ #include diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index 0cf1b60e1..d74e619fa 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -1,105 +1,58 @@ cet_enable_asserts() art_make_library( - EXCLUDE "PMTChannelMapDumper.cxx" - LIBRARIES - art::Utilities - canvas::canvas - fhiclcpp::fhiclcpp - messagefacility::MF_MessageLogger - cetlib_except::cetlib_except - cetlib::cetlib - larcorealg::CoreUtils - - # for PostGres algorithms (includes duplicates above) - icarusalg::Utilities - larcorealg::CoreUtils - messagefacility::MF_MessageLogger - fhiclcpp::fhiclcpp - cetlib::cetlib - cetlib_except::cetlib_except - wda::wda - - # for SQLite algorithms (includes duplicates above) - icarusalg::Utilities - larevt::CalibrationDBI_Providers - larcorealg::CoreUtils - messagefacility::MF_MessageLogger - fhiclcpp::fhiclcpp - cetlib::cetlib - cetlib_except::cetlib_except - SQLite::SQLite3 - + EXCLUDE "PMTChannelMapDumper.cxx" + LIBRARIES + icarusalg::Utilities + larcorealg::CoreUtils + art::Framework_Services_Registry + fhiclcpp::fhiclcpp + messagefacility::MF_MessageLogger + cetlib::cetlib + cetlib_except::cetlib_except + + # for PostgreSQL algorithm and service provider (includes duplicates above) + icarusalg::Utilities + larcorealg::CoreUtils + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib_except::cetlib_except + wda::wda + + # for SQLite algorithm and service provider (includes duplicates above) + icarusalg::Utilities + larevt::CalibrationDBI_Providers + larcorealg::CoreUtils + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib::cetlib + cetlib_except::cetlib_except + SQLite::SQLite3 + ) -set( SERVICE_LIBRARIES - icaruscode::Decode_ChannelMapping - lardata::Utilities - lardata::ArtDataHelper - larcorealg::CoreUtils - wda::wda - art::Framework_Core - art::Framework_Principal - art::Framework_Services_Registry - art_root_io::tfile_support - art_root_io::TFileService_service - art::Utilities - art::Persistency_Common - art::Persistency_Provenance - art::Utilities canvas::canvas - messagefacility::MF_MessageLogger - messagefacility::headers - fhiclcpp::fhiclcpp - cetlib::cetlib cetlib_except::cetlib_except - larevt::CalibrationDBI_IOVData - larevt::CalibrationDBI_Providers -) -set( TOOL_LIBRARIES - larcorealg::CoreUtils - lardata::Utilities - lardata::ArtDataHelper - wda::wda - art::Framework_Core - art::Framework_Principal - art::Framework_Services_Registry - art_root_io::tfile_support - art_root_io::TFileService_service - art::Utilities - art::Persistency_Common canvas::canvas - art::Persistency_Provenance - art::Utilities - messagefacility::MF_MessageLogger - messagefacility::headers - fhiclcpp::fhiclcpp - cetlib::cetlib cetlib_except::cetlib_except - SQLite::SQLite3 - larevt::CalibrationDBI_IOVData - larevt::CalibrationDBI_Providers - ) - -cet_build_plugin(ICARUSChannelMap art::service LIBRARIES ${SERVICE_LIBRARIES}) - cet_build_plugin(ICARUSChannelMapSQLite art::service - LIBRARIES - icaruscode::Decode_ChannelMapping - art::Framework_Principal - messagefacility::MF_MessageLogger - messagefacility::headers - ) + LIBRARIES + icaruscode::Decode_ChannelMapping + art::Framework_Principal + messagefacility::MF_MessageLogger + messagefacility::headers + ) + +add_subdirectory("Legacy") cet_make_exec(NAME "PMTChannelMapDumper" - LIBRARIES - icaruscode::Decode_ChannelMapping - larevt::CalibrationDBI_IOVData - messagefacility::MF_MessageLogger - fhiclcpp::fhiclcpp - cetlib::cetlib - cetlib_except::cetlib_except - Boost::filesystem - ) + LIBRARIES + icaruscode::Decode_ChannelMapping_Legacy + icaruscode::Decode_ChannelMapping + larevt::CalibrationDBI_IOVData + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib::cetlib + cetlib_except::cetlib_except + Boost::filesystem + ) install_headers() install_fhicl() install_source() - -add_subdirectory("Legacy") diff --git a/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt index 536ee3f23..db2b982fc 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/Legacy/CMakeLists.txt @@ -1,5 +1,15 @@ cet_enable_asserts() +art_make_library( + LIBRARIES + icaruscode::Decode_ChannelMapping + art::Utilities + messagefacility::MF_MessageLogger + fhiclcpp::fhiclcpp + cetlib::cetlib + cetlib_except::cetlib_except +) + cet_build_plugin(ChannelMapSQLite art::tool LIBRARIES icaruscode::Decode_ChannelMapping @@ -10,6 +20,15 @@ cet_build_plugin(ChannelMapPostGres art::tool icaruscode::Decode_ChannelMapping ) +cet_build_plugin(ICARUSChannelMap art::service + LIBRARIES + icaruscode::Decode_ChannelMapping_Legacy + icaruscode::Decode_ChannelMapping + art::Framework_Principal + messagefacility::MF_MessageLogger + messagefacility::headers + ) + install_headers() install_fhicl() install_source() diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc index e184e87bd..430431b22 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc +++ b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc @@ -1,5 +1,5 @@ /** - * @file icaruscode/Decode/ChannelMapping/ChannelMapPostGres_tool.cc + * @file icaruscode/Decode/ChannelMapping/Legacy/ChannelMapPostGres_tool.cc * @brief _art_ tool wrapping ICARUS channel mapping PostGres database helper. * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * @see icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc index aa76fde99..f67bec031 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc +++ b/icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc @@ -1,5 +1,5 @@ /** - * @file icaruscode/Decode/ChannelMapping/ChannelMapSQLite_tool.cc + * @file icaruscode/Decode/ChannelMapping/Legacy/ChannelMapSQLite_tool.cc * @brief _art_ tool wrapping ICARUS channel mapping SQLite database helper. * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * @see icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx similarity index 97% rename from icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx rename to icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx index 2d0a672ef..cf0c0bf78 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx @@ -1,11 +1,11 @@ //////////////////////////////////////////////////////////////////////// -/// \file icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx -/// \author T. Usher (factorized by Gianluca Petrillo, petrillo@slac.stanford.edu) -/// \see icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h +/// \file icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx +/// \author T. Usher (factorized by G. Petrillo, petrillo@slac.stanford.edu) +/// \see icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h //////////////////////////////////////////////////////////////////////// // library header -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" +#include "icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h similarity index 92% rename from icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h rename to icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h index 63e2c82c0..f5bec2b57 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h @@ -1,11 +1,11 @@ //////////////////////////////////////////////////////////////////////// -/// \file icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h -/// \author T. Usher (factorised by Gianluca Petrillo, petrillo@slac.stanford.edu) +/// \file icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h +/// \author T. Usher (factorised by G. Petrillo, petrillo@slac.stanford.edu) /// \see icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.cxx //////////////////////////////////////////////////////////////////////// -#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDER_H -#define ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDER_H +#ifndef ICARUSCODE_DECODE_CHANNELMAPPING_LEGACY_ICARUSCHANNELMAPPROVIDER_H +#define ICARUSCODE_DECODE_CHANNELMAPPING_LEGACY_ICARUSCHANNELMAPPROVIDER_H // ICARUS libraries #include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" @@ -114,4 +114,4 @@ class icarusDB::ICARUSChannelMapProvider: public IICARUSChannelMap // ----------------------------------------------------------------------------- -#endif // ICARUSCODE_DECODE_CHANNELMAPPING_ICARUSCHANNELMAPPROVIDER_H +#endif // ICARUSCODE_DECODE_CHANNELMAPPING_LEGACY_ICARUSCHANNELMAPPROVIDER_H diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMap_service.cc similarity index 95% rename from icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc rename to icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMap_service.cc index 8093d8205..0fccd0f4a 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMap_service.cc @@ -1,10 +1,10 @@ /** - * @file icaruscode/Decode/ChannelMapping/ICARUSChannelMap_service.cc + * @file icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMap_service.cc * @brief Wrapper service for `icarusDB::ICARUSChannelMapProvider`. * @author Gianluca Petrillo (petrillo@slac.stanford.edu) */ -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" +#include "icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // framework libraries diff --git a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx index 1f3752e2e..19a76d25c 100644 --- a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx @@ -4,18 +4,18 @@ * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * * This utility can be run with any configuration file including a configuration - * for `IICARUSChannelMap` service featuring SQLite backend. + * for `IICARUSChannelMap` service featuring a few hard-coded backends. * - * It is using _art_ facilities for tool loading, but it does not run in _art_ - * environment. So it may break without warning and without solution. + * It may be using _art_ facilities for tool loading, but it does not run in + * _art_ environment. So it may break without warning and without solution. * */ // ICARUS libraries +#include "icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapSQLiteProvider.h" #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" diff --git a/icaruscode/Decode/ChannelMapping/TPCChannelmapping.h b/icaruscode/Decode/ChannelMapping/TPCChannelmapping.h deleted file mode 100644 index 0750b8fb2..000000000 --- a/icaruscode/Decode/ChannelMapping/TPCChannelmapping.h +++ /dev/null @@ -1,596 +0,0 @@ -// ------------------------------------------------- -// This is the first pass to this script -// It will improve gradually as we move on -// Also coding style will gradually improve. -// -// -// Author : Biswaranjan Behera @ 02 April 2020 -// email : bishu@colostate.edu -//------------------------------------------------- - -#include "wda.h" - -#include -#include -#include -#include -#include - -namespace database -{ - - // ----------------------------------------------------- - // This Function does the basic information retrieval - // One passes in the type of data requested and a reference to the data holder - // The function connects via the libwda function to recover the - // data and checks to insure there were not connection errors. - // The function returns the error status, if null then success - //----------------------------------------------------- - - inline int GetDataset(const std::string name, const std::string url, const std::string& dataType, Dataset& dataSet) - { - const int timeout(200); - std::string dburl = url + "&t=" + dataType; - - int error(0); - - dataSet = getDataWithTimeout(dburl.data(),name.data(),timeout,&error); - - if (error) - { - std::string errorMsg = "Database access GetDataset failed with error " + std::to_string(error) + "\nDB url: " - + dburl + ", name: " + name + ", type: " + dataType; - std::cout << "****> Database retrieval error, code: " << error << std::endl; - throw std::runtime_error(errorMsg); - } - - return error; - } - - // ----------------------------------------------------- - // The aim of this function is to build a map between the - // TPC Fragment IDs and the readout board IDs. Here we - // expect there will be some number of boards per Fragment - //----------------------------------------------------- - - using ReadoutIDVec = std::vector; - using CrateNameReadoutIDPair = std::pair; - using TPCFragmentIDToReadoutIDMap = std::map; - - inline int BuildTPCFragmentIDToReadoutIDMap(TPCFragmentIDToReadoutIDMap& fragmentBoardMap) - { - const unsigned int tpcIdentifier(0x00001000); - const std::string name("icarus_hw_readoutboard"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType("readout_boards"); - Dataset dataset; - - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - - // Include a by hand mapping of fragement ID to crate - using FlangeIDToCrateMap = std::map; - - FlangeIDToCrateMap flangeIDToCrateMap; - - flangeIDToCrateMap[19] = "WW01T"; - flangeIDToCrateMap[68] = "WW01M"; - flangeIDToCrateMap[41] = "WW01B"; - flangeIDToCrateMap[11] = "WW02"; - flangeIDToCrateMap[17] = "WW03"; - flangeIDToCrateMap[36] = "WW04"; - flangeIDToCrateMap[18] = "WW05"; - flangeIDToCrateMap[58] = "WW06"; - flangeIDToCrateMap[71] = "WW07"; - flangeIDToCrateMap[14] = "WW08"; - flangeIDToCrateMap[25] = "WW09"; - flangeIDToCrateMap[34] = "WW10"; - flangeIDToCrateMap[67] = "WW11"; - flangeIDToCrateMap[33] = "WW12"; - flangeIDToCrateMap[87] = "WW13"; - flangeIDToCrateMap[10] = "WW14"; - flangeIDToCrateMap[59] = "WW15"; - flangeIDToCrateMap[95] = "WW16"; - flangeIDToCrateMap[22] = "WW17"; - flangeIDToCrateMap[91] = "WW18"; - flangeIDToCrateMap[61] = "WW19"; - flangeIDToCrateMap[55] = "WW20T"; - flangeIDToCrateMap[97] = "WW20M"; - flangeIDToCrateMap[100] = "WW20B"; - flangeIDToCrateMap[83] = "WE01T"; - flangeIDToCrateMap[85] = "WE01M"; - flangeIDToCrateMap[7] = "WE01B"; - flangeIDToCrateMap[80] = "WE02"; - flangeIDToCrateMap[52] = "WE03"; - flangeIDToCrateMap[32] = "WE04"; - flangeIDToCrateMap[70] = "WE05"; - flangeIDToCrateMap[74] = "WE06"; - flangeIDToCrateMap[46] = "WE07"; - flangeIDToCrateMap[81] = "WE08"; - flangeIDToCrateMap[63] = "WE09"; - flangeIDToCrateMap[30] = "WE10"; - flangeIDToCrateMap[51] = "WE11"; - flangeIDToCrateMap[90] = "WE12"; - flangeIDToCrateMap[23] = "WE13"; - flangeIDToCrateMap[93] = "WE14"; - flangeIDToCrateMap[92] = "WE15"; - flangeIDToCrateMap[88] = "WE16"; - flangeIDToCrateMap[73] = "WE17"; - flangeIDToCrateMap[1] = "WE18"; - flangeIDToCrateMap[66] = "WE19"; - flangeIDToCrateMap[48] = "WE20T"; - flangeIDToCrateMap[13] = "WE20M"; - flangeIDToCrateMap[56] = "WE20B"; - flangeIDToCrateMap[94] = "EW01T"; - flangeIDToCrateMap[77] = "EW01M"; - flangeIDToCrateMap[72] = "EW01B"; - flangeIDToCrateMap[65] = "EW02"; - flangeIDToCrateMap[4] = "EW03"; - flangeIDToCrateMap[89] = "EW04"; - flangeIDToCrateMap[37] = "EW05"; - flangeIDToCrateMap[76] = "EW06"; - flangeIDToCrateMap[49] = "EW07"; - flangeIDToCrateMap[60] = "EW08"; - flangeIDToCrateMap[21] = "EW09"; - flangeIDToCrateMap[6] = "EW10"; - flangeIDToCrateMap[62] = "EW11"; - flangeIDToCrateMap[2] = "EW12"; - flangeIDToCrateMap[29] = "EW13"; - flangeIDToCrateMap[44] = "EW14"; - flangeIDToCrateMap[9] = "EW15"; - flangeIDToCrateMap[31] = "EW16"; - flangeIDToCrateMap[98] = "EW17"; - flangeIDToCrateMap[38] = "EW18"; - flangeIDToCrateMap[99] = "EW19"; - flangeIDToCrateMap[53] = "EW20T"; - flangeIDToCrateMap[82] = "EW20M"; - flangeIDToCrateMap[35] = "EW20B"; - flangeIDToCrateMap[96] = "EE01T"; - flangeIDToCrateMap[28] = "EE01M"; - flangeIDToCrateMap[16] = "EE01T"; - flangeIDToCrateMap[69] = "EE02"; - flangeIDToCrateMap[20] = "EE02"; - flangeIDToCrateMap[79] = "EE02"; - flangeIDToCrateMap[50] = "EE02"; - flangeIDToCrateMap[45] = "EE02"; - flangeIDToCrateMap[84] = "EE02"; - flangeIDToCrateMap[42] = "EE02"; - flangeIDToCrateMap[39] = "EE02"; - flangeIDToCrateMap[26] = "EE02"; - flangeIDToCrateMap[64] = "EE02"; - flangeIDToCrateMap[43] = "EE02"; - flangeIDToCrateMap[47] = "EE02"; - flangeIDToCrateMap[15] = "EE02"; - flangeIDToCrateMap[3] = "EE02"; - flangeIDToCrateMap[27] = "EE02"; - flangeIDToCrateMap[24] = "EE02"; - flangeIDToCrateMap[40] = "EE02"; - flangeIDToCrateMap[75] = "EE02"; - flangeIDToCrateMap[86] = "EE20T"; - flangeIDToCrateMap[54] = "EE20M"; - flangeIDToCrateMap[8] = "EE20B"; - - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - - // Loop through the data to recover the channels - // NOTE that we skip the first row because that is just the labels - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - - if (tuple != NULL) - { - // Note that the fragment ID is stored in the database as a string which reads as a hex number - // Meaning we have to read back as a string and decode to get the numerical value. - char fragmentBuffer[16]; - - getStringValue(tuple, 8, fragmentBuffer, sizeof(fragmentBuffer), &error); - - if (error) throw std::runtime_error("Encountered error in trying to recover FragmentID from database"); - - std::string fragmentIDString(fragmentBuffer,4); - - unsigned int fragmentID = std::stol(fragmentIDString,nullptr,16); - - if (!(fragmentID & tpcIdentifier)) continue; - - if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) - { - unsigned int flangeID = getLongValue(tuple, 1, &error); - - if (error) throw std::runtime_error("Encountered error in trying to recover Board Flange ID from database"); - - fragmentBoardMap[fragmentID].first = flangeIDToCrateMap[flangeID]; - } - - unsigned int readoutID = getLongValue(tuple, 0, &error); - - if (error) throw std::runtime_error("Encountered error in trying to recover Board ReadoutID from database"); - - fragmentBoardMap[fragmentID].second.emplace_back(readoutID); - - releaseTuple(tuple); - } - } - - return error; - } - - // ----------------------------------------------------- - // The aim of this function is to build a map between the - // TPC readout board IDs and the associated channels. So for - // each readout board ID we expect a number of channels back - // from the data base. So the returned data structure will - // be a map of readout ID to a vector of channels - //----------------------------------------------------- - - using ChannelPlanePair = std::pair; - using ChannelPlanePairVec = std::vector; - using SlotChannelVecPair = std::pair; - using TPCReadoutBoardToChannelMap = std::map; - - const unsigned int CHANNELSPERBOARD = 64; - - inline int BuildTPCReadoutBoardToChannelMap(TPCReadoutBoardToChannelMap& rbChanMap) - { - const std::string name("icarus_hardware_dev"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType("daq_channels"); - Dataset dataset; - - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - - // If there was an error the function above would have printed a message so bail out - if (error) throw std::runtime_error("Encountered error accessing the database with GetDataset"); - - // Loop through the data to recover the channels, making sure to skip the first (header) row - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - - if (tuple != NULL) - { - unsigned int readoutBoardID = getLongValue(tuple, 2, &error); - - if (error) throw std::runtime_error("Encountered error when trying to read Board ReadoutID"); - - if (rbChanMap.find(readoutBoardID) == rbChanMap.end()) - { - unsigned int readoutBoardSlot = getLongValue(tuple, 4, &error); - - if (error) throw std::runtime_error("Encountered error when trying to read Board Readout slot"); - - rbChanMap[readoutBoardID].first = readoutBoardSlot; - rbChanMap[readoutBoardID].second.resize(CHANNELSPERBOARD); - } - - unsigned int channelNum = getLongValue(tuple, 5, &error); - - if (error) throw std::runtime_error("Encountered error when trying to read channel number"); - - unsigned int channelID = getLongValue(tuple, 0, &error); - - if (error) throw std::runtime_error("Encountered error when recovering the channel ID list"); - - // Recover the plane identifier - char fragmentBuffer[16]; - - getStringValue(tuple, 10, fragmentBuffer, sizeof(fragmentBuffer), &error); - - if (error) throw std::runtime_error("Encountered error when trying to read plane type"); - - // Make sure lower case... (sigh...) - for(size_t charIdx = 0; charIdx < sizeof(fragmentBuffer); charIdx++) fragmentBuffer[charIdx] = tolower(fragmentBuffer[charIdx]); - - unsigned int plane(3); - - if (strstr(fragmentBuffer,"collection")) plane = 2; - else if (strstr(fragmentBuffer,"induction 2")) plane = 1; - else if (strstr(fragmentBuffer,"induction 1")) plane = 0; - - if (plane > 2) std::cout << "YIKES!!! Plane is " << plane << " for channel " << channelID << " with type " << std::string(fragmentBuffer) << std::endl; - - rbChanMap[readoutBoardID].second[channelNum] = ChannelPlanePair(channelID,plane); - } - } - - return error; - } - - // ------------------------------------------------- - // This Function returns Fragment_ID. - // input : readout_board_id - //------------------------------------------------- - - inline char* Fragment_ID(int readout_board_ID) - { - Dataset ds; - const std::string name("icarus_hw_readoutboard"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType = "readout_boards"; - - int error = GetDataset(name,dburl,dataType, ds); - - if (error) - { // Check for curl library errors - fprintf(stderr, "error code=%d\n", error); perror("error message"); - } - if (getHTTPstatus(ds) != 200) - { // Check for HTTP error - fprintf(stderr, "HTTP code=%ld, message: '%s'\n", getHTTPstatus(ds), getHTTPmessage(ds)); - } - - char ss[10]; - int err; - int readoutboard_id; - int nrows = getNtuples(ds); - Tuple tup; - for (int rows = 0; rows < nrows; rows++ ){ - tup = getTuple(ds, rows); // Get the row with double array - - if (tup != NULL) { - //int nc = getNfields(tup); - //for (i = 0; i < nc; i++) { - //len = getStringValue(tup, i ,8, sizeof (ss), &err); - //fprintf(stderr, "[%d]: l=%d, s='%s'\n", i, len, ss); - //fprintf(stderr, "[4]: v=%i\n", getStringValue(tup, i ,ss, sizeof (ss), &err)); - // } - readoutboard_id = (int)getDoubleValue(tup, 0, &err); - if (readoutboard_id == readout_board_ID){ - getStringValue(tup, 8 ,ss, sizeof (ss), &err); - } - releaseTuple(tup); - } - } - char* fragment_id = new char[4]; - std::strcpy(fragment_id, ss); - return fragment_id; - } - - // ------------------------------------------------- - // This Function returns vector of Channel_ID, - // As One read out board contains 64 channels. - // input : readout_board_id - //------------------------------------------------- - - inline std::vector Channel_ID(int readout_board_ID) - { - Dataset ds; - const std::string name("icarus_hardware_dev"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType = "daq_channels"; - - int error = GetDataset(name,dburl,dataType, ds); - - if (error) { // Check for curl library errors - fprintf(stderr, "error code=%d\n", error); perror("error message"); - } - if (getHTTPstatus(ds) != 200) { // Check for HTTP error - fprintf(stderr, "HTTP code=%ld, message: '%s'\n", getHTTPstatus(ds), getHTTPmessage(ds)); - } - - int channel_id; - std::vector channelidvec; - int nrows = getNtuples(ds); - for (int rows = 0; rows < nrows; rows++ ){ - Tuple tu = getTuple(ds, rows); // Get the row with double array - - // If we get the names print them - if (tu != NULL) { - int err(0); - // If everything is OK - int readoutboardid = (int)getDoubleValue(tu, 2, &err); - - if (readoutboardid == readout_board_ID){ - channel_id = (int)getDoubleValue(tu, 0, &err); - channelidvec.push_back(channel_id); - } - releaseTuple(tu); - } - } - return channelidvec; - } - - - //******************* PMT Channel Mapping *********************** - - // Ultimately, we want to map between Fragment IDs and a pair of numbers - the channel in the fragment and the LArSoft channel ID - using DigitizerChannelChannelIDPair = std::pair; - using DigitizerChannelChannelIDPairVec = std::vector; - using FragmentToDigitizerChannelMap = std::map; - - inline int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) - { - // clearing is cleansing - fragmentToDigitizerChannelMap.clear(); - - // Recover the information from the database on the mapping - const std::string name("Pmt_placement"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType("pmt_placements"); - Dataset dataset; - - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - - // Ok, now we can start extracting the information - // We do this by looping through the database and building the map from that - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - - if (tuple != NULL) - { - char digitizerBuffer[10]; - - // Recover the digitizer label first - getStringValue(tuple, 8, digitizerBuffer, sizeof(digitizerBuffer), &error); - - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT digitizer label"); - - std::string digitizerLabel(digitizerBuffer, 8); //sizeof(digitizerBuffer)); - - // Recover the fragment id - unsigned fragmentID = getLongValue(tuple, 18, &error); - - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT fragment id"); - - // Now recover the digitizer channel number - unsigned int digitizerChannelNo = getLongValue(tuple, 9, &error); - - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT digitizer channel number"); - - // Finally, get the LArsoft channel ID - unsigned int channelID = getLongValue(tuple, 17, &error); - - if (error) throw std::runtime_error("Encountered error when trying to recover the PMT channel ID"); - - // Fill the map - fragmentToDigitizerChannelMap[fragmentID].emplace_back(digitizerChannelNo,channelID); - - releaseTuple(tuple); - } - } - - return error; - } - - //--------------------------------------------------------------- - // The aim of this function is to build a map between the - // Larsoft PMT Channel ID and the physical location of PMT ID - //--------------------------------------------------------------- - - inline int PMTChannelIDFromPhysicalPMTPositionID(unsigned int pmtid) - { - const std::string name("icarus_hw_readoutboard"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType("pmt_placements"); - Dataset dataset; - - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - - unsigned int PhysicalPMTPositionID; - unsigned int PMTChannelID; - - // Loop through the data to recover the channels - // NOTE that we skip the first row because that is just the labels - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - - if (tuple != NULL) - { - - PhysicalPMTPositionID = getLongValue(tuple, 0, &error); - - if (error) throw std::runtime_error("Encountered error when trying to read Physical PMT Position ID from database"); - - if (PhysicalPMTPositionID == pmtid) { - - PMTChannelID = getLongValue(tuple, 17, &error); - - if (error) throw std::runtime_error("Encountered error in trying to recover Larsoft PMT Channel ID from database"); - - }else continue; - - releaseTuple(tuple); - } - } - - return PMTChannelID; - } - - //----------------------------------------------------------------------------- - // The aim of this function is to build a map between the - // Larsoft PMT Channel ID and the Digitizer channel number and Digitizer label - //----------------------------------------------------------------------------- - - inline int PMTChannelIDFromDigitizer(std::string digitizerlabel, int digitizerchannelnumber) - { - const std::string name("icarus_hw_readoutboard"); - const std::string dburl("https://dbdata0vm.fnal.gov:9443/QE/hw/app/SQ/query?dbname=icarus_hardware_dev"); - const std::string dataType("pmt_placements"); - Dataset dataset; - - // Recover the data from the database - int error = GetDataset(name,dburl,dataType,dataset); - - // If there was an error the function above would have printed a message so bail out - if (error) throw(std::exception()); - - unsigned int PMTChannelID; - - // Loop through the data to recover the channels - // NOTE that we skip the first row because that is just the labels - for(int row = 1; row < getNtuples(dataset); row++) - { - // Recover the row - Tuple tuple = getTuple(dataset, row); - - if (tuple != NULL) - { - char digitizerBuffer[10]; - - getStringValue(tuple, 8, digitizerBuffer, sizeof(digitizerBuffer), &error); - std::string digitizerLabel(digitizerBuffer, sizeof(digitizerBuffer)); - - int digitizerChannelNumber = getDoubleValue(tuple, 9, &error); - - - int matchedcharacter = digitizerLabel.compare(digitizerlabel); - - // Not sure what I am doing wrong why 2 is coming for matchedcharacter, - // but I have tried a simple compare string with same name it is 0. - // std::string s1("EE-BOT-B"); - // std::string s2("EE-BOT-B"); - // int compare = s1.compare(s2); - // if (compare == 0) std::cout << "strings are equal" << std::endl; - - if(matchedcharacter == 2 && digitizerChannelNumber == digitizerchannelnumber){ - - PMTChannelID = getLongValue(tuple, 17, &error); - - if (error) throw std::runtime_error("Encountered error in trying to recover Larsoft PMT Channel ID from database"); - - }else continue; - - releaseTuple(tuple); - } - } - - return PMTChannelID; - - } - - // ------------------------------------------------- - // This is the main Function - //------------------------------------------------- - - //int main() - //{ - // std::vector ch_id_vec = Channel_ID(854); - // for(std::vector::iterator it = ch_id_vec.begin(); it != ch_id_vec.end(); it++) { - // std::cout << "channel_id: \t" << *it << std::endl; - // } - // - // std ::cout << Fragment_ID(89) << std::endl; - // - // std ::cout << Fragment_ID(854) << std::endl; - // - // return 0; - //} - -} // end of namespace From 63925510edfe0c8003014af44887945d232e1826 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 24 Feb 2024 01:38:56 -0600 Subject: [PATCH 08/19] Renamed PMTChannelMapDumper into ChannelMapDumper Because it dumps almost all channel maps. --- .../Decode/ChannelMapping/CMakeLists.txt | 4 +-- ...nnelMapDumper.cxx => ChannelMapDumper.cxx} | 28 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) rename icaruscode/Decode/ChannelMapping/{PMTChannelMapDumper.cxx => ChannelMapDumper.cxx} (92%) diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index d74e619fa..aa7a31934 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -1,7 +1,7 @@ cet_enable_asserts() art_make_library( - EXCLUDE "PMTChannelMapDumper.cxx" + EXCLUDE "ChannelMapDumper.cxx" LIBRARIES icarusalg::Utilities larcorealg::CoreUtils @@ -41,7 +41,7 @@ cet_build_plugin(ICARUSChannelMapSQLite art::service add_subdirectory("Legacy") -cet_make_exec(NAME "PMTChannelMapDumper" +cet_make_exec(NAME "ChannelMapDumper" LIBRARIES icaruscode::Decode_ChannelMapping_Legacy icaruscode::Decode_ChannelMapping diff --git a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx similarity index 92% rename from icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx rename to icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx index 19a76d25c..608cd476b 100644 --- a/icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx @@ -1,5 +1,5 @@ /** - * @file icaruscode/Decode/ChannelMapping/PMTChannelMapDumper.cxx + * @file icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx * @brief Utility dumping the content of PMT channel mapping on screen. * @author Gianluca Petrillo (petrillo@slac.stanford.edu) * @@ -79,7 +79,7 @@ void dumpTPCmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { constexpr unsigned int FragmentIDoffset = 0x1000; - mf::LogVerbatim log("PMTchannelMappingDumper"); + mf::LogVerbatim log("ChannelMapDumper"); // by fragment unsigned int nFragmentIDs = mapping.nTPCfragmentIDs(); @@ -155,7 +155,7 @@ void dumpTPCmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- void dumpPMTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { - mf::LogVerbatim log("PMTchannelMappingDumper"); + mf::LogVerbatim log("ChannelMapDumper"); unsigned int nFragmentIDs = mapping.nPMTfragmentIDs(); log << "Reported " << nFragmentIDs << " PMT fragment IDs."; @@ -203,7 +203,7 @@ void dumpPMTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- void dumpCRTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { - mf::LogVerbatim log("PMTchannelMappingDumper"); + mf::LogVerbatim log("ChannelMapDumper"); constexpr unsigned int MaxHWmac = 1000; @@ -229,16 +229,16 @@ void dumpCRTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { // ----------------------------------------------------------------------------- void dumpMapping(icarusDB::IICARUSChannelMapProvider const& channelMapping) { - mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '-'); dumpTPCmapping(channelMapping); - mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '-'); dumpPMTmapping(channelMapping); - mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '-'); dumpCRTmapping(channelMapping); - mf::LogVerbatim("PMTchannelMappingDumper") << std::string(80, '-'); + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '-'); } @@ -248,7 +248,7 @@ int main(int argc, char** argv) { using Environment = testing::TesterEnvironment; - testing::BasicEnvironmentConfiguration config("PMTchannelMappingDumper"); + testing::BasicEnvironmentConfiguration config("ChannelMapDumper"); // // parameter parsing @@ -277,9 +277,9 @@ int main(int argc, char** argv) { std::string const serviceType = channelMapConfig.get ("service_provider", "ICARUSChannelMapSQLite"); channelMapConfig.erase("service_provider"); // if not present, still friends - mf::LogVerbatim("PMTChannelMapDumper") + mf::LogVerbatim("ChannelMapDumper") << "Initializing a provider of type '" << serviceType << "'"; - mf::LogTrace("PMTChannelMapDumper") + mf::LogTrace("ChannelMapDumper") << "with configuration:\n{" << channelMapConfig.to_indented_string(1) << "\n}"; if (serviceType == "ICARUSChannelMapSQLite") { @@ -296,7 +296,7 @@ int main(int argc, char** argv) { (channelMapConfig); } else { - mf::LogError("PMTChannelMapDumper") + mf::LogError("ChannelMapDumper") << "Fatal: don't know what to do with IICARUSChannelMap.service_type: '" << serviceType << "'."; return 1; @@ -306,14 +306,14 @@ int main(int argc, char** argv) { // dump // for (icarusDB::RunPeriod const period: icarusDB::RunPeriods::All) { - mf::LogVerbatim("PMTchannelMapDumper") + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '=') << "\nRun period #" << static_cast(period) << ":\n"; channelMapping->forPeriod(period); dumpMapping(*channelMapping); } - mf::LogVerbatim("PMTchannelMappingDumper") + mf::LogVerbatim("ChannelMapDumper") << std::string(80, '=') << "\nDumped " << icarusDB::RunPeriods::All.size() << " run periods." ; From af9b259c352d07e2e3f81b97aaef98eacb2e2882 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 24 Feb 2024 20:49:06 -0600 Subject: [PATCH 09/19] SQLite channel mapping now uses column names. Instead of hard-coded column numbers. --- .../Decode/ChannelMapping/CMakeLists.txt | 1 + .../ChannelMapping/ChannelMapSQLite.cxx | 140 ++++++++++++++---- 2 files changed, 115 insertions(+), 26 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index aa7a31934..1777854e4 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -28,6 +28,7 @@ art_make_library( cetlib::cetlib cetlib_except::cetlib_except SQLite::SQLite3 + Microsoft.GSL::GSL ) diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx index b5e966dd6..fb7671c4d 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -6,6 +6,7 @@ // library header #include "icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h" +#include "icaruscode/Decode/ChannelMapping/PositionFinder.h" // ICARUS libraries @@ -18,7 +19,10 @@ #include "cetlib/search_path.h" // SQLite -#include +#include "sqlite3.h" + +// Guildelines library +#include "gsl/span" // C++ standard libraries #include // std::transform() @@ -151,6 +155,14 @@ namespace { } // local namespace +// ----------------------------------------------------------------------------- +void dumpColumnNames(std::string const& tag, int n, char** names) { + mf::LogInfo out{ tag }; + out << tag << ": " << n << " columns:"; + for (int i: util::counter(n)) + out << " [" << i << "] \"" << names[i] << "\""; +} + // ----------------------------------------------------------------------------- std::array @@ -255,15 +267,26 @@ int icarusDB::ChannelMapSQLite::GetDataset // ----------------------------------------------------------------------------- -// The aim of this function is to build a map between the -// TPC Fragment IDs and the readout board IDs. Here we -// expect there will be some number of boards per Fragment -//----------------------------------------------------- +// --- TPC +// ----------------------------------------------------------------------------- int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback (void* dataOut, int argc, char**argv, char** azColName) { - const unsigned int tpcIdentifier(0x00001000); - + constexpr unsigned int tpcIdentifier(0x00001000); + // find the position of the columns we need + /* + * [20240224] 9 columns: + * [0] "readout_board_id" [1] "flange_id" [2] "chimney_number" + * [3] "tpc_id" [4] "create_time" [5] "create_user" + * [6] "update_time" [7] "update_user" [8] "fragement_id" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn ] + = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} } + ("readout_board_id"s, "flange_id"s, "fragement_id"s ); + auto& fragmentBoardMap = *static_cast(dataOut); @@ -368,10 +391,6 @@ int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback { 8, "EE20B" } }; // flangeIDToCrateMap[] - constexpr std::size_t ReadoutBoardIDcolumn = 0; - constexpr std::size_t FlangeIDcolumn = 1; - constexpr std::size_t FragmentIDcolumn = 8; - unsigned int const fragmentID = std::stol(argv[FragmentIDcolumn], nullptr, 16); @@ -416,11 +435,26 @@ int icarusDB::ChannelMapSQLite::BuildTPCFragmentIDToReadoutIDMap int icarusDB::ChannelMapSQLite::buildTPCReadoutBoardToChannelMap_callback (void* dataOut, int argc, char**argv, char** azColName) { - constexpr std::size_t ChannelIDcolumn = 0; - constexpr std::size_t ReadoutBoardIDcolumn = 2; - constexpr std::size_t ReadoutBoardSlotColumn = 4; - constexpr std::size_t ChannelNumberColumn = 5; - constexpr std::size_t FragmentBufferColumn = 10; + + // find the position of the columns we need + /* + * [20240224] 19 columns: + * [0] "channel_id" [1] "wire_number" [2] "readout_board_id" + * [3] "chimney_number" [4] "readout_board_slot" [5] "channel_number" + * [6] "create_time" [7] "create_user" [8] "update_time" + * [9] "update_user" [10] "plane" [11] "cable_label_number" + * [12] "channel_type" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ + ChannelIDcolumn, ReadoutBoardIDcolumn, ReadoutBoardSlotColumn, + ChannelNumberColumn, PlaneIdentifierColumn + ] = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} }( + "channel_id"s, "readout_board_id"s, "readout_board_slot"s, + "channel_number"s, "plane"s + ); auto& rbChanMap= *static_cast(dataOut); @@ -436,7 +470,7 @@ int icarusDB::ChannelMapSQLite::buildTPCReadoutBoardToChannelMap_callback unsigned int channelNum = std::stol(argv[ChannelNumberColumn]); unsigned int channelID = std::stol(argv[ChannelIDcolumn]); - std::string const fragmentBuffer = argv[FragmentBufferColumn]; + std::string const fragmentBuffer = argv[PlaneIdentifierColumn]; unsigned int const plane = TPCplaneIdentifierToPlane(fragmentBuffer); if (plane >= 3) { mf::LogError{ "ChannelMapSQLite" } << "YIKES!!! Plane is " << plane @@ -472,14 +506,34 @@ int icarusDB::ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap } // icarusDB::ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap() +// ----------------------------------------------------------------------------- +// --- PMT // ----------------------------------------------------------------------------- int icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback (void* dataOut, int argc, char**argv, char** azColName) { - constexpr std::size_t LaserChannelColumn = 7; - constexpr std::size_t DigitizerChannelColumn = 9; - constexpr std::size_t ChannelIDcolumn = 17; - constexpr std::size_t FragmentIDcolumn = 18; + // find the position of the columns we need + /* + * [20240224] 19 columns: + * [0] "pmt_id" [1] "pmt_sn" [2] "sector_label" + * [3] "ch_number" [4] "pmt_position_code" [5] "hv_cable_label" + * [6] "signal_cable_label" [7] "light_fiber_label" [8] "digitizer_label" + * [9] "digitizer_ch_number" [10] "hv_supply_label" [11] "hv_supply_ch_number" + * [12] "create_time" [13] "update_user" [14] "update_time" + * [15] "create_user" [16] "pmt_in_tpc_plane" [17] "channel_id" + * [18] "fragment_id" + * Look for the ones we care of: + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ + LaserChannelColumn, DigitizerChannelColumn, ChannelIDcolumn, + FragmentIDcolumn + ] = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} }( + "light_fiber_label"s, "digitizer_ch_number"s, "channel_id"s, + "fragment_id"s + ); auto& fragmentToDigitizerChannelMap = *static_cast(dataOut); @@ -538,13 +592,26 @@ int icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap } // icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap() +// ----------------------------------------------------------------------------- +// --- CRT // ----------------------------------------------------------------------------- int icarusDB::ChannelMapSQLite::buildCRTChannelIDToHWtoSimMacAddressPairMap_callback (void* dataOut, int argc, char**argv, char** azColName) { - constexpr std::size_t ChannelIDcolumn = 10; - constexpr std::size_t SimMACaddressColumn = 11; - constexpr std::size_t HWaddressColumn = 12; + /* + * [20240224] 13 columns: + * [0] "feb_id" [1] "feb_channel" [2] "pedestal" + * [3] "threshold_adjust" [4] "bias" [5] "hg" + * [6] "create_time" [7] "update_user" [8] "update_time" + * [9] "create_user" [10] "channel_id" [11] "feb_index" + * [12] "mac_address" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ ChannelIDcolumn, SimMACaddressColumn, HWaddressColumn ] + = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} } + ("channel_id"s, "feb_index"s, "mac_address"s ); auto& crtChannelIDToHWtoSimMacAddressPairMap = *static_cast @@ -601,8 +668,29 @@ int icarusDB::ChannelMapSQLite::BuildCRTChannelIDToHWtoSimMacAddressPairMap int icarusDB::ChannelMapSQLite::buildTopCRTHWtoSimMacAddressPairMap_callback (void* dataOut, int argc, char**argv, char** azColName) { - constexpr std::size_t SimMACaddressColumn = 41; - constexpr std::size_t HWaddressColumn = 3; + /* + * [20240224] 42 columns: + * [0] "feb_barcode" [1] "serialnum" [2] "mac_add8b" + * [3] "mac_add" [4] "voltage" [5] "ch0" + * [6] "ch1" [7] "ch2" [8] "ch3" + * [9] "ch4" [10] "ch5" [11] "ch6" + * [12] "ch7" [13] "ch8" [14] "ch9" + * [15] "ch10" [16] "ch11" [17] "ch12" + * [18] "ch13" [19] "ch14" [20] "ch15" + * [21] "ch16" [22] "ch17" [23] "ch18" + * [24] "ch19" [25] "ch20" [26] "ch21" + * [27] "ch22" [28] "ch23" [29] "ch24" + * [30] "ch25" [31] "ch26" [32] "ch27" + * [33] "ch28" [34] "ch29" [35] "ch30" + * [36] "ch31" [37] "create_time" [38] "update_user" + * [39] "update_time" [40] "create_user" [41] "feb_index" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ SimMACaddressColumn, HWaddressColumn ] + = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} } + ("feb_index"s, "mac_add"s ); auto& topcrtHWtoSimMacAddressPairMap = *static_cast(dataOut); From 48eb08fa47d80bed9780ab8612b96a3ba4890b9d Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 24 Feb 2024 21:04:58 -0600 Subject: [PATCH 10/19] Renamed internal variables to reflect whether they are for TPC or PMT The public interface is unchanged and still confusing as always. --- .../ChannelMapping/ChannelMapPostGres.cxx | 4 +- .../ChannelMapping/ChannelMapPostGres.h | 2 +- .../ChannelMapping/ChannelMapSQLite.cxx | 18 ++----- .../Decode/ChannelMapping/ChannelMapSQLite.h | 4 +- .../ICARUSChannelMapProviderBase.h | 29 +++++----- .../ICARUSChannelMapProviderBase.txx | 53 ++++++++++--------- .../Decode/ChannelMapping/IChannelMapping.h | 2 +- .../Legacy/ICARUSChannelMapProvider.cxx | 2 +- 8 files changed, 55 insertions(+), 59 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx index 4ab4479bc..fd7bac284 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx @@ -377,7 +377,7 @@ int icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap // ----------------------------------------------------------------------------- -int icarusDB::ChannelMapPostGres::BuildFragmentToDigitizerChannelMap +int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const { assert( !fCurrentPMTTimestamp.empty() ); @@ -457,7 +457,7 @@ int icarusDB::ChannelMapPostGres::BuildFragmentToDigitizerChannelMap } // for return 0; -} // icarusDB::ChannelMapPostGres::BuildFragmentToDigitizerChannelMap() +} // icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap() // ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h index e77a13e33..c4c1c2ff3 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h @@ -113,7 +113,7 @@ class icarusDB::ChannelMapPostGres * and the related crate and readout information. * Then define the function interface to fill these data structures */ - virtual int BuildFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; + virtual int BuildPMTFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; /** diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx index fb7671c4d..38db426bb 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -155,14 +155,6 @@ namespace { } // local namespace -// ----------------------------------------------------------------------------- -void dumpColumnNames(std::string const& tag, int n, char** names) { - mf::LogInfo out{ tag }; - out << tag << ": " << n << " columns:"; - for (int i: util::counter(n)) - out << " [" << i << "] \"" << names[i] << "\""; -} - // ----------------------------------------------------------------------------- std::array @@ -509,7 +501,7 @@ int icarusDB::ChannelMapSQLite::BuildTPCReadoutBoardToChannelMap // ----------------------------------------------------------------------------- // --- PMT // ----------------------------------------------------------------------------- -int icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback +int icarusDB::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback (void* dataOut, int argc, char**argv, char** azColName) { // find the position of the columns we need @@ -560,11 +552,11 @@ int icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback (digitizerChannelNo, channelID, laserChannel); return 0; -} // icarusDB::ChannelMapSQLite::buildFragmentToDigitizerChannelMap_callback() +} // ...::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback() // ----------------------------------------------------------------------------- -int icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap +int icarusDB::ChannelMapSQLite::BuildPMTFragmentToDigitizerChannelMap (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const { // clearing is cleansing @@ -576,7 +568,7 @@ int icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap // Recover the data from the database int error = GetDataset( - dataType, buildFragmentToDigitizerChannelMap_callback, + dataType, buildPMTFragmentToDigitizerChannelMap_callback, &fragmentToDigitizerChannelMap ); @@ -589,7 +581,7 @@ int icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap } return error; -} // icarusDB::ChannelMapSQLite::BuildFragmentToDigitizerChannelMap() +} // icarusDB::ChannelMapSQLite::BuildPMTFragmentToDigitizerChannelMap() // ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h index d1bc3ad56..09553aa90 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h @@ -99,7 +99,7 @@ class icarusDB::ChannelMapSQLite /// Fill mapping between PMT fragment IDs and the related crate and readout /// information. - virtual int BuildFragmentToDigitizerChannelMap + virtual int BuildPMTFragmentToDigitizerChannelMap (FragmentToDigitizerChannelMap&) const override; @@ -207,7 +207,7 @@ class icarusDB::ChannelMapSQLite (void* dataOut, int argc, char**argv, char** azColName); /// Fills the PMT fragment map with the information from one channel. - static int buildFragmentToDigitizerChannelMap_callback + static int buildPMTFragmentToDigitizerChannelMap_callback (void* dataOut, int argc, char**argv, char** azColName); /// Fills the channel mapping for side CRT. diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h index a04c863a6..3b3634612 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h @@ -108,7 +108,7 @@ class icarusDB::ICARUSChannelMapProviderBase {} - /// --- BEGIN --- Data period selection ------------------------------------ + /// --- BEGIN --- Data period selection -------------------------------------- /// @name Data period selection /// @{ @@ -119,10 +119,10 @@ class icarusDB::ICARUSChannelMapProviderBase virtual bool forPeriod(icarusDB::RunPeriod period) override; /// @} - /// --- END ----- Data period selection ------------------------------------ + /// --- END ----- Data period selection -------------------------------------- - /// --- BEGIN --- TPC information ------------------------------------------ + /// --- BEGIN --- TPC information -------------------------------------------- /// @name TPC information /// @{ @@ -183,7 +183,7 @@ class icarusDB::ICARUSChannelMapProviderBase /// --- END - - - TPC board information - - - - - - - - - - - - - - - - - - - /// --- BEGIN --- PMT information ------------------------------------------ + /// --- BEGIN --- PMT information -------------------------------------------- /// @name PMT information /// @{ @@ -199,18 +199,20 @@ class icarusDB::ICARUSChannelMapProviderBase (unsigned int) const override; /// @} - /// --- END ----- PMT information ------------------------------------------ + /// --- END ----- PMT information -------------------------------------------- - /// --- BEGIN --- CRT information ------------------------------------------ + /// --- BEGIN --- CRT information -------------------------------------------- /// @name CRT information /// @{ - /// Returns the sim Mac address corresponding to the specified side CRT hardware address. + /// Returns the sim Mac address corresponding to the specified side CRT + /// hardware address. virtual unsigned int getSimMacAddress(unsigned int hwmacaddress) const override; - /// Returns the sim Mac address corresponding to the specified top CRT hardware address. + /// Returns the sim Mac address corresponding to the specified top CRT + /// hardware address. virtual unsigned int gettopSimMacAddress(unsigned int) const override; /// Returns the Gain and Pedestal for Side CRT. @@ -218,12 +220,13 @@ class icarusDB::ICARUSChannelMapProviderBase (int mac5, int chan) const override; /// @} - /// --- END ----- CRT information ------------------------------------------ + /// --- END ----- CRT information -------------------------------------------- /// Returns the channel mapping database key for the specified PMT fragment ID. static constexpr unsigned int PMTfragmentIDtoDBkey(unsigned int fragmentID); - /// Returns the PMT fragment ID for the specified channel mapping database key. + /// Returns the PMT fragment ID for the specified channel mapping database + /// key. static constexpr unsigned int DBkeyToPMTfragmentID(unsigned int DBkey); @@ -244,11 +247,11 @@ class icarusDB::ICARUSChannelMapProviderBase // --- BEGIN --- Cache ------------------------------------------------------- - icarusDB::TPCFragmentIDToReadoutIDMap fFragmentToReadoutMap; + icarusDB::TPCFragmentIDToReadoutIDMap fTPCFragmentToReadoutMap; - icarusDB::TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; + icarusDB::TPCReadoutBoardToChannelMap fTPCReadoutBoardToChannelMap; - icarusDB::FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + icarusDB::FragmentToDigitizerChannelMap fPMTFragmentToDigitizerMap; icarusDB::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx index 3515ab691..55011a8f8 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx @@ -74,14 +74,15 @@ template bool icarusDB::ICARUSChannelMapProviderBase::hasFragmentID (const unsigned int fragmentID) const { - return fFragmentToReadoutMap.find(fragmentID) != fFragmentToReadoutMap.end(); + return + fTPCFragmentToReadoutMap.find(fragmentID) != fTPCFragmentToReadoutMap.end(); } // ----------------------------------------------------------------------------- template unsigned int icarusDB::ICARUSChannelMapProviderBase::nTPCfragmentIDs() const { - return fFragmentToReadoutMap.size(); + return fTPCFragmentToReadoutMap.size(); } @@ -90,9 +91,9 @@ template std::string const& icarusDB::ICARUSChannelMapProviderBase::getCrateName (const unsigned int fragmentID) const { - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + auto const fragToReadoutItr = fTPCFragmentToReadoutMap.find(fragmentID); - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + if (fragToReadoutItr == fTPCFragmentToReadoutMap.end()) { throw myException() << "Fragment ID " << fragmentID << " not found in lookup map when looking up crate name \n"; } @@ -106,9 +107,9 @@ template auto icarusDB::ICARUSChannelMapProviderBase::getReadoutBoardVec (const unsigned int fragmentID) const -> icarusDB::ReadoutIDVec const& { - auto const fragToReadoutItr = fFragmentToReadoutMap.find(fragmentID); + auto const fragToReadoutItr = fTPCFragmentToReadoutMap.find(fragmentID); - if (fragToReadoutItr == fFragmentToReadoutMap.end()) { + if (fragToReadoutItr == fTPCFragmentToReadoutMap.end()) { throw myException() << "Fragment ID " << fragmentID << " not found in lookup map when looking up board vector.\n"; } @@ -122,7 +123,7 @@ template auto icarusDB::ICARUSChannelMapProviderBase::getReadoutBoardToChannelMap() const -> const TPCReadoutBoardToChannelMap& { - return fReadoutBoardToChannelMap; + return fTPCReadoutBoardToChannelMap; } @@ -132,14 +133,14 @@ bool icarusDB::ICARUSChannelMapProviderBase::hasBoardID (const unsigned int boardID) const { return - fReadoutBoardToChannelMap.find(boardID) != fReadoutBoardToChannelMap.end(); + fTPCReadoutBoardToChannelMap.find(boardID) != fTPCReadoutBoardToChannelMap.end(); } // ----------------------------------------------------------------------------- template unsigned int icarusDB::ICARUSChannelMapProviderBase::nTPCboardIDs() const { - return fReadoutBoardToChannelMap.size(); + return fTPCReadoutBoardToChannelMap.size(); } @@ -148,9 +149,9 @@ template unsigned int icarusDB::ICARUSChannelMapProviderBase::getBoardSlot (const unsigned int boardID) const { - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + auto const readoutBoardItr = fTPCReadoutBoardToChannelMap.find(boardID); - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + if (readoutBoardItr == fTPCReadoutBoardToChannelMap.end()) { throw myException() << "Board ID " << boardID << " not found in lookup map when looking up board slot.\n"; } @@ -164,9 +165,9 @@ template auto icarusDB::ICARUSChannelMapProviderBase::getChannelPlanePair (const unsigned int boardID) const -> ChannelPlanePairVec const& { - auto const readoutBoardItr = fReadoutBoardToChannelMap.find(boardID); + auto const readoutBoardItr = fTPCReadoutBoardToChannelMap.find(boardID); - if (readoutBoardItr == fReadoutBoardToChannelMap.end()) { + if (readoutBoardItr == fTPCReadoutBoardToChannelMap.end()) { throw myException() << "Board ID " << boardID << " not found in lookup map when looking up channel/plane pair.\n"; } @@ -189,7 +190,7 @@ template unsigned int icarusDB::ICARUSChannelMapProviderBase::nPMTfragmentIDs() const { - return fFragmentToDigitizerMap.size(); + return fPMTFragmentToDigitizerMap.size(); } @@ -256,8 +257,8 @@ template auto icarusDB::ICARUSChannelMapProviderBase::findPMTfragmentEntry (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* { - auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); - return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); + auto it = fPMTFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); + return (it == fPMTFragmentToDigitizerMap.end())? nullptr: &(it->second); } @@ -271,8 +272,8 @@ void icarusDB::ICARUSChannelMapProviderBase::readFromDatabase() { // TPC fragment-based mapping cet::cpu_timer theClockFragmentIDs; theClockFragmentIDs.start(); - fFragmentToReadoutMap.clear(); - if (fChannelMappingAlg.BuildTPCFragmentIDToReadoutIDMap(fFragmentToReadoutMap)) + fTPCFragmentToReadoutMap.clear(); + if (fChannelMappingAlg.BuildTPCFragmentIDToReadoutIDMap(fTPCFragmentToReadoutMap)) { throw myException() << "Cannot recover the TPC fragment ID channel map from the database.\n"; @@ -280,9 +281,9 @@ void icarusDB::ICARUSChannelMapProviderBase::readFromDatabase() { else if (fDiagnosticOutput) { auto log = mfLogVerbatim(); - log << "FragmentID to Readout ID map has " << fFragmentToReadoutMap.size() + log << "FragmentID to Readout ID map has " << fTPCFragmentToReadoutMap.size() << " elements"; - for(auto const& [ fragmentID, crateAndBoards ]: fFragmentToReadoutMap) { + for(auto const& [ fragmentID, crateAndBoards ]: fTPCFragmentToReadoutMap) { log << "\n Frag: " << std::hex << fragmentID << std::dec << ", Crate: " << crateAndBoards.first << ", # boards: " << crateAndBoards.second.size(); @@ -298,9 +299,9 @@ void icarusDB::ICARUSChannelMapProviderBase::readFromDatabase() { cet::cpu_timer theClockReadoutIDs; theClockReadoutIDs.start(); - fReadoutBoardToChannelMap.clear(); + fTPCReadoutBoardToChannelMap.clear(); if (fChannelMappingAlg.BuildTPCReadoutBoardToChannelMap - (fReadoutBoardToChannelMap) + (fTPCReadoutBoardToChannelMap) ) { mfLogError() << "******* FAILED TO CONFIGURE CHANNEL MAP ********"; throw myException() << "Failed to read the database.\n"; @@ -315,18 +316,18 @@ void icarusDB::ICARUSChannelMapProviderBase::readFromDatabase() { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PMT channel mapping - fFragmentToDigitizerMap.clear(); - if (fChannelMappingAlg.BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) + fPMTFragmentToDigitizerMap.clear(); + if (fChannelMappingAlg.BuildPMTFragmentToDigitizerChannelMap(fPMTFragmentToDigitizerMap)) { throw myException() << "Cannot recover the PMT fragment ID channel map from the database.\n"; } else if (fDiagnosticOutput) { auto log = mfLogVerbatim(); - log << "FragmentID to Readout ID map has " << fFragmentToDigitizerMap.size() + log << "FragmentID to Readout ID map has " << fPMTFragmentToDigitizerMap.size() << " Fragment IDs"; - for(auto const& [ fragmentID, digitizers ]: fFragmentToDigitizerMap) { + for(auto const& [ fragmentID, digitizers ]: fPMTFragmentToDigitizerMap) { log << "\n Frag: " << std::hex << fragmentID << std::dec << ", # pairs: " << digitizers.size(); } diff --git a/icaruscode/Decode/ChannelMapping/IChannelMapping.h b/icaruscode/Decode/ChannelMapping/IChannelMapping.h index 4fa794569..2ba1c6998 100644 --- a/icaruscode/Decode/ChannelMapping/IChannelMapping.h +++ b/icaruscode/Decode/ChannelMapping/IChannelMapping.h @@ -74,7 +74,7 @@ class icarusDB::IChannelMapping { /// Fill the mapping between PMT Fragment IDs and the related crate and /// readout information. - virtual int BuildFragmentToDigitizerChannelMap + virtual int BuildPMTFragmentToDigitizerChannelMap (FragmentToDigitizerChannelMap&) const = 0; /// @} diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx index cf0c0bf78..3debcf8e6 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx @@ -111,7 +111,7 @@ void ICARUSChannelMapProvider::readFromDatabase() { // Do the channel mapping initialization fFragmentToDigitizerMap.clear(); - if (fChannelMappingTool->BuildFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) + if (fChannelMappingTool->BuildPMTFragmentToDigitizerChannelMap(fFragmentToDigitizerMap)) { throw cet::exception("ICARUSChannelMapProvider") << "Cannot recover the Fragment ID channel map from the database \n"; } From 76f05d0432c71a43c7522afc01876ba190f89904 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 24 Feb 2024 23:17:02 -0600 Subject: [PATCH 11/19] PostgreSLQ channel mapping interface now uses column names instead of numbers Except the CRT calibration database. --- .../ChannelMapping/ChannelMapPostGres.cxx | 167 +++++++++++++++--- .../ICARUSChannelMapProviderBase.txx | 2 +- 2 files changed, 144 insertions(+), 25 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx index fd7bac284..96a7e9415 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx @@ -47,7 +47,43 @@ namespace icarusDB::details { operator Tuple() const { return get(); } }; -} // local namespace + + /// Wrapper of `PositionFinder` to extract the names from a `WDATuple`. + class WDAPositionFinder + : public icarus::ns::util::PositionFinder> + { + + std::vector fNames; ///< Storage for the column names + + public: + WDAPositionFinder(WDATuple&& namesTuple) + : icarus::ns::util::PositionFinder>{ fNames } + , fNames{ tupleToVector(namesTuple) } + {} + + static std::vector tupleToVector(WDATuple& namesTuple) + { + unsigned int const n = getNfields(namesTuple); + std::vector names{ n }; + for (unsigned int const i: util::counter(n)) { + std::string& name = names[i]; // util::enumerate() fails on l-values + int error = 0; + name.resize(128, '\0'); + std::size_t const length + = getStringValue(namesTuple, i, name.data(), name.size(), &error); + if (error) { // we know very little of the context... sorry, use gdb + throw cet::exception{ "ChannelMapPostGres" } + << "Failed (code: " << error << ") to extract column #" << i + << " name from a channel mapping database table"; + } + name.erase(length); + } + return names; + } // tupleToVector() + + }; // WDAPositionFinder + +} // namespace icarusDB::details // ----------------------------------------------------------------------------- @@ -133,6 +169,8 @@ icarusDB::details::WDADataset icarusDB::ChannelMapPostGres::GetCRTCaldata } +// ----------------------------------------------------------------------------- +// --- TPC // ----------------------------------------------------------------------------- int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap (TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const @@ -244,12 +282,21 @@ int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap { 8, "EE20B" } }; // flangeIDToCrateMap[] - constexpr std::size_t ReadoutBoardIDcolumn = 0; - constexpr std::size_t FlangeIDcolumn = 1; - constexpr std::size_t FragmentIDcolumn = 8; + // Loop through the data to recover the channels; + // find the position of the columns we need from the first row + /* + * [20240224] 9 columns: + * [0] "readout_board_id" [1] "flange_id" [2] "chimney_number" + * [3] "tpc_id" [4] "create_time" [5] "create_user" + * [6] "update_time" [7] "update_user" [8] "fragement_id" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn ] + = details::WDAPositionFinder{ getTuple(dataset, 0) } + ("readout_board_id"s, "flange_id"s, "fragement_id"s ); - // Loop through the data to recover the channels - // NOTE that we skip the first row because that is just the labels for (int const row: util::counter(1, getNtuples(dataset))) { // Recover the row details::WDATuple tuple { getTuple(dataset, row) }; @@ -305,11 +352,25 @@ int icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap std::string const dataType { "daq_channels" }; details::WDADataset dataset = GetDataset(name, fDBURL, dataType); - constexpr std::size_t ChannelIDcolumn = 0; - constexpr std::size_t ReadoutBoardIDcolumn = 2; - constexpr std::size_t ReadoutBoardSlotColumn = 4; - constexpr std::size_t ChannelNumberColumn = 5; - constexpr std::size_t PlaneIdentifierColumn = 10; + // find the position of the columns we need from the first row + /* + * [20240224] 13 columns: + * [0] "channel_id" [1] "wire_number" [2] "readout_board_id" + * [3] "chimney_number" [4] "readout_board_slot" [5] "channel_number" + * [6] "create_time" [7] "create_user" [8] "update_time" + * [9] "update_user" [10] "plane" [11] "cable_label_number" + * [12] "channel_type" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ + ChannelIDcolumn, ReadoutBoardIDcolumn, ReadoutBoardSlotColumn, + ChannelNumberColumn, PlaneIdentifierColumn + ]= details::WDAPositionFinder{ getTuple(dataset, 0) }( + "channel_id"s, "readout_board_id"s, "readout_board_slot"s, + "channel_number"s, "plane"s + ); // Loop through the data to recover the channels, // making sure to skip the first (header) row @@ -376,6 +437,8 @@ int icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap } // icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap() +// ----------------------------------------------------------------------------- +// --- PMT // ----------------------------------------------------------------------------- int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const @@ -392,7 +455,29 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap { "&w=period_active:eq:" + fCurrentPMTTimestamp }; details::WDADataset dataset = GetDataset(name, fDBURL + period_query, dataType); - + + // find the position of the columns we need from the first row + /* + * [20240224] 20 columns: + * [0] "pmt_id" [1] "period_active" [2] "pmt_in_tpc_plane" + * [3] "channel_id" [4] "pmt_sn" [5] "sector_label" + * [6] "ch_number" [7] "pmt_position_code" [8] "hv_cable_label" + * [9] "signal_cable_label" [10] "light_fiber_label" [11] "digitizer_label" + * [12] "digitizer_ch_number" [13] "hv_supply_label" [14]"hv_supply_ch_number" + * [15] "fragment_id" [16] "create_time" [17] "update_user" + * [18] "update_time" [19] "create_user" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ + ChannelIDcolumn, LaserChannelColumn, DigitizerColumn, + DigitizerChannelNoColumn, FragmentIDcolumn + ]= details::WDAPositionFinder{ getTuple(dataset, 0) }( + "channel_id"s, "light_fiber_label"s, "digitizer_label"s, + "digitizer_ch_number"s, "fragment_id"s + ); + // Ok, now we can start extracting the information // We do this by looping through the database and building the map from that // NOTE that we skip the first row because that is just the labels @@ -401,12 +486,6 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap details::WDATuple tuple { getTuple(dataset, row) }; if (!tuple) continue; - constexpr std::size_t ChannelIDcolumn = 3; - constexpr std::size_t LaserChannelColumn = 10; - constexpr std::size_t DigitizerColumn = 11; - constexpr std::size_t DigitizerChannelNoColumn = 12; - constexpr std::size_t FragmentIDcolumn = 15; - int error = 0; // nice... and currently unused @@ -460,6 +539,8 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap } // icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap() +// ----------------------------------------------------------------------------- +// --- CRT // ----------------------------------------------------------------------------- int icarusDB::ChannelMapPostGres::BuildCRTChannelIDToHWtoSimMacAddressPairMap (CRTChannelIDToHWtoSimMacAddressPairMap& crtChannelIDToHWtoSimMacAddressPairMap) @@ -473,9 +554,21 @@ int icarusDB::ChannelMapPostGres::BuildCRTChannelIDToHWtoSimMacAddressPairMap std::string const dataType { "feb_channels" }; details::WDADataset dataset = GetDataset(name, fDBURL, dataType); - constexpr std::size_t ChannelIDcolumn = 10; - constexpr std::size_t SimMacAddressColumn = 11; - constexpr std::size_t HWMacAddressColumn = 12; + // find the position of the columns we need from the first row + /* + * [20240224] 13 columns: + * [0] "feb_id" [1] "feb_channel" [2] "pedestal" + * [3] "threshold_adjust" [4] "bias" [5] "hg" + * [6] "create_time" [7] "update_user" [8] "update_time" + * [9] "create_user" [10] "channel_id" [11] "feb_index" + * [12] "mac_address" + */ + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ ChannelIDcolumn, SimMacAddressColumn, HWMacAddressColumn ] + = details::WDAPositionFinder{ getTuple(dataset, 0) } + ("channel_id"s, "feb_index"s, "mac_address"s ); // Ok, now we can start extracting the information // We do this by looping through the database and building the map from that @@ -532,9 +625,31 @@ int icarusDB::ChannelMapPostGres::BuildTopCRTHWtoSimMacAddressPairMap details::WDADataset dataset = GetDataset(name, fDBURL, dataType); - constexpr std::size_t SimMacAddressColumn = 41; - constexpr std::size_t HWMacAddressColumn = 3; - + /* + * [20240224] 42 columns: + * [0] "feb_barcode" [1] "serialnum" [2] "mac_add8b" + * [3] "mac_add" [4] "voltage" [5] "ch0" + * [6] "ch1" [7] "ch2" [8] "ch3" + * [9] "ch4" [10] "ch5" [11] "ch6" + * [12] "ch7" [13] "ch8" [14] "ch9" + * [15] "ch10" [16] "ch11" [17] "ch12" + * [18] "ch13" [19] "ch14" [20] "ch15" + * [21] "ch16" [22] "ch17" [23] "ch18" + * [24] "ch19" [25] "ch20" [26] "ch21" + * [27] "ch22" [28] "ch23" [29] "ch24" + * [30] "ch25" [31] "ch26" [32] "ch27" + * [33] "ch28" [34] "ch29" [35] "ch30" + * [36] "ch31" [37] "create_time" [38] "update_user" + * [39] "update_time" [40] "create_user" [41] "feb_index" + */ + + // technical detail: `PositionFinder` uses `operator==` to compare, and the + // input is C-strings; we force the other term of comparison to C++ strings + using namespace std::string_literals; + auto const [ SimMacAddressColumn, HWMacAddressColumn ] + = details::WDAPositionFinder{ getTuple(dataset, 0) } + ("feb_index"s, "mac_add"s ); + // Ok, now we can start extracting the information // We do this by looping through the database and building the map from that for(int const row: util::counter(1, getNtuples(dataset))) { @@ -576,6 +691,10 @@ int icarusDB::ChannelMapPostGres::BuildSideCRTCalibrationMap details::WDADataset dataset = GetCRTCaldata(name, fCRTcalibrationDBURL); printDatasetError(dataset); // probably never prints since on error throws + + // the shape of this database is different from the others, + // there is no header row and there is some "introductory" data + // (which we'll skip) in the first rows for (int const row: util::counter(getNtuples(dataset))) { diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx index 55011a8f8..ef6492439 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx @@ -201,7 +201,7 @@ auto icarusDB::ICARUSChannelMapProviderBase::getChannelIDPairVec -> DigitizerChannelChannelIDPairVec const& { mfLogTrace() - << "Call to: ICARUSChannelMapProviderBase::getChannelIDPairVec(" + << "Call to: ICARUSChannelMapProviderBase::getChannelIDPairVec(" << fragmentID << ")"; DigitizerChannelChannelIDPairVec const* digitizerPair From 4f177ce04d7f500bc61170da2f04be0233a3aa30 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Mon, 26 Feb 2024 19:44:26 -0600 Subject: [PATCH 12/19] Renamed sbn::ExtraTriggerInfo::SectorStatus --- icaruscode/Decode/DecoderTools/TriggerDecoderV3_tool.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/icaruscode/Decode/DecoderTools/TriggerDecoderV3_tool.cc b/icaruscode/Decode/DecoderTools/TriggerDecoderV3_tool.cc index 8162818ab..4953e4cd3 100644 --- a/icaruscode/Decode/DecoderTools/TriggerDecoderV3_tool.cc +++ b/icaruscode/Decode/DecoderTools/TriggerDecoderV3_tool.cc @@ -168,6 +168,11 @@ namespace daq * * For the expected matching with PMT, see the documentation of * `sbn::ExtraTriggerInfo::CryostatInfo::LVDSstatus`. + * * `sectorStatus`: information for detector sector (one per TPC), + * reporting the discrimination status of the adder signals at + * the time of the global trigger: `00000000 00NnnssS`, with `S` + * (least significant bit) the southernmost adder, and then + * northward until the northernmost one, `N`. * * Information may be missing. If a count is not available, its value is * set to `0` (which is an invalid value because their valid range starts @@ -817,7 +822,7 @@ namespace daq encodeLVDSbits(cryostat, 0 /* any of the connectors */, connectors01) }; - cryoInfo.SectorStatus = { + cryoInfo.sectorStatus = { encodeSectorBits(cryostat, 2 /* any of the connectors */, connectors23), encodeSectorBits(cryostat, 0 /* any of the connectors */, connectors01) }; From afc7387bee71c53decfd44253673960c944a96dd Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Wed, 10 Jan 2024 16:57:15 -0600 Subject: [PATCH 13/19] Added information to diagnostic tree of PMT decoder --- .../Definitions/CAEN_V1730_setup_icarus.fcl | 4 +- .../Decode/DaqDecoderICARUSPMT_module.cc | 94 ++++++++++++++----- 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/fcl/reco/Definitions/CAEN_V1730_setup_icarus.fcl b/fcl/reco/Definitions/CAEN_V1730_setup_icarus.fcl index ab86fbf61..bb6320122 100644 --- a/fcl/reco/Definitions/CAEN_V1730_setup_icarus.fcl +++ b/fcl/reco/Definitions/CAEN_V1730_setup_icarus.fcl @@ -27,8 +27,8 @@ BEGIN_PROLOG # the offset measured against a (supposedly) common reference via the # Trigger Time Tag counter of the readout board settles to 48 ns # (the counter tick is worth 16 ns). -# Archeology research suggests that these delays might be outdated even for Run0 -# but there is no definitive evidence. +# Archaeology research suggests that these delays might be outdated even for +# Run0 but there is no definitive evidence. # icarus_V1730_West_setup_Run0: [ diff --git a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc index e89a63ceb..5a40cf3fe 100644 --- a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc +++ b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc @@ -383,7 +383,10 @@ namespace icarus { class DaqDecoderICARUSPMT; } * * `triggerSec`, `triggerNS` (32-bit integer each): same time as `trigger` * branch, split into second and nanosecond components. * * `relBeamGateNS`, (32-bit integer): beam gate time opening relative to - * the trigger time, in nanoseconds; it may be affected by rounding. + * the trigger time, in nanoseconds. + * * `relEnableGateNS`, (32-bit integer): enable gate time opening relative + * to the beam gate time, in nanoseconds. If larger than 2.1 seconds ( + * @f$\pm 2^{31}@f$ ns), it is capped. * branch, split into second and nanosecond components. * * `fragTime` (64-bit signed integer), `fragTimeSec` (32-bit signed * integer): the timestamp of the PMT fragment, assigned by the board @@ -395,7 +398,14 @@ namespace icarus { class DaqDecoderICARUSPMT; } * * `waveformSize` (unsigned integer): number of ticks for the waveforms * from this fragment. * * `triggerBits` (unsigned integer): bits from the `raw::Trigger`. - * * `gateCount` (unsigned integer): number of this gate from run start. + * * `triggerSource` (unsigned integer): value of the trigger source bit + * (from `sbn::ExtraTriggerInfo::triggerSource`; see + * `sbn::bits::triggerSource`). + * * `gateID` (unsigned integer): number of this gate from run start + * (note: this used to be `gateCount` until around `v09_80_00`). + * * `gateCount` (unsigned integer): number of gates from this trigger + * source since run start, including this one (note: this used to be the + * number of _all_ gates regardless the source until around `v09_80_00`). * * `onGlobalTrigger` (boolean): whether the waveform covers the nominal * trigger time (which should be equivalent to whether the fragment was * triggered by the global trigger). @@ -784,8 +794,11 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { struct TriggerInfo_t { SplitTimestamp_t time; ///< Time of the trigger (absolute). long int trigToBeam; ///< Time of beam gate relative to trigger [ns]. + long int beamToEnable; ///< Enable gate time relative to beam gate [ns]. sbn::triggerSourceMask bits; ///< Trigger bits. - unsigned int gateCount = 0U; ///< Gate number from the beginning of run. + unsigned int gateID = 0U; ///< Gate number from the beginning of run. + unsigned int gateCount = 0U; ///< Gate number for this source. + sbn::triggerSource sourceType; ///< Trigger source bit. sbn::triggerType triggerType; ///< Type of trigger (minimum bias, majority). electronics_time relTriggerTime; ///< Trigger time. electronics_time relBeamGateTime; ///< Beam gate time. @@ -1010,6 +1023,7 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { SplitTimestamp_t fragTime; ///< PMT fragment time stamp. long int relBeamGate; ///< Beam gate start relative to trigger [ns]. + long int relEnableGate; ///< Enable gate start relative to beam gate [ns]. /// Time assigned to the waveforms. double waveformTime = std::numeric_limits::lowest(); @@ -1018,6 +1032,10 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { unsigned int triggerBits = 0x0; ///< Trigger bits, from `raw::Trigger`. + unsigned int triggerSource = 0x0; ///< Trigger source bit. + + unsigned int gateID = 0U; ///< The number of gates of this source so far. + unsigned int gateCount = 0U; ///< The number of gate from run start. /// Whether waveforms cover nominal trigger time. @@ -1341,6 +1359,17 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { //------------------------------------------------------------------------------ namespace { + /// Converts `v` into type `T`, returning `min()`/`max()` if out of `T` range. + template + T clampInto(U v) { + + using traits_t = std::numeric_limits; + + if (v > traits_t::max()) return traits_t::max(); + if (v < traits_t::min()) return traits_t::min(); + return static_cast(v); + } // clampInto() + /// Moves the contend of `src` into the end of `dest`. template std::vector& appendTo(std::vector& dest, std::vector&& src) { @@ -1844,6 +1873,9 @@ void icarus::DaqDecoderICARUSPMT::produce(art::Event& event) { timeCorrectionProducts[fCorrectionInstance] = {}; } // process each (proto)waveform in a category marked as correction source + mf::LogTrace{ fLogCategory } + << "We have now " << protoWaveforms.size() << " protoWaveforms."; + for (ProtoWaveform_t const& waveform: protoWaveforms) { // extract correction only from waveforms on global trigger, @@ -1859,6 +1891,14 @@ void icarus::DaqDecoderICARUSPMT::produce(art::Event& event) { = timeCorrectionProducts.find(waveform.channelSetup->category); if (itCorr == timeCorrectionProducts.end()) continue; // we don't need this + mf::LogTrace{ fLogCategory } + << "Time corr. from CH=" << std::hex << waveform.waveform.ChannelNumber() + << " for category " << waveform.channelSetup->category; + if (!itCorr->second.empty()) { + mf::LogTrace{ fLogCategory } + << " already " << itCorr->second.size() << " present"; + } + try { fPMTWaveformTimeCorrectionManager.findWaveformTimeCorrections( waveform.waveform, @@ -1880,7 +1920,7 @@ void icarus::DaqDecoderICARUSPMT::produce(art::Event& event) { << waveform.channelSetup->category << "'.\n"; } - } + } // for protowaveforms // --------------------------------------------------------------------------- // output @@ -2192,14 +2232,17 @@ auto icarus::DaqDecoderICARUSPMT::fetchTriggerTimestamp { if (!fTriggerTag) { - return { - SplitTimestamp_t(event.time().value()) // time - , 0U // trigToBeam - , {} // bits - , 0U // gateCount - , sbn::triggerType::NBits // triggerType - , fDetTimings.TriggerTime() // relTriggerTime - , fDetTimings.BeamGateTime() // relBeamGateTime + return { + SplitTimestamp_t(event.time().value()) // time + , std::numeric_limits::min() // trigToBeam + , std::numeric_limits::min() // beamToEnable + , {} // bits + , 0U // gateID + , 0U // gateCount + , sbn::triggerSource::NBits // sourceType + , sbn::triggerType::NBits // triggerType + , fDetTimings.TriggerTime() // relTriggerTime + , fDetTimings.BeamGateTime() // relBeamGateTime }; } @@ -2232,23 +2275,26 @@ auto icarus::DaqDecoderICARUSPMT::fetchTriggerTimestamp long long int const relBeamGate = timestampDiff (extraTrigger.beamGateTimestamp, extraTrigger.triggerTimestamp); + long long int const relEnableGate = timestampDiff + (extraTrigger.enableGateTimestamp, extraTrigger.beamGateTimestamp); electronics_time const relTriggerTime { util::quantities::microsecond{ trigger.TriggerTime() } }; electronics_time const relBeamGateTime { util::quantities::microsecond{ trigger.BeamGateTime() } }; - unsigned int const gateCount = extraTrigger.gateID; - return { - SplitTimestamp_t // time + SplitTimestamp_t // time { static_cast(extraTrigger.triggerTimestamp) } - , relBeamGate // trigToBeam - , {trigger.TriggerBits()} // bits - , gateCount // gateCount - , extraTrigger.triggerType // triggerType - , relTriggerTime // relTriggerTime - , relBeamGateTime // relBeamGateTime + , relBeamGate // trigToBeam + , clampInto(relEnableGate) // beamToEnable + , {trigger.TriggerBits()} // bits + , extraTrigger.gateID // gateID + , extraTrigger.gateCount // gateCount + , extraTrigger.sourceType // sourceType + , extraTrigger.triggerType // triggerType + , relTriggerTime // relTriggerTime + , relBeamGateTime // relBeamGateTime }; } // icarus::DaqDecoderICARUSPMT::fetchTriggerTimestamp() @@ -2810,11 +2856,14 @@ void icarus::DaqDecoderICARUSPMT::fillPMTfragmentTree( fTreeFragment->data.TriggerTimeTag = fragInfo.TTT; fTreeFragment->data.trigger = triggerInfo.time; fTreeFragment->data.relBeamGate = triggerInfo.trigToBeam; + fTreeFragment->data.relEnableGate = triggerInfo.beamToEnable; fTreeFragment->data.fragTime = { static_cast(fragInfo.fragmentTimestamp) }; fTreeFragment->data.waveformTime = waveformTimestamp.value(); fTreeFragment->data.waveformSize = fragInfo.nSamplesPerChannel; fTreeFragment->data.triggerBits = triggerInfo.bits; + fTreeFragment->data.triggerSource = value(triggerInfo.sourceType); + fTreeFragment->data.gateID = triggerInfo.gateID; fTreeFragment->data.gateCount = triggerInfo.gateCount; fTreeFragment->data.onGlobalTrigger = containsGlobalTrigger(waveformTimestamp, fragInfo.nSamplesPerChannel); @@ -3277,9 +3326,12 @@ void icarus::DaqDecoderICARUSPMT::initFragmentsTree() { tree->Branch("triggerSec", &data.trigger.split.seconds); tree->Branch("triggerNS", &data.trigger.split.nanoseconds); tree->Branch("relBeamGateNS", &data.relBeamGate, "relBeamGateNS/I"); // ROOT 6.24 can't handle `long` neither + tree->Branch("relEnableGateNS", &data.relEnableGate, "relEnableGateNS/I"); // ditto tree->Branch("waveformTime", &data.waveformTime); tree->Branch("waveformSize", &data.waveformSize); tree->Branch("triggerBits", &data.triggerBits); + tree->Branch("triggerSource", &data.triggerSource); + tree->Branch("gateID", &data.gateID); tree->Branch("gateCount", &data.gateCount); tree->Branch("onGlobal", &data.onGlobalTrigger); tree->Branch("minimumBias", &data.minimumBias); From 3184033ceac8a7979505be2f90478068f5e29843 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Wed, 7 Feb 2024 18:49:51 -0600 Subject: [PATCH 14/19] DaqDecoderICARUSPMT module: added trigger location to debug tree --- icaruscode/Decode/DaqDecoderICARUSPMT_module.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc index 5a40cf3fe..5a0aa20fe 100644 --- a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc +++ b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc @@ -401,6 +401,9 @@ namespace icarus { class DaqDecoderICARUSPMT; } * * `triggerSource` (unsigned integer): value of the trigger source bit * (from `sbn::ExtraTriggerInfo::triggerSource`; see * `sbn::bits::triggerSource`). + * * `triggerLocation` (unsigned integer): value of the trigger location bit + * (from `sbn::ExtraTriggerInfo::triggerLocationBits`; see + * `sbn::bits::triggerLocation`). * * `gateID` (unsigned integer): number of this gate from run start * (note: this used to be `gateCount` until around `v09_80_00`). * * `gateCount` (unsigned integer): number of gates from this trigger @@ -800,6 +803,7 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { unsigned int gateCount = 0U; ///< Gate number for this source. sbn::triggerSource sourceType; ///< Trigger source bit. sbn::triggerType triggerType; ///< Type of trigger (minimum bias, majority). + sbn::triggerLocationMask triggerLocation; ///< Where the trigger came from. electronics_time relTriggerTime; ///< Trigger time. electronics_time relBeamGateTime; ///< Beam gate time. }; // TriggerInfo_t @@ -1034,6 +1038,8 @@ class icarus::DaqDecoderICARUSPMT: public art::EDProducer { unsigned int triggerSource = 0x0; ///< Trigger source bit. + unsigned int triggerLocation = 0x0; ///< Trigger location bit mask. + unsigned int gateID = 0U; ///< The number of gates of this source so far. unsigned int gateCount = 0U; ///< The number of gate from run start. @@ -2241,6 +2247,7 @@ auto icarus::DaqDecoderICARUSPMT::fetchTriggerTimestamp , 0U // gateCount , sbn::triggerSource::NBits // sourceType , sbn::triggerType::NBits // triggerType + , sbn::triggerLocationMask{} // triggerLocation , fDetTimings.TriggerTime() // relTriggerTime , fDetTimings.BeamGateTime() // relBeamGateTime }; @@ -2293,6 +2300,7 @@ auto icarus::DaqDecoderICARUSPMT::fetchTriggerTimestamp , extraTrigger.gateCount // gateCount , extraTrigger.sourceType // sourceType , extraTrigger.triggerType // triggerType + , extraTrigger.triggerLocation() // triggerLocation , relTriggerTime // relTriggerTime , relBeamGateTime // relBeamGateTime }; @@ -2863,6 +2871,7 @@ void icarus::DaqDecoderICARUSPMT::fillPMTfragmentTree( fTreeFragment->data.waveformSize = fragInfo.nSamplesPerChannel; fTreeFragment->data.triggerBits = triggerInfo.bits; fTreeFragment->data.triggerSource = value(triggerInfo.sourceType); + fTreeFragment->data.triggerLocation = triggerInfo.triggerLocation.bits; fTreeFragment->data.gateID = triggerInfo.gateID; fTreeFragment->data.gateCount = triggerInfo.gateCount; fTreeFragment->data.onGlobalTrigger From 8ae23bf7874e8501fd5b64a7131a1652e39954ae Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Mon, 26 Feb 2024 23:16:24 -0600 Subject: [PATCH 15/19] Fix to PMT decoder debug tree --- icaruscode/Decode/DaqDecoderICARUSPMT_module.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc index 5a0aa20fe..3b14aae50 100644 --- a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc +++ b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc @@ -3340,6 +3340,7 @@ void icarus::DaqDecoderICARUSPMT::initFragmentsTree() { tree->Branch("waveformSize", &data.waveformSize); tree->Branch("triggerBits", &data.triggerBits); tree->Branch("triggerSource", &data.triggerSource); + tree->Branch("triggerLocation", &data.triggerLocation); tree->Branch("gateID", &data.gateID); tree->Branch("gateCount", &data.gateCount); tree->Branch("onGlobal", &data.onGlobalTrigger); From 6dfb0faa3079fe1bf4f65c2c394b6658cd2d3ce5 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Thu, 29 Feb 2024 19:54:16 -0600 Subject: [PATCH 16/19] Breaking change to ChannelMapping service interface (PMT). The interface for PMT channel mapping is changed: * the main call to receive PMT mapping information was renamed from `getChannelIDPairVec()` to `getPMTchannelInfo()` * the name of the returned type was renamed from `DigitizerChannelChannelIDPairVec` to `PMTdigitizerInfoVec` * more importantly, the data for each channel, which was stored in a triple, `std::tuple` with alias name `DigitizerChannelChannelIDPair`, is now a different object, a record (`struct`) named `PMTChannelInfo_t`. The update instructions are that where a value `t` was obtained as an element of the vector from `getChannelIDPairVec()`, now `t` is obtained as element of the return of `getPMTchannelInfo()` and access needs to be changed as follows: 1. `std::get<0>(t)` becomes `t.digitizerChannelNo` 2. `std::get<1>(t)` becomes `t.channelID` 3. `std::get<2>(t)` becomes `t.laserChannelNo` All code in `icaruscode` has been updated accordingly. --- .../ChannelMapping/ChannelMapDumper.cxx | 35 +++++-------------- .../ChannelMapping/ChannelMapPostGres.cxx | 15 ++++---- .../ChannelMapping/ChannelMapPostGres.h | 3 +- .../ChannelMapping/ChannelMapSQLite.cxx | 8 ++--- .../Decode/ChannelMapping/ChannelMapSQLite.h | 2 +- .../ICARUSChannelMapDataTypes.h | 35 ++++++++++++++----- .../ICARUSChannelMapProviderBase.h | 17 +++++---- .../ICARUSChannelMapProviderBase.txx | 15 ++++---- .../Decode/ChannelMapping/IChannelMapping.h | 2 +- .../IICARUSChannelMapProvider.h | 7 ++-- .../Legacy/ICARUSChannelMapProvider.cxx | 9 ++--- .../Legacy/ICARUSChannelMapProvider.h | 11 +++--- .../Decode/DaqDecoderICARUSPMT_module.cc | 8 ++--- .../PMTconfigurationExtractor.cxx | 10 +++--- .../Calibration/PMTLaserCalibration_module.cc | 4 +-- .../PMTWaveformTimeCorrectionExtractor.cxx | 4 +-- 16 files changed, 93 insertions(+), 92 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx index 608cd476b..58b4c063a 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapDumper.cxx @@ -34,24 +34,6 @@ #include -// ----------------------------------------------------------------------------- -template -struct SortByElement { - - template - bool operator() (TupleA const& A, TupleB const& B) const - { return less(A, B); } - - template - static decltype(auto) key(Tuple const& t) { return std::get(t); } - - template - static bool less(TupleA const& A, TupleB const& B) - { using std::less; return less{}(key(A), key(B)); } - -}; // SortByElement<> - - // ----------------------------------------------------------------------------- /// Helper to split text in rows. class Pager { @@ -175,24 +157,23 @@ void dumpPMTmapping(icarusDB::IICARUSChannelMapProvider const& mapping) { continue; } - icarusDB::DigitizerChannelChannelIDPairVec digitizerChannels - = mapping.getChannelIDPairVec(effFragmentID); + icarusDB::PMTdigitizerInfoVec digitizerChannels + = mapping.getPMTchannelInfo(effFragmentID); - std::sort - (digitizerChannels.begin(), digitizerChannels.end(), SortByElement<1U>{}); + std::sort(digitizerChannels.begin(), digitizerChannels.end()); log << "\n[" << iFragment << "] 0x" << std::hex << fragmentID << std::dec << " includes " << digitizerChannels.size() - << " LArSoft channels between " << std::get<1U>( digitizerChannels.front() ) - << " and " << std::get<1U>( digitizerChannels.back() ) + << " LArSoft channels between " << digitizerChannels.front().channelID + << " and " << digitizerChannels.back().channelID << " [board channel index in brackets]:"; Pager pager{ 8 }; - for(auto const & [ digitizerChannel, channelID, laserChannel ]: digitizerChannels) { + for(auto const & chInfo: digitizerChannels) { if (pager.nextHasNewLine()) log << "\n "; - log << " " << std::setw(3) << channelID - << " [" << std::setw(3) << digitizerChannel << "]"; + log << " " << std::setw(3) << chInfo.channelID + << " [" << std::setw(3) << chInfo.digitizerChannelNo << "]"; } // for channel } // for fragment diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx index 96a7e9415..5633bf5b8 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx @@ -441,7 +441,7 @@ int icarusDB::ChannelMapPostGres::BuildTPCReadoutBoardToChannelMap // --- PMT // ----------------------------------------------------------------------------- int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap - (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const + (PMTFragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const { assert( !fCurrentPMTTimestamp.empty() ); @@ -496,6 +496,9 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap << ") retrieving PMT digitizer from channel mapping database\n"; } + + PMTChannelInfo_t chInfo; + // fragment id unsigned long const fragmentID = getLongValue(tuple, FragmentIDcolumn, &error); @@ -505,7 +508,7 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap } // digitizer channel number - unsigned int const digitizerChannelNo + chInfo.digitizerChannelNo = getLongValue(tuple, DigitizerChannelNoColumn, &error); if (error) { throw myException() << "Error (code: " << error << " on row " << row @@ -513,7 +516,7 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap } // LArsoft channel ID - unsigned int const channelID = getLongValue(tuple, ChannelIDcolumn, &error); + chInfo.channelID = getLongValue(tuple, ChannelIDcolumn, &error); if (error) { throw myException() << "Error (code: " << error << " on row " << row << ") reading PMT channel ID\n"; @@ -526,12 +529,10 @@ int icarusDB::ChannelMapPostGres::BuildPMTFragmentToDigitizerChannelMap << ") retrieving PMT laser channel from channel mapping database\n"; } // will throw on error: - unsigned int const laserChannel - = std::stol(laserChannelLabel.value().substr(2)); + chInfo.laserChannelNo = std::stol(laserChannelLabel.value().substr(2)); // fill the map - fragmentToDigitizerChannelMap[fragmentID].emplace_back - (digitizerChannelNo, channelID, laserChannel); + fragmentToDigitizerChannelMap[fragmentID].push_back(std::move(chInfo)); } // for diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h index c4c1c2ff3..8413b887d 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.h @@ -113,7 +113,8 @@ class icarusDB::ChannelMapPostGres * and the related crate and readout information. * Then define the function interface to fill these data structures */ - virtual int BuildPMTFragmentToDigitizerChannelMap(FragmentToDigitizerChannelMap&) const override; + virtual int BuildPMTFragmentToDigitizerChannelMap + (PMTFragmentToDigitizerChannelMap&) const override; /** diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx index 38db426bb..4723f0bb6 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -528,7 +528,7 @@ int icarusDB::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback ); auto& fragmentToDigitizerChannelMap - = *static_cast(dataOut); + = *static_cast(dataOut); // Start extracting info unsigned int const fragmentID = std::stol(argv[FragmentIDcolumn]); @@ -548,8 +548,8 @@ int icarusDB::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback } // Fill the map - fragmentToDigitizerChannelMap[fragmentID].emplace_back - (digitizerChannelNo, channelID, laserChannel); + fragmentToDigitizerChannelMap[fragmentID].push_back + ({ digitizerChannelNo, channelID, laserChannel }); return 0; } // ...::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback() @@ -557,7 +557,7 @@ int icarusDB::ChannelMapSQLite::buildPMTFragmentToDigitizerChannelMap_callback // ----------------------------------------------------------------------------- int icarusDB::ChannelMapSQLite::BuildPMTFragmentToDigitizerChannelMap - (FragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const + (PMTFragmentToDigitizerChannelMap& fragmentToDigitizerChannelMap) const { // clearing is cleansing fragmentToDigitizerChannelMap.clear(); diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h index 09553aa90..8c7b7fd7d 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.h @@ -100,7 +100,7 @@ class icarusDB::ChannelMapSQLite /// Fill mapping between PMT fragment IDs and the related crate and readout /// information. virtual int BuildPMTFragmentToDigitizerChannelMap - (FragmentToDigitizerChannelMap&) const override; + (PMTFragmentToDigitizerChannelMap&) const override; /// Fill mapping between side CRT hardware mac_address and the simulated diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h index 5d3622c91..ac0802999 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapDataTypes.h @@ -12,6 +12,7 @@ #include #include #include +#include #include // std::size_t @@ -62,18 +63,36 @@ namespace icarusDB { /// @name Data structures for PMT channel mapping. /// @{ - /// A pair of tree: PMT digitizer channel number, LArSoft channel ID - /// and laser channel. - using DigitizerChannelChannelIDPair - = std::tuple; + /// Collection of information pertaining a single PMT. + struct PMTChannelInfo_t { + static constexpr int NoDigitizerChannel + = std::numeric_limits::max(); + static constexpr unsigned int NoChannelID + = std::numeric_limits::max(); + static constexpr unsigned int NoLaserChannel + = std::numeric_limits::max(); + + /// Number of the channel within its digitizer. + unsigned int digitizerChannelNo = NoDigitizerChannel; + + /// LArSoft channel ID. + unsigned int channelID = NoChannelID; + + /// Number of laser channel shining into this PMT. + unsigned int laserChannelNo = NoLaserChannel; + + /// Sorting by channel ID. + constexpr bool operator< (PMTChannelInfo_t const& other) const noexcept + { return channelID < other.channelID; } + + }; // PMTChannelInfo_t /// A sequence of PMT channel information for a single digitizer. - using DigitizerChannelChannelIDPairVec - = std::vector; + using PMTdigitizerInfoVec = std::vector; /// Map from PMT fragment ID to information on all its digitizer channels. - using FragmentToDigitizerChannelMap - = std::map; + using PMTFragmentToDigitizerChannelMap + = std::map; /// @} diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h index 3b3634612..ca76fe56e 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h @@ -193,10 +193,9 @@ class icarusDB::ICARUSChannelMapProviderBase /// Returns the number of PMT fragment IDs known to the mapping. virtual unsigned int nPMTfragmentIDs() const override; - /// Returns a list of triplets: digitizer channel number, channel ID and - /// laser channel. - virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec - (unsigned int) const override; + /// Returns records on all the PMT channels covered by the fragment `ID`. + virtual PMTdigitizerInfoVec const& getPMTchannelInfo (unsigned int ID) const + override; /// @} /// --- END ----- PMT information -------------------------------------------- @@ -251,7 +250,7 @@ class icarusDB::ICARUSChannelMapProviderBase icarusDB::TPCReadoutBoardToChannelMap fTPCReadoutBoardToChannelMap; - icarusDB::FragmentToDigitizerChannelMap fPMTFragmentToDigitizerMap; + icarusDB::PMTFragmentToDigitizerChannelMap fPMTFragmentToDigitizerMap; icarusDB::CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; @@ -266,10 +265,10 @@ class icarusDB::ICARUSChannelMapProviderBase /// Has the channel mapping tool fill the mapping caches. void readFromDatabase(); - /// Returns the list of board channel-to-PMT channel ID mapping within the - /// specified fragment. - /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment - icarusDB::DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry + /// Returns the list of records of all channels in the PMT readout board with + /// the specified fragment. + /// @returns a pointer to the list, or `nullptr` if invalid fragment + icarusDB::PMTdigitizerInfoVec const* findPMTfragmentEntry (unsigned int fragmentID) const; /// Returns an exception signed by this object. diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx index ef6492439..3aea619d8 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx @@ -196,18 +196,15 @@ unsigned int icarusDB::ICARUSChannelMapProviderBase::nPMTfragmentIDs() // ----------------------------------------------------------------------------- template -auto icarusDB::ICARUSChannelMapProviderBase::getChannelIDPairVec - (const unsigned int fragmentID) const - -> DigitizerChannelChannelIDPairVec const& +auto icarusDB::ICARUSChannelMapProviderBase::getPMTchannelInfo + (unsigned int fragmentID) const -> PMTdigitizerInfoVec const& { - mfLogTrace() - << "Call to: ICARUSChannelMapProviderBase::getChannelIDPairVec(" + mfLogTrace() << "Call to: ICARUSChannelMapProviderBase::getPMTchannelInfo(" << fragmentID << ")"; - DigitizerChannelChannelIDPairVec const* digitizerPair - = findPMTfragmentEntry(fragmentID); + PMTdigitizerInfoVec const* digitizerInfo = findPMTfragmentEntry(fragmentID); - if (digitizerPair) return *digitizerPair; + if (digitizerInfo) return *digitizerInfo; throw myException() << "Fragment ID " << fragmentID << " not found in lookup map when looking for PMT channel info.\n"; @@ -255,7 +252,7 @@ auto icarusDB::ICARUSChannelMapProviderBase::getSideCRTCalibrationMap // ----------------------------------------------------------------------------- template auto icarusDB::ICARUSChannelMapProviderBase::findPMTfragmentEntry - (unsigned int fragmentID) const -> DigitizerChannelChannelIDPairVec const* + (unsigned int fragmentID) const -> PMTdigitizerInfoVec const* { auto it = fPMTFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); return (it == fPMTFragmentToDigitizerMap.end())? nullptr: &(it->second); diff --git a/icaruscode/Decode/ChannelMapping/IChannelMapping.h b/icaruscode/Decode/ChannelMapping/IChannelMapping.h index 2ba1c6998..2be79235d 100644 --- a/icaruscode/Decode/ChannelMapping/IChannelMapping.h +++ b/icaruscode/Decode/ChannelMapping/IChannelMapping.h @@ -75,7 +75,7 @@ class icarusDB::IChannelMapping { /// Fill the mapping between PMT Fragment IDs and the related crate and /// readout information. virtual int BuildPMTFragmentToDigitizerChannelMap - (FragmentToDigitizerChannelMap&) const = 0; + (PMTFragmentToDigitizerChannelMap&) const = 0; /// @} // --- END ----- PMT mapping ------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h b/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h index 4319fc65d..9546a2cb9 100644 --- a/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h +++ b/icaruscode/Decode/ChannelMapping/IICARUSChannelMapProvider.h @@ -131,10 +131,9 @@ class icarusDB::IICARUSChannelMapProvider { /// Returns the number of PMT fragment IDs known to the mapping. virtual unsigned int nPMTfragmentIDs() const = 0; - /// Returns a list of triplets: digitizer channel number, channel ID and - /// laser channel. - virtual DigitizerChannelChannelIDPairVec const& getChannelIDPairVec - (unsigned int) const = 0; + /// Returns records on all the PMT channels covered by the fragment `ID`. + virtual PMTdigitizerInfoVec const& getPMTchannelInfo(unsigned int ID) const + = 0; /// @} /// --- END ----- PMT information -------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx index 3debcf8e6..55e709444 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.cxx @@ -261,13 +261,14 @@ unsigned int ICARUSChannelMapProvider::nPMTfragmentIDs() const { } -const DigitizerChannelChannelIDPairVec& ICARUSChannelMapProvider::getChannelIDPairVec(const unsigned int fragmentID) const +/// Returns records on all the PMT channels covered by the fragment `ID`. +const PMTdigitizerInfoVec& ICARUSChannelMapProvider::getPMTchannelInfo(unsigned int fragmentID) const { mf::LogTrace{ "ICARUSChannelMapProvider" } << "Call to: ICARUSChannelMapProvider::getChannelIDPairVec(" << fragmentID << ")"; - DigitizerChannelChannelIDPairVec const* digitizerPair = findPMTfragmentEntry(fragmentID); + PMTdigitizerInfoVec const* digitizerInfo = findPMTfragmentEntry(fragmentID); - if (digitizerPair) return *digitizerPair; + if (digitizerInfo) return *digitizerInfo; throw cet::exception("ICARUSChannelMapProvider") << "Fragment ID " << fragmentID << " not found in lookup map when looking for PMT channel info \n"; } @@ -309,7 +310,7 @@ const DigitizerChannelChannelIDPairVec& ICARUSChannelMapProvider::getChannelIDPa } auto ICARUSChannelMapProvider::findPMTfragmentEntry(unsigned int fragmentID) const - -> DigitizerChannelChannelIDPairVec const* + -> PMTdigitizerInfoVec const* { auto it = fFragmentToDigitizerMap.find(PMTfragmentIDtoDBkey(fragmentID)); return (it == fFragmentToDigitizerMap.end())? nullptr: &(it->second); diff --git a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h index f5bec2b57..7fb23342b 100644 --- a/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h +++ b/icaruscode/Decode/ChannelMapping/Legacy/ICARUSChannelMapProvider.h @@ -56,8 +56,8 @@ class icarusDB::ICARUSChannelMapProvider: public IICARUSChannelMap bool hasPMTDigitizerID(const unsigned int) const override; /// Returns the number of PMT fragment IDs known to the service. - unsigned int nPMTfragmentIDs() const override; - const DigitizerChannelChannelIDPairVec& getChannelIDPairVec(const unsigned int) const override; + unsigned int nPMTfragmentIDs() const override; + const PMTdigitizerInfoVec& getPMTchannelInfo(unsigned int) const override; // Section for CRT channel mapping unsigned int getSimMacAddress (const unsigned int) const override; @@ -87,7 +87,7 @@ class icarusDB::ICARUSChannelMapProvider: public IICARUSChannelMap TPCReadoutBoardToChannelMap fReadoutBoardToChannelMap; - FragmentToDigitizerChannelMap fFragmentToDigitizerMap; + PMTFragmentToDigitizerChannelMap fFragmentToDigitizerMap; CRTChannelIDToHWtoSimMacAddressPairMap fCRTChannelIDToHWtoSimMacAddressPairMap; @@ -102,9 +102,10 @@ class icarusDB::ICARUSChannelMapProvider: public IICARUSChannelMap void readFromDatabase(); - /// Returns the list of board channel-to-PMT channel ID mapping within the specified fragment. + /// Returns the list of records of all channels in the PMT readout board with + /// the specified fragment. /// @returns a pointer to the mapping list, or `nullptr` if invalid fragment - DigitizerChannelChannelIDPairVec const* findPMTfragmentEntry + PMTdigitizerInfoVec const* findPMTfragmentEntry (unsigned int fragmentID) const; diff --git a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc index 3b14aae50..52a7ef929 100644 --- a/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc +++ b/icaruscode/Decode/DaqDecoderICARUSPMT_module.cc @@ -2450,8 +2450,8 @@ auto icarus::DaqDecoderICARUSPMT::createFragmentWaveforms( std::optional diagOut; if (fDiagnosticOutput) diagOut.emplace(fLogCategory); - icarusDB::DigitizerChannelChannelIDPairVec const& digitizerChannelVec - = fChannelMap.getChannelIDPairVec + icarusDB::PMTdigitizerInfoVec const& digitizerChannelVec + = fChannelMap.getPMTchannelInfo (effectivePMTboardFragmentID(fragInfo.fragmentID)) ; @@ -2465,8 +2465,8 @@ auto icarus::DaqDecoderICARUSPMT::createFragmentWaveforms( auto channelNumberToChannel = [&digitizerChannelVec](unsigned short int channelNumber) -> raw::Channel_t { - for (auto const & [ chNo, chID, _ ]: digitizerChannelVec) // too pythonic? - if (chNo == channelNumber) return chID; + for (icarusDB::PMTChannelInfo_t const & chInfo: digitizerChannelVec) + if (chInfo.digitizerChannelNo == channelNumber) return chInfo.channelID; return sbn::V1730channelConfiguration::NoChannelID; }; diff --git a/icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.cxx b/icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.cxx index 419b48119..95376bcbc 100644 --- a/icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.cxx +++ b/icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.cxx @@ -160,17 +160,19 @@ sbn::PMTconfiguration icarus::PMTconfigurationExtractor::finalize continue; } - icarusDB::DigitizerChannelChannelIDPairVec const& digitizerChannelVec - = fChannelMap->getChannelIDPairVec(fragmentID); + icarusDB::PMTdigitizerInfoVec const& digitizerChannelVec + = fChannelMap->getPMTchannelInfo(fragmentID); // finds the channel ID matching the specified channel number of this board auto const toChannelID = [&channelIDs=digitizerChannelVec] (short unsigned int channelNo) { auto const it = std::find_if(channelIDs.begin(), channelIDs.end(), - [channelNo](auto const& p){ return std::get<0U>(p) == channelNo; }); + [channelNo](auto const& p) + { return p.digitizerChannelNo == channelNo; } + ); return (it != channelIDs.end()) - ? std::get<1U>(*it) + ? it->channelID : sbn::V1730channelConfiguration::NoChannelID ; }; diff --git a/icaruscode/PMT/Calibration/PMTLaserCalibration_module.cc b/icaruscode/PMT/Calibration/PMTLaserCalibration_module.cc index 1552059be..cc0c6d889 100644 --- a/icaruscode/PMT/Calibration/PMTLaserCalibration_module.cc +++ b/icaruscode/PMT/Calibration/PMTLaserCalibration_module.cc @@ -189,9 +189,9 @@ void pmtcalo::PMTLaserCalibration::beginJob() for( std::size_t fragId=0; fragId<24; fragId++ ){ - for( auto const & [_,channelId,laserChannel] : fChannelMap.getChannelIDPairVec(fragId) ){ + for( icarusDB::PMTChannelInfo_t const & chInfo: fChannelMap.getPMTchannelInfo(fragId) ){ - if( laserChannel == fLaserChannel ){ fIlluminatedChannels.push_back( channelId ); }; + if( chInfo.laserChannelNo == fLaserChannel ){ fIlluminatedChannels.push_back( chInfo.channelID ); }; } diff --git a/icaruscode/Timing/PMTWaveformTimeCorrectionExtractor.cxx b/icaruscode/Timing/PMTWaveformTimeCorrectionExtractor.cxx index 411700f36..72de9db6d 100644 --- a/icaruscode/Timing/PMTWaveformTimeCorrectionExtractor.cxx +++ b/icaruscode/Timing/PMTWaveformTimeCorrectionExtractor.cxx @@ -203,9 +203,9 @@ void icarus::timing::PMTWaveformTimeCorrectionExtractor::findWaveformTimeCorrect // we now access the channels that we need for( auto const & crateFragID : itCrateFragment->second ){ - for( auto const & mapRow : fChannelMap.getChannelIDPairVec(crateFragID) ){ + for( auto const & mapRow : fChannelMap.getPMTchannelInfo(crateFragID) ){ - unsigned int channelID = std::get<1U>(mapRow); + unsigned int channelID = mapRow.channelID; double cableDelay = 0; From f5dc6346eb787bcddf55979c4801185672d2f6fd Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sat, 2 Mar 2024 00:10:14 -0600 Subject: [PATCH 17/19] Missed the PostgreSQL service entirely --- icaruscode/Decode/ChannelMapping/CMakeLists.txt | 8 ++++++++ .../ChannelMapping/ICARUSChannelMapPostGres_service.cc | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/icaruscode/Decode/ChannelMapping/CMakeLists.txt b/icaruscode/Decode/ChannelMapping/CMakeLists.txt index 1777854e4..770b8d084 100644 --- a/icaruscode/Decode/ChannelMapping/CMakeLists.txt +++ b/icaruscode/Decode/ChannelMapping/CMakeLists.txt @@ -40,6 +40,14 @@ cet_build_plugin(ICARUSChannelMapSQLite art::service messagefacility::headers ) +cet_build_plugin(ICARUSChannelMapPostGres art::service + LIBRARIES + icaruscode::Decode_ChannelMapping + art::Framework_Principal + messagefacility::MF_MessageLogger + messagefacility::headers + ) + add_subdirectory("Legacy") cet_make_exec(NAME "ChannelMapDumper" diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc index bb559c025..acb43b051 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGres_service.cc @@ -6,6 +6,7 @@ // ICARUS libraries #include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapPostGresProvider.h" +#include "icaruscode/Decode/ChannelMapping/IICARUSChannelMap.h" #include "icaruscode/Decode/ChannelMapping/RunPeriods.h" // framework libraries @@ -51,7 +52,7 @@ namespace icarusDB { class ICARUSChannelMapPostGres; } * */ class icarusDB::ICARUSChannelMapPostGres - : public IICARUSChannelMap, public ICARUSChannelMapPostGresProvider, + : public IICARUSChannelMap, public ICARUSChannelMapPostGresProvider { /// Prepares the mapping for the specified run. From 357a6446ce2ea824c6a376ca7765d805c7ab60f4 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sun, 3 Mar 2024 00:07:06 -0600 Subject: [PATCH 18/19] Renamed template implementation file from .txx to .tcc Because otherwise the CET build system does not install it and standalone ROOT/cppyy can't load the class. --- icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h | 2 +- ...nnelMapProviderBase.txx => ICARUSChannelMapProviderBase.tcc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename icaruscode/Decode/ChannelMapping/{ICARUSChannelMapProviderBase.txx => ICARUSChannelMapProviderBase.tcc} (100%) diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h index ca76fe56e..66f511e0e 100644 --- a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h +++ b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.h @@ -282,7 +282,7 @@ class icarusDB::ICARUSChannelMapProviderBase // --- template implementation // ----------------------------------------------------------------------------- -#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx" +#include "icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.tcc" // ----------------------------------------------------------------------------- diff --git a/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx b/icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.tcc similarity index 100% rename from icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.txx rename to icaruscode/Decode/ChannelMapping/ICARUSChannelMapProviderBase.tcc From aefe7390f54f6a254d754591661e31873723e528 Mon Sep 17 00:00:00 2001 From: Gianluca Petrillo Date: Sun, 3 Mar 2024 00:08:55 -0600 Subject: [PATCH 19/19] Channel mapping: removed some hard-coded mapping Also this fixes another bug that I had missed, again from copy&paste. Some information that is not currently in the database is still hard-coded. --- .../ChannelMapping/ChannelMapPostGres.cxx | 156 ++++++------------ .../ChannelMapping/ChannelMapSQLite.cxx | 140 ++++------------ 2 files changed, 85 insertions(+), 211 deletions(-) diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx index 5633bf5b8..a89b1ec9a 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapPostGres.cxx @@ -175,112 +175,32 @@ icarusDB::details::WDADataset icarusDB::ChannelMapPostGres::GetCRTCaldata int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap (TPCFragmentIDToReadoutIDMap& fragmentBoardMap) const { - const unsigned int tpcIdentifier(0x00001000); + using namespace std::string_literals; + constexpr unsigned int tpcIdentifier(0x00001000); // Recover the data from the database std::string const name { "icarus_hw_readoutboard" }; std::string const dataType { "readout_boards" }; details::WDADataset dataset = GetDataset(name, fDBURL, dataType); - // Include a by hand mapping of fragment ID to crate - static std::map const flangeIDToCrateMap = { - { 19, "WW01T" }, - { 68, "WW01M" }, - { 41, "WW01B" }, - { 11, "WW02" }, - { 17, "WW03" }, - { 36, "WW04" }, - { 18, "WW05" }, - { 58, "WW06" }, - { 71, "WW07" }, - { 14, "WW08" }, - { 25, "WW09" }, - { 34, "WW10" }, - { 67, "WW11" }, - { 33, "WW12" }, - { 87, "WW13" }, - { 10, "WW14" }, - { 59, "WW15" }, - { 95, "WW16" }, - { 22, "WW17" }, - { 91, "WW18" }, - { 61, "WW19" }, - { 55, "WW20T" }, - { 97, "WW20M" }, - { 100, "WW20B" }, - { 83, "WE01T" }, - { 85, "WE01M" }, - { 7, "WE01B" }, - { 80, "WE02" }, - { 52, "WE03" }, - { 32, "WE04" }, - { 70, "WE05" }, - { 74, "WE06" }, - { 46, "WE07" }, - { 81, "WE08" }, - { 63, "WE09" }, - { 30, "WE10" }, - { 51, "WE11" }, - { 90, "WE12" }, - { 23, "WE13" }, - { 93, "WE14" }, - { 92, "WE15" }, - { 88, "WE16" }, - { 73, "WE17" }, - { 1, "WE18" }, - { 66, "WE19" }, - { 48, "WE20T" }, - { 13, "WE20M" }, - { 56, "WE20B" }, - { 94, "EW01T" }, - { 77, "EW01M" }, - { 72, "EW01B" }, - { 65, "EW02" }, - { 4, "EW03" }, - { 89, "EW04" }, - { 37, "EW05" }, - { 76, "EW06" }, - { 49, "EW07" }, - { 60, "EW08" }, - { 21, "EW09" }, - { 6, "EW10" }, - { 62, "EW11" }, - { 2, "EW12" }, - { 29, "EW13" }, - { 44, "EW14" }, - { 9, "EW15" }, - { 31, "EW16" }, - { 98, "EW17" }, - { 38, "EW18" }, - { 99, "EW19" }, - { 53, "EW20T" }, - { 82, "EW20M" }, - { 35, "EW20B" }, - { 96, "EE01T" }, - { 28, "EE01M" }, - { 16, "EE01T" }, - { 69, "EE02" }, - { 20, "EE03" }, - { 79, "EE04" }, - { 50, "EE05" }, - { 45, "EE06" }, - { 84, "EE07" }, - { 42, "EE08" }, - { 39, "EE09" }, - { 26, "EE10" }, - { 64, "EE11" }, - { 43, "EE12" }, - { 47, "EE13" }, - { 15, "EE14" }, - { 3, "EE15" }, - { 27, "EE16" }, - { 24, "EE17" }, - { 40, "EE18" }, - { 75, "EE19" }, - { 86, "EE20T" }, - { 54, "EE20M" }, - { 8, "EE20B" } - }; // flangeIDToCrateMap[] + // Include a by hand mapping of fragment ID to position in "corner" chimneys + // (this information is not present in the database) + static std::map const flangeIDsuffixes = { + { 19, "T"s }, { 68, "M"s }, { 41, "B"s }, // WW01 + { 55, "T"s }, { 97, "M"s }, { 100, "B"s }, // WW20 + { 83, "T"s }, { 85, "M"s }, { 7, "B"s }, // WE01 + { 48, "T"s }, { 13, "M"s }, { 56, "B"s }, // WE20 + { 94, "T"s }, { 77, "M"s }, { 72, "B"s }, // EW01 + { 53, "T"s }, { 82, "M"s }, { 35, "B"s }, // EW20 + { 96, "T"s }, { 28, "M"s }, { 16, "B"s }, // EE01 + { 86, "T"s }, { 54, "M"s }, { 8, "B"s } // EE20 + }; // flangeIDsuffixes[] + + auto const flangeSuffix = [](int flangeID) -> std::string + { + auto const it = flangeIDsuffixes.find(flangeID); + return (it == flangeIDsuffixes.end())? std::string{}: it->second; + }; // Loop through the data to recover the channels; // find the position of the columns we need from the first row @@ -292,10 +212,13 @@ int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap */ // technical detail: `PositionFinder` uses `operator==` to compare, and the // input is C-strings; we force the other term of comparison to C++ strings - using namespace std::string_literals; - auto const [ ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn ] - = details::WDAPositionFinder{ getTuple(dataset, 0) } - ("readout_board_id"s, "flange_id"s, "fragement_id"s ); + auto const [ + ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn, + TPCIDcolumn, ChimneyNoColumn + ] = details::WDAPositionFinder{ getTuple(dataset, 0) }( + "readout_board_id"s, "flange_id"s, "fragement_id"s, + "tpc_id"s, "chimney_number"s + ); for (int const row: util::counter(1, getNtuples(dataset))) { // Recover the row @@ -319,14 +242,35 @@ int icarusDB::ChannelMapPostGres::BuildTPCFragmentIDToReadoutIDMap if (!(fragmentID & tpcIdentifier)) continue; if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) { + unsigned int const flangeID = getLongValue(tuple, FlangeIDcolumn, &error); if (error) { throw myException() << "Error (code: " << error << " on row " << row << ") retrieving TPC flange ID from channel mapping database\n"; } - fragmentBoardMap[fragmentID].first = flangeIDToCrateMap.at(flangeID); - } + + // build the flange name + Expected const chimneyNoString = getStringFromTuple(tuple, ChimneyNoColumn); + if (!chimneyNoString) { + throw myException() << "Error (code: " << chimneyNoString.code() + << " on row " << row + << ") retrieving chimney number from channel mapping database\n"; + } + + Expected const TPCIDstring = getStringFromTuple(tuple, TPCIDcolumn); + if (!TPCIDstring) { + throw myException() << "Error (code: " << TPCIDstring.code() + << " on row " << row + << ") retrieving TPC tag from channel mapping database\n"; + } + + std::string const flangeTag = TPCIDstring.value() + + std::string(std::max(0, 2-(int)chimneyNoString.value().length()), '0') + + chimneyNoString.value() + flangeSuffix(flangeID); + + fragmentBoardMap[fragmentID].first = flangeTag; + } // if first time with this flange unsigned int const readoutID = getLongValue(tuple, ReadoutBoardIDcolumn, &error); diff --git a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx index 4723f0bb6..355e9e66f 100644 --- a/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx +++ b/icaruscode/Decode/ChannelMapping/ChannelMapSQLite.cxx @@ -275,113 +275,35 @@ int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback // technical detail: `PositionFinder` uses `operator==` to compare, and the // input is C-strings; we force the other term of comparison to C++ strings using namespace std::string_literals; - auto const [ ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn ] - = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} } - ("readout_board_id"s, "flange_id"s, "fragement_id"s ); + auto const [ + ReadoutBoardIDcolumn, FlangeIDcolumn, FragmentIDcolumn, + TPCIDcolumn, ChimneyNoColumn + ] = icarus::ns::util::PositionFinder{ gsl::span{azColName, (unsigned) argc} }( + "readout_board_id"s, "flange_id"s, "fragement_id"s, + "tpc_id"s, "chimney_number"s + ); auto& fragmentBoardMap = *static_cast(dataOut); - // Include a by hand mapping of fragment ID to crate - // Note that we now know we can get this from the "flanges" table... so an upgrade coming soon... - static std::map const flangeIDToCrateMap = { - { 19, "WW01T" }, - { 68, "WW01M" }, - { 41, "WW01B" }, - { 11, "WW02" }, - { 17, "WW03" }, - { 36, "WW04" }, - { 18, "WW05" }, - { 58, "WW06" }, - { 71, "WW07" }, - { 14, "WW08" }, - { 25, "WW09" }, - { 34, "WW10" }, - { 67, "WW11" }, - { 33, "WW12" }, - { 87, "WW13" }, - { 10, "WW14" }, - { 59, "WW15" }, - { 95, "WW16" }, - { 22, "WW17" }, - { 91, "WW18" }, - { 61, "WW19" }, - { 55, "WW20T" }, - { 97, "WW20M" }, - { 100, "WW20B" }, - { 83, "WE01T" }, - { 85, "WE01M" }, - { 7, "WE01B" }, - { 80, "WE02" }, - { 52, "WE03" }, - { 32, "WE04" }, - { 70, "WE05" }, - { 74, "WE06" }, - { 46, "WE07" }, - { 81, "WE08" }, - { 63, "WE09" }, - { 30, "WE10" }, - { 51, "WE11" }, - { 90, "WE12" }, - { 23, "WE13" }, - { 93, "WE14" }, - { 92, "WE15" }, - { 88, "WE16" }, - { 73, "WE17" }, - { 1, "WE18" }, - { 66, "WE19" }, - { 48, "WE20T" }, - { 13, "WE20M" }, - { 56, "WE20B" }, - { 94, "EW01T" }, - { 77, "EW01M" }, - { 72, "EW01B" }, - { 65, "EW02" }, - { 4, "EW03" }, - { 89, "EW04" }, - { 37, "EW05" }, - { 76, "EW06" }, - { 49, "EW07" }, - { 60, "EW08" }, - { 21, "EW09" }, - { 6, "EW10" }, - { 62, "EW11" }, - { 2, "EW12" }, - { 29, "EW13" }, - { 44, "EW14" }, - { 9, "EW15" }, - { 31, "EW16" }, - { 98, "EW17" }, - { 38, "EW18" }, - { 99, "EW19" }, - { 53, "EW20T" }, - { 82, "EW20M" }, - { 35, "EW20B" }, - { 96, "EE01T" }, - { 28, "EE01M" }, - { 16, "EE01T" }, - { 69, "EE02" }, - { 20, "EE03" }, - { 79, "EE04" }, - { 50, "EE05" }, - { 45, "EE06" }, - { 84, "EE07" }, - { 42, "EE08" }, - { 39, "EE09" }, - { 26, "EE10" }, - { 64, "EE11" }, - { 43, "EE12" }, - { 47, "EE13" }, - { 15, "EE14" }, - { 3, "EE15" }, - { 27, "EE16" }, - { 24, "EE17" }, - { 40, "EE18" }, - { 75, "EE19" }, - { 86, "EE20T" }, - { 54, "EE20M" }, - { 8, "EE20B" } - }; // flangeIDToCrateMap[] + // Include a by hand mapping of fragment ID to position in "corner" chimneys + // (this information is not present in the database) + static std::map const flangeIDsuffixes = { + { 19, "T"s }, { 68, "M"s }, { 41, "B"s }, // WW01 + { 55, "T"s }, { 97, "M"s }, { 100, "B"s }, // WW20 + { 83, "T"s }, { 85, "M"s }, { 7, "B"s }, // WE01 + { 48, "T"s }, { 13, "M"s }, { 56, "B"s }, // WE20 + { 94, "T"s }, { 77, "M"s }, { 72, "B"s }, // EW01 + { 53, "T"s }, { 82, "M"s }, { 35, "B"s }, // EW20 + { 96, "T"s }, { 28, "M"s }, { 16, "B"s }, // EE01 + { 86, "T"s }, { 54, "M"s }, { 8, "B"s } // EE20 + }; // flangeIDsuffixes[] + + auto const flangeSuffix = [](int flangeID) -> std::string + { + auto const it = flangeIDsuffixes.find(flangeID); + return (it == flangeIDsuffixes.end())? std::string{}: it->second; + }; unsigned int const fragmentID = std::stol(argv[FragmentIDcolumn], nullptr, 16); @@ -389,8 +311,16 @@ int icarusDB::ChannelMapSQLite::buildTPCFragmentIDToReadoutIDMap_callback if (fragmentID & tpcIdentifier) { if (fragmentBoardMap.find(fragmentID) == fragmentBoardMap.end()) { unsigned int const flangeID = std::stol(argv[FlangeIDcolumn]); - fragmentBoardMap[fragmentID].first = flangeIDToCrateMap.at(flangeID); - } + + // build the flange name + std::string const chimneyNoString = argv[ChimneyNoColumn]; + std::string const TPCIDstring = argv[TPCIDcolumn]; + std::string const flangeTag = TPCIDstring + + std::string(std::max(0, 2 - (int)chimneyNoString.length()), '0') + + chimneyNoString + flangeSuffix(flangeID); + + fragmentBoardMap[fragmentID].first = flangeTag; + } // if first time with this flange unsigned int const readoutID = std::stol(argv[ReadoutBoardIDcolumn]); fragmentBoardMap[fragmentID].second.emplace_back(readoutID);