Project
Loading...
Searching...
No Matches
DCSProcessor.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#include <string_view>
17
18// ROOT includes
19#include "TLinearFitter.h"
20#include "TVectorD.h"
21
22// O2 includes
26#include "Framework/Logger.h"
27
28#include "TPCdcs/DCSProcessor.h"
29
30using namespace o2::tpc;
31using namespace o2::dcs;
32
33void DCSProcessor::process(const gsl::span<const DPCOM> dps)
34{
35 if (dps.size() == 0) {
36 return;
37 }
38
39 mHasData = true;
40
41 using namespace std::literals;
42 constexpr auto TEMP_ID{"TPC_PT"sv};
43 constexpr auto HV_ID{"TPC_HV"sv};
44 constexpr auto GAS_ID1{"TPC_GC"sv};
45 constexpr auto GAS_ID2{"TPC_An"sv};
46
47 for (const auto& dp : dps) {
48 const std::string_view alias(dp.id.get_alias());
49 const auto id = alias.substr(0, 6);
50 if (id == TEMP_ID) {
51 LOGP(debug, "Temperature DP: {}", alias);
53 } else if (id == HV_ID) {
54 LOGP(debug, "HV DP: {}", alias);
55 fillHV(dp);
56 } else if (id == GAS_ID1 || id == GAS_ID2) {
57 LOGP(debug, "Gas DP: {}", alias);
58 fillGas(dp);
59 } else {
60 LOGP(warning, "Unknown data point: {}", alias);
61 }
62 }
63}
64
65float DCSProcessor::getValueF(const DPCOM& dp) const
66{
67 if (dp.id.get_type() == DeliveryType::DPVAL_FLOAT) {
68 return o2::dcs::getValue<float>(dp);
69 } else if (dp.id.get_type() == DeliveryType::DPVAL_DOUBLE) {
70 return static_cast<float>(o2::dcs::getValue<double>(dp));
71 } else {
72 LOGP(warning, "Unexpected delivery type for {}: {}", dp.id.get_alias(), (int)dp.id.get_type());
73 }
74
75 return 0.f;
76}
77
79{
80 const std::string_view alias(dp.id.get_alias());
81 const auto value = getValueF(dp);
82 const auto time = dp.data.get_epoch_time();
83 mTemperature.fill(alias, time, value);
84}
85
87{
88 const std::string_view alias(dp.id.get_alias());
89 const auto time = dp.data.get_epoch_time();
90
91 const auto type = dp.id.get_type();
92 if (alias.back() == 'S') { //
93 uint32_t value;
94 // TODO: Remove once type is clear
95 static bool statTypePrinted = false;
96 if (!statTypePrinted) {
97 LOGP(info, "Delivery type for STATUS ({}): {}", alias, (int)type);
98 statTypePrinted = true;
99 }
100 if (type == DeliveryType::DPVAL_UINT) {
101 value = o2::dcs::getValue<uint32_t>(dp);
102 } else if (type == DeliveryType::DPVAL_INT) {
103 value = uint32_t(o2::dcs::getValue<int32_t>(dp));
104 } else {
105 value = uint32_t(getValueF(dp));
106 }
107 mHighVoltage.fillStatus(alias, time, value);
108 } else {
109 // TODO: Remove once type is clear
110 static bool uiTypePrinted = false;
111 if (!uiTypePrinted) {
112 LOGP(info, "Delivery type for current, voltage ({}): {}", alias, (int)type);
113 uiTypePrinted = true;
114 }
115 const auto value = getValueF(dp);
116 mHighVoltage.fillUI(alias, time, value);
117 }
118}
119
121{
122 const std::string_view alias(dp.id.get_alias());
123 const auto value = getValueF(dp);
124 const auto time = dp.data.get_epoch_time();
125 mGas.fill(alias, time, value);
126}
127
129{
132 finalizeGas();
133 mHasData = false;
134}
135
137{
139 TLinearFitter fitter(3, "x0 ++ x1 ++ x2");
140 bool nextInterval = true;
141 std::array<size_t, dcs::Temperature::SensorsPerSide> startPos{};
142 const size_t sensorOffset = (side == Side::C) ? dcs::Temperature::SensorsPerSide : 0;
143 dcs::TimeStampType refTime = getMinTime(mTemperature.raw);
144
145 while (nextInterval) {
146 // TODO: check if we should use refTime
147 dcs::TimeStampType firstTime = std::numeric_limits<dcs::TimeStampType>::max();
148
149 nextInterval = false;
150 for (size_t iSensor = 0; iSensor < dcs::Temperature::SensorsPerSide; ++iSensor) {
151 const auto& sensor = mTemperature.raw[iSensor + sensorOffset];
152
153 LOGP(debug, "sensor {}, start {}, size {}", sensor.sensorNumber, startPos[iSensor], sensor.data.size());
154 while (startPos[iSensor] < sensor.data.size()) {
155 const auto& dataPoint = sensor.data[startPos[iSensor]];
156 if ((dataPoint.time - refTime) >= mFitInterval) {
157 LOGP(debug, "sensor {}, {} - {} >= {}", sensor.sensorNumber, dataPoint.time, refTime, mFitInterval);
158 break;
159 }
160 nextInterval = true;
161 firstTime = std::min(firstTime, dataPoint.time);
162 const auto temperature = dataPoint.value;
163 // sanity check
164 if (temperature < 15 || temperature > 25) {
165 ++startPos[iSensor];
166 continue;
167 }
168 const auto& pos = dcs::Temperature::SensorPosition[iSensor + sensorOffset];
169 double x[] = {1., double(pos.x), double(pos.y)};
170 fitter.AddPoint(x, temperature, 1);
171 ++startPos[iSensor];
172 }
173 }
174 if (firstTime < std::numeric_limits<dcs::TimeStampType>::max()) {
175 fitter.Eval();
176 LOGP(info, "Side {}, fit interval {} - {} with {} points", int(side), refTime, refTime + mFitInterval - 1, fitter.GetNpoints());
177
178 auto& stats = (side == Side::A) ? mTemperature.statsA : mTemperature.statsC;
179 auto& stat = stats.data.emplace_back();
180 stat.time = firstTime;
181 stat.value.mean = fitter.GetParameter(0);
182 stat.value.gradX = fitter.GetParameter(1);
183 stat.value.gradY = fitter.GetParameter(2);
184
185 fitter.ClearPoints();
186 refTime += mFitInterval;
187 }
188 }
189}
190
192{
193 mTemperature.sortAndClean();
196 mTimeTemperature = {getMinTime(mTemperature.raw), getMaxTime(mTemperature.raw)};
197}
198
200{
201 mHighVoltage.sortAndClean();
202
203 auto minTime = getMinTime(mHighVoltage.currents);
204 minTime = std::min(minTime, getMinTime(mHighVoltage.voltages));
205 minTime = std::min(minTime, getMinTime(mHighVoltage.states));
206
207 auto maxTime = getMaxTime(mHighVoltage.currents);
208 maxTime = std::max(maxTime, getMaxTime(mHighVoltage.voltages));
209 maxTime = std::max(maxTime, getMaxTime(mHighVoltage.states));
210
211 mTimeHighVoltage = {minTime, maxTime};
212}
213
215{
216 mGas.sortAndClean();
217 mTimeGas = {mGas.getMinTime(), mGas.getMaxTime()};
218}
219
221{
222 if (!mDebugStream) {
223 mDebugStream = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugOutputName.data(), "recreate");
224 }
225
226 *mDebugStream << "dcs"
227 << "Temperature=" << mTemperature
228 << "HV=" << mHighVoltage
229 << "Gas=" << mGas
230 << "\n";
231}
232
234{
235 if (mDebugStream) {
236 mDebugStream->Close();
237 }
238}
int16_t time
Definition RawEventData.h:4
uint16_t pos
Definition RawData.h:3
uint32_t side
Definition RawData.h:0
TPC DCS data point processor.
std::ostringstream debug
DeliveryType get_type() const noexcept
const char *const get_alias() const noexcept
dcs::TimeStampType getMinTime(const std::vector< dcs::DataPointVector< T > > &data)
get minimum time over all sensors. Assumes data is sorted in time
void process(const gsl::span< const DPCOM > dps)
void fitTemperature(Side side)
void fillHV(const DPCOM &dp)
dcs::TimeStampType getMaxTime(const std::vector< dcs::DataPointVector< T > > &data)
get maximum time over all sensors. Assumes data is sorted in time
void fillTemperature(const DPCOM &dp)
float getValueF(const DPCOM &dp) const
void writeDebug()
write the debug output tree
void fillGas(const DPCOM &dp)
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
uint64_t TimeStampType
Definition DCS.h:41
Global TPC definitions and constants.
Definition SimTraits.h:167
Side
TPC readout sidE.
Definition Defs.h:35
@ A
Definition Defs.h:35
@ C
Definition Defs.h:36
uint64_t get_epoch_time() const noexcept
void fill(std::string_view sensor, const TimeStampType time, const DataType value)
Definition DCS.h:400
TimeStampType getMaxTime() const
Definition DCS.cxx:104
TimeStampType getMinTime() const
Definition DCS.cxx:87
void sortAndClean()
Definition DCS.h:443
void sortAndClean()
Definition DCS.h:359
std::vector< RawDPsF > voltages
voltages per GEM stack, counting is IROCs GEM1 top, bottom, GEM2 top, bottom, .. O1 ....
Definition DCS.h:306
std::vector< RawDPsState > states
HV state per sector.
Definition DCS.h:308
std::vector< RawDPsF > currents
currents per GEM stack, counting is IROCs GEM1 top, bottom, GEM2 top, bottom, .. O1 ....
Definition DCS.h:307
void fillStatus(std::string_view sensor, const TimeStampType time, const uint32_t value)
Fill stack status information.
Definition DCS.h:349
void fillUI(std::string_view sensor, const TimeStampType time, const DataType value)
Fill voltage and current information.
Definition DCS.h:327
static constexpr std::array< Position, SensorsPerSide *SIDES > SensorPosition
Definition DCS.h:190
StatsDPs statsA
statistics fit values per integration time A-Side
Definition DCS.h:225
StatsDPs statsC
statistics fit values per integration time C-Side
Definition DCS.h:226
static constexpr int SensorsPerSide
number of temperature sensors in the active volume per side
Definition DCS.h:186
std::vector< RawDPsF > raw
raw temperature values from DCS for
Definition DCS.h:227
void fill(std::string_view sensor, const TimeStampType time, const DataType temperature)
Definition DCS.h:239