diff --git a/Detectors/FIT/macros/CMakeLists.txt b/Detectors/FIT/macros/CMakeLists.txt index a6bf1799a5dde..9be9eb6a7e8d4 100644 --- a/Detectors/FIT/macros/CMakeLists.txt +++ b/Detectors/FIT/macros/CMakeLists.txt @@ -49,5 +49,21 @@ o2_add_test_root_macro(readAlignParam.C PUBLIC_LINK_LIBRARIES O2::CCDB LABELS fit) +o2_add_test_root_macro(compareLUT.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsFIT + O2::CCDB + LABELS fit) + +o2_add_test_root_macro(convertLUTCSVtoROOT.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsFIT + O2::CCDB + O2::CommonUtils + LABELS fit) + +o2_add_test_root_macro(fetchLUT.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsFIT + O2::CCDB + LABELS fit) + o2_data_file(COPY readFITDCSdata.C DESTINATION Detectors/FIT/macros/) o2_data_file(COPY readFITDeadChannelMap.C DESTINATION Detectors/FIT/macros/) \ No newline at end of file diff --git a/Detectors/FIT/macros/compareLUT.C b/Detectors/FIT/macros/compareLUT.C new file mode 100644 index 0000000000000..f71a7aff4d850 --- /dev/null +++ b/Detectors/FIT/macros/compareLUT.C @@ -0,0 +1,99 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include + +R__LOAD_LIBRARY(libO2CommonUtils) +R__LOAD_LIBRARY(libO2DataFormatsFIT) + +#include "CommonUtils/ConfigurableParamHelper.h" +#include "DataFormatsFIT/LookUpTable.h" +#include "Framework/Logger.h" +#include "CommonConstants/LHCConstants.h" +#endif + +std::vector readLUTFromFile(const std::string filePath, const std::string objectName) +{ + TFile file(filePath.c_str(), "READ"); + if (file.IsOpen() == false) { + LOGP(fatal, "Failed to open {}", filePath); + } + LOGP(info, "Successfully opened {}", filePath); + + std::vector* lut = nullptr; + file.GetObject>(objectName.c_str(), lut); + + if (lut == nullptr) { + LOGP(fatal, "Failed to read object {}", objectName); + } + LOGP(info, "Successfully get {} object", objectName); + + std::vector lutCopy = *lut; + file.Close(); + + return std::move(lutCopy); +} + +inline bool operator==(const o2::fit::EntryFEE& lhs, const o2::fit::EntryFEE& rhs) +{ + auto comparer = [](const o2::fit::EntryFEE& e) { + return std::tie( + e.mEntryCRU.mLinkID, e.mEntryCRU.mEndPointID, e.mEntryCRU.mCRUID, e.mEntryCRU.mFEEID, + e.mChannelID, e.mLocalChannelID, e.mModuleType, e.mModuleName, + e.mBoardHV, e.mChannelHV, e.mSerialNumberMCP, e.mCableHV, e.mCableSignal); + }; + return comparer(lhs) == comparer(rhs); +} + +void compareLUT(const std::string fileA, const std::string fileB, bool compareEvenForDifferentSize = false, const std::string objectName = "LookupTable") +{ + std::vector lutA = readLUTFromFile(fileA, objectName); + std::vector lutB = readLUTFromFile(fileB, objectName); + + bool lutAreSame = true; + + if (lutA.size() != lutB.size()) { + LOGP(error, "The LUT vary in size: {} for {} vs {} for {}", lutA.size(), fileA, lutB.size(), fileB); + lutAreSame = false; + if (compareEvenForDifferentSize == false) { + return; + } + } + + size_t size = (lutA.size() < lutB.size()) ? lutA.size() : lutB.size(); + + std::cout << "--- Comparision ---" << std::endl; + + for (size_t idx = 0; idx < size; idx++) { + if (lutA[idx] == lutB[idx]) { + continue; + } else { + std::cout << "Entry " << idx << " in " << fileA << " entry: " << lutA[idx] << std::endl; + std::cout << "Entry " << idx << " in " << fileB << " entry: " << lutB[idx] << std::endl; + lutAreSame = false; + } + } + + for (size_t idx = size; idx < lutA.size(); idx++) { + std::cout << "Extra entry " << idx << " in " << fileA << ": " << lutA[idx] << std::endl; + } + + for (size_t idx = size; idx < lutB.size(); idx++) { + std::cout << "Extra entry " << idx << " in " << fileB << ": " << lutB[idx] << std::endl; + } + + if (lutAreSame) { + std::cout << "LUTs are the same!" << std::endl; + } else { + std::cout << "LUTs are different!" << std::endl; + } +} diff --git a/Detectors/FIT/macros/convertLUTCSVtoROOT.C b/Detectors/FIT/macros/convertLUTCSVtoROOT.C new file mode 100644 index 0000000000000..bf4fc6a07ef4e --- /dev/null +++ b/Detectors/FIT/macros/convertLUTCSVtoROOT.C @@ -0,0 +1,91 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#include + +R__LOAD_LIBRARY(libO2CommonUtils) +R__LOAD_LIBRARY(libO2CCDB) +R__LOAD_LIBRARY(libO2DataFormatsFIT) + +#include "DataFormatsFIT/LookUpTable.h" +#include "Framework/Logger.h" +#include "CommonConstants/LHCConstants.h" +#endif + +void saveToRoot(std::vector& lut, string_view path); + +void convertLUTCSVtoROOT(const std::string csvFilePath, const std::string rootFilePath) +{ + std::vector lut; + std::ifstream lutCSV(csvFilePath); + if (lutCSV.is_open() == false) { + LOGP(error, "Failed to open {}", csvFilePath); + return; + } + + std::string line; + std::getline(lutCSV, line); + std::map headerMap; + + auto headersView = std::string_view(line) | std::views::split(','); + + int index = 0; + for (auto&& rng : headersView) { + std::string columnName(rng.begin(), rng.end()); + headerMap[columnName] = index++; + } + + while (std::getline(lutCSV, line)) { + if (line.size() == 0) { + return; + } + o2::fit::EntryFEE entry; + auto fieldViews = std::string_view(line) | std::views::split(','); + std::vector parsedLine; + for (auto&& view : fieldViews) { + parsedLine.emplace_back(view.begin(), view.end()); + } + if (parsedLine.size() < headerMap.size()) { + LOGP(error, "Ill-formed line: {}", line); + return; + } + + entry.mEntryCRU.mLinkID = std::stoi(parsedLine[headerMap.at("LinkID")]); + entry.mEntryCRU.mEndPointID = std::stoi(parsedLine[headerMap.at("EndPointID")]); + entry.mEntryCRU.mCRUID = std::stoi(parsedLine[headerMap.at("CRUID")]); + entry.mEntryCRU.mFEEID = std::stoi(parsedLine[headerMap.at("FEEID")]); + + entry.mModuleType = parsedLine[headerMap.at("ModuleType")]; + entry.mLocalChannelID = parsedLine[headerMap.at("LocalChannelID")]; + entry.mChannelID = parsedLine[headerMap.at("channel #")]; + entry.mModuleName = parsedLine[headerMap.at("Module")]; + entry.mBoardHV = parsedLine[headerMap.at("HV board")]; + entry.mChannelHV = parsedLine[headerMap.at("HV channel")]; + entry.mSerialNumberMCP = parsedLine[headerMap.at("MCP S/N")]; + entry.mCableHV = parsedLine[headerMap.at("HV cable")]; + entry.mCableSignal = parsedLine[headerMap.at("signal cable")]; + lut.emplace_back(entry); + } + saveToRoot(lut, rootFilePath); +} + +void saveToRoot(std::vector& lut, string_view path) +{ + TFile file(path.data(), "RECREATE"); + if (file.IsOpen() == false) { + LOGP(fatal, "Failed to open file {}", path.data()); + } + + file.WriteObject(&lut, "LookupTable"); + file.Close(); +} \ No newline at end of file diff --git a/Detectors/FIT/macros/fetchLUT.C b/Detectors/FIT/macros/fetchLUT.C new file mode 100644 index 0000000000000..3775421e672b8 --- /dev/null +++ b/Detectors/FIT/macros/fetchLUT.C @@ -0,0 +1,103 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#include + +R__LOAD_LIBRARY(libO2CommonUtils) +R__LOAD_LIBRARY(libO2CCDB) +R__LOAD_LIBRARY(libO2DataFormatsFIT) + +#include "CommonUtils/ConfigurableParamHelper.h" +#include "DataFormatsFIT/LookUpTable.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/CCDBTimeStampUtils.h" +#include "Framework/Logger.h" +#include "CommonConstants/LHCConstants.h" + +#endif + +void saveToCSV(const std::vector& lut, string_view path); +void saveToRoot(std::shared_ptr> lut, string_view path); + +void fetchLUT(const std::string ccdbUrl, const std::string detector, long timestamp = -1, const std::string fileName = "", bool asCsv = true) +{ + o2::ccdb::CcdbApi ccdbApi; + ccdbApi.init(ccdbUrl); + const std::string ccdbPath = detector + "/Config/LookupTable"; + std::map metadata; + + if (timestamp == -1) { + timestamp = o2::ccdb::getCurrentTimestamp(); + } + + std::shared_ptr> lut(ccdbApi.retrieveFromTFileAny>(ccdbPath, metadata, timestamp)); + + if (!lut) { + LOGP(error, "LUT object not found in {}/{} for timestamp {}.", ccdbUrl, ccdbPath, timestamp); + return; + } else { + LOGP(info, "Successfully fetched LUT for {} from {}", detector, ccdbUrl); + } + + std::cout << detector << " lookup table: " << std::endl; + for (const auto& entry : (*lut)) { + std::cout << entry << std::endl; + } + + if (fileName.empty()) { + return; + } + + if (asCsv) { + saveToCSV(*lut, fileName); + } else { + saveToRoot(lut, fileName); + } +} + +void saveToCSV(const std::vector& lut, string_view path) +{ + std::ofstream ofs(path.data()); + if (!ofs.is_open()) { + LOGP(error, "Cannot open file for writing: {}", path); + return; + } + ofs << "LinkID,EndPointID,CRUID,FEEID,ModuleType,LocalChannelID,channel #,Module,HV board,HV channel,MCP S/N,HV cable,signal cable\n"; + for (const auto& entry : lut) { + ofs << entry.mEntryCRU.mLinkID << "," + << entry.mEntryCRU.mEndPointID << "," + << entry.mEntryCRU.mCRUID << "," + << entry.mEntryCRU.mFEEID << "," + << entry.mModuleType << "," + << entry.mLocalChannelID << "," + << entry.mChannelID << "," + << entry.mModuleName << "," + << entry.mBoardHV << "," + << entry.mChannelHV << "," + << entry.mSerialNumberMCP << "," + << entry.mCableHV << "," + << entry.mCableSignal << "\n"; + } + ofs.close(); +} + +void saveToRoot(std::shared_ptr> lut, string_view path) +{ + TFile file(path.data(), "RECREATE"); + if (file.IsOpen() == false) { + LOGP(fatal, "Failed to open file {}", path.data()); + } + + file.WriteObject(lut.get(), "LookupTable"); + file.Close(); +} \ No newline at end of file