19#include <TGeoGlobalMagField.h>
25 auto bc =
static_cast<uint8_t
>(
time.bc % 4);
38 mSegmentation{mch::mapping::segmentation(deId)},
44 mNofNoisyPadsDist{
DigitizerParam::Instance().noiseOnlyProba * mSegmentation.nofPads()},
45 mPadIdDist{0, mSegmentation.nofPads() - 1},
48 mSignals(mSegmentation.nofPads())
59 auto chargeBending = chargeCorr *
charge;
60 auto chargeNonBending =
charge / chargeCorr;
70 auto hitlengthZ = lentrance.Z() - lexit.Z();
75 if (abs(hitlengthZ) > pitch * 1.99) {
76 lpos.SetXYZ((lexit.X() + lentrance.X()) / 2., (lexit.Y() + lentrance.Y()) / 2., (lexit.Z() + lentrance.Z()) / 2.);
78 lpos.SetXYZ(lexit.X(),
82 auto localX = mResponse.
getAnod(lpos.X());
83 auto localY = lpos.Y();
88 auto thetawire = atan((exitPoint.Y() - entrancePoint.Y()) / (entrancePoint.Z() - exitPoint.Z()));
91 double b[3] = {0., 0., 0.};
92 double x[3] = {entrancePoint.X(), entrancePoint.Y(), entrancePoint.Z()};
93 if (TGeoGlobalMagField::Instance()->GetField()) {
94 TGeoGlobalMagField::Instance()->Field(
x,
b);
96 LOG(fatal) <<
"no b field in MCH DEDigitizer";
101 auto betagamma = hit.
eTot() / 0.1056583745;
102 auto yAngleEffect = mResponse.
inclandbfield(thetawire, betagamma,
b[0]);
103 localY += yAngleEffect;
107 auto xMin = localX - dxy;
108 auto xMax = localX + dxy;
109 auto yMin = localY - dxy;
110 auto yMax = localY + dxy;
114 auto dx = mSegmentation.
padSizeX(padid) * 0.5;
115 auto dy = mSegmentation.
padSizeY(padid) * 0.5;
118 auto q = mResponse.
chargePadfraction(xPad - dx, xPad + dx, yPad - dy, yPad + dy);
120 q *= mSegmentation.isBendingPad(padid) ? chargeBending : chargeNonBending;
122 addSignal(padid, collisionTime, q, label);
130 if (mNofNoisyPadsDist.mean() > 0.) {
133 for (
auto ir = firstROF.first;
ir <= lastROF.first;
ir += 4) {
134 int nofNoisyPads = mNofNoisyPadsDist(mRandom);
135 for (
auto i = 0;
i < nofNoisyPads; ++
i) {
136 addNoise(mPadIdDist(mRandom),
ir);
142size_t DEDigitizer::digitize(std::map<InteractionRecord, DigitsAndLabels>& irDigitsAndLabels)
145 for (
int padid = 0; padid < mSignals.size(); ++padid) {
146 auto& signals = mSignals[padid];
149 if (mTimeDist.stddev() > 0.f) {
150 for (
auto& signal : signals) {
151 if (!signal.labels.front().isNoise()) {
152 addTimeDispersion(signal);
158 if (DigitizerParam::Instance().handlePileup) {
159 std::sort(signals.begin(), signals.end(), [](
const Signal&
s1,
const Signal& s2) {
160 return s1.rofIR < s2.rofIR || (s1.rofIR == s2.rofIR && s1.bcInROF < s2.bcInROF);
165 auto previousDigitBCStart = std::numeric_limits<int64_t>::min();
166 auto previousDigitBCEnd = std::numeric_limits<int64_t>::min();
167 float previousRawCharge = 0.f;
168 for (
auto& signal : signals) {
170 auto rawCharge = signal.charge;
171 auto nSamples = mResponse.nSamples(rawCharge);
175 if (!signal.labels.back().isNoise()) {
176 addNoise(signal, nSamples);
177 if (!isAboveThreshold(signal.charge)) {
184 auto digitBCStart = signal.rofIR.toLong();
185 auto digitBCEnd = digitBCStart + 4 * nSamples - 1;
186 if (DigitizerParam::Instance().handlePileup && digitBCStart <= previousDigitBCEnd + 8) {
187 rawCharge += previousRawCharge;
188 auto minNSamples = (std::max(previousDigitBCEnd, digitBCEnd) + 1 - previousDigitBCStart) / 4;
189 nSamples = std::max(
static_cast<uint32_t
>(minNSamples), mResponse.nSamples(rawCharge));
190 appendLastDigit(previousDigitsAndLabels, signal, nSamples);
191 previousDigitBCEnd = previousDigitBCStart + 4 * nSamples - 1;
192 previousRawCharge = rawCharge;
195 previousDigitsAndLabels = addNewDigit(irDigitsAndLabels, padid, signal, nSamples);
196 previousDigitBCStart = digitBCStart;
197 previousDigitBCEnd = digitBCEnd;
198 previousRawCharge = rawCharge;
206void DEDigitizer::clear()
208 for (
auto& signals : mSignals) {
219 auto& signals = mSignals[padid];
220 auto itSignal = std::find_if(signals.begin(), signals.end(),
221 [&rofTime](
const Signal& s) { return s.rofIR == rofTime.first; });
223 if (itSignal != signals.end()) {
225 itSignal->bcInROF = std::min(itSignal->bcInROF, rofTime.second);
226 itSignal->charge +=
charge;
227 itSignal->labels.push_back(
label);
230 signals.emplace_back(rofTime.first, rofTime.second,
charge,
label);
234void DEDigitizer::addNoise(
int padid,
const InteractionRecord& rofIR)
237 auto& signals = mSignals[padid];
238 auto itSignal = std::find_if(signals.begin(), signals.end(), [&rofIR](
const Signal& s) { return s.rofIR == rofIR; });
241 if (itSignal == signals.end()) {
242 auto bc =
static_cast<uint8_t>(mBCDist(mRandom));
243 auto charge = (mNoiseOnlyDist.stddev() > 0.f) ? mNoiseOnlyDist(mRandom) : mNoiseOnlyDist.mean();
245 signals.emplace_back(rofIR,
bc,
charge, MCCompLabel(
true));
250void DEDigitizer::addNoise(
Signal& signal, uint32_t nSamples)
252 if (mNoiseDist.stddev() > 0.f) {
253 signal.charge += mNoiseDist(mRandom) * std::sqrt(nSamples);
257void DEDigitizer::addTimeDispersion(
Signal& signal)
259 auto time = signal.rofIR.toLong() + signal.bcInROF + std::llround(mTimeDist(mRandom));
269bool DEDigitizer::isAboveThreshold(
float charge)
272 if (mMinChargeDist.stddev() > 0.f) {
273 return charge > mMinChargeDist(mRandom);
275 return charge > mMinChargeDist.mean();
280DEDigitizer::DigitsAndLabels* DEDigitizer::addNewDigit(std::map<InteractionRecord, DigitsAndLabels>& irDigitsAndLabels,
281 int padid,
const Signal& signal, uint32_t nSamples)
const
283 uint32_t
adc = std::round(signal.charge);
284 auto time = signal.rofIR.differenceInBC({0, mFirstTFOrbit});
285 nSamples = std::min(nSamples, 0x3FFU);
286 bool saturated =
false;
289 if (
adc > 0xFFFFFU) {
294 auto& digitsAndLabels = irDigitsAndLabels[signal.rofIR];
295 digitsAndLabels.first.emplace_back(mDeId, padid,
adc,
time, nSamples, saturated);
296 digitsAndLabels.second.addElements(digitsAndLabels.first.size() - 1, signal.labels);
298 return &digitsAndLabels;
301void DEDigitizer::appendLastDigit(DigitsAndLabels* digitsAndLabels,
const Signal& signal, uint32_t nSamples)
const
303 auto& lastDigit = digitsAndLabels->first.back();
304 uint32_t
adc = lastDigit.getADC() + std::round(signal.charge);
306 lastDigit.setADC(std::min(
adc, 0xFFFFFU));
307 lastDigit.setNofSamples(std::min(nSamples, 0x3FFU));
308 lastDigit.setSaturated(
adc > 0xFFFFFU);
309 digitsAndLabels->second.addElements(digitsAndLabels->first.size() - 1, signal.labels);
std::pair< o2::InteractionRecord, uint8_t > time2ROFtime(const o2::InteractionRecord &time)
Convert collision time to ROF time (ROF duration = 4 BC)
Definition of the MagF class.
DEDigitizer(int deId, math_utils::Transform3D transformation, std::mt19937 &random)
void processHit(const Hit &hit, const InteractionRecord &collisionTime, int evID, int srcID)
std::pair< std::vector< Digit >, dataformats::MCLabelContainer > DigitsAndLabels
math_utils::Point3D< float > exitPoint() const
math_utils::Point3D< float > entrancePoint() const
float getSigmaIntegration() const
float chargePadfraction(float xmin, float xmax, float ymin, float ymax) const
float inclandbfield(float thetawire, float betagamma, float bx) const
compute deteriation of y-resolution due to track inclination and B-field
float getAnod(float x) const
return wire coordinate closest to x
bool isAboveThreshold(float charge) const
float chargeCorr() const
return a randomized charge correlation between cathodes
float etocharge(float edepos) const
float getChargeSpread() const
double padPositionX(int dePadIndex) const
double padSizeY(int dePadIndex) const
double padPositionY(int dePadIndex) const
void forEachPadInArea(double xmin, double ymin, double xmax, double ymax, CALLABLE &&func) const
double padSizeX(int dePadIndex) const
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * label
uint8_t itsSharedClusterMap uint8_t
@ Signal
A message which is created every time a SIGUSR1 is received.
static InteractionRecord long2IR(int64_t l)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)