16 #include "CLHEP/Random/RandGaussZiggurat.h"
20 inline float remainder_1(
float a,
int b) {
21 float remainderValue = std::fmod(
a,
b);
22 if (remainderValue != 0. ||
a == 0.) {
23 return remainderValue;
25 return static_cast<float>(
b);
29 inline float exp16(
float x) {
36 const std::string &
name,
39 m_version(
"HGTD Timing three-ring layout"),
42 m_electronicJitter(std::sqrt((0.025 * 0.025) - (0.010 * 0.010))),
45 m_radii{120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230,
46 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350,
47 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470,
48 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590,
49 600, 610, 620, 630, 640, 650, 660, 670, 680, 690},
51 m_doseInner1000{1.995, 1.953, 1.787, 1.687, 1.608, 1.518,
52 1.448, 1.425, 1.354, 1.328, 1.275},
54 m_doseMiddle2000{2.44, 2.355, 2.26, 2.204, 2.137, 2.081, 2.015, 1.96,
55 1.878, 1.87, 1.809, 1.732, 1.722, 1.63, 1.588, 1.57,
56 1.509, 1.464, 1.44, 1.38, 1.333, 1.321, 1.284, 1.271},
58 m_doseOuter4000{2.458, 2.4, 2.382, 2.362, 2.266, 2.207, 2.122, 2.067,
59 2.046, 1.973, 1.94, 1.9, 1.869, 1.83, 1.711, 1.701,
60 1.685, 1.615, 1.626, 1.565, 1.53, 1.499, 1.429},
62 m_doseResolution{{0.01, 0.025}, {0.1, 0.031}, {0.3, 0.035}, {0.6, 0.040},
63 {1.0, 0.046}, {3.0, 0.065}, {6.0, 0.065}},
65 m_doseGain{{0.01, 39}, {0.1, 23}, {0.3, 21}, {0.6, 19},
66 {1.0, 10}, {3.0, 5}, {6.0, 4}} {}
73 "ERROR while initializing the HGTD timing resolution. Vector of "
75 return StatusCode::FAILURE;
80 return StatusCode::SUCCESS;
94 return StatusCode::SUCCESS;
100 float sigmaT = 99999.;
115 return std::sqrt(sigmaT2);
127 for (
unsigned int i = 1;
i <
m_radii.size();
i++) {
150 for (
unsigned int i = 1;
i <
m_radii.size();
i++) {
206 for (
unsigned int i = 0;
i <
m_dose.size();
i++) {
231 for (
unsigned int i = 0;
i <
m_dose.size();
i++) {
236 for (
unsigned int j = 1; j <
m_doseGain.size(); j++) {
270 CLHEP::HepRandomEngine *rndm_engine)
const {
273 float pulseParameter[4] = {0};
274 pulseParameter[0] = 0.036;
277 pulseParameter[3] = CLHEP::RandGaussZiggurat::shoot(
283 0.4785 + 1.4196 * pulseParameter[3];
290 float invsq2pi = 1 / sqrt(2 *
M_PI);
291 float mpshift = -0.22278298;
294 float mpc = pulseParameter[1] - mpshift * pulseParameter[0];
296 float step_par =
step / (sqrt(2) * pulseParameter[3]);
297 float f_weight = pulseParameter[2] *
step * invsq2pi / pulseParameter[3];
302 for (
int i = 412;
i < 527;
i++) {
304 fland = TMath::Landau(3.5 + (
i * 0.005), mpc, pulseParameter[0]) /
306 p_time = (1.5 + (
i % 6 -
i) * 0.005) / (sqrt(2) * pulseParameter[3]);
308 for (
size_t point =
i % 6; point < pulseWaveform.size(); point += 6) {
310 pulseWaveform[point] += fland * exp16(-p_time * p_time);
313 for (
size_t point = 0; point < pulseWaveform.size(); point++) {
314 pulseWaveform[point] = f_weight * pulseWaveform[point];
317 return pulseWaveform;
322 std::map<
int, std::pair<float, float>> &pulsebin,
const float t,
323 const float E,
float *
max, CLHEP::HepRandomEngine *rndm_engine)
const {
329 for (
size_t point = 0; point < pulseWaveform.size(); point++) {
331 energy = pulseWaveform[point] *
E +
332 CLHEP::RandGaussZiggurat::shoot(rndm_engine, 0, 0.015) *
E;
333 time =
t + point * 0.005;
334 timebin = (
int)(
t / 0.005) + point;
336 auto pulse = pulsebin.find(timebin);
337 if (pulse == pulsebin.end()) {
339 pulse = pulsebin.find(timebin);
341 (*pulse).second = {(*pulse).second.first +
time *
energy,
342 (*pulse).second.second +
energy};
344 if (
max[0] < (*pulse).second.second) {
345 max[0] = (*pulse).second.second;
346 max[1] = (*pulse).second.first /
max[0];
353 const float t,
const float E,
const float r,
354 CLHEP::HepRandomEngine *rndm_engine)
const {
355 std::map<int, std::pair<float, float>> pulseBins;
356 float max_hit[4] = {0};
359 for (
auto &pulse : pulseBins) {
360 if (pulse.second.second == 0) {
362 "HGTD_TimingResolution::calculateTime -> Energy goes zero, please "
363 "have a check, energy * time = "
364 << pulse.second.first <<
" while energy = " << pulse.second.second);
367 pulse.second.first = 0;
369 pulse.second.first = pulse.second.first / pulse.second.second;
372 if ((max_hit[1] > pulse.second.first) &&
374 (max_hit[3] > pulse.second.first || max_hit[3] == 0)) {
375 max_hit[2] = pulse.second.second;
376 max_hit[3] = pulse.second.first;