diff --git a/Detectors/TRD/calibration/CMakeLists.txt b/Detectors/TRD/calibration/CMakeLists.txt index d879d10d56112..e2f66dce6cb03 100644 --- a/Detectors/TRD/calibration/CMakeLists.txt +++ b/Detectors/TRD/calibration/CMakeLists.txt @@ -15,15 +15,30 @@ o2_add_library(TRDCalibration SOURCES src/TrackBasedCalib.cxx src/CalibratorVdExB.cxx src/KrClusterFinder.cxx + src/DCSProcessor.cxx PUBLIC_LINK_LIBRARIES O2::TRDBase O2::DataFormatsTRD O2::DataFormatsGlobalTracking O2::DetectorsBase O2::DetectorsCalibration O2::MathUtils - O2::GPUTracking) + O2::GPUTracking + O2::DetectorsDCS) o2_target_root_dictionary(TRDCalibration HEADERS include/TRDCalibration/TrackBasedCalib.h include/TRDCalibration/CalibratorVdExB.h - include/TRDCalibration/KrClusterFinder.h) + include/TRDCalibration/KrClusterFinder.h + include/TRDCalibration/DCSProcessor.h) + +o2_add_executable(trd-dcs-sim-workflow + COMPONENT_NAME calibration + SOURCES workflow/trd-dcs-sim-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::DCStestWorkflow) + +o2_add_executable(trd-dcs-workflow + COMPONENT_NAME calibration + SOURCES workflow/trd-dcs-data-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::TRDCalibration + O2::DetectorsDCS) diff --git a/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h b/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h new file mode 100644 index 0000000000000..4776ff85e27b8 --- /dev/null +++ b/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h @@ -0,0 +1,106 @@ +// 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. + +#ifndef DETECTOR_TRDDCSPROCESSOR_H_ +#define DETECTOR_TRDDCSPROCESSOR_H_ + +#include "Framework/Logger.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DeliveryType.h" +#include "CCDB/CcdbObjectInfo.h" +#include "CommonUtils/MemFileHelper.h" +#include "CCDB/CcdbApi.h" +#include +#include +#include +#include + +/// @brief Class to process TRD DCS data points + +namespace o2 +{ +namespace trd +{ + +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; + +struct TRDDCSMinMaxMeanInfo { + float minValue{0.f}; // min value seen by the TRD DCS processor + float maxValue{0.f}; // max value seen by the TRD DCS processor + float meanValue{0.f}; // mean value seen by the TRD DCS processor + int nPoints{0}; // number of values seen by the TRD DCS processor + + void print() const; + void addPoint(float value); + + ClassDefNV(TRDDCSMinMaxMeanInfo, 1); +}; + +class DCSProcessor +{ + + public: + using TFType = uint64_t; + using CcdbObjectInfo = o2::ccdb::CcdbObjectInfo; + + DCSProcessor() = default; + ~DCSProcessor() = default; + + void init(const std::vector& pids); + + int process(const gsl::span dps); + int processDP(const DPCOM& dpcom); + int processFlags(uint64_t flag, const char* pid); + + void updateDPsCCDB(); + + const CcdbObjectInfo& getccdbDPsInfo() const { return mCcdbDPsInfo; } + CcdbObjectInfo& getccdbDPsInfo() { return mCcdbDPsInfo; } + const std::unordered_map& getTRDDPsInfo() const { return mTRDDCS; } + + template + void prepareCCDBobjectInfo(T& obj, CcdbObjectInfo& info, const std::string& path, TFType tf, + const std::map& md); + + void setStartValidity(TFType tf) { mStartValidity = tf; } + void useVerboseMode() { mVerbose = true; } + + void clearDPsinfo() + { + mDpsDoublesmap.clear(); + mTRDDCS.clear(); + } + + private: + std::unordered_map mTRDDCS; // this is the object that will go to the CCDB + std::unordered_map mPids; // contains all PIDs for the processor, the bool + // will be true if the DP was processed at least once + std::unordered_map> mDpsDoublesmap; // this is the map that will hold the DPs for the + // double type + + CcdbObjectInfo mCcdbDPsInfo; + TFType mStartTF; // TF index for processing of first processed TF, used to store CCDB object + TFType mStartValidity = 0; // TF index for processing, used to store CCDB object + bool mStartTFset = false; + + bool mVerbose = false; + + ClassDefNV(DCSProcessor, 0); +}; + +} // namespace trd +} // namespace o2 + +#endif diff --git a/Detectors/TRD/calibration/macros/CMakeLists.txt b/Detectors/TRD/calibration/macros/CMakeLists.txt index 11929d06b2e2b..742114fd59842 100644 --- a/Detectors/TRD/calibration/macros/CMakeLists.txt +++ b/Detectors/TRD/calibration/macros/CMakeLists.txt @@ -9,7 +9,24 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +if(BUILD_TESTING) o2_add_test_root_macro(checkNoisyMCMs.C PUBLIC_LINK_LIBRARIES O2::DataFormatsTRD O2::CCDB LABELS trd) +endif() + +o2_add_test_root_macro(makeTRDCCDBEntryForDCS.C + PUBLIC_LINK_LIBRARIES O2::DetectorsDCS + O2::CCDB + LABELS trd) + +o2_add_test_root_macro(readTRDDCSentries.C + PUBLIC_LINK_LIBRARIES O2::DetectorsDCS + O2::CCDB + LABELS trd) + +install( + FILES makeTRDCCDBEntryForDCS.C + readTRDDCSentries.C + DESTINATION share/macro/) diff --git a/Detectors/TRD/calibration/macros/makeTRDCCDBEntryForDCS.C b/Detectors/TRD/calibration/macros/makeTRDCCDBEntryForDCS.C new file mode 100644 index 0000000000000..14081d8b67a03 --- /dev/null +++ b/Detectors/TRD/calibration/macros/makeTRDCCDBEntryForDCS.C @@ -0,0 +1,56 @@ +// 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. + +#include +#include +#include "TFile.h" +#include "CCDB/CcdbApi.h" +#include "DetectorsDCS/AliasExpander.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/DataPointIdentifier.h" + +#include +#include + +using DPID = o2::dcs::DataPointIdentifier; + +int makeTRDCCDBEntryForDCS(const std::string url = "http://localhost:8080") +{ + + // macro to populate CCDB for TRD with the configuration for DCS + std::unordered_map dpid2DataDesc; + std::vector aliasesFloat; + aliasesFloat.insert(aliasesFloat.end(), {"trd_gasCO2", "trd_gasH2O", "trd_gasO2"}); + aliasesFloat.insert(aliasesFloat.end(), {"trd_gaschromatographCO2", "trd_gaschromatographN2", "trd_gaschromatographXe"}); + // aliasesFloat.insert(aliasesFloat.end(), {"trd_hvAnodeImon[00..539]", "trd_hvAnodeUmon[00..539]", "trd_hvDriftImon[00..539]", "trd_hvDriftImon[00..539]"}); + // std::vector aliasesInt = {"trd_fedChamberStatus[00..539]", "trd_runNo", "trd_runType"}; + std::vector aliasesInt = {"trd_runNo", "trd_runType"}; + std::vector expAliasesFloat = o2::dcs::expandAliases(aliasesFloat); + std::vector expAliasesInt = o2::dcs::expandAliases(aliasesInt); + + DPID dpidTmp; + for (size_t i = 0; i < expAliasesFloat.size(); ++i) { + DPID::FILL(dpidTmp, expAliasesFloat[i], o2::dcs::DeliveryType::DPVAL_DOUBLE); + dpid2DataDesc[dpidTmp] = "TRDDATAPOINTS"; + } + for (size_t i = 0; i < expAliasesInt.size(); ++i) { + DPID::FILL(dpidTmp, expAliasesInt[i], o2::dcs::DeliveryType::DPVAL_INT); + dpid2DataDesc[dpidTmp] = "TRDDATAPOINTS"; + } + + o2::ccdb::CcdbApi api; + api.init(url); + std::map md; + long ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + api.storeAsTFileAny(&dpid2DataDesc, "TRD/Config/DCSDPconfig", md, ts); + + return 0; +} diff --git a/Detectors/TRD/calibration/macros/readTRDDCSentries.C b/Detectors/TRD/calibration/macros/readTRDDCSentries.C new file mode 100644 index 0000000000000..feaf8e5eb8b2e --- /dev/null +++ b/Detectors/TRD/calibration/macros/readTRDDCSentries.C @@ -0,0 +1,68 @@ +// 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. + +// macro to read the TOF DCS information from CCDB +// default ts is very big: Saturday, November 20, 2286 5:46:39 PM + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "CCDB/CcdbApi.h" +#include "DetectorsDCS/DataPointIdentifier.h" + +#include +#include +#include +#include +#endif + +void readTRDDCSentries(long ts = 9999999999000, const char* ccdb = "http://localhost:8080") +{ + + o2::ccdb::CcdbApi api; + api.init(ccdb); // or http://ccdb-test.cern.ch:8080 + std::map metadata; + if (ts == 9999999999000) { + ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + } + + std::unordered_map* map = api.retrieveFromTFileAny>("TRD/Config/DCSDPconfig", metadata, ts); + for (auto& i : *map) { + std::cout << "id = " << i.first << std::endl; + std::cout << "string= " << i.second << std::endl; + } + /* + std::unordered_map* m = api.retrieveFromTFileAny>("TOF/DCSDPs", metadata, ts); + std::cout << "size of map = " << m->size() << std::endl; + + for (auto& i : *m) { + std::cout << "id = " << i.first << std::endl; + i.second.print(); + } + + std::bitset* feac = api.retrieveFromTFileAny>("TOF/LVStatus", metadata, ts); + //std::cout << "LV info (FEAC): " << feac->to_string() << std::endl; + std::cout << "LV info (FEAC): number of channels that are ON = " << feac->count() << std::endl; + for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ++ich) { + if (feac->test(ich) != 0) { + std::cout << "LV for channel " << ich << " is ON" << std::endl; + } + } + + std::bitset* hv = api.retrieveFromTFileAny>("TOF/HVStatus", metadata, ts); + //std::cout << "HV info : " << hv->to_string() << std::endl; + std::cout << "HV info : number of channels that are ON = " << hv->count() << std::endl; + for (int ich = 0; ich < o2::tof::Geo::NCHANNELS; ++ich) { + if (hv->test(ich) != 0) { + std::cout << "HV for channel " << ich << " is ON" << std::endl; + } + } +*/ + return; +} diff --git a/Detectors/TRD/calibration/src/DCSProcessor.cxx b/Detectors/TRD/calibration/src/DCSProcessor.cxx new file mode 100644 index 0000000000000..292b7884b0a87 --- /dev/null +++ b/Detectors/TRD/calibration/src/DCSProcessor.cxx @@ -0,0 +1,241 @@ +// 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. + +#include "TRDCalibration/DCSProcessor.h" +#include "DetectorsCalibration/Utils.h" + +using namespace o2::trd; +using namespace o2::dcs; + +using DeliveryType = o2::dcs::DeliveryType; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +void TRDDCSMinMaxMeanInfo::print() const +{ + LOG(info) << "Min value: " << minValue; + LOG(info) << "Max value: " << maxValue; + LOG(info) << "Mean value: " << meanValue; + LOG(info) << "Number of points added: " << nPoints; +} + +void TRDDCSMinMaxMeanInfo::addPoint(float value) +{ + if (nPoints == 0) { + minValue = value; + maxValue = value; + meanValue = value; + } else { + if (value < minValue) { + minValue = value; + } + if (value > maxValue) { + maxValue = value; + } + meanValue += (value - meanValue) / (nPoints + 1); + } + ++nPoints; +} + +//__________________________________________________________________ + +void DCSProcessor::init(const std::vector& pids) +{ + // fill the array of the DPIDs that will be used by TRD + // pids should be provided by CCDB + + for (const auto& it : pids) { + mPids[it] = false; + } +} + +//__________________________________________________________________ + +int DCSProcessor::process(const gsl::span dps) +{ + + // first we check which DPs are missing - if some are, it means that + // the delta map was sent + if (mVerbose) { + LOG(info) << "\n\n\nProcessing new TF\n-----------------"; + } + if (!mStartTFset) { + mStartTF = mStartValidity; + mStartTFset = true; + } + + std::unordered_map mapin; + for (auto& it : dps) { + mapin[it.id] = it.data; + } + for (auto& it : mPids) { + const auto& el = mapin.find(it.first); + if (el == mapin.end()) { + LOG(info) << "DP " << it.first << " not found in map"; + } else { + LOG(info) << "DP " << it.first << " found in map"; + } + } + + // now we process all DPs, one by one + for (const auto& it : dps) { + // we process only the DPs defined in the configuration + const auto& el = mPids.find(it.id); + if (el == mPids.end()) { + LOG(info) << "DP " << it.id << " not found in DCSProcessor, we will not process it"; + continue; + } + processDP(it); + mPids[it.id] = true; + } + + return 0; +} + +//__________________________________________________________________ + +int DCSProcessor::processDP(const DPCOM& dpcom) +{ + + // processing single DP + + auto& dpid = dpcom.id; + const auto& type = dpid.get_type(); + if (mVerbose) { + if (type == DPVAL_DOUBLE) { + LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); + } else if (type == DPVAL_INT) { + LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); + } + } + auto flags = dpcom.data.get_flags(); + if (processFlags(flags, dpid.get_alias()) == 0) { + if (type == DPVAL_DOUBLE) { + auto& dvect = mDpsDoublesmap[dpid]; + LOG(info) << "mDpsDoublesmap[dpid].size() = " << dvect.size(); + auto etime = dpcom.data.get_epoch_time(); + if (dvect.size() == 0 || etime != dvect.back().data.get_epoch_time()) { + // only add data point in case it was not already read before + dvect.push_back(dpcom); + } + } + if (type == DPVAL_INT) { + // TODO so far there is no processing at all for these type of DCS data points + if (std::strstr(dpid.get_alias(), "trd_runNo") != nullptr) { // DP is trd_runNo + std::string aliasStr(dpid.get_alias()); + auto runNumber = o2::dcs::getValue(dpcom); + if (mVerbose) { + LOG(info) << "Run number = " << runNumber; + } + // end processing current DP, when it is of type trd_runNo + } else if (std::strstr(dpid.get_alias(), "trd_runType") != nullptr) { // DP is trd_runType + std::string aliasStr(dpid.get_alias()); + auto runType = o2::dcs::getValue(dpcom); + if (mVerbose) { + LOG(info) << "Run type = " << runType; + } + } + } + } + return 0; +} + +//______________________________________________________________________ + +int DCSProcessor::processFlags(const uint64_t flags, const char* pid) +{ + + // function to process the flag. the return code zero means that all is fine. + // anything else means that there was an issue + + // for now, I don't know how to use the flags, so I do nothing + + if (flags & DataPointValue::KEEP_ALIVE_FLAG) { + LOG(info) << "KEEP_ALIVE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::END_FLAG) { + LOG(info) << "END_FLAG active for DP " << pid; + } + if (flags & DataPointValue::FBI_FLAG) { + LOG(info) << "FBI_FLAG active for DP " << pid; + } + if (flags & DataPointValue::NEW_FLAG) { + LOG(info) << "NEW_FLAG active for DP " << pid; + } + if (flags & DataPointValue::DIRTY_FLAG) { + LOG(info) << "DIRTY_FLAG active for DP " << pid; + } + if (flags & DataPointValue::TURN_FLAG) { + LOG(info) << "TURN_FLAG active for DP " << pid; + } + if (flags & DataPointValue::WRITE_FLAG) { + LOG(info) << "WRITE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::READ_FLAG) { + LOG(info) << "READ_FLAG active for DP " << pid; + } + if (flags & DataPointValue::OVERWRITE_FLAG) { + LOG(info) << "OVERWRITE_FLAG active for DP " << pid; + } + if (flags & DataPointValue::VICTIM_FLAG) { + LOG(info) << "VICTIM_FLAG active for DP " << pid; + } + if (flags & DataPointValue::DIM_ERROR_FLAG) { + LOG(info) << "DIM_ERROR_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_DPID_FLAG) { + LOG(info) << "BAD_DPID_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_FLAGS_FLAG) { + LOG(info) << "BAD_FLAGS_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_TIMESTAMP_FLAG) { + LOG(info) << "BAD_TIMESTAMP_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_PAYLOAD_FLAG) { + LOG(info) << "BAD_PAYLOAD_FLAG active for DP " << pid; + } + if (flags & DataPointValue::BAD_FBI_FLAG) { + LOG(info) << "BAD_FBI_FLAG active for DP " << pid; + } + + return 0; +} + +//______________________________________________________________________ + +void DCSProcessor::updateDPsCCDB() +{ + // here we create the object to then be sent to CCDB + LOG(info) << "Finalizing"; + + for (const auto& it : mPids) { + const auto& type = it.first.get_type(); + if (type == o2::dcs::DPVAL_DOUBLE) { + auto& trddcs = mTRDDCS[it.first]; + if (it.second == true) { // we processed the DP at least 1x + auto& dpVect = mDpsDoublesmap[it.first]; + for (const auto& dpCom : dpVect) { + trddcs.addPoint(o2::dcs::getValue(dpCom)); + } + } + if (mVerbose) { + LOG(info) << "PID = " << it.first.get_alias(); + trddcs.print(); + } + } + } + std::map md; + md["responsible"] = "Ole Schmidt"; + o2::calibration::Utils::prepareCCDBobjectInfo(mTRDDCS, mCcdbDPsInfo, "TRD/Calib/DCSDPs", md, mStartValidity, o2::calibration::Utils::INFINITE_TIME); + + return; +} diff --git a/Detectors/TRD/calibration/src/TRDCalibrationLinkDef.h b/Detectors/TRD/calibration/src/TRDCalibrationLinkDef.h index d704d37332fda..10fa842d89a9f 100644 --- a/Detectors/TRD/calibration/src/TRDCalibrationLinkDef.h +++ b/Detectors/TRD/calibration/src/TRDCalibrationLinkDef.h @@ -21,4 +21,7 @@ #pragma link C++ class o2::trd::TrackBasedCalib + ; #pragma link C++ class o2::trd::KrClusterFinder + ; +#pragma link C++ struct o2::trd::TRDDCSMinMaxMeanInfo + ; +#pragma link C++ class std::unordered_map < o2::dcs::DataPointIdentifier, o2::trd::TRDDCSMinMaxMeanInfo> + ; + #endif diff --git a/Detectors/TRD/calibration/workflow/TRDDCSDataProcessorSpec.h b/Detectors/TRD/calibration/workflow/TRDDCSDataProcessorSpec.h new file mode 100644 index 0000000000000..6f628b82e57ba --- /dev/null +++ b/Detectors/TRD/calibration/workflow/TRDDCSDataProcessorSpec.h @@ -0,0 +1,178 @@ +// 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. + +#ifndef O2_TRD_DATAPROCESSOR_H +#define O2_TRD_DATAPROCESSOR_H + +/// @file DCSTRDDataProcessorSpec.h +/// @brief TRD Processor for DCS Data Points + +#include +#include +#include +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/AliasExpander.h" +#include "TRDCalibration/DCSProcessor.h" +#include "DetectorsCalibration/Utils.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/DeviceSpec.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace trd +{ + +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; +using DPCOM = o2::dcs::DataPointCompositeObject; + +class TRDDCSDataProcessor : public o2::framework::Task +{ + public: + void init(o2::framework::InitContext& ic) final + { + + std::vector vect; + mGasDPsUpdateInterval = ic.options().get("DPs-update-interval-gas"); + if (mGasDPsUpdateInterval == 0) { + LOG(error) << "TRD DPs update interval set to zero seconds --> changed to 900s"; + mGasDPsUpdateInterval = 900; + } + bool useCCDBtoConfigure = ic.options().get("use-ccdb-to-configure"); + if (useCCDBtoConfigure) { + LOG(info) << "Configuring via CCDB"; + std::string ccdbpath = ic.options().get("ccdb-path"); + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + mgr.setURL(ccdbpath); + o2::ccdb::CcdbApi api; + api.init(mgr.getURL()); + long ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + std::unordered_map* dpid2DataDesc = mgr.getForTimeStamp>("TRD/Config/DCSDPconfig", ts); + for (auto& i : *dpid2DataDesc) { + vect.push_back(i.first); + } + } else { + LOG(info) << "Configuring via hardcoded strings"; + std::vector aliasesFloat; + aliasesFloat.insert(aliasesFloat.end(), {"trd_gasCO2", "trd_gasH2O", "trd_gasO2"}); + aliasesFloat.insert(aliasesFloat.end(), {"trd_gaschromatographCO2", "trd_gaschromatographN2", "trd_gaschromatographXe"}); + // aliasesFloat.insert(aliasesFloat.end(), {"trd_hvAnodeImon[00..539]", "trd_hvAnodeUmon[00..539]", "trd_hvDriftImon[00..539]", "trd_hvDriftImon[00..539]"}); + // std::vector aliasesInt = {"trd_fedChamberStatus[00..539]", "trd_runNo", "trd_runType"}; + std::vector aliasesInt = {"trd_runNo", "trd_runType"}; + std::vector expAliasesFloat = o2::dcs::expandAliases(aliasesFloat); + std::vector expAliasesInt = o2::dcs::expandAliases(aliasesInt); + for (const auto& i : expAliasesFloat) { + vect.emplace_back(i, o2::dcs::DPVAL_DOUBLE); + } + for (const auto& i : expAliasesInt) { + vect.emplace_back(i, o2::dcs::DPVAL_INT); + } + } + + LOG(info) << "Listing Data Points for TRD:"; + for (auto& i : vect) { + LOG(info) << i; + } + + mProcessor = std::make_unique(); + bool useVerboseMode = ic.options().get("use-verbose-mode"); + if (useVerboseMode) { + LOG(info) << "Using verbose mode for TRD DCS processor"; + mProcessor->useVerboseMode(); + } + mProcessor->init(vect); + mTimer = std::chrono::high_resolution_clock::now(); + } + + void run(o2::framework::ProcessingContext& pc) final + { + auto startValidity = DataRefUtils::getHeader(pc.inputs().getFirstValid(true))->creation; + auto dps = pc.inputs().get>("input"); + auto timeNow = std::chrono::high_resolution_clock::now(); + if (startValidity == 0xffffffffffffffff) { + // in case it is not set + startValidity = std::chrono::duration_cast(timeNow.time_since_epoch()).count(); // in ms + } + mProcessor->setStartValidity(startValidity); + mProcessor->process(dps); + + auto elapsedTime = timeNow - mTimer; // in ns + if (elapsedTime.count() * 1e-9 >= mGasDPsUpdateInterval) { + sendDPsoutputGas(pc.outputs()); + mTimer = timeNow; + } + } + + void endOfStream(o2::framework::EndOfStreamContext& ec) final + { + sendDPsoutputGas(ec.outputs()); + } + + private: + std::unique_ptr mProcessor; + std::chrono::high_resolution_clock::time_point mTimer; + int64_t mGasDPsUpdateInterval; + + //________________________________________________________________ + void sendDPsoutputGas(DataAllocator& output) + { + // extract CCDB infos and calibration object for DPs + mProcessor->updateDPsCCDB(); + const auto& payload = mProcessor->getTRDDPsInfo(); + auto& info = mProcessor->getccdbDPsInfo(); + auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); + LOG(info) << "Sending object " << info.getPath() << "/" << info.getFileName() << " of size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "TRD_DCSGasDPs", 0}, *image.get()); + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "TRD_DCSGasDPs", 0}, info); + mProcessor->clearDPsinfo(); + } + +}; // end class +} // namespace trd + +namespace framework +{ + +DataProcessorSpec getTRDDCSDataProcessorSpec() +{ + + std::vector outputs; + + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "TRD_DCSGasDPs"}); + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "TRD_DCSGasDPs"}); + + return DataProcessorSpec{ + "trd-dcs-data-processor", + Inputs{{"input", "DCS", "TRDDATAPOINTS"}}, + outputs, + AlgorithmSpec{adaptFromTask()}, + Options{{"ccdb-path", VariantType::String, "http://localhost:8080", {"Path to CCDB"}}, + {"use-ccdb-to-configure", VariantType::Bool, false, {"Use CCDB to configure"}}, + {"use-verbose-mode", VariantType::Bool, false, {"Use verbose mode"}}, + {"DPs-update-interval-gas", VariantType::Int64, 900ll, {"Interval (in s) after which to update the DPs CCDB entry for gas parameters"}}}}; +} + +} // namespace framework +} // namespace o2 + +#endif diff --git a/Detectors/TRD/calibration/workflow/trd-dcs-data-workflow.cxx b/Detectors/TRD/calibration/workflow/trd-dcs-data-workflow.cxx new file mode 100644 index 0000000000000..ba6c3e773b7e5 --- /dev/null +++ b/Detectors/TRD/calibration/workflow/trd-dcs-data-workflow.cxx @@ -0,0 +1,42 @@ +// 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. + +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "Framework/TypeTraits.h" +#include +namespace o2::framework +{ +template <> +struct has_root_dictionary, void> : std::true_type { +}; +} // namespace o2::framework +#include "Framework/DataProcessorSpec.h" +#include "TRDDCSDataProcessorSpec.h" + +using namespace o2::framework; + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + specs.emplace_back(getTRDDCSDataProcessorSpec()); + return specs; +} diff --git a/Detectors/TRD/calibration/workflow/trd-dcs-sim-workflow.cxx b/Detectors/TRD/calibration/workflow/trd-dcs-sim-workflow.cxx new file mode 100644 index 0000000000000..cec58e286d194 --- /dev/null +++ b/Detectors/TRD/calibration/workflow/trd-dcs-sim-workflow.cxx @@ -0,0 +1,52 @@ +// 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. + +#include "DCStestWorkflow/DCSRandomDataGeneratorSpec.h" +#include "Framework/runDataProcessing.h" + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& configcontext) +{ + std::vector dphints; + // for TRD + // for test, we use less DPs than official ones + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasCO2", 0, 50.}); // adding a data point of type double with the name trd_gasCO2 which takes values between 0 and 50 + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasH2O", 0, 500.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasO2", 0, 100.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographCO2", 0, 100.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographN2", 0, 100.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographXe", 0, 100.}); + // dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvAnodeImon[00..02]", 0, 50.}); + // dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvAnodeUmon[00..02]", 0, 50.}); + // dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvDriftImon[00..02]", 0, 50.}); + // dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvDriftUmon[00..02]", 0, 50.}); + // dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_fedChamberStatus", 0, 255}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_runNo", 0, 255}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_runType", 0, 255}); + // for TRD, official list, not yet complete + /* + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasCO2", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasH2O", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gasO2", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographCO2", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographN2", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_gaschromatographXe", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvAnodeImon[00..539]", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvAnodeUmon[00..539]", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvDriftImon[00..539]", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_hvDriftUmon[00..539]", 0, 50.}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_fedChamberStatus", 0, 255}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_runNo", 0, 255}); + dphints.emplace_back(o2::dcs::test::DataPointHint{"trd_runType", 0, 255}); + */ + o2::framework::WorkflowSpec specs; + specs.emplace_back(o2::dcs::test::getDCSRandomDataGeneratorSpec(dphints, "TRD")); + return specs; +}