32 : mDataSource(datasource), mRunMFT(doMFT)
34 std::string detector = doMFT ?
"MFT" :
"ITS";
48 LOG(info) <<
"ITSMFTDeadMapBuilder init... " << mSelfName;
50 mTFSampling = ic.
options().
get<
int>(
"tf-sampling");
51 mTFSamplingTolerance = ic.
options().
get<
int>(
"tf-sampling-tolerance");
52 if (mTFSamplingTolerance > mTFSampling) {
53 LOG(warning) <<
"Invalid request tf-sampling-tolerance larger or equal than tf-sampling. Setting tolerance to " << mTFSampling - 1;
54 mTFSamplingTolerance = mTFSampling - 1;
56 mSampledSlidingWindowSize = ic.
options().
get<
int>(
"tf-sampling-history-size");
57 mTFLength = ic.
options().
get<
int>(
"tf-length");
58 mDoLocalOutput = ic.
options().
get<
bool>(
"local-output");
59 mObjectName = ic.
options().
get<std::string>(
"outfile");
60 mCCDBUrl = ic.
options().
get<std::string>(
"ccdb-url");
61 if (mCCDBUrl ==
"none") {
65 mLocalOutputDir = ic.
options().
get<std::string>(
"output-dir");
66 mSkipStaticMap = ic.
options().
get<
bool>(
"skip-static-map");
67 mNoGroupITSLanes = ic.
options().
get<
bool>(
"no-group-its-lanes");
79 mSampledHistory.clear();
81 mStaticChipStatus.clear();
85 if (!mSkipStaticMap) {
86 mStaticChipStatus.resize(N_CHIPS,
false);
89 LOG(info) <<
"Sampling one TF every " << mTFSampling <<
" with " << mTFSamplingTolerance <<
" TF tolerance";
95 mStuckPixelFileName = ic.
options().
get<std::string>(
"save-stuck-pixels");
96 mDoStuckPixels = (!mRunMFT && !mStuckPixelFileName.empty());
99 LOG(info) <<
"Stuck pixel saving ENABLED. CCDB object name: " << mStuckPixelFileName;
100 mStuckPixelData.
clear();
102 LOG(info) <<
"Stuck pixel saving DISABLED.";
109std::vector<uint16_t> ITSMFTDeadMapBuilder::getChipIDsOnSameCable(uint16_t chip)
111 if (mRunMFT || chip < N_CHIPS_ITSIB) {
112 return std::vector<uint16_t>{chip};
114 uint16_t firstchipcable = 7 * (uint16_t)((chip - N_CHIPS_ITSIB) / 7) + N_CHIPS_ITSIB;
115 std::vector<uint16_t> chipList(7);
116 std::generate(chipList.begin(), chipList.end(), [&firstchipcable]() { return firstchipcable++; });
122bool ITSMFTDeadMapBuilder::acceptTF(
long orbit)
124 if (mTFSamplingTolerance < 1) {
125 return ((
orbit / mTFLength) % mTFSampling == 0);
128 if ((
orbit / mTFLength) % mTFSampling > mTFSamplingTolerance) {
132 long sampling_index =
orbit / mTFLength / mTFSampling;
134 if (mSampledTFs.find(sampling_index) == mSampledTFs.end()) {
135 mSampledTFs.insert(sampling_index);
136 mSampledHistory.push_back(sampling_index);
138 if (mSampledHistory.size() > mSampledSlidingWindowSize) {
139 long oldIndex = mSampledHistory.front();
140 mSampledHistory.pop_front();
141 mSampledTFs.erase(oldIndex);
151void ITSMFTDeadMapBuilder::finalizeOutput()
154 if (!mSkipStaticMap) {
155 std::vector<uint16_t> staticmap{};
156 int staticmap_chipcounter = 0;
157 for (uint16_t el = 0; el < mStaticChipStatus.size(); el++) {
158 if (mStaticChipStatus[el]) {
161 staticmap_chipcounter++;
162 bool previous_dead = (el > 0 && !mStaticChipStatus[el - 1]);
163 bool next_dead = (el < mStaticChipStatus.size() - 1 && !mStaticChipStatus[el + 1]);
164 if (!previous_dead && next_dead) {
165 staticmap.push_back(el | (uint16_t)(0x8000));
166 }
else if (previous_dead && next_dead) {
169 staticmap.push_back(el);
173 LOG(info) <<
"Filling static part of the map with " << staticmap_chipcounter
174 <<
" dead chips, saved into " << staticmap.size() <<
" words";
179 if (mDoLocalOutput) {
180 std::string localoutfilename = mLocalOutputDir +
"/" + mObjectName;
181 TFile outfile(localoutfilename.c_str(),
"RECREATE");
182 outfile.WriteObjectAny(&mMapObject,
"o2::itsmft::TimeDeadMap",
"ccdb_object");
189 if (mDoStuckPixels && mDoLocalOutput) {
190 std::string stuckOutFileName = mLocalOutputDir +
"/" + mStuckPixelFileName;
191 TFile stuckOutFile(stuckOutFileName.c_str(),
"RECREATE");
193 if (!stuckOutFile.IsZombie()) {
196 TTree localTree(
"ErrorTree",
"Stuck Pixel Errors");
197 localTree.SetDirectory(&stuckOutFile);
198 localTree.Branch(
"orbit", &mErrOrbit,
"orbit/L");
199 localTree.Branch(
"chipid", &mErrChipID,
"chipid/s");
200 localTree.Branch(
"row", &mErrRow,
"row/s");
201 localTree.Branch(
"col", &mErrCol,
"col/s");
203 for (
const auto&
entry : mStuckPixelData.getEntries()) {
204 mErrOrbit =
entry.orbit;
205 mErrChipID =
entry.chipID;
211 stuckOutFile.Write();
212 stuckOutFile.Close();
214 LOG(info) <<
"StuckPixel TTree saved locally to " << stuckOutFileName
215 <<
" (" << mStuckPixelData.
size() <<
" entries)";
217 LOG(error) <<
"Failed to open " << stuckOutFileName <<
" for StuckPixel TTree.";
230 LOG(info) <<
"Skipping the processing of inputs for timeslice "
232 <<
" (firstTForbit is "
237 auto start = std::chrono::high_resolution_clock::now();
241 if (tinfo.globalRunNumberChanged || mFirstOrbitRun == 0x0) {
242 mRunNumber = tinfo.runNumber;
243 mFirstOrbitRun = mFirstOrbitTF;
252 mFirstOrbitTF = tinfo.firstTForbit;
255 long sampled_orbit = mFirstOrbitTF - mFirstOrbitRun;
257 if (!acceptTF(sampled_orbit)) {
266 if (mDoStuckPixels) {
267 const auto repErrors = pc.
inputs().
get<gsl::span<o2::itsmft::ErrorMessage>>(
"repErr");
268 for (
const auto& err : repErrors) {
271 static_cast<Long64_t
>(mFirstOrbitTF),
272 static_cast<uint16_t
>(err.id),
273 static_cast<uint16_t
>(err.errInfo0),
274 static_cast<uint16_t
>(err.errInfo1));
279 LOG(info) <<
"Processing step #" << mStepCounter <<
" out of " << mTFCounter
280 <<
" good TF received. First orbit " << mFirstOrbitTF;
284 std::vector<bool> ChipStatus(N_CHIPS,
false);
286 if (mDataSource ==
"digits") {
287 const auto elements = pc.
inputs().
get<gsl::span<o2::itsmft::Digit>>(
"elements");
288 const auto ROFs = pc.
inputs().
get<gsl::span<o2::itsmft::ROFRecord>>(
"ROFs");
289 for (
const auto& rof : ROFs) {
290 auto elementsInTF = rof.getROFData(elements);
291 for (
const auto& el : elementsInTF) {
292 ChipStatus.at((
int)el.getChipIndex()) =
true;
295 }
else if (mDataSource ==
"clusters") {
296 const auto elements = pc.
inputs().
get<gsl::span<o2::itsmft::CompClusterExt>>(
"elements");
297 const auto ROFs = pc.
inputs().
get<gsl::span<o2::itsmft::ROFRecord>>(
"ROFs");
298 for (
const auto& rof : ROFs) {
299 auto elementsInTF = rof.getROFData(elements);
300 for (
const auto& el : elementsInTF) {
301 ChipStatus.at((
int)el.getSensorID()) =
true;
304 }
else if (mDataSource ==
"chipsstatus") {
305 const auto elements = pc.
inputs().
get<gsl::span<char>>(
"elements");
306 for (uint16_t chipID = 0; chipID < elements.size(); chipID++) {
307 if (elements[chipID]) {
308 ChipStatus.at(chipID) =
true;
314 if (!mSkipStaticMap) {
315 for (
size_t el = 0; el < mStaticChipStatus.size(); el++) {
316 mStaticChipStatus[el] = mStaticChipStatus[el] || ChipStatus[el];
321 if (!mRunMFT && !mNoGroupITSLanes) {
322 for (uint16_t el = N_CHIPS_ITSIB; el < ChipStatus.size(); el++) {
323 if (ChipStatus.at(el)) {
324 std::vector<uint16_t> chipincable = getChipIDsOnSameCable(el);
325 for (uint16_t el2 : chipincable) {
326 ChipStatus.at(el2) =
true;
335 for (uint16_t el = 0; el < ChipStatus.size(); el++) {
336 if (ChipStatus.at(el)) {
340 bool previous_dead = (el > 0 && !ChipStatus.at(el - 1));
341 bool next_dead = (el < ChipStatus.size() - 1 && !ChipStatus.at(el + 1));
342 if (!previous_dead && next_dead) {
343 mDeadMapTF.push_back(el | (uint16_t)(0x8000));
344 }
else if (previous_dead && next_dead) {
347 mDeadMapTF.push_back(el);
351 LOG(info) <<
"TF contains " << CountDead <<
" dead chips, saved into "
352 << mDeadMapTF.size() <<
" words.";
355 mMapObject.
fillMap(mFirstOrbitTF, mDeadMapTF);
357 auto end = std::chrono::high_resolution_clock::now();
358 int difference = std::chrono::duration_cast<std::chrono::microseconds>(
end -
start).count();
360 LOG(info) <<
"Elapsed time in TF processing: " << difference / 1000. <<
" ms";
362 if (pc.
transitionState() == TransitionHandlingState::Requested && !isEnded) {
363 std::string detname = mRunMFT ?
"MFT" :
"ITS";
364 LOG(warning) <<
"Transition state requested for " << detname
365 <<
" process, calling stop() and stopping the process of new data.";
373void ITSMFTDeadMapBuilder::PrepareOutputCcdb(
EndOfStreamContext* ec, std::string ccdburl)
376 std::map<std::string, std::string> md = {
377 {
"map_version", MAP_VERSION},
380 std::string
path = mRunMFT ?
"MFT/Calib/" :
"ITS/Calib/";
384 std::string name_str =
"TimeDeadMap";
391 mTimeStart - 120 * 1000,
395 info.setFileName(mObjectName);
396 info.setAdjustableEOV();
400 LOG(important) <<
"Sending object " <<
info.getPath() <<
"/" <<
info.getFileName()
401 <<
" to ccdb-populator, of size " <<
image->size()
402 <<
" bytes, valid for "
403 <<
info.getStartValidityTimestamp() <<
" : "
404 <<
info.getEndValidityTimestamp();
413 }
else if (!ccdburl.empty()) {
414 LOG(important) << mSelfName <<
" sending object " << ccdburl <<
"/browse/"
415 <<
info.getPath() <<
"/" <<
info.getFileName()
416 <<
" of size " <<
image->size() <<
" bytes, valid for "
417 <<
info.getStartValidityTimestamp() <<
" : "
418 <<
info.getEndValidityTimestamp();
425 info.getStartValidityTimestamp(),
info.getEndValidityTimestamp());
428 LOG(warning) <<
"PrepareOutputCcdb called with empty arguments for TimeDeadMap. Doing nothing.";
431 LOG(warning) <<
"Time-dependent dead map is empty and will not be forwarded as output";
439 if (mDoStuckPixels) {
440 std::string name_sp =
"StuckPixels";
447 mTimeStart - 120 * 1000,
451 info_sp.setFileName(mStuckPixelFileName);
452 info_sp.setAdjustableEOV();
454 LOG(info) <<
"StuckPixelData contains " << mStuckPixelData.
size()
455 <<
" entries (" << image_sp->size()
456 <<
" bytes), publishing to " <<
path + name_sp;
461 }
else if (!ccdburl.empty()) {
462 LOG(important) << mSelfName <<
" sending StuckPixelData to "
463 << ccdburl <<
"/browse/" << info_sp.getPath();
466 mApi_sp.
init(ccdburl);
468 &image_sp->at(0), image_sp->size(), info_sp.getFileName(), info_sp.getObjectType(),
469 info_sp.getPath(), info_sp.getMetaData(),
470 info_sp.getStartValidityTimestamp(), info_sp.getEndValidityTimestamp());
473 LOG(warning) <<
"PrepareOutputCcdb called with empty arguments for StuckPixels. Doing nothing.";
484 LOG(info) <<
"endOfStream report: " << mSelfName;
486 PrepareOutputCcdb(&ec,
"");
487 LOG(info) <<
"Stop process of new data because of endOfStream";
497 LOG(info) <<
"stop() report: " << mSelfName;
499 if (!mCCDBUrl.empty()) {
500 std::string detname = mRunMFT ?
"MFT" :
"ITS";
501 LOG(warning) <<
"endOfStream not processed. Sending output to ccdb from the "
502 << detname <<
" deadmap builder workflow.";
503 PrepareOutputCcdb(
nullptr, mCCDBUrl);
505 LOG(alarm) <<
"endOfStream not processed. Nothing forwarded as output.";
507 LOG(info) <<
"Stop process of new data because of stop() call.";
523 std::vector<InputSpec> inputs;
525 if (datasource ==
"digits") {
526 inputs.emplace_back(
"elements", detOrig,
"DIGITS", 0, Lifetime::Timeframe);
527 inputs.emplace_back(
"ROFs", detOrig,
"DIGITSROF", 0, Lifetime::Timeframe);
528 }
else if (datasource ==
"clusters") {
529 inputs.emplace_back(
"elements", detOrig,
"COMPCLUSTERS", 0, Lifetime::Timeframe);
530 inputs.emplace_back(
"ROFs", detOrig,
"CLUSTERSROF", 0, Lifetime::Timeframe);
531 }
else if (datasource ==
"chipsstatus") {
532 inputs.emplace_back(
"elements", detOrig,
"CHIPSSTATUS", 0, Lifetime::Timeframe);
540 inputs.emplace_back(
"repErr", detOrig,
"ErrorInfo", 0, Lifetime::Timeframe);
543 std::vector<OutputSpec> outputs;
553 std::string detector = doMFT ?
"mft" :
"its";
554 std::string objectname_default = detector +
"_time_deadmap.root";
557 "itsmft-deadmap-builder_" + detector,
560 AlgorithmSpec{adaptFromTask<ITSMFTDeadMapBuilder>(datasource, doMFT)},
562 {
"tf-sampling", VariantType::Int, 350, {
"Process every Nth TF. Selection according to first TF orbit."}},
563 {
"tf-sampling-tolerance", VariantType::Int, 20, {
"Tolerance on the tf-sampling value (sliding window size)."}},
564 {
"tf-sampling-history-size", VariantType::Int, 1000, {
"Do not check if new TF is contained in a window that is older than N steps."}},
565 {
"tf-length", VariantType::Int, 32, {
"Orbits per TF."}},
566 {
"skip-static-map", VariantType::Bool,
false, {
"Do not fill static part of the map."}},
567 {
"no-group-its-lanes", VariantType::Bool,
false, {
"Do not group ITS OB chips into lanes."}},
568 {
"ccdb-url", VariantType::String, std::string(
""), {
"CCDB url. Ignored if endOfStream is processed."}},
569 {
"outfile", VariantType::String, objectname_default, {
"ROOT object file name."}},
570 {
"local-output", VariantType::Bool,
false, {
"Save ROOT file locally."}},
571 {
"output-dir", VariantType::String, std::string(
"./"), {
"Local output directory."}},
572 {
"save-stuck-pixels", VariantType::String, std::string(
""), {
"Enable ITS stuck-pixel collection and set the CCDB/local ROOT filename. Empty = disabled."}},
Definition of the ITSMFT compact cluster.
Alpide Chip and GBT link decoding statistics.
CCDB-serializable container for stuck (repeating) pixel error records.
Definition of the ITSMFT time-dependend dead map.
void init(std::string const &hosts)
static std::unique_ptr< std::vector< char > > createObjectImage(const T *obj, CcdbObjectInfo *info=nullptr)
int storeAsBinaryFile(const char *buffer, size_t size, const std::string &fileName, const std::string &objectType, const std::string &path, const std::map< std::string, std::string > &metadata, long startValidityTimestamp, long endValidityTimestamp, std::vector< char >::size_type maxSize=0) const
T get(const char *key) const
void snapshot(const Output &spec, T const &object)
DataAllocator & outputs()
ConfigParamRegistry const & options()
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
TransitionHandlingState transitionState() const
static constexpr int getNChips()
number of chips per barrel
static constexpr Int_t getNChips()
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void stop() final
This is invoked on stop.
void init(InitContext &ic) final
~ITSMFTDeadMapBuilder() override
void run(ProcessingContext &pc) final
ITSMFTDeadMapBuilder(std::string datasource, bool doMFT)
void addEntry(Long64_t orbit, uint16_t chipID, uint16_t row, uint16_t col)
void fillMap(unsigned long firstOrbit, const std::vector< uint16_t > &deadVect)
void setMapVersion(std::string version)
unsigned long getEvolvingMapSize() const
GLsizei const GLchar *const * path
constexpr o2::header::DataOrigin gDataOriginMFT
constexpr o2::header::DataOrigin gDataOriginITS
long getCurrentTimestamp()
returns the timestamp in long corresponding to "now"
int adjustOverriddenEOV(CcdbApi &api, const CcdbObjectInfo &infoNew)
set EOV of overriden objects to SOV-1 of overriding one if it is allowed
std::vector< ConfigParamSpec > Options
o2::framework::DataProcessorSpec getITSMFTDeadMapBuilderSpec(std::string datasource, bool doMFT)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
static constexpr o2::header::DataOrigin gDataOriginCDBWrapper
static constexpr o2::header::DataOrigin gDataOriginCDBPayload
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"