Project
Loading...
Searching...
No Matches
Digitizer.cxx
Go to the documentation of this file.
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
13
16#include "TRKBase/Specs.h"
19
20#include <TRandom.h>
21// #include <climits>
22#include <vector>
23#include <iostream>
24#include <numeric>
25#include <ranges>
26#include <fairlogger/Logger.h> // for LOG
27
29using o2::trkft3::Hit;
31
32using namespace o2::trkft3;
33using namespace o2::itsmft;
34// using namespace o2::base;
35//_______________________________________________________________________
36template <int DetID>
38{
39 LOG(info) << "Initializing digitizer";
40 mNumberOfChips = mGeometry->getNumberOfChips();
41 mChips.resize(mNumberOfChips);
42 for (int i = mNumberOfChips; i--;) {
43 mChips[i].setChipIndex(i);
44 if (mNoiseMap) {
45 mChips[i].setNoiseMap(mNoiseMap);
46 }
47 if (mDeadChanMap) {
48 mChips[i].disable(mDeadChanMap->isFullChipMasked(i));
49 mChips[i].setDeadChanMap(mDeadChanMap);
50 }
51 }
52
53 // setting the correct response function (for the moment, for both VD and MLOT the same response function is used)
54 mChipSimResp = mParams.getResponse();
55 mChipSimRespVD = mChipSimResp;
56 mChipSimRespMLOT = mChipSimResp;
57
59 // TODO: adjust Y shift when the geometry is improved
60 LOG(info) << " Depth max VD: " << mChipSimRespVD->getDepthMax();
61 LOG(info) << " Depth min VD: " << mChipSimRespVD->getDepthMin();
62
63 LOG(info) << " Depth max MLOT: " << mChipSimRespMLOT->getDepthMax();
64 LOG(info) << " Depth min MLOT: " << mChipSimRespMLOT->getDepthMin();
65
66 float thicknessVD = 0.0095; // cm --- hardcoded based on geometry currently present
67 float thicknessMLOT = o2::trk::SegmentationChip::SiliconThicknessMLOT; // 0.01 cm = 100 um --- based on geometry currently present
68
69 LOG(info) << "Using response name: " << mRespName;
70 mSimRespOrientation = false;
71
72 if (mRespName == "APTS") { // default
75 mSimRespVDShift = mChipSimRespVD->getDepthMax(); // the curved, rescaled, sensors have a width from 0 to -45. Must add ~10 um (= max depth) to match the APTS response.
78 mSimRespOrientation = true;
79 } else if (mRespName == "ALICE3") {
82 mSimRespVDShift = mChipSimRespVD->getDepthMax(); // the curved, rescaled, sensors have a width from 0 to -95 um. Must align the start of epi layer with the response function.
85 } else {
86 LOG(fatal) << "Unknown response name: " << mRespName;
87 }
88
89 mSimRespMLOTShift = mChipSimRespMLOT->getDepthMax() - thicknessMLOT / 2.f; // the shift should be done considering the rescaling done to adapt to the wrong silicon thickness. TODO: remove the scaling factor for the depth when the silicon thickness match the simulated response
90
91 LOGP(info, "{} Digitizer is initialised.", o2::detectors::DetID::getName(DetID));
92 mParams.print();
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");
97
99}
100
101template <int DetID>
103{
104 if (mGeometry->getSubDetID(chipID) == 0) {
105 return mChipSimRespVD;
106 }
107
108 else if (mGeometry->getSubDetID(chipID) == 1 || mGeometry->getSubDetID(chipID) == 2) {
109 return mChipSimRespMLOT;
110 }
111 return nullptr;
112};
113
114//_______________________________________________________________________
115template <int DetID>
116void Digitizer<DetID>::process(const std::vector<Hit>* hits, int evID, int srcID, int layer)
117{
118 // digitize single event, the time must have been set beforehand
119
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;
124
125 // std::cout << "Printing segmentation info: " << std::endl;
126 // SegmentationChip::Print();
127
128 // is there something to flush ?
129 if (mNewROFrame > mROFrameMin) {
130 fillOutputContainer(mNewROFrame - 1, layer); // flush out all frames preceding the new one
131 }
132
133 int nHits = hits->size();
134 std::vector<int> hitIdx(nHits);
135 std::iota(std::begin(hitIdx), std::end(hitIdx), 0);
136 // sort hits to improve memory access
137 std::sort(hitIdx.begin(), hitIdx.end(),
138 [hits](auto lhs, auto rhs) {
139 return (*hits)[lhs].GetDetectorID() < (*hits)[rhs].GetDetectorID();
140 });
141 LOG(info) << "Processing " << nHits << " hits";
142 for (int i : hitIdx | std::views::filter([&](int idx) {
143 if (layer < 0) {
144 return true;
145 }
146 return getROFLayer((*hits)[idx].GetDetectorID()) == layer;
147 })) {
148 processHit((*hits)[i], mROFrameMax, evID, srcID, layer);
149 }
150}
151
152//_______________________________________________________________________
153template <int DetID>
155{
156 LOG(info) << "Setting event time to " << irt.getTimeNS() << " ns after orbit 0 bc 0";
157 // assign event time in ns
158 mEventTime = irt;
159 // RO frame corresponding to provided time
160 mCollisionTimeWrtROF = mEventTime.timeInBCNS; // in triggered mode the ROF starts at BC (is there a delay?)
161 auto nbc = mEventTime.differenceInBC(mIRFirstSampledTF);
162
163 if (mCollisionTimeWrtROF < 0 && nbc > 0) {
164 nbc--;
165 }
166
167 mROFsWrtFirstRO = std::floor(float(nbc) / mParams.getROFrameLengthInBC(layer));
168 if (nbc < 0) {
169 mNewROFrame = 0;
170 } else {
171 mNewROFrame = nbc / mParams.getROFrameLengthInBC(layer);
172 }
173
174 LOG(debug) << " NewROFrame " << mNewROFrame << " nbc " << nbc << " ROFsWrtFirstRO " << mROFsWrtFirstRO;
175
176 // in continuous mode depends on starts of periodic readout frame
177 mCollisionTimeWrtROF += (nbc % mParams.getROFrameLengthInBC(layer)) * o2::constants::lhc::LHCBunchSpacingNS;
178
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");
182 }
183
184 if (mROFrameMax < mNewROFrame) {
185 mROFrameMax = mNewROFrame - 1; // all frames up to this are finished
186 }
187}
188
189//_______________________________________________________________________
190template <int DetID>
191void Digitizer<DetID>::fillOutputContainer(uint32_t frameLast, int layer)
192{
193 // // fill output with digits from min.cached up to requested frame, generating the noise beforehand
194 if (frameLast > mROFrameMax) {
195 frameLast = mROFrameMax;
196 }
197 // // make sure all buffers for extra digits are created up to the maxFrame
198 getExtraDigBuffer(mROFrameMax);
199 LOG(info) << "Filling " << mGeometry->getName() << " digits output for RO frames " << mROFrameMin << ":"
200 << frameLast;
201
203
204 // we have to write chips in RO increasing order, therefore have to loop over the frames here
205 for (; mROFrameMin <= frameLast; mROFrameMin++) {
206 rcROF.setROFrame(mROFrameMin);
207 rcROF.setFirstEntry(mDigits->size()); // start of current ROF in digits
208
209 auto& extra = *(mExtraBuff.front().get());
210 for (auto& chip : mChips) {
211 if (chip.isDisabled() || (layer >= 0 && getROFLayer(chip.getChipIndex()) != layer)) {
212 continue;
213 }
214 chip.addNoise(mROFrameMin, mROFrameMin, &mParams, mGeometry->getSubDetID(chip.getChipIndex()), mGeometry->getLayer(chip.getChipIndex()));
215 auto& buffer = chip.getPreDigits();
216 if (buffer.empty()) {
217 continue;
218 }
219 auto itBeg = buffer.begin();
220 auto iter = itBeg;
221 ULong64_t maxKey = chip.getOrderingKey(mROFrameMin + 1, 0, 0) - 1; // fetch digits with key below that
222 for (; iter != buffer.end(); ++iter) {
223 if (iter->first > maxKey) {
224 break; // is the digit ROFrame from the key > the max requested frame
225 }
226 auto& preDig = iter->second; // preDigit
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; // extra contributors are in extra array
233 while (nextRef.next >= 0) {
234 nextRef = extra[nextRef.next];
235 mMCLabels->addElement(digID, nextRef.label);
236 }
237 }
238 }
239 buffer.erase(itBeg, iter);
240 }
241 // finalize ROF record
242 rcROF.setNEntries(mDigits->size() - rcROF.getFirstEntry()); // number of digits
243 rcROF.getBCData().setFromLong(mIRFirstSampledTF.toLong() + mROFrameMin * mParams.getROFrameLengthInBC(layer));
244 if (mROFRecords) {
245 mROFRecords->push_back(rcROF);
246 }
247 extra.clear(); // clear container for extra digits of the mROFrameMin ROFrame
248 // and move it as a new slot in the end
249 mExtraBuff.emplace_back(mExtraBuff.front().release());
250 mExtraBuff.pop_front();
251 }
252}
253
254//_______________________________________________________________________
255template <int DetID>
256void Digitizer<DetID>::processHit(const o2::trkft3::Hit& hit, uint32_t& maxFr, int evID, int srcID, int rofLayer)
257{
258 int chipID = hit.GetDetectorID();
259 int subDetID = mGeometry->getSubDetID(chipID);
260
261 int layer = mGeometry->getLayer(chipID); // local layer nr for response
262 int disk = getDisk(chipID);
263
264 if (disk != -1) {
265 LOG(debug) << "Skipping VD disk " << disk;
266 return; // skipping hits on disks for the moment
267 }
268
269 LOG(debug) << "Processing hit for chip " << chipID;
270 auto& chip = mChips[chipID];
271 if (chip.isDisabled()) {
272 LOG(debug) << "Skipping disabled chip " << chipID;
273 return;
274 }
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)");
283 }
284 return;
285 }
286 timeInROF += mCollisionTimeWrtROF;
287 if (mROFsWrtFirstRO < -1 || (mROFsWrtFirstRO == -1 && timeInROF < 0)) {
288 // disregard this hit because it comes from an event byefore readout starts and it does not effect this RO
289 LOG(debug) << "Ignoring hit with timeInROF = " << timeInROF;
290 return;
291 }
292
293 // calculate RO Frame for this hit
294 if (timeInROF < 0) {
295 timeInROF = 0.;
296 }
297 float tTot = mParams.getSignalShape().getMaxDuration();
298 // frame of the hit signal start wrt event ROFrame
299 int roFrameRel = int(timeInROF * mParams.getROFrameLengthInv(rofLayer));
300 // frame of the hit signal end wrt event ROFrame: in the triggered mode we read just 1 frame
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) {
305 maxFr = roFrameMax; // if signal extends beyond current maxFrame, increase the latter
306 }
307
308 // here we start stepping in the depth of the sensor to generate charge diffusion
309 float nStepsInv = mParams.getNSimStepsInv();
310 int nSteps = mParams.getNSimSteps();
311
312 const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID());
313 // matrix.print();
314
316 math_utils::Vector3D<float> xyzLocS(matrix ^ (hit.GetPosStart())); // start position in sensor frame
317 math_utils::Vector3D<float> xyzLocE(matrix ^ (hit.GetPos())); // end position in sensor frame
318
319 if (subDetID == 0) { // VD - need to take into account for the curved layers. TODO: consider the disks
320 // transform the point on the curved surface to a flat one
321 math_utils::Vector2D<float> xyFlatS = Segmentation::curvedToFlat(layer, xyzLocS.x(), xyzLocS.y());
322 math_utils::Vector2D<float> xyFlatE = Segmentation::curvedToFlat(layer, xyzLocE.x(), xyzLocE.y());
323 LOG(debug) << "Called curved to flat: " << xyzLocS.x() << " -> " << xyFlatS.x() << ", " << xyzLocS.y() << " -> " << xyFlatS.y();
324 // update the local coordinates with the flattened ones
325 xyzLocS.SetXYZ(xyFlatS.x(), xyFlatS.y(), xyzLocS.Z());
326 xyzLocE.SetXYZ(xyFlatE.x(), xyFlatE.y(), xyzLocE.Z());
327 }
328
329 // std::cout<<"Printing example of point in 0.35 0.35 0 in global frame: "<<std::endl;
330 // math_utils::Point3D<float> examplehitGlob(0.35, 0.35, 0);
331 // math_utils::Vector3D<float> exampleLoc(matrix ^ (examplehitGlob)); // start position in sensor frame
332 // std::cout<< "Example hit in local frame: " << exampleLoc << std::endl;
333 // std::cout<<"Going back to glob coordinates: " << (matrix * exampleLoc) << std::endl;
334
336 step -= xyzLocS;
337 step *= nStepsInv; // position increment at each step
338 // the electrons will injected in the middle of each step
339 // starting from the middle of the first step
340 math_utils::Vector3D<float> stepH(step * 0.5);
341 xyzLocS += stepH;
342 xyzLocE -= stepH;
343
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;
346
348 // get entrance pixel row and col
349 while (!Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), rowS, colS, subDetID, layer, disk)) { // guard-ring ?
350 if (++nSkip >= nSteps) {
351 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
352 return; // did not enter to sensitive matrix
353 }
354 xyzLocS += step;
355 }
356
357 // get exit pixel row and col
358 while (!Segmentation::localToDetector(xyzLocE.X(), xyzLocE.Z(), rowE, colE, subDetID, layer, disk)) {
359 if (++nSkip >= nSteps) {
360 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
361 return; // did not enter to sensitive matrix
362 }
363 xyzLocE -= step;
364 }
365
366 int nCols = getNCols(subDetID, layer);
367 int nRows = getNRows(subDetID, layer);
368
369 // estimate the limiting min/max row and col where the non-0 response is possible
370 if (rowS > rowE) {
371 std::swap(rowS, rowE);
372 }
373 if (colS > colE) {
374 std::swap(colS, colE);
375 }
376 rowS -= AlpideRespSimMat::NPix / 2;
377 rowE += AlpideRespSimMat::NPix / 2;
378 if (rowS < 0) {
379 rowS = 0;
380 }
381 if (rowE >= nRows) {
382 rowE = nRows - 1;
383 }
384 colS -= AlpideRespSimMat::NPix / 2;
385 colE += AlpideRespSimMat::NPix / 2;
386 if (colS < 0) {
387 colS = 0;
388 }
389 if (colE >= nCols) {
390 colE = nCols - 1;
391 }
392 int rowSpan = rowE - rowS + 1, colSpan = colE - colS + 1; // size of plaquet where some response is expected
393
394 float respMatrix[rowSpan][colSpan]; // response accumulated here
395 std::fill(&respMatrix[0][0], &respMatrix[0][0] + rowSpan * colSpan, 0.f);
396
397 float nElectrons = hit.GetEnergyLoss() * mParams.getEnergyToNElectrons(); // total number of deposited electrons
398 nElectrons *= nStepsInv; // N electrons injected per step
399 if (nSkip) {
400 nSteps -= nSkip;
401 }
402
403 int rowPrev = -1, colPrev = -1, row, col;
404 float cRowPix = 0.f, cColPix = 0.f; // local coordinate of the current pixel center
405
406 const o2::trkft3::ChipSimResponse* resp = getChipResponse(chipID);
407 // std::cout << "Printing chip response:" << std::endl;
408 // resp->print();
409
410 // take into account that the ChipSimResponse depth defintion has different min/max boundaries
411 // although the max should coincide with the surface of the epitaxial layer, which in the chip
412 // local coordinates has Y = +SensorLayerThickness/2
413 // LOG(info)<<"SubdetID = " << subDetID<< " shift: "<<mSimRespVDShift<<" or "<<mSimRespMLOTShift;
414 // LOG(info)<< " Before shift: S = " << xyzLocS.Y()*1e4 << " E = " << xyzLocE.Y()*1e4;
415 xyzLocS.SetY(xyzLocS.Y() + ((subDetID == 0) ? mSimRespVDShift : mSimRespMLOTShift));
416 // LOG(info)<< " After shift: S = " << xyzLocS.Y()*1e4 << " E = " << xyzLocE.Y()*1e4;
417
418 // collect charge in every pixel which might be affected by the hit
419 for (int iStep = nSteps; iStep--;) {
420 // Get the pixel ID
421 Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), row, col, subDetID, layer, disk);
422 if (row != rowPrev || col != colPrev) { // update pixel and coordinates of its center
423 if (!Segmentation::detectorToLocal(row, col, cRowPix, cColPix, subDetID, layer, disk)) {
424 continue; // should not happen
425 }
426 rowPrev = row;
427 colPrev = col;
428 }
429 bool flipCol = false, flipRow = false;
430 // note that response needs coordinates along column row (locX) (locZ) then depth (locY)
431 float rowMax{}, colMax{};
432 const AlpideRespSimMat* rspmat{nullptr};
433 if (subDetID == 0) { // VD
434 rowMax = 0.5f * Segmentation::PitchRowVD * mSimRespVDScaleX;
435 colMax = 0.5f * Segmentation::PitchColVD * mSimRespVDScaleZ;
436 rspmat = resp->getResponse(mSimRespVDScaleX * (xyzLocS.X() - cRowPix), mSimRespVDScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
437 } else { // ML/OT
438 rowMax = 0.5f * Segmentation::PitchRowMLOT * mSimRespMLOTScaleX;
439 colMax = 0.5f * Segmentation::PitchColMLOT * mSimRespMLOTScaleZ;
440 rspmat = resp->getResponse(mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix), mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
441 }
442
443 xyzLocS += step;
444
445 if (rspmat == nullptr) {
446 LOG(debug) << "Error in rspmat for step " << iStep << " / " << nSteps;
447 continue;
448 }
449 // LOG(info) << "rspmat valid! for step " << iStep << " / " << nSteps << ", (row,col) = (" << row << "," << col << ")";
450 // LOG(info) << "rspmat valid! for step " << iStep << " / " << nSteps << " Y= " << xyzLocS.Y()*1e4 << " , (row,col) = (" << row << "," << col << ")";
451 // rspmat->print(); // print the response matrix for debugging
452
453 for (int irow = AlpideRespSimMat::NPix; irow--;) {
454 int rowDest = row + irow - AlpideRespSimMat::NPix / 2 - rowS; // destination row in the respMatrix
455 if (rowDest < 0 || rowDest >= rowSpan) {
456 continue;
457 }
458 for (int icol = AlpideRespSimMat::NPix; icol--;) {
459 int colDest = col + icol - AlpideRespSimMat::NPix / 2 - colS; // destination column in the respMatrix
460 if (colDest < 0 || colDest >= colSpan) {
461 continue;
462 }
463 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, mSimRespOrientation ? !flipRow : flipRow, flipCol);
464 }
465 }
466 }
467 LOG(info) << "Response done; adding labels; making digits";
468 // fire the pixels assuming Poisson(n_response_electrons)
469 o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false);
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--;) { // irow ranging from 4 to 0
473 uint16_t rowIS = irow + rowS; // row distant irow from the row of the hit start
474 for (int icol = colSpan; icol--;) { // icol ranging from 4 to 0
475 float nEleResp = respMatrix[irow][icol]; // value of the probability of the response in this pixel
476 if (nEleResp <= 1.e-36) {
477 continue;
478 }
479 LOG(debug) << "nEleResp: value " << nEleResp << " for pixel " << irow << " " << icol;
480 int nEle = gRandom->Poisson(nElectrons * nEleResp); // total charge in given pixel = number of electrons generated in the hit multiplied by the probability of being detected in their position
481 LOG(debug) << "Charge detected in the pixel: " << nEle << " for pixel " << irow << " " << icol;
482 // ignore charge which have no chance to fire the pixel
483 if (nEle < mParams.getMinChargeToAccount()) {
484 LOG(debug) << "Ignoring pixel with nEle = " << nEle << " < min charge to account "
485 << mParams.getMinChargeToAccount() << " for pixel " << irow << " " << icol;
486 continue;
487 }
488
489 uint16_t colIS = icol + colS; // col distant icol from the col of the hit start
490 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
491 continue;
492 }
493 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
494 continue;
495 }
496 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl, rofLayer);
497 }
498 }
499}
500
501//________________________________________________________________________________
502template <int DetID>
503void Digitizer<DetID>::registerDigits(o2::trkft3::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF,
504 uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl, int layer)
505{
506 // Register digits for given pixel, accounting for the possible signal contribution to
507 // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame
508 // In every ROFrame we check the collected signal during strobe
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; // strobe start wrt signal start
512 for (int i = 0; i < nROF; i++) { // loop on all the ROFs occupied by the same signal to calculate the charge accumulated in that ROF
513 uint32_t roFr = roFrame + i;
514 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength(layer));
515 tStrobe += mParams.getROFrameLength(layer); // for the next ROF
516
517 // discard too small contributions, they have no chance to produce a digit
518 if (nEleROF < mParams.getMinChargeToAccount()) {
519 continue;
520 }
521 if (roFr > mEventROFrameMax) {
522 mEventROFrameMax = roFr;
523 }
524 if (roFr < mEventROFrameMin) {
525 mEventROFrameMin = roFr;
526 }
527 auto key = chip.getOrderingKey(roFr, row, col);
529 if (!pd) {
530 chip.addDigit(key, roFr, row, col, nEleROF, lbl);
531 LOG(debug) << "Added digit with key: " << key << " ROF: " << roFr << " row: " << row << " col: " << col << " charge: " << nEleROF;
532 } else { // there is already a digit at this slot, account as PreDigitExtra contribution
533 LOG(debug) << "Added to pre-digit with key: " << key << " ROF: " << roFr << " row: " << row << " col: " << col << " charge: " << nEleROF;
534 pd->charge += nEleROF;
535 if (pd->labelRef.label == lbl) { // don't store the same label twice
536 continue;
537 }
538 ExtraDig* extra = getExtraDigBuffer(roFr);
539 int& nxt = pd->labelRef.next;
540 bool skip = false;
541 while (nxt >= 0) {
542 if ((*extra)[nxt].label == lbl) { // don't store the same label twice
543 skip = true;
544 break;
545 }
546 nxt = (*extra)[nxt].next;
547 }
548 if (skip) {
549 continue;
550 }
551 // new predigit will be added in the end of the chain
552 nxt = extra->size();
553 extra->emplace_back(lbl);
554 }
555 }
556}
557
std::ostringstream debug
int32_t i
uint32_t col
Definition RawData.h:4
Definition of the SegmentationChipclass.
specs of the ALICE3 TRK
Definition of the TRK/FT3 digitizer.
StringRef key
int GetTrackID() const
Definition BaseHits.h:30
V GetEnergyLoss() const
Definition BaseHits.h:103
math_utils::Point3D< T > GetPos() const
Definition BaseHits.h:67
E GetTime() const
Definition BaseHits.h:71
unsigned short GetDetectorID() const
Definition BaseHits.h:73
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:146
bool getResponse(float vRow, float vCol, float cDepth, AlpideRespSimMat &dest) const
void addDigit(ULong64_t key, UInt_t roframe, UShort_t row, UShort_t col, int charge, o2::MCCompLabel lbl)
o2::itsmft::PreDigit * findDigit(ULong64_t key)
auto getChipResponse(int chipID)
Definition Digitizer.cxx:95
void fillOutputContainer(uint32_t maxFrame=0xffffffff, int layer=-1)
void setEventTime(const o2::InteractionTimeRecord &irt, int layer=-1)
void process(const std::vector< Hit > *hits, int evID, int srcID, int layer=-1)
Steer conversion of hits to digits.
static constexpr bool detectorToLocal(int iRow, int iCol, float &xRow, float &zCol, int subDetID, int layer, int disk) noexcept
static constexpr float PitchColVD
static bool localToDetector(float xRow, float zCol, int &iRow, int &iCol, int subDetID, int layer, int disk) noexcept
static constexpr float PitchColMLOT
static constexpr float PitchRowMLOT
static constexpr float PitchRowVD
static constexpr float SiliconThicknessMLOT
static math_utils::Vector2D< float > curvedToFlat(const int layer, const float xCurved, const float yCurved) noexcept
static ULong64_t getOrderingKey(UInt_t roframe, UShort_t row, UShort_t col)
Get global ordering key made of readout frame, column and row.
math_utils::Point3D< Float_t > GetPosStart() const
Definition Hit.h:43
void setNEntries(int n)
Definition ROFRecord.h:39
const BCData & getBCData() const
Definition ROFRecord.h:41
int getFirstEntry() const
Definition ROFRecord.h:46
void setFirstEntry(int idx)
Definition ROFRecord.h:38
void setROFrame(ROFtype rof)
Definition ROFRecord.h:36
GLuint buffer
Definition glcorearb.h:655
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
constexpr double LHCBunchSpacingNS
value_T step
Definition TrackUtils.h:42
constexpr std::array< int, nLayers > nRows
Definition Specs.h:59
constexpr double pitchZ
Definition Specs.h:141
constexpr double pitchX
Definition Specs.h:140
constexpr double pitchZ
Definition Specs.h:133
constexpr double pitchX
Definition Specs.h:132
void setFromLong(int64_t l)
double timeInBCNS
time in NANOSECONDS relative to orbit/bc
double getTimeNS() const
get time in ns from orbit=0/bc=0
int next
eventual next contribution to the same pixel
Definition PreDigit.h:36
o2::MCCompLabel label
hit label
Definition PreDigit.h:35
int charge
N electrons.
Definition PreDigit.h:46
PreDigitLabelRef labelRef
label and reference to the next one
Definition PreDigit.h:47
IR getFirstSampledTFIR() const
get TF and HB (abs) for this IR
Definition HBFUtils.h:74
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row