From b5e744b854038cc415f1eeb57c96b378bcca401f Mon Sep 17 00:00:00 2001 From: mlesch Date: Tue, 29 Oct 2024 17:08:41 +0100 Subject: [PATCH 1/3] TPC: Reductor for DCS Temperatures --- Modules/TPC/CMakeLists.txt | 5 +- Modules/TPC/include/TPC/DCSPTempReductor.h | 66 ++++++++++++ Modules/TPC/include/TPC/LinkDef.h | 1 + Modules/TPC/run/tpcDCSPTempTrending.json | 116 +++++++++++++++++++++ Modules/TPC/src/DCSPTempReductor.cxx | 105 +++++++++++++++++++ 5 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 Modules/TPC/include/TPC/DCSPTempReductor.h create mode 100644 Modules/TPC/run/tpcDCSPTempTrending.json create mode 100644 Modules/TPC/src/DCSPTempReductor.cxx diff --git a/Modules/TPC/CMakeLists.txt b/Modules/TPC/CMakeLists.txt index e8e9b53a95..a5c22a3444 100644 --- a/Modules/TPC/CMakeLists.txt +++ b/Modules/TPC/CMakeLists.txt @@ -38,7 +38,8 @@ target_sources(O2QcTPC PRIVATE src/PID.cxx src/TrackClusters.cxx src/VDriftCalibReductor.cxx src/SeparationPowerReductor.cxx - src/TimeGainCalibReductor.cxx) + src/TimeGainCalibReductor.cxx + src/DCSPTempReductor.cxx) target_include_directories( O2QcTPC @@ -97,6 +98,7 @@ add_root_dictionary(O2QcTPC include/TPC/VDriftCalibReductor.h include/TPC/SeparationPowerReductor.h include/TPC/TimeGainCalibReductor.h + include/TPC/DCSPTempReductor.h LINKDEF include/TPC/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/TPC @@ -180,4 +182,5 @@ install(FILES run/tpcQCPID_sampled.json run/tpcQCvDriftTrending.json run/tpcQCTrending_separationpower.json run/tpcQCTimeGainCalibTrending.json + run/tpcDCSPTempTrending.json DESTINATION etc) diff --git a/Modules/TPC/include/TPC/DCSPTempReductor.h b/Modules/TPC/include/TPC/DCSPTempReductor.h new file mode 100644 index 0000000000..df9d5301c5 --- /dev/null +++ b/Modules/TPC/include/TPC/DCSPTempReductor.h @@ -0,0 +1,66 @@ +// 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 DCSPTempReductor.h +/// \author Marcel Lesch +/// + +#ifndef QUALITYCONTROL_DCSPTEMPREDUCTOR_H +#define QUALITYCONTROL_DCSPTEMPREDUCTOR_H + +#include "QualityControl/ReductorConditionAny.h" +#include + +namespace o2::quality_control_modules::tpc +{ + +/// \brief A Reductor for calibration objects of the TPC DCS temperatures +/// +/// A Reductor for TPC DCS temperatures. +/// It produces a branch in the format: +/// "tempSensor[18]/F:tempSensorErr[18]:tempMeanPerSide[2]:tempMeanPerSideErr[2]:tempGradXPerSide[2]:tempGradXPerSideErr[2]:tempGradYPerSide[2]:tempGradYPerSideErr[2]" +/// tempSensor[i] is the raw sensor temperature for each of the 18 sensores +/// tempMeanPerSide[i] is the mean temperatue per TPC-Side (0: A-Side, 1: C-Side) +/// tempGradXPerSide[i] is the temperatue gradient in x direction per TPC-Side (0: A-Side, 1: C-Side) +/// tempGradYPerSide[i] is the temperatue gradient in y direction per TPC-Side (0: A-Side, 1: C-Side) + +class DCSPTempReductor : public quality_control::postprocessing::ReductorConditionAny +{ + public: + DCSPTempReductor() = default; + ~DCSPTempReductor() = default; + + void* getBranchAddress() override; + const char* getBranchLeafList() override; + bool update(ConditionRetriever& retriever) override; + + private: + struct { + Float_t tempSensor[18]; + Float_t tempSensorErr[18]; // uncertainties + + Float_t tempMeanPerSide[2]; + Float_t tempMeanPerSideErr[2]; // uncertainties + + Float_t tempGradXPerSide[2]; + Float_t tempGradXPerSideErr[2]; // uncertainties + + Float_t tempGradYPerSide[2]; // uncertainties + Float_t tempGradYPerSideErr[2]; // uncertainties + } mStats; + + void calcMeanAndStddev(std::vector& values, float& mean, float& stddev); +}; + +} // namespace o2::quality_control_modules::tpc + +#endif // QUALITYCONTROL_DCSPTEMPREDUCTOR_H diff --git a/Modules/TPC/include/TPC/LinkDef.h b/Modules/TPC/include/TPC/LinkDef.h index 93756d99cc..21565f1ee4 100644 --- a/Modules/TPC/include/TPC/LinkDef.h +++ b/Modules/TPC/include/TPC/LinkDef.h @@ -43,6 +43,7 @@ #pragma link C++ class o2::quality_control_modules::tpc::VDriftCalibReductor + ; #pragma link C++ class o2::quality_control_modules::tpc::SeparationPowerReductor + ; #pragma link C++ class o2::quality_control_modules::tpc::TimeGainCalibReductor + ; +#pragma link C++ class o2::quality_control_modules::tpc::DCSPTempReductor + ; #pragma link C++ function o2::quality_control_modules::tpc::addAndPublish + ; #pragma link C++ function o2::quality_control_modules::tpc::toVector + ; diff --git a/Modules/TPC/run/tpcDCSPTempTrending.json b/Modules/TPC/run/tpcDCSPTempTrending.json new file mode 100644 index 0000000000..943d8dc8c8 --- /dev/null +++ b/Modules/TPC/run/tpcDCSPTempTrending.json @@ -0,0 +1,116 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "ccdb-test.cern.ch:8080", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "", + "type": "", + "start": "", + "end": "" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "ccdb-test.cern.ch:8080" + }, + "postprocessing": { + "periodSeconds": "10" + } + }, + "postprocessing": { + "TemperatureQC": { + "active": "true", + "resumeTrend": "false", + "className": "o2::quality_control::postprocessing::TrendingTask", + "moduleName": "QualityControl", + "detectorName": "TPC", + "producePlotsOnUpdate": "true", + "dataSources": [ + { + "type": "condition", + "path": "TPC/Calib/", + "names": [ "Temperature" ], + "reductorName": "o2::quality_control_modules::tpc::DCSPTempReductor", + "moduleName": "QcTPC" + } + ], + "plots": [ + { + "name": "Temp_Mean_ASide", + "title": "Mean Temperature A Side", + "varexp": "Temperature.tempMeanPerSide[0]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "mean temp A Side:time", + "graphErrors": "Temperature.tempMeanPerSideErr[0]:0" + }, + { + "name": "Temp_GradX_ASide", + "title": "GradX Temperature A Side", + "varexp": "Temperature.tempGradXPerSide[0]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "gradX temp A Side:time", + "graphErrors": "Temperature.tempGradXPerSideErr[0]:0" + }, + { + "name": "Temp_GradY_ASide", + "title": "GradY Temperature A Side", + "varexp": "Temperature.tempGradYPerSide[0]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "gradY temp A Side:time", + "graphErrors": "Temperature.tempGradYPerSideErr[0]:0" + }, + { + "name": "Temp_Mean_CSide", + "title": "Mean Temperature C Side", + "varexp": "Temperature.tempMeanPerSide[1]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "mean temp C Side:time", + "graphErrors": "Temperature.tempMeanPerSideErr[1]:0" + }, + { + "name": "Temp_GradX_CSide", + "title": "GradX Temperature C Side", + "varexp": "Temperature.tempGradXPerSide[1]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "gradX temp C Side:time", + "graphErrors": "Temperature.tempGradXPerSideErr[1]:0" + }, + { + "name": "Temp_GradY_CSide", + "title": "GradY Temperature C Side", + "varexp": "Temperature.tempGradYPerSide[1]:time", + "selection": "", + "option": "*L", + "graphAxisLabel": "gradY temp C Side:time", + "graphErrors": "Temperature.tempGradYPerSideErr[1]:0" + } + ], + "initTrigger": [ + "userorcontrol" + ], + "updateTrigger": [ + "foreachlatest:ccdb:TPC/Calib/Temperature/" + ], + "stopTrigger": [ + "userorcontrol" + ] + } + } + } + } + \ No newline at end of file diff --git a/Modules/TPC/src/DCSPTempReductor.cxx b/Modules/TPC/src/DCSPTempReductor.cxx new file mode 100644 index 0000000000..50c92d28e2 --- /dev/null +++ b/Modules/TPC/src/DCSPTempReductor.cxx @@ -0,0 +1,105 @@ +// 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 DCSPTempReductor.cxx +/// \author Marcel Lesch +/// + +#include "TPC/DCSPTempReductor.h" +#include "DataFormatsTPC/DCS.h" + +namespace o2::quality_control_modules::tpc +{ + +void* DCSPTempReductor::getBranchAddress() +{ + return &mStats; +} + +const char* DCSPTempReductor::getBranchLeafList() +{ + return "tempSensor[18]/F:tempSensorErr[18]:tempMeanPerSide[2]:tempMeanPerSideErr[2]:tempGradXPerSide[2]:tempGradXPerSideErr[2]:tempGradYPerSide[2]:tempGradYPerSideErr[2]"; +} + +bool DCSPTempReductor::update(ConditionRetriever& retriever) +{ + if (auto dcstemp = retriever.retrieve()) { + + int sensorCounter = 0; + std::vector sensorData[18]; + for (const auto sensor : dcstemp->raw) { + for (const auto& value : sensor.data) { + sensorData[sensorCounter].push_back(value.value); + } + calcMeanAndStddev(sensorData[sensorCounter], mStats.tempSensor[sensorCounter], mStats.tempSensorErr[sensorCounter]); + sensorCounter++; + if (sensorCounter > 17) + break; + } + + std::vector sideData[3]; // 0 mean, 1 gradX, 2 gradY + + // A-Side + for (const auto& value : dcstemp->statsA.data) { // why is this loop needed + sideData[0].push_back(value.value.mean); // will not work with the loop above + sideData[1].push_back(value.value.gradX); + sideData[2].push_back(value.value.gradY); + } + + calcMeanAndStddev(sideData[0], mStats.tempMeanPerSide[0], mStats.tempMeanPerSideErr[0]); + calcMeanAndStddev(sideData[1], mStats.tempGradXPerSide[0], mStats.tempGradXPerSideErr[0]); + calcMeanAndStddev(sideData[2], mStats.tempGradYPerSide[0], mStats.tempGradYPerSideErr[0]); + + for (int iCount = 0; iCount < 3; iCount++) { + sideData[iCount].clear(); + } + + // C-Side + for (const auto& value : dcstemp->statsC.data) { // why is this loop needed + sideData[0].push_back(value.value.mean); // will not work with the loop above + sideData[1].push_back(value.value.gradX); + sideData[2].push_back(value.value.gradY); + } + + calcMeanAndStddev(sideData[0], mStats.tempMeanPerSide[1], mStats.tempMeanPerSideErr[1]); + calcMeanAndStddev(sideData[1], mStats.tempGradXPerSide[1], mStats.tempGradXPerSideErr[1]); + calcMeanAndStddev(sideData[2], mStats.tempGradYPerSide[1], mStats.tempGradYPerSideErr[1]); + + return true; + } + return false; +} + +void DCSPTempReductor::calcMeanAndStddev(std::vector& values, float& mean, float& stddev) +{ + if (values.size() == 0) { + mean = 0.; + stddev = 0.; + return; + } + + // Mean + float sum = std::accumulate(values.begin(), values.end(), 0.0); + mean = sum / values.size(); + + // Stddev + if (values.size() == 1) { // we only have one point -> no stddev + stddev = 0.; + } else { // for >= 2 points, we calculate the spread + std::vector diff(values.size()); + std::transform(values.begin(), values.end(), diff.begin(), [mean](double x) { return x - mean; }); + double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); + stddev = std::sqrt(sq_sum / (values.size() * (values.size() - 1.))); + } +} + +} // namespace o2::quality_control_modules::tpc \ No newline at end of file From 8949fb16e2a6c19a940a2d0d943cf1b3746330bd Mon Sep 17 00:00:00 2001 From: mlesch Date: Thu, 31 Oct 2024 13:01:35 +0100 Subject: [PATCH 2/3] clean-up --- Modules/TPC/include/TPC/DCSPTempReductor.h | 8 ++++---- Modules/TPC/src/DCSPTempReductor.cxx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/TPC/include/TPC/DCSPTempReductor.h b/Modules/TPC/include/TPC/DCSPTempReductor.h index df9d5301c5..2787e3c9bb 100644 --- a/Modules/TPC/include/TPC/DCSPTempReductor.h +++ b/Modules/TPC/include/TPC/DCSPTempReductor.h @@ -29,9 +29,9 @@ namespace o2::quality_control_modules::tpc /// It produces a branch in the format: /// "tempSensor[18]/F:tempSensorErr[18]:tempMeanPerSide[2]:tempMeanPerSideErr[2]:tempGradXPerSide[2]:tempGradXPerSideErr[2]:tempGradYPerSide[2]:tempGradYPerSideErr[2]" /// tempSensor[i] is the raw sensor temperature for each of the 18 sensores -/// tempMeanPerSide[i] is the mean temperatue per TPC-Side (0: A-Side, 1: C-Side) -/// tempGradXPerSide[i] is the temperatue gradient in x direction per TPC-Side (0: A-Side, 1: C-Side) -/// tempGradYPerSide[i] is the temperatue gradient in y direction per TPC-Side (0: A-Side, 1: C-Side) +/// tempMeanPerSide[i] is the mean temperature per TPC-Side (0: A-Side, 1: C-Side) +/// tempGradXPerSide[i] is the temperature gradient in x direction per TPC-Side (0: A-Side, 1: C-Side) +/// tempGradYPerSide[i] is the temperature gradient in y direction per TPC-Side (0: A-Side, 1: C-Side) class DCSPTempReductor : public quality_control::postprocessing::ReductorConditionAny { @@ -54,7 +54,7 @@ class DCSPTempReductor : public quality_control::postprocessing::ReductorConditi Float_t tempGradXPerSide[2]; Float_t tempGradXPerSideErr[2]; // uncertainties - Float_t tempGradYPerSide[2]; // uncertainties + Float_t tempGradYPerSide[2]; Float_t tempGradYPerSideErr[2]; // uncertainties } mStats; diff --git a/Modules/TPC/src/DCSPTempReductor.cxx b/Modules/TPC/src/DCSPTempReductor.cxx index 50c92d28e2..b208a482d5 100644 --- a/Modules/TPC/src/DCSPTempReductor.cxx +++ b/Modules/TPC/src/DCSPTempReductor.cxx @@ -49,8 +49,8 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) std::vector sideData[3]; // 0 mean, 1 gradX, 2 gradY // A-Side - for (const auto& value : dcstemp->statsA.data) { // why is this loop needed - sideData[0].push_back(value.value.mean); // will not work with the loop above + for (const auto& value : dcstemp->statsA.data) { + sideData[0].push_back(value.value.mean); sideData[1].push_back(value.value.gradX); sideData[2].push_back(value.value.gradY); } @@ -64,8 +64,8 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) } // C-Side - for (const auto& value : dcstemp->statsC.data) { // why is this loop needed - sideData[0].push_back(value.value.mean); // will not work with the loop above + for (const auto& value : dcstemp->statsC.data) { + sideData[0].push_back(value.value.mean); sideData[1].push_back(value.value.gradX); sideData[2].push_back(value.value.gradY); } From b666a091701acc0f114b6095823a96031d19c497 Mon Sep 17 00:00:00 2001 From: mlesch Date: Tue, 19 Nov 2024 17:15:55 +0100 Subject: [PATCH 3/3] Implementing changes --- Modules/TPC/include/TPC/DCSPTempReductor.h | 2 -- Modules/TPC/include/TPC/Utility.h | 6 ++++ Modules/TPC/src/DCSPTempReductor.cxx | 40 +++++----------------- Modules/TPC/src/Utility.cxx | 23 +++++++++++++ 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/Modules/TPC/include/TPC/DCSPTempReductor.h b/Modules/TPC/include/TPC/DCSPTempReductor.h index 2787e3c9bb..0cdad5f1d6 100644 --- a/Modules/TPC/include/TPC/DCSPTempReductor.h +++ b/Modules/TPC/include/TPC/DCSPTempReductor.h @@ -57,8 +57,6 @@ class DCSPTempReductor : public quality_control::postprocessing::ReductorConditi Float_t tempGradYPerSide[2]; Float_t tempGradYPerSideErr[2]; // uncertainties } mStats; - - void calcMeanAndStddev(std::vector& values, float& mean, float& stddev); }; } // namespace o2::quality_control_modules::tpc diff --git a/Modules/TPC/include/TPC/Utility.h b/Modules/TPC/include/TPC/Utility.h index 59474b5c51..bfc17727a0 100644 --- a/Modules/TPC/include/TPC/Utility.h +++ b/Modules/TPC/include/TPC/Utility.h @@ -107,5 +107,11 @@ void calculateStatistics(const double* yValues, const double* yErrors, bool useE /// \param mean double&, reference to double that should store mean /// \param stddevOfMean double&, reference to double that should store stddev of mean void retrieveStatistics(std::vector& values, std::vector& errors, bool useErrors, double& mean, double& stddevOfMean); + +/// \brief Calculates mean and stddev from a vector +/// \param values std::vector& vector that contains the data points +/// \param mean float&, reference to float that should store mean +/// \param stddev float&, reference to float that should store stddev of mean +void calcMeanAndStddev(const std::vector& values, float& mean, float& stddev); } // namespace o2::quality_control_modules::tpc #endif // QUALITYCONTROL_TPCUTILITY_H \ No newline at end of file diff --git a/Modules/TPC/src/DCSPTempReductor.cxx b/Modules/TPC/src/DCSPTempReductor.cxx index b208a482d5..717f98510f 100644 --- a/Modules/TPC/src/DCSPTempReductor.cxx +++ b/Modules/TPC/src/DCSPTempReductor.cxx @@ -16,6 +16,7 @@ #include "TPC/DCSPTempReductor.h" #include "DataFormatsTPC/DCS.h" +#include "TPC/Utility.h" namespace o2::quality_control_modules::tpc { @@ -36,9 +37,9 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) int sensorCounter = 0; std::vector sensorData[18]; - for (const auto sensor : dcstemp->raw) { + for (const auto& sensor : dcstemp->raw) { for (const auto& value : sensor.data) { - sensorData[sensorCounter].push_back(value.value); + sensorData[sensorCounter].emplace_back(value.value); } calcMeanAndStddev(sensorData[sensorCounter], mStats.tempSensor[sensorCounter], mStats.tempSensorErr[sensorCounter]); sensorCounter++; @@ -50,9 +51,9 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) // A-Side for (const auto& value : dcstemp->statsA.data) { - sideData[0].push_back(value.value.mean); - sideData[1].push_back(value.value.gradX); - sideData[2].push_back(value.value.gradY); + sideData[0].emplace_back(value.value.mean); + sideData[1].emplace_back(value.value.gradX); + sideData[2].emplace_back(value.value.gradY); } calcMeanAndStddev(sideData[0], mStats.tempMeanPerSide[0], mStats.tempMeanPerSideErr[0]); @@ -65,9 +66,9 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) // C-Side for (const auto& value : dcstemp->statsC.data) { - sideData[0].push_back(value.value.mean); - sideData[1].push_back(value.value.gradX); - sideData[2].push_back(value.value.gradY); + sideData[0].emplace_back(value.value.mean); + sideData[1].emplace_back(value.value.gradX); + sideData[2].emplace_back(value.value.gradY); } calcMeanAndStddev(sideData[0], mStats.tempMeanPerSide[1], mStats.tempMeanPerSideErr[1]); @@ -79,27 +80,4 @@ bool DCSPTempReductor::update(ConditionRetriever& retriever) return false; } -void DCSPTempReductor::calcMeanAndStddev(std::vector& values, float& mean, float& stddev) -{ - if (values.size() == 0) { - mean = 0.; - stddev = 0.; - return; - } - - // Mean - float sum = std::accumulate(values.begin(), values.end(), 0.0); - mean = sum / values.size(); - - // Stddev - if (values.size() == 1) { // we only have one point -> no stddev - stddev = 0.; - } else { // for >= 2 points, we calculate the spread - std::vector diff(values.size()); - std::transform(values.begin(), values.end(), diff.begin(), [mean](double x) { return x - mean; }); - double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); - stddev = std::sqrt(sq_sum / (values.size() * (values.size() - 1.))); - } -} - } // namespace o2::quality_control_modules::tpc \ No newline at end of file diff --git a/Modules/TPC/src/Utility.cxx b/Modules/TPC/src/Utility.cxx index dffb2b4c75..a0548a1988 100644 --- a/Modules/TPC/src/Utility.cxx +++ b/Modules/TPC/src/Utility.cxx @@ -341,4 +341,27 @@ void retrieveStatistics(std::vector& values, std::vector& errors } } +void calcMeanAndStddev(const std::vector& values, float& mean, float& stddev) +{ + if (values.size() == 0) { + mean = 0.; + stddev = 0.; + return; + } + + // Mean + const float sum = std::accumulate(values.begin(), values.end(), 0.0); + mean = sum / values.size(); + + // Stddev + if (values.size() == 1) { // we only have one point -> no stddev + stddev = 0.; + } else { // for >= 2 points, we calculate the spread + std::vector diff(values.size()); + std::transform(values.begin(), values.end(), diff.begin(), [mean](auto x) { return x - mean; }); + const auto sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.f); + stddev = std::sqrt(sq_sum / (values.size() * (values.size() - 1.))); + } +} + } // namespace o2::quality_control_modules::tpc \ No newline at end of file