R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BDigitizingPaddleNeuland.cxx
Go to the documentation of this file.
4#include "R3BLogger.h"
5#include "R3BShared.h"
7#include <RtypesCore.h>
8#include <algorithm>
9#include <cmath>
10#include <cstdint>
11#include <fairlogger/Logger.h>
12#include <utility>
13#include <vector>
14
16{
17 namespace
18 {
19 const uint8_t DEFAULT_ITERATION = 8U;
20 // check if a signal is matched to two or more signals. If so, discard the lastest match.
21 auto CheckMatchValidity(const std::vector<AbstractPaddle::ChannelSignalPair>& matchedPairs,
22 const AbstractChannel::Hit& signal) -> bool
23 {
24 auto is_valid = true;
25 auto it_existed = find_if(matchedPairs.begin(),
26 matchedPairs.end(),
27 [&signal](const auto& pair) -> bool { return &(pair.right.get()) == &(signal); });
28 if (it_existed != matchedPairs.end())
29 {
30 R3BLOG(debug, "one signal is matched again to another signal! The signal is discarded.");
31 is_valid = false;
32 }
33 return is_valid;
34 }
35
36 template <uint8_t iterations = DEFAULT_ITERATION>
37 auto FastExp(const Float_t val) -> Float_t
38 {
39 auto exp = 1.F + (val / (iterations >> 1U));
40 for (auto i = 0; i < iterations; ++i)
41 {
42 exp *= exp;
43 }
44 return exp;
45 }
46 } // namespace
47
48 Paddle::Paddle(int paddle_id)
50 {
51 }
52
53 Paddle::Paddle(int paddle_id, R3B::Neuland::Cal2HitPar* cal_to_hit_par)
55 , cal_to_hit_par_{ cal_to_hit_par }
56 {
57 }
58
60 const AbstractChannel::Hit& secondSignal) const -> float
61 {
62 auto firstE = static_cast<float>(firstSignal.qdcUnSat);
63 auto secondE = static_cast<float>(secondSignal.qdcUnSat);
64 auto firstT = firstSignal.tdc;
65 auto secondT = secondSignal.tdc;
66
67 // keep the exponent always negative to prevent the exploding of exponential function
68 auto res = 0.F;
69 if (firstT > secondT)
70 {
71 res = std::abs(((firstE / secondE) *
72 FastExp<4>(static_cast<float>(attenuation_ * effective_speed_ * (firstT - secondT)))) -
73 1);
74 }
75 else
76 {
77 res = std::abs(((secondE / firstE) * FastExp<4>(static_cast<float>(attenuation_ * effective_speed_ *
78 static_cast<float>(secondT - firstT)))) -
79 1);
80 }
81 return res;
82 }
83
85 {
86 if (cal_to_hit_par_ == nullptr)
87 {
88 return;
89 }
90 const auto& module_par = cal_to_hit_par_->GetModulePars().at(GetPaddleID());
91 effective_speed_ = module_par.effective_speed.value;
92 attenuation_ = 1. / module_par.light_attenuation_length.value;
93 time_offset_ = module_par.t_diff.value;
94 time_sync_ = module_par.t_sync.value;
96 }
97
98 inline auto Paddle::compute_energy(const AbstractChannel::Hit& firstSignal,
99 const AbstractChannel::Hit& secondSignal) const -> double
100 {
101 return std::sqrt(firstSignal.qdcUnSat * secondSignal.qdcUnSat) * reverse_atten_fac_;
102 }
103
104 inline auto Paddle::compute_time(const AbstractChannel::Hit& firstSignal,
105 const AbstractChannel::Hit& secondSignal) const -> double
106 {
107 // LOG(info) << "ComputeTime: using eff_speed:" << effective_speed_ << std::endl;
108 return ((firstSignal.tdc + secondSignal.tdc) / 2) - (HALF_BAR_LENGTH / effective_speed_) - time_sync_;
109 }
110
111 inline auto Paddle::compute_position(const AbstractChannel::Hit& leftSignal,
112 const AbstractChannel::Hit& rightSignal) const -> double
113 {
114 if (leftSignal.side == rightSignal.side)
115 {
116 R3BLOG(fatal, "cannot compute position with signals from same side!");
117 return 0.F;
118 }
119
120 return (leftSignal.side == Side::left)
121 ? (leftSignal.tdc - rightSignal.tdc + time_offset_) / 2 * effective_speed_
122 : (rightSignal.tdc - leftSignal.tdc + time_offset_) / 2 * effective_speed_;
123 }
124
126 {
127 auto channel_side_right = Side{ Side::right };
128 auto channel_side_left = Side{ Side::left };
129 auto rightChannelHit =
130 GenerateChannelSignal(signal.time, signal.energy_dep, signal.distance_to_center, channel_side_right);
131 auto leftChannelHit =
132 GenerateChannelSignal(signal.time, signal.energy_dep, -1 * signal.distance_to_center, channel_side_left);
133 return { leftChannelHit, rightChannelHit };
134 }
135
136 auto Paddle::GenerateChannelSignal(const double mcTime,
137 const double mcLight,
138 const double dist,
139 enum Side channel_side) const -> AbstractChannel::Signal
140 {
141 const auto light = mcLight * std::exp(-Paddle::attenuation_ * (Paddle::HALF_BAR_LENGTH - dist));
142 const auto site_sign = (channel_side == Side::right) ? 1 : -1;
143
144 const auto time = mcTime + ((Paddle::HALF_BAR_LENGTH - dist) / effective_speed_) +
145 (site_sign * time_offset_ * 0.5) + time_sync_;
146
147 return { time, light };
148 }
149
151 const AbstractChannel::Hits& firstSignals,
152 const AbstractChannel::Hits& secondSignals) -> std::vector<ChannelSignalPair>
153 {
154 // step1: determine the signals with smaller size:
155 decltype(auto) smallerSizeSignals = (firstSignals.size() < secondSignals.size()) ? firstSignals : secondSignals;
156 decltype(auto) largerSizeSignals = (firstSignals.size() >= secondSignals.size()) ? firstSignals : secondSignals;
157
158 // create empty pairs to be filled:
159 auto channelPairs = std::vector<ChannelSignalPair>{};
160 channelPairs.reserve(smallerSizeSignals.size());
161
162 // step2: signal matching:
163 for (const auto& it : smallerSizeSignals)
164 {
165 // find the element from largerSizeSignals with minimum matching value
166 auto it_min = std::min_element(largerSizeSignals.begin(),
167 largerSizeSignals.end(),
168 [&it = std::as_const(it), &self](const auto& left, const auto& right) -> bool
169 { return (self.match_hits(it, left) < self.match_hits(it, right)); });
170 if (it_min == largerSizeSignals.end())
171 {
172 LOG(warn) << "DigitizingPaddleNeuland.cxx::SignalCouplingNeuland(): failed to find minimum value!";
173 }
174 else
175 {
176 if (CheckMatchValidity(channelPairs, *it_min))
177 {
178 channelPairs.emplace_back(it, *it_min);
179 }
180 }
181 }
182 // step3: output pairs
183 return channelPairs;
184 }
185
186} // namespace R3B::Digitizing::Neuland
#define R3BLOG(severity, x)
Definition R3BLogger.h:32
AbstractPaddle(int paddleID, SignalCouplingStrategy strategy=SignalCouplingByTime)
auto compute_channel_signals(const Signal &signal) const -> Pair< AbstractChannel::Signal > override
auto match_hits(const AbstractChannel::Hit &firstSignal, const AbstractChannel::Hit &secondSignal) const -> float override
auto compute_energy(const AbstractChannel::Hit &firstSignal, const AbstractChannel::Hit &secondSignal) const -> double override
auto compute_position(const AbstractChannel::Hit &leftSignal, const AbstractChannel::Hit &rightSignal) const -> double override
auto GenerateChannelSignal(double mcTime, double mcLight, double dist, enum Side channel_side) const -> AbstractChannel::Signal
auto compute_time(const AbstractChannel::Hit &firstSignal, const AbstractChannel::Hit &secondSignal) const -> double override
static auto HitCouplingNeuland(const AbstractPaddle &self, const AbstractChannel::Hits &firstSignals, const AbstractChannel::Hits &secondSignals) -> std::vector< ChannelSignalPair >
Simulation of Mock Bar/Paddle.
static const uint8_t DEFAULT_ITERATION
Definition R3BShared.h:169
auto FastExp(const float val) -> float
Definition R3BShared.h:171