107 if (mDigits.size() == 0 || mTriggerRecords.size() == 0) {
112 int nClsInvalidFit = 0;
119 std::vector<uint64_t> digitIdxArray(mDigits.size());
120 std::iota(digitIdxArray.begin(), digitIdxArray.end(), 0);
121 for (
const auto& trig : mTriggerRecords) {
123 const auto&
digits = mDigits;
124 std::stable_sort(std::begin(digitIdxArray) + trig.getFirstDigit(), std::begin(digitIdxArray) + trig.getNumberOfDigits() + trig.getFirstDigit(),
125 [&
digits](uint64_t
i, uint64_t
j) { return digits[i].getDetector() < digits[j].getDetector(); });
139 int digitCounter = 0;
140 std::array<unsigned int, MAXCHAMBER + 1> idxFirstDigitInDet{};
141 auto idxHelperPtr = &(idxFirstDigitInDet.data()[1]);
142 idxHelperPtr[-1] = 0;
143 for (
int iDigit = trig.getFirstDigit(); iDigit < trig.getFirstDigit() + trig.getNumberOfDigits(); ++iDigit) {
144 if (mDigits[digitIdxArray[iDigit]].getDetector() > currDet) {
145 nextDet = mDigits[digitIdxArray[iDigit]].getDetector();
146 for (
int iDet = currDet; iDet < nextDet; ++iDet) {
147 idxHelperPtr[iDet] = digitCounter;
153 for (
int iDet = currDet; iDet <=
MAXCHAMBER; ++iDet) {
154 idxHelperPtr[iDet] = digitCounter;
158 for (
int iDet = 0; iDet <
MAXCHAMBER; ++iDet) {
159 unsigned int nDigitsInDet = idxFirstDigitInDet[iDet + 1] - idxFirstDigitInDet[iDet];
160 std::vector<bool> isAdcUsed(nDigitsInDet *
TIMEBINS);
161 std::vector<bool> isDigitUsed(nDigitsInDet);
162 bool continueClusterSearch =
true;
164 while (continueClusterSearch) {
171 for (
unsigned int iDigit = 0; iDigit < nDigitsInDet; ++iDigit) {
172 uint64_t digitIdx = digitIdxArray[trig.getFirstDigit() + idxFirstDigitInDet[iDet] + iDigit];
173 if (mDigits[digitIdx].isSharedDigit()) {
177 if (isDigitUsed[iDigit]) {
182 auto maxAdcInDigit = mDigits[digitIdx].getADCmax(tbMaxADC);
183 if (maxAdcInDigit > adcMax) {
186 rowMax = mDigits[digitIdx].getPadRow();
187 colMax = mDigits[digitIdx].getPadCol();
188 adcMax = maxAdcInDigit;
191 if (adcMax < mMinAdcForMax) {
203 int nUsedADCsInCl = 0;
204 std::vector<uint64_t> constituentAdcIndices;
205 for (
unsigned int iDigit = 0; iDigit < nDigitsInDet; ++iDigit) {
206 uint64_t digitIdx = digitIdxArray[trig.getFirstDigit() + idxFirstDigitInDet[iDet] + iDigit];
207 if (mDigits[digitIdx].isSharedDigit()) {
211 int row = mDigits[digitIdx].getPadRow();
212 if (std::abs(
row - rowMax) > 1) {
215 int col = mDigits[digitIdx].getPadCol();
216 if (std::abs(
col - colMax) > 2) {
219 bool addedAdc =
false;
220 for (
int iTb = 0; iTb <
TIMEBINS; ++iTb) {
221 if (isAdcUsed[iDigit *
TIMEBINS + iTb]) {
226 isAdcUsed[iDigit *
TIMEBINS + iTb] =
true;
227 if (mDigits[digitIdx].getADC()[iTb] > mMinAdcClContrib) {
237 constituentAdcIndices.push_back(digitIdx *
TIMEBINS + iTb);
240 isDigitUsed[iDigit] =
true;
241 if (
row < lowerRow) {
244 if (
row > upperRow) {
247 if (
col < lowerCol) {
250 if (
col > upperCol) {
257 int clSizeTime = upperTb - lowerTb;
258 int clSizeRow = upperRow - lowerRow;
259 int clSizeCol = upperCol - lowerCol;
261 if (nUsedADCsInCl > 0) {
263 continueClusterSearch =
true;
267 std::array<int, TIMEBINS> sumPerTb{};
268 int sumOfAllTimeBins = 0;
269 int sumOfAllTimeBinsAboveThreshold = 0;
270 for (
const auto idx : constituentAdcIndices) {
273 sumOfAllTimeBins += mDigits[iDigit].getADC()[iTb] - mBaselineAdc;
274 sumPerTb[iTb] += mDigits[iDigit].getADC()[iTb] - mBaselineAdc;
275 if (mDigits[iDigit].getADC()[iTb] > mMinAdcClEoverT) {
276 sumOfAllTimeBinsAboveThreshold += mDigits[iDigit].getADC()[iTb] - mBaselineAdc;
280 uint32_t sumOfAdcTrunc;
282 auto rmsAdcClusterTrunc =
getRms(constituentAdcIndices, 2, 3.,
static_cast<uint32_t
>(mMinAdcClEoverT * .95), rmsTimeTrunc, sumOfAdcTrunc);
283 (
void)rmsAdcClusterTrunc;
288 mLandauChi2Functor.
x.clear();
289 mLandauChi2Functor.
y.clear();
290 for (
int iTb = 0; iTb <
TIMEBINS; ++iTb) {
291 mLandauChi2Functor.
x.push_back((
float)iTb);
292 mLandauChi2Functor.
y.push_back(sumPerTb[iTb]);
293 if (sumPerTb[iTb] < mMinAdcForMax) {
296 if (sumPerTb[iTb] > maxAdcA) {
297 maxAdcA = sumPerTb[iTb];
307 for (
int iTb = 2; iTb <
TIMEBINS - 2; ++iTb) {
308 if (std::abs(maxTbA - iTb) < 3 || sumPerTb[iTb] < mMinAdcForSecondMax) {
312 if (sumPerTb[iTb] > maxAdcB) {
314 if (sumPerTb[iTb - 1] < sumPerTb[iTb] &&
315 sumPerTb[iTb - 2] < sumPerTb[iTb] &&
316 sumPerTb[iTb + 1] < sumPerTb[iTb] &&
317 sumPerTb[iTb + 2] < sumPerTb[iTb]) {
318 maxAdcB = sumPerTb[iTb];
327 if (maxAdcA < 0 || maxTbA <= 1 || maxTbA >= (
TIMEBINS - 2)) {
336 if ((sumPerTb[maxTbA - 1] /
static_cast<double>(maxAdcA)) < 0.1 || (sumPerTb[maxTbA + 1] /
static_cast<double>(maxAdcA)) < 0.25) {
342 if ((sumPerTb[maxTbB - 1] /
static_cast<double>(maxAdcB)) < 0.1 || (sumPerTb[maxTbB + 1] /
static_cast<double>(maxAdcB)) < 0.25) {
346 if (!isBadA && !isBadB) {
348 if (maxTbA > maxTbB || maxAdcA <= maxAdcB) {
354 if (clSizeCol > 0 && clSizeTime > 3 && clSizeTime <
TIMEBINS) {
355 mFitter.Config().ParSettings(0).SetValue(maxAdcA);
356 mFitter.Config().ParSettings(1).SetValue(maxTbA);
357 mFitter.Config().ParSettings(2).SetValue(.5);
358 bool fitOK = mFitter.FitFCN();
362 mFuncLandauFit->SetParameters(mFitResult->GetParams()[0], mFitResult->GetParams()[1], mFitResult->GetParams()[2]);
363 double integralLandauFit = fitOK ? mFuncLandauFit->Integral(0.,
static_cast<double>(
TIMEBINS), 1.e-9) : 0.;
367 auto rmsAdc =
getRms(constituentAdcIndices, 1, 2.5, mMinAdcClContrib, rmsTime, rmsSumAdc);
371 if (!isBadA && !isBadB) {
374 for (
int iTb = 0; iTb <
TIMEBINS; ++iTb) {
375 if (iTb < (maxTbB - 2)) {
376 sumAdcA += mLandauChi2Functor.
y[iTb];
378 sumAdcA += mFuncLandauFit->Eval(mLandauChi2Functor.
x[iTb]);
379 sumAdcB += mLandauChi2Functor.
y[iTb] - mFuncLandauFit->Eval(mLandauChi2Functor.
x[iTb]);
384 if (sumOfAllTimeBins <= std::numeric_limits<uint16_t>::max() &&
385 sumOfAllTimeBinsAboveThreshold <= std::numeric_limits<uint16_t>::max() &&
386 integralLandauFit <= std::numeric_limits<uint16_t>::max() &&
387 sumAdcA <= std::numeric_limits<uint16_t>::max() &&
388 sumAdcB <= std::numeric_limits<uint16_t>::max() &&
389 rmsAdc <= std::numeric_limits<uint16_t>::max() &&
390 rmsTime <= std::numeric_limits<uint8_t>::max() &&
391 nUsedADCsInCl <= std::numeric_limits<uint8_t>::max() &&
392 sumOfAdcTrunc <= std::numeric_limits<uint16_t>::max()) {
401 cluster.
setAdcData(sumOfAllTimeBins, (
int)rmsAdc, (
int)sumAdcA, (
int)sumAdcB, sumOfAllTimeBinsAboveThreshold, (
int)integralLandauFit, sumOfAdcTrunc);
404 mKrClusters.push_back(cluster);
409 LOG(
debug) <<
"Kr cluster cannot be added because values are out of range";
410 LOGF(
debug,
"sumOfAllTimeBins(%i), sumAdcA(%f), sumAdcB(%f), clSizeRow(%i), clSizeCol(%i), clSizeTime(%i), maxTbA(%i), maxTbB(%i)", sumOfAllTimeBins, sumAdcA, sumAdcB, clSizeRow, clSizeCol, clSizeTime, maxTbA, maxTbB);
411 LOGF(
debug,
"rmsAdc(%f), rmsTime(%f), nUsedADCsInCl(%i), sumOfAllTimeBinsAboveThreshold(%i), integralLandauFit(%f), sumOfAdcTrunc(%u)", rmsAdc, rmsTime, nUsedADCsInCl, sumOfAllTimeBinsAboveThreshold, integralLandauFit, sumOfAdcTrunc);
419 mTrigRecs.emplace_back(mTriggerRecords[0].getBCData(), nClsTotal);
420 LOGF(info,
"Number of Kr clusters with a) invalid fit (%i) b) out-of-range values which were dropped (%i)", nClsInvalidFit, nClsDropped);