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