Skip to content

Commit 34ca379

Browse files
committed
Common mode calculation
1 parent fcc6aba commit 34ca379

File tree

4 files changed

+819
-0
lines changed

4 files changed

+819
-0
lines changed

Detectors/TPC/base/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ o2_add_library(TPCBase
3838
src/IonTailSettings.cxx
3939
src/FEEConfig.cxx
4040
src/DeadChannelMapCreator.cxx
41+
src/CommonModeCorrection.cxx
4142
PUBLIC_LINK_LIBRARIES Vc::Vc Boost::boost O2::DataFormatsTPC
4243
O2::DetectorsRaw O2::CCDB FairRoot::Base)
4344

@@ -70,6 +71,7 @@ o2_target_root_dictionary(TPCBase
7071
include/TPCBase/IonTailSettings.h
7172
include/TPCBase/FEEConfig.h
7273
include/TPCBase/DeadChannelMapCreator.h
74+
include/TPCBase/CommonModeCorrection.h
7375
include/TPCBase/CDBTypes.h)
7476
o2_add_test(Base
7577
COMPONENT_NAME tpc
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file CommonModeCorrection.h
13+
/// \brief Calculate the common mode correction factor
14+
/// \author Jens Wiechula, Jens.Wiechula@ikf.uni-frankfurt.de
15+
16+
#ifndef AliceO2_TPC_CommonModeCorrection_H_
17+
#define AliceO2_TPC_CommonModeCorrection_H_
18+
19+
#include <gsl/span>
20+
#include <string_view>
21+
#include <vector>
22+
23+
#include "DataFormatsTPC/Digit.h"
24+
#include "TPCBase/FEEConfig.h"
25+
26+
namespace o2::tpc
27+
{
28+
29+
/// Class to calculate the common mode correction
30+
///
31+
/// Calculation of the common mode correction, based on the algorithm propsed by Marian Ivanov
32+
/// The calculation is done for one single CRU and time bin
33+
class CommonModeCorrection
34+
{
35+
public:
36+
struct CMdata {
37+
std::vector<float> adcValues;
38+
std::vector<float> cmKValues;
39+
std::vector<float> pedestals;
40+
41+
void resize(size_t newSize)
42+
{
43+
adcValues.resize(newSize);
44+
cmKValues.resize(newSize);
45+
pedestals.resize(newSize);
46+
}
47+
48+
void clear()
49+
{
50+
adcValues.clear();
51+
cmKValues.clear();
52+
pedestals.clear();
53+
}
54+
};
55+
56+
struct CMInfo {
57+
float cmValue{}; ///< common mode value from pseudo code
58+
float cmValueStd{}; ///< std dev of common mode values from pseudo code
59+
float cmValueCRU{}; ///< common mode value from firmware, if available
60+
float sumPos{}; ///< sum of positive signals > mSumPosThreshold
61+
float sumNeg{}; ///< sum of negative signals <= mSumPosThreshold, corrected for k-factor
62+
uint16_t nPadsUsed{}; ///< number of pads used for CM calculation
63+
uint16_t nNeg{}; ///< number of pads used for sumNeg
64+
uint16_t nOccupancy{}; ///< number of CM corrected pads larger than mOccupancyThreshold
65+
uint16_t nSaturation{}; ///< number of pads in saturation
66+
};
67+
68+
struct CMDebug {
69+
std::vector<uint8_t> nPadsOk{};
70+
std::vector<uint16_t> adcDist{};
71+
};
72+
73+
using CalPadMapType = std::unordered_map<std::string, CalPad>;
74+
75+
/// Calculation of the common mode value
76+
///
77+
/// \param value pad-by-pad charge values
78+
/// \param cmKValues corresponding pad-by-pad common mode k-factors
79+
/// \param pedestals corresponding pad-by-pad pedestals
80+
/// \param
81+
CMInfo getCommonMode(gsl::span<const float> values, gsl::span<const float> cmKValues, gsl::span<const float> pedestals, CMDebug* cmDebug = nullptr) const;
82+
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)); }
83+
84+
CMInfo getCommonMode(const CMdata& cmData) const { return getCommonMode(std::span(cmData.adcValues), std::span(cmData.cmKValues), std::span(cmData.pedestals)); }
85+
86+
void setNPadsCompRandom(int n) { mNPadsCompRamdom = n; }
87+
int getNPadsCompRandom() const { return mNPadsCompRamdom; }
88+
89+
void setNPadsCompMin(int n) { mNPadsCompMin = n; }
90+
int getNPadsCompMin() const { return mNPadsCompMin; }
91+
92+
/// Minimum number of pads required in the CM calculation to be used for digit correction
93+
void setNPadsMinCM(int n) { mNPadsMinCM = n; }
94+
int getNPadsMinCM() const { return mNPadsMinCM; }
95+
96+
void setQEmpty(float q) { mQEmpty = q; }
97+
float getQEmpty() const { return mQEmpty; }
98+
99+
void setQComp(float q) { mQComp = q; }
100+
float getQComp() const { return mQComp; }
101+
102+
/// The mQComp will be set to (cm - mQCompScaleThreshold) * mQCompScale, if cm > mQCompScaleThreshold
103+
void setQCompScaleThreshold(float q) { mQCompScaleThreshold = q; }
104+
float getQCompScaleThreshold() const { return mQCompScaleThreshold; }
105+
106+
/// The mQComp will be set to (cm - mQCompScaleThreshold) * mQCompScale, if cm > mQCompScaleThreshold
107+
void setQCompScale(float q) { mQCompScale = q; }
108+
float getQCompScale() const { return mQCompScale; }
109+
110+
/// Threshold above which a signal is considered for sumPos, if debug information is used
111+
void setSumPosThreshold(float threshold) { mSumPosThreshold = threshold; }
112+
float getSumPosThreshold() const { return mSumPosThreshold; }
113+
114+
/// Threshold above which a signal is considered for the occupancy
115+
void setOccupancyThreshold(float threshold) { mOccupancyThreshold = threshold; }
116+
float getOccupancyThreshold() const { return mOccupancyThreshold; }
117+
118+
/// Pad maps loaded from FEEConfig
119+
void setPadMaps(CalPadMapType& padMaps) { mPadMaps = padMaps; }
120+
121+
/// load a CalPad from file and add it to the local mPadMaps
122+
/// \param fileName input file name
123+
/// \param nameInFile name of the CalPad object in the file
124+
/// \param namePadMap name under which to store the object in the mPadMaps, if empty use the same as nameInFile
125+
void loadCalPad(std::string_view fileName, std::string_view nameInFile, std::string_view namePadMap = "");
126+
127+
/// load CMkValues from file, assuming it is stored under the name "CMkValues
128+
void loadCMkValues(std::string_view fileName) { loadCalPad(fileName, "CMkValues"); }
129+
130+
/// load Pedestals from file, assuming it is stored under the name "Pedestals
131+
void loadPedestals(std::string_view fileName) { loadCalPad(fileName, "Pedestals"); }
132+
133+
/// Custom setting of CalPad, overwriting what was set in mPadMaps
134+
void setCalPad(const CalPad& calPad, std::string_view name) { mPadMaps[name.data()] = calPad; }
135+
136+
/// cmk value
137+
float getCMkValue(int sector, int row, int pad) { return mPadMaps["CMkValues"].getValue(sector, row, pad); }
138+
139+
/// pedestal value
140+
float getPedestalValue(int sector, int row, int pad) { return mPadMaps["Pedestals"].getValue(sector, row, pad); }
141+
142+
/// load the Pad maps from CCDB
143+
void
144+
loadDefaultPadMaps(FEEConfig::Tags feeTag = FEEConfig::Tags::Physics30sigma);
145+
146+
CMdata collectCMdata(const std::vector<Digit>& digits, int cru, int timeBin);
147+
148+
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;
149+
150+
/// corret digits for common mode
151+
/// \param cmValues will contain CM information for each CRU and time bin
152+
/// \param negativeOnly only correct negative common mode signals
153+
/// \return maximum
154+
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;
155+
156+
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);
157+
158+
void limitKFactorPrecision(bool limit = true) { mLimitKFactor = limit; }
159+
void limitPedestalPrecision(bool limit = true) { mLimitPedestal = limit; }
160+
161+
/// set the number of threads used for CM calculation
162+
/// \param nThreads number of threads
163+
static void setNThreads(const int nThreads) { sNThreads = nThreads; }
164+
165+
/// \return returns the number of threads used for decoding
166+
static int getNThreads() { return sNThreads; }
167+
168+
/// add artificial common mode, only works when using the 'correctDigits' function
169+
void addCommonMode(float cm) { mArtificialCM = cm; }
170+
171+
void setCorrectOutputForPedestal(bool corret = true) { mCorrectOutputForPedestal = corret; }
172+
bool getCorrectOutputForPedestal() const { return mCorrectOutputForPedestal; }
173+
174+
/// Add zeros for pads without signal
175+
void setAddSubthreshold(bool addSubthreshold) { mSubthreshold = addSubthreshold; }
176+
bool getAddSubthreshold() const { return mSubthreshold; }
177+
178+
static float decodeInjectedCMValue(float lower, float upper);
179+
180+
private:
181+
inline static int sNThreads{1}; ///< Number of parallel threads for the CM calculation
182+
int mNPadsCompRamdom{10}; ///< Number of random pads to compare with to check if the present pad is empty
183+
int mNPadsCompMin{7}; ///< Minimum number of neighbouring pads with q close to present pad to define this as empty
184+
int mNPadsMinCM{0}; ///< Minimum number of pads required in the CM calculation to be used for digit correction
185+
float mQEmpty{2}; ///< Threshold to enter check for empty pad
186+
float mQComp{1}; ///< Threshold for comparison with random pads
187+
float mQCompScaleThreshold{0}; ///< Charge threshold from which on to increase mQComp
188+
float mQCompScale{0}; ///< Slope with which to increase mQComp if below mQCompScaleThreshold
189+
float mSumPosThreshold{2}; ///< calculate sumPos > mSumPosThreshold, sumNeg M<= mSumPosThreshold
190+
float mOccupancyThreshold{3}; ///< calculate number of pads > mQCompScaleThreshold after CM correction
191+
bool mLimitKFactor{false}; ///< Limit the k-factor precision to 2I6F
192+
bool mLimitPedestal{false}; ///< Limit the preestal precision to 10I2F
193+
int mSubthreshold{0}; ///< Add data for pads without signal. 1 = add zeros; 2 = add random noise
194+
float mArtificialCM{}; ///< artificial common mode signals
195+
bool mCorrectOutputForPedestal{false}; ///< correct the writte out ADC for the pedestal value
196+
197+
CalPadMapType mPadMaps; ///< Pad-by-pad CRU configuration values (Pedestal, Noise, ITF + CM parameters)
198+
199+
struct pos {
200+
int row;
201+
int pad;
202+
};
203+
204+
// positions of lower words per CRU in sector
205+
const std::array<pos, 10> mCMInjectIDLower{
206+
// row0 pad0 row1 pad1
207+
pos{0, 2},
208+
pos{20, 1},
209+
pos{32, 2},
210+
pos{51, 1},
211+
pos{63, 1},
212+
pos{84, 1},
213+
pos{97, 1},
214+
pos{116, 2},
215+
pos{127, 2},
216+
pos{142, 0},
217+
};
218+
219+
// positions of upper words per CRU in sector
220+
const std::array<pos, 10> mCMInjectIDUpper{
221+
// row0 pad0 row1 pad1
222+
pos{0, 3},
223+
pos{20, 3},
224+
pos{32, 3},
225+
pos{51, 3},
226+
pos{63, 2},
227+
pos{84, 4},
228+
pos{97, 2},
229+
pos{115, 5},
230+
pos{127, 3},
231+
pos{142, 4},
232+
};
233+
234+
/// Return the value stored in mPadMaps["calibName"]
235+
/// \param calibName name of calibraion in mPadMaps
236+
/// \param cru CRU number
237+
/// \param pad Pad number within the CRU
238+
float getCalPadValue(const std::string calibName, int icru, int pad) const;
239+
240+
bool padMapExists(const std::string& calibName);
241+
242+
ClassDefNV(CommonModeCorrection, 2);
243+
};
244+
245+
} // namespace o2::tpc
246+
#endif

0 commit comments

Comments
 (0)