Skip to content

Commit dd273bd

Browse files
authored
ITS: process hits from different MEBs + bug fix for scurve dump (#12110)
* added possibility to process hits from different MEBs + bug fix for s-curves dump * reverted unwanted change
1 parent fbb3a88 commit dd273bd

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ namespace its
6363
{
6464

6565
int nInj = 50;
66+
int nInjScaled = 50; // different from nInj only if mMeb > 0, in this case it is nInj/3.
6667

6768
// List of the possible run types for reference
6869
enum RunTypes {
@@ -72,6 +73,7 @@ enum RunTypes {
7273
THR_SCAN_SHORT_2_10HZ = 18,
7374
THR_SCAN_SHORT_100HZ = 19,
7475
THR_SCAN_SHORT_200HZ = 20,
76+
THR_SCAN_SHORT_150INJ = 55,
7577
VCASN150 = 23,
7678
VCASN100 = 10,
7779
VCASN100_100HZ = 21,
@@ -164,7 +166,7 @@ class ITSThresholdCalibrator : public Task
164166
short int vRow[N_COL];
165167
short int vThreshold[N_COL];
166168
bool vSuccess[N_COL];
167-
unsigned char vNoise[N_COL];
169+
float vNoise[N_COL];
168170
unsigned char vPoints[N_COL];
169171
short int vMixData[N_COL];
170172
unsigned char vCharge[N_COL];
@@ -288,6 +290,7 @@ class ITSThresholdCalibrator : public Task
288290
// parameters for manual mode: if run type is not among the listed one
289291
bool isManualMode = false;
290292
bool saveTree;
293+
bool scaleNinj = false;
291294
short int manualMin, manualMin2 = 0;
292295
short int manualMax, manualMax2 = 0;
293296
short int manualStep = 1, manualStep2 = 1;
@@ -306,6 +309,7 @@ class ITSThresholdCalibrator : public Task
306309
int maxDumpS = -1; // maximum number of s-curves to be dumped, default -1 = dump all
307310
std::string chipDumpS = ""; // list of comma-separated O2 chipIDs to be dumped, default is empty = dump all
308311
int dumpCounterS[24120] = {0}; // count dumps for every chip
312+
int countCdw[24120] = {0}; // count how many CDWs have been processed with the maximum charge injected: usefull for s-curve dump when hits do not arrive in order
309313
TFile* fileDumpS; // file where to store the s-curves on disk
310314
std::vector<short int> chipDumpList; // vector of chips to dump
311315

@@ -317,6 +321,9 @@ class ITSThresholdCalibrator : public Task
317321
bool mCalculate2DParams = true;
318322
int chargeA = 0;
319323
int chargeB = 0;
324+
325+
// Variable to select from which MEB to consider the hits.
326+
int mMeb = -1;
320327
};
321328

322329
// Create a processor spec

Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ namespace its
2828
// Define error function for ROOT fitting
2929
double erf(double* xx, double* par)
3030
{
31-
return (nInj / 2) * TMath::Erf((xx[0] - par[0]) / (sqrt(2) * par[1])) + (nInj / 2);
31+
return (nInjScaled / 2) * TMath::Erf((xx[0] - par[0]) / (sqrt(2) * par[1])) + (nInjScaled / 2);
3232
}
3333

3434
// ITHR erf is reversed
3535
double erf_ithr(double* xx, double* par)
3636
{
37-
return (nInj / 2) * (1 - TMath::Erf((xx[0] - par[0]) / (sqrt(2) * par[1])));
37+
return (nInjScaled / 2) * (1 - TMath::Erf((xx[0] - par[0]) / (sqrt(2) * par[1])));
3838
}
3939

4040
//////////////////////////////////////////////////////////////////////////////
@@ -183,13 +183,17 @@ void ITSThresholdCalibrator::init(InitContext& ic)
183183

184184
// this is not mandatory since it's 5 by default
185185
manualStrobeWindow = ic.options().get<short int>("manual-strobewindow");
186+
187+
// Flag to scale the number of injections by 3 in case --meb-select is used
188+
scaleNinj = ic.options().get<bool>("scale-ninj");
186189
}
187190

188191
// Flag to enable the analysis of CRU_ITS data
189192
isCRUITS = ic.options().get<bool>("enable-cru-its");
190193

191194
// Number of injections
192195
nInj = ic.options().get<int>("ninj");
196+
nInjScaled = nInj;
193197

194198
// Flag to enable the call of the finalize() method at end of stream
195199
isFinalizeEos = ic.options().get<bool>("finalize-at-eos");
@@ -242,6 +246,12 @@ void ITSThresholdCalibrator::init(InitContext& ic)
242246
}
243247
}
244248

249+
// Variable to select from which multi-event buffer select the hits
250+
mMeb = ic.options().get<int>("meb-select");
251+
if (mMeb > 2) {
252+
LOG(error) << "MEB cannot be greater than 2. Please check your command line.";
253+
}
254+
245255
return;
246256
}
247257

@@ -357,7 +367,7 @@ void ITSThresholdCalibrator::initThresholdTree(bool recreate /*=true*/)
357367
this->mThresholdTree->Branch("row", &vRow, "vRow[1024]/S");
358368
if (this->mScanType == 'T') {
359369
this->mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S");
360-
this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/b");
370+
this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F");
361371
this->mThresholdTree->Branch("spoints", &vPoints, "vPoints[1024]/b");
362372
this->mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O");
363373
} else if (mScanType == 'D' || mScanType == 'A') { // this->mScanType == 'D' and this->mScanType == 'A'
@@ -381,7 +391,7 @@ void ITSThresholdCalibrator::initThresholdTree(bool recreate /*=true*/)
381391
this->mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S");
382392
} else if (mScanType == 'r') {
383393
this->mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S");
384-
this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/b");
394+
this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F");
385395
this->mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O");
386396
this->mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S");
387397
}
@@ -417,7 +427,7 @@ bool ITSThresholdCalibrator::findUpperLower(
417427
}
418428
for (int i = upper; i > 0; i--) {
419429
int comp = mScanType != 'r' ? data[iloop2][i] : data[i][iloop2];
420-
if (comp >= nInj) {
430+
if (comp >= nInjScaled) {
421431
lower = i;
422432
break;
423433
}
@@ -427,7 +437,7 @@ bool ITSThresholdCalibrator::findUpperLower(
427437

428438
for (int i = 0; i < NPoints; i++) {
429439
int comp = mScanType != 'r' ? data[iloop2][i] : data[i][iloop2];
430-
if (comp >= nInj) {
440+
if (comp >= nInjScaled) {
431441
upper = i;
432442
break;
433443
}
@@ -611,7 +621,7 @@ bool ITSThresholdCalibrator::findThresholdHitcounting(
611621
for (unsigned short int i = 0; i < NPoints; i++) {
612622
numberOfHits += (mScanType != 'r') ? data[iloop2][i] : data[i][iloop2];
613623
int comp = (mScanType != 'r') ? data[iloop2][i] : data[i][iloop2];
614-
if (!is50 && comp == nInj) {
624+
if (!is50 && comp == nInjScaled) {
615625
is50 = true;
616626
}
617627
}
@@ -625,11 +635,11 @@ bool ITSThresholdCalibrator::findThresholdHitcounting(
625635
}
626636

627637
if (this->mScanType == 'T') {
628-
thresh = this->mX[N_RANGE - 1] - numberOfHits / float(nInj);
638+
thresh = this->mX[N_RANGE - 1] - numberOfHits / float(nInjScaled);
629639
} else if (this->mScanType == 'V') {
630-
thresh = (this->mX[N_RANGE - 1] * nInj - numberOfHits) / float(nInj);
640+
thresh = (this->mX[N_RANGE - 1] * nInjScaled - numberOfHits) / float(nInjScaled);
631641
} else if (this->mScanType == 'I') {
632-
thresh = (numberOfHits + nInj * this->mX[0]) / float(nInj);
642+
thresh = (numberOfHits + nInjScaled * this->mX[0]) / float(nInjScaled);
633643
} else {
634644
LOG(error) << "Unexpected runtype encountered in findThresholdHitcounting()";
635645
return false;
@@ -748,7 +758,7 @@ void ITSThresholdCalibrator::extractThresholdRow(const short int& chipID, const
748758
vChipid[col_i] = chipID;
749759
vRow[col_i] = row;
750760
vThreshold[col_i] = (mScanType == 'T' || mScanType == 'r') ? (short int)(thresh * 10.) : (short int)(thresh);
751-
vNoise[col_i] = (unsigned char)(noise * 10.); // always factor 10 also for ITHR/VCASN to not have all zeros
761+
vNoise[col_i] = (float)(noise * 10.); // always factor 10 also for ITHR/VCASN to not have all zeros
752762
vSuccess[col_i] = success;
753763
vPoints[col_i] = spoints > 0 ? (unsigned char)(spoints) : 0;
754764

@@ -904,7 +914,7 @@ void ITSThresholdCalibrator::setRunType(const short int& runtype)
904914
this->mCheckExactRow = true;
905915

906916
} else if (runtype == THR_SCAN_SHORT || runtype == THR_SCAN_SHORT_100HZ ||
907-
runtype == THR_SCAN_SHORT_200HZ || runtype == THR_SCAN_SHORT_33 || runtype == THR_SCAN_SHORT_2_10HZ) {
917+
runtype == THR_SCAN_SHORT_200HZ || runtype == THR_SCAN_SHORT_33 || runtype == THR_SCAN_SHORT_2_10HZ || runtype == THR_SCAN_SHORT_150INJ) {
908918
// threshold_scan_short -- just extract thresholds for each pixel and write to TTree
909919
// 10 rows per chip
910920
this->mScanType = 'T';
@@ -913,7 +923,12 @@ void ITSThresholdCalibrator::setRunType(const short int& runtype)
913923
this->mMax = 50;
914924
this->N_RANGE = 51;
915925
this->mCheckExactRow = true;
916-
926+
if (runtype == THR_SCAN_SHORT_150INJ) {
927+
nInj = 150;
928+
if (mMeb >= 0) {
929+
nInjScaled = nInj / 3;
930+
}
931+
}
917932
} else if (runtype == VCASN150 || runtype == VCASN100 || runtype == VCASN100_100HZ || runtype == VCASN130 || runtype == VCASNBB) {
918933
// VCASN tuning for different target thresholds
919934
// Store average VCASN for each chip into CCDB
@@ -1007,7 +1022,7 @@ void ITSThresholdCalibrator::setRunType(const short int& runtype)
10071022
this->initThresholdTree();
10081023
} else {
10091024
// No other run type recognized by this workflow
1010-
LOG(warning) << "Runtype " << runtype << " not recognized by calibration workflow.";
1025+
LOG(error) << "Runtype " << runtype << " not recognized by calibration workflow (ignore if you are in manual mode)";
10111026
if (isManualMode) {
10121027
LOG(info) << "Entering manual mode: be sure to have set all parameters correctly";
10131028
this->mScanType = manualScanType[0];
@@ -1025,6 +1040,9 @@ void ITSThresholdCalibrator::setRunType(const short int& runtype)
10251040
}
10261041
this->mFitType = (mScanType == 'D' || mScanType == 'A' || mScanType == 'P' || mScanType == 'p') ? NO_FIT : mFitType;
10271042
this->mCheckExactRow = (mScanType == 'D' || mScanType == 'A') ? false : true;
1043+
if (scaleNinj) {
1044+
nInjScaled = nInj / 3;
1045+
}
10281046
} else {
10291047
throw runtype;
10301048
}
@@ -1062,7 +1080,7 @@ bool ITSThresholdCalibrator::isScanFinished(const short int& chipID, const short
10621080
short int chg = (mScanType == 'I' || mScanType == 'D' || mScanType == 'A') ? 0 : (N_RANGE - 1);
10631081

10641082
// check 2 pixels in case one of them is dead
1065-
return ((this->mPixelHits[chipID][row][col][0][chg] >= nInj || this->mPixelHits[chipID][row][col + 100][0][chg] >= nInj) && (!mCheckCw || cwcnt == nInj - 1));
1083+
return ((this->mPixelHits[chipID][row][col][0][chg] >= nInjScaled || this->mPixelHits[chipID][row][col + 100][0][chg] >= nInjScaled) && (!mCheckCw || cwcnt == nInj - 1));
10661084
}
10671085

10681086
//////////////////////////////////////////////////////////////////////////////
@@ -1429,7 +1447,7 @@ void ITSThresholdCalibrator::run(ProcessingContext& pc)
14291447
continue;
14301448
}
14311449

1432-
if (!mChipsForbRows[chipID] && (!mCheckExactRow || d.getRow() == row)) { // row has NOT to be forbidden and we ignore hits coming from other rows (potential masking issue on chip)
1450+
if (!mChipsForbRows[chipID] && (!mCheckExactRow || d.getRow() == row) && (mMeb < 0 || cwcnt % 3 == mMeb)) { // row has NOT to be forbidden and we ignore hits coming from other rows (potential masking issue on chip)
14331451
// Increment the number of counts for this pixel
14341452
this->mPixelHits[chipID][d.getRow()][col][chgPoint][loopPoint]++;
14351453
}
@@ -1450,7 +1468,10 @@ void ITSThresholdCalibrator::run(ProcessingContext& pc)
14501468
if (isDumpS) {
14511469
auto fndVal = std::find(chipDumpList.begin(), chipDumpList.end(), chipID);
14521470
int checkR = (mScanType == 'I') ? mMin : mMax;
1453-
passCondition = (cwcnt == nInj - 1) && (loopval == checkR) && (fndVal != chipDumpList.end() || !chipDumpList.size()); // in this way we dump any s-curve, bad and good
1471+
if (loopval == checkR) {
1472+
countCdw[chipID]++;
1473+
}
1474+
passCondition = (countCdw[chipID] == nInj) && (loopval == checkR) && (fndVal != chipDumpList.end() || !chipDumpList.size()); // in this way we dump any s-curve, bad and good
14541475
if (mVerboseOutput) {
14551476
LOG(info) << "Loopval: " << loopval << " counter: " << cwcnt << " checkR: " << checkR << " chipID: " << chipID << " pass: " << passCondition;
14561477
}
@@ -1467,6 +1488,7 @@ void ITSThresholdCalibrator::run(ProcessingContext& pc)
14671488

14681489
if (mScanType != 'D' && mScanType != 'A' && mScanType != 'P' && mScanType != 'p' && mScanType != 'R' && mScanType != 'r' && passCondition) { // for D,A,P we do it at the end in finalize()
14691490
this->extractAndUpdate(chipID, row);
1491+
countCdw[chipID] = 0;
14701492
// remove entry for this row whose scan is completed
14711493
mPixelHits[chipID].erase(row);
14721494
mForbiddenRows[chipID].push_back(row); // due to the loose cut in isScanFinished, extra hits may come for this deleted row. In this way the row is ignored afterwards
@@ -1982,6 +2004,7 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf)
19822004
{"manual-scantype", VariantType::String, "T", {"scan type, can be D, T, I, V, P, p: use only in manual mode"}},
19832005
{"manual-strobewindow", VariantType::Int, 5, {"strobe duration in clock cycles, default is 5 = 125 ns: use only in manual mode"}},
19842006
{"save-tree", VariantType::Bool, false, {"Flag to save ROOT tree on disk: use only in manual mode"}},
2007+
{"scale-ninj", VariantType::Bool, false, {"Flag to activate the scale of the number of injects to be used to count hits from specific MEBs: use only in manual mode and in combination with --meb-select"}},
19852008
{"enable-mpv", VariantType::Bool, false, {"Flag to enable calculation of most-probable value in vcasn/ithr scans"}},
19862009
{"enable-cru-its", VariantType::Bool, false, {"Flag to enable the analysis of raw data on disk produced by CRU_ITS IB commissioning tools"}},
19872010
{"ninj", VariantType::Int, 50, {"Number of injections per change, default is 50"}},
@@ -1991,7 +2014,8 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf)
19912014
{"calculate-slope", VariantType::Bool, false, {"For Pulse Shape 2D: if enabled it calculate the slope of the charge vs strobe delay trend for each pixel and fill it in the output tree"}},
19922015
{"finalize-at-eos", VariantType::Bool, false, {"Call the finalize() method at the end of stream: to be used in case end-of-run flags are not available so to force calculations at end of run"}},
19932016
{"charge-a", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 1st point used for the slope calculation"}},
1994-
{"charge-b", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 2nd point used for the slope calculation"}}}};
2017+
{"charge-b", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 2nd point used for the slope calculation"}},
2018+
{"meb-select", VariantType::Int, -1, {"Select from which multi-event buffer consider the hits: 0,1 or 2"}}}};
19952019
}
19962020
} // namespace its
19972021
} // namespace o2

0 commit comments

Comments
 (0)