Jpp 20.0.0-27-g39925593c-D
the software that should make you happy
Loading...
Searching...
No Matches
JPMTSignalProcessorInterface.hh
Go to the documentation of this file.
1#ifndef __JDETECTOR__JPMTSIGNALPROCESSORINTERFACE__
2#define __JDETECTOR__JPMTSIGNALPROCESSORINTERFACE__
3
4#include <algorithm>
5#include <cmath>
6#include <limits>
7
10
11
12/**
13 * \author mdejong
14 */
15
16namespace JDETECTOR {}
17namespace JPP { using namespace JDETECTOR; }
18
19namespace JDETECTOR {
20
21 /**
22 * PMT signal processor interface.
23 *
24 * This class supports the implementation of the PMT simulator interface using
25 * an alternative set of virtual methods.
26 * These methods constitute a user interface to the expected performance of a PMT.
27 *
28 * Each photon is converted to a photo-electron using member method getRandomTime().
29 * For this, the data structure JPhotoElectron is used.
30 * Note that the quantum efficiency (QE) of the PMT actually is included in the simulation of the detector response.
31 * A relative QE is applied via method applyQE().
32 * All photo-electrons are then time sorted.
33 * The photo-electrons which simultaneously arrive are merged.
34 * The corresponding condition is defined by member method compare().
35 * The time of the combined signal is determined by the time of the first photo-electron and
36 * the rise time of the analogue pulse to the threshold of the discriminator via method getRiseTime().
37 * In this, the actual amplitude of the combined analogue signal and the calibration of the PMT are taken into account.
38 * The amplitude of the combined analogue signal is simulated using member method getRandomCharge().
39 * For this, the data structure JPMTSignal is used.
40 *
41 * The analogue signals of the PMT are processed by a discriminator.
42 * This discriminator produces a time-over-threshold signal for each analogue signal that passes a preset threshold.
43 * The output signal is described by the time of the leading edge and the length of the time-over-threshold signal.
44 * For this, the data structure JPMTPulse is used.
45 * The determination of the time of the leading edge and the length of the time-over-threshold signal
46 * require a designated model.
47 * The class JPMTAnalogueSignalProcessor provides for an implementation of such a model.
48 *
49 * Overlapping time-over-threshold pulses are merged.
50 * The time of the leading edge is then set to the earliest leading edge and
51 * the time-over-threshold to the difference between
52 * the latest trailing edge and the earliest leading edge.
53 * The merging of hits is implemented in member method merge().
54 *
55 * The default implementation of these virtual methods corresponds to no smearing
56 * and a time-over-threshold value equal to a fixed two photo-electron resolution times the number of photo-electrons.
57 * The width of the charge distribution and the two photo-electron resolution are implemented in methods
58 * getQmin() and getTmin(), respectively.
59 *
60 * For a realistic PMT simulation, the derived class should provide for
61 * an implementation of each of these virtual methods.
62 */
64 public:
65 /**
66 * Default constructor.
67 */
70
71
72 /**
73 * Virtual destructor.
74 */
77
78
79 /**
80 * Process hits.
81 *
82 * Two (or more) photo-electrons are combined if they are comparable according method compare.\n
83 * Two (or more) consecutive hits hits maybe merged (according method merge).\n
84 * A PMT signal with negative number of photo-electrons is not subjected to the quantum efficiency and transit-time distribution.\n
85 * This feature is used to simulate the singles rate of a PMT when the measured QE is zero.
86 *
87 * \param calibration PMT calibration
88 * \param input PMT signals
89 * \param output PMT hits
90 */
91 void operator()(const JCalibration& calibration,
92 const JPMTData<JPMTSignal>& input,
93 JPMTData<JPMTPulse>& output) const
94 {
95 // apply transition time distribution to each photo-electron.
96
98
99 for (JPMTData<JPMTSignal>::const_iterator hit = input.begin(); hit != input.end(); ++hit) {
100
101 for (int i = 0; i < hit->npe; ++i) {
102 if (applyQE()) {
103 buffer.push_back(JPhotoElectron(getRandomTime(hit->t_ns)));
104 }
105 }
106
107 for (int i = 0; i > hit->npe; --i) {
108 buffer.push_back(JPhotoElectron(hit->t_ns));
109 }
110 }
111
112 if (!buffer.empty()) {
113
114 buffer.push_back(JPhotoElectron::getEndMarker());
115
116 buffer.sort();
117
118
119 // generate PMT hits from time sequence of photo-electrons.
120
121 for (JPMTData<JPhotoElectron>::const_iterator q = buffer.begin(), p = q++; q != buffer.end(); ++q) {
122
123 while (compare(*p,*q)) {
124 ++q;
125 }
126
127 const double npe = getRandomCharge(distance(p,q));
128
129 if (applyThreshold(npe)) {
130 output.push_back(JPMTPulse(putTime(p->t_ns + getRiseTime(npe), calibration), getTimeOverThreshold(npe)));
131 }
132
133 p = q;
134 }
135
136 // merge overlapping PMT hits.
137
138 merge(output);
139 }
140 }
141
142
143 /**
144 * Apply relative QE.
145 * The default implementation returns <tt>true</tt>.
146 *
147 * \return true if accepted; false if rejected
148 */
149 virtual bool applyQE() const
150 {
151 return true;
152 }
153
154
155 /**
156 * Get randomised time according transition time distribution.
157 * The default implementation returns the given value.
158 *
159 * \param t_ns time [ns]
160 * \return time [ns]
161 */
162 virtual double getRandomTime(const double t_ns) const
163 {
164 return t_ns;
165 }
166
167
168 /**
169 * Compare arrival times of photo-electrons.
170 * The default implementation uses method getTmin as two photo-electron resolution.
171 *
172 * \param first first photo-electron
173 * \param second second photo-electron
174 * \return true if arrival times of photo-electrons are within two photo-electron resolution; else false
175 */
176 virtual bool compare(const JPhotoElectron& first, const JPhotoElectron& second) const
177 {
178 return second.t_ns - first.t_ns <= getTmin();
179 }
180
181
182 /**
183 * Get randomised charge according to gain and gain spread.
184 * The default implementation returns the given value.
185 *
186 * \param NPE number of photo-electrons
187 * \return number of photo-electrons
188 */
189 virtual double getRandomCharge(const int NPE) const
190 {
191 return (double) NPE;
192 }
193
194
195 /**
196 * Get probability density for given charge.
197 *
198 * \param npe observed number of photo-electrons
199 * \param NPE true number of photo-electrons
200 * \return probability [npe^-1]
201 */
202 virtual double getChargeProbability(const double npe, const int NPE) const
203 {
204 return (fabs(npe - NPE) <= 0.5 * getQmin() ? 1.0 / getQmin() : 0.0);
205 }
206
207
208 /**
209 * Apply threshold.
210 * The default implementation returns <tt>true</tt>.
211 *
212 * \param npe number of photo-electrons
213 * \return true if pass; else false
214 */
215 virtual bool applyThreshold(const double npe) const
216 {
217 return (npe > 0.0);
218 }
219
220
221 /**
222 * Get time to reach threshold.
223 * The default implementation returns <tt>0</tt>.
224 *
225 * \param npe number of photo-electrons
226 * \return time [ns]
227 */
228 virtual double getRiseTime(const double npe) const
229 {
230 return 0.0;
231 }
232
233
234 /**
235 * Get time-over-threshold (ToT).
236 * The default implementation corresponds to a linear relation between the number of photo-electrons and the time-over-threshold.
237 *
238 * \param npe number of photo-electrons
239 * \return ToT [ns]
240 */
241 virtual double getTimeOverThreshold(const double npe) const
242 {
243 return TIME_OVER_THRESHOLD_NS + getTmin() * (round(npe) - 1.0);
244 }
245
246
247 /**
248 * Get derivative of number of photo-electrons to time-over-threshold.
249 *
250 * \param npe number of photo-electrons
251 * \return dnpe/dToT [ns^-1]
252 */
253 virtual double getDerivative(const double npe) const
254 {
255 return 1.0 / getTmin();
256 }
257
258
259 /**
260 * Probability that a hit survives the simulation of the PMT.
261 * The default implementation returns one (zero) if given number of photo-electrons is larger than (less or equal to) zero.\n
262 * The QE is excluded when the option is set to <tt>false</tt>.
263 *
264 * \param NPE number of photo-electrons
265 * \param option include QE
266 * \return probability
267 */
268 virtual double getSurvivalProbability(const int NPE, const bool option = true) const
269 {
270 if (NPE > 0)
271 return 1.0;
272 else
273 return 0.0;
274 }
275
276
277 /**
278 * Get number of photo-electrons.
279 * The default implementation corresponds to a linear relation between the number of photo-electrons and the time-over-threshold.
280 *
281 * \param tot_ns time over threshold [ns]
282 * \return number of photo-electrons
283 */
284 virtual double getNPE(const double tot_ns) const
285 {
286 return 1.0 + (tot_ns - TIME_OVER_THRESHOLD_NS) / getTmin();
287 }
288
289
290 /**
291 * Merging of PMT hits.
292 *
293 * Hits with overlapping time-over-threshold signals should -de facto- be combined.
294 * In this, the leading edge is maintained and the time-over-threshold is
295 * set to the difference between the overall trailing and leading edges.
296 * As a result, the number of PMT hits may be reduced.
297 *
298 * \param data PMT hits (I/O)
299 */
300 virtual void merge(JPMTData<JPMTPulse>& data) const
301 {
302 using namespace std;
303
304 JPMTData<JPMTPulse>::iterator out = data.begin();
305
306 for (JPMTData<JPMTPulse>::iterator i = data.begin(); i != data.end(); ) {
307
308 double t1 = i->t_ns;
309 double t2 = i->t_ns + i->tot_ns;
310
311 while (++i != data.end() && i->t_ns < t2 + getTmin()) {
312 t2 = max(t2, i->t_ns + i->tot_ns);
313 }
314
315 out->t_ns = t1;
316 out->tot_ns = t2 - t1;
317
318 ++out;
319 }
320
321 data.resize(distance(data.begin(), out));
322 }
323
324
325 /**
326 * Get two photo-electron resolution for time-over-threshold
327 *
328 * \return minimal time [ns]
329 */
330 static double getTmin()
331 {
332 return 1.0;
333 }
334
335
336 /**
337 * Get width of charge distribution.
338 *
339 * \return width charge distribution [npe]
340 */
341 static double getQmin()
342 {
343 return 1.0e-3;
344 }
345 };
346
347
348 /**
349 * Get charge probability.
350 *
351 * \param pmt PMT signal processor
352 * \param npe measured number of photo-electrons
353 * \param NPE expected number of photo-electrons
354 * \param precision precision
355 * \return probability
356 */
358 const double npe,
359 const double NPE,
360 const double precision = 1.0e-4)
361 {
362 int i = (int) (NPE - 5.0 * sqrt(NPE));
363
364 if (i < 1) {
365 i = 1;
366 }
367
368 double p = NPE * exp(-NPE) / (double) 1;
369
370 for (int __i = 1; __i != i; ++__i) {
371 p *= NPE / __i;
372 }
373
374 double P = 0.0;
375
376 for (double p0 = 0.0; (p >= p0 || p > precision); ++i, p0 = p, p *= NPE / (double) i) {
377 P += pmt.getChargeProbability(npe, i) * p;
378 }
379
380 return P;
381 }
382}
383
384#endif
Time calibration (including definition of sign of time offset).
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Data structure for time calibration.
Template data structure for PMT I/O.
std::vector< JElement_t >::const_iterator const_iterator
std::vector< JElement_t >::iterator iterator
virtual bool applyQE() const
Apply relative QE.
virtual double getChargeProbability(const double npe, const int NPE) const
Get probability density for given charge.
virtual double getSurvivalProbability(const int NPE, const bool option=true) const
Probability that a hit survives the simulation of the PMT.
virtual double getDerivative(const double npe) const
Get derivative of number of photo-electrons to time-over-threshold.
virtual double getTimeOverThreshold(const double npe) const
Get time-over-threshold (ToT).
virtual double getRandomCharge(const int NPE) const
Get randomised charge according to gain and gain spread.
static double getQmin()
Get width of charge distribution.
virtual bool applyThreshold(const double npe) const
Apply threshold.
virtual bool compare(const JPhotoElectron &first, const JPhotoElectron &second) const
Compare arrival times of photo-electrons.
virtual double getRiseTime(const double npe) const
Get time to reach threshold.
static double getTmin()
Get two photo-electron resolution for time-over-threshold.
virtual double getNPE(const double tot_ns) const
Get number of photo-electrons.
void operator()(const JCalibration &calibration, const JPMTData< JPMTSignal > &input, JPMTData< JPMTPulse > &output) const
Process hits.
virtual double getRandomTime(const double t_ns) const
Get randomised time according transition time distribution.
virtual void merge(JPMTData< JPMTPulse > &data) const
Merging of PMT hits.
file Auxiliary data structures and methods for detector calibration.
Definition JAnchor.hh:12
const double TIME_OVER_THRESHOLD_NS
Specification for time-over-threshold corresponding to a one photo-electron pulse.
double getChargeProbability(const JPMTSignalProcessorInterface &pmt, const double npe, const double NPE, const double precision=1.0e-4)
Get charge probability.
double putTime(const T &t1, const JCalibration &cal)
Get de-calibrated time.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Data structure for PMT digital pulse.
Data structure for single photo-electron.
static JPhotoElectron getEndMarker()
Get end marker.