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::itsmft::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 // importing the charge collection tables
52 // (initialized while building O2)
53 auto file = TFile::Open(mResponseFile.data());
54 if (!file) {
55 LOG(fatal) << "Cannot open response file " << mResponseFile;
56 }
57
58 // setting the correct response function (for the moment, for both VD and MLOT the APTS response function is udes)
59 mChipSimResp = (o2::trk::ChipSimResponse*)file->Get("response1");
60 mChipSimRespVD = mChipSimResp;
61 mChipSimRespMLOT = mChipSimResp;
62
64 // TODO: adjust Y shift when the geometry is improved
65 LOG(info) << " Depth max VD: " << mChipSimRespVD->getDepthMax();
66 LOG(info) << " Depth min VD: " << mChipSimRespVD->getDepthMin();
67
68 LOG(info) << " Depth max MLOT: " << mChipSimRespMLOT->getDepthMax();
69 LOG(info) << " Depth min MLOT: " << mChipSimRespMLOT->getDepthMin();
70
71 float thicknessVD = 0.0095; // cm --- hardcoded based on geometry currently present
72 float thicknessMLOT = 0.1; // cm --- hardcoded based on geometry currently present
73
76 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.
79 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
80 mSimRespOrientation = false;
81
82 // importing the parameters from DPLDigitizerParam.h
84
85 LOGP(info, "TRK Digitizer is initialised.");
86 mParams.print();
87 LOGP(info, "VD shift = {} ; ML/OT shift = {} = {} - {}", mSimRespVDShift, mSimRespMLOTShift, mChipSimRespMLOT->getDepthMax(), thicknessMLOT / 2.f);
88 LOGP(info, "VD pixel scale on x = {} ; z = {}", mSimRespVDScaleX, mSimRespVDScaleZ);
89 LOGP(info, "ML/OT pixel scale on x = {} ; z = {}", mSimRespMLOTScaleX, mSimRespMLOTScaleZ);
90 LOGP(info, "Response orientation: {}", mSimRespOrientation ? "flipped" : "normal");
91
93}
94
96{
97 if (mGeometry->getSubDetID(chipID) == 0) {
98 return mChipSimRespVD;
99 }
100
101 else if (mGeometry->getSubDetID(chipID) == 1) {
102 return mChipSimRespMLOT;
103 }
104 return nullptr;
105};
106
107//_______________________________________________________________________
108void Digitizer::process(const std::vector<Hit>* hits, int evID, int srcID)
109{
110 // digitize single event, the time must have been set beforehand
111
112 LOG(info) << " Digitizing " << mGeometry->getName() << " (ID: " << mGeometry->getDetID()
113 << ") hits of entry " << evID << " from source " << srcID
114 << " at time " << mEventTime << " ROFrame= " << mNewROFrame << ")"
115 << " cont.mode: " << isContinuous()
116 << " Min/Max ROFrames " << mROFrameMin << "/" << mROFrameMax;
117
118 // std::cout << "Printing segmentation info: " << std::endl;
119 // SegmentationChip::Print();
120
121 // // is there something to flush ?
122 if (mNewROFrame > mROFrameMin) {
123 fillOutputContainer(mNewROFrame - 1); // flush out all frames preceding the new one
124 }
125
126 int nHits = hits->size();
127 std::vector<int> hitIdx(nHits);
128 std::iota(std::begin(hitIdx), std::end(hitIdx), 0);
129 // sort hits to improve memory access
130 std::sort(hitIdx.begin(), hitIdx.end(),
131 [hits](auto lhs, auto rhs) {
132 return (*hits)[lhs].GetDetectorID() < (*hits)[rhs].GetDetectorID();
133 });
134 LOG(info) << "Processing " << nHits << " hits";
135 for (int i : hitIdx) {
136 processHit((*hits)[i], mROFrameMax, evID, srcID);
137 }
138
139 // in the triggered mode store digits after every MC event
140 // TODO: in the real triggered mode this will not be needed, this is actually for the
141 // single event processing only
142 if (!mParams.isContinuous()) {
143 fillOutputContainer(mROFrameMax);
144 }
145}
146
147//_______________________________________________________________________
149{
150 LOG(info) << "Setting event time ";
151 // assign event time in ns
152 mEventTime = irt;
153 if (!mParams.isContinuous()) {
154 mROFrameMin = 0; // in triggered mode reset the frame counters
155 mROFrameMax = 0;
156 }
157 // RO frame corresponding to provided time
158 mCollisionTimeWrtROF = mEventTime.timeInBCNS; // in triggered mode the ROF starts at BC (is there a delay?)
159 if (mParams.isContinuous()) {
160 auto nbc = mEventTime.differenceInBC(mIRFirstSampledTF);
161
162 if (mCollisionTimeWrtROF < 0 && nbc > 0) {
163 nbc--;
164 }
165
166 mNewROFrame = nbc / mParams.getROFrameLengthInBC();
167
168 LOG(info) << " NewROFrame " << mNewROFrame << " = " << nbc << "/" << mParams.getROFrameLengthInBC() << " (nbc/mParams.getROFrameLengthInBC()";
169
170 // in continuous mode depends on starts of periodic readout frame
171 mCollisionTimeWrtROF += (nbc % mParams.getROFrameLengthInBC()) * o2::constants::lhc::LHCBunchSpacingNS;
172 } else {
173 mNewROFrame = 0;
174 }
175
176 if (mNewROFrame < mROFrameMin) {
177 LOG(error) << "New ROFrame " << mNewROFrame << " (" << irt << ") precedes currently cashed " << mROFrameMin;
178 throw std::runtime_error("deduced ROFrame precedes already processed one");
179 }
180
181 if (mParams.isContinuous() && mROFrameMax < mNewROFrame) {
182 mROFrameMax = mNewROFrame - 1; // all frames up to this are finished
183 }
184}
185
186//_______________________________________________________________________
187void Digitizer::fillOutputContainer(uint32_t frameLast)
188{
189 // // fill output with digits from min.cached up to requested frame, generating the noise beforehand
190 if (frameLast > mROFrameMax) {
191 frameLast = mROFrameMax;
192 }
193 // // make sure all buffers for extra digits are created up to the maxFrame
194 getExtraDigBuffer(mROFrameMax);
195 LOG(info) << "Filling " << mGeometry->getName() << " digits output for RO frames " << mROFrameMin << ":"
196 << frameLast;
197
199
200 // we have to write chips in RO increasing order, therefore have to loop over the frames here
201 for (; mROFrameMin <= frameLast; mROFrameMin++) {
202 rcROF.setROFrame(mROFrameMin);
203 rcROF.setFirstEntry(mDigits->size()); // start of current ROF in digits
204
205 auto& extra = *(mExtraBuff.front().get());
206 for (auto& chip : mChips) {
207 if (chip.isDisabled()) {
208 continue;
209 }
210 // chip.addNoise(mROFrameMin, mROFrameMin, &mParams); /// TODO: add noise
211 auto& buffer = chip.getPreDigits();
212 if (buffer.empty()) {
213 continue;
214 }
215 auto itBeg = buffer.begin();
216 auto iter = itBeg;
217 ULong64_t maxKey = chip.getOrderingKey(mROFrameMin + 1, 0, 0) - 1; // fetch digits with key below that
218 for (; iter != buffer.end(); ++iter) {
219 if (iter->first > maxKey) {
220 break; // is the digit ROFrame from the key > the max requested frame
221 }
222 auto& preDig = iter->second; // preDigit
223 if (preDig.charge >= mParams.getChargeThreshold()) {
224 int digID = mDigits->size();
225 mDigits->emplace_back(chip.getChipIndex(), preDig.row, preDig.col, preDig.charge);
226 LOG(debug) << "Adding digit ID: " << digID << " with chipID: " << chip.getChipIndex() << ", row: " << preDig.row << ", col: " << preDig.col << ", charge: " << preDig.charge;
227 mMCLabels->addElement(digID, preDig.labelRef.label);
228 auto& nextRef = preDig.labelRef; // extra contributors are in extra array
229 while (nextRef.next >= 0) {
230 nextRef = extra[nextRef.next];
231 mMCLabels->addElement(digID, nextRef.label);
232 }
233 }
234 }
235 buffer.erase(itBeg, iter);
236 }
237 // finalize ROF record
238 rcROF.setNEntries(mDigits->size() - rcROF.getFirstEntry()); // number of digits
239 if (isContinuous()) {
240 rcROF.getBCData().setFromLong(mIRFirstSampledTF.toLong() + mROFrameMin * mParams.getROFrameLengthInBC());
241 } else {
242 rcROF.getBCData() = mEventTime; // RSTODO do we need to add trigger delay?
243 }
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//_______________________________________________________________________
255void Digitizer::processHit(const o2::itsmft::Hit& hit, uint32_t& maxFr, int evID, int srcID)
256{
257 int chipID = hit.GetDetectorID();
258 int subDetID = mGeometry->getSubDetID(chipID);
259
260 int layer = mGeometry->getLayer(chipID);
261 int disk = mGeometry->getDisk(chipID);
262
263 if (disk != -1) {
264 LOG(debug) << "Skipping disk " << disk;
265 return; // skipping hits on disks for the moment
266 }
267
268 LOG(debug) << "Processing hit for chip " << chipID;
269 auto& chip = mChips[chipID];
270 if (chip.isDisabled()) {
271 LOG(debug) << "Skipping disabled chip " << chipID;
272 return;
273 }
274 float timeInROF = hit.GetTime() * sec2ns;
275 LOG(debug) << "timeInROF: " << timeInROF;
276 if (timeInROF > 20e3) {
277 const int maxWarn = 10;
278 static int warnNo = 0;
279 if (warnNo < maxWarn) {
280 LOG(warning) << "Ignoring hit with time_in_event = " << timeInROF << " ns"
281 << ((++warnNo < maxWarn) ? "" : " (suppressing further warnings)");
282 }
283 return;
284 }
285 if (isContinuous()) {
286 timeInROF += mCollisionTimeWrtROF;
287 }
288 if (timeInROF < 0) {
289 // disregard this hit because it comes from an event byefore readout starts and it does not effect this RO
290 LOG(debug) << "Ignoring hit with timeInROF = " << timeInROF;
291 return;
292 }
293
294 // calculate RO Frame for this hit
295 if (timeInROF < 0) {
296 timeInROF = 0.;
297 }
298 float tTot = mParams.getSignalShape().getMaxDuration();
299 // frame of the hit signal start wrt event ROFrame
300 int roFrameRel = int(timeInROF * mParams.getROFrameLengthInv());
301 // frame of the hit signal end wrt event ROFrame: in the triggered mode we read just 1 frame
302 uint32_t roFrameRelMax = mParams.isContinuous() ? (timeInROF + tTot) * mParams.getROFrameLengthInv() : roFrameRel;
303 int nFrames = roFrameRelMax + 1 - roFrameRel;
304 uint32_t roFrameMax = mNewROFrame + roFrameRelMax;
305 if (roFrameMax > maxFr) {
306 maxFr = roFrameMax; // if signal extends beyond current maxFrame, increase the latter
307 }
308
309 // here we start stepping in the depth of the sensor to generate charge diffusion
310 float nStepsInv = mParams.getNSimStepsInv();
311 int nSteps = mParams.getNSimSteps();
312
313 const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID());
314 // matrix.print();
315
317 math_utils::Vector3D<float> xyzLocS(matrix ^ (hit.GetPosStart())); // start position in sensor frame
318 math_utils::Vector3D<float> xyzLocE(matrix ^ (hit.GetPos())); // end position in sensor frame
319
320 if (subDetID == 0) { // VD - need to take into account for the curved layers. TODO: consider the disks
321 // transform the point on the curved surface to a flat one
322 math_utils::Vector2D<float> xyFlatS = Segmentation::curvedToFlat(layer, xyzLocS.x(), xyzLocS.y());
323 math_utils::Vector2D<float> xyFlatE = Segmentation::curvedToFlat(layer, xyzLocE.x(), xyzLocE.y());
324 LOG(debug) << "Called curved to flat: " << xyzLocS.x() << " -> " << xyFlatS.x() << ", " << xyzLocS.y() << " -> " << xyFlatS.y();
325 // update the local coordinates with the flattened ones
326 xyzLocS.SetXYZ(xyFlatS.x(), xyFlatS.y(), xyzLocS.Z());
327 xyzLocE.SetXYZ(xyFlatE.x(), xyFlatE.y(), xyzLocE.Z());
328 }
329
330 // std::cout<<"Printing example of point in 0.35 0.35 0 in global frame: "<<std::endl;
331 // math_utils::Point3D<float> examplehitGlob(0.35, 0.35, 0);
332 // math_utils::Vector3D<float> exampleLoc(matrix ^ (examplehitGlob)); // start position in sensor frame
333 // std::cout<< "Example hit in local frame: " << exampleLoc << std::endl;
334 // std::cout<<"Going back to glob coordinates: " << (matrix * exampleLoc) << std::endl;
335
337 LOG(debug) << "local original: startPos = " << xyzLocS << ", endPos = " << xyzLocE << std::endl;
338 xyzLocS.SetY(xyzLocS.Y());
339 xyzLocE.SetY(xyzLocE.Y());
340
341 LOG(debug) << "rescaled Y: startPos = " << xyzLocS << ", endPos = " << xyzLocE << 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 xyzLocS.SetY(xyzLocS.Y() + ((subDetID == 0) ? mSimRespVDShift : mSimRespMLOTShift));
422
423 // collect charge in every pixel which might be affected by the hit
424 for (int iStep = nSteps; iStep--;) {
425 // Get the pixel ID
426 Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), row, col, subDetID, layer, disk);
427 if (row != rowPrev || col != colPrev) { // update pixel and coordinates of its center
428 if (!Segmentation::detectorToLocal(row, col, cRowPix, cColPix, subDetID, layer, disk)) {
429 continue; // should not happen
430 }
431 rowPrev = row;
432 colPrev = col;
433 }
434 bool flipCol = false, flipRow = false;
435 // note that response needs coordinates along column row (locX) (locZ) then depth (locY)
436 float rowMax{}, colMax{};
437 const AlpideRespSimMat* rspmat{nullptr};
438 if (subDetID == 0) { // VD
439 rowMax = 0.5f * Segmentation::PitchRowVD * mSimRespVDScaleX;
440 colMax = 0.5f * Segmentation::PitchColVD * mSimRespVDScaleZ;
441 rspmat = resp->getResponse(mSimRespVDScaleX * (xyzLocS.X() - cRowPix), mSimRespVDScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
442 } else { // ML/OT
443 rowMax = 0.5f * Segmentation::PitchRowMLOT * mSimRespMLOTScaleX;
444 colMax = 0.5f * Segmentation::PitchColMLOT * mSimRespMLOTScaleZ;
445 rspmat = resp->getResponse(mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix), mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
446 }
447
448 xyzLocS += step;
449
450 if (rspmat == nullptr) {
451 LOG(debug) << "Error in rspmat for step " << iStep << " / " << nSteps;
452 continue;
453 }
454 LOG(debug) << "rspmat valid! for step " << iStep << " / " << nSteps << ", (row,col) = (" << row << "," << col << ")";
455 // rspmat->print(); // print the response matrix for debugging
456
457 for (int irow = AlpideRespSimMat::NPix; irow--;) {
458 int rowDest = row + irow - AlpideRespSimMat::NPix / 2 - rowS; // destination row in the respMatrix
459 if (rowDest < 0 || rowDest >= rowSpan) {
460 continue;
461 }
462 for (int icol = AlpideRespSimMat::NPix; icol--;) {
463 int colDest = col + icol - AlpideRespSimMat::NPix / 2 - colS; // destination column in the respMatrix
464 if (colDest < 0 || colDest >= colSpan) {
465 continue;
466 }
467 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, mSimRespOrientation ? !flipRow : flipRow, !flipCol);
468 }
469 }
470 }
471
472 // fire the pixels assuming Poisson(n_response_electrons)
473 o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false);
474 auto roFrameAbs = mNewROFrame + roFrameRel;
475 LOG(debug) << "Spanning through rows and columns; rowspan = " << rowSpan << " colspan = " << colSpan << " = " << colE << " - " << colS << " +1 " << std::endl;
476 for (int irow = rowSpan; irow--;) { // irow ranging from 4 to 0
477 uint16_t rowIS = irow + rowS; // row distant irow from the row of the hit start
478 for (int icol = colSpan; icol--;) { // icol ranging from 4 to 0
479 float nEleResp = respMatrix[irow][icol]; // value of the probability of the response in this pixel
480 if (nEleResp <= 1.e-36) {
481 continue;
482 }
483 LOG(debug) << "nEleResp: value " << nEleResp << " for pixel " << irow << " " << icol << std::endl;
484 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
485 LOG(debug) << "Charge detected in the pixel: " << nEle << " for pixel " << irow << " " << icol << std::endl;
486 // ignore charge which have no chance to fire the pixel
487 if (nEle < mParams.getMinChargeToAccount()) {
488 LOG(debug) << "Ignoring pixel with nEle = " << nEle << " < min charge to account "
489 << mParams.getMinChargeToAccount() << " for pixel " << irow << " " << icol;
490 continue;
491 }
492
493 uint16_t colIS = icol + colS; // col distant icol from the col of the hit start
494 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
495 continue;
496 }
497 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
498 continue;
499 }
500
501 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl);
502 }
503 }
504}
505
506//________________________________________________________________________________
507void Digitizer::registerDigits(o2::trk::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF,
508 uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl)
509{
510 // Register digits for given pixel, accounting for the possible signal contribution to
511 // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame
512 // In every ROFrame we check the collected signal during strobe
513 LOG(debug) << "Registering digits for chip " << chip.getChipIndex() << " at ROFrame " << roFrame
514 << " row " << row << " col " << col << " nEle " << nEle << " label " << lbl;
515 float tStrobe = mParams.getStrobeDelay() - tInROF; // strobe start wrt signal start
516 for (int i = 0; i < nROF; i++) {
517 uint32_t roFr = roFrame + i;
518 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength());
519 tStrobe += mParams.getROFrameLength(); // for the next ROF
520
521 // discard too small contributions, they have no chance to produce a digit
522 if (nEleROF < mParams.getMinChargeToAccount()) {
523 continue;
524 }
525 if (roFr > mEventROFrameMax) {
526 mEventROFrameMax = roFr;
527 }
528 if (roFr < mEventROFrameMin) {
529 mEventROFrameMin = roFr;
530 }
531 auto key = chip.getOrderingKey(roFr, row, col);
533 if (!pd) {
534 chip.addDigit(key, roFr, row, col, nEleROF, lbl);
535 LOG(debug) << "Added digit " << key << " " << roFr << " " << row << " " << col << " " << nEleROF;
536 } else { // there is already a digit at this slot, account as PreDigitExtra contribution
537 pd->charge += nEleROF;
538 if (pd->labelRef.label == lbl) { // don't store the same label twice
539 continue;
540 }
541 ExtraDig* extra = getExtraDigBuffer(roFr);
542 int& nxt = pd->labelRef.next;
543 bool skip = false;
544 while (nxt >= 0) {
545 if ((*extra)[nxt].label == lbl) { // don't store the same label twice
546 skip = true;
547 break;
548 }
549 nxt = (*extra)[nxt].next;
550 }
551 if (skip) {
552 continue;
553 }
554 // new predigit will be added in the end of the chain
555 nxt = extra->size();
556 extra->emplace_back(lbl);
557 }
558 }
559}
Definition of the ITSMFT digit.
int32_t i
uint32_t col
Definition RawData.h:4
Definition of the SegmentationChipclass.
Definition of the TRK digitizer.
std::ostringstream debug
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
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
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)
bool isContinuous() const
Definition Digitizer.h:78
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
math_utils::Point3D< Float_t > GetPosStart() const
Definition Hit.h:60
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)
static constexpr float PitchColVD
static constexpr float PitchColMLOT
static constexpr float PitchRowMLOT
static constexpr float PitchRowVD
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:56
constexpr double pitchZ
Definition Specs.h:131
constexpr double pitchX
Definition Specs.h:130
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