38 if (
values.size() != cmKValues.size() ||
values.size() != pedestals.size()) {
39 LOGP(error,
"vector sizes of input values, cmKValues and pedestals don't match: {}, {}, {}",
values.size(), cmKValues.size(), pedestals.size());
43 std::vector<float> adcCM;
47 cmDebug->
nPadsOk.resize(mNPadsCompRamdom + 1);
51 for (
size_t iPad = 0; iPad <
values.size(); ++iPad) {
52 const float kCM = mLimitKFactor ? fixedSizeToFloat<6>(floatToFixedSize<8, 6>(cmKValues[iPad])) : cmKValues[iPad];
54 const float adcPadRaw =
values[iPad];
55 const float adcPad = adcPadRaw - pedestal;
56 const float adcPadNorm = (kCM > 0) ? adcPad / kCM : 0;
58 if (adcPadRaw > 1023.7) {
62 if (adcPad > mQEmpty) {
67 if ((mQCompScaleThreshold < 0) && (adcPadNorm < mQCompScaleThreshold)) {
68 qCompAdd = (mQCompScaleThreshold - adcPadNorm) * mQCompScale;
69 LOGP(info,
"Setting qCompAdd to {} for {}", qCompAdd, adcPadNorm);
74 for (
int iRnd = 0; iRnd < mNPadsCompRamdom; ++iRnd) {
78 }
while (padRnd == iPad);
79 const float kCMRnd = mLimitKFactor ? fixedSizeToFloat<6>(floatToFixedSize<8, 6>(cmKValues[padRnd])) : cmKValues[padRnd];
81 const float adcPadRnd =
values[padRnd] - pedestalRnd;
82 const float adcPadRndNorm = (kCMRnd > 0) ? adcPadRnd / kCMRnd : 0;
83 const float adcDist = std::abs(adcPadNorm - adcPadRndNorm);
85 const size_t distPos = std::min(cmDebug->
adcDist.size() - 1,
size_t(adcDist / 0.5));
88 if (adcDist < mQComp) {
97 if (nPadsOK >= mNPadsCompMin) {
98 adcCM.emplace_back(adcPadNorm);
102 const int entriesCM =
int(adcCM.size());
103 float commonMode = 0;
104 float commonModeStd = 0;
107 std::for_each(adcCM.begin(), adcCM.end(), [&commonMode, &commonModeStd](
const auto val) {
109 commonModeStd += val * val;
111 commonMode /= float(entriesCM);
112 commonModeStd = std::sqrt(std::abs(commonModeStd / entriesCM - commonMode * commonMode));
118 for (
size_t iPad = 0; iPad <
values.size(); ++iPad) {
119 const float kCM = mLimitKFactor ? fixedSizeToFloat<6>(floatToFixedSize<8, 6>(cmKValues[iPad])) : cmKValues[iPad];
121 const float adcPadRaw =
values[iPad];
122 const float adcPad = adcPadRaw - pedestal;
123 const float adcPadNorm = (kCM > 0) ? adcPad / kCM : 0;
124 const float adcPadCorr = adcPad - kCM * commonMode;
126 if (adcPadCorr > mSumPosThreshold) {
127 cmInfo.
sumPos += adcPadCorr;
129 cmInfo.
sumNeg += adcPadNorm;
133 if (mOccupancyThreshold > 0) {
134 if (adcPadCorr > mOccupancyThreshold) {
189int CommonModeCorrection::getCommonMode(std::vector<Digit>&
digits, std::vector<std::vector<CMInfo>>& cmValues,
bool negativeOnly,
bool hasInjectedCMValue, std::vector<std::vector<CMDebug>>* cmDebug,
int minTimeBin,
int maxTimeBin)
const
192 int maxTimeBinProcessed = -1;
194 int lastTimeBin = -1;
196 const auto& cmkValues = mPadMaps.at(
"CMkValues");
197 const auto& pedestals = mPadMaps.at(
"Pedestals");
199 bool doArtificialCM = std::abs(mArtificialCM) > 0;
202 float cmInjectedLower{};
203 float cmInjectedUpper{};
205 for (
size_t iDigit = 0; iDigit <
digits.size(); ++iDigit) {
206 auto& digit =
digits[iDigit];
207 const auto timeBin = digit.getTimeStamp();
208 if ((minTimeBin > -1) && (timeBin < minTimeBin)) {
211 if ((maxTimeBin > -1) && (timeBin > maxTimeBin)) {
214 if ((lastCRU > -1) && ((digit.getCRU() != lastCRU) || (digit.getTimeStamp() != lastTimeBin))) {
215 auto& cmValuesCRU = cmValues[lastCRU];
216 if (cmValuesCRU.size() <= lastTimeBin) {
217 cmValuesCRU.resize(lastTimeBin + 500);
219 (*cmDebug)[lastCRU].resize(lastTimeBin + 500);
222 if (mSubthreshold > 0) {
226 data.resize(nPadsCRU);
227 if (mSubthreshold == 2) {
229 data.adcValues[
i] = gRandom->Gaus();
234 cmValuesCRU[lastTimeBin] =
getCommonMode(
data.adcValues,
data.cmKValues,
data.pedestals, cmDebug ? &((*cmDebug)[lastCRU][lastTimeBin]) :
nullptr);
235 if (hasInjectedCMValue) {
242 const auto sector =
CRU(digit.getCRU()).
sector();
243 const auto cmkValue = cmkValues.getValue(sector, digit.getRow(), digit.getPad());
244 const auto pedestal = pedestals.getValue(sector, digit.getRow(), digit.getPad());
245 float charge = digit.getChargeFloat();
246 if (doArtificialCM) {
247 charge = std::clamp(
charge + mArtificialCM * cmkValue, 0.f, 1023.f);
249 lastCRU = digit.getCRU();
250 lastTimeBin = timeBin;
251 maxTimeBinProcessed = std::max(lastTimeBin, maxTimeBinProcessed);
253 bool isInjectedCMPad =
false;
254 if (hasInjectedCMValue) {
255 const auto posLow = mCMInjectIDLower[lastCRU % 10];
256 const auto posUpper = mCMInjectIDUpper[lastCRU % 10];
257 const auto row = digit.getRow();
258 const auto pad = digit.getPad();
259 if (
row == posLow.row) {
260 if (pad == posLow.pad) {
261 cmInjectedLower = digit.getChargeFloat();
262 isInjectedCMPad =
true;
266 if (
row == posUpper.row) {
267 if (pad == posUpper.pad) {
268 cmInjectedUpper = digit.getChargeFloat();
269 isInjectedCMPad =
true;
271 if (cmInjectedUpper == 0) {
272 LOGP(info,
"cm upper = 0 cru {}, row {}, pad {}", digit.getCRU(),
row, pad);
278 if (!isInjectedCMPad) {
280 data.cmKValues.emplace_back(cmkValue);
281 data.pedestals.emplace_back(pedestal);
285 auto& cmValuesCRU = cmValues[lastCRU];
286 if (cmValuesCRU.size() <= lastTimeBin) {
287 cmValuesCRU.resize(lastTimeBin + 500);
289 (*cmDebug)[lastCRU].resize(lastTimeBin + 500);
292 cmValuesCRU[lastTimeBin] =
getCommonMode(
data.adcValues,
data.cmKValues,
data.pedestals, cmDebug ? &((*cmDebug)[lastCRU][lastTimeBin]) :
nullptr);
295 if (hasInjectedCMValue) {
301 return maxTimeBinProcessed;
304int CommonModeCorrection::correctDigits(std::vector<Digit>&
digits, std::vector<std::vector<CMInfo>>& cmValues,
bool negativeOnly,
bool hasInjectedCMValue, std::vector<std::vector<CMDebug>>* cmDebug,
int minTimeBin,
int maxTimeBin)
const
306 const auto maxTimeBinProcessed =
getCommonMode(
digits, cmValues, negativeOnly, hasInjectedCMValue, cmDebug, minTimeBin, maxTimeBin);
307 const auto& cmkValues = mPadMaps.at(
"CMkValues");
308 const auto& pedestals = mPadMaps.at(
"Pedestals");
310 for (
auto& digit :
digits) {
311 const auto timeBin = digit.getTimeStamp();
312 if ((minTimeBin > -1) && (timeBin < minTimeBin)) {
315 if ((maxTimeBin > -1) && (timeBin > maxTimeBin)) {
318 const auto sector =
CRU(digit.getCRU()).
sector();
319 const auto cmKValue = cmkValues.getValue(sector, digit.getRow(), digit.getPad());
321 const auto cmValue = cmValues[digit.getCRU()][digit.getTimeStamp()].cmValue;
322 const auto cmNPads = cmValues[digit.getCRU()][digit.getTimeStamp()].nPadsUsed;
323 if ((!negativeOnly || cmValue < 0) && (cmNPads > mNPadsMinCM)) {
324 digit.setCharge(digit.getCharge() - cmValue * cmKValue);
325 if (mCorrectOutputForPedestal) {
326 const auto sector =
CRU(digit.getCRU()).
sector();
327 const auto pedestal = pedestals.getValue(sector, digit.getRow(), digit.getPad());
328 digit.setCharge(digit.getChargeFloat() - pedestal);
333 return maxTimeBinProcessed;
336void CommonModeCorrection::correctDigits(std::string_view digiFileIn, Long64_t maxEntries, std::string_view digitFileOut, std::string_view cmFileOut,
bool negativeOnly,
int nThreads,
bool writeOnlyCM,
bool writeDebug,
bool hasInjectedCMValue,
int minTimeBin,
int maxTimeBin)
338 ROOT::EnableThreadSafety();
341 Long64_t nEntries =
tree->GetEntries();
342 if (maxEntries > 0) {
343 nEntries = std::min(nEntries, maxEntries);
346 if (mPadMaps.find(
"Pedestals") == mPadMaps.end()) {
347 LOGP(info,
"Using empty pedestals");
348 mPadMaps[
"Pedestals"] =
CalPad(
"Pedestals");
351 std::unique_ptr<TFile> fOut;
352 std::unique_ptr<TTree> tOut;
354 fOut.reset(TFile::Open(digitFileOut.data(),
"RECREATE"));
355 fOut->SetCompressionLevel(5);
356 fOut->SetCompressionAlgorithm(5);
357 tOut = std::make_unique<TTree>(
"o2sim",
"o2sim");
360 std::array<std::vector<o2::tpc::Digit>*, 36> digitizedSignal;
361 std::array<TBranch*, 36> outBranches{};
362 for (
size_t iSec = 0; iSec < digitizedSignal.size(); ++iSec) {
363 digitizedSignal[iSec] =
nullptr;
364 tree->SetBranchAddress(Form(
"TPCDigit_%zu", iSec), &digitizedSignal[iSec]);
366 outBranches[iSec] = tOut->Branch(Form(
"TPCDigit_%zu", iSec), &digitizedSignal[iSec]);
371 pcstream.
GetFile()->SetCompressionAlgorithm(5);
372 pcstream.
GetFile()->SetCompressionLevel(5);
374 for (Long64_t iTF = 0; iTF < nEntries; ++iTF) {
376 LOGP(info,
"Processing entry {}/{}", iTF + 1, nEntries);
378 std::vector<std::vector<CMInfo>> cmValues;
379 std::vector<std::vector<CMDebug>> cmDebug;
385 int maxTimeBinSeen = -1;
387 auto worker = [&](
int iTread) {
389 for (
size_t iSector = iTread; iSector < 36; iSector += nThreads) {
390 LOGP(info,
"Processing entry {}/{}, starting sector {}", iTF + 1, nEntries, iSector);
391 auto digits = digitizedSignal[iSector];
392 int maxTimeBinSector = 0;
394 maxTimeBinSector =
correctDigits(*
digits, cmValues, negativeOnly, hasInjectedCMValue, writeDebug ? &cmDebug :
nullptr, minTimeBin, maxTimeBin);
397 static std::mutex maxMutex;
398 std::lock_guard lock{maxMutex};
399 maxTimeBinSeen = std::max(maxTimeBinSeen, maxTimeBinSector);
400 if (outBranches[iSector]) {
401 outBranches[iSector]->Fill();
402 LOGP(info,
"Filling branch for sector {}", iSector);
408 std::vector<std::thread> threads(nThreads);
410 for (
int i = 0;
i < threads.size();
i++) {
411 threads[
i] = std::thread(worker,
i);
415 for (
auto& th : threads) {
419 size_t maxTimeCRU = 0;
420 for (
int iCRU = 0; iCRU < cmValues.size(); ++iCRU) {
421 maxTimeCRU = std::max(maxTimeCRU, cmValues[iCRU].
size());
423 const int maxTBCRU = std::min(maxTimeBinSeen,
int(maxTimeCRU));
425 for (
int iTimeBin = 0; iTimeBin < maxTBCRU; ++iTimeBin) {
429 std::vector<float> sumPosStack(36 * 4);
430 std::vector<float> nPosStack(36 * 4);
431 std::vector<float> nSaturationStack(36 * 4);
433 std::vector<float> sumPosStackCRUCorr(
CRU::MaxCRU);
434 std::vector<float> nSaturationStackCRU(
CRU::MaxCRU);
436 for (
int iCRU = 0; iCRU < cmValues.size(); ++iCRU) {
437 if (cmValues[iCRU].
size() == 0) {
440 cm[iCRU] = cmValues[iCRU][iTimeBin];
442 cmD[iCRU] = cmDebug[iCRU][iTimeBin];
446 const auto index = stackID.getIndex();
447 sumPosStack[
index] += cm[iCRU].sumPos;
449 nSaturationStack[
index] += cm[iCRU].nSaturation;
452 for (
int iCRU = 0; iCRU < cmValues.size(); ++iCRU) {
453 if (cmValues[iCRU].
size() == 0) {
458 const auto index = stackID.getIndex();
459 sumPosStackCRU[iCRU] = sumPosStack[
index];
460 sumPosStackCRUCorr[iCRU] = sumPosStack[
index] - nPosStack[
index] * cm[iCRU].cmValue;
461 nSaturationStackCRU[iCRU] = nSaturationStack[
index];
466 <<
"iTimeBin=" << iTimeBin
468 <<
"sumPosStack=" << sumPosStackCRU
469 <<
"sumPosStackCorr=" << sumPosStackCRUCorr
470 <<
"nSaturationStack=" << nSaturationStackCRU;
474 <<
"cmDebug=" << cmD;
488 tOut->SetEntries(nEntries);
std::enable_if<!std::is_base_of< o2::conf::ConfigurableParam, T >::value, T * >::type retrieveFromTFileAny(std::string const &path, std::map< std::string, std::string > const &metadata, long timestamp=-1, std::map< std::string, std::string > *headers=nullptr, std::string const &etag="", const std::string &createdNotAfter="", const std::string &createdNotBefore="") const