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