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