101 o2::emcal::BadChannelMap calibrateBadChannels(
const boost::histogram::histogram<axes...>& hist,
const boost::histogram::histogram<axes...>& histTime = boost::histogram::make_histogram(boost::histogram::axis::variable<>{0., 1.}, boost::histogram::axis::variable<>{0., 1.}))
103 double time1 = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
104 std::map<int, std::pair<double, double>> slices = {{0, {0.1, 0.3}}, {1, {0.3, 0.5}}, {2, {0.5, 1.0}}, {3, {1.0, 4.0}}, {4, {4.0, 39.0}}};
106 std::fill(std::begin(mBadCellFracSM), std::end(mBadCellFracSM), 0);
107 for (
unsigned int i = 0;
i < mBadCellFracFEC.size(); ++
i) {
108 std::fill(std::begin(mBadCellFracFEC[
i]), std::end(mBadCellFracFEC[
i]), 0);
111 auto histScaled = hist;
112 if (mBCMScaleFactors) {
113 LOG(info) <<
"Rescaling BCM histo";
115 for (
int icell = 0; icell < 17644; icell++) {
116 for (
int ebin = 0; ebin < hist.axis(0).
size(); ebin++) {
117 double lowerE = hist.axis(0).bin(ebin).lower();
118 double upperE = hist.axis(0).bin(ebin).upper();
119 double midE = (lowerE + upperE) / 2.;
120 histScaled.at(ebin, icell) = hist.at(ebin, icell) / mBCMScaleFactors->
getScaleVal(icell, midE);
129 const bool doIncludeTime = (histTime.axis(0).size() > 1 &&
EMCALCalibParams::Instance().useTimeInfoForCalib_bc) ?
true : false;
130 BadChannelCalibTimeInfo calibrationTimeInfo;
138#if (defined(WITH_OPENMP) && !defined(__CLING__))
140 mNThreads = std::min(omp_get_max_threads(), mNcells);
142 LOG(info) <<
"Number of threads that will be used = " << mNThreads;
143#pragma omp parallel for num_threads(mNThreads)
145 LOG(info) <<
"OPEN MP will not be used for the bad channel calibration";
149 for (
int cellID = 0; cellID < mNcells; cellID++) {
150 LOG(
debug) <<
"analysing cell " << cellID;
151 if (calibrationInformation.energyPerHitMap[0][cellID] == 0) {
152 LOG(
debug) <<
"Cell " << cellID <<
" is dead.";
158 for (
auto& [sliceIndex, slice] : slices) {
159 auto ranges = calibrationInformation.goodCellWindowMap[sliceIndex];
160 auto rangesNHits = calibrationInformation.goodCellWindowNHitsMap[sliceIndex];
161 auto meanPerCell = calibrationInformation.energyPerHitMap[sliceIndex][cellID];
162 auto meanPerCellNHits = calibrationInformation.nHitsMap[sliceIndex][cellID];
163 LOG(
debug) <<
"Energy Per Hit: Mean per cell is " << meanPerCell <<
" Good Cell Window: [ " << ranges.first <<
" , " << ranges.second <<
" ]";
164 LOG(
debug) <<
"NHits: Mean per cell is " << meanPerCellNHits <<
" Good Cell Window: [ " << rangesNHits.first <<
" , " << rangesNHits.second <<
" ]";
167 double meanNHits = 0.5 * (rangesNHits.first + rangesNHits.second);
168 if (meanNHits <
EMCALCalibParams::Instance().minNHitsForNHitCut || (std::abs(ranges.first) < 0.001 && std::abs(ranges.second) < 0.001)) {
169 LOG(
debug) <<
"On average, only " << meanNHits <<
" found in energy interval [" << slice.first <<
" - " << slice.second <<
"]. Will do untight cut on upper limit";
171 LOG(
debug) <<
"********* FAILED for number of hits **********";
176 }
else if (meanPerCellNHits < rangesNHits.first || meanPerCellNHits > rangesNHits.second) {
177 LOG(
debug) <<
"********* FAILED for mean NHits **********";
183 if (meanNHits >
EMCALCalibParams::Instance().minNHitsForMeanEnergyCut && (meanPerCell < ranges.first || meanPerCell > ranges.second)) {
184 LOG(
debug) <<
"********* FAILED for mean energy **********";
191 if (!
failed && doIncludeTime) {
192 if (std::abs(calibrationTimeInfo.goodCellWindow) < 0.001) {
193 LOG(warning) <<
"Good cell window for time distribution is 0. Will skip the cut on time distribution";
195 LOG(
debug) <<
" calibrationTimeInfo.goodCellWindow " << calibrationTimeInfo.goodCellWindow <<
" calibrationTimeInfo.sigmaCell[cellID] " << calibrationTimeInfo.sigmaCell[cellID];
196 if (calibrationTimeInfo.sigmaCell[cellID] > calibrationTimeInfo.goodCellWindow) {
197 LOG(
debug) <<
"Cell " << cellID <<
" is flagged due to time distribution";
199 }
else if (calibrationTimeInfo.fracHitsPreTrigg[cellID] > calibrationTimeInfo.goodCellWindowFracHitsPreTrigg) {
200 LOG(
debug) <<
"Cell " << cellID <<
" is flagged due to time distribution (pre-trigger)";
202 }
else if (calibrationTimeInfo.fracHitsPostTrigg[cellID] > calibrationTimeInfo.goodCellWindowFracHitsPostTrigg) {
203 LOG(
debug) <<
"Cell " << cellID <<
" is flagged due to time distribution (post-trigger)";
210 LOG(
debug) <<
"Cell " << cellID <<
" is bad.";
215 LOG(
debug) <<
"Cell " << cellID <<
" is good.";
224 checkMaskSM(mOutputBCM);
228 checkMaskFEC(mOutputBCM);
231 double time2 = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
232 double diffTransfer = time2 - time1;
233 LOG(info) <<
"Total time" << diffTransfer <<
" ns";
248 BadChannelCalibInfo outputInfo;
249 std::map<slice_t, std::array<double, mNcells>> outputMapEnergyPerHit;
250 std::map<slice_t, std::array<double, mNcells>> outputMapNHits;
252 for (
const auto& [sliceIndex, sliceLimits] : sliceMap) {
253 std::array<double, mNcells> energyPerHit, nHits;
254 std::fill(energyPerHit.begin(), energyPerHit.end(), 0.);
255 std::fill(nHits.begin(), nHits.end(), 0.);
256 outputMapEnergyPerHit[sliceIndex] = energyPerHit;
257 outputMapNHits[sliceIndex] = nHits;
259#if (defined(WITH_OPENMP) && !defined(__CLING__))
261 mNThreads = std::min(omp_get_max_threads(), mNcells);
263 LOG(info) <<
"Number of threads that will be used = " << mNThreads;
264#pragma omp parallel for num_threads(mNThreads)
266 LOG(info) <<
"OPEN MP will not be used for the bad channel calibration";
269 for (
int cellID = 0; cellID < mNcells; cellID++) {
270 int binCellID = cellAmplitude.axis(1).index(cellID);
272 auto projectedSum = boost::histogram::algorithm::sum(projectedSlice);
273 if (projectedSum == 0) {
276 for (
const auto& [sliceIndex, slice] : sliceMap) {
277 double emin = slice.first;
278 double emax = slice.second;
279 int binXLowSlice = cellAmplitude.axis(0).index(emin);
280 int binXHighSlice = cellAmplitude.axis(0).index(emax);
283 double sumVal = boost::histogram::algorithm::sum(slicedHist);
286 outputMapEnergyPerHit[sliceIndex][cellID] = meanVal;
287 outputMapNHits[sliceIndex][cellID] = sumVal;
291 for (
const auto& [sliceIndex, slice] : sliceMap) {
292 Double_t meanPerSlice = 0.0;
293 Double_t sigmaPerSlice = 0.0;
294 TRobustEstimator robustEstimator;
295 auto& means = outputMapEnergyPerHit[sliceIndex];
296 robustEstimator.EvaluateUni(means.size(), means.data(), meanPerSlice, sigmaPerSlice, 0);
297 if (std::abs(meanPerSlice) < 0.001 && std::abs(sigmaPerSlice) < 0.001) {
298 robustEstimator.EvaluateUni(means.size(), means.data(), meanPerSlice, sigmaPerSlice, means.size() * 0.95);
301 Double_t meanPerSlice_NHits = 0.0;
302 Double_t sigmaPerSlice_NHits = 0.0;
303 TRobustEstimator robustEstimatorNHits;
304 auto& meansNHits = outputMapNHits[sliceIndex];
305 robustEstimatorNHits.EvaluateUni(meansNHits.size(), meansNHits.data(), meanPerSlice_NHits, sigmaPerSlice_NHits, 0);
306 if (std::abs(meanPerSlice_NHits) < 0.001 && std::abs(sigmaPerSlice_NHits) < 0.001) {
307 robustEstimator.EvaluateUni(meansNHits.size(), meansNHits.data(), meanPerSlice_NHits, sigmaPerSlice_NHits, meansNHits.size() * 0.95);
310 LOG(
debug) <<
"Energy Per hit: Mean per slice is: " << meanPerSlice <<
" Sigma Per Slice: " << sigmaPerSlice <<
" with size " << outputMapEnergyPerHit[sliceIndex].size();
311 LOG(
debug) <<
"NHits: Mean per slice is: " << meanPerSlice_NHits <<
" Sigma Per Slice: " << sigmaPerSlice_NHits <<
" with size " << outputMapNHits[sliceIndex].size();
313 double maxVal = meanPerSlice + mSigma * sigmaPerSlice;
314 double minVal = meanPerSlice - mSigma * sigmaPerSlice;
315 double maxValNHits = meanPerSlice_NHits + mSigma * sigmaPerSlice_NHits;
316 double minValNHits = meanPerSlice_NHits - mSigma * sigmaPerSlice_NHits;
318 outputInfo.goodCellWindowMap[sliceIndex] = {minVal, maxVal};
319 outputInfo.goodCellWindowNHitsMap[sliceIndex] = {minValNHits, maxValNHits};
322 outputInfo.energyPerHitMap = outputMapEnergyPerHit;
323 outputInfo.nHitsMap = outputMapNHits;
335 BadChannelCalibTimeInfo timeInfo;
336 for (
int i = 0;
i < mNcells; ++
i) {
338 const int indexLow = histCellTime.axis(1).index(
i);
339 const int indexHigh = histCellTime.axis(1).index(
i + 1);
342 int maxElementIndex = std::max_element(boostHistCellSlice.begin(), boostHistCellSlice.end()) - boostHistCellSlice.begin() - 1;
343 if (maxElementIndex < 0) {
346 float maxElementCenter = 0.5 * (boostHistCellSlice.axis(0).bin(maxElementIndex).upper() + boostHistCellSlice.axis(0).bin(maxElementIndex).lower());
355 timeInfo.fracHitsPreTrigg[
i] = sumTrigg == 0 ? 0. : sumPreTrigg / sumTrigg;
356 timeInfo.fracHitsPostTrigg[
i] = sumTrigg == 0 ? 0. : sumPostTrigg / sumTrigg;
361 double avMean = 0, avSigma = 0;
362 TRobustEstimator robustEstimator;
363 robustEstimator.EvaluateUni(timeInfo.sigmaCell.size(), timeInfo.sigmaCell.data(), avMean, avSigma, 0.5 * timeInfo.sigmaCell.size());
366 if (std::abs(avMean) < 0.001 && std::abs(avSigma) < 0.001) {
367 robustEstimator.EvaluateUni(timeInfo.sigmaCell.size(), timeInfo.sigmaCell.data(), avMean, avSigma, 0.95 * timeInfo.sigmaCell.size());
372 double avMeanPre = 0, avSigmaPre = 0;
373 robustEstimator.EvaluateUni(timeInfo.fracHitsPreTrigg.size(), timeInfo.fracHitsPreTrigg.data(), avMeanPre, avSigmaPre, 0.5 * timeInfo.fracHitsPreTrigg.size());
374 if (std::abs(avMeanPre) < 0.001 && std::abs(avSigmaPre) < 0.001) {
375 robustEstimator.EvaluateUni(timeInfo.fracHitsPreTrigg.size(), timeInfo.fracHitsPreTrigg.data(), avMeanPre, avSigmaPre, 0.95 * timeInfo.fracHitsPreTrigg.size());
379 double avMeanPost = 0, avSigmaPost = 0;
380 robustEstimator.EvaluateUni(timeInfo.fracHitsPostTrigg.size(), timeInfo.fracHitsPostTrigg.data(), avMeanPost, avSigmaPost, 0.5 * timeInfo.fracHitsPostTrigg.size());
381 if (std::abs(avMeanPost) < 0.001 && std::abs(avSigmaPost) < 0.001) {
382 robustEstimator.EvaluateUni(timeInfo.fracHitsPostTrigg.size(), timeInfo.fracHitsPostTrigg.data(), avMeanPost, avSigmaPost, 0.95 * timeInfo.fracHitsPostTrigg.size());
400 auto histReduced = boost::histogram::algorithm::reduce(hist, boost::histogram::algorithm::shrink(minTime, maxTime), boost::histogram::algorithm::shrink(0, mNcells));
417 for (
unsigned int i = 0;
i < mNcells; ++
i) {
419 const int indexLow = histReduced.axis(1).index(
i);
420 const int indexHigh = histReduced.axis(1).index(
i + 1);
423 LOG(
debug) <<
"calibrate cell time " <<
i <<
" of " << mNcells;
424 int maxElementIndex = std::max_element(boostHist1d.begin(), boostHist1d.end()) - boostHist1d.begin() - 1;
425 if (maxElementIndex < 0) {
428 float maxElementCenter = 0.5 * (boostHist1d.axis(0).bin(maxElementIndex).upper() + boostHist1d.axis(0).bin(maxElementIndex).lower());
430 if (restrictFitRangeToMax > 0) {
431 boostHist1d = boost::histogram::algorithm::reduce(boostHist1d, boost::histogram::algorithm::shrink(maxElementCenter - restrictFitRangeToMax, maxElementCenter + restrictFitRangeToMax));
435 auto fitValues = o2::utils::fitBoostHistoWithGaus<double>(boostHist1d);
437 mean = maxElementCenter;
439 mean = fitValues.at(1);
445 LOG(warning) << createErrorMessageFitGaus(err) <<
"; for cell " <<
i <<
" (Will take the parameter of the previous cell: " << mean <<
"ns)";