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