Skip to content

Commit

Permalink
Merge branch 'AliceO2Group:dev' into new-detector4
Browse files Browse the repository at this point in the history
  • Loading branch information
pkurash authored Dec 24, 2024
2 parents 2b8a26e + 89375b5 commit d79cf33
Show file tree
Hide file tree
Showing 15 changed files with 1,056 additions and 64 deletions.
2 changes: 2 additions & 0 deletions Detectors/TPC/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ o2_add_library(TPCBase
src/IonTailSettings.cxx
src/FEEConfig.cxx
src/DeadChannelMapCreator.cxx
src/CommonModeCorrection.cxx
PUBLIC_LINK_LIBRARIES Vc::Vc Boost::boost O2::DataFormatsTPC
O2::DetectorsRaw O2::CCDB FairRoot::Base)

Expand Down Expand Up @@ -70,6 +71,7 @@ o2_target_root_dictionary(TPCBase
include/TPCBase/IonTailSettings.h
include/TPCBase/FEEConfig.h
include/TPCBase/DeadChannelMapCreator.h
include/TPCBase/CommonModeCorrection.h
include/TPCBase/CDBTypes.h)
o2_add_test(Base
COMPONENT_NAME tpc
Expand Down
246 changes: 246 additions & 0 deletions Detectors/TPC/base/include/TPCBase/CommonModeCorrection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file CommonModeCorrection.h
/// \brief Calculate the common mode correction factor
/// \author Jens Wiechula, [email protected]

#ifndef AliceO2_TPC_CommonModeCorrection_H_
#define AliceO2_TPC_CommonModeCorrection_H_

#include <gsl/span>
#include <string_view>
#include <vector>

#include "DataFormatsTPC/Digit.h"
#include "TPCBase/FEEConfig.h"

namespace o2::tpc
{

/// Class to calculate the common mode correction
///
/// Calculation of the common mode correction, based on the algorithm propsed by Marian Ivanov
/// The calculation is done for one single CRU and time bin
class CommonModeCorrection
{
public:
struct CMdata {
std::vector<float> adcValues;
std::vector<float> cmKValues;
std::vector<float> pedestals;

void resize(size_t newSize)
{
adcValues.resize(newSize);
cmKValues.resize(newSize);
pedestals.resize(newSize);
}

void clear()
{
adcValues.clear();
cmKValues.clear();
pedestals.clear();
}
};

struct CMInfo {
float cmValue{}; ///< common mode value from pseudo code
float cmValueStd{}; ///< std dev of common mode values from pseudo code
float cmValueCRU{}; ///< common mode value from firmware, if available
float sumPos{}; ///< sum of positive signals > mSumPosThreshold
float sumNeg{}; ///< sum of negative signals <= mSumPosThreshold, corrected for k-factor
uint16_t nPadsUsed{}; ///< number of pads used for CM calculation
uint16_t nNeg{}; ///< number of pads used for sumNeg
uint16_t nOccupancy{}; ///< number of CM corrected pads larger than mOccupancyThreshold
uint16_t nSaturation{}; ///< number of pads in saturation
};

struct CMDebug {
std::vector<uint8_t> nPadsOk{};
std::vector<uint16_t> adcDist{};
};

using CalPadMapType = std::unordered_map<std::string, CalPad>;

/// Calculation of the common mode value
///
/// \param value pad-by-pad charge values
/// \param cmKValues corresponding pad-by-pad common mode k-factors
/// \param pedestals corresponding pad-by-pad pedestals
/// \param
CMInfo getCommonMode(gsl::span<const float> values, gsl::span<const float> cmKValues, gsl::span<const float> pedestals, CMDebug* cmDebug = nullptr) const;
CMInfo getCommonMode(const std::vector<float>& values, const std::vector<float>& cmKValues, const std::vector<float>& pedestals) const { return getCommonMode(gsl::span(values), gsl::span(cmKValues), gsl::span(pedestals)); }

CMInfo getCommonMode(const CMdata& cmData) const { return getCommonMode(std::span(cmData.adcValues), std::span(cmData.cmKValues), std::span(cmData.pedestals)); }

void setNPadsCompRandom(int n) { mNPadsCompRamdom = n; }
int getNPadsCompRandom() 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; }

void setQComp(float q) { mQComp = q; }
float getQComp() const { return mQComp; }

/// The mQComp will be set to (cm - mQCompScaleThreshold) * mQCompScale, if cm > mQCompScaleThreshold
void setQCompScaleThreshold(float q) { mQCompScaleThreshold = q; }
float getQCompScaleThreshold() const { return mQCompScaleThreshold; }

/// The mQComp will be set to (cm - mQCompScaleThreshold) * mQCompScale, if cm > mQCompScaleThreshold
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; }

/// Threshold above which a signal is considered for the occupancy
void setOccupancyThreshold(float threshold) { mOccupancyThreshold = threshold; }
float getOccupancyThreshold() const { return mOccupancyThreshold; }

/// Pad maps loaded from FEEConfig
void setPadMaps(CalPadMapType& padMaps) { mPadMaps = padMaps; }

/// load a CalPad from file and add it to the local mPadMaps
/// \param fileName input file name
/// \param nameInFile name of the CalPad object in the file
/// \param namePadMap name under which to store the object in the mPadMaps, if empty use the same as nameInFile
void loadCalPad(std::string_view fileName, std::string_view nameInFile, std::string_view namePadMap = "");

/// load CMkValues from file, assuming it is stored under the name "CMkValues
void loadCMkValues(std::string_view fileName) { loadCalPad(fileName, "CMkValues"); }

/// load Pedestals from file, assuming it is stored under the name "Pedestals
void loadPedestals(std::string_view fileName) { loadCalPad(fileName, "Pedestals"); }

/// 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);

CMdata collectCMdata(const std::vector<Digit>& digits, int cru, int timeBin);

int getCommonMode(std::vector<Digit>& digits, std::vector<std::vector<CMInfo>>& cmValues, bool negativeOnly = false, bool hasInjectedCMValue = false, std::vector<std::vector<CMDebug>>* 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<Digit>& digits, std::vector<std::vector<CMInfo>>& cmValues, bool negativeOnly = false, bool hasInjectedCMValue = false, std::vector<std::vector<CMDebug>>* 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, bool hasInjectedCMValue = false, int minTimeBin = -1, int maxTimeBin = -1);

void limitKFactorPrecision(bool limit = true) { mLimitKFactor = limit; }
void limitPedestalPrecision(bool limit = true) { mLimitPedestal = limit; }

/// set the number of threads used for CM calculation
/// \param nThreads number of threads
static void setNThreads(const int nThreads) { sNThreads = nThreads; }

/// \return returns the number of threads used for decoding
static int getNThreads() { return sNThreads; }

/// 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 setAddSubthreshold(bool addSubthreshold) { mSubthreshold = addSubthreshold; }
bool getAddSubthreshold() const { return mSubthreshold; }

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
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
float mOccupancyThreshold{3}; ///< calculate number of pads > mQCompScaleThreshold after CM correction
bool mLimitKFactor{false}; ///< Limit the k-factor precision to 2I6F
bool mLimitPedestal{false}; ///< Limit the preestal precision to 10I2F
int mSubthreshold{0}; ///< Add data for pads without signal. 1 = add zeros; 2 = add random noise
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<pos, 10> 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<pos, 10> 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
/// \param pad Pad number within the CRU
float getCalPadValue(const std::string calibName, int icru, int pad) const;

bool padMapExists(const std::string& calibName);

ClassDefNV(CommonModeCorrection, 2);
};

} // namespace o2::tpc
#endif
19 changes: 14 additions & 5 deletions Detectors/TPC/base/include/TPCBase/Mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,14 @@ class Mapper

