Project
Loading...
Searching...
No Matches
bad-channels-ccdb.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
12#include <boost/program_options.hpp>
13#include <algorithm>
14#include <ctime>
15#include <fstream>
16#include <iterator>
17#include <numeric>
18#include <regex>
19#include <set>
20#include <string>
21#include <vector>
22#include "CCDB/CcdbApi.h"
30
31namespace po = boost::program_options;
32
33using BadChannelsVector = std::vector<o2::mch::DsChannelId>;
34
35std::string ccdbPath(const std::string badChannelType)
36{
37 return fmt::format("MCH/Calib/{}", badChannelType);
38}
39
40std::set<uint64_t> listTSWhenBadChannelsChange(const std::string ccdbUrl, const std::string badChannelType,
41 uint64_t startTimestamp, uint64_t endTimestamp, bool verbose)
42{
43 std::set<uint64_t> tsChanges{startTimestamp};
44
45 std::cout << std::endl;
47 api.init(ccdbUrl);
48 auto source = ccdbPath(badChannelType);
49
50 // store every timestamps in the time range when the bad channels potentially change
51 if (verbose) {
52 std::cout << fmt::format("\nlist of {} files potentially valid in the range {} - {}:\n", source, startTimestamp, endTimestamp);
53 }
54 std::istringstream fileInfo(api.list(source, false, "text/plain"));
55 std::string dummy{};
56 std::string path{};
57 uint64_t begin = 0;
58 uint64_t end = 0;
59 uint64_t creation = 0;
60 bool inRange = false;
61 for (std::string line; std::getline(fileInfo, line);) {
62 if (line.find("Validity:") == 0) {
63 std::istringstream in(line);
64 in >> dummy >> begin >> dummy >> end;
65 if (begin < endTimestamp && end > startTimestamp) {
66 if (begin >= startTimestamp) {
67 tsChanges.emplace(begin);
68 }
69 if (end < endTimestamp) {
70 tsChanges.emplace(end);
71 }
72 inRange = true;
73 }
74 } else if (verbose) {
75 if (line.find("ID:") == 0) {
76 std::istringstream in(line);
77 in >> dummy >> path;
78 } else if (inRange && line.find("Created:") == 0) {
79 std::istringstream in(line);
80 in >> dummy >> creation;
81 std::cout << fmt::format("- {}\n", path);
82 std::cout << fmt::format(" validity range: {} - {}\n", begin, end);
83 std::cout << fmt::format(" creation time: {}\n", creation);
84 inRange = false;
85 }
86 }
87 }
88 if (verbose) {
89 std::cout << fmt::format("\nlist of timestamps when the bad channels potentially change:\n");
90 for (auto ts : tsChanges) {
91 std::cout << fmt::format(" {}\n", ts);
92 }
93 }
94
95 // select timestamps when the bad channels actually change
96 if (verbose) {
97 std::cout << fmt::format("\nlist of {} files actually valid in the range {} - {}:\n", source, startTimestamp, endTimestamp);
98 }
99 std::map<std::string, std::string> metadata{};
100 std::string currentETag{};
101 for (auto itTS = tsChanges.begin(); itTS != tsChanges.end();) {
102 auto headers = api.retrieveHeaders(source, metadata, *itTS);
103 if (headers["ETag"].empty()) {
104 std::cout << "- Warning: missing file" << std::endl;
105 auto validUntil = (std::next(itTS) != tsChanges.end()) ? *std::next(itTS) : endTimestamp;
106 std::cout << fmt::format(" validity range: {} - {}\n", *itTS, validUntil);
107 ++itTS;
108 } else if (headers["ETag"] == currentETag) {
109 itTS = tsChanges.erase(itTS);
110 } else {
111 if (verbose) {
112 std::cout << fmt::format("- {}\n", headers["Location"]);
113 std::cout << fmt::format(" validity range: {} - {}\n", headers["Valid-From"], headers["Valid-Until"]);
114 std::cout << fmt::format(" creation time: {}\n", headers["Created"]);
115 }
116 currentETag = headers["ETag"];
117 ++itTS;
118 }
119 }
120 std::cout << fmt::format("\nlist of timestamps when the bad channels actually change:\n");
121 for (auto ts : tsChanges) {
122 std::cout << fmt::format(" {}\n", ts);
123 }
124
125 return tsChanges;
126}
127
129 const std::string badChannelType, uint64_t timestamp, bool verbose)
130{
131 std::cout << std::endl;
133 api.init(ccdbUrl);
134 std::map<std::string, std::string> metadata;
135 auto source = ccdbPath(badChannelType);
136 auto* badChannels = api.retrieveFromTFileAny<BadChannelsVector>(source, metadata, timestamp);
137 if (badChannels == nullptr) {
138 std::cout << "do you want to proceed anyway? [y/n] ";
139 std::string response{};
140 while (true) {
141 std::cin >> response;
142 if (response == "y") {
143 std::cout << "number of bad channels = 0" << std::endl;
144 return {};
145 } else if (response == "n") {
146 exit(3);
147 }
148 }
149 }
150 std::cout << "number of bad channels = " << badChannels->size() << std::endl;
151 if (verbose) {
152 for (const auto& badChannel : *badChannels) {
153 std::cout << badChannel.asString() << "\n";
154 }
155 }
156 return *badChannels;
157}
158
160{
161 static auto det2elec = o2::mch::raw::createDet2ElecMapper<o2::mch::raw::ElectronicMapperGenerated>();
162 const auto& seg = o2::mch::mapping::segmentation(dsDetId.deId());
163 auto dsElecId = det2elec(dsDetId);
164 seg.forEachPadInDualSampa(dsDetId.dsId(), [&](int pad) {
165 uint8_t channel = seg.padDualSampaChannel(pad);
166 const auto c = o2::mch::DsChannelId(dsElecId->solarId(), dsElecId->elinkId(), channel);
167 bv.emplace_back(c);
168 });
169}
170
171void rejectSolars(const std::vector<uint16_t> solarIds, BadChannelsVector& bv)
172{
173 for (auto solar : solarIds) {
174 auto ds = o2::mch::raw::getDualSampas<o2::mch::raw::ElectronicMapperGenerated>(solar);
175 for (const auto& dsDetId : ds) {
176 rejectDS(dsDetId, bv);
177 }
178 }
179}
180
181void rejectDSs(const std::vector<uint16_t> dsIdxs, BadChannelsVector& bv)
182{
183 for (auto ds : dsIdxs) {
185 std::cout << "Error: invalid DS index " << ds << std::endl;
186 continue;
187 }
189 rejectDS(dsDetId, bv);
190 }
191}
192
193void rejectHVLVs(const std::vector<std::string> dcsAliases, BadChannelsVector& bv)
194{
195 for (auto alias : dcsAliases) {
196 if (!o2::mch::dcs::isValid(alias)) {
197 std::cout << "Error: invalid alias " << alias << std::endl;
198 continue;
199 }
200 for (auto ds : o2::mch::dcs::aliasToDsIndices(alias)) {
202 rejectDS(dsDetId, bv);
203 }
204 }
205}
206
207void rejectDEs(const std::vector<uint16_t> deIds, BadChannelsVector& bv)
208{
209 static auto det2elec = o2::mch::raw::createDet2ElecMapper<o2::mch::raw::ElectronicMapperGenerated>();
210 for (auto de : deIds) {
212 std::cout << "Error: invalid DE ID " << de << std::endl;
213 continue;
214 }
216 seg.forEachPad([&](int pad) {
217 auto ds = seg.padDualSampaId(pad);
218 o2::mch::raw::DsDetId dsDetId(de, ds);
219 auto dsElecId = det2elec(dsDetId);
220 uint8_t channel = seg.padDualSampaChannel(pad);
221 const auto c = o2::mch::DsChannelId(dsElecId->solarId(), dsElecId->elinkId(), channel);
222 bv.emplace_back(c);
223 });
224 }
225}
226
227void uploadBadChannels(const std::string ccdbUrl,
228 const std::string badChannelType,
229 uint64_t startTimestamp,
230 uint64_t endTimestamp,
232 bool makeDefault)
233{
234 std::sort(bv.begin(), bv.end());
235 bv.erase(std::unique(bv.begin(), bv.end()), bv.end());
236
237 std::cout << std::endl;
239 api.init(ccdbUrl);
240 std::map<std::string, std::string> md;
241 auto dest = ccdbPath(badChannelType);
242 std::cout << fmt::format("storing {} {}bad channels (valid from {} to {}) to {}\n", bv.size(),
243 makeDefault ? "default " : "", startTimestamp, endTimestamp, dest);
244
245 if (makeDefault) {
246 md["default"] = "true";
247 md["Created"] = "1";
248 }
249 api.storeAsTFileAny(&bv, dest, md, startTimestamp, endTimestamp);
250}
251
252int main(int argc, char** argv)
253{
254 po::variables_map vm;
255 po::options_description usage("Usage");
256
257 std::string ccdbUrl;
258 std::string ccdbRefUrl;
259 std::string dpConfName;
260 std::string badChannelType;
261 uint64_t startTimestamp;
262 uint64_t endTimestamp;
263 bool list;
264 bool put;
265 bool query;
266 bool verbose;
267 bool uploadDefault;
268
269 auto tnow = std::chrono::system_clock::now().time_since_epoch();
270 using namespace std::chrono_literals;
271 auto tend = tnow + 24h;
272
273 uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(tnow).count();
274 uint64_t end = std::chrono::duration_cast<std::chrono::milliseconds>(tend).count();
275
276 // clang-format off
277 usage.add_options()
278 ("help,h", "produce help message")
279 ("ccdb,c",po::value<std::string>(&ccdbUrl)->default_value("http://localhost:6464"),"ccdb url")
280 ("starttimestamp",po::value<uint64_t>(&startTimestamp)->default_value(now),"timestamp for query or put - (default=now)")
281 ("endtimestamp", po::value<uint64_t>(&endTimestamp)->default_value(end), "end of validity (for put) - default=1 day from now")
282 ("list,l", po::bool_switch(&list),"list timestamps, within the given range, when the bad channels change")
283 ("put,p",po::bool_switch(&put),"upload bad channel object")
284 ("referenceccdb,r",po::value<std::string>(&ccdbRefUrl)->default_value("http://alice-ccdb.cern.ch"),"reference ccdb url")
285 ("upload-default-values,u",po::bool_switch(&uploadDefault),"upload default values")
286 ("type,t",po::value<std::string>(&badChannelType)->default_value("BadChannel"),"type of bad channel (BadChannel or RejectList)")
287 ("query,q",po::bool_switch(&query),"dump bad channel object from CCDB")
288 ("verbose,v",po::bool_switch(&verbose),"verbose output")
289 ("solar,s",po::value<std::vector<uint16_t>>()->multitoken(),"solar ids to reject")
290 ("ds,d", po::value<std::vector<uint16_t>>()->multitoken(), "dual sampas indices to reject")
291 ("de,e", po::value<std::vector<uint16_t>>()->multitoken(), "DE ids to reject")
292 ("alias,a", po::value<std::vector<std::string>>()->multitoken(), "DCS alias (HV or LV) to reject")
293 ;
294 // clang-format on
295
296 po::options_description cmdline;
297 cmdline.add(usage);
298
299 po::store(po::command_line_parser(argc, argv).options(cmdline).run(), vm);
300
301 if (vm.count("help")) {
302 std::cout << "This program get/set MCH bad channels CCDB object\n";
303 std::cout << usage << "\n";
304 return 2;
305 }
306
307 try {
308 po::notify(vm);
309 } catch (boost::program_options::error& e) {
310 std::cout << "Error: " << e.what() << "\n";
311 exit(1);
312 }
313
314 if (badChannelType != "BadChannel" && badChannelType != "RejectList") {
315 std::cout << "Error: badChannelType " << badChannelType << " is invalid. Only BadChannel or RejectList are legit\n";
316 exit(2);
317 }
318
319 if (list) {
320 auto tsChanges = listTSWhenBadChannelsChange(ccdbUrl, badChannelType, startTimestamp, endTimestamp, verbose);
321 }
322
323 if (query) {
324 queryBadChannels(ccdbUrl, badChannelType, startTimestamp, verbose);
325 }
326
327 if (put) {
329 if (vm.count("solar")) {
330 rejectSolars(vm["solar"].as<std::vector<uint16_t>>(), bv);
331 }
332 if (vm.count("ds")) {
333 rejectDSs(vm["ds"].as<std::vector<uint16_t>>(), bv);
334 }
335 if (vm.count("de")) {
336 rejectDEs(vm["de"].as<std::vector<uint16_t>>(), bv);
337 }
338 if (vm.count("alias")) {
339 rejectHVLVs(vm["alias"].as<std::vector<std::string>>(), bv);
340 }
341
342 if (uploadDefault) {
343 uploadBadChannels(ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, true);
344 } else {
345 auto tsChanges = listTSWhenBadChannelsChange(ccdbRefUrl, badChannelType, startTimestamp, endTimestamp, false);
346
347 std::cout << fmt::format("\n{} object{} valid in the reference CCDB ({}) for this time range. What do you want to do?\n",
348 tsChanges.size(), (tsChanges.size() > 1) ? "s are" : " is", ccdbRefUrl);
349 std::cout << fmt::format("[a] abort: do nothing\n");
350 std::cout << fmt::format("[o] overwrite: create 1 new object for the whole time range to supersede the existing one{}\n",
351 (tsChanges.size() > 1) ? "s" : "");
352 std::cout << fmt::format("[u] update: create {} new object{} within the time range adding new bad channels to existing ones\n",
353 tsChanges.size(), (tsChanges.size() > 1) ? "s" : "");
354 std::string response{};
355 std::cin >> response;
356
357 if (response == "a" || response == "abort") {
358 return 0;
359 } else if (response == "o" || response == "overwrite") {
360 uploadBadChannels(ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, false);
361 } else if (response == "u" || response == "update") {
362 tsChanges.emplace(endTimestamp);
363 auto itStartTS = tsChanges.begin();
364 for (auto itStopTS = std::next(itStartTS); itStopTS != tsChanges.end(); ++itStartTS, ++itStopTS) {
365 auto bv2 = queryBadChannels(ccdbRefUrl, badChannelType, *itStartTS, false);
366 bv2.insert(bv2.end(), bv.begin(), bv.end());
367 uploadBadChannels(ccdbUrl, badChannelType, *itStartTS, *itStopTS, bv2, false);
368 }
369 } else {
370 std::cout << "invalid response (must be a, o or u) --> abort\n";
371 exit(3);
372 }
373 }
374 }
375
376 return 0;
377}
o2::mch::mapping::CathodeSegmentation seg
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
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 e
void rejectDSs(const std::vector< uint16_t > dsIdxs, BadChannelsVector &bv)
BadChannelsVector queryBadChannels(const std::string ccdbUrl, const std::string badChannelType, uint64_t timestamp, bool verbose)
void uploadBadChannels(const std::string ccdbUrl, const std::string badChannelType, uint64_t startTimestamp, uint64_t endTimestamp, BadChannelsVector &bv, bool makeDefault)
void rejectHVLVs(const std::vector< std::string > dcsAliases, BadChannelsVector &bv)
std::vector< o2::mch::DsChannelId > BadChannelsVector
std::string ccdbPath(const std::string badChannelType)
void rejectDS(const o2::mch::raw::DsDetId &dsDetId, BadChannelsVector &bv)
void rejectDEs(const std::vector< uint16_t > deIds, BadChannelsVector &bv)
void rejectSolars(const std::vector< uint16_t > solarIds, BadChannelsVector &bv)
std::set< uint64_t > listTSWhenBadChannelsChange(const std::string ccdbUrl, const std::string badChannelType, uint64_t startTimestamp, uint64_t endTimestamp, bool verbose)
uint32_t c
Definition RawData.h:2
Class for time synchronization of RawReader instances.
std::string list(std::string const &path="", bool latestOnly=false, std::string const &returnFormat="text/plain", long createdNotAfter=-1, long createdNotBefore=-1) const
Definition CcdbApi.cxx:1309
int storeAsTFileAny(const T *obj, std::string const &path, std::map< std::string, std::string > const &metadata, long startValidityTimestamp=-1, long endValidityTimestamp=-1, std::vector< char >::size_type maxSize=0) const
Definition CcdbApi.h:163
void init(std::string const &hosts)
Definition CcdbApi.cxx:240
std::enable_if<!std::is_base_of< o2::conf::ConfigurableParam, T >::value, T * >::type retrieveFromTFileAny(std::string const &path, std::map< std::string, std::string > const &metadata, long timestamp=-1, std::map< std::string, std::string > *headers=nullptr, std::string const &etag="", const std::string &createdNotAfter="", const std::string &createdNotBefore="") const
Definition CcdbApi.h:662
std::map< std::string, std::string > retrieveHeaders(std::string const &path, std::map< std::string, std::string > const &metadata, long timestamp=-1) const
Definition CcdbApi.cxx:1569
void forEachPadInDualSampa(int dualSampaId, CALLABLE &&func) const
int padDualSampaChannel(int catPadIndex) const
int padDualSampaId(int catPadIndex) const
A DsDetId is just a pair (detection element id, dual sampa id)
Definition DsDetId.h:22
uint16_t deId() const
deId returns one of the 156 possible detection element id
Definition DsDetId.h:27
uint16_t dsId() const
Definition DsDetId.h:31
GLuint GLuint end
Definition glcorearb.h:469
GLsizei GLsizei GLchar * source
Definition glcorearb.h:798
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLsizeiptr const void GLenum usage
Definition glcorearb.h:659
bool isValidDetElemId(int deId)
std::set< DsIndex > aliasToDsIndices(std::string_view alias)
Definition Mapper.cxx:41
bool isValid(std::string_view dcsAlias)
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
constexpr uint16_t NumberOfDualSampas
Definition DsIndex.h:28
o2::mch::raw::DsDetId getDsDetId(DsIndex dsIndex)
Definition DsIndex.cxx:90
void empty(int)
std::string ccdbUrl
uint16_t de
o2::mch::DsIndex ds
#define main