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