Project
Loading...
Searching...
No Matches
BadChannelCalibrationDevice.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
13#include "CCDB/CcdbApi.h"
14#include "CCDB/CcdbObjectInfo.h"
21#include "Framework/Output.h"
23#include "TObjString.h"
24#include <TBuffer3D.h>
25#include <cmath>
26#include <limits>
27#include <numeric>
28
30{
31
32void BadChannelCalibrationDevice::init(o2::framework::InitContext& ic)
33{
35 mLoggingInterval = ic.options().get<int>("logging-interval") * 1000;
36
37 mCalibrator = std::make_unique<o2::mch::calibration::BadChannelCalibrator>();
38 mCalibrator->setSlotLength(o2::calibration::INFINITE_TF);
39 mCalibrator->setUpdateAtTheEndOfRunOnly();
40 mCalibrator->setLoggingInterval(mLoggingInterval);
41 mTimeStamp = std::numeric_limits<uint64_t>::max();
42}
43
44//_________________________________________________________________
45void BadChannelCalibrationDevice::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj)
46{
48}
49
50void BadChannelCalibrationDevice::logStats(size_t dataSize)
51{
52 static auto loggerStart = std::chrono::high_resolution_clock::now();
53 static auto loggerEnd = loggerStart;
54 static size_t nDigits = 0;
55 static size_t nTF = 0;
56 static size_t nTFtot = 0;
57 static size_t nTFtotWithData = 0;
58
59 if (mLoggingInterval == 0) {
60 return;
61 }
62
63 nDigits += dataSize;
64 nTF += 1;
65 nTFtot += 1;
66 if (dataSize > 1000) {
67 nTFtotWithData += 1;
68 }
69
70 loggerEnd = std::chrono::high_resolution_clock::now();
71 std::chrono::duration<double, std::milli> loggerElapsed = loggerEnd - loggerStart;
72 if (loggerElapsed.count() > mLoggingInterval) {
73 LOG(warning) << "received " << nDigits << " digits in " << nTF << " time frames";
74 LOG(warning) << "received " << nTFtotWithData << " time frames with data out of " << nTFtot << " total time frames ("
75 << ((nTFtot > 0) ? (nTFtotWithData * 100.0) / nTFtot : 0.0) << "%)";
76 nDigits = 0;
77 nTF = 0;
78 loggerStart = std::chrono::high_resolution_clock::now();
79 }
80}
81
82void BadChannelCalibrationDevice::run(o2::framework::ProcessingContext& pc)
83{
84 if (mSkipData) {
85 return;
86 }
87
89 o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mCalibrator->getCurrentTFInfo());
90 mTimeStamp = std::min(mTimeStamp, mCalibrator->getCurrentTFInfo().creation);
91 auto data = pc.inputs().get<gsl::span<o2::mch::calibration::PedestalDigit>>("digits");
92 mCalibrator->process(data);
93
94 if (!BadChannelCalibratorParam::Instance().onlyAtEndOfStream) {
95 std::string reason;
96 if (mCalibrator->readyToSend(reason)) {
97 mHasEnoughStat = true;
98 LOGP(warning, "We're ready to send output to CCDB ({})", reason);
99 sendOutput(pc.outputs(), reason);
100 mSkipData = true;
101 }
102 }
103 logStats(data.size());
104}
105
106template <typename T>
107ccdb::CcdbObjectInfo createCcdbInfo(const T& object, uint64_t timeStamp, std::string_view reason)
108{
109 auto clName = o2::utils::MemFileHelper::getClassName(object);
110 auto flName = o2::ccdb::CcdbApi::generateFileName(clName);
111 std::map<std::string, std::string> md;
112 md["upload-reason"] = reason;
113 constexpr auto fiveDays = 5 * o2::ccdb::CcdbObjectInfo::DAY;
114 return o2::ccdb::CcdbObjectInfo("MCH/Calib/BadChannel", clName, flName, md, timeStamp, timeStamp + fiveDays);
115}
116
117void BadChannelCalibrationDevice::endOfStream(o2::framework::EndOfStreamContext& ec)
118{
119 if (BadChannelCalibratorParam::Instance().onlyAtEndOfStream) {
120 std::string reason;
121 if (mCalibrator->readyToSend(reason)) {
122 mHasEnoughStat = true;
123 }
124 sendOutput(ec.outputs(), "End Of Stream");
125 }
126}
127
128std::string toCSV(const std::vector<o2::mch::DsChannelId>& channels)
129{
130 std::stringstream csv;
131 csv << fmt::format("solarid,dsid,ch\n");
132
133 for (const auto& c : channels) {
134 csv << fmt::format("{},{},{}\n",
135 c.getSolarId(), c.getElinkId(), c.getChannel());
136 }
137
138 return csv.str();
139}
140
141template <typename T>
144 T* payload,
145 o2::ccdb::CcdbObjectInfo* payloadInfo)
146{
147
149 auto image = o2::ccdb::CcdbApi::createObjectImage(payload, payloadInfo);
150
151 LOG(warning) << "Sending object " << payloadInfo->getPath()
152 << " of type" << payloadInfo->getObjectType()
153 << " /" << payloadInfo->getFileName()
154 << " of size " << image->size()
155 << " bytes, valid for " << payloadInfo->getStartValidityTimestamp()
156 << " : " << payloadInfo->getEndValidityTimestamp();
157
158 output.snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBPayload, "MCH_BADCHAN", subSpec}, *image.get());
159 output.snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBWrapper, "MCH_BADCHAN", subSpec}, *payloadInfo);
160}
161
162void BadChannelCalibrationDevice::sendOutput(o2::framework::DataAllocator& output,
163 std::string_view reason)
164{
165 auto& slot = mCalibrator->getFirstSlot();
166 const auto pedData = slot.getContainer();
167 uint64_t nentries = std::accumulate(pedData->cbegin(), pedData->cend(),
168 0,
169 [&](uint64_t n, const PedestalChannel& c) { return n +
170 static_cast<uint64_t>(c.mEntries); });
171 std::string reason_with_entries;
172
173 if (pedData->size() > 0) {
174 int mean = static_cast<int>(std::round(static_cast<float>(nentries) / pedData->size()));
175 reason_with_entries = fmt::format("{} ; <entries per channel>={}", reason, mean);
176 } else {
177 reason_with_entries = fmt::format("{} ; no entries", reason);
178 }
179
180 LOGP(warning, "sendOutput: {}", reason_with_entries);
181 mCalibrator->finalize();
182
183 // the bad channels table is only updated if there is enough statistics
184 if (mHasEnoughStat) {
185 // send regular bad channel object to subspec 0. This regular object
186 // is meant for O2 consumption (in reconstruction and/or simulation)
187 const auto& badChannels = mCalibrator->getBadChannelsVector();
188 auto info = createCcdbInfo(badChannels, mTimeStamp, reason_with_entries);
189
190 sendCalibrationOutput(output, 0, &badChannels, &info);
191
192 // send also a simplified (in comma-separated values format) version
193 // of the bad channel list to subspec 1.
194 // This simplified version is meant for DCS usage
195 // (to populate the Oracle online DB for electronics configuration)
196
197 TObjString badChannelsPOD(toCSV(badChannels).c_str());
198 auto infoPOD = createCcdbInfo(badChannelsPOD, mTimeStamp, reason_with_entries);
199
200 sendCalibrationOutput(output, 1, &badChannelsPOD, &infoPOD);
201
202 LOGP(info, "csv={}", badChannelsPOD.String().Data());
203 } else {
204 LOGP(error, "CCDB not updated: {}", reason_with_entries);
205 }
206
207 // and finally send also the data used to compute the bad channel map
208 // on a separate channel (for QC mainly)
209 // this is sent also if statistics is too low, for diagnostics purposes
210 output.snapshot(o2::framework::Output{"MCH", "PEDESTALS", 0},
211 mCalibrator->getPedestalsVector());
212 if (mHasEnoughStat) {
213 output.snapshot(o2::framework::Output{"MCH", "BADCHAN", 0},
214 mCalibrator->getBadChannelsVector());
215 } else {
216 output.cookDeadBeef(o2::framework::Output{"MCH", "BADCHAN"});
217 }
218}
219} // namespace o2::mch::calibration
Utils and constants for calibration and related workflows.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
uint32_t c
Definition RawData.h:2
void checkUpdates(o2::framework::ProcessingContext &pc)
bool finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
static std::string generateFileName(const std::string &inp)
Definition CcdbApi.cxx:816
static std::unique_ptr< std::vector< char > > createObjectImage(const T *obj, CcdbObjectInfo *info=nullptr)
Definition CcdbApi.h:103
long getEndValidityTimestamp() const
const std::string & getPath() const
static constexpr long DAY
const std::string & getObjectType() const
long getStartValidityTimestamp() const
const std::string & getFileName() const
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
GLdouble n
Definition glcorearb.h:1982
GLeglImageOES image
Definition glcorearb.h:4021
GLenum GLsizei dataSize
Definition glcorearb.h:3994
GLboolean * data
Definition glcorearb.h:298
constexpr TFType INFINITE_TF
Definition TimeSlot.h:30
std::string toCSV(const std::vector< o2::mch::DsChannelId > &channels)
ccdb::CcdbObjectInfo createCcdbInfo(const T &object, uint64_t timeStamp, std::string_view reason)
void sendCalibrationOutput(o2::framework::DataAllocator &output, header::DataHeader::SubSpecificationType subSpec, T *payload, o2::ccdb::CcdbObjectInfo *payloadInfo)
static void fillTFIDInfo(o2::framework::ProcessingContext &pc, o2::dataformats::TFIDInfo &ti)
static constexpr o2::header::DataOrigin gDataOriginCDBWrapper
Definition Utils.h:44
static constexpr o2::header::DataOrigin gDataOriginCDBPayload
Definition Utils.h:43
uint32_t SubSpecificationType
Definition DataHeader.h:620
static std::string getClassName(const T &obj)
get the class name of the object
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< ChannelData > channels