Jpp  19.1.0
the software that should make you happy
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 
16 namespace JDETECTOR {}
17 namespace JPP { using namespace JDETECTOR; }
18 
19 namespace 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  */
69  {}
70 
71 
72  /**
73  * Virtual destructor.
74  */
76  {}
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).
84  *
85  * \param calibration PMT calibration
86  * \param input PMT signals
87  * \param output PMT hits
88  */
89  void operator()(const JCalibration& calibration,
90  const JPMTData<JPMTSignal>& input,
91  JPMTData<JPMTPulse>& output) const
92  {
93  // apply transition time distribution to each photo-electron.
94 
96 
97  for (JPMTData<JPMTSignal>::const_iterator hit = input.begin(); hit != input.end(); ++hit) {
98 
99  for (int i = 0; i != hit->npe; ++i) {
100 
101  if (applyQE()) {
102  buffer.push_back(JPhotoElectron(getRandomTime(hit->t_ns)));
103  }
104  }
105  }
106 
107  if (!buffer.empty()) {
108 
109  buffer.push_back(JPhotoElectron::getEndMarker());
110 
111  buffer.sort();
112 
113 
114  // generate PMT hits from time sequence of photo-electrons.
115 
116  for (JPMTData<JPhotoElectron>::const_iterator q = buffer.begin(), p = q++; q != buffer.end(); ++q) {
117 
118  while (compare(*p,*q)) {
119  ++q;
120  }
121 
122  const double npe = getRandomCharge(distance(p,q));
123 
124  if (applyThreshold(npe)) {
125  output.push_back(JPMTPulse(putTime(p->t_ns + getRiseTime(npe), calibration), getTimeOverThreshold(npe)));
126  }
127 
128  p = q;
129  }
130 
131  // merge overlapping PMT hits.
132 
133  merge(output);
134  }
135  }
136 
137 
138  /**
139  * Apply relative QE.
140  * The default implementation returns <tt>true</tt>.
141  *
142  * \return true if accepted; false if rejected
143  */
144  virtual bool applyQE() const
145  {
146  return true;
147  }
148 
149 
150  /**
151  * Get randomised time according transition time distribution.
152  * The default implementation returns the given value.
153  *
154  * \param t_ns time [ns]
155  * \return time [ns]
156  */
157  virtual double getRandomTime(const double t_ns) const
158  {
159  return t_ns;
160  }
161 
162 
163  /**
164  * Compare arrival times of photo-electrons.
165  * The default implementation uses method getTmin as two photo-electron resolution.
166  *
167  * \param first first photo-electron
168  * \param second second photo-electron
169  * \return true if arrival times of photo-electrons are within two photo-electron resolution; else false
170  */
171  virtual bool compare(const JPhotoElectron& first, const JPhotoElectron& second) const
172  {
173  return second.t_ns - first.t_ns <= getTmin();
174  }
175 
176 
177  /**
178  * Get randomised charge according to gain and gain spread.
179  * The default implementation returns the given value.
180  *
181  * \param NPE number of photo-electrons
182  * \return number of photo-electrons
183  */
184  virtual double getRandomCharge(const int NPE) const
185  {
186  return (double) NPE;
187  }
188 
189 
190  /**
191  * Get probability density for given charge.
192  *
193  * \param npe observed number of photo-electrons
194  * \param NPE true number of photo-electrons
195  * \return probability [npe^-1]
196  */
197  virtual double getChargeProbability(const double npe, const int NPE) const
198  {
199  return (fabs(npe - NPE) <= 0.5 * getQmin() ? 1.0 / getQmin() : 0.0);
200  }
201 
202 
203  /**
204  * Apply threshold.
205  * The default implementation returns <tt>true</tt>.
206  *
207  * \param npe number of photo-electrons
208  * \return true if pass; else false
209  */
210  virtual bool applyThreshold(const double npe) const
211  {
212  return (npe > 0.0);
213  }
214 
215 
216  /**
217  * Get time to reach threshold.
218  * The default implementation returns <tt>0</tt>.
219  *
220  * \param npe number of photo-electrons
221  * \return time [ns]
222  */
223  virtual double getRiseTime(const double npe) const
224  {
225  return 0.0;
226  }
227 
228 
229  /**
230  * Get time-over-threshold (ToT).
231  * The default implementation corresponds to a linear relation between the number of photo-electrons and the time-over-threshold.
232  *
233  * \param npe number of photo-electrons
234  * \return ToT [ns]
235  */
236  virtual double getTimeOverThreshold(const double npe) const
237  {
238  return TIME_OVER_THRESHOLD_NS + getTmin() * (round(npe) - 1.0);
239  }
240 
241 
242  /**
243  * Get derivative of number of photo-electrons to time-over-threshold.
244  *
245  * \param npe number of photo-electrons
246  * \return dnpe/dToT [ns^-1]
247  */
248  virtual double getDerivative(const double npe) const
249  {
250  return 1.0 / getTmin();
251  }
252 
253 
254  /**
255  * Probability that a hit survives the simulation of the PMT.
256  * The default implementation returns <tt>1</tt> if given value larger than <tt>0</tt>.
257  *
258  * \param NPE number of photo-electrons
259  * \return probability
260  */
261  virtual double getSurvivalProbability(const int NPE) const
262  {
263  if (NPE > 0)
264  return 1.0;
265  else
266  return 0.0;
267  }
268 
269 
270  /**
271  * Get number of photo-electrons.
272  * The default implementation corresponds to a linear relation between the number of photo-electrons and the time-over-threshold.
273  *
274  * \param tot_ns time over threshold [ns]
275  * \return number of photo-electrons
276  */
277  virtual double getNPE(const double tot_ns) const
278  {
279  return 1.0 + (tot_ns - TIME_OVER_THRESHOLD_NS) / getTmin();
280  }
281 
282 
283  /**
284  * Merging of PMT hits.
285  *
286  * Hits with overlapping time-over-threshold signals should -de facto- be combined.
287  * In this, the leading edge is maintained and the time-over-threshold is
288  * set to the difference between the overall trailing and leading edges.
289  * As a result, the number of PMT hits may be reduced.
290  *
291  * \param data PMT hits (I/O)
292  */
293  virtual void merge(JPMTData<JPMTPulse>& data) const
294  {
295  using namespace std;
296 
297  JPMTData<JPMTPulse>::iterator out = data.begin();
298 
299  for (JPMTData<JPMTPulse>::iterator i = data.begin(); i != data.end(); ) {
300 
301  double t1 = i->t_ns;
302  double t2 = i->t_ns + i->tot_ns;
303 
304  while (++i != data.end() && i->t_ns < t2 + getTmin()) {
305  t2 = max(t2, i->t_ns + i->tot_ns);
306  }
307 
308  out->t_ns = t1;
309  out->tot_ns = t2 - t1;
310 
311  ++out;
312  }
313 
314  data.resize(distance(data.begin(), out));
315  }
316 
317 
318  /**
319  * Get two photo-electron resolution for time-over-threshold
320  *
321  * \return minimal time [ns]
322  */
323  static double getTmin()
324  {
325  return 1.0;
326  }
327 
328 
329  /**
330  * Get width of charge distribution.
331  *
332  * \return width charge distribution [npe]
333  */
334  static double getQmin()
335  {
336  return 1.0e-3;
337  }
338  };
339 
340 
341  /**
342  * Get charge probability.
343  *
344  * \param pmt PMT signal processor
345  * \param npe measured number of photo-electrons
346  * \param NPE expected number of photo-electrons
347  * \param precision precision
348  * \return probability
349  */
351  const double npe,
352  const double NPE,
353  const double precision = 1.0e-4)
354  {
355  int i = (int) (NPE - 5.0 * sqrt(NPE));
356 
357  if (i < 1) {
358  i = 1;
359  }
360 
361  double p = NPE * exp(-NPE) / (double) 1;
362 
363  for (int __i = 1; __i != i; ++__i) {
364  p *= NPE / __i;
365  }
366 
367  double P = 0.0;
368 
369  for (double p0 = 0.0; (p >= p0 || p > precision); ++i, p0 = p, p *= NPE / (double) i) {
370  P += pmt.getChargeProbability(npe, i) * p;
371  }
372 
373  return P;
374  }
375 }
376 
377 #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 getDerivative(const double npe) const
Get derivative of number of photo-electrons to time-over-threshold.
virtual ~JPMTSignalProcessorInterface()
Virtual destructor.
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.
virtual double getSurvivalProbability(const int NPE) const
Probability that a hit survives the simulation of the PMT.
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 putTime(const T &t1, const JCalibration &cal)
Get de-calibrated time.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Definition: JSTDTypes.hh:14
Data structure for PMT digital pulse.
Data structure for single photo-electron.
static JPhotoElectron getEndMarker()
Get end marker.