bool isOutOfSector(GlobalPosition3D posEle, const Sector& sector, const float margin = 0.f) const;

static bool isEdgePad(int rowInSector, int padInRow);
static bool isFirstOrLastRowInStack(int rowInSector);
static bool isBelowSpacerCross(int rowInSector, int padInRow);
static bool isHighCouplingPad(int rowInSector, int padInRow)
{
return isEdgePad(rowInSector, padInRow) || isFirstOrLastRowInStack(rowInSector) || isBelowSpacerCross(rowInSector, padInRow);
}

static constexpr unsigned short getNumberOfIROCs() { return 36; }
static constexpr unsigned short getNumberOfOROCs() { return 36; }
static constexpr unsigned short getPadsInIROC() { return mPadsInIROC; }
Expand Down Expand Up @@ -523,6 +531,7 @@ class Mapper
static constexpr unsigned int GLOBALPADOFFSET[NREGIONS]{0, 1200, 2400, 3840, 5280, 6720, 8160, 9760, 11360, 12960}; ///< offset of number of pads for region
static constexpr unsigned int ROWSPERREGION[NREGIONS]{17, 15, 16, 15, 18, 16, 16, 14, 13, 12}; ///< number of pad rows for region
static constexpr unsigned int ROWOFFSET[NREGIONS]{0, 17, 32, 48, 63, 81, 97, 113, 127, 140}; ///< offset to calculate local row from global row
static constexpr unsigned int ROWOFFSETSTACK[4]{0, 63, 97, 127}; ///< offset to calculate local row from global row
static constexpr float REGIONAREA[NREGIONS]{374.4f, 378.f, 453.6f, 470.88f, 864.f, 864.f, 1167.36f, 1128.96f, 1449.6f, 1456.8f}; ///< volume of each region in cm^2
static constexpr float INVPADAREA[NREGIONS]{1 / 0.312f, 1 / 0.315f, 1 / 0.315f, 1 / 0.327f, 1 / 0.6f, 1 / 0.6f, 1 / 0.7296f, 1 / 0.7056f, 1 / 0.906f, 1 / 0.9105f}; ///< inverse size of the pad area padwidth*padLength
static constexpr unsigned REGION[PADROWS] = {
Expand All @@ -542,7 +551,7 @@ class Mapper
{0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4}, // region 7
{0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5}, // region 8
{0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5} // region 9
}; ///< additional pads per row compared to first row
}; ///< additional pads per row compared to first row
const inline static std::vector<unsigned int> OFFSETCRULOCAL[NREGIONS]{
{0, 66, 132, 198, 266, 334, 402, 472, 542, 612, 684, 756, 828, 902, 976, 1050, 1124}, // region 0
{0, 76, 152, 228, 306, 384, 462, 542, 622, 702, 784, 866, 948, 1032, 1116}, // region 1
Expand All @@ -554,7 +563,7 @@ class Mapper
{0, 110, 220, 332, 444, 556, 670, 784, 898, 1014, 1130, 1246, 1364, 1482}, // region 7
{0, 118, 236, 356, 476, 598, 720, 844, 968, 1092, 1218, 1344, 1472}, // region 8
{0, 128, 258, 388, 520, 652, 784, 918, 1052, 1188, 1324, 1462} // region 9
}; ///< row offset in cru for given local pad row
}; ///< row offset in cru for given local pad row
const inline static std::vector<unsigned int> PADSPERROW[NREGIONS]{
{66, 66, 66, 68, 68, 68, 70, 70, 70, 72, 72, 72, 74, 74, 74, 74, 76}, // region 0
{76, 76, 76, 78, 78, 78, 80, 80, 80, 82, 82, 82, 84, 84, 84}, // region 1
Expand All @@ -566,7 +575,7 @@ class Mapper
{110, 110, 112, 112, 112, 114, 114, 114, 116, 116, 116, 118, 118, 118}, // region 7
{118, 118, 120, 120, 122, 122, 124, 124, 124, 126, 126, 128, 128}, // region 8
{128, 130, 130, 132, 132, 132, 134, 134, 136, 136, 138, 138} // region 9
}; ///< number of pads per row in region
}; ///< number of pads per row in region
static constexpr unsigned int OFFSETCRUGLOBAL[PADROWS]{
0, 66, 132, 198, 266, 334, 402, 472, 542, 612, 684, 756, 828, 902, 976, 1050, 1124, // region 0
0, 76, 152, 228, 306, 384, 462, 542, 622, 702, 784, 866, 948, 1032, 1116, // region 1
Expand All @@ -578,7 +587,7 @@ class Mapper
0, 110, 220, 332, 444, 556, 670, 784, 898, 1014, 1130, 1246, 1364, 1482, // region 7
0, 118, 236, 356, 476, 598, 720, 844, 968, 1092, 1218, 1344, 1472, // region 8
0, 128, 258, 388, 520, 652, 784, 918, 1052, 1188, 1324, 1462 // region 9
}; ///< row offset in cru for given global pad row
}; ///< row offset in cru for given global pad row

static constexpr unsigned int LinksPerRegionPerEndpoint[NREGIONS][NENDPOINTS]{
{8, 7}, // region 0
Expand All @@ -591,7 +600,7 @@ class Mapper
{10, 10}, // region 7
{10, 10}, // region 8
{10, 10}, // region 9
}; ///< number of links per region per end point
}; ///< number of links per region per end point

private:
Mapper(const std::string& mappingDir);
Expand Down
Loading

0 comments on commit d79cf33

Please sign in to comment.