diff --git a/Detectors/ITSMFT/ITS/macros/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/CMakeLists.txt index 8c6767cfdad89..d651d94fbc07a 100644 --- a/Detectors/ITSMFT/ITS/macros/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(EVE) add_subdirectory(test) +add_subdirectory(DCS) diff --git a/Detectors/ITSMFT/ITS/macros/DCS/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/DCS/CMakeLists.txt new file mode 100644 index 0000000000000..5850bebbeae05 --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/DCS/CMakeLists.txt @@ -0,0 +1,18 @@ +# 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. + +o2_add_test_root_macro( + makeITSCCDBEntryForDCS.C + PUBLIC_LINK_LIBRARIES O2::DetectorsDCS O2::CCDB) + +install( + FILES makeITSCCDBEntryForDCS.C + DESTINATION share/macro/) diff --git a/Detectors/ITSMFT/ITS/macros/DCS/makeITSCCDBEntryForDCS.C b/Detectors/ITSMFT/ITS/macros/DCS/makeITSCCDBEntryForDCS.C new file mode 100644 index 0000000000000..482f48132f80b --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/DCS/makeITSCCDBEntryForDCS.C @@ -0,0 +1,58 @@ +// 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 "CommonUtils/NameConf.h" +#endif +#include +#include +#include "TFile.h" +#include "DetectorsDCS/AliasExpander.h" +#include "DetectorsDCS/DeliveryType.h" +#include "DetectorsDCS/DataPointIdentifier.h" +#include +#include +#include "CCDB/CcdbApi.h" + +using DPID = o2::dcs::DataPointIdentifier; + +int makeITSCCDBEntryForDCS(std::string ccdb_path = o2::base::NameConf::getCCDBServer()) +{ + + std::unordered_map dpid2DataDesc; + std::vector aliases; + + // fill aliases + int nStaves[] = {12, 16, 20, 24, 30, 42, 48}; + for (int iL = 0; iL < 7; iL++) { + for (int iS = 0; iS < nStaves[iL]; iS++) { + std::string stv = iS > 9 ? std::to_string(iS) : std::string(1, '0').append(std::to_string(iS)); + aliases.push_back("ITS_L" + std::to_string(iL) + "_" + stv + "_STROBE"); + } + } + + std::vector expaliases = o2::dcs::expandAliases(aliases); + + DPID dpidtmp; + for (size_t i = 0; i < expaliases.size(); ++i) { + DPID::FILL(dpidtmp, expaliases[i], o2::dcs::DeliveryType::DPVAL_INT); + dpid2DataDesc[dpidtmp] = "ITSDATAPOINTS"; + } + + o2::ccdb::CcdbApi api; + api.init(ccdb_path); + std::map md; + md["comment"] = "uploaded with O2 makeITSCCDBEntryForDCS.C"; + long ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + api.storeAsTFileAny(&dpid2DataDesc, "ITS/Config/DCSDPconfig", md, ts, ts + 365L * 10 * 24 * 3600 * 1000); // validity is 10 years + + return 0; +} diff --git a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt index 261465ec4568a..785417d915a67 100644 --- a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt @@ -25,8 +25,13 @@ o2_add_library(ITSWorkflow src/ThresholdAggregatorSpec.cxx src/DCSParserWorkflow.cxx src/DCSParserSpec.cxx + src/DCSAdaposParserWorkflow.cxx + src/DCSAdaposParserSpec.cxx + src/DCSDataGeneratorWorkflow.cxx + src/DCSGeneratorSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig + O2::DetectorsDCS O2::DataFormatsITS O2::DataFormatsDCS O2::DataFormatsTRD @@ -73,6 +78,16 @@ o2_add_executable(dcs-parser-workflow COMPONENT_NAME its PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) +o2_add_executable(dcs-generator-workflow + SOURCES src/its-dcs-generator-workflow.cxx + COMPONENT_NAME its + PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) + +o2_add_executable(dcs-adapos-parser-workflow + SOURCES src/its-dcs-adapos-parser-workflow.cxx + COMPONENT_NAME its + PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) + if (OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h new file mode 100644 index 0000000000000..cd9be3afc4c95 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserSpec.h @@ -0,0 +1,96 @@ +// 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. + +/// @file DCSAdaposParserSpec.h + +#ifndef O2_ITS_DCS_PARSER_SPEC_H +#define O2_ITS_DCS_PARSER_SPEC_H + +#include +#include +#include +#include +#include + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/Task.h" +#include "Framework/InputRecordWalker.h" +#include + +#include + +#include "Framework/RawDeviceService.h" +#include "Headers/DataHeader.h" +#include "DetectorsCalibration/Utils.h" +#include "CCDB/CcdbObjectInfo.h" +#include "CCDB/CcdbApi.h" + +#include "DetectorsDCS/DataPointIdentifier.h" +#include "DetectorsDCS/DataPointValue.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "CCDB/BasicCCDBManager.h" + +using namespace o2::framework; +using namespace o2::itsmft; + +namespace o2 +{ +namespace its +{ + +using DPCOM = o2::dcs::DataPointCompositeObject; +using DPID = o2::dcs::DataPointIdentifier; +using DPVAL = o2::dcs::DataPointValue; + +class ITSDCSAdaposParser : public Task +{ + public: + ITSDCSAdaposParser(); + ~ITSDCSAdaposParser() override = default; + + void init(InitContext& ic) final; + void run(ProcessingContext& pc) final; + + ////////////////////////////////////////////////////////////////// + private: + // Helper functions + void process(const gsl::span dps); + void processDP(const DPCOM& dpcom); + void pushToCCDB(ProcessingContext&); + void getCurrentCcdbAlpideParam(); + + // Ccdb url for ccdb upload withing the wf + std::string mCcdbUrl = ""; + + // store the strobe length for each DPID = stave + std::unordered_map mDPstrobe; + double mStrobeToUpload = 0.; + bool doStrobeUpload = false; + + std::string mSelfName; + bool mVerboseOutput = false; + + // for ccdb alpide param fetching + o2::itsmft::DPLAlpideParam* mCcdbAlpideParam; + std::string mCcdbFetchUrl = "http://ccdb-test.cern.ch:8080"; + o2::ccdb::BasicCCDBManager& mMgr = o2::ccdb::BasicCCDBManager::instance(); + long int startTime; +}; + +// Create a processor spec +o2::framework::DataProcessorSpec getITSDCSAdaposParserSpec(); + +} // namespace its +} // namespace o2 + +#endif diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserWorkflow.h new file mode 100644 index 0000000000000..def1e910d571b --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSAdaposParserWorkflow.h @@ -0,0 +1,33 @@ +// 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. + +/// @file DCSAdaposParserWorkflow.h + +#ifndef O2_ITS_DCS_ADAPOS_PARSER_WORKFLOW_H +#define O2_ITS_DCS_ADAPOS_PARSER_WORKFLOW_H + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace dcs_adapos_parser_workflow +{ + +framework::WorkflowSpec getWorkflow(); + +} + +} // namespace its +} // namespace o2 +#endif diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSDataGeneratorWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSDataGeneratorWorkflow.h new file mode 100644 index 0000000000000..bdc4937160212 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSDataGeneratorWorkflow.h @@ -0,0 +1,33 @@ +// 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. + +/// @file DCSDataGeneratorWorkflow.h + +#ifndef O2_ITS_DCS_PARSER_WORKFLOW_H +#define O2_ITS_DCS_PARSER_WORKFLOW_H + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace dcs_generator_workflow +{ + +framework::WorkflowSpec getWorkflow(); + +} // namespace dcs_generator_workflow + +} // namespace its +} // namespace o2 +#endif diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSGeneratorSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSGeneratorSpec.h new file mode 100644 index 0000000000000..92b0e2b6e7a34 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSGeneratorSpec.h @@ -0,0 +1,29 @@ +// 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_ITS_WORKFLOW_DCS_DATA_GENERATOR_SPEC_H +#define O2_ITS_WORKFLOW_DCS_DATA_GENERATOR_SPEC_H + +#include "DetectorsDCS/DCSDataPointHint.h" +#include "Framework/DataProcessorSpec.h" +#include +#include +#include +#include + +using namespace o2::framework; + +namespace o2::its +{ +o2::framework::DataProcessorSpec getITSDCSDataGeneratorSpec(const char* detName = "ITS"); +} // namespace o2::its + +#endif diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserSpec.cxx new file mode 100644 index 0000000000000..1aa78eb329c9b --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserSpec.cxx @@ -0,0 +1,224 @@ +// 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. + +/// @file DCSAdaposParserSpec.cxx + +#include "ITSWorkflow/DCSAdaposParserSpec.h" + +namespace o2 +{ +namespace its +{ +////////////////////////////////////////////////////////////////////////////// +// Default constructor +ITSDCSAdaposParser::ITSDCSAdaposParser() +{ + this->mSelfName = o2::utils::Str::concat_string(ChipMappingITS::getName(), "ITSDCSAdaposParser"); +} + +////////////////////////////////////////////////////////////////////////////// +void ITSDCSAdaposParser::init(InitContext& ic) +{ + LOGF(info, "ITSDCSAdaposParser init...", mSelfName); + + this->mCcdbUrl = ic.options().get("ccdb-url"); + + this->mVerboseOutput = ic.options().get("verbose"); + + // Read alpide param object from ccdb: this is the first read, object will be refreshed in run() + this->mCcdbFetchUrl = ic.options().get("ccdb-fetch-url"); + mMgr.setURL(mCcdbFetchUrl); + getCurrentCcdbAlpideParam(); + startTime = o2::ccdb::getCurrentTimestamp(); + + return; +} + +////////////////////////////////////////////////////////////////////////////// +// Main running function +// Get Data from ADAPOS and prepare CCDB objects +void ITSDCSAdaposParser::run(ProcessingContext& pc) +{ + + // Retrieve adapos data and process them + auto dps = pc.inputs().get>("input"); + process(dps); + + if (doStrobeUpload && dps.size() > 0) { + // upload to ccdb + pushToCCDB(pc); + } + + // refresh the local Alpide Param object in case another software/user uploaded an object in that path + // do the update every 10s + long int currentTs = o2::ccdb::getCurrentTimestamp(); + if (currentTs - startTime > 10000) { + getCurrentCcdbAlpideParam(); + startTime = currentTs; + } + + // clear memory + mDPstrobe.clear(); + + return; +} + +//////////////////////////////////////////////////////////////////////////// +// Function to retrieve AlpideParam object from CCDB +void ITSDCSAdaposParser::getCurrentCcdbAlpideParam() +{ + long int ts = o2::ccdb::getCurrentTimestamp(); + LOG(info) << "Getting AlpideParam from CCDB url " << mCcdbFetchUrl << " with timestamp " << ts; + mMgr.setTimestamp(ts); + mCcdbAlpideParam = mMgr.get>("ITS/Config/AlpideParam"); +} + +////////////////////////////////////////////////////////////////////////////// +// Function to process DPs +void ITSDCSAdaposParser::process(const gsl::span dps) +{ + + // first we check which DPs are missing - if some are, it means that + // the delta map was sent + if (mVerboseOutput) { + LOG(info) << "\n\n\nProcessing new TF\n-----------------"; + } + + // Process all DPs, one by one + for (const auto& it : dps) { + processDP(it); + } + + /************************************** + decide whether to upload or not the object to ccdb. The logic for strobe length is: + - compare the value which arrived from ADAPOS with the one stored in CCDB + - if the values are different, store it and create a new object for ccdb + - refresh the local ccdb object (int run() method) + - the logic continue... memory is cleaned at the end of every run() cycle + ***************************************/ + auto mapel = mDPstrobe.begin(); + if (!mDPstrobe.size()) { + doStrobeUpload = false; + return; + } + + if (mapel->second.payload_pt1 + 8 != mCcdbAlpideParam->roFrameLengthInBC) { + mStrobeToUpload = mapel->second.payload_pt1; + doStrobeUpload = true; + } else { + doStrobeUpload = false; + } + + return; +} + +////////////////////////////////////////////////////////////////////////////// +// Process single DPs +void ITSDCSAdaposParser::processDP(const DPCOM& dpcom) +{ + auto& dpid = dpcom.id; + const auto& type = dpid.get_type(); + auto& val = dpcom.data; + auto flags = val.get_flags(); + + if (mVerboseOutput) { + LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); + } + + if (o2::dcs::getValue(dpcom) < 190) { + if (mVerboseOutput) { + LOG(info) << "Value is < 190 BCs, skipping it"; + } + return; + } + + if (o2::dcs::getValue(dpcom) > 189) { // Discard strobe length lower than this: thr scan + mDPstrobe[dpid] = val; + } +} + +////////////////////////////////////////////////////////////////////////////// +void ITSDCSAdaposParser::pushToCCDB(ProcessingContext& pc) +{ + // Timestamps for CCDB entry + long tstart = 0, tend = 0; + // retireve run start/stop times from CCDB + o2::ccdb::CcdbApi api; + api.init("http://alice-ccdb.cern.ch"); + // Initialize empty metadata object for search + std::map metadata; + + tstart = o2::ccdb::getCurrentTimestamp(); + tend = tstart + 365L * 2 * 24 * 3600 * 1000; // valid two years by default + + // Create metadata for database object + metadata = {{"comment", "uploaded by flp199 (ADAPOS data)"}, {"StrobeLength", std::to_string(mStrobeToUpload + 8)}}; + + std::string path("ITS/Config/AlpideParam"); + + std::string filename = "o2-itsmft-DPLAlpideParam<0>_" + std::to_string(tstart) + ".root"; + o2::ccdb::CcdbObjectInfo info(path, "dplalpideparam", filename, metadata, tstart, tend); + // Define the dpl alpide param and set the strobe length to ship + auto& dplAlpideParams = o2::itsmft::DPLAlpideParam::Instance(); + dplAlpideParams.updateFromString(fmt::format("ITSAlpideParam.roFrameLengthInBC = {}", (int)mStrobeToUpload + 8)); // +8 is because the strobe length of ALPIDE (sent via ADAPOS) is 200ns shorter than the external trigger strobe length. + auto class_name = o2::utils::MemFileHelper::getClassName(dplAlpideParams); + + auto image = o2::ccdb::CcdbApi::createObjectImage(&dplAlpideParams, &info); + info.setFileName(filename); + + // Send to ccdb-populator wf or upload directly from here + if (mCcdbUrl.empty()) { + LOG(info) << "Class Name: " << class_name << " | File Name: " << filename + << "\nSending to ccdb-populator the object " << info.getPath() << "/" << info.getFileName() + << " of size " << image->size() << " bytes, valid for " + << info.getStartValidityTimestamp() << " : " + << info.getEndValidityTimestamp(); + + pc.outputs().snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "ITSALPIDEPARAM", 0}, *image); + pc.outputs().snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "ITSALPIDEPARAM", 0}, info); + + } else { // if url is specified, send object to ccdb from THIS wf + + LOG(info) << "Sending object " << info.getFileName() << " to " << mCcdbUrl << "/browse/" + << info.getPath() << " from the ITS ADAPOS parser workflow"; + o2::ccdb::CcdbApi mApi; + mApi.init(mCcdbUrl); + mApi.storeAsBinaryFile( + &image->at(0), image->size(), info.getFileName(), info.getObjectType(), info.getPath(), + info.getMetaData(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); + } + + return; +} + +////////////////////////////////////////////////////////////////////////////// +DataProcessorSpec getITSDCSAdaposParserSpec() +{ + o2::header::DataOrigin detOrig = o2::header::gDataOriginITS; + std::vector inputs; + inputs.emplace_back("input", "ITS", "ITSDATAPOINTS"); + + std::vector outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "ITSALPIDEPARAM"}, Lifetime::Sporadic); + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "ITSALPIDEPARAM"}, Lifetime::Sporadic); + + return DataProcessorSpec{ + "its-adapos-parser", + inputs, + outputs, + AlgorithmSpec{adaptFromTask()}, + Options{ + {"verbose", VariantType::Bool, false, {"Use verbose output mode"}}, + {"ccdb-url", VariantType::String, "", {"CCDB url, default is empty (i.e. send output to CCDB populator workflow)"}}, + {"ccdb-fetch-url", VariantType::String, "", {"CCDB url from when to fetch the AlpideParam object, default is ccdb-test"}}}}; +} +} // namespace its +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserWorkflow.cxx new file mode 100644 index 0000000000000..f13f727ba0ee1 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSAdaposParserWorkflow.cxx @@ -0,0 +1,33 @@ +// 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. + +/// @file DCSAdaposParserWorkflow.cxx + +#include "ITSWorkflow/DCSAdaposParserWorkflow.h" +#include "ITSWorkflow/DCSAdaposParserSpec.h" + +namespace o2 +{ +namespace its +{ +namespace dcs_adapos_parser_workflow +{ +framework::WorkflowSpec getWorkflow() +{ + framework::WorkflowSpec specs; + + specs.emplace_back(o2::its::getITSDCSAdaposParserSpec()); + + return specs; +} +} // namespace dcs_adapos_parser_workflow +} // namespace its +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSDataGeneratorWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSDataGeneratorWorkflow.cxx new file mode 100644 index 0000000000000..9e41b6fdbd107 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSDataGeneratorWorkflow.cxx @@ -0,0 +1,33 @@ +// 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. + +/// @file DCSDataGeneratorWorkflow.cxx + +#include "ITSWorkflow/DCSDataGeneratorWorkflow.h" +#include "ITSWorkflow/DCSGeneratorSpec.h" + +namespace o2 +{ +namespace its +{ +namespace dcs_generator_workflow +{ +framework::WorkflowSpec getWorkflow() +{ + framework::WorkflowSpec specs; + + specs.emplace_back(o2::its::getITSDCSDataGeneratorSpec("ITS")); + + return specs; +} +} // namespace dcs_generator_workflow +} // namespace its +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSGeneratorSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSGeneratorSpec.cxx new file mode 100644 index 0000000000000..48bbaed171a85 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSGeneratorSpec.cxx @@ -0,0 +1,149 @@ +// 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 "ITSWorkflow/DCSGeneratorSpec.h" +#include "DetectorsDCS/DataPointCompositeObject.h" +#include "DetectorsDCS/DataPointGenerator.h" +#include "DetectorsDCS/DataPointCreator.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ControlService.h" +#include "Framework/DeviceSpec.h" +#include "Framework/Logger.h" +#include "Framework/Task.h" +#include +#include +#include +#include +#include + +using namespace o2::its; + +namespace +{ +std::vector generate(std::vector aliases, int val) +{ + std::vector dataPoints; + + for (auto alias : aliases) { + dataPoints.emplace_back(o2::dcs::createDataPointCompositeObject(alias, val, 1, 0)); + } + + return dataPoints; +} + +//______________________________________________________________________________________________________________ +// class ITSDCSDataGenerator +class ITSDCSDataGenerator : public o2::framework::Task +{ + public: + ITSDCSDataGenerator(o2::header::DataDescription description); + + void init(o2::framework::InitContext& ic) final; + + void run(o2::framework::ProcessingContext& pc) final; + + void fillAliasesStrobeDuration(); + + private: + uint64_t mMaxTF = 1e6; + uint64_t mTFs = 0; + uint64_t mMaxCyclesNoFullMap; + uint64_t changeAfterTF = 0; + int valueA = 190; + int valueB = 190; + bool isStrobeDurationData = false; + std::vector mAliases; + std::vector mDataPointHints; + o2::header::DataDescription mDataDescription; +}; + +ITSDCSDataGenerator::ITSDCSDataGenerator(o2::header::DataDescription description) : mDataDescription(description) {} + +void ITSDCSDataGenerator::fillAliasesStrobeDuration() +{ + + // Aliases in this case are in the format: ITS_L0_00_STROBE + // Here we fill them for every stave in mAliases + int nStaves[] = {12, 16, 20, 24, 30, 42, 48}; + for (int iL = 0; iL < 7; iL++) { + for (int iS = 0; iS < nStaves[iL]; iS++) { + std::string stv = iS > 9 ? std::to_string(iS) : std::string(1, '0').append(std::to_string(iS)); + mAliases.push_back("ITS_L" + std::to_string(iL) + "_" + stv + "_STROBE"); + } + } +} + +void ITSDCSDataGenerator::init(o2::framework::InitContext& ic) +{ + mMaxTF = ic.options().get("max-timeframes"); + mMaxCyclesNoFullMap = ic.options().get("max-cycles-no-full-map"); + isStrobeDurationData = ic.options().get("generate-strobe-duration-data"); + changeAfterTF = ic.options().get("change-after-n-timeframes"); + valueA = ic.options().get("value-a"); + valueB = ic.options().get("value-b"); + + if (isStrobeDurationData) { + fillAliasesStrobeDuration(); + } +} + +void ITSDCSDataGenerator::run(o2::framework::ProcessingContext& pc) +{ + auto input = pc.inputs().begin(); + uint64_t tfid = o2::header::get((*input).header)->startTime; + if (tfid >= mMaxTF) { + LOG(info) << "ITS DCS Data generator reached TF " << tfid << ", stopping"; + pc.services().get().endOfStream(); + pc.services().get().readyToQuit(o2::framework::QuitRequest::Me); + } + + // generate data simulating ADAPOS + bool doGen = mTFs % mMaxCyclesNoFullMap == 0; + std::vector dpcoms; + if (doGen) { + dpcoms = generate(mAliases, mTFs > changeAfterTF ? valueB : valueA); + } + + LOG(info) << "TF " << tfid << " has generated " << dpcoms.size() << " DPs"; + auto& timingInfo = pc.services().get(); + auto timeNow = std::chrono::system_clock::now(); + timingInfo.creation = std::chrono::duration_cast(timeNow.time_since_epoch()).count(); // in ms + + pc.outputs().snapshot(Output{"ITS", mDataDescription, 0, Lifetime::Timeframe}, dpcoms); + mTFs++; +} +} // namespace + +namespace o2::its +{ +o2::framework::DataProcessorSpec getITSDCSDataGeneratorSpec(const char* detName) +{ + std::string desc{detName}; + desc += "DATAPOINTS"; + + o2::header::DataDescription dd; + + dd.runtimeInit(desc.c_str(), desc.size()); + + return DataProcessorSpec{ + "its-dcs-data-generator", + Inputs{}, + Outputs{{{"outputDCS"}, "ITS", dd}}, + AlgorithmSpec{adaptFromTask(dd)}, + Options{ + {"change-after-n-timeframes", VariantType::Int64, 99999999999ll, {"change value generated after n timeframes: do not change val by default"}}, + {"value-a", VariantType::Int, 0, {"First value to be generated, will change to value-b after nTF = change-after-n-timeframes"}}, + {"value-b", VariantType::Int, 1, {"Second value to be generated, will be after value-a once nTF = change-after-n-timeframes has been reached"}}, + {"max-timeframes", VariantType::Int64, 99999999999ll, {"max TimeFrames to generate"}}, + {"max-cycles-no-full-map", VariantType::Int64, 6000ll, {"max num of cycles between the sending of 2 full maps"}}, + {"generate-strobe-duration-data", VariantType::Bool, false, {"enable generation of DCS data containing the strobe duration in BCs"}}}}; +} +} // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-dcs-adapos-parser-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-dcs-adapos-parser-workflow.cxx new file mode 100644 index 0000000000000..3f7400a90e9bb --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/its-dcs-adapos-parser-workflow.cxx @@ -0,0 +1,25 @@ +// 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 "ITSWorkflow/DCSAdaposParserWorkflow.h" +#include "ITSWorkflow/DCSAdaposParserSpec.h" + +using namespace o2::framework; + +#include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + LOG(info) << "Initializing O2 ITS-DCS Adapos data Parser:"; + + return std::move(o2::its::dcs_adapos_parser_workflow::getWorkflow()); +} diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-dcs-generator-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-dcs-generator-workflow.cxx new file mode 100644 index 0000000000000..16a3ac56c456f --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/its-dcs-generator-workflow.cxx @@ -0,0 +1,25 @@ +// 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 "ITSWorkflow/DCSDataGeneratorWorkflow.h" +#include "ITSWorkflow/DCSGeneratorSpec.h" + +using namespace o2::framework; + +#include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + LOG(info) << "Initializing O2 ITS-DCS Data Generator"; + + return std::move(o2::its::dcs_generator_workflow::getWorkflow()); +}