From 35536a32a4e475fbd725059b48eaa8c229e763f3 Mon Sep 17 00:00:00 2001 From: wiechula Date: Wed, 16 Oct 2024 09:15:33 +0200 Subject: [PATCH] Fix and extend CM --- .../include/TPCBase/CommonModeCorrection.h | 109 +++++++-- .../TPC/base/src/CommonModeCorrection.cxx | 209 +++++++++++++++--- Detectors/TPC/base/src/TPCBaseLinkDef.h | 2 + 3 files changed, 274 insertions(+), 46 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CommonModeCorrection.h b/Detectors/TPC/base/include/TPCBase/CommonModeCorrection.h index 286897fdf8312..cac1ba96c9992 100644 --- a/Detectors/TPC/base/include/TPCBase/CommonModeCorrection.h +++ b/Detectors/TPC/base/include/TPCBase/CommonModeCorrection.h @@ -38,6 +38,13 @@ class CommonModeCorrection std::vector cmKValues; std::vector pedestals; + void resize(size_t newSize) + { + adcValues.resize(newSize); + cmKValues.resize(newSize); + pedestals.resize(newSize); + } + void clear() { adcValues.clear(); @@ -50,6 +57,11 @@ class CommonModeCorrection float cmValue{}; float cmValueStd{}; int nPadsUsed{}; + float cmValueCRU{}; + float sumPos{}; + float sumNeg{}; + int nNeg{}; + int nSaturation{}; }; struct CMDebug { @@ -73,8 +85,12 @@ class CommonModeCorrection void setNPadsCompRandom(int n) { mNPadsCompRamdom = n; } int getNPadsCompRandom() const { return mNPadsCompRamdom; } - void setNPadsCompMin(int n) { mNPadsCompRamdom = n; } - int getNPadsCompMin() const { return mNPadsCompRamdom; } + void setNPadsCompMin(int n) { mNPadsCompMin = n; } + int getNPadsCompMin() const { return mNPadsCompMin; } + + /// Minimum number of pads required in the CM calculation to be used for digit correction + void setNPadsMinCM(int n) { mNPadsMinCM = n; } + int getNPadsMinCM() const { return mNPadsMinCM; } void setQEmpty(float q) { mQEmpty = q; } float getQEmpty() const { return mQEmpty; } @@ -90,6 +106,10 @@ class CommonModeCorrection void setQCompScale(float q) { mQCompScale = q; } float getQCompScale() const { return mQCompScale; } + /// Threshold above which a signal is considered for sumPos, if debug information is used + void setSumPosThreshold(float threshold) { mSumPosThreshold = threshold; } + float getSumPosThreshold() const { return mSumPosThreshold; } + /// Pad maps loaded from FEEConfig void setPadMaps(CalPadMapType& padMaps) { mPadMaps = padMaps; } @@ -108,18 +128,27 @@ class CommonModeCorrection /// Custom setting of CalPad, overwriting what was set in mPadMaps void setCalPad(const CalPad& calPad, std::string_view name) { mPadMaps[name.data()] = calPad; } + /// cmk value + float getCMkValue(int sector, int row, int pad) { return mPadMaps["CMkValues"].getValue(sector, row, pad); } + + /// pedestal value + float getPedestalValue(int sector, int row, int pad) { return mPadMaps["Pedestals"].getValue(sector, row, pad); } + /// load the Pad maps from CCDB - void loadDefaultPadMaps(FEEConfig::Tags feeTag = FEEConfig::Tags::Physics30sigma); + void + loadDefaultPadMaps(FEEConfig::Tags feeTag = FEEConfig::Tags::Physics30sigma); CMdata collectCMdata(const std::vector& digits, int cru, int timeBin); + int getCommonMode(std::vector& digits, std::vector>& cmValues, bool negativeOnly = false, bool hasInjectedCMValue = false, std::vector>* cmDebug = nullptr, int minTimeBin = -1, int maxTimeBin = -1) const; + /// corret digits for common mode /// \param cmValues will contain CM information for each CRU and time bin /// \param negativeOnly only correct negative common mode signals /// \return maximum - int correctDigits(std::vector& digits, std::vector>& cmValues, bool negativeOnly = false, std::vector>* cmDebug = nullptr, int minTimeBin = -1, int maxTimeBin = -1) const; + int correctDigits(std::vector& digits, std::vector>& cmValues, bool negativeOnly = false, bool hasInjectedCMValue = false, std::vector>* cmDebug = nullptr, int minTimeBin = -1, int maxTimeBin = -1) const; - void correctDigits(std::string_view digiFileIn, Long64_t maxEntries = -1, std::string_view digitFileOut = "tpcdigit_cmcorr.root", std::string_view cmFileOut = "CommonModeValues.root", bool negativeOnly = false, int nThreads = 1, bool writeOnlyCM = false, bool writeDebug = false, int minTimeBin = -1, int maxTimeBin = -1); + void correctDigits(std::string_view digiFileIn, Long64_t maxEntries = -1, std::string_view digitFileOut = "tpcdigit_cmcorr.root", std::string_view cmFileOut = "CommonModeValues.root", bool negativeOnly = false, int nThreads = 1, bool writeOnlyCM = false, bool writeDebug = false, bool hasInjectedCMValue = false, int minTimeBin = -1, int maxTimeBin = -1); void limitKFactorPrecision(bool limit = true) { mLimitKFactor = limit; } void limitPedestalPrecision(bool limit = true) { mLimitPedestal = limit; } @@ -134,20 +163,68 @@ class CommonModeCorrection /// add artificial common mode, only works when using the 'correctDigits' function void addCommonMode(float cm) { mArtificialCM = cm; } + void setCorrectOutputForPedestal(bool corret = true) { mCorrectOutputForPedestal = corret; } + bool getCorrectOutputForPedestal() const { return mCorrectOutputForPedestal; } + + /// Add zeros for pads without signal + void setAddZeros(bool addZeros) { mAddZeros = addZeros; } + bool getAddZeros() const { return mAddZeros; } + + static float decodeInjectedCMValue(float lower, float upper); + private: - inline static int sNThreads{1}; ///< Number of parallel threads for the CM calculation - int mNPadsCompRamdom{10}; ///< Number of random pads to compare with to check if the present pad is empty - int mNPadsCompMin{7}; ///< Minimum number of neighbouring pads with q close to present pad to define this as empty - float mQEmpty{2}; ///< Threshold to enter check for empty pad - float mQComp{1}; ///< Threshold for comparison with random pads - float mQCompScaleThreshold{0}; ///< Charge threshold from which on to increase mQComp - float mQCompScale{0}; ///< Slope with which to increase mQComp if below mQCompScaleThreshold - bool mLimitKFactor{false}; ///< Limit the k-factor precision to 2I6F - bool mLimitPedestal{false}; ///< Limit the preestal precision to 10I2F - float mArtificialCM{}; ///< artificial common mode signals + inline static int sNThreads{1}; ///< Number of parallel threads for the CM calculation + int mNPadsCompRamdom{10}; ///< Number of random pads to compare with to check if the present pad is empty + int mNPadsCompMin{7}; ///< Minimum number of neighbouring pads with q close to present pad to define this as empty + int mNPadsMinCM{0}; ///< Minimum number of pads required in the CM calculation to be used for digit correction + float mQEmpty{2}; ///< Threshold to enter check for empty pad + float mQComp{1}; ///< Threshold for comparison with random pads + float mQCompScaleThreshold{0}; ///< Charge threshold from which on to increase mQComp + float mQCompScale{0}; ///< Slope with which to increase mQComp if below mQCompScaleThreshold + float mSumPosThreshold{2}; ///< calculate sumPos > mSumPosThreshold, sumNeg M<= mSumPosThreshold + bool mLimitKFactor{false}; ///< Limit the k-factor precision to 2I6F + bool mLimitPedestal{false}; ///< Limit the preestal precision to 10I2F + bool mAddZeros{false}; ///< Add zeros for pads without signal + float mArtificialCM{}; ///< artificial common mode signals + bool mCorrectOutputForPedestal{false}; ///< correct the writte out ADC for the pedestal value CalPadMapType mPadMaps; ///< Pad-by-pad CRU configuration values (Pedestal, Noise, ITF + CM parameters) + struct pos { + int row; + int pad; + }; + + // positions of lower words per CRU in sector + const std::array mCMInjectIDLower{ + // row0 pad0 row1 pad1 + pos{0, 2}, + pos{20, 1}, + pos{32, 2}, + pos{51, 1}, + pos{63, 1}, + pos{84, 1}, + pos{97, 1}, + pos{116, 2}, + pos{127, 2}, + pos{142, 0}, + }; + + // positions of upper words per CRU in sector + const std::array mCMInjectIDUpper{ + // row0 pad0 row1 pad1 + pos{0, 3}, + pos{20, 3}, + pos{32, 3}, + pos{51, 3}, + pos{63, 2}, + pos{84, 4}, + pos{97, 2}, + pos{115, 5}, + pos{127, 3}, + pos{142, 4}, + }; + /// Return the value stored in mPadMaps["calibName"] /// \param calibName name of calibraion in mPadMaps /// \param cru CRU number @@ -156,7 +233,7 @@ class CommonModeCorrection bool padMapExists(const std::string& calibName); - ClassDefNV(CommonModeCorrection, 0); + ClassDefNV(CommonModeCorrection, 1); }; } // namespace o2::tpc diff --git a/Detectors/TPC/base/src/CommonModeCorrection.cxx b/Detectors/TPC/base/src/CommonModeCorrection.cxx index ffb039bc6e789..62e2bfcef25ab 100644 --- a/Detectors/TPC/base/src/CommonModeCorrection.cxx +++ b/Detectors/TPC/base/src/CommonModeCorrection.cxx @@ -22,6 +22,7 @@ #include "TPCBase/Utils.h" #include "TPCBase/CRUCalibHelpers.h" #include "TChain.h" +#include "TROOT.h" #include "TFile.h" #include "MathUtils/RandomRing.h" #include "CommonUtils/TreeStreamRedirector.h" @@ -50,8 +51,20 @@ CommonModeCorrection::CMInfo CommonModeCorrection::getCommonMode(gsl::span(floatToFixedSize<8, 6>(cmKValues[iPad])) : cmKValues[iPad]; const float pedestal = mLimitPedestal ? fixedSizeToFloat(floatToFixedSize(pedestals[iPad])) : pedestals[iPad]; - const float adcPad = values[iPad] - pedestal; - const float adcPadNorm = adcPad / kCM; + const float adcPadRaw = values[iPad]; + const float adcPad = adcPadRaw - pedestal; + const float adcPadNorm = (kCM > 0) ? adcPad / kCM : 0; + + if (adcPad > mSumPosThreshold) { + cmInfo.sumPos += adcPad; + } else { + cmInfo.sumNeg += adcPadNorm; + ++cmInfo.nNeg; + } + + if (adcPadRaw > 1023.7) { + ++cmInfo.nSaturation; + } if (adcPad > mQEmpty) { continue; @@ -73,7 +86,8 @@ CommonModeCorrection::CMInfo CommonModeCorrection::getCommonMode(gsl::span(floatToFixedSize<8, 6>(cmKValues[padRnd])) : cmKValues[padRnd]; const float pedestalRnd = mLimitPedestal ? fixedSizeToFloat(floatToFixedSize(pedestals[padRnd])) : pedestals[padRnd]; const float adcPadRnd = values[padRnd] - pedestalRnd; - const float adcDist = std::abs(adcPadNorm - adcPadRnd / kCMRnd); + const float adcPadRndNorm = (kCMRnd > 0) ? adcPadRnd / kCMRnd : 0; + const float adcDist = std::abs(adcPadNorm - adcPadRndNorm); if (cmDebug) { const size_t distPos = std::min(cmDebug->adcDist.size() - 1, size_t(adcDist / 0.5)); ++cmDebug->adcDist[distPos]; @@ -156,7 +170,7 @@ CommonModeCorrection::CMdata CommonModeCorrection::collectCMdata(const std::vect return data; } -int CommonModeCorrection::correctDigits(std::vector& digits, std::vector>& cmValues, bool negativeOnly, std::vector>* cmDebug, int minTimeBin, int maxTimeBin) const +int CommonModeCorrection::getCommonMode(std::vector& digits, std::vector>& cmValues, bool negativeOnly, bool hasInjectedCMValue, std::vector>* cmDebug, int minTimeBin, int maxTimeBin) const { // calculation common mode values int maxTimeBinProcessed = -1; @@ -168,6 +182,10 @@ int CommonModeCorrection::correctDigits(std::vector& digits, std::vector< bool doArtificialCM = std::abs(mArtificialCM) > 0; + // for decoding of the injected common mode signals + float cmInjectedLower{}; + float cmInjectedUpper{}; + for (size_t iDigit = 0; iDigit < digits.size(); ++iDigit) { auto& digit = digits[iDigit]; const auto timeBin = digit.getTimeStamp(); @@ -180,12 +198,21 @@ int CommonModeCorrection::correctDigits(std::vector& digits, std::vector< if ((lastCRU > -1) && ((digit.getCRU() != lastCRU) || (digit.getTimeStamp() != lastTimeBin))) { auto& cmValuesCRU = cmValues[lastCRU]; if (cmValuesCRU.size() <= lastTimeBin) { - cmValuesCRU.resize(cmValuesCRU.size() + 500); + cmValuesCRU.resize(lastTimeBin + 500); if (cmDebug) { - (*cmDebug)[lastCRU].resize((*cmDebug)[lastCRU].size() + 500); + (*cmDebug)[lastCRU].resize(lastTimeBin + 500); + } + } + if (mAddZeros) { + const size_t nPadsCRU = Mapper::PADSPERREGION[lastCRU % 10]; + if (data.adcValues.size() < nPadsCRU) { + data.resize(nPadsCRU); } } cmValuesCRU[lastTimeBin] = getCommonMode(data.adcValues, data.cmKValues, data.pedestals, cmDebug ? &((*cmDebug)[lastCRU][lastTimeBin]) : nullptr); + if (hasInjectedCMValue) { + cmValuesCRU[lastTimeBin].cmValueCRU = decodeInjectedCMValue(cmInjectedLower, cmInjectedUpper); + } // LOGP(info, "processing CRU {}, timeBin {}, CM = {}", lastCRU, lastTimeBin, cmValuesCRU[lastTimeBin].cmValue); data.clear(); @@ -204,21 +231,55 @@ int CommonModeCorrection::correctDigits(std::vector& digits, std::vector< lastCRU = digit.getCRU(); lastTimeBin = timeBin; maxTimeBinProcessed = std::max(lastTimeBin, maxTimeBinProcessed); + + if (hasInjectedCMValue) { + const auto posLow = mCMInjectIDLower[lastCRU % 10]; + const auto posUpper = mCMInjectIDUpper[lastCRU % 10]; + const auto row = digit.getRow(); + const auto pad = digit.getPad(); + if (row == posLow.row) { + if (pad == posLow.pad) { + cmInjectedLower = digit.getChargeFloat(); + // LOGP(info, "setting lower CM value cru {}, row {}, pad {}: {:012b}", digit.getCRU(), row, pad, floatToFixedSize(digit.getChargeFloat())); + } + } + if (row == posUpper.row) { + if (pad == posUpper.pad) { + cmInjectedUpper = digit.getChargeFloat(); + // LOGP(info, "setting upper CM value cru {}, row {}, pad {}: {:012b}", digit.getCRU(), row, pad, floatToFixedSize(digit.getChargeFloat())); + if (cmInjectedUpper == 0) { + LOGP(info, "cm upper = 0 cru {}, row {}, pad {}", digit.getCRU(), row, pad); + } + } + } + } } { auto& cmValuesCRU = cmValues[lastCRU]; if (cmValuesCRU.size() <= lastTimeBin) { - cmValuesCRU.resize(cmValuesCRU.size() + 500); + cmValuesCRU.resize(lastTimeBin + 500); if (cmDebug) { - (*cmDebug)[lastCRU].resize((*cmDebug)[lastCRU].size() + 500); + (*cmDebug)[lastCRU].resize(lastTimeBin + 500); } } cmValuesCRU[lastTimeBin] = getCommonMode(data.adcValues, data.cmKValues, data.pedestals, cmDebug ? &((*cmDebug)[lastCRU][lastTimeBin]) : nullptr); // LOGP(info, "processing CRU {}, timeBin {}, CM = {}", lastCRU, lastTimeBin, cmValuesCRU[lastTimeBin].cmValue); + + if (hasInjectedCMValue) { + cmValuesCRU[lastTimeBin].cmValueCRU = decodeInjectedCMValue(cmInjectedLower, cmInjectedUpper); + } + data.clear(); } + return maxTimeBinProcessed; +} - // apply correction +int CommonModeCorrection::correctDigits(std::vector& digits, std::vector>& cmValues, bool negativeOnly, bool hasInjectedCMValue, std::vector>* cmDebug, int minTimeBin, int maxTimeBin) const +{ + const auto maxTimeBinProcessed = getCommonMode(digits, cmValues, negativeOnly, hasInjectedCMValue, cmDebug, minTimeBin, maxTimeBin); + const auto& cmkValues = mPadMaps.at("CMkValues"); + const auto& pedestals = mPadMaps.at("Pedestals"); + // ===| apply correction |==== for (auto& digit : digits) { const auto timeBin = digit.getTimeStamp(); if ((minTimeBin > -1) && (timeBin < minTimeBin)) { @@ -231,16 +292,23 @@ int CommonModeCorrection::correctDigits(std::vector& digits, std::vector< const auto cmKValue = cmkValues.getValue(sector, digit.getRow(), digit.getPad()); // LOGP(info, "correcting value for CRU {}, time bin {}", digit.getCRU(), digit.getTimeStamp()); const auto cmValue = cmValues[digit.getCRU()][digit.getTimeStamp()].cmValue; - if (!negativeOnly || cmValue < 0) { + const auto cmNPads = cmValues[digit.getCRU()][digit.getTimeStamp()].nPadsUsed; + if ((!negativeOnly || cmValue < 0) && (cmNPads > mNPadsMinCM)) { digit.setCharge(digit.getCharge() - cmValue * cmKValue); + if (mCorrectOutputForPedestal) { + const auto sector = CRU(digit.getCRU()).sector(); + const auto pedestal = pedestals.getValue(sector, digit.getRow(), digit.getPad()); + digit.setCharge(digit.getChargeFloat() - pedestal); + } } } return maxTimeBinProcessed; } -void 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, int minTimeBin, int maxTimeBin) +void 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) { + ROOT::EnableThreadSafety(); TChain* tree = o2::tpc::utils::buildChain(fmt::format("ls {}", digiFileIn), "o2sim", "o2sim"); Long64_t nEntries = tree->GetEntries(); @@ -261,11 +329,12 @@ void CommonModeCorrection::correctDigits(std::string_view digiFileIn, Long64_t m } std::array*, 36> digitizedSignal; + std::array outBranches{}; for (size_t iSec = 0; iSec < digitizedSignal.size(); ++iSec) { digitizedSignal[iSec] = nullptr; tree->SetBranchAddress(Form("TPCDigit_%zu", iSec), &digitizedSignal[iSec]); if (tOut) { - tOut->Branch(Form("TPCDigit_%zu", iSec), &digitizedSignal[iSec]); + outBranches[iSec] = tOut->Branch(Form("TPCDigit_%zu", iSec), &digitizedSignal[iSec]); } } @@ -287,16 +356,22 @@ void CommonModeCorrection::correctDigits(std::string_view digiFileIn, Long64_t m auto worker = [&](int iTread) { // for (size_t iSector = 0; iSector < 36; ++iSector) { for (size_t iSector = iTread; iSector < 36; iSector += nThreads) { + LOGP(info, "Processing entry {}/{}, starting sector {}", iTF + 1, nEntries, iSector); auto digits = digitizedSignal[iSector]; - if (!digits || (digits->size() == 0)) { - continue; + int maxTimeBinSector = 0; + if (digits && (digits->size() > 0)) { + maxTimeBinSector = correctDigits(*digits, cmValues, negativeOnly, hasInjectedCMValue, writeDebug ? &cmDebug : nullptr, minTimeBin, maxTimeBin); } - const int maxTimeBinSector = correctDigits(*digits, cmValues, negativeOnly, writeDebug ? &cmDebug : nullptr, minTimeBin, maxTimeBin); { static std::mutex maxMutex; std::lock_guard lock{maxMutex}; maxTimeBin = std::max(maxTimeBin, maxTimeBinSector); + if (outBranches[iSector]) { + outBranches[iSector]->Fill(); + LOGP(info, "Filling branch for sector {}", iSector); + } } + LOGP(info, "Processing entry {}/{}, finishing sector {}", iTF + 1, nEntries, iSector); } }; @@ -311,32 +386,76 @@ void CommonModeCorrection::correctDigits(std::string_view digiFileIn, Long64_t m th.join(); } + size_t maxTimeCRU = 0; for (int iCRU = 0; iCRU < cmValues.size(); ++iCRU) { - int maxTBCRU = std::min(maxTimeBin, int(cmValues[iCRU].size())); - for (int iTimeBin = 0; iTimeBin < maxTBCRU; ++iTimeBin) { - pcstream << "cm" - << "iTF=" << iTF - << "iCRU=" << iCRU - << "iTimeBin=" << iTimeBin - << "cmInfo=" << cmValues[iCRU][iTimeBin]; + maxTimeCRU = std::max(maxTimeCRU, cmValues[iCRU].size()); + } + const int maxTBCRU = std::min(maxTimeBin, int(maxTimeCRU)); + + for (int iTimeBin = 0; iTimeBin < maxTBCRU; ++iTimeBin) { + + std::vector cm(CRU::MaxCRU); + std::vector cmD(CRU::MaxCRU); + std::vector sumPosStack(36 * 4); + std::vector nPosStack(36 * 4); + std::vector nSaturationStack(36 * 4); + std::vector sumPosStackCRU(CRU::MaxCRU); + std::vector sumPosStackCRUCorr(CRU::MaxCRU); + std::vector nSaturationStackCRU(CRU::MaxCRU); + + for (int iCRU = 0; iCRU < cmValues.size(); ++iCRU) { + if (cmValues[iCRU].size() == 0) { + continue; + } + cm[iCRU] = cmValues[iCRU][iTimeBin]; if (writeDebug) { - pcstream << "cm" - << "cmDebug=" << cmDebug[iCRU][iTimeBin]; + cmD[iCRU] = cmDebug[iCRU][iTimeBin]; + } + const CRU cru(iCRU); + const StackID stackID{cru.sector(), cru.gemStack()}; + const auto index = stackID.getIndex(); + sumPosStack[index] += cm[iCRU].sumPos; + nPosStack[index] += (Mapper::PADSPERREGION[cru.region()] - cm[iCRU].nNeg); + nSaturationStack[index] += cm[iCRU].nSaturation; + } + + for (int iCRU = 0; iCRU < cmValues.size(); ++iCRU) { + if (cmValues[iCRU].size() == 0) { + continue; } - // << "cm=" << cmValues[iCRU][iTimeBin].cmValue - // << "cmEntries=" << cmValues[iCRU][iTimeBin].nPadsUsed + const CRU cru(iCRU); + const StackID stackID{cru.sector(), cru.gemStack()}; + const auto index = stackID.getIndex(); + sumPosStackCRU[iCRU] = sumPosStack[index]; + sumPosStackCRUCorr[iCRU] = sumPosStack[index] - nPosStack[index] * cm[iCRU].cmValue; + nSaturationStackCRU[iCRU] = nSaturationStack[index]; + } + + pcstream << "cm" + << "iTF=" << iTF + << "iTimeBin=" << iTimeBin + << "cmInfo=" << cm + << "sumPosStack=" << sumPosStackCRU + << "sumPosStackCorr=" << sumPosStackCRUCorr + << "nSaturationStack=" << nSaturationStackCRU; + + if (writeDebug) { pcstream << "cm" - << "\n"; + << "cmDebug=" << cmD; } - } - if (tOut) { - tOut->Fill(); + pcstream << "cm" + << "\n"; } + + // if (tOut) { + // tOut->Fill(); + // } } pcstream.Close(); if (fOut && tOut) { + tOut->SetEntries(nEntries); fOut->cd(); tOut->Write(); tOut.reset(); @@ -344,6 +463,36 @@ void CommonModeCorrection::correctDigits(std::string_view digiFileIn, Long64_t m } } +float CommonModeCorrection::decodeInjectedCMValue(float lower, float upper) +{ + // CRU row0 pad0 row1 pad1 + // 0 0 2 0 3 + // 1 20 1 20 3 + // 2 32 2 32 3 + // 3 51 1 51 3 + // 4 62 1 62 2 + // 5 84 1 84 4 + // 6 97 1 97 2 + // 7 116 2 115 5 + // 8 127 2 127 3 + // 9 142 0 142 4 + // + // CM Value encoding: + // Kanal 0 : Bit 11 ... 8 = 0x8. Bit 7..0 CM-Werte Bits 7...0 + // Kanal 1 : Bit 11.. 9 = "100". Bit 8 = CM Positive, Bits 6..0 = CM-Wert Bits 14..8 + const int ilower = floatToFixedSize(lower); + const int iupper = floatToFixedSize(upper); + if (!(ilower & 0x800) || !(iupper & 0x800)) { + LOGP(error, "Not a CM word: lower: {:012b} upper: {:012b}", ilower, iupper); + return 0; + } + const int fixedSizeCM = ((iupper & 0x7F) << 8) + (ilower & 0xFF); + const float floatCM = fixedSizeToFloat<8>(fixedSizeCM); + + // bit 8 of upper word is the sign 1 = positive + return (iupper & 0x100) ? floatCM : -floatCM; +} + float CommonModeCorrection::getCalPadValue(const std::string calibName, int icru, int pad) const { if (mPadMaps.find(calibName) == mPadMaps.end()) { diff --git a/Detectors/TPC/base/src/TPCBaseLinkDef.h b/Detectors/TPC/base/src/TPCBaseLinkDef.h index 33a08c5a46b25..60924db3953e2 100644 --- a/Detectors/TPC/base/src/TPCBaseLinkDef.h +++ b/Detectors/TPC/base/src/TPCBaseLinkDef.h @@ -67,6 +67,8 @@ #pragma link C++ class o2::tpc::FEEConfig + ; #pragma link C++ class o2::tpc::CRUConfig + ; #pragma link C++ class o2::tpc::CommonModeCorrection + ; +#pragma link C++ class std::vector < o2::tpc::CommonModeCorrection::CMInfo> + ; +#pragma link C++ class std::vector < o2::tpc::CommonModeCorrection::CMDebug> + ; #pragma link C++ namespace o2::tpc::utils; #pragma link C++ function o2::tpc::utils::tokenize(const std::string_view, const std::string_view);