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
12#include <TRandom.h>
13#include <cmath>
14#include <numeric>
17#include "FV0Base/Geometry.h"
18#include "FV0Base/Constants.h"
19#include "TF1Convolution.h"
20
22
23using namespace o2::math_utils;
24using namespace o2::fv0;
25
27{
28 mEventId = -1;
29 mSrcId = -1;
30 for (auto& analogSignal : mPmtChargeVsTime) {
31 std::fill_n(std::begin(analogSignal), analogSignal.size(), 0);
32 }
33 mLastBCCache.clear();
34 mCfdStartIndex.fill(0);
35}
36
37//_______________________________________________________________________
39{
40 LOG(info) << "init";
41 mNBins = FV0DigParam::Instance().waveformNbins; // Will be computed using detector set-up from CDB
42 mBinSize = FV0DigParam::Instance().waveformBinWidth; // Will be set-up from CDB
43 mNTimeBinsPerBC = std::lround(o2::constants::lhc::LHCBunchSpacingNS / mBinSize); // 1920 bins/BC
44
45 for (Int_t detID = 0; detID < Constants::nFv0Channels; detID++) {
46 mPmtChargeVsTime[detID].resize(mNBins);
47 mLastBCCache.mPmtChargeVsTime[detID].resize(mNBins);
48 }
49
51 TF1Convolution convolutionRingA1ToA4("expo", "landau", 5.e-09, 90.e-09, false);
52 TF1 convolutionRingA1ToA4Fn("convolutionFn", convolutionRingA1ToA4, 5.e-09, 90.e-09, convolutionRingA1ToA4.GetNpar());
53 convolutionRingA1ToA4Fn.SetParameters(FV0DigParam::Instance().constRingA1ToA4, FV0DigParam::Instance().slopeRingA1ToA4,
54 FV0DigParam::Instance().mpvRingA1ToA4, FV0DigParam::Instance().sigmaRingA1ToA4);
55
57 TF1Convolution convolutionRing5("expo", "landau", 5.e-09, 90.e-09, false);
58 TF1 convolutionRing5Fn("convolutionFn", convolutionRing5, 5.e-09, 90.e-09, convolutionRing5.GetNpar());
59 convolutionRing5Fn.SetParameters(FV0DigParam::Instance().constRing5, FV0DigParam::Instance().slopeRing5,
60 FV0DigParam::Instance().mpvRing5, FV0DigParam::Instance().sigmaRing5);
62 mPmtResponseGlobalRingA1ToA4.resize(mNBins);
63 const float binSizeInNs = mBinSize * 1.e-09; // to convert ns into sec
64 double x = (binSizeInNs) / 2.0;
65 for (auto& y : mPmtResponseGlobalRingA1ToA4) {
66 y = FV0DigParam::Instance().getNormRingA1ToA4() // normalisation to have MIP adc at 16
67 * convolutionRingA1ToA4Fn.Eval(x + FV0DigParam::Instance().offsetRingA1ToA4); // offset to adjust mean position of waveform
68 x += binSizeInNs;
69 }
71 mPmtResponseGlobalRing5.resize(mNBins);
72 x = (binSizeInNs) / 2.0;
73 for (auto& y : mPmtResponseGlobalRing5) {
74 y = FV0DigParam::Instance().getNormRing5() // normalisation to have MIP adc at 16
75 * convolutionRing5Fn.Eval(x + FV0DigParam::Instance().offsetRing5); // offset to adjust mean position of waveform
76 x += binSizeInNs;
77 }
78 mLastBCCache.clear();
79 mCfdStartIndex.fill(0);
80 LOG(info) << "init -> finished";
81}
82
83void Digitizer::process(const std::vector<o2::fv0::Hit>& hits,
84 std::vector<o2::fv0::Digit>& digitsBC,
85 std::vector<o2::fv0::ChannelData>& digitsCh,
86 std::vector<o2::fv0::DetTrigInput>& digitsTrig,
88{
89 LOG(debug) << "Begin with " << hits.size() << " hits";
90 flush(digitsBC, digitsCh, digitsTrig, labels); // flush cached signal which cannot be affect by new event
91
92 std::vector<int> hitIdx(hits.size());
93 std::iota(std::begin(hitIdx), std::end(hitIdx), 0);
94 std::sort(std::begin(hitIdx), std::end(hitIdx),
95 [&hits](int a, int b) { return hits[a].GetTrackID() < hits[b].GetTrackID(); });
96
97 // use ordered hits
98 for (auto ids : hitIdx) {
99 const auto& hit = hits[ids];
100 Int_t detId = hit.GetDetectorID();
101
102 if (mDeadChannelMap && !mDeadChannelMap->isChannelAlive(detId)) {
103 continue;
104 }
105
106 Double_t hitEdep = hit.GetHitValue() * 1e3; // convert to MeV
107 Float_t const hitTime = hit.GetTime() * 1e9; // convert to ns
108 // TODO: check how big is inaccuracy if more than 1 'below-threshold' particles hit the same detector cell
110 continue;
111 }
112 float distanceFromXc = 0;
113 if (Geometry::instance()->isRing5(detId)) {
114 distanceFromXc = getDistFromCellCenter(detId, hit.GetX(), hit.GetY());
115 }
116
117 int iChannelPerCell = 0;
118 while (iChannelPerCell < 2) { // loop over 2 channels, into which signal from each cell in ring 5 is split
119 if (Geometry::instance()->isRing5(detId)) {
120 // The first channel number is located counter-clockwise from the cell center
121 // and remains identical to the detector number, the second one is clockwise and incremented by 8
122 if (iChannelPerCell == 1) {
123 detId += 8;
124 }
125 // Split signal magnitude to fractions depending on the distance of the hit from the cell center
126 hitEdep = (hit.GetHitValue() * 1e3) * getSignalFraction(distanceFromXc, iChannelPerCell == 0);
127 // LOG(info) << " detId: " << detId << "-" << iChannelPerCell << " hitEdep: " << hitEdep << " distanceFromXc: " << distanceFromXc;
128 ++iChannelPerCell;
129 } else {
130 iChannelPerCell = 2; // not a ring 5 cell -> don't repeat the loop
131 }
132 Double_t const nPhotons = hitEdep * DP::N_PHOTONS_PER_MEV;
133 float const nPhE = SimulateLightYield(detId, nPhotons);
134 float const mipFraction = float(nPhE / FV0DigParam::Instance().avgNumberPhElectronPerMip);
135 Long64_t timeHit = hitTime;
136 timeHit += mIntRecord.getTimeNS();
137 o2::InteractionTimeRecord const irHit(timeHit);
138 std::array<o2::InteractionRecord, NBC2Cache> cachedIR;
139 int nCachedIR = 0;
140 for (int i = BCCacheMin; i < BCCacheMax + 1; i++) {
141 double const tNS = timeHit + o2::constants::lhc::LHCBunchSpacingNS * i;
142 cachedIR[nCachedIR].setFromNS(tNS);
143 if (tNS < 0 && cachedIR[nCachedIR] > irHit) {
144 continue; // don't go to negative BC/orbit (it will wrap)
145 }
146 // ensure existence of cached container
147 setBCCache(cachedIR[nCachedIR++]);
148 } // BCCache loop
149
150 createPulse(mipFraction, hit.GetTrackID(), hitTime, hit.GetPos().R(), cachedIR, nCachedIR, detId);
151
152 } // while loop
153 } // hitloop
154}
155
156void Digitizer::createPulse(float mipFraction, int parID, const double hitTime, const float hitR,
157 std::array<o2::InteractionRecord, NBC2Cache> const& cachedIR, int nCachedIR, const int detId)
158{
159
160 std::array<bool, NBC2Cache> added;
161 added.fill(false);
162
163 for (int ir = 0; ir < NBC2Cache; ir++) {
164 auto bcCache = getBCCache(cachedIR[ir]);
165 for (int ich = 0; ich < Constants::nFv0Channels; ich++) {
166 (*bcCache).mPmtChargeVsTime[ich].resize(mNTimeBinsPerBC);
167 }
168 }
169
170 // Subtract time-of-flight from hit time
171 const float timeOfFlight = hitR / o2::constants::physics::LightSpeedCm2NS;
172 Int_t const NBinShift = std::lround((hitTime - timeOfFlight + FV0DigParam::Instance().hitTimeOffset) / FV0DigParam::Instance().waveformBinWidth);
173
174 if (NBinShift >= 0 && NBinShift < FV0DigParam::Instance().waveformNbins) {
175 mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins, 0.);
176 if (isRing5(detId)) {
177 std::memcpy(&mPmtResponseTemp[NBinShift], &mPmtResponseGlobalRing5[0],
178 sizeof(double) * (FV0DigParam::Instance().waveformNbins - NBinShift));
179 } else {
180 std::memcpy(&mPmtResponseTemp[NBinShift], &mPmtResponseGlobalRingA1ToA4[0],
181 sizeof(double) * (FV0DigParam::Instance().waveformNbins - NBinShift));
182 }
183 } else {
184 if (isRing5(detId)) {
185 mPmtResponseTemp = mPmtResponseGlobalRing5;
186 mPmtResponseTemp.erase(mPmtResponseTemp.begin(), mPmtResponseTemp.begin() + abs(NBinShift));
187 } else {
188 mPmtResponseTemp = mPmtResponseGlobalRingA1ToA4;
189 mPmtResponseTemp.erase(mPmtResponseTemp.begin(), mPmtResponseTemp.begin() + abs(NBinShift));
190 }
191
192 mPmtResponseTemp.resize(FV0DigParam::Instance().waveformNbins);
193 }
194
195 for (int ir = 0; ir < int(mPmtResponseTemp.size() / mNTimeBinsPerBC); ir++) {
196 auto bcCache = getBCCache(cachedIR[ir]);
197
198 for (int iBin = 0; iBin < mNTimeBinsPerBC; iBin++) {
199 (*bcCache).mPmtChargeVsTime[detId][iBin] += (mPmtResponseTemp[ir * mNTimeBinsPerBC + iBin] * mipFraction);
200 }
201 added[ir] = true;
202 }
204 for (int ir = 0; ir < nCachedIR; ir++) {
205 if (added[ir]) {
206 auto bcCache = getBCCache(cachedIR[ir]);
207 (*bcCache).labels.emplace_back(parID, mEventId, mSrcId, detId);
208 }
209 }
210}
211
212void Digitizer::flush(std::vector<o2::fv0::Digit>& digitsBC,
213 std::vector<o2::fv0::ChannelData>& digitsCh,
214 std::vector<o2::fv0::DetTrigInput>& digitsTrig,
216{
217 ++mEventId;
218 while (!mCache.empty()) {
219 auto const& bc = mCache.front();
220 if (mIntRecord.differenceInBC(bc) > NBC2Cache) { // Build events that are separated by NBC2Cache BCs from current BC
221 storeBC(bc, digitsBC, digitsCh, digitsTrig, labels);
222 mCache.pop_front();
223 } else {
224 return;
225 }
226 }
227}
228
229void Digitizer::storeBC(const BCCache& bc,
230 std::vector<o2::fv0::Digit>& digitsBC,
231 std::vector<o2::fv0::ChannelData>& digitsCh,
232 std::vector<o2::fv0::DetTrigInput>& digitsTrig,
234
235{
236 size_t const nBC = digitsBC.size(); // save before digitsBC is being modified
237 size_t const first = digitsCh.size(); // save before digitsCh is being modified
238 int8_t nTotFiredCells = 0;
239 int8_t nTrgFiredCells = 0; // number of fired cells, that follow additional trigger conditions (time gate)
240 int totalChargeAllRing = 0;
241 int totalChargeInnerRing = 0;
242 int totalChargeOuterRing = 0;
243 int32_t avgTime = 0;
244 double nSignalInner = 0;
245 double nSignalOuter = 0;
246
247 if (mLastBCCache.differenceInBC(bc) != 1) { // if the last buffered BC is not the one before the current BC
248 mLastBCCache.clear(); // clear the bufffer (mPmtChargeVsTime set to 0s)
249 mCfdStartIndex.fill(0); // reset all start indices to 0, i.e., to the beginning of the BC
250 }
251
252 for (int iPmt = 0; iPmt < Constants::nFv0Channels; iPmt++) {
253 // run the CFD: this updates the start index for the next BC in case the CFD dead time ends in the next BC
254 double cfdWithOffset = SimulateTimeCfd(mCfdStartIndex[iPmt], mLastBCCache.mPmtChargeVsTime[iPmt], bc.mPmtChargeVsTime[iPmt]);
255 double cfdZero = cfdWithOffset - FV0DigParam::Instance().avgCfdTimeForMip;
256
257 // Conditions to sum charge are: all participating channels must have time within +/- 2.5 ns, AND
258 // at least one channel must follow more strict conditions (see below)
259 if (cfdZero < -FV0DigParam::Instance().cfdCheckWindow || cfdZero > FV0DigParam::Instance().cfdCheckWindow) {
260 continue;
261 }
262
263 int iTotalCharge = std::lround(IntegrateCharge(bc.mPmtChargeVsTime[iPmt]) * DP::INV_CHARGE_PER_ADC); // convert Coulomb to adc;
264
265 uint8_t channelBits = FV0DigParam::Instance().defaultChainQtc;
266 if (std::rand() % 2) {
268 }
269 if (iTotalCharge > (FV0DigParam::Instance().maxCountInAdc) && FV0DigParam::Instance().useMaxChInAdc) {
270 iTotalCharge = FV0DigParam::Instance().maxCountInAdc; // max adc channel for one PMT
272 }
273
274 if (iTotalCharge < FV0DigParam::Instance().getCFDTrshInAdc()) {
275 continue;
276 }
277
278 int iCfdZero = std::lround(cfdZero * DP::INV_TIME_PER_TDCCHANNEL);
279 digitsCh.emplace_back(iPmt, iCfdZero, iTotalCharge, channelBits);
280 ++nTotFiredCells;
281
282 int triggerGate = FV0DigParam::Instance().mTime_trg_gate;
283 if (std::abs(iCfdZero) < triggerGate) {
284 ++nTrgFiredCells;
285 //---trigger---
286 totalChargeAllRing += iTotalCharge;
287 avgTime += iCfdZero;
288 if (iPmt < 24) {
289 nSignalInner++;
290 totalChargeInnerRing += iTotalCharge;
291 } else {
292 nSignalOuter++;
293 totalChargeOuterRing += iTotalCharge;
294 }
295 }
296 }
297 // save BC information for the CFD detector
298 mLastBCCache = bc;
299 if (nTotFiredCells < 1) {
300 return;
301 }
302 if (nTrgFiredCells > 0) {
303 avgTime /= nTrgFiredCells;
304 } else {
306 }
308 bool isA, isNchannels, isAIn, isAOut, isTotalCharge;
309 isA = nTrgFiredCells > 0;
310 isNchannels = nTrgFiredCells > FV0DigParam::Instance().NchannelsLevel;
311 // isAIn = nSignalInner > FV0DigParam::Instance().NchannelsLevel; // ring 1,2 and 3
312 isAIn = 0.125 * totalChargeInnerRing > 2 * FV0DigParam::Instance().InnerChargeLevel; // ring 1,2 and 3
313 // isAOut = nSignalOuter > FV0DigParam::Instance().NchannelsLevel; // ring 4 and 5
314 isAOut = 0.125 * totalChargeOuterRing > 2 * FV0DigParam::Instance().OuterChargeLevel; // ring 4 and 5
315 isTotalCharge = 0.125 * totalChargeAllRing > 2 * FV0DigParam::Instance().ChargeLevel;
316
317 Triggers triggers;
318 const int unusedCharge = o2::fit::Triggers::DEFAULT_AMP;
319 const int unusedTime = o2::fit::Triggers::DEFAULT_TIME;
320 const int unusedZero = o2::fit::Triggers::DEFAULT_ZERO;
321 const bool unusedBitsInSim = false; // bits related to laser and data validity
322 const bool bitDataIsValid = true;
323 triggers.setTriggers(isA, isAIn, isAOut, isTotalCharge, isNchannels, nTrgFiredCells, (int8_t)unusedZero,
324 (int32_t)(0.125 * totalChargeAllRing), (int32_t)unusedCharge, (int16_t)avgTime, (int16_t)unusedTime, unusedBitsInSim, unusedBitsInSim, bitDataIsValid);
325 digitsBC.emplace_back(first, nTotFiredCells, bc, triggers, mEventId - 1);
326 digitsTrig.emplace_back(bc, isA, isAIn, isAOut, isTotalCharge, isNchannels);
327 for (auto const& lbl : bc.labels) {
328 labels.addElement(nBC, lbl);
329 }
330}
331
332// -------------------------------------------------------------------------------
333// --- Internal helper methods related to conversion of energy-deposition into ---
334// --- photons -> photoelectrons -> electrical signal ---
335// -------------------------------------------------------------------------------
336Int_t Digitizer::SimulateLightYield(Int_t pmt, Int_t nPhot) const
337{
338 const Float_t epsilon = 0.0001f;
340 if ((fabs(1.0f - p) < epsilon) || nPhot == 0) {
341 return nPhot;
342 }
343 const Int_t n = Int_t(nPhot < 100
344 ? gRandom->Binomial(nPhot, p)
345 : gRandom->Gaus((p * nPhot) + 0.5, TMath::Sqrt(p * (1. - p) * nPhot)));
346 return n;
347}
348//---------------------------------------------------------------------------
349Float_t Digitizer::IntegrateCharge(const ChannelDigitF& pulse) const
350{
351 int const chargeIntMin = FV0DigParam::Instance().isIntegrateFull ? 0 : (FV0DigParam::Instance().avgCfdTimeForMip - 6.0) / mBinSize; // Charge integration offset (cfd mean time - 6 ns)
352 int const chargeIntMax = FV0DigParam::Instance().isIntegrateFull ? mNTimeBinsPerBC : (FV0DigParam::Instance().avgCfdTimeForMip + 14.0) / mBinSize; // Charge integration offset (cfd mean time + 14 ns)
353 if (chargeIntMin < 0 || chargeIntMin > mNTimeBinsPerBC || chargeIntMax > mNTimeBinsPerBC) {
354 LOG(fatal) << "invalid indicess: chargeInMin=" << chargeIntMin << " chargeIntMax=" << chargeIntMax;
355 }
356 Float_t totalCharge = 0.0f;
357 for (int iTimeBin = chargeIntMin; iTimeBin < chargeIntMax; iTimeBin++) {
358 totalCharge += pulse[iTimeBin];
359 }
360 return totalCharge;
361}
362//---------------------------------------------------------------------------
363Float_t Digitizer::SimulateTimeCfd(int& startIndex, const ChannelDigitF& pulseLast, const ChannelDigitF& pulse) const
364{
365 Float_t timeCfd = -1024.0f;
366
367 if (pulse.empty()) {
368 startIndex = 0;
369 return timeCfd;
370 }
371
372 Float_t const cfdThrInCoulomb = FV0DigParam::Instance().mCFD_trsh * 1e-3 / 50 * mBinSize * 1e-9; // convert mV into Coulomb assuming 50 Ohm
373
374 Int_t const binShift = TMath::Nint(FV0DigParam::Instance().timeShiftCfd / mBinSize);
375 Float_t sigPrev = 5 * pulseLast[mNTimeBinsPerBC - binShift - 1] - pulseLast[mNTimeBinsPerBC - 1]; // CFD output from the last bin of the last BC
376 for (Int_t iTimeBin = 0; iTimeBin < mNTimeBinsPerBC; ++iTimeBin) {
377 Float_t const sigCurrent = 5.0f * (iTimeBin >= binShift ? pulse[iTimeBin - binShift] : pulseLast[mNTimeBinsPerBC - binShift + iTimeBin]) - pulse[iTimeBin];
378 if (iTimeBin >= startIndex && std::abs(pulse[iTimeBin]) > cfdThrInCoulomb) { // enable
379 if (sigPrev < 0.0f && sigCurrent >= 0.0f) { // test for zero-crossing
380 timeCfd = Float_t(iTimeBin) * mBinSize;
381 startIndex = iTimeBin + std::lround(FV0DigParam::Instance().mCfdDeadTime / mBinSize); // update startIndex (CFD dead time)
382 if (startIndex < mNTimeBinsPerBC) {
383 startIndex = 0; // dead-time ends in same BC: no impact on the following BC
384 } else {
385 startIndex -= mNTimeBinsPerBC;
386 }
387 if (startIndex > mNTimeBinsPerBC) {
388 LOG(fatal) << "CFD dead-time was set to > 25 ns";
389 }
390 break; // only detects the 1st zero-crossing in the BC
391 }
392 }
393 sigPrev = sigCurrent;
394 }
395 return timeCfd;
396}
397
398float Digitizer::getDistFromCellCenter(UInt_t cellId, double hitx, double hity)
399{
401
402 // Parametrize the line (ax+by+c=0) that crosses the detector center and the cell's middle point
403 Point3Dsimple* pCell = &geo->getCellCenter(cellId);
404 float x0, y0, z0;
405 geo->getGlobalPosition(x0, y0, z0);
406 double a = -(y0 - pCell->y) / (x0 - pCell->x);
407 double b = 1;
408 double c = -(y0 - a * x0);
409 // Return the distance from hit to this line
410 return (a * hitx + b * hity + c) / TMath::Sqrt(a * a + b * b);
411}
412
413float Digitizer::getSignalFraction(float distanceFromXc, bool isFirstChannel)
414{
415 float const fraction = sigmoidPmtRing5(distanceFromXc);
416 if (distanceFromXc > 0) {
417 return isFirstChannel ? fraction : (1. - fraction);
418 } else {
419 return isFirstChannel ? (1. - fraction) : fraction;
420 }
421}
422
423//_____________________________________________________________________________
424o2::fv0::Digitizer::BCCache& Digitizer::setBCCache(const o2::InteractionRecord& ir)
425{
426 if (mCache.empty() || mCache.back() < ir) {
427 mCache.emplace_back();
428 auto& cb = mCache.back();
429 cb = ir;
430 return cb;
431 }
432 if (mCache.front() > ir) {
433 mCache.emplace_front();
434 auto& cb = mCache.front();
435 cb = ir;
436 return cb;
437 }
438 for (auto cb = mCache.begin(); cb != mCache.end(); cb++) {
439 if ((*cb) == ir) {
440 return *cb;
441 }
442 if (ir < (*cb)) {
443 auto cbnew = mCache.emplace(cb); // insert new element before cb
444 (*cbnew) = ir;
445 return (*cbnew);
446 }
447 }
448 return mCache.front();
449}
450//_____________________________________________________________________________
451o2::fv0::Digitizer::BCCache* Digitizer::getBCCache(const o2::InteractionRecord& ir)
452{
453 // get pointer on existing cache
454 for (auto cb = mCache.begin(); cb != mCache.end(); cb++) {
455 if ((*cb) == ir) {
456 return &(*cb);
457 }
458 }
459 return nullptr;
460}
461
462bool Digitizer::isRing5(int detID)
463{
464 if (detID > 31) {
465 return true;
466 } else {
467 return false;
468 }
469}
470
std::vector< std::string > labels
#define O2ParamImpl(classname)
General constants in FV0.
std::ostringstream debug
Base definition of FV0 geometry.
ClassImp(o2::fv0::Digitizer)
uint64_t bc
Definition RawEventData.h:5
Configurable digitization parameters.
int32_t i
A container to hold and manage MC truth information/labels.
static const int16_t DEFAULT_AMP
Definition Triggers.h:51
static const int16_t DEFAULT_TIME
Definition Triggers.h:50
void setTriggers(uint8_t trgsig, uint8_t chanA, uint8_t chanC, int32_t aamplA, int32_t aamplC, int16_t atimeA, int16_t atimeC)
Definition Triggers.h:103
static const int16_t DEFAULT_ZERO
Definition Triggers.h:52
void flush(std::vector< o2::fv0::Digit > &digitsBC, std::vector< o2::fv0::ChannelData > &digitsCh, std::vector< o2::fv0::DetTrigInput > &digitsTrig, o2::dataformats::MCTruthContainer< o2::fv0::MCLabel > &labels)
void process(const std::vector< o2::fv0::Hit > &hits, std::vector< o2::fv0::Digit > &digitsBC, std::vector< o2::fv0::ChannelData > &digitsCh, std::vector< o2::fv0::DetTrigInput > &digitsTrig, o2::dataformats::MCTruthContainer< o2::fv0::MCLabel > &labels)
Definition Digitizer.cxx:83
FV0 Geometry.
Definition Geometry.h:51
static Geometry * instance(EGeoType initType=eUninitialized)
Point3Dsimple & getCellCenter(UInt_t cellId)
Definition Geometry.cxx:125
bool isRing5(UInt_t cellId)
Definition Geometry.cxx:135
void getGlobalPosition(float &x, float &y, float &z)
Utility functions to be accessed externally.
Definition Geometry.cxx:118
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint * ids
Definition glcorearb.h:647
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLfloat x0
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLfloat GLfloat y0
Definition glcorearb.h:5034
constexpr double LHCBunchSpacingNS
constexpr float LightSpeedCm2NS
float sigmoidPmtRing5(float x)
Definition Digitizer.h:152
float float & c
Definition Utils.h:111
int64_t differenceInBC(const InteractionRecord &other) const
double getTimeNS() const
get time in ns from orbit=0/bc=0
const bool isChannelAlive(const uint8_t &chId) const
void setFlag(uint8_t flag)
Definition ChannelData.h:55
static constexpr int nFv0Channels
Definition Constants.h:32
static constexpr float N_PHOTONS_PER_MEV
static constexpr float INV_CHARGE_PER_ADC
static constexpr float INV_TIME_PER_TDCCHANNEL
std::array< ChannelDigitF, Constants::nFv0Channels > mPmtChargeVsTime
Definition Digitizer.h:75
float getNormRingA1ToA4() const
Definition FV0DigParam.h:37
float getNormRing5() const
Definition FV0DigParam.h:45
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)