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 mTimeStamp = std::numeric_limits<uint64_t>::max();
41}
42
43//_________________________________________________________________
44void BadChannelCalibrationDevice::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj)
45{
47}
48
49void BadChannelCalibrationDevice::logStats(size_t dataSize)
50{
51 static auto loggerStart = std::chrono::high_resolution_clock::now();
52 static auto loggerEnd = loggerStart;
53 static size_t nDigits = 0;
54 static size_t nTF = 0;
55
56 if (mLoggingInterval == 0) {
57 return;
58 }
59
60 nDigits += dataSize;
61 nTF += 1;
62
63 loggerEnd = std::chrono::high_resolution_clock::now();
64 std::chrono::duration<double, std::milli> loggerElapsed = loggerEnd - loggerStart;
65 if (loggerElapsed.count() > 1000) {
66 LOG(info) << "received " << nDigits << " digits in " << nTF << " time frames";
67 nDigits = 0;
68 nTF = 0;
69 loggerStart = std::chrono::high_resolution_clock::now();
70 }
71}
72
73void BadChannelCalibrationDevice::run(o2::framework::ProcessingContext& pc)
74{
75 if (mSkipData) {
76 return;
77 }
78
80 o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mCalibrator->getCurrentTFInfo());
81 mTimeStamp = std::min(mTimeStamp, mCalibrator->getCurrentTFInfo().creation);
82 auto data = pc.inputs().get<gsl::span<o2::mch::calibration::PedestalDigit>>("digits");
83 mCalibrator->process(data);
84
85 if (!BadChannelCalibratorParam::Instance().onlyAtEndOfStream) {
86 std::string reason;
87 if (mCalibrator->readyToSend(reason)) {
88 mHasEnoughStat = true;
89 LOGP(info, "We're ready to send output to CCDB ({})", reason);
90 sendOutput(pc.outputs(), reason);
91 mSkipData = true;
92 }
93 }
94 logStats(data.size());
95}
96
97template <typename T>
98ccdb::CcdbObjectInfo createCcdbInfo(const T& object, uint64_t timeStamp, std::string_view reason)
99{
100 auto clName = o2::utils::MemFileHelper::getClassName(object);
101 auto flName = o2::ccdb::CcdbApi::generateFileName(clName);
102 std::map<std::string, std::string> md;
103 md["upload-reason"] = reason;
104 constexpr auto fiveDays = 5 * o2::ccdb::CcdbObjectInfo::DAY;
105 return o2::ccdb::CcdbObjectInfo("MCH/Calib/BadChannel", clName, flName, md, timeStamp, timeStamp + fiveDays);
106}
107
108void BadChannelCalibrationDevice::endOfStream(o2::framework::EndOfStreamContext& ec)
109{
110 if (BadChannelCalibratorParam::Instance().onlyAtEndOfStream) {
111 std::string reason;
112 if (mCalibrator->readyToSend(reason)) {
113 mHasEnoughStat = true;
114 }
115 sendOutput(ec.outputs(), "End Of Stream");
116 }
117}
118
119std::string toCSV(const std::vector<o2::mch::DsChannelId>& channels)
120{
121 std::stringstream csv;
122 csv << fmt::format("solarid,dsid,ch\n");
123
124 for (const auto& c : channels) {
125 csv << fmt::format("{},{},{}\n",
126 c.getSolarId(), c.getElinkId(), c.getChannel());
127 }
128
129 return csv.str();
130}
131
132template <typename T>
135 T* payload,
136 o2::ccdb::CcdbObjectInfo* payloadInfo)
137{
138
140 auto image = o2::ccdb::CcdbApi::createObjectImage(payload, payloadInfo);
141
142 LOG(info) << "Sending object " << payloadInfo->getPath()
143 << " of type" << payloadInfo->getObjectType()
144 << " /" << payloadInfo->getFileName()
145 << " of size " << image->size()
146 << " bytes, valid for " << payloadInfo->getStartValidityTimestamp()
147 << " : " << payloadInfo->getEndValidityTimestamp();
148
149 output.snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBPayload, "MCH_BADCHAN", subSpec}, *image.get());
150 output.snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBWrapper, "MCH_BADCHAN", subSpec}, *payloadInfo);
151}
152
153void BadChannelCalibrationDevice::sendOutput(o2::framework::DataAllocator& output,
154 std::string_view reason)
155{
156 auto& slot = mCalibrator->getFirstSlot();
157 const auto pedData = slot.getContainer();
158 uint64_t nentries = std::accumulate(pedData->cbegin(), pedData->cend(),
159 0,
160 [&](uint64_t n, const PedestalChannel& c) { return n +
161 static_cast<uint64_t>(c.mEntries); });
162 std::string reason_with_entries;
163
164 if (pedData->size() > 0) {
165 int mean = static_cast<int>(std::round(static_cast<float>(nentries) / pedData->size()));
166 reason_with_entries = fmt::format("{} ; <entries per channel>={}", reason, mean);
167 } else {
168 reason_with_entries = fmt::format("{} ; no entries", reason);
169 }
170
171 LOGP(info, "sendOutput: {}", reason_with_entries);
172 mCalibrator->finalize();
173
174 // the bad channels table is only updated if there is enough statistics
175 if (mHasEnoughStat) {
176 // send regular bad channel object to subspec 0. This regular object
177 // is meant for O2 consumption (in reconstruction and/or simulation)
178 const auto& badChannels = mCalibrator->getBadChannelsVector();
179 auto info = createCcdbInfo(badChannels, mTimeStamp, reason_with_entries);
180
181 sendCalibrationOutput(output, 0, &badChannels, &info);
182
183 // send also a simplified (in comma-separated values format) version
184 // of the bad channel list to subspec 1.
185 // This simplified version is meant for DCS usage
186 // (to populate the Oracle online DB for electronics configuration)
187
188 TObjString badChannelsPOD(toCSV(badChannels).c_str());
189 auto infoPOD = createCcdbInfo(badChannelsPOD, mTimeStamp, reason_with_entries);
190
191 sendCalibrationOutput(output, 1, &badChannelsPOD, &infoPOD);
192
193 LOGP(info, "csv={}", badChannelsPOD.String().Data());
194 } else {
195 LOGP(error, "CCDB not updated: {}", reason_with_entries);
196 }
197
198 // and finally send also the data used to compute the bad channel map
199 // on a separate channel (for QC mainly)
200 // this is sent also if statistics is too low, for diagnostics purposes
201 output.snapshot(o2::framework::Output{"MCH", "PEDESTALS", 0},
202 mCalibrator->getPedestalsVector());
203 if (mHasEnoughStat) {
204 output.snapshot(o2::framework::Output{"MCH", "BADCHAN", 0},
205 mCalibrator->getBadChannelsVector());
206 } else {
207 output.cookDeadBeef(o2::framework::Output{"MCH", "BADCHAN"});
208 }
209}
210} // 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:798
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