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