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
14#include "FT0Base/FT0DigParam.h"
18
20#include "FT0Base/Constants.h"
21#include <map>
22
23#include "TMath.h"
24#include "TRandom.h"
25#include <TH1F.h>
26#include <algorithm>
27#include <cassert>
28#include <iostream>
29#include <optional>
30#include <Vc/Vc>
31
32using namespace o2::ft0;
33
35
36namespace o2::ft0
37{
38// signal shape function
39template <typename Float>
41{
42 float p0, p1, p2, p3, p4, p5, p6, p7;
43 p0 = 1.30853;
44 p1 = 0.516807;
45 p2 = 3.36714;
46 p3 = -1.01206;
47 p4 = 1.42832;
48 p5 = 1.1589;
49 p6 = 1.22019;
50 p7 = 0.426818;
51
52 Double_t val = 0;
53
54 if (x > p3) {
55 Double_t x1 = x - p3;
56 Double_t arg1 = (log(x1) - p0) / p1;
57 val += p2 * (1.0 / (x1 * p1 * sqrt(2 * TMath::Pi()))) * exp(-0.5 * arg1 * arg1);
58 }
59
60 if (x > p7) {
61 Double_t x2 = x - p7;
62 Double_t arg2 = (log(x2) - p4) / p5;
63 val += p6 * (1.0 / (x2 * p5 * sqrt(2 * TMath::Pi()))) * exp(-0.5 * arg2 * arg2);
64 }
65
66 return val;
67};
68
69// integrated signal shape function
70inline float signalForm_integral(float x)
71{
72 float p0, p1, p2, p3, p4, p5, p6, p7;
73 p0 = 1.30853;
74 p1 = 0.516807;
75 p2 = 3.36714;
76 p3 = -1.01206;
77 p4 = 1.42832;
78 p5 = 1.1589;
79 p6 = 1.22019;
80 p7 = 0.426818;
81 Double_t val = 0;
82
83 if (x > p3) {
84 Double_t x1 = x - p3;
85 Double_t z1 = (log(x1) - p0) / (sqrt(2) * p1);
86 val += p2 * 0.5 * (1 + TMath::Erf(z1)); // norm1 * CDF1
87 }
88
89 if (x > p7) {
90 Double_t x2 = x - p7;
91 Double_t z2 = (log(x2) - p4) / (sqrt(2) * p5);
92 val += p6 * 0.5 * (1 + TMath::Erf(z2)); // norm2 * CDF2
93 }
94
95 return val;
96};
97/*
98// signal shape function
99template <typename Float>
100Float signalForm_i(Float x)
101{
102using namespace std;
103Float const a = -0.45458;
104Float const b = -0.83344945;
105return x > Float(0) ? -(exp(b * x) - exp(a * x)) / Float(7.8446501) : Float(0);
106};
107
108// integrated signal shape function
109inline float signalForm_integral(float x)
110{
111using namespace std;
112double const a = -0.45458;
113double const b = -0.83344945;
114if (x < 0) {
115 x = 0;
116}
117return -(exp(b * x) / b - exp(a * x) / a) / 7.8446501;
118};
119*/
120// SIMD version of the integrated signal shape function
121inline Vc::float_v signalForm_integralVc(Vc::float_v x)
122{
123 auto const mask = (x >= 0.0f);
124 Vc::float_v arg(0);
125 arg.assign(x, mask); // branchless if
126 Vc::float_v const a(-0.45458f);
127 Vc::float_v const b(-0.83344945f);
128 Vc::float_v result = -(Vc::exp(b * arg) / b - Vc::exp(a * arg) / a) / 7.8446501f;
129 return result;
130};
131} // namespace o2::ft0
132
133Digitizer::CFDOutput Digitizer::get_time(const std::vector<float>& times, float deadTime)
134{
135 assert(std::is_sorted(std::begin(times), std::end(times)));
136
137 // get a new batch of random values
138 for (float& n : mNoiseSamples) {
139 n = mRndGaus.getNextValue();
140 }
141
142 // this lambda function evaluates the signal shape at a give time
143 auto value_at = [&](float time) {
144 float val = 0;
145 // (1) sum over individual hits
146 Vc::float_v acc(0);
147 Vc::float_v tableVal(0);
148 const float* tp = times.data();
149 size_t m = times.size() / Vc::float_v::size();
150 for (size_t i = 0; i < m; ++i) {
151 tableVal.load(tp);
152 tp += Vc::float_v::size();
153 Vc::prefetchForOneRead(tp);
154 acc += signalFormVc(time - tableVal);
155 }
156 val += acc.sum();
157 // non-SIMD tail
158 for (size_t i = Vc::float_v::size() * m; i < times.size(); ++i, ++tp) {
159 val += signalForm(time - (*tp));
160 }
161 // (2) add noise
162 // find the right indices into the sinc table
163 int timeIndex = std::lround(time / FT0DigParam::Instance().mNoisePeriod * mSincTable.size());
164 int timeOffset = timeIndex / mSincTable.size();
165 timeIndex %= mSincTable.size();
166 if (timeOffset >= mNumNoiseSamples) { // this happens when time >= 25 ns
167 timeOffset = mNumNoiseSamples - 1;
168 LOG(debug) << "timeOffset >= mNumNoiseSamples";
169 }
170 if (timeOffset <= -mNumNoiseSamples) { // this happens when time <= -25 ns
171 timeOffset = -mNumNoiseSamples + 1;
172 LOG(debug) << "timeOffset <= -mNumNoiseSamples";
173 }
174 Vc::float_v noiseVal(0);
175 const float* np = mNoiseSamples.data();
176 tp = mSincTable[timeIndex].data() + mNumNoiseSamples - timeOffset;
177 acc = 0.0f;
178 m = mNumNoiseSamples / Vc::float_v::Size;
179 for (size_t i = 0; i < m; ++i) {
180 tableVal.load(tp);
181 tp += Vc::float_v::Size;
182 Vc::prefetchForOneRead(tp);
183 noiseVal.load(np);
184 np += Vc::float_v::Size;
185 Vc::prefetchForOneRead(np);
186 acc += noiseVal * tableVal;
187 }
188 val += acc.sum(); // horizontal sum
189 // non-SIMD tail
190 for (size_t i = Vc::float_v::Size * m; i < mNumNoiseSamples; ++i, ++tp, ++np) {
191 val += (*np) * (*tp);
192 }
193 return val;
194 };
195 auto const min_time = std::max(deadTime, *std::min_element(std::begin(times),
196 std::end(times)));
197 CFDOutput result{std::nullopt, -0.5f * FT0DigParam::Instance().mBunchWidth};
198 bool is_positive = true;
199
200 // reset the chache
201 std::fill_n(std::begin(mSignalCache), std::size(mSignalCache), -1.0f);
202 const auto& params = FT0DigParam::Instance();
203 // we need double precision for time in order to match previous behaviour
204 for (double time = min_time; time < 0.5 * params.mBunchWidth; time += DP::SIGNAL_CACHE_DT) {
205 float const val = value_at(time);
206 int const index = std::lround((time + 0.5 * params.mBunchWidth) / DP::SIGNAL_CACHE_DT);
207 if (index >= 0 && index < mSignalCache.size()) { // save the value for later use
208 mSignalCache[index] = val;
209 }
210 // look up the time-shifted signal value from the past
211 float val_prev = 0.0f;
212 int const index_prev = std::lround((time - params.mCFDShiftPos + 0.5f * params.mBunchWidth) / DP::SIGNAL_CACHE_DT);
213 val_prev = ((index_prev < 0 || index_prev >= mSignalCache.size() || mSignalCache[index_prev] < 0.0f)
214 ? value_at(time - params.mCFDShiftPos) // was not computed before
215 : mSignalCache[index_prev]); // is available in the cache
216 float const cfd_val = 5.0f * val_prev - val;
217 if (std::abs(val) > params.mCFD_trsh && !is_positive && cfd_val > 0.0f) {
218 if (!result.particle) {
219 result.particle = time;
220 }
221 result.deadTime = time + params.mCFDdeadTime;
222 time += params.mCFDdeadTime - DP::SIGNAL_CACHE_DT;
223 is_positive = true;
224 } else {
225 is_positive = cfd_val > 0.0f;
226 }
227 }
228 return result;
229}
230
231double Digitizer::measure_amplitude(const std::vector<float>& times) const
232{
233 float const from = FT0DigParam::Instance().mAmpRecordLow;
234 float const to = from + FT0DigParam::Instance().mAmpRecordUp;
235 // SIMD version has a negligible effect on the total wall time
236 Vc::float_v acc(0);
237 Vc::float_v tv(0);
238 const float* tp = times.data();
239 size_t const m = times.size() / Vc::float_v::Size;
240 for (size_t i = 0; i < m; ++i) {
241 tv.load(tp);
242 tp += Vc::float_v::Size;
243 Vc::prefetchForOneRead(tp);
244 acc += signalForm_integralVc(to - tv) - signalForm_integralVc(from - tv);
245 }
246 float result = acc.sum(); // horizontal sum
247 // non-SIMD tail
248 for (size_t i = Vc::float_v::Size * m; i < times.size(); ++i, ++tp) {
249 result += signalForm_integral(to - (*tp)) - signalForm_integral(from - (*tp));
250 }
251 return result;
252}
253
254void Digitizer::process(const std::vector<o2::ft0::HitType>* hits,
255 std::vector<o2::ft0::Digit>& digitsBC,
256 std::vector<o2::ft0::ChannelData>& digitsCh,
257 std::vector<o2::ft0::DetTrigInput>& digitsTrig,
259{
260 ;
261 // Calculating signal time, amplitude in mean_time +- time_gate --------------
262 LOG(debug) << " process firstBCinDeque " << firstBCinDeque << " mIntRecord " << mIntRecord;
263 if (firstBCinDeque != mIntRecord) {
264 flush(digitsBC, digitsCh, digitsTrig, label);
265 }
266
267 Int_t parent = -10;
268 for (auto const& hit : *hits) {
269 if (hit.GetEnergyLoss() > 0) {
270 continue;
271 }
272
273 Int_t hit_ch = hit.GetDetectorID();
274
275 // If the dead channel map is used, and the channel with ID 'hit_ch' is dead, don't process this hit.
276 if (mDeadChannelMap && !mDeadChannelMap->isChannelAlive(hit_ch)) {
277 continue;
278 }
279
280 const auto& params = FT0DigParam::Instance();
281
282 Bool_t is_A_side = (hit_ch < 4 * mGeometry.NCellsA);
283
284 // Subtract time-of-flight from hit time
285 const Float_t timeOfFlight = hit.GetPos().R() / o2::constants::physics::LightSpeedCm2NS;
286 const Float_t timeOffset = is_A_side ? params.hitTimeOffsetA : params.hitTimeOffsetC;
287 Double_t hit_time = hit.GetTime() - timeOfFlight + timeOffset + mIntRecord.getTimeOffsetWrtBC();
288
289 if (hit_time > 150) {
290 continue; // not collect very slow particles
291 }
292
293 auto relBC = o2::InteractionRecord{hit_time};
294 if (mCache.size() <= relBC.bc) {
295 mCache.resize(relBC.bc + 1);
296 }
297 mCache[relBC.bc].hits.emplace_back(BCCache::particle{hit_ch, hit_time - relBC.bc2ns()});
298 // charge particles in MCLabel
299 Int_t parentID = hit.GetTrackID();
300 if (parentID != parent) {
301 mCache[relBC.bc].labels.emplace(parentID, mEventID, mSrcID, hit_ch);
302 parent = parentID;
303 }
304 }
305}
306
307void Digitizer::storeBC(BCCache& bc,
308 std::vector<o2::ft0::Digit>& digitsBC,
309 std::vector<o2::ft0::ChannelData>& digitsCh,
310 std::vector<o2::ft0::DetTrigInput>& digitsTrig,
312{
313 if (bc.hits.empty()) {
314 return;
315 }
316 const auto& pmLookupTable = PMLookupTable::Instance();
317
318 int n_hit_A = 0, n_hit_C = 0, mean_time_A = 0, mean_time_C = 0;
319 int summ_ampl_A = 0, summ_ampl_C = 0;
320 int sum_A_ampl = 0, sum_C_ampl = 0;
321 int nPMTs = mGeometry.NCellsA * 4 + mGeometry.NCellsC * 4;
322 std::vector<int> sum_ampl_ipmt(nPMTs, 0);
323 // Per-PM summed charge (like in digits2trgFT0)
324 std::map<uint8_t, int> mapPMhash2sumAmpl;
325 for (const auto& entry : pmLookupTable.getPMs()) {
326 mapPMhash2sumAmpl.insert({entry.first, 0});
327 }
328
329 int vertex_time;
330 const auto& params = FT0DigParam::Instance();
331 int first = digitsCh.size(), nStored = 0;
332 auto& particles = bc.hits;
333 std::sort(std::begin(particles), std::end(particles));
334 auto channel_end = particles.begin();
335 std::vector<float> channel_times;
336 // std::set<int> disabledChannels = {40, 41, 42, 43, 88, 89, 90, 91, 56, 57, 58, 59, 60, 61, 62, 63, 72, 73, 74, 75, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 164, 165, 166, 167, 184, 185, 186, 187, 160, 161, 162, 163, 188, 189, 190, 191, 156, 157, 158, 159, 192, 193, 194, 195, 152, 153, 154, 155, 196, 197, 198, 199, 148, 149, 150, 151, 144, 145, 146, 147, 204, 205, 206, 207, 200, 201, 202, 203}; // przykładowe kanały
337 for (Int_t ipmt = 0; ipmt < params.mMCPs; ++ipmt) {
338 auto channel_begin = channel_end;
339 channel_end = std::find_if(channel_begin, particles.end(),
340 [ipmt](BCCache::particle const& p) { return p.hit_ch != ipmt; });
341
342 // The hits between 'channel_begin' and 'channel_end' now contains all hits for channel 'ipmt'
343
344 if (channel_end - channel_begin < params.mAmp_trsh) {
345 continue;
346 }
347 channel_times.resize(channel_end - channel_begin);
348 std::transform(channel_begin, channel_end, channel_times.begin(), [](BCCache::particle const& p) { return p.hit_time; });
349 int chain = (std::rand() % 2) ? 1 : 0;
350 auto cfd = get_time(channel_times, mDeadTimes[ipmt].intrec.bc2ns() -
351 firstBCinDeque.bc2ns() +
352 mDeadTimes[ipmt].deadTime);
353 mDeadTimes[ipmt].intrec = firstBCinDeque;
354 mDeadTimes[ipmt].deadTime = cfd.deadTime;
355
356 if (!cfd.particle) {
357 continue;
358 }
359 // miscalibrate CFD with cahnnel offsets
360 int miscalib = 0;
361 if (mCalibOffset) {
362 miscalib = mCalibOffset->mTimeOffsets[ipmt];
363 }
364 int smeared_time = 1000. * (*cfd.particle - params.mCfdShift) * params.mChannelWidthInverse + miscalib; // + int(1000. * mIntRecord.getTimeOffsetWrtBC() * params.mChannelWidthInverse);
365 bool is_time_in_signal_gate = (smeared_time > -params.mTime_trg_gate && smeared_time < params.mTime_trg_gate);
366 float charge = measure_amplitude(channel_times) * params.mCharge2amp;
367 float amp = is_time_in_signal_gate ? params.mMV_2_Nchannels * charge : 0;
368 if (amp > 4095) {
369 amp = 4095;
370 }
371 // if (!disabledChannels.count(ipmt)) {
372 // continue;
373 // }
374
375 LOG(debug) << mEventID << " bc " << firstBCinDeque.bc << " orbit " << firstBCinDeque.orbit << ", ipmt " << ipmt << ", smeared_time " << smeared_time << " nStored " << nStored << " offset " << miscalib;
376 if (is_time_in_signal_gate) {
379 // Sum channel charge per PM (similar logic as in digits2trgFT0)
381 mapPMhash2sumAmpl[pmLookupTable.getPMHash(static_cast<PMLookupTable::ChannelID>(ipmt))] += static_cast<int>(amp);
382 }
383 }
384 digitsCh.emplace_back(ipmt, smeared_time, int(amp), chain);
385 nStored++;
386
387 // fill triggers
388
389 Bool_t is_A_side = (ipmt < 4 * mGeometry.NCellsA);
390 if (!is_time_in_signal_gate) {
391 continue;
392 }
393
394 sum_ampl_ipmt[ipmt] += amp;
395
396 if (is_A_side) {
397 n_hit_A++;
398 summ_ampl_A += amp;
399 mean_time_A += smeared_time;
400 } else {
401 n_hit_C++;
402 summ_ampl_C += amp;
403 mean_time_C += smeared_time;
404 }
405 }
406
407 for (size_t i = 0; i < sum_ampl_ipmt.size(); i++) {
408 sum_ampl_ipmt[i] = sum_ampl_ipmt[i] >> 3;
409 if (i < 4 * mGeometry.NCellsA) {
410 sum_A_ampl += sum_ampl_ipmt[i];
411 } else {
412 sum_C_ampl += sum_ampl_ipmt[i];
413 }
414 }
415
416 // Sum over PMs (using per-PM map) for debug/monitoring
417 int sum_PM_ampl_debug = 0;
418 int sum_PM_ampl_A_debug = 0;
419 int sum_PM_ampl_C_debug = 0;
420 for (const auto& entry : mapPMhash2sumAmpl) {
421 int pmAmpl = (entry.second >> 3);
422 sum_PM_ampl_debug += pmAmpl;
423 if (pmLookupTable.isASide(entry.first)) {
424 sum_PM_ampl_A_debug += pmAmpl;
425 } else {
426 sum_PM_ampl_C_debug += pmAmpl;
427 }
428 }
429 LOG(debug) << "Sum PM amplitude (LUT-based): total=" << sum_PM_ampl_debug
430 << " A-side=" << sum_PM_ampl_A_debug
431 << " C-side=" << sum_PM_ampl_C_debug;
432
433 Bool_t is_A, is_C, isVertex, is_Central, is_SemiCentral = 0;
434 is_A = n_hit_A > 0;
435 is_C = n_hit_C > 0;
436 is_Central = sum_PM_ampl_A_debug + sum_PM_ampl_C_debug >= 2 * params.mtrg_central_trh;
437 is_SemiCentral = sum_PM_ampl_A_debug + sum_PM_ampl_C_debug >= 2 * params.mtrg_semicentral_trh && !is_Central;
438 uint32_t amplA = is_A ? summ_ampl_A * 0.125 : -5000; // sum amplitude A side / 8 (hardware)
439 uint32_t amplC = is_C ? summ_ampl_C * 0.125 : -5000; // sum amplitude C side / 8 (hardware)
440 int timeA = is_A ? mean_time_A / n_hit_A : -5000; // average time A side
441 int timeC = is_C ? mean_time_C / n_hit_C : -5000; // average time C side
442 vertex_time = (timeC - timeA) * 0.5;
443 isVertex = is_A && is_C && (vertex_time > -params.mTime_trg_vertex_gate && vertex_time < params.mTime_trg_vertex_gate);
444 LOG(debug) << " A " << is_A << " timeA " << timeA << " mean_time_A " << mean_time_A << " n_hit_A " << n_hit_A << " C " << is_C << " timeC " << timeC << " mean_time_C " << mean_time_C << " n_hit_C " << n_hit_C << " vertex_time " << vertex_time;
445 Triggers triggers;
446 bool isLaser = false;
447 bool isOutputsAreBlocked = false;
448 bool isDataValid = true;
449 if (nStored > 0) {
450 triggers.setTriggers(is_A, is_C, isVertex, is_Central, is_SemiCentral, int8_t(n_hit_A), int8_t(n_hit_C),
451 amplA, amplC, timeA, timeC, isLaser, isOutputsAreBlocked, isDataValid);
452 digitsBC.emplace_back(first, nStored, firstBCinDeque, triggers, mEventID - 1);
453 digitsTrig.emplace_back(firstBCinDeque, is_A, is_C, isVertex, is_Central, is_SemiCentral);
454 size_t const nBC = digitsBC.size();
455 for (auto const& lbl : bc.labels) {
456 labels.addElement(nBC - 1, lbl);
457 }
458 }
459 // Debug output -------------------------------------------------------------
460
461 LOG(debug) << "Event ID: " << mEventID << ", bc " << firstBCinDeque.bc << ", N hit " << bc.hits.size();
462 LOG(debug) << "N hit A: " << int(triggers.getNChanA()) << " N hit C: " << int(triggers.getNChanC()) << " summ ampl A: " << int(triggers.getAmplA())
463 << " summ ampl C: " << int(triggers.getAmplC()) << " mean time A: " << triggers.getTimeA()
464 << " mean time C: " << triggers.getTimeC() << " nStored " << nStored;
465
466 LOG(debug) << "IS A " << triggers.getOrA() << " IsC " << triggers.getOrC() << " vertex " << triggers.getVertex() << " is Central " << triggers.getCen() << " is SemiCentral " << triggers.getSCen();
467}
468
469//------------------------------------------------------------------------
470void Digitizer::flush(std::vector<o2::ft0::Digit>& digitsBC,
471 std::vector<o2::ft0::ChannelData>& digitsCh,
472 std::vector<o2::ft0::DetTrigInput>& digitsTrig,
474{
475
476 assert(firstBCinDeque <= mIntRecord);
477
478 while (firstBCinDeque < mIntRecord && !mCache.empty()) {
479 storeBC(mCache.front(), digitsBC, digitsCh, digitsTrig, labels);
480 mCache.pop_front();
481 ++firstBCinDeque;
482 }
483 firstBCinDeque = mIntRecord;
484}
485
486void Digitizer::flush_all(std::vector<o2::ft0::Digit>& digitsBC,
487 std::vector<o2::ft0::ChannelData>& digitsCh,
488 std::vector<o2::ft0::DetTrigInput>& digitsTrig,
490{
491
492 assert(firstBCinDeque <= mIntRecord);
493 ++mEventID;
494 while (!mCache.empty()) {
495 storeBC(mCache.front(), digitsBC, digitsCh, digitsTrig, labels);
496 mCache.pop_front();
497 ++firstBCinDeque;
498 }
499}
500
502{
503 auto const sinc = [](double x) { x *= TMath::Pi(); return (std::abs(x) < 1e-12) ? 1.0 : std::sin(x) / x; };
504
505 // number of noise samples in one BC
506 const auto& params = FT0DigParam::Instance();
507 mNumNoiseSamples = std::ceil(params.mBunchWidth / params.mNoisePeriod);
508 mNoiseSamples.resize(mNumNoiseSamples);
509
510 // set up tables with sinc function values (times noiseVar)
511 for (size_t i = 0, n = mSincTable.size(); i < n; ++i) {
512 float const time = i / float(n) * params.mNoisePeriod; // [0 .. 1/params.mNoisePeriod)
513 LOG(debug) << "initParameters " << i << "/" << n << " " << time;
514 // we make a table of sinc values between -num_noise_samples and 2*num_noise_samples
515 mSincTable[i].resize(3 * mNumNoiseSamples);
516 for (int j = -mNumNoiseSamples; j < 2 * mNumNoiseSamples; ++j) {
517 mSincTable[i][mNumNoiseSamples + j] = params.mNoiseVar * sinc((time + 0.5f * params.mBunchWidth) / params.mNoisePeriod - j);
518 }
519 }
520 // set up the lookup table for the signal form
521 for (size_t i = 0; i < DP::SIGNAL_TABLE_SIZE; ++i) {
522 float const x = float(i) / float(DP::SIGNAL_TABLE_SIZE) * params.mBunchWidth;
523 mSignalTable[i] = signalForm_i(x);
524 }
525
526 // cache for signal time series used by the CFD -BC/2 .. +3BC/2
527 mSignalCache.resize(std::lround(params.mBunchWidth / DP::SIGNAL_CACHE_DT));
528}
529//_______________________________________________________________________
531{
532 LOG(info) << " @@@ Digitizer::init " << std::endl;
533 mDeadTimes.fill({InteractionRecord(0), -100.});
535}
536//_______________________________________________________________________
538{
540}
541
542//_______________________________________________________________________
544{
545 const auto& params = FT0DigParam::Instance();
546 LOG(info) << " Run Digitzation with parametrs: \n"
547 << " CFD amplitude threshold \n " << params.mCFD_trsh << " CFD signal gate in ps \n"
548 << params.mTime_trg_gate << "shift to have signal around zero after CFD trancformation \n"
549 << params.mCfdShift << "CFD distance between 0.3 of max amplitude to max \n"
550 << params.mCFDShiftPos << "MIP -> mV " << params.mMip_in_V << " Pe in MIP \n"
551 << params.mPe_in_mip << "noise level " << params.mNoiseVar << " noise frequency \n"
552 << params.mNoisePeriod << " mMCPs " << params.mMCPs;
553}
554
std::vector< unsigned long > times
#define O2ParamImpl(classname)
uint64_t exp(uint64_t base, uint8_t exp) noexcept
General constants in FT0.
std::ostringstream debug
ClassImp(Digitizer)
int64_t timeC
int16_t charge
Definition RawEventData.h:5
int64_t amplA
int64_t timeA
int64_t amplC
uint64_t bc
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
Configurable digitization parameters.
int32_t i
GPUChain * chain
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
configStandalone Reconstruction rec_tpc float
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
std::vector< o2::MCCompLabel > labels
Definition of a container to keep Monte Carlo truth external to simulation objects.
Header to collect physics constants.
uint32_t j
Definition RawData.h:0
A container to hold and manage MC truth information/labels.
uint8_t getNChanC() const
Definition Triggers.h:97
int32_t getAmplC() const
Definition Triggers.h:99
bool getCen() const
Definition Triggers.h:85
int32_t getAmplA() const
Definition Triggers.h:98
bool getVertex() const
Definition Triggers.h:87
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
int16_t getTimeC() const
Definition Triggers.h:101
uint8_t getNChanA() const
Definition Triggers.h:96
bool getOrA() const
Definition Triggers.h:80
bool getOrC() const
Definition Triggers.h:81
int16_t getTimeA() const
Definition Triggers.h:100
bool getSCen() const
Definition Triggers.h:83
void flush(std::vector< o2::ft0::Digit > &digitsBC, std::vector< o2::ft0::ChannelData > &digitsCh, std::vector< o2::ft0::DetTrigInput > &digitsTrig, o2::dataformats::MCTruthContainer< o2::ft0::MCLabel > &label)
void printParameters() const
CFDOutput get_time(const std::vector< float > &times, float deadTime)
VcType signalFormVc(VcType x) const
Definition Digitizer.h:121
void process(const std::vector< o2::ft0::HitType > *hits, std::vector< o2::ft0::Digit > &digitsBC, std::vector< o2::ft0::ChannelData > &digitsCh, std::vector< o2::ft0::DetTrigInput > &digitsTrig, o2::dataformats::MCTruthContainer< o2::ft0::MCLabel > &label)
void flush_all(std::vector< o2::ft0::Digit > &digitsBC, std::vector< o2::ft0::ChannelData > &digitsCh, std::vector< o2::ft0::DetTrigInput > &digitsTrig, o2::dataformats::MCTruthContainer< o2::ft0::MCLabel > &label)
double measure_amplitude(const std::vector< float > &times) const
float signalForm(float x) const
Definition Digitizer.h:106
static constexpr int NCellsA
Definition Geometry.h:52
static constexpr int NCellsC
Definition Geometry.h:53
static const PMLookupTable & Instance()
Return the process-wide immutable lookup table.
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLuint index
Definition glcorearb.h:781
GLint first
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint GLuint mask
Definition glcorearb.h:291
uint8_t int statusCode int
Float signalForm_i(Float x)
Definition Digitizer.cxx:40
Vc::float_v signalForm_integralVc(Vc::float_v x)
float signalForm_integral(float x)
Definition Digitizer.cxx:70
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
static double bc2ns(int bc, unsigned int orbit)
const bool isChannelAlive(const uint8_t &chId) const
static constexpr std::size_t sNCHANNELS_PM
Definition Constants.h:33
static constexpr double SIGNAL_CACHE_DT
std::array< int16_t, o2::ft0::Geometry::Nchannels > mTimeOffsets
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"