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