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.
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
char error[CURL_ERROR_SIZE]
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:905
static std::unique_ptr< std::vector< char > > createObjectImage(const T *obj, CcdbObjectInfo *info=nullptr)
Definition CcdbApi.h:109
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
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
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