31 auto gain = calPads[0];
34 LOGP(error,
"No valid gain map object '{}' could be loaded from file '{}'", calDetFileName, gainMapName);
38 LOGP(info,
"Loaded gain map object '{}' from file '{}'", calDetFileName, gainMapName);
41void KrBoxClusterFinder::createInitialMap(
const gsl::span<const Digit> eventSector)
43 mSetOfTimeSlices.clear();
44 mThresholdInfo.clear();
46 for (
int iTimeSlice = 0; iTimeSlice <= 2 * mMaxClusterSizeTime; ++iTimeSlice) {
47 addTimeSlice(eventSector, iTimeSlice);
51void KrBoxClusterFinder::fillADCValueInLastSlice(
int cru,
int rowInSector,
int padInRow,
float adcValue)
53 auto& timeSlice = mSetOfTimeSlices.back();
54 auto& thresholdInfo = mThresholdInfo.back();
58 const int corPad = padInRow - (padsInRow / 2) + (MaxPads / 2);
60 if (adcValue > mQThresholdMax) {
61 thresholdInfo.digitAboveThreshold =
true;
62 thresholdInfo.rowAboveThreshold[rowInSector] =
true;
66 const auto correctionFactorCalDet = mGainMap.get();
67 if (!correctionFactorCalDet) {
68 timeSlice[rowInSector][corPad] = adcValue;
73 float correctionFactor = correctionFactorCalDet->getValue(mSector, padNum);
75 if (correctionFactor <= 0) {
76 LOGP(warning,
"Encountered correction factor which is zero.");
77 LOGP(warning,
"Digit will be set to 0!");
80 adcValue /= correctionFactor;
83 timeSlice[rowInSector][corPad] = adcValue;
86void KrBoxClusterFinder::addTimeSlice(
const gsl::span<const Digit> eventSector,
const int timeSlice)
88 mSetOfTimeSlices.emplace_back();
89 mThresholdInfo.emplace_back();
91 for (; mFirstDigit < eventSector.size(); ++mFirstDigit) {
92 const auto& digit = eventSector[mFirstDigit];
93 const int time = digit.getTimeStamp();
94 if (
time != timeSlice) {
98 const int cru = digit.getCRU();
101 const int rowInSector = digit.getRow();
102 const int padInRow = digit.getPad();
103 const float adcValue = digit.getChargeFloat();
105 fillADCValueInLastSlice(cru, rowInSector, padInRow, adcValue);
114 createInitialMap(eventSector);
115 for (
int iTimeSlice = mMaxClusterSizeTime; iTimeSlice < mMaxTimes - mMaxClusterSizeTime; ++iTimeSlice) {
117 if (mThresholdInfo[mMaxClusterSizeTime].digitAboveThreshold) {
120 popFirstTimeSliceFromMap();
121 addTimeSlice(eventSector, iTimeSlice + mMaxClusterSizeTime + 1);
124 if (mFirstDigit >= eventSector.size()) {
134 mMaxClusterSizeTime =
param.MaxClusterSizeTime;
136 mMaxClusterSizeRowIROC =
param.MaxClusterSizeRowIROC;
137 mMaxClusterSizeRowOROC1 =
param.MaxClusterSizeRowOROC1;
138 mMaxClusterSizeRowOROC2 =
param.MaxClusterSizeRowOROC2;
139 mMaxClusterSizeRowOROC3 =
param.MaxClusterSizeRowOROC3;
141 mMaxClusterSizePadIROC =
param.MaxClusterSizePadIROC;
142 mMaxClusterSizePadOROC1 =
param.MaxClusterSizePadOROC1;
143 mMaxClusterSizePadOROC2 =
param.MaxClusterSizePadOROC2;
144 mMaxClusterSizePadOROC3 =
param.MaxClusterSizePadOROC3;
146 mQThresholdMax =
param.QThresholdMax;
147 mQThreshold =
param.QThreshold;
148 mMinNumberOfNeighbours =
param.MinNumberOfNeighbours;
150 mCutMinSigmaTime =
param.CutMinSigmaTime;
151 mCutMaxSigmaTime =
param.CutMaxSigmaTime;
152 mCutMinSigmaPad =
param.CutMinSigmaPad;
153 mCutMaxSigmaPad =
param.CutMaxSigmaPad;
154 mCutMinSigmaRow =
param.CutMinSigmaRow;
155 mCutMaxSigmaRow =
param.CutMaxSigmaRow;
156 mCutMaxQtot =
param.CutMaxQtot;
157 mCutQtot0 =
param.CutQtot0;
158 mCutQtotSizeSlope =
param.CutQtotSizeSlope;
159 mCutMaxSize =
param.CutMaxSize;
160 mApplyCuts =
param.ApplyCuts;
162 if (
param.GainMapFile.size()) {
163 LOGP(info,
"loading gain map '{}' from file {}",
param.GainMapName,
param.GainMapFile);
171void KrBoxClusterFinder::updateTempClusterFinal(
const int timeOffset)
174 mTempCluster.
reset();
176 const float oneOverQtot = 1. / mTempCluster.
totCharge;
177 mTempCluster.
meanPad *= oneOverQtot;
178 mTempCluster.
sigmaPad *= oneOverQtot;
179 mTempCluster.
meanRow *= oneOverQtot;
180 mTempCluster.
sigmaRow *= oneOverQtot;
181 mTempCluster.
meanTime *= oneOverQtot;
191 mTempCluster.
meanPad = mTempCluster.
meanPad + (corPadsMean / 2.0) - (MaxPads / 2.0);
193 mTempCluster.
sector = (
decltype(mTempCluster.
sector))mSector;
195 mTempCluster.
meanTime += timeOffset;
200void KrBoxClusterFinder::updateTempCluster(
float tempCharge,
int tempPad,
int tempRow,
int tempTime)
202 if (tempCharge < mQThreshold) {
203 LOGP(warning,
"Update cluster was called but current charge is below mQThreshold");
209 if (mTempCluster.
size < 255) {
210 mTempCluster.
size += 1;
215 mTempCluster.
meanPad += tempPad * tempCharge;
216 mTempCluster.
sigmaPad += tempPad * tempPad * tempCharge;
218 mTempCluster.
meanRow += tempRow * tempCharge;
219 mTempCluster.
sigmaRow += tempRow * tempRow * tempCharge;
221 mTempCluster.
meanTime += tempTime * tempCharge;
222 mTempCluster.
sigmaTime += tempTime * tempTime * tempCharge;
224 if (tempCharge > mTempCluster.
maxCharge) {
235 std::vector<std::tuple<int, int, int>> localMaximaCoords;
237 const int iTime = mMaxClusterSizeTime;
238 const auto& mapRow = mSetOfTimeSlices[iTime];
239 const auto& thresholdInfo = mThresholdInfo[iTime];
241 for (
int iRow = 0; iRow < MaxRows; iRow++) {
245 mMaxClusterSizePad = mMaxClusterSizePadIROC;
246 mMaxClusterSizeRow = mMaxClusterSizeRowIROC;
247 }
else if (iRow == MaxRowsIROC) {
248 mMaxClusterSizePad = mMaxClusterSizePadOROC1;
249 mMaxClusterSizeRow = mMaxClusterSizeRowOROC1;
250 }
else if (iRow == MaxRowsIROC + MaxRowsOROC1) {
251 mMaxClusterSizePad = mMaxClusterSizePadOROC2;
252 mMaxClusterSizeRow = mMaxClusterSizeRowOROC2;
253 }
else if (iRow == MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) {
254 mMaxClusterSizePad = mMaxClusterSizePadOROC3;
255 mMaxClusterSizeRow = mMaxClusterSizeRowOROC3;
258 if (!thresholdInfo.rowAboveThreshold[iRow]) {
262 const auto& mapPad = mapRow[iRow];
266 for (
int iPad = MaxPads / 2 - padsInRow / 2; iPad < MaxPads / 2 + padsInRow / 2; iPad++) {
268 const float qMax = mapPad[iPad];
271 if (qMax <= mQThresholdMax) {
277 int noNeighbours = 0;
278 if ((iPad + 1 < MaxPads) && (mapPad[iPad + 1] > mQThreshold)) {
279 if (mapPad[iPad + 1] > qMax) {
285 if ((iPad - 1 >= 0) && (mapPad[iPad - 1] > mQThreshold)) {
286 if (mapPad[iPad - 1] > qMax) {
292 if ((iRow + 1 < MaxRows) && (mSetOfTimeSlices[iTime][iRow + 1][iPad] > mQThreshold)) {
293 if (mSetOfTimeSlices[iTime][iRow + 1][iPad] > qMax) {
299 if ((iRow - 1 >= 0) && (mSetOfTimeSlices[iTime][iRow - 1][iPad] > mQThreshold)) {
300 if (mSetOfTimeSlices[iTime][iRow - 1][iPad] > qMax) {
306 if ((iTime + 1 < mMaxTimes) && (mSetOfTimeSlices[iTime + 1][iRow][iPad] > mQThreshold)) {
307 if (mSetOfTimeSlices[iTime + 1][iRow][iPad] > qMax) {
313 if ((iTime - 1 >= 0) && (mSetOfTimeSlices[iTime - 1][iRow][iPad] > mQThreshold)) {
314 if (mSetOfTimeSlices[iTime - 1][iRow][iPad] > qMax) {
319 if (noNeighbours < mMinNumberOfNeighbours) {
328 bool thisIsMax =
true;
330 for (
int j = -mMaxClusterSizeTime; (
j <= mMaxClusterSizeTime) && thisIsMax;
j++) {
331 if ((iTime +
j >= mMaxTimes) || (iTime +
j < 0)) {
334 for (
int k = -mMaxClusterSizeRow; (k <= mMaxClusterSizeRow) && thisIsMax; k++) {
335 if ((iRow + k >= MaxRows) || (iRow + k < 0)) {
338 for (
int i = -mMaxClusterSizePad; (
i <= mMaxClusterSizePad) && thisIsMax;
i++) {
339 if ((iPad +
i >= MaxPads) || (iPad +
i < 0)) {
342 if (mSetOfTimeSlices[iTime +
j][iRow + k][iPad +
i] > qMax) {
354 buildCluster(iPad, iRow, iTime, directFilling, timeOffset);
356 localMaximaCoords.emplace_back(std::make_tuple(iPad, iRow, iTime));
360 iPad += mMaxClusterSizePad;
365 return localMaximaCoords;
387 mTempCluster.
reset();
391 for (
int iTime = -mMaxClusterSizeTime; iTime <= mMaxClusterSizeTime; iTime++) {
394 for (
int iRow = -mMaxClusterSizeRow; iRow <= mMaxClusterSizeRow; iRow++) {
396 if (clusterCenterRow + iRow < 0) {
398 }
else if (clusterCenterRow + iRow >= MaxRows) {
402 else if (clusterCenterRow < MaxRowsIROC) {
403 if (clusterCenterRow + iRow > MaxRowsIROC) {
406 }
else if (clusterCenterRow < MaxRowsIROC + MaxRowsOROC1) {
407 if (clusterCenterRow + iRow < MaxRowsIROC || clusterCenterRow + iRow >= MaxRowsIROC + MaxRowsOROC1) {
410 }
else if (clusterCenterRow < MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) {
411 if (clusterCenterRow + iRow < MaxRowsIROC + MaxRowsOROC1 || clusterCenterRow + iRow >= MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) {
414 }
else if (clusterCenterRow < MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2 + MaxRowsOROC3) {
415 if (clusterCenterRow + iRow < MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) {
421 for (
int iPad = -mMaxClusterSizePad; iPad <= mMaxClusterSizePad; iPad++) {
423 if (clusterCenterPad + iPad < 0) {
425 }
else if (clusterCenterPad + iPad >= MaxPads) {
431 if (mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad] <= mQThreshold) {
436 if (std::abs(iTime) == std::abs(iPad) && std::abs(iTime) == std::abs(iRow)) {
438 if (mSetOfTimeSlices[clusterCenterTime + iTime - signnum(iTime)][clusterCenterRow + iRow - signnum(iRow)][clusterCenterPad + iPad - signnum(iPad)] > mQThreshold) {
440 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
444 else if (std::abs(iTime) == std::abs(iPad)) {
445 if (mSetOfTimeSlices[clusterCenterTime + iTime - signnum(iTime)][clusterCenterRow + iRow][clusterCenterPad + iPad - signnum(iPad)] > mQThreshold) {
446 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
448 }
else if (std::abs(iTime) == std::abs(iRow)) {
449 if (mSetOfTimeSlices[clusterCenterTime + iTime - signnum(iTime)][clusterCenterRow + iRow - signnum(iRow)][clusterCenterPad + iPad] > mQThreshold) {
450 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
452 }
else if (std::abs(iPad) == std::abs(iRow)) {
453 if (mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow - signnum(iRow)][clusterCenterPad + iPad - signnum(iPad)] > mQThreshold) {
454 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
456 }
else if (std::abs(iTime) > std::abs(iPad) && std::abs(iTime) > std::abs(iRow)) {
457 if (mSetOfTimeSlices[clusterCenterTime + iTime - signnum(iTime)][clusterCenterRow + iRow][clusterCenterPad + iPad] > mQThreshold) {
458 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
460 }
else if (std::abs(iTime) < std::abs(iPad) && std::abs(iPad) > std::abs(iRow)) {
461 if (mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad - signnum(iPad)] > mQThreshold) {
462 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
464 }
else if (std::abs(iTime) < std::abs(iRow) && std::abs(iPad) < std::abs(iRow)) {
465 if (mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow - signnum(iRow)][clusterCenterPad + iPad] > mQThreshold) {
466 updateTempCluster(mSetOfTimeSlices[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad], clusterCenterPad + iPad, clusterCenterRow + iRow, clusterCenterTime + iTime);
475 updateTempClusterFinal(timeOffset);
478 if (!mApplyCuts || acceptCluster(mTempCluster)) {
479 mClusters.emplace_back(mTempCluster);
489 if (
row < MaxRowsIROC) {
490 mMaxClusterSizePad = mMaxClusterSizePadIROC;
491 mMaxClusterSizeRow = mMaxClusterSizeRowIROC;
492 }
else if (
row < MaxRowsIROC + MaxRowsOROC1) {
493 mMaxClusterSizePad = mMaxClusterSizePadOROC1;
494 mMaxClusterSizeRow = mMaxClusterSizeRowOROC1;
495 }
else if (
row < MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) {
496 mMaxClusterSizePad = mMaxClusterSizePadOROC2;
497 mMaxClusterSizeRow = mMaxClusterSizeRowOROC2;
498 }
else if (
row < MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2 + MaxRowsOROC3) {
499 mMaxClusterSizePad = mMaxClusterSizePadOROC3;
500 mMaxClusterSizeRow = mMaxClusterSizeRowOROC3;
504bool KrBoxClusterFinder::acceptCluster(
const KrCluster& cl)
519 if (cl.
totCharge > mCutQtot0 + mCutQtotSizeSlope * cl.
size) {
524 if (cl.
size > mCutMaxSize) {
static const KrBoxClusterFinderParam & Instance()
void loadGainMapFromFile(const std::string_view calDetFileName, const std::string_view gainMapName="GainMap")
void init()
initialize the parameters from KrBoxClusterFinderParam
void loopOverSector(const gsl::span< const Digit > eventSector, const int sector)
std::vector< std::tuple< int, int, int > > findLocalMaxima(bool directFilling=true, const int timeOffset=0)
After the map is created, we look for local maxima with this function:
KrCluster buildCluster(int clusterCenterPad, int clusterCenterRow, int clusterCenterTime, bool directFilling=false, const int timeOffset=0)
void setMaxClusterSize(int maxClusterSizeRowIROC, int maxClusterSizeRowOROC1, int maxClusterSizeRowOROC2, int maxClusterSizeRowOROC3, int maxClusterSizePadIROC, int maxClusterSizePadOROC1, int maxClusterSizePadOROC2, int maxClusterSizePadOROC3, int maxClusterSizeTime)
Set Function for maximal cluster sizes in different ROCs.
int getNumberOfPadsInRowSector(int row) const
GlobalPadNumber globalPadNumber(const PadPos &globalPadPosition) const
std::vector< CalPad * > readCalPads(const std::string_view fileName, const std::vector< std::string > &calPadNames)
Global TPC definitions and constants.
float meanPad
Center of gravity (Pad number)
float meanTime
Center of gravity (Time)
float maxCharge
Maximum charge of the cluster (ADC counts)
unsigned char sector
Sector number.
float sigmaTime
RMS of cluster in time direction.
unsigned char maxChargePad
Pad with max. charge in cluster (for leader pad method)
void reset()
Used to set all Cluster variables to zero.
float meanRow
Center of gravity (Row number)
float sigmaPad
RMS of cluster in pad direction.
float sigmaRow
RMS of cluster in row direction.
float totCharge
Total charge of the cluster (ADC counts)
unsigned char size
Size of the cluster (TPCDigits)
unsigned char maxChargeRow
Row with max. charge in cluster (for leader pad method)