39 LOG(info) <<
"Initializing digitizer";
40 mNumberOfChips = mGeometry->getNumberOfChips();
41 mChips.resize(mNumberOfChips);
42 for (
int i = mNumberOfChips;
i--;) {
43 mChips[
i].setChipIndex(
i);
45 mChips[
i].setNoiseMap(mNoiseMap);
48 mChips[
i].disable(mDeadChanMap->isFullChipMasked(
i));
49 mChips[
i].setDeadChanMap(mDeadChanMap);
54 mChipSimResp = mParams.getResponse();
55 mChipSimRespVD = mChipSimResp;
56 mChipSimRespMLOT = mChipSimResp;
60 LOG(info) <<
" Depth max VD: " << mChipSimRespVD->getDepthMax();
61 LOG(info) <<
" Depth min VD: " << mChipSimRespVD->getDepthMin();
63 LOG(info) <<
" Depth max MLOT: " << mChipSimRespMLOT->getDepthMax();
64 LOG(info) <<
" Depth min MLOT: " << mChipSimRespMLOT->getDepthMin();
66 float thicknessVD = 0.0095;
69 LOG(info) <<
"Using response name: " << mRespName;
70 mSimRespOrientation =
false;
72 if (mRespName ==
"APTS") {
75 mSimRespVDShift = mChipSimRespVD->getDepthMax();
78 mSimRespOrientation =
true;
79 }
else if (mRespName ==
"ALICE3") {
82 mSimRespVDShift = mChipSimRespVD->getDepthMax();
86 LOG(fatal) <<
"Unknown response name: " << mRespName;
89 mSimRespMLOTShift = mChipSimRespMLOT->getDepthMax() - thicknessMLOT / 2.f;
93 LOGP(info,
"VD shift = {} ; ML/OT shift = {} = {} - {}", mSimRespVDShift, mSimRespMLOTShift, mChipSimRespMLOT->getDepthMax(), thicknessMLOT / 2.f);
94 LOGP(info,
"VD pixel scale on x = {} ; z = {}", mSimRespVDScaleX, mSimRespVDScaleZ);
95 LOGP(info,
"ML/OT pixel scale on x = {} ; z = {}", mSimRespMLOTScaleX, mSimRespMLOTScaleZ);
96 LOGP(info,
"Response orientation: {}", mSimRespOrientation ?
"flipped" :
"normal");
104 if (mGeometry->getSubDetID(chipID) == 0) {
105 return mChipSimRespVD;
108 else if (mGeometry->getSubDetID(chipID) == 1 || mGeometry->getSubDetID(chipID) == 2) {
109 return mChipSimRespMLOT;
120 LOG(info) <<
" Digitizing " << mGeometry->getName() <<
" (ID: " << mGeometry->getDetID()
121 <<
") hits of event " << evID <<
" from source " << srcID
122 <<
" at time " << mEventTime.getTimeNS() <<
" ROFrame = " << mNewROFrame
123 <<
" Min/Max ROFrames " << mROFrameMin <<
"/" << mROFrameMax <<
" layer " <<
layer;
129 if (mNewROFrame > mROFrameMin) {
130 fillOutputContainer(mNewROFrame - 1,
layer);
133 int nHits = hits->size();
134 std::vector<int> hitIdx(nHits);
135 std::iota(std::begin(hitIdx), std::end(hitIdx), 0);
137 std::sort(hitIdx.begin(), hitIdx.end(),
138 [hits](
auto lhs,
auto rhs) {
139 return (*hits)[lhs].GetDetectorID() < (*hits)[rhs].GetDetectorID();
141 LOG(info) <<
"Processing " << nHits <<
" hits";
146 return getROFLayer((*hits)[idx].GetDetectorID()) ==
layer;
148 processHit((*hits)[
i], mROFrameMax, evID, srcID,
layer);
156 LOG(info) <<
"Setting event time to " << irt.
getTimeNS() <<
" ns after orbit 0 bc 0";
161 auto nbc = mEventTime.differenceInBC(mIRFirstSampledTF);
163 if (mCollisionTimeWrtROF < 0 && nbc > 0) {
167 mROFsWrtFirstRO = std::floor(
float(nbc) / mParams.getROFrameLengthInBC(
layer));
171 mNewROFrame = nbc / mParams.getROFrameLengthInBC(
layer);
174 LOG(
debug) <<
" NewROFrame " << mNewROFrame <<
" nbc " << nbc <<
" ROFsWrtFirstRO " << mROFsWrtFirstRO;
179 if (mNewROFrame < mROFrameMin) {
180 LOG(error) <<
"New ROFrame " << mNewROFrame <<
" (" << irt <<
") precedes currently cashed " << mROFrameMin;
181 throw std::runtime_error(
"deduced ROFrame precedes already processed one");
184 if (mROFrameMax < mNewROFrame) {
185 mROFrameMax = mNewROFrame - 1;
194 if (frameLast > mROFrameMax) {
195 frameLast = mROFrameMax;
198 getExtraDigBuffer(mROFrameMax);
199 LOG(info) <<
"Filling " << mGeometry->getName() <<
" digits output for RO frames " << mROFrameMin <<
":"
205 for (; mROFrameMin <= frameLast; mROFrameMin++) {
209 auto& extra = *(mExtraBuff.front().get());
210 for (
auto& chip : mChips) {
211 if (chip.isDisabled() || (
layer >= 0 && getROFLayer(chip.getChipIndex()) !=
layer)) {
214 chip.addNoise(mROFrameMin, mROFrameMin, &mParams, mGeometry->getSubDetID(chip.getChipIndex()), mGeometry->getLayer(chip.getChipIndex()));
215 auto&
buffer = chip.getPreDigits();
219 auto itBeg =
buffer.begin();
221 ULong64_t maxKey = chip.getOrderingKey(mROFrameMin + 1, 0, 0) - 1;
222 for (; iter !=
buffer.end(); ++iter) {
223 if (iter->first > maxKey) {
226 auto& preDig = iter->second;
227 if (preDig.charge >= mParams.getChargeThreshold()) {
228 int digID = mDigits->size();
229 mDigits->emplace_back(chip.getChipIndex(), preDig.row, preDig.col, preDig.charge);
230 LOG(
debug) <<
"Adding digit ID: " << digID <<
" with chipID: " << chip.getChipIndex() <<
", row: " << preDig.row <<
", col: " << preDig.col <<
", charge: " << preDig.charge;
231 mMCLabels->addElement(digID, preDig.labelRef.label);
232 auto& nextRef = preDig.labelRef;
233 while (nextRef.next >= 0) {
234 nextRef = extra[nextRef.next];
235 mMCLabels->addElement(digID, nextRef.label);
239 buffer.erase(itBeg, iter);
245 mROFRecords->push_back(rcROF);
249 mExtraBuff.emplace_back(mExtraBuff.front().release());
250 mExtraBuff.pop_front();
259 int subDetID = mGeometry->getSubDetID(chipID);
261 int layer = mGeometry->getLayer(chipID);
262 int disk = getDisk(chipID);
265 LOG(
debug) <<
"Skipping VD disk " << disk;
269 LOG(
debug) <<
"Processing hit for chip " << chipID;
270 auto& chip = mChips[chipID];
271 if (chip.isDisabled()) {
272 LOG(
debug) <<
"Skipping disabled chip " << chipID;
275 float timeInROF = hit.
GetTime() * sec2ns;
276 LOG(
debug) <<
"Hit time: " << timeInROF <<
" ns";
277 if (timeInROF > 20e3) {
278 const int maxWarn = 10;
279 static int warnNo = 0;
280 if (warnNo < maxWarn) {
281 LOG(warning) <<
"Ignoring hit with time_in_event = " << timeInROF <<
" ns"
282 << ((++warnNo < maxWarn) ?
"" :
" (suppressing further warnings)");
286 timeInROF += mCollisionTimeWrtROF;
287 if (mROFsWrtFirstRO < -1 || (mROFsWrtFirstRO == -1 && timeInROF < 0)) {
289 LOG(
debug) <<
"Ignoring hit with timeInROF = " << timeInROF;
297 float tTot = mParams.getSignalShape().getMaxDuration();
299 int roFrameRel =
int(timeInROF * mParams.getROFrameLengthInv(rofLayer));
301 uint32_t roFrameRelMax = (timeInROF + tTot) * mParams.getROFrameLengthInv(rofLayer);
302 int nFrames = roFrameRelMax + 1 - roFrameRel;
303 uint32_t roFrameMax = mNewROFrame + roFrameRelMax;
304 if (roFrameMax > maxFr) {
309 float nStepsInv = mParams.getNSimStepsInv();
310 int nSteps = mParams.getNSimSteps();
312 const auto& matrix = mGeometry->getMatrixL2G(hit.
GetDetectorID());
323 LOG(
debug) <<
"Called curved to flat: " << xyzLocS.x() <<
" -> " << xyFlatS.x() <<
", " << xyzLocS.y() <<
" -> " << xyFlatS.y();
325 xyzLocS.SetXYZ(xyFlatS.x(), xyFlatS.y(), xyzLocS.Z());
326 xyzLocE.SetXYZ(xyFlatE.x(), xyFlatE.y(), xyzLocE.Z());
344 LOG(
debug) <<
"Step into the sensitive volume: " <<
step <<
". Number of steps: " << nSteps;
345 int rowS = -1, colS = -1, rowE = -1, colE = -1, nSkip = 0;
350 if (++nSkip >= nSteps) {
351 LOG(
debug) <<
"Did not enter to sensitive matrix, " << nSkip <<
" >= " << nSteps;
359 if (++nSkip >= nSteps) {
360 LOG(
debug) <<
"Did not enter to sensitive matrix, " << nSkip <<
" >= " << nSteps;
371 std::swap(rowS, rowE);
374 std::swap(colS, colE);
392 int rowSpan = rowE - rowS + 1, colSpan = colE - colS + 1;
394 float respMatrix[rowSpan][colSpan];
395 std::fill(&respMatrix[0][0], &respMatrix[0][0] + rowSpan * colSpan, 0.f);
397 float nElectrons = hit.
GetEnergyLoss() * mParams.getEnergyToNElectrons();
398 nElectrons *= nStepsInv;
403 int rowPrev = -1, colPrev = -1,
row,
col;
404 float cRowPix = 0.f, cColPix = 0.f;
415 xyzLocS.SetY(xyzLocS.Y() + ((subDetID == 0) ? mSimRespVDShift : mSimRespMLOTShift));
419 for (
int iStep = nSteps; iStep--;) {
422 if (
row != rowPrev ||
col != colPrev) {
429 bool flipCol =
false, flipRow =
false;
431 float rowMax{}, colMax{};
436 rspmat = resp->
getResponse(mSimRespVDScaleX * (xyzLocS.X() - cRowPix), mSimRespVDScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
440 rspmat = resp->
getResponse(mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix), mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
445 if (rspmat ==
nullptr) {
446 LOG(
debug) <<
"Error in rspmat for step " << iStep <<
" / " << nSteps;
455 if (rowDest < 0 || rowDest >= rowSpan) {
460 if (colDest < 0 || colDest >= colSpan) {
463 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, mSimRespOrientation ? !flipRow : flipRow, flipCol);
467 LOG(info) <<
"Response done; adding labels; making digits";
470 auto roFrameAbs = mNewROFrame + roFrameRel;
471 LOG(
debug) <<
"\nSpanning through rows and columns; rowspan = " << rowSpan <<
" colspan = " << colSpan <<
" = " << colE <<
" - " << colS <<
" +1 ";
472 for (
int irow = rowSpan; irow--;) {
473 uint16_t rowIS = irow + rowS;
474 for (
int icol = colSpan; icol--;) {
475 float nEleResp = respMatrix[irow][icol];
476 if (nEleResp <= 1.e-36) {
479 LOG(
debug) <<
"nEleResp: value " << nEleResp <<
" for pixel " << irow <<
" " << icol;
480 int nEle = gRandom->Poisson(nElectrons * nEleResp);
481 LOG(
debug) <<
"Charge detected in the pixel: " << nEle <<
" for pixel " << irow <<
" " << icol;
483 if (nEle < mParams.getMinChargeToAccount()) {
484 LOG(
debug) <<
"Ignoring pixel with nEle = " << nEle <<
" < min charge to account "
485 << mParams.getMinChargeToAccount() <<
" for pixel " << irow <<
" " << icol;
489 uint16_t colIS = icol + colS;
490 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
493 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
496 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl, rofLayer);
509 LOG(
debug) <<
"Registering digits for chip " << chip.
getChipIndex() <<
" at ROFrame " << roFrame
510 <<
" row " <<
row <<
" col " <<
col <<
" nEle " << nEle <<
" label " << lbl;
511 float tStrobe = mParams.getStrobeDelay(
layer) - tInROF;
512 for (
int i = 0;
i < nROF;
i++) {
513 uint32_t roFr = roFrame +
i;
514 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength(
layer));
515 tStrobe += mParams.getROFrameLength(
layer);
518 if (nEleROF < mParams.getMinChargeToAccount()) {
521 if (roFr > mEventROFrameMax) {
522 mEventROFrameMax = roFr;
524 if (roFr < mEventROFrameMin) {
525 mEventROFrameMin = roFr;
531 LOG(
debug) <<
"Added digit with key: " <<
key <<
" ROF: " << roFr <<
" row: " <<
row <<
" col: " <<
col <<
" charge: " << nEleROF;
533 LOG(
debug) <<
"Added to pre-digit with key: " <<
key <<
" ROF: " << roFr <<
" row: " <<
row <<
" col: " <<
col <<
" charge: " << nEleROF;
538 ExtraDig* extra = getExtraDigBuffer(roFr);
542 if ((*extra)[nxt].
label == lbl) {
546 nxt = (*extra)[nxt].next;
553 extra->emplace_back(lbl);