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(debug) << " Depth max: " << mChipSimRespVD->getDepthMax();
66 LOG(debug) << " Depth min: " << mChipSimRespVD->getDepthMin();
67
68 float thicknessVD = 0.0095; // cm --- hardcoded based on geometry currently present
69 float thicknessMLOT = 0.1; // cm --- hardcoded based on geometry currently present
70
73 mSimRespVDScaleDepth = o2::trk::constants::apts::thickness / (thicknessVD);
74 // mSimRespVDShift = mChipSimRespVD->getDepthMax() - thicknessVD * mSimRespVDScaleDepth / 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
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 mSimRespMLOTScaleDepth = o2::trk::constants::apts::thickness / (thicknessMLOT);
79 mSimRespMLOTShift = mChipSimRespMLOT->getDepthMax() - thicknessMLOT * mSimRespMLOTScaleDepth / 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 * mSimRespMLOTScaleDepth / 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;
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 if (subDetID == 0) {
339 xyzLocS.SetY(xyzLocS.Y() * mSimRespVDScaleDepth);
340 xyzLocE.SetY(xyzLocE.Y() * mSimRespVDScaleDepth);
341 } else {
342 xyzLocS.SetY(xyzLocS.Y() * mSimRespMLOTScaleDepth);
343 xyzLocE.SetY(xyzLocE.Y() * mSimRespMLOTScaleDepth);
344 }
345 LOG(debug) << "rescaled Y: startPos = " << xyzLocS << ", endPos = " << xyzLocE << std::endl;
346
348 step -= xyzLocS;
349 step *= nStepsInv; // position increment at each step
350 // the electrons will injected in the middle of each step
351 // starting from the middle of the first step
352 math_utils::Vector3D<float> stepH(step * 0.5);
353 xyzLocS += stepH;
354 xyzLocE -= stepH;
355
356 LOG(debug) << "Step into the sensitive volume: " << step << ". Number of steps: " << nSteps;
357 int rowS = -1, colS = -1, rowE = -1, colE = -1, nSkip = 0;
358
360 // get entrance pixel row and col
361 while (!Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), rowS, colS, subDetID, layer, disk)) { // guard-ring ?
362 if (++nSkip >= nSteps) {
363 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
364 return; // did not enter to sensitive matrix
365 }
366 xyzLocS += step;
367 }
368
369 // get exit pixel row and col
370 while (!Segmentation::localToDetector(xyzLocE.X(), xyzLocE.Z(), rowE, colE, subDetID, layer, disk)) {
371 if (++nSkip >= nSteps) {
372 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
373 return; // did not enter to sensitive matrix
374 }
375 xyzLocE -= step;
376 }
377
378 int nCols = getNCols(subDetID, layer);
379 int nRows = getNRows(subDetID, layer);
380
381 // estimate the limiting min/max row and col where the non-0 response is possible
382 if (rowS > rowE) {
383 std::swap(rowS, rowE);
384 }
385 if (colS > colE) {
386 std::swap(colS, colE);
387 }
388 rowS -= AlpideRespSimMat::NPix / 2;
389 rowE += AlpideRespSimMat::NPix / 2;
390 if (rowS < 0) {
391 rowS = 0;
392 }
393 if (rowE >= nRows) {
394 rowE = nRows - 1;
395 }
396 colS -= AlpideRespSimMat::NPix / 2;
397 colE += AlpideRespSimMat::NPix / 2;
398 if (colS < 0) {
399 colS = 0;
400 }
401 if (colE >= nCols) {
402 colE = nCols - 1;
403 }
404 int rowSpan = rowE - rowS + 1, colSpan = colE - colS + 1; // size of plaquet where some response is expected
405
406 float respMatrix[rowSpan][colSpan]; // response accumulated here
407 std::fill(&respMatrix[0][0], &respMatrix[0][0] + rowSpan * colSpan, 0.f);
408
409 float nElectrons = hit.GetEnergyLoss() * mParams.getEnergyToNElectrons(); // total number of deposited electrons
410 nElectrons *= nStepsInv; // N electrons injected per step
411 if (nSkip) {
412 nSteps -= nSkip;
413 }
414
415 int rowPrev = -1, colPrev = -1, row, col;
416 float cRowPix = 0.f, cColPix = 0.f; // local coordinate of the current pixel center
417
418 const o2::trk::ChipSimResponse* resp = getChipResponse(chipID);
419 // std::cout << "Printing chip response:" << std::endl;
420 // resp->print();
421
422 // take into account that the ChipSimResponse depth defintion has different min/max boundaries
423 // although the max should coincide with the surface of the epitaxial layer, which in the chip
424 // local coordinates has Y = +SensorLayerThickness/2
425 xyzLocS.SetY(xyzLocS.Y() + ((subDetID == 0) ? mSimRespVDShift : mSimRespMLOTShift));
426
427 // collect charge in every pixel which might be affected by the hit
428 for (int iStep = nSteps; iStep--;) {
429 // Get the pixel ID
430 Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), row, col, subDetID, layer, disk);
431 if (row != rowPrev || col != colPrev) { // update pixel and coordinates of its center
432 if (!Segmentation::detectorToLocal(row, col, cRowPix, cColPix, subDetID, layer, disk)) {
433 continue; // should not happen
434 }
435 rowPrev = row;
436 colPrev = col;
437 }
438 bool flipCol = false, flipRow = false;
439 // note that response needs coordinates along column row (locX) (locZ) then depth (locY)
440 float rowMax{}, colMax{};
441 const AlpideRespSimMat* rspmat{nullptr};
442 if (subDetID == 0) { // VD
443 rowMax = 0.5f * Segmentation::PitchRowVD * mSimRespVDScaleX;
444 colMax = 0.5f * Segmentation::PitchColVD * mSimRespVDScaleZ;
445 rspmat = resp->getResponse(mSimRespVDScaleX * (xyzLocS.X() - cRowPix), mSimRespVDScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
446 } else { // ML/OT
447 rowMax = 0.5f * Segmentation::PitchRowMLOT * mSimRespMLOTScaleX;
448 colMax = 0.5f * Segmentation::PitchColMLOT * mSimRespMLOTScaleZ;
449 rspmat = resp->getResponse(mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix), mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
450 }
451
452 float tempPitchX = 0, tempPitchZ = 0;
453 if (subDetID == 0) {
454 tempPitchX = Segmentation::PitchRowVD;
455 tempPitchZ = Segmentation::PitchColVD;
456 } else {
457 tempPitchX = Segmentation::PitchRowMLOT;
458 tempPitchZ = Segmentation::PitchColMLOT;
459 }
460 LOG(debug) << "X and Z inside pixel at start = " << (xyzLocS.X() - cRowPix) << " , " << (xyzLocS.Z() - cColPix) << ", rescaled: " << mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix) << " , " << mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix);
461 LOG(debug) << "Hit inside pitch? X: " << ((xyzLocS.X() - cRowPix) < tempPitchX) << " Z: " << ((xyzLocS.Z() - cColPix) < tempPitchZ);
462
463 xyzLocS += step;
464
465 if (rspmat == nullptr) {
466 LOG(debug) << "Error in rspmat for step " << iStep << " / " << nSteps;
467 continue;
468 }
469 LOG(debug) << "rspmat valid! for step " << iStep << " / " << nSteps << ", (row,col) = (" << row << "," << col << ")";
470 // rspmat->print(); // print the response matrix for debugging
471
472 for (int irow = AlpideRespSimMat::NPix; irow--;) {
473 int rowDest = row + irow - AlpideRespSimMat::NPix / 2 - rowS; // destination row in the respMatrix
474 if (rowDest < 0 || rowDest >= rowSpan) {
475 continue;
476 }
477 for (int icol = AlpideRespSimMat::NPix; icol--;) {
478 int colDest = col + icol - AlpideRespSimMat::NPix / 2 - colS; // destination column in the respMatrix
479 if (colDest < 0 || colDest >= colSpan) {
480 continue;
481 }
482 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, mSimRespOrientation ? !flipRow : flipRow, flipCol);
483 }
484 }
485 }
486
487 // fire the pixels assuming Poisson(n_response_electrons)
488 o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false);
489 auto roFrameAbs = mNewROFrame + roFrameRel;
490 LOG(debug) << "Spanning through rows and columns; rowspan = " << rowSpan << " colspan = " << colSpan << " = " << colE << " - " << colS << " +1 " << std::endl;
491 for (int irow = rowSpan; irow--;) { // irow ranging from 4 to 0
492 uint16_t rowIS = irow + rowS; // row distant irow from the row of the hit start
493 for (int icol = colSpan; icol--;) { // icol ranging from 4 to 0
494 float nEleResp = respMatrix[irow][icol]; // value of the probability of the response in this pixel
495 if (nEleResp <= 1.e-36) {
496 continue;
497 }
498 LOG(debug) << "nEleResp: value " << nEleResp << " for pixel " << irow << " " << icol << std::endl;
499 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
500 LOG(debug) << "Charge detected in the pixel: " << nEle << " for pixel " << irow << " " << icol << std::endl;
501 // ignore charge which have no chance to fire the pixel
502 if (nEle < mParams.getMinChargeToAccount()) {
503 LOG(debug) << "Ignoring pixel with nEle = " << nEle << " < min charge to account "
504 << mParams.getMinChargeToAccount() << " for pixel " << irow << " " << icol;
505 continue;
506 }
507
508 uint16_t colIS = icol + colS; // col distant icol from the col of the hit start
509 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
510 continue;
511 }
512 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
513 continue;
514 }
515
516 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl);
517 }
518 }
519}
520
521//________________________________________________________________________________
522void Digitizer::registerDigits(o2::trk::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF,
523 uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl)
524{
525 // Register digits for given pixel, accounting for the possible signal contribution to
526 // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame
527 // In every ROFrame we check the collected signal during strobe
528 LOG(debug) << "Registering digits for chip " << chip.getChipIndex() << " at ROFrame " << roFrame
529 << " row " << row << " col " << col << " nEle " << nEle << " label " << lbl;
530 float tStrobe = mParams.getStrobeDelay() - tInROF; // strobe start wrt signal start
531 for (int i = 0; i < nROF; i++) {
532 uint32_t roFr = roFrame + i;
533 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength());
534 tStrobe += mParams.getROFrameLength(); // for the next ROF
535
536 // discard too small contributions, they have no chance to produce a digit
537 if (nEleROF < mParams.getMinChargeToAccount()) {
538 continue;
539 }
540 if (roFr > mEventROFrameMax) {
541 mEventROFrameMax = roFr;
542 }
543 if (roFr < mEventROFrameMin) {
544 mEventROFrameMin = roFr;
545 }
546 auto key = chip.getOrderingKey(roFr, row, col);
548 if (!pd) {
549 chip.addDigit(key, roFr, row, col, nEleROF, lbl);
550 LOG(debug) << "Added digit " << key << " " << roFr << " " << row << " " << col << " " << nEleROF;
551 } else { // there is already a digit at this slot, account as PreDigitExtra contribution
552 pd->charge += nEleROF;
553 if (pd->labelRef.label == lbl) { // don't store the same label twice
554 continue;
555 }
556 ExtraDig* extra = getExtraDigBuffer(roFr);
557 int& nxt = pd->labelRef.next;
558 bool skip = false;
559 while (nxt >= 0) {
560 if ((*extra)[nxt].label == lbl) { // don't store the same label twice
561 skip = true;
562 break;
563 }
564 nxt = (*extra)[nxt].next;
565 }
566 if (skip) {
567 continue;
568 }
569 // new predigit will be added in the end of the chain
570 nxt = extra->size();
571 extra->emplace_back(lbl);
572 }
573 }
574}
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 const void Print() noexcept
Print segmentation info.
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:122
constexpr double pitchX
Definition Specs.h:121
constexpr double thickness
Definition Specs.h:124
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