46template <
class Mapping>
48 : mDoClusters(inp.doClusters), mDoPatterns(inp.doPatterns), mDoDigits(inp.doDigits), mDoCalibData(inp.doCalib), mDoStaggering(inp.doStaggering), mAllowReporting(inp.allowReporting), mVerifyDecoder(inp.verifyDecoder), mInputSpec(inp.inputSpec), mGGCCDBRequest(gr)
54 mLayers = Mapping::NLayers;
55 mEstNDig.resize(mLayers, 0);
56 mEstNClus.resize(mLayers, 0);
57 mEstNClusPatt.resize(mLayers, 0);
58 mEstNCalib.resize(mLayers, 0);
63template <
class Mapping>
75 for (
int iLayer{0}; iLayer < mLayers; ++iLayer) {
77 dec->setUserDataOrigin(dataOrig);
78 dec->setUserDataDescription(dataDesc);
81 }
catch (
const std::exception& e) {
82 LOG(error) <<
"exception was thrown in decoder creation: " << e.what();
85 LOG(error) <<
"non-std::exception was thrown in decoder creation";
88 mApplyNoiseMap = !ic.
options().
get<
bool>(
"ignore-noise-map");
89 mUseClusterDictionary = !ic.
options().
get<
bool>(
"ignore-cluster-dictionary");
91 float fr = ic.
options().
get<
float>(
"rof-length-error-freq");
92 mROFErrRepIntervalMS = fr <= 0. ? -1 :
long(fr * 1e3);
93 mNThreads = std::max(1, ic.
options().
get<
int>(
"nthreads"));
94 mUnmutExtraLanes = ic.
options().
get<
bool>(
"unmute-extra-lanes");
95 mVerbosity = ic.
options().
get<
int>(
"decoder-verbosity");
96 auto dmpSz = ic.
options().
get<
int>(
"stop-raw-data-dumps-after-size");
98 mMaxRawDumpsSize = size_t(dmpSz) * 1024 * 1024;
100 mDumpOnError = ic.
options().
get<
int>(
"raw-data-dumps");
101 if (mDumpOnError < 0) {
102 mDumpOnError = -mDumpOnError;
103 mDumpFrom1stPipeline =
true;
106 throw std::runtime_error(fmt::format(
"unknown raw data dump level {} requested", mDumpOnError));
108 auto dumpDir = ic.
options().
get<std::string>(
"raw-data-dumps-directory");
110 throw std::runtime_error(fmt::format(
"directory {} for raw data dumps does not exist", dumpDir));
112 for (
int iLayer{0}; iLayer < mLayers; ++iLayer) {
113 mDecoder[iLayer]->setNThreads(mNThreads);
114 mDecoder[iLayer]->setAlwaysParseTrigger(ic.
options().
get<
bool>(
"always-parse-trigger"));
115 mDecoder[iLayer]->setAllowEmptyROFs(ic.
options().
get<
bool>(
"allow-empty-rofs"));
116 mDecoder[iLayer]->setRawDumpDirectory(dumpDir);
117 mDecoder[iLayer]->setFillCalibData(mDoCalibData);
118 mDecoder[iLayer]->setVerifyDecoder(mVerifyDecoder);
119 bool ignoreRampUp = !ic.
options().
get<
bool>(
"accept-rof-rampup-data");
120 mDecoder[iLayer]->setSkipRampUpData(ignoreRampUp);
122 }
catch (
const std::exception& e) {
123 LOG(error) <<
"exception was thrown in decoder configuration: " << e.what();
126 LOG(error) <<
"non-std::exception was thrown in decoder configuration";
131 mClusterer = std::make_unique<Clusterer>();
132 mClusterer->setNChips(Mapping::getNChips());
137 for (uint32_t iLayer{0}; iLayer < mLayers; ++iLayer) {
138 std::vector<o2::framework::InputSpec>
filter;
139 for (
const auto feeID : map.getLayer2FEEIDs(iLayer)) {
142 mDecoder[iLayer]->setInputFilter(
filter);
148template <
class Mapping>
151 updateTimeDependentParams(pc);
152 static bool firstCall =
true;
158 for (
int iLayer{0}; iLayer < mLayers; ++iLayer) {
161 mDecoder[iLayer]->setVerbosity(mDecoder[iLayer]->getInstanceID() == 0 ? mVerbosity : (mUnmutExtraLanes ? mVerbosity : -1));
163 mAllowReporting &= (mDecoder[0]->getInstanceID() == 0) || mUnmutExtraLanes;
167 double timeCPU0 = mTimer.CpuTime(), timeReal0 = mTimer.RealTime();
169 auto orig = Mapping::getOrigin();
172 auto& chipStatus = pc.
outputs().
make<std::vector<char>>(
Output{orig,
"CHIPSSTATUS", 0}, (size_t)Mapping::getNChips());
173 auto& linkErrors = pc.
outputs().
make<std::vector<GBTLinkDecodingStat>>(
Output{orig,
"LinkErrors", 0});
174 auto& decErrors = pc.
outputs().
make<std::vector<ChipError>>(
Output{orig,
"ChipErrors", 0});
175 auto& errMessages = pc.
outputs().
make<std::vector<ErrorMessage>>(
Output{orig,
"ErrorInfo", 0});
176 auto& physTriggers = pc.
outputs().
make<std::vector<PhysTrigger>>(
Output{orig,
"PHYSTRIG", 0});
178 for (uint32_t iLayer{0}; iLayer < mLayers; ++iLayer) {
179 const auto& par = AlpideParam::Instance();
182 int nLayer = mDoStaggering ? iLayer : -1;
183 std::vector<o2::itsmft::CompClusterExt> clusCompVec;
184 std::vector<o2::itsmft::ROFRecord> clusROFVec;
185 std::vector<unsigned char> clusPattVec;
186 std::vector<Digit> digVec;
187 std::vector<GBTCalibData> calVec;
188 std::vector<ROFRecord> digROFVec;
190 digVec.reserve(mEstNDig[iLayer]);
191 digROFVec.reserve(nROFsTF);
194 clusCompVec.reserve(mEstNClus[iLayer]);
195 clusROFVec.reserve(nROFsTF);
196 clusPattVec.reserve(mEstNClusPatt[iLayer]);
199 calVec.reserve(mEstNCalib[iLayer]);
203 mDecoder[iLayer]->startNewTF(pc.
inputs());
204 mDecoder[iLayer]->setDecodeNextAuto(
false);
207 int nTriggersProcessed = mDecoder[iLayer]->getNROFsProcessed();
208 static long lastErrReportTS = 0;
209 while (mDecoder[iLayer]->decodeNextTrigger() >= 0) {
210 if ((!lastIR.isDummy() && lastIR >= mDecoder[iLayer]->getInteractionRecord()) || mFirstIR > mDecoder[iLayer]->getInteractionRecord()) {
211 const int MaxErrLog = 2;
212 static int errLocCount = 0;
213 if (errLocCount++ < MaxErrLog) {
214 LOGP(warn,
"Impossible ROF IR {}{}, previous was {}, TF 1st IR was {}, discarding in decoding", mDecoder[iLayer]->getInteractionRecord().
asString(), ((mDoStaggering) ? std::format(
" on layer {}", iLayer) :
""), lastIR.asString(), mFirstIR.asString());
216 nTriggersProcessed = 0x7fffffff;
219 lastIR = mDecoder[iLayer]->getInteractionRecord();
220 mDecoder[iLayer]->fillChipsStatus(chipStatus);
221 if (mDoDigits || mClusterer->getMaxROFDepthToSquash(nLayer)) {
222 mDecoder[iLayer]->fillDecodedDigits(digVec, digROFVec);
224 mDecoder[iLayer]->fillCalibData(calVec);
227 if (mDoClusters && !mClusterer->getMaxROFDepthToSquash(nLayer)) {
228 mClusterer->process(mNThreads, *mDecoder[iLayer].
get(), &clusCompVec, mDoPatterns ? &clusPattVec :
nullptr, &clusROFVec);
231 nTriggersProcessed = mDecoder[iLayer]->getNROFsProcessed() - nTriggersProcessed - 1;
233 if ((nROFsTF != nTriggersProcessed) && mROFErrRepIntervalMS > 0 && mTFCounter > 1 && nTriggersProcessed > 0) {
234 long currTS = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
235 if (currTS - lastErrReportTS > mROFErrRepIntervalMS) {
236 LOGP(critical,
"Inconsistent number of ROF per TF {}{} from parameters. Received {} from readout (muting further reporting for {} ms)", nROFsTF, ((mDoStaggering) ? std::format(
" on layer {}", iLayer) :
""), nTriggersProcessed, mROFErrRepIntervalMS);
237 lastErrReportTS = currTS;
240 if (mDoClusters && mClusterer->getMaxROFDepthToSquash(nLayer)) {
250 mClusterer->setMaxROFDepthToSquash(mClusterer->getMaxROFDepthToSquash(nLayer));
251 mClusterer->process(mNThreads, reader, &clusCompVec, mDoPatterns ? &clusPattVec :
nullptr, &clusROFVec);
253 }
catch (
const std::exception& e) {
254 static size_t nErr = 0;
256 if (++nErr < maxWarn) {
257 LOGP(alarm,
"EXCEPTION {} in raw decoder{}, abandoning TF decoding {}", e.what(), ((mDoStaggering) ? std::format(
" on layer {}", iLayer) :
""), nErr == maxWarn ?
"(will mute further warnings)" :
"");
262 std::vector<o2::itsmft::ROFRecord> expDigRofVec(nROFsTF);
263 ensureContinuousROF(digROFVec, expDigRofVec, iLayer, nROFsTF,
"digits");
265 mEstNDig[iLayer] = std::max(mEstNDig[iLayer],
size_t(digVec.size() * 1.2));
268 mEstNCalib[iLayer] = std::max(mEstNCalib[iLayer],
size_t(calVec.size() * 1.2));
270 LOG(
debug) << mSelfName <<
" Decoded " << digVec.size() <<
" Digits in " << digROFVec.size() <<
" ROFs" << ((mDoStaggering) ? std::format(
" on layer {}", iLayer) :
"");
274 std::vector<o2::itsmft::ROFRecord> expClusRofVec(nROFsTF);
275 ensureContinuousROF(clusROFVec, expClusRofVec, iLayer, nROFsTF,
"clusters");
279 mEstNClus[iLayer] = std::max(mEstNClus[iLayer],
size_t(clusCompVec.size() * 1.2));
280 mEstNClusPatt[iLayer] = std::max(mEstNClusPatt[iLayer],
size_t(clusPattVec.size() * 1.2));
281 LOG(info) << mSelfName <<
" Built " << clusCompVec.size() <<
" clusters in " << expClusRofVec.size() <<
" ROFs" << ((mDoStaggering) ? std::format(
" on layer {}", iLayer) :
"");
284 mDecoder[iLayer]->collectDecodingErrors(linkErrors, decErrors, errMessages);
285 physTriggers.insert(physTriggers.end(), mDecoder[iLayer]->getExternalTriggers().begin(), mDecoder[iLayer]->getExternalTriggers().end());
290 if (mRawDumpedSize > mMaxRawDumpsSize && mMaxRawDumpsSize > 0) {
291 LOGP(info,
"Max total dumped size {} MB exceeded allowed limit, disabling further dumping", mRawDumpedSize / (1024 * 1024));
299 LOG(
debug) << mSelfName <<
" Total time for TF " << tfID <<
'(' << mTFCounter <<
") : CPU: " << mTimer.CpuTime() - timeCPU0 <<
" Real: " << mTimer.RealTime() - timeReal0;
304template <
class Mapping>
310 mFinalizeDone =
true;
311 LOGF(info,
"%s statistics:", mSelfName);
312 LOGF(info,
"%s Total STF decoding%s timing (w/o disk IO): Cpu: %.3e Real: %.3e s in %d slots", mSelfName,
313 mDoClusters ?
"/clustering" :
"", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
314 for (
int iLayer{0}; iLayer < mLayers && mAllowReporting; ++iLayer) {
315 if (mDecoder[iLayer]) {
316 LOG_IF(info, mDoStaggering) <<
"Report for decoder of layer " << iLayer;
317 mDecoder[iLayer]->printReport();
326template <
class Mapping>
334 const auto& alpParams = DPLAlpideParam<Mapping::getDetID()>::Instance();
341 const auto& clParams = ClustererParam<Mapping::getDetID()>::Instance();
343 LOGP(fatal,
"maxBCDiffToMaskBias = {} and maxBCDiffToMaskBias = {} cannot be set at the same time. Either set masking or squashing with a BCDiff > 0", clParams.
maxBCDiffToMaskBias, clParams.
maxBCDiffToSquashBias);
348 mClusterer->setMaxBCSeparationToMask(nbc);
353 int nROFsToSquash = 0;
354 if (clParams.
maxSOTMUS > 0 && rofBC > 0) {
359 for (
int iLayer{0}; iLayer < mLayers; ++iLayer) {
364 mClusterer->print(
false);
372template <
class Mapping>
379 LOG(info) << Mapping::getName() <<
" noise map updated" << (!mApplyNoiseMap ?
" but masking is disabled" :
"");
380 if (mApplyNoiseMap) {
386 LOG(info) << Mapping::getName() <<
" cluster dictionary updated" << (!mUseClusterDictionary ?
" but its using is disabled" :
"");
387 if (mUseClusterDictionary) {
394 LOG(info) <<
"Alpide param updated";
400template <
class Mapping>
404 mFinalizeDone =
false;
407 for (
int iLayer{0}; iLayer < mLayers; ++iLayer) {
408 if (mDecoder[iLayer]) {
409 mDecoder[iLayer]->reset();
418template <
class Mapping>
419void STFDecoder<Mapping>::ensureContinuousROF(
const std::vector<ROFRecord>& rofVec, std::vector<ROFRecord>& expROFVec,
int lr,
int nROFsTF,
const char*
name)
421 const auto&
par = AlpideParam::Instance();
425 expROFVec.resize(nROFsTF);
426 for (
int iROF{0}; iROF < nROFsTF; ++iROF) {
427 auto& rof = expROFVec[iROF];
432 rof.setROFrame(iROF);
434 rof.setFirstEntry(-1);
436 uint32_t prevEntry{0};
437 for (
const auto& rof : rofVec) {
438 const auto&
ir = rof.getBCData();
440 LOGP(warn,
"Discard ROF {} preceding TF 1st orbit {}{}",
ir.
asString(), mFirstTFOrbit, ((mDoStaggering) ? std::format(
" on layer {}", lr) :
""));
443 auto irToFirst =
ir - mFirstIR;
444 if (irToFirst.toLong() -
par.getROFDelayInBC(lr) < 0) {
445 LOGP(warn,
"Discard ROF {} preceding TF 1st orbit {} due to imposed ROF delay{}",
ir.
asString(), mFirstTFOrbit, ((mDoStaggering) ? std::format(
" on layer {}", lr) :
""));
448 irToFirst -=
par.getROFDelayInBC(lr);
449 const long irROF = irToFirst.toLong() /
par.getROFLengthInBC(lr);
450 if (irROF >= nROFsTF) {
451 LOGP(warn,
"Discard ROF {} exceeding TF orbit range{}",
ir.
asString(), ((mDoStaggering) ? std::format(
" on layer {}", lr) :
""));
454 auto& expROF = expROFVec[irROF];
455 if (expROF.getNEntries() == 0) {
456 expROF.setFirstEntry(rof.getFirstEntry());
457 expROF.setNEntries(rof.getNEntries());
459 if (expROF.getNEntries() < rof.getNEntries()) {
460 LOGP(warn,
"Repeating {} with {} {}, prefer to already processed instance with {} {}{}", rof.asString(), rof.getNEntries(),
name, expROF.getNEntries(),
name, ((mDoStaggering) ? std::format(
" on layer {}", lr) :
""));
461 expROF.setFirstEntry(rof.getFirstEntry());
462 expROF.setNEntries(rof.getNEntries());
464 LOGP(warn,
"Repeating {} with {} {}, discard preferring already processed instance with {} {}{}", rof.asString(), rof.getNEntries(),
name, expROF.getNEntries(),
name, ((mDoStaggering) ? std::format(
" on layer {}", lr) :
""));
469 for (
auto& rof : expROFVec) {
470 if (rof.getFirstEntry() < 0) {
471 rof.setFirstEntry(prevFirst);
473 prevFirst = rof.getFirstEntry();
480 std::vector<OutputSpec> outputs;
482 uint32_t nLayers = 1;
488 for (uint32_t iLayer = 0; iLayer < nLayers; ++iLayer) {
490 outputs.emplace_back(inp.
origin,
"DIGITS", iLayer, Lifetime::Timeframe);
491 outputs.emplace_back(inp.
origin,
"DIGITSROF", iLayer, Lifetime::Timeframe);
494 outputs.emplace_back(inp.
origin,
"COMPCLUSTERS", iLayer, Lifetime::Timeframe);
495 outputs.emplace_back(inp.
origin,
"CLUSTERSROF", iLayer, Lifetime::Timeframe);
499 outputs.emplace_back(inp.
origin,
"PATTERNS", iLayer, Lifetime::Timeframe);
503 outputs.emplace_back(inp.
origin,
"GBTCALIB", 0, Lifetime::Timeframe);
505 outputs.emplace_back(inp.
origin,
"PHYSTRIG", 0, Lifetime::Timeframe);
506 outputs.emplace_back(inp.
origin,
"LinkErrors", 0, Lifetime::Timeframe);
507 outputs.emplace_back(inp.
origin,
"ChipErrors", 0, Lifetime::Timeframe);
508 outputs.emplace_back(inp.
origin,
"ErrorInfo", 0, Lifetime::Timeframe);
509 outputs.emplace_back(inp.
origin,
"CHIPSSTATUS", 0, Lifetime::Timeframe);
513 inputs.emplace_back(
"stfDist",
"FLP",
"DISTSUBTIMEFRAME", 0, o2::framework::Lifetime::Timeframe);
515 inputs.emplace_back(
"noise", inp.
origin,
"NOISEMAP", 0, Lifetime::Condition,
517 inputs.emplace_back(
"alppar", inp.
origin,
"ALPIDEPARAM", 0, Lifetime::Condition,
ccdbParamSpec(fmt::format(
"{}/Config/AlpideParam", inp.
origin.
as<std::string>())));
519 inputs.emplace_back(
"cldict", inp.
origin,
"CLUSDICT", 0, Lifetime::Condition,
ccdbParamSpec(fmt::format(
"{}/Calib/ClusterDictionary", inp.
origin.
as<std::string>())));
520 inputs.emplace_back(
"cluspar", inp.
origin,
"CLUSPARAM", 0, Lifetime::Condition,
ccdbParamSpec(fmt::format(
"{}/Config/ClustererParam", inp.
origin.
as<std::string>())));
523 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
538 {
"nthreads", VariantType::Int, 1, {
"Number of decoding/clustering threads"}},
539 {
"decoder-verbosity", VariantType::Int, 0, {
"Verbosity level (-1: silent, 0: errors, 1: headers, 2: data, 3: raw data dump) of 1st lane"}},
540 {
"always-parse-trigger", VariantType::Bool,
false, {
"parse trigger word even if flags continuation of old trigger"}},
541 {
"raw-data-dumps", VariantType::Int,
int(
GBTLink::RawDataDumps::DUMP_NONE), {
"Raw data dumps on error (0: none, 1: HBF for link, 2: whole TF for all links. If negative, dump only on from 1st pipeline."}},
542 {
"raw-data-dumps-directory", VariantType::String,
"", {
"Destination directory for the raw data dumps"}},
543 {
"stop-raw-data-dumps-after-size", VariantType::Int, 1024, {
"Stop dumping once this size in MB is accumulated. 0: no limit"}},
544 {
"unmute-extra-lanes", VariantType::Bool,
false, {
"allow extra lanes to be as verbose as 1st one"}},
545 {
"allow-empty-rofs", VariantType::Bool,
false, {
"record ROFs w/o any hit"}},
546 {
"ignore-noise-map", VariantType::Bool,
false, {
"do not mask pixels flagged in the noise map"}},
547 {
"accept-rof-rampup-data", VariantType::Bool,
false, {
"do not discard data during ROF ramp up"}},
548 {
"rof-length-error-freq", VariantType::Float, 60.f, {
"do not report ROF length error more frequently than this value, disable if negative"}},
549 {
"ignore-cluster-dictionary", VariantType::Bool,
false, {
"do not use cluster dictionary, always store explicit patterns"}}}};
Definition of the ITS/MFT clusterer settings.
Definition of the ITSMFT compact cluster.
std::string asString(TDataMember const &dm, char *pointer)
Definition of the Alpide pixel reader for MC digits processing.
Declarations of helper classes for the ITS/MFT raw data decoding.
Header of the AggregatedRunInfo struct.
Helper for geometry and GRP related CCDB requests.
Definition of the ITS cluster finder.
Definition of the Alpide pixel reader for raw data processing.
Device to decode ITS/MFT raw data from STF.
Checks validity of hardware address (HW) and transform it to digit AbsId index.
void checkUpdates(o2::framework::ProcessingContext &pc)
static int getNHBFPerTF()
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
static const VerbosityConfig & Instance()
T get(const char *key) const
void snapshot(const Output &spec, T const &object)
decltype(auto) make(const Output &spec, Args... args)
ConfigParamRegistry const & options()
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
static void setNoisyPixels(const NoiseMap *noise)
void setDigits(const gsl::span< const o2::itsmft::Digit > a)
void setSquashingDist(const int16_t v)
void setMaxBCSeparationToSquash(int n)
void setROFRecords(const gsl::span< const o2::itsmft::ROFRecord > a)
void setSquashingDepth(const int16_t v)
NoiseMap class for the ITS and MFT.
void run(ProcessingContext &pc) final
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void init(InitContext &ic) final
GLuint const GLchar * name
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLfloat GLfloat GLfloat v2
constexpr o2::header::DataOrigin gDataOriginMFT
constexpr o2::header::DataDescription gDataDescriptionRawData
constexpr o2::header::DataOrigin gDataOriginITS
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
Node par(int index)
Parameters.
Defining ITS Vertex explicitly as messageable.
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > select(char const *matcher="")
o2::framework::DataProcessorSpec getSTFDecoderSpec(const STFDecoderInp &inp)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string asString() const
size_t maxInputTimeslices
The maximum number of time pipelining for this device.
size_t inputTimesliceId
The time pipelining id of this particular device.
bool globalRunNumberChanged
float maxSOTMUS
max expected signal over threshold in \mus
int getMaxBCDiffToSquashBias(int layer) const noexcept
int maxBCDiffToSquashBias
squash if 2 ROFs differ by <= StrobeLength + Bias BCs, use value <0 to disable squashing
int maxRowColDiffToMask
pixel may be masked as overflow if such a neighbour in prev frame was fired
int maxBCDiffToMaskBias
mask if 2 ROFs differ by <= StrobeLength + Bias BCs, use value <0 to disable masking
static constexpr int getNLayers()
int getROFLengthInBC(int layer) const noexcept
int roFrameLengthInBC
ROF length in BC for continuous mode.
float roFrameLengthTrig
length of RO frame in ns for triggered mode
o2::header::DataOrigin origin
static bool pathIsDirectory(const std::string_view p)
static std::vector< std::string > tokenize(const std::string &src, char delim, bool trimToken=true, bool skipEmpty=true)
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)