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 // 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 = o2::trk::SegmentationChip::SiliconThicknessMLOT; // 0.01 cm = 100 um --- 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;
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::trk::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 step -= xyzLocS;
338 step *= nStepsInv; // position increment at each step
339 // the electrons will injected in the middle of each step
340 // starting from the middle of the first step
341 math_utils::Vector3D<float> stepH(step * 0.5);
342 xyzLocS += stepH;
343 xyzLocE -= stepH;
344
345 LOG(debug) << "Step into the sensitive volume: " << step << ". Number of steps: " << nSteps;
346 int rowS = -1, colS = -1, rowE = -1, colE = -1, nSkip = 0;
347
349 // get entrance pixel row and col
350 while (!Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), rowS, colS, subDetID, layer, disk)) { // guard-ring ?
351 if (++nSkip >= nSteps) {
352 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
353 return; // did not enter to sensitive matrix
354 }
355 xyzLocS += step;
356 }
357
358 // get exit pixel row and col
359 while (!Segmentation::localToDetector(xyzLocE.X(), xyzLocE.Z(), rowE, colE, subDetID, layer, disk)) {
360 if (++nSkip >= nSteps) {
361 LOG(debug) << "Did not enter to sensitive matrix, " << nSkip << " >= " << nSteps;
362 return; // did not enter to sensitive matrix
363 }
364 xyzLocE -= step;
365 }
366
367 int nCols = getNCols(subDetID, layer);
368 int nRows = getNRows(subDetID, layer);
369
370 // estimate the limiting min/max row and col where the non-0 response is possible
371 if (rowS > rowE) {
372 std::swap(rowS, rowE);
373 }
374 if (colS > colE) {
375 std::swap(colS, colE);
376 }
377 rowS -= AlpideRespSimMat::NPix / 2;
378 rowE += AlpideRespSimMat::NPix / 2;
379 if (rowS < 0) {
380 rowS = 0;
381 }
382 if (rowE >= nRows) {
383 rowE = nRows - 1;
384 }
385 colS -= AlpideRespSimMat::NPix / 2;
386 colE += AlpideRespSimMat::NPix / 2;
387 if (colS < 0) {
388 colS = 0;
389 }
390 if (colE >= nCols) {
391 colE = nCols - 1;
392 }
393 int rowSpan = rowE - rowS + 1, colSpan = colE - colS + 1; // size of plaquet where some response is expected
394
395 float respMatrix[rowSpan][colSpan]; // response accumulated here
396 std::fill(&respMatrix[0][0], &respMatrix[0][0] + rowSpan * colSpan, 0.f);
397
398 float nElectrons = hit.GetEnergyLoss() * mParams.getEnergyToNElectrons(); // total number of deposited electrons
399 nElectrons *= nStepsInv; // N electrons injected per step
400 if (nSkip) {
401 nSteps -= nSkip;
402 }
403
404 int rowPrev = -1, colPrev = -1, row, col;
405 float cRowPix = 0.f, cColPix = 0.f; // local coordinate of the current pixel center
406
407 const o2::trk::ChipSimResponse* resp = getChipResponse(chipID);
408 // std::cout << "Printing chip response:" << std::endl;
409 // resp->print();
410
411 // take into account that the ChipSimResponse depth defintion has different min/max boundaries
412 // although the max should coincide with the surface of the epitaxial layer, which in the chip
413 // local coordinates has Y = +SensorLayerThickness/2
414 // LOG(info)<<"SubdetID = " << subDetID<< " shift: "<<mSimRespVDShift<<" or "<<mSimRespMLOTShift;
415 // LOG(info)<< " Before shift: S = " << xyzLocS.Y()*1e4 << " E = " << xyzLocE.Y()*1e4;
416 xyzLocS.SetY(xyzLocS.Y() + ((subDetID == 0) ? mSimRespVDShift : mSimRespMLOTShift));
417 // LOG(info)<< " After shift: S = " << xyzLocS.Y()*1e4 << " E = " << xyzLocE.Y()*1e4;
418
419 // collect charge in every pixel which might be affected by the hit
420 for (int iStep = nSteps; iStep--;) {
421 // Get the pixel ID
422 Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), row, col, subDetID, layer, disk);
423 if (row != rowPrev || col != colPrev) { // update pixel and coordinates of its center
424 if (!Segmentation::detectorToLocal(row, col, cRowPix, cColPix, subDetID, layer, disk)) {
425 continue; // should not happen
426 }
427 rowPrev = row;
428 colPrev = col;
429 }
430 bool flipCol = false, flipRow = false;
431 // note that response needs coordinates along column row (locX) (locZ) then depth (locY)
432 float rowMax{}, colMax{};
433 const AlpideRespSimMat* rspmat{nullptr};
434 if (subDetID == 0) { // VD
435 rowMax = 0.5f * Segmentation::PitchRowVD * mSimRespVDScaleX;
436 colMax = 0.5f * Segmentation::PitchColVD * mSimRespVDScaleZ;
437 rspmat = resp->getResponse(mSimRespVDScaleX * (xyzLocS.X() - cRowPix), mSimRespVDScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
438 } else { // ML/OT
439 rowMax = 0.5f * Segmentation::PitchRowMLOT * mSimRespMLOTScaleX;
440 colMax = 0.5f * Segmentation::PitchColMLOT * mSimRespMLOTScaleZ;
441 rspmat = resp->getResponse(mSimRespMLOTScaleX * (xyzLocS.X() - cRowPix), mSimRespMLOTScaleZ * (xyzLocS.Z() - cColPix), xyzLocS.Y(), flipRow, flipCol, rowMax, colMax);
442 }
443
444 xyzLocS += step;
445
446 if (rspmat == nullptr) {
447 LOG(debug) << "Error in rspmat for step " << iStep << " / " << nSteps;
448 continue;
449 }
450 // LOG(info) << "rspmat valid! for step " << iStep << " / " << nSteps << ", (row,col) = (" << row << "," << col << ")";
451 // LOG(info) << "rspmat valid! for step " << iStep << " / " << nSteps << " Y= " << xyzLocS.Y()*1e4 << " , (row,col) = (" << row << "," << col << ")";
452 // rspmat->print(); // print the response matrix for debugging
453
454 for (int irow = AlpideRespSimMat::NPix; irow--;) {
455 int rowDest = row + irow - AlpideRespSimMat::NPix / 2 - rowS; // destination row in the respMatrix
456 if (rowDest < 0 || rowDest >= rowSpan) {
457 continue;
458 }
459 for (int icol = AlpideRespSimMat::NPix; icol--;) {
460 int colDest = col + icol - AlpideRespSimMat::NPix / 2 - colS; // destination column in the respMatrix
461 if (colDest < 0 || colDest >= colSpan) {
462 continue;
463 }
464 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, mSimRespOrientation ? !flipRow : flipRow, !flipCol);
465 }
466 }
467 }
468
469 // fire the pixels assuming Poisson(n_response_electrons)
470 o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false);
471 auto roFrameAbs = mNewROFrame + roFrameRel;
472 LOG(debug) << "\nSpanning through rows and columns; rowspan = " << rowSpan << " colspan = " << colSpan << " = " << colE << " - " << colS << " +1 ";
473 for (int irow = rowSpan; irow--;) { // irow ranging from 4 to 0
474 uint16_t rowIS = irow + rowS; // row distant irow from the row of the hit start
475 for (int icol = colSpan; icol--;) { // icol ranging from 4 to 0
476 float nEleResp = respMatrix[irow][icol]; // value of the probability of the response in this pixel
477 if (nEleResp <= 1.e-36) {
478 continue;
479 }
480 LOG(debug) << "nEleResp: value " << nEleResp << " for pixel " << irow << " " << icol;
481 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
482 LOG(debug) << "Charge detected in the pixel: " << nEle << " for pixel " << irow << " " << icol;
483 // ignore charge which have no chance to fire the pixel
484 if (nEle < mParams.getMinChargeToAccount()) {
485 LOG(debug) << "Ignoring pixel with nEle = " << nEle << " < min charge to account "
486 << mParams.getMinChargeToAccount() << " for pixel " << irow << " " << icol;
487 continue;
488 }
489
490 uint16_t colIS = icol + colS; // col distant icol from the col of the hit start
491 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
492 continue;
493 }
494 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
495 continue;
496 }
497
498 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl);
499 }
500 }
501}
502
503//________________________________________________________________________________
504void Digitizer::registerDigits(o2::trk::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF,
505 uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl)
506{
507 // Register digits for given pixel, accounting for the possible signal contribution to
508 // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame
509 // In every ROFrame we check the collected signal during strobe
510 LOG(debug) << "Registering digits for chip " << chip.getChipIndex() << " at ROFrame " << roFrame
511 << " row " << row << " col " << col << " nEle " << nEle << " label " << lbl;
512 float tStrobe = mParams.getStrobeDelay() - tInROF; // strobe start wrt signal start
513 for (int i = 0; i < nROF; i++) {
514 uint32_t roFr = roFrame + i;
515 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength());
516 tStrobe += mParams.getROFrameLength(); // for the next ROF
517
518 // discard too small contributions, they have no chance to produce a digit
519 if (nEleROF < mParams.getMinChargeToAccount()) {
520 continue;
521 }
522 if (roFr > mEventROFrameMax) {
523 mEventROFrameMax = roFr;
524 }
525 if (roFr < mEventROFrameMin) {
526 mEventROFrameMin = roFr;
527 }
528 auto key = chip.getOrderingKey(roFr, row, col);
530 if (!pd) {
531 chip.addDigit(key, roFr, row, col, nEleROF, lbl);
532 LOG(debug) << "Added digit " << key << " " << roFr << " " << row << " " << col << " " << nEleROF;
533 } else { // there is already a digit at this slot, account as PreDigitExtra contribution
534 pd->charge += nEleROF;
535 if (pd->labelRef.label == lbl) { // don't store the same label twice
536 continue;
537 }
538 ExtraDig* extra = getExtraDigBuffer(roFr);
539 int& nxt = pd->labelRef.next;
540 bool skip = false;
541 while (nxt >= 0) {
542 if ((*extra)[nxt].label == lbl) { // don't store the same label twice
543 skip = true;
544 break;
545 }
546 nxt = (*extra)[nxt].next;
547 }
548 if (skip) {
549 continue;
550 }
551 // new predigit will be added in the end of the chain
552 nxt = extra->size();
553 extra->emplace_back(lbl);
554 }
555 }
556}
Definition of the ITSMFT digit.
std::ostringstream debug
int32_t i
uint32_t col
Definition RawData.h:4
Definition of the SegmentationChipclass.
Definition of the TRK digitizer.
StringRef key
int GetTrackID() const
Definition BaseHits.h:30
V GetEnergyLoss() const
Definition BaseHits.h:103
math_utils::Point3D< T > GetPos() const
Definition BaseHits.h:67
E GetTime() const
Definition BaseHits.h:71
unsigned short GetDetectorID() const
Definition BaseHits.h:73
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
const char * getName() const
const o2::detectors::DetID & getDetID() const
const Mat3D & getMatrixL2G(int sensID) const
float getCollectedCharge(float totalNEle, float tMin, float tMax) const
bool getResponse(float vRow, float vCol, float cDepth, AlpideRespSimMat &dest) const
void addDigit(ULong64_t key, UInt_t roframe, UShort_t row, UShort_t col, int charge, o2::MCCompLabel lbl)
o2::itsmft::PreDigit * findDigit(ULong64_t key)
static ULong64_t getOrderingKey(UInt_t roframe, UShort_t row, UShort_t col)
Get global ordering key made of readout frame, column and row.
int getMinChargeToAccount() const
Definition DigiParams.h:82
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
bool isFullChipMasked(int chip) const
Definition NoiseMap.h:186
bool isNoisy(int chip, int row, int col) const
Definition NoiseMap.h:151
void setNEntries(int n)
Definition ROFRecord.h:48
const BCData & getBCData() const
Definition ROFRecord.h:58
void setFirstEntry(int idx)
Definition ROFRecord.h:47
int getFirstEntry() const
Definition ROFRecord.h:63
void setROFrame(ROFtype rof)
Definition ROFRecord.h:45
static bool localToDetector(float x, float z, int &iRow, int &iCol)
static bool detectorToLocal(L row, L col, T &xRow, T &zCol)
math_utils::Point3D< Float_t > GetPosStart() const
Definition Hit.h:60
static constexpr float PitchColVD
static constexpr float PitchColMLOT
static constexpr float PitchRowMLOT
static void Print() noexcept
Print segmentation info.
static constexpr float PitchRowVD
static constexpr float SiliconThicknessMLOT
GLuint buffer
Definition glcorearb.h:655
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
constexpr double LHCBunchSpacingNS
value_T step
Definition TrackUtils.h:42
constexpr std::array< int, nLayers > nRows
Definition Specs.h:56
constexpr double pitchZ
Definition Specs.h:128
constexpr double pitchX
Definition Specs.h:127
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