LDMX Software
QIEInputPulse.cxx
Go to the documentation of this file.
1
6#include "TrigScint/QIEInputPulse.h"
7
8#include <cmath>
9#include <iostream>
10
11namespace trigscint {
12
13void QIEInputPulse::AddPulse(float toff, float ampl) {
14 toff_.push_back(toff);
15 ampl_.push_back(ampl);
16}
17
18float QIEInputPulse::Eval(float T) {
19 if (ampl_.size() == 0) return 0;
20 float val = 0;
21 for (int i = 0; i < ampl_.size(); i++) {
22 val += EvalSingle(T, i);
23 }
24 return val;
25}
26
27// Bimoid pulse, made out of difference of two sigmoids parametrized by
28// rt,ft respectively.
29// Parameters:
30// rise = rise time
31// fall = fall time
32Bimoid::Bimoid(float rise, float fall) {
33 rt_ = rise;
34 ft_ = fall;
35}
36
37float Bimoid::EvalSingle(float T, int id) {
38 if (T < toff_[id]) return 0;
39 // Normalization constant
40 float nc = (ft_ - rt_) * log(2) / ampl_[id];
41
42 float y1 = 1 / (1 + exp((toff_[id] - T) / rt_));
43 float y2 = 1 / (1 + exp((toff_[id] - T) / ft_));
44 return ((y1 - y2) / nc);
45}
46
47float Bimoid::Integrate(float T1, float T2) {
48 float val = 0;
49 for (int id = 0; id < ampl_.size(); id++) {
50 if (ampl_[id] > 0 && T2 > toff_[id]) {
51 val += I_Int(T2, id) - I_Int(T1, id);
52 }
53 }
54 return val;
55}
56
57float Bimoid::I_Int(float T, int id) {
58 if (T <= toff_[id]) return 0;
59 // Normalization constant
60 float nc = (ft_ - rt_) * log(2) / ampl_[id];
61
62 float t = T - toff_[id]; // time relative to offset
63
64 float II = // Integral
65 rt_ * log(1 + exp((t - toff_[id]) / rt_)) -
66 ft_ * log(1 + exp((t - toff_[id]) / ft_));
67
68 return II / nc;
69}
70
71float Bimoid::Max(int id) {
72 float a = 0;
73 float b = 50;
74 float mx = (a + b) / 2; // maximum
75
76 while (std::abs(Derivative(mx, id)) >= 1e-5) {
77 if (Derivative(a, id) * Derivative(mx, id) > 0) {
78 a = mx;
79 } else
80 b = mx;
81 mx = (a + b) / 2;
82 }
83 return (mx);
84}
85
86float Bimoid::Derivative(float T, int id) {
87 // Normalization constant
88 float nc = (ft_ - rt_) * log(2) / ampl_[id];
89
90 float T_ = T - toff_[id];
91 float E1 = exp(-T_ / rt_);
92 float E2 = exp(-T_ / ft_);
93
94 float v1 = E1 / (rt_ * pow(1 + E1, 2));
95 float v2 = E2 / (ft_ * pow(1 + E2, 2));
96
97 return ((v1 - v2) / nc); // Actual derivative
98}
99
101
102// A current pulse formed by assuming SiPM as an ideal capacitor which is
103// fed with a constant current.
104// Parameters:
105// k_ = 1/(RC time constant of the capacitor)
106// tmax_ = The charging time of the capacitor
107Expo::Expo(float k, float tmax) {
108 k_ = k;
109 tmax_ = tmax;
110
111 rt_ = (log(9 + exp(-k_ * tmax_)) - log(1 + 9 * exp(-k_ * tmax_))) / k_;
112 ft_ = log(9) / k_;
113}
114
115// Manually set the rise time and fall time of the pulse
116void Expo::SetRiseFall(float rr, float ff) {
117 rt_ = rr;
118 ft_ = ff;
119
120 k_ = log(9) / ft_;
121 tmax_ = (log(9 - exp(-k_ * rt_)) - log(9 * exp(-k_ * rt_) - 1)) / k_;
122}
123
124float Expo::EvalSingle(float t_, int id) {
125 if (id >= ampl_.size()) return 0;
126 if (t_ <= toff_[id]) return 0;
127 if (ampl_[id] == 0) return 0;
128
129 // Normalization constant
130 float nc = ampl_[id] / tmax_;
131 // time relative to the offset
132 float T = t_ - toff_[id];
133 if (T < tmax_) {
134 return (nc * (1 - exp(-k_ * T)));
135 } else {
136 return (nc * (1 - exp(-k_ * tmax_)) * exp(k_ * (tmax_ - T)));
137 }
138 return -1;
139}
140
141float Expo::Max(int id) {
142 // Normalization constant
143 float nc = ampl_[id] / tmax_;
144 return nc * (1 - exp(-k_ * tmax_));
145}
146
147float Expo::Integrate(float T1, float T2) {
148 float val = 0;
149 for (int id = 0; id < ampl_.size(); id++) {
150 if (ampl_[id] > 0 && T2 > toff_[id]) {
151 val += I_Int(T2, id) - I_Int(T1, id);
152 }
153 }
154 return val;
155}
156
157float Expo::Derivative(float T, int id) {
158 if (id >= ampl_.size()) return 0;
159 if (T <= toff_[id]) return 0;
160
161 float t = T - toff_[id];
162 // Normalization constant
163 float nc = ampl_[id] / tmax_;
164
165 if (t <= tmax_) return (nc * k_ * exp(-k_ * t));
166 return (-nc * k_ * (1 - exp(-k_ * tmax_)) * exp(k_ * (tmax_ - t)));
167}
168
169float Expo::I_Int(float T, int id) {
170 if (T <= toff_[id]) return 0;
171 float t = T - toff_[id];
172 // Normalization constant
173 float nc = ampl_[id] / tmax_;
174 if (t < tmax_) return (nc * (k_ * t + exp(-k_ * t) - 1) / k_);
175
176 float c1 = (1 - exp(-k_ * tmax_)) / k_;
177 float c2 = tmax_ - c1 * exp(k_ * (tmax_ - t));
178 return nc * c2;
179}
180
181} // namespace trigscint
float EvalSingle(float T, int id) override
Evaluate the pulse at time T.
float Max(int id) override
maximum of the pulse
Bimoid(float start, float qq)
Constructor.
float Integrate(float T1, float T2) override
Integrate the pulse from T1 to T2.
float ft_
fall time
float Derivative(float T, int id) override
Differentiate pulse at time T.
float rt_
rise time
float I_Int(float T, int id)
Indefinite integral at time T.
float Max(int id) override
maximum of the pulse
float k_
1/RC time constant (for the capacitor)
float I_Int(float T, int id)
Indefinite integral at time T.
float ft_
Fall Time.
float Integrate(float T1, float T2) override
Integrate the pulse from T1 to T2.
Expo()
The default constructor.
float Derivative(float T, int id) override
Differentiate pulse at time T.
void SetRiseFall(float rr, float ff)
Set Rise and Fall time of the pulse.
float rt_
Rise Time.
float tmax_
time when pulse attains maximum
float EvalSingle(float T, int id) override
Evaluate the pulse at time T.
float Eval(float T)
Evaluate the pulse train at time T.
std::vector< float > ampl_
collection of pulse amplitudes
std::vector< float > toff_
collection of pulse time offsets
virtual float EvalSingle(float T, int id)=0
Evaluate the pulse train at time T.
void AddPulse(float toff, float ampl)
To add a pulse to the collection.