@@ -142,6 +142,9 @@ void ITSThresholdCalibrator::init(InitContext& ic)
142142 throw std::runtime_error (" Min VCASN/ITHR is larger than Max VCASN/ITHR: check the settings, analysis not possible" );
143143 }
144144
145+ // Get flag to enable most-probable value calculation
146+ isMpv = ic.options ().get <bool >(" enable-mpv" );
147+
145148 // Parameters to operate in manual mode (when run type is not recognized automatically)
146149 isManualMode = ic.options ().get <bool >(" manual-mode" );
147150 if (isManualMode) {
@@ -228,7 +231,7 @@ void ITSThresholdCalibrator::initThresholdTree(bool recreate /*=true*/)
228231// x is the array of charge injected values;
229232// NPoints is the length of both arrays.
230233bool ITSThresholdCalibrator::findUpperLower (
231- const unsigned short int * data, const short int * x, const short int & NPoints,
234+ const unsigned short int * data, const short int & NPoints,
232235 short int & lower, short int & upper, bool flip)
233236{
234237 // Initialize (or re-initialize) upper and lower
@@ -284,7 +287,7 @@ bool ITSThresholdCalibrator::findUpperLower(
284287// ////////////////////////////////////////////////////////////////////////////
285288// Main findThreshold function which calls one of the three methods
286289bool ITSThresholdCalibrator::findThreshold (
287- const unsigned short int * data, const short int * x, short int & NPoints,
290+ const unsigned short int * data, const float * x, short int & NPoints,
288291 float & thresh, float & noise)
289292{
290293 bool success = false ;
@@ -314,13 +317,13 @@ bool ITSThresholdCalibrator::findThreshold(
314317// NPoints is the length of both arrays.
315318// thresh, noise, chi2 pointers are updated with results from the fit
316319bool ITSThresholdCalibrator::findThresholdFit (
317- const unsigned short int * data, const short int * x, const short int & NPoints,
320+ const unsigned short int * data, const float * x, const short int & NPoints,
318321 float & thresh, float & noise)
319322{
320323 // Find lower & upper values of the S-curve region
321324 short int lower, upper;
322325 bool flip = (this ->mScanType == ' I' );
323- if (!this ->findUpperLower (data, x, NPoints, lower, upper, flip) || lower == upper) {
326+ if (!this ->findUpperLower (data, NPoints, lower, upper, flip) || lower == upper) {
324327 if (this ->mVerboseOutput ) {
325328 LOG (warning) << " Start-finding unsuccessful: (lower, upper) = ("
326329 << lower << " , " << upper << " )" ;
@@ -362,13 +365,13 @@ bool ITSThresholdCalibrator::findThresholdFit(
362365// x is the array of charge injected values;
363366// NPoints is the length of both arrays.
364367
365- bool ITSThresholdCalibrator::findThresholdDerivative (const unsigned short int * data, const short int * x, const short int & NPoints,
368+ bool ITSThresholdCalibrator::findThresholdDerivative (const unsigned short int * data, const float * x, const short int & NPoints,
366369 float & thresh, float & noise)
367370{
368371 // Find lower & upper values of the S-curve region
369372 short int lower, upper;
370373 bool flip = (this ->mScanType == ' I' );
371- if (!this ->findUpperLower (data, x, NPoints, lower, upper, flip) || lower == upper) {
374+ if (!this ->findUpperLower (data, NPoints, lower, upper, flip) || lower == upper) {
372375 if (this ->mVerboseOutput ) {
373376 LOG (warning) << " Start-finding unsuccessful: (lower, upper) = (" << lower << " , " << upper << " )" ;
374377 }
@@ -381,7 +384,7 @@ bool ITSThresholdCalibrator::findThresholdDerivative(const unsigned short int* d
381384
382385 // Fill array with derivatives
383386 for (int i = lower; i < upper; i++) {
384- deriv[i - lower] = std::abs (data[i + 1 ] - data[i]) / float (this ->mX [i + 1 ] - mX [i]);
387+ deriv[i - lower] = std::abs (data[i + 1 ] - data[i]) / (this ->mX [i + 1 ] - mX [i]);
385388 xfx += this ->mX [i] * deriv[i - lower];
386389 fx += deriv[i - lower];
387390 }
@@ -406,7 +409,7 @@ bool ITSThresholdCalibrator::findThresholdDerivative(const unsigned short int* d
406409// x is the array of charge injected values;
407410// NPoints is the length of both arrays.
408411bool ITSThresholdCalibrator::findThresholdHitcounting (
409- const unsigned short int * data, const short int * x, const short int & NPoints, float & thresh)
412+ const unsigned short int * data, const float * x, const short int & NPoints, float & thresh)
410413{
411414 unsigned short int numberOfHits = 0 ;
412415 bool is50 = false ;
@@ -496,22 +499,27 @@ void ITSThresholdCalibrator::saveThreshold()
496499 if (this ->mScanType != ' D' && this ->mScanType != ' A' ) {
497500 // Save info in a map for later averaging
498501 int sumT = 0 , sumSqT = 0 , sumN = 0 , sumSqN = 0 ;
499- int countSuccess = 0 ;
502+ int countSuccess = 0 , countUnsuccess = 0 ;
500503 for (int i = 0 ; i < this ->N_COL ; i++) {
501504 if (vSuccess[i]) {
502505 sumT += vThreshold[i];
503506 sumN += (int )vNoise[i];
504507 sumSqT += (vThreshold[i]) * (vThreshold[i]);
505508 sumSqN += ((int )vNoise[i]) * ((int )vNoise[i]);
506509 countSuccess++;
510+ if (vThreshold[i] >= mMin && vThreshold[i] <= mMax && (mScanType == ' I' || mScanType == ' V' )) {
511+ mpvCounter[vChipid[0 ]][vThreshold[i] - mMin ]++;
512+ }
513+ } else {
514+ countUnsuccess++;
507515 }
508516 }
509517 short int chipID = vChipid[0 ];
510- std::array<long int , 5 > dataSum{{sumT, sumSqT, sumN, sumSqN, countSuccess}};
518+ std::array<long int , 6 > dataSum{{sumT, sumSqT, sumN, sumSqN, countSuccess, countUnsuccess }};
511519 if (!(this ->mThresholds .count (chipID))) {
512520 this ->mThresholds [chipID] = dataSum;
513521 } else {
514- std::array<long int , 5 > dataAll{{this ->mThresholds [chipID][0 ] + dataSum[0 ], this ->mThresholds [chipID][1 ] + dataSum[1 ], this ->mThresholds [chipID][2 ] + dataSum[2 ], this ->mThresholds [chipID][3 ] + dataSum[3 ], this ->mThresholds [chipID][4 ] + dataSum[4 ]}};
522+ std::array<long int , 6 > dataAll{{this ->mThresholds [chipID][0 ] + dataSum[0 ], this ->mThresholds [chipID][1 ] + dataSum[1 ], this ->mThresholds [chipID][2 ] + dataSum[2 ], this ->mThresholds [chipID][3 ] + dataSum[3 ], this ->mThresholds [chipID][4 ] + dataSum[4 ], this -> mThresholds [chipID][ 5 ] + dataSum[ 5 ]}};
515523 this ->mThresholds [chipID] = dataAll;
516524 }
517525 }
@@ -679,22 +687,22 @@ void ITSThresholdCalibrator::setRunType(const short int& runtype)
679687 }
680688 }
681689
682- this ->mX = new short int [N_RANGE];
690+ this ->mX = new float [N_RANGE];
683691 for (short int i = this ->mMin ; i <= this ->mMax ; i++) {
684- this ->mX [i - this ->mMin ] = i ;
692+ this ->mX [i - this ->mMin ] = ( float )i + 0.5 ;
685693 }
686694
687695 // Initialize objects for doing the threshold fits
688696 if (this ->mFitType == FIT) {
689697 // Initialize the histogram used for error function fits
690698 // Will initialize the TF1 in setRunType (it is different for different runs)
691699 this ->mFitHist = new TH1F (
692- " mFitHist" , " mFitHist" , N_RANGE, this -> mX [0 ], this -> mX [N_RANGE - 1 ]);
700+ " mFitHist" , " mFitHist" , N_RANGE, mX [0 ] - 0.5 , mX [N_RANGE - 1 ] + 0.5 );
693701
694702 // Initialize correct fit function for the scan type
695703 this ->mFitFunction = (this ->mScanType == ' I' )
696704 ? new TF1 (" mFitFunction" , erf_ithr, 0 , 1500 , 2 )
697- : new TF1 (" mFitFunction" , erf, 0 , 1500 , 2 );
705+ : new TF1 (" mFitFunction" , erf, 3 , 1500 , 2 );
698706 this ->mFitFunction ->SetParName (0 , " Threshold" );
699707 this ->mFitFunction ->SetParName (1 , " Noise" );
700708 }
@@ -934,7 +942,7 @@ void ITSThresholdCalibrator::finaliseCCDB(o2::framework::ConcreteDataMatcher& ma
934942
935943// ////////////////////////////////////////////////////////////////////////////
936944// Calculate the average threshold given a vector of threshold objects
937- void ITSThresholdCalibrator::findAverage (const std::array<long int , 5 >& data, float & avgT, float & rmsT, float & avgN, float & rmsN)
945+ void ITSThresholdCalibrator::findAverage (const std::array<long int , 6 >& data, float & avgT, float & rmsT, float & avgN, float & rmsN)
938946{
939947 avgT = (!data[4 ]) ? 0 . : (float )data[0 ] / (float )data[4 ];
940948 rmsT = (!data[4 ]) ? 0 . : std::sqrt ((float )data[1 ] / (float )data[4 ] - avgT * avgT);
@@ -946,7 +954,7 @@ void ITSThresholdCalibrator::findAverage(const std::array<long int, 5>& data, fl
946954// ////////////////////////////////////////////////////////////////////////////
947955void ITSThresholdCalibrator::addDatabaseEntry (
948956 const short int & chipID, const char * name, const float & avgT,
949- const float & rmsT, const float & avgN, const float & rmsN, bool status, bool isQC)
957+ const float & rmsT, const float & avgN, const float & rmsN, const float & status, bool isQC)
950958{
951959 // Obtain specific chip information from the chip ID (layer, stave, ...)
952960 int lay, sta, ssta, mod, chipInMod; // layer, stave, sub stave, module, chip
@@ -1070,7 +1078,7 @@ void ITSThresholdCalibrator::addDatabaseEntry(
10701078 o2::dcs::addConfigItem (this ->mTuning , " ChipDbID" , std::to_string (confDBid));
10711079 o2::dcs::addConfigItem (this ->mTuning , name, (strcmp (name, " ITHR" ) == 0 || strcmp (name, " VCASN" ) == 0 ) ? std::to_string ((int )avgT) : std::to_string (avgT));
10721080 o2::dcs::addConfigItem (this ->mTuning , " Rms" , std::to_string (rmsT));
1073- o2::dcs::addConfigItem (this ->mTuning , " Status" , std::to_string (status)); // pass or fail
1081+ o2::dcs::addConfigItem (this ->mTuning , " Status" , std::to_string (status)); // percentage of unsuccess
10741082 }
10751083 if (this ->mScanType == ' T' ) {
10761084 o2::dcs::addConfigItem (this ->mTuning , " Noise" , std::to_string (avgN));
@@ -1122,10 +1130,15 @@ void ITSThresholdCalibrator::finalize(EndOfStreamContext* ec)
11221130 ++it;
11231131 continue ;
11241132 }
1125- float avgT, rmsT, avgN, rmsN;
1133+ float avgT, rmsT, avgN, rmsN, mpvT, outVal ;
11261134 this ->findAverage (it->second , avgT, rmsT, avgN, rmsN);
1127- bool status = (this ->mX [0 ] < avgT && avgT < this ->mX [N_RANGE - 1 ]);
1128- this ->addDatabaseEntry (it->first , name, avgT, rmsT, avgN, rmsN, status, false );
1135+ outVal = avgT;
1136+ if (isMpv) {
1137+ mpvT = std::distance (mpvCounter[it->first ].begin (), std::max_element (mpvCounter[it->first ].begin (), mpvCounter[it->first ].end ())) + mMin ;
1138+ outVal = mpvT;
1139+ }
1140+ float status = ((float )it->second [5 ] / (float )(it->second [4 ] + it->second [5 ])) * 100 .; // percentage of unsuccessful threshold extractions
1141+ this ->addDatabaseEntry (it->first , name, outVal, rmsT, avgN, rmsN, status, false );
11291142 if (!this ->mCheckEos ) {
11301143 this ->mRunTypeChip [it->first ] = 0 ; // so that this chip will never appear again in the DCSconfigObject_t
11311144 it = this ->mThresholds .erase (it);
@@ -1143,10 +1156,15 @@ void ITSThresholdCalibrator::finalize(EndOfStreamContext* ec)
11431156 ++it;
11441157 continue ;
11451158 }
1146- float avgT, rmsT, avgN, rmsN;
1159+ float avgT, rmsT, avgN, rmsN, mpvT, outVal ;
11471160 this ->findAverage (it->second , avgT, rmsT, avgN, rmsN);
1148- bool status = (this ->mX [0 ] < avgT && avgT < this ->mX [N_RANGE - 1 ]);
1149- this ->addDatabaseEntry (it->first , name, avgT, rmsT, avgN, rmsN, status, false );
1161+ outVal = avgT;
1162+ if (isMpv) {
1163+ mpvT = std::distance (mpvCounter[it->first ].begin (), std::max_element (mpvCounter[it->first ].begin (), mpvCounter[it->first ].end ())) + mMin ;
1164+ outVal = mpvT;
1165+ }
1166+ float status = ((float )it->second [5 ] / (float )(it->second [4 ] + it->second [5 ])) * 100 .; // percentage of unsuccessful threshold extractions
1167+ this ->addDatabaseEntry (it->first , name, outVal, rmsT, avgN, rmsN, status, false );
11501168 if (!this ->mCheckEos ) {
11511169 this ->mRunTypeChip [it->first ] = 0 ; // so that this chip will never appear again in the DCSconfigObject_t
11521170 it = this ->mThresholds .erase (it);
@@ -1166,7 +1184,7 @@ void ITSThresholdCalibrator::finalize(EndOfStreamContext* ec)
11661184 }
11671185 float avgT, rmsT, avgN, rmsN;
11681186 this ->findAverage (it->second , avgT, rmsT, avgN, rmsN);
1169- bool status = (this -> mX [ 0 ] < avgT && avgT < this -> mX [N_RANGE - 1 ] * 10 );
1187+ float status = (( float )it-> second [ 5 ] / ( float )(it-> second [ 4 ] + it-> second [ 5 ])) * 100 .; // percentage of unsuccessful threshold extractions
11701188 this ->addDatabaseEntry (it->first , name, avgT, rmsT, avgN, rmsN, status, false );
11711189 if (!this ->mCheckEos ) {
11721190 this ->mRunTypeChip [it->first ] = 0 ; // so that this chip will never appear again in the DCSconfigObject_t
@@ -1314,7 +1332,8 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf)
13141332 {" manual-min" , VariantType::Int, 0 , {" Min value of the variable used for the scan: use only in manual mode" }},
13151333 {" manual-max" , VariantType::Int, 50 , {" Max value of the variable used for the scan: use only in manual mode" }},
13161334 {" manual-scantype" , VariantType::String, " T" , {" scan type, can be D, T, I, V: use only in manual mode" }},
1317- {" save-tree" , VariantType::Bool, false , {" Flag to save ROOT tree on disk: use only in manual mode" }}}};
1335+ {" save-tree" , VariantType::Bool, false , {" Flag to save ROOT tree on disk: use only in manual mode" }},
1336+ {" enable-mpv" , VariantType::Bool, false , {" Flag to enable calculation of most-probable value in vcasn/ithr scans" }}}};
13181337}
13191338} // namespace its
13201339} // namespace o2
0 commit comments