Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JFitK40.hh
Go to the documentation of this file.
1 #ifndef __JCALIBRATE_JFITK40__
2 #define __JCALIBRATE_JFITK40__
3 
4 #include "TMath.h"
5 #include "TString.h"
6 #include "TF2.h"
7 #include "TH2.h"
8 #include "TFitResult.h"
9 
10 #include "JROOT/JRootToolkit.hh"
11 #include "JDetector/JModule.hh"
12 #include "JMath/JMathToolkit.hh"
13 #include "JLang/JException.hh"
15 
16 
17 /**
18  * \author mdejong
19  */
20 
21 namespace JCALIBRATE {}
22 namespace JPP { using namespace JCALIBRATE; }
23 
24 namespace JCALIBRATE {
25 
29  using JDETECTOR::JModule;
30 
31 
32  static const double FITK40_QE_MIN = 0.0; //!< Minimal quantum efficiency [unit]
33  static const double FITK40_QE_MAX = 10.0; //!< Maximal quantum efficiency [unit]
34  static const double FITK40_TTS_MIN_NS = 0.0; //!< Minimal transition-time spread [ns]
35  static const double FITK40_TTS_MAX_NS = 3.5; //!< Maximal transition-time spread [ns]
36 
37 
38  /**
39  * Fit parameters for single PMT.
40  */
42  /**
43  * Default constructor.
44  */
46  QE (1.0),
47  TTS(2.0),
48  t0 (0.0)
49  {}
50 
51 
52  Double_t QE; //!< quantum efficiency [unit]
53  Double_t TTS; //!< transition-time spread [ns]
54  Double_t t0; //!< time offset [ns]
55  };
56 
57 
58  /**
59  * Fit parameters for two-fold coincidence rate due to K40.
60  */
62  /**
63  * Default constructor.
64  *
65  * The default parameter values are set to those obtained from a designated simulation
66  * of K40 decays (see http://wiki.km3net.de/index.php/OMGsim_simulations_for_K40_fit).\n
67  * If you change these values, you may also want to change the corresponding values in JK40DefaultSimulator.hh.
68  */
70  Rate_Hz(21.2300), // [Hz]
71  p1 ( 3.3592),
72  p2 (-1.5064),
73  p3 ( 0.2884),
74  p4 ( 1.7771),
75  bg ( 1.0e-3),
76  cc ( 1.0e-3)
77  {}
78 
79 
80  /**
81  * Copy constructor.
82  *
83  * \param data data
84  */
85  JFitK40Parameters(const Double_t* data)
86  {
87  if (data != NULL) {
88  setModelParameters(data);
89  }
90  }
91 
92 
93  /**
94  * Get number of model parameters.
95  *
96  * \return number of parameters
97  */
99  {
100  return sizeof(JFitK40Parameters) / sizeof(Double_t);
101  }
102 
103 
104  /**
105  * Get model parameters.
106  *
107  * \return pointer to parameters
108  */
109  const Double_t* getModelParameters() const
110  {
111  return &Rate_Hz;
112  }
113 
114 
115  /**
116  * Get model parameters.
117  *
118  * \return pointer to parameters
119  */
120  Double_t* getModelParameters()
121  {
122  return &Rate_Hz;
123  }
124 
125 
126  /**
127  * Set model parameters.
128  *
129  * \param data pointer to parameters
130  */
131  void setModelParameters(const Double_t* data)
132  {
133  for (Int_t i = 0; i != getNumberOfModelParameters(); ++i) {
134  getModelParameters()[i] = data[i];
135  }
136  }
137 
138 
139  /**
140  * Get model parameter.
141  *
142  * \param i parameter index
143  * \return parameter value
144  */
145  Double_t getModelParameter(Int_t i) const
146  {
147  return getModelParameters()[i];
148  }
149 
150 
151  /**
152  * Get model parameter.
153  *
154  * \param p pointer to data member
155  * \return parameter index and value
156  */
158  {
159  const Int_t i = &(this->*p) - getModelParameters();
160 
161  return JFitParameter_t(i, getModelParameter(i));
162  }
163 
164 
165  /**
166  * Get model parameter.
167  *
168  * \param pmt PMT number
169  * \param p pointer to data member of PMT parameters
170  * \return parameter index and value
171  */
172  JFitParameter_t getModelParameter(Int_t pmt, Double_t JPMTParameters_t::*p) const
173  {
174  const Int_t i = &(parameters[pmt].*p) - getModelParameters();
175 
176  return JFitParameter_t(i, getModelParameter(i));
177  }
178 
179 
180  /**
181  * Get QE of given PMT.
182  *
183  * \param pmt pmt address
184  * \return QE
185  */
186  Double_t getQE(const int pmt) const
187  {
188  return parameters[pmt].QE;
189  }
190 
191 
192  /**
193  * Set QE of given PMT.
194  *
195  * \param pmt pmt address
196  * \param QE QE
197  */
198  void setQE(const int pmt, const Double_t QE)
199  {
200  parameters[pmt].QE = QE;
201  }
202 
203 
204  /**
205  * Get time resolution of given PMT.
206  *
207  * \param pmt pmt address
208  * \return TTS [ns]
209  */
210  Double_t getTTS(const int pmt) const
211  {
212  return parameters[pmt].TTS;
213  }
214 
215 
216  /**
217  * Set time resolution of given PMT.
218  *
219  * \param pmt pmt address
220  * \param TTS TTS [ns]
221  */
222  void setTTS(const int pmt, const Double_t TTS)
223  {
224  parameters[pmt].TTS = TTS;
225  }
226 
227 
228  /**
229  * Get time offset of given PMT.
230  * Note that the time offset of each PMT is corrected by
231  * the average time offset of all PMTs.
232  *
233  * \param pmt pmt address
234  * \return time offset [ns]
235  */
236  Double_t getT0(const int pmt) const
237  {
238  return parameters[pmt].t0;
239  }
240 
241 
242  /**
243  * Set time offset of given PMT.
244  *
245  * \param pmt pmt address
246  * \param t0 time offset [ns]
247  */
248  void setT0(const int pmt, const Double_t t0)
249  {
250  parameters[pmt].t0 = t0;
251  }
252 
253 
254  // fit parameters
255 
256  Double_t Rate_Hz; //!< maximal coincidence rate [Hz]
257  Double_t p1; //!< angle dependence coincidence rate
258  Double_t p2; //!< angle dependence coincidence rate
259  Double_t p3; //!< angle dependence coincidence rate
260  Double_t p4; //!< angle dependence coincidence rate
261  Double_t bg; //!< remaining constant background
262  Double_t cc; //!< fraction of signal correlated background
263 
265  };
266 
267 
268  /**
269  * Parametrisation of two-fold coincidence rate due to K40 and other radioactive decays.
270  *
271  * Note that for use in ROOT fit operations, the member method JFitK40::getRate is static.\n
272  */
273  struct JFitK40 :
274  public JFitK40Parameters,
275  public TF2,
276  public JModule,
277  public JCombinatorics
278  {
279  /**
280  * Data structure for a pair of addresses.
281  */
283 
284 
285  /**
286  * Constructor.
287  *
288  * \param module detector module
289  * \param xmin minimal x
290  * \param xmax maximal x
291  * \param ymin minimal y
292  * \param ymax maximal y
293  * \param option true = fix average t0; false = free average t0
294  */
295  JFitK40(const JModule& module,
296  const Double_t xmin,
297  const Double_t xmax,
298  const Double_t ymin,
299  const Double_t ymax,
300  const bool option) :
301 
302  TF2("fitk40",
303  JFitK40::getRate,
304  xmin, xmax, ymin, ymax,
306 
307  sigmaK40_ns(0.54)
308  {
309  static_cast<JModule&>(*this) = module;
310 
311  this->configure(module.size());
312 
313  this->sort(JPairwiseComparator(module));
314 
315  index_of_average_t0 = (option ? 0 : -1);
316 
317  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
318  disable[i] = false;
319  }
320  }
321 
322 
323  /**
324  * Get intrinsic K40 arrival time spread.
325  *
326  * \return sigma [ns]
327  */
328  Double_t getSigmaK40() const
329  {
330  return this->sigmaK40_ns;
331  }
332 
333 
334  /**
335  * Set intrinsic K40 arrival time spread.
336  *
337  * \param sigma sigma [ns]
338  */
339  void setSigmaK40(const Double_t sigma)
340  {
341  this->sigmaK40_ns = sigma;
342  }
343 
344 
345  /**
346  * Test PMT status.
347  *
348  * \param pmt pmt address
349  * \return true if given pmt is disabled; else false
350  */
351  bool is_disabled(int pmt) const
352  {
353  return disable[pmt];
354  }
355 
356 
357  /**
358  * Test PMT status.
359  *
360  * \param pmt pmt address
361  * \return true if given pmt is used for average t0; else false
362  */
363  bool is_average_t0(int pmt) const
364  {
365  return pmt == index_of_average_t0;
366  }
367 
368 
369  /**
370  * Get time offset of given PMT.
371  *
372  * Note that if the average time offset is constraint,
373  * the time offset of each PMT is corrected by the average time offset of all PMTs.
374  *
375  * \param pmt pmt address
376  * \return time offset [ns]
377  */
378  Double_t getT0(const int pmt) const
379  {
380  if (index_of_average_t0 == -1) {
381 
382  return JFitK40Parameters::getT0(pmt);
383 
384  } else {
385 
386  if (disable[pmt]) {
387 
388  return parameters[pmt].t0;
389 
390  } else {
391 
392  Int_t n0 = 0; // number of non-fixed t0's
393  Double_t t0 = 0.0; // average of non-fixed t0's
394 
395  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
396  if (!disable[i] && i != index_of_average_t0) {
397  n0 += 1;
398  t0 += parameters[i].t0;
399  }
400  }
401 
402  t0 /= (n0 + 1);
403 
404  if (pmt != index_of_average_t0)
405  return parameters[pmt].t0 - t0;
406  else
407  return -t0;
408  }
409  }
410  }
411 
412 
413  /**
414  * Enable PMT.
415  *
416  * \param pmt pmt address
417  */
418  void enablePMT(const int pmt)
419  {
420  disable[pmt] = false;
421  }
422 
423 
424  /**
425  * Disable PMT.
426  *
427  * Note that if the average time offset is constraint to zero,
428  * the corresponding index may change.
429  *
430  * \param pmt pmt address
431  */
432  void disablePMT(const int pmt)
433  {
434  disable[pmt] = true;
435 
436  if (index_of_average_t0 == pmt) {
437 
440  break;
441  }
442  }
443 
445  THROW(JIndexOutOfRange, "JFitK40::disable PMT: No free index for average t0.");
446  }
447  }
448  }
449 
450 
451  /**
452  * Get cosine of space angle between PMT axes.
453  *
454  * \param pair pair of addresses
455  * \return cosine
456  */
457  double getDot(const pair_type& pair) const
458  {
459  return JMATH::getDot(this->getPMT(pair.first),
460  this->getPMT(pair.second));
461  }
462 
463 
464  /**
465  * Get time resolution of given PMT pair.
466  *
467  * \param pair pair of addresses
468  * \return sigma [ns]
469  */
470  Double_t getSigma(const pair_type& pair) const
471  {
472  return TMath::Sqrt(getTTS(pair.first) * getTTS(pair.first) +
473  getTTS(pair.second) * getTTS(pair.second) +
474  getSigmaK40() * getSigmaK40());
475  }
476 
477 
478  /**
479  * Get time offset of given PMT pair.
480  *
481  * \param pair pair of addresses
482  * \return time offset [ns]
483  */
484  Double_t getT0(const pair_type& pair) const
485  {
486  if (index_of_average_t0 == -1) {
487 
488  return parameters[pair.first].t0 - parameters[pair.second].t0;
489 
490  } else {
491 
492  if (pair.first == index_of_average_t0) {
493 
494  return -parameters[pair.second].t0;
495 
496  } else if (pair.second == index_of_average_t0) {
497 
498  return parameters[pair.first].t0;
499 
500  } else {
501 
502  return parameters[pair.first].t0 - parameters[pair.second].t0;
503  }
504  }
505  }
506 
507 
508  /**
509  * Get K40 coincidence rate as a function of cosine angle between PMT axes.
510  *
511  * \param ct cosine angle between PMT axes
512  * \return rate [Hz]
513  */
514  Double_t getValue(const Double_t ct) const
515  {
516  return Rate_Hz * TMath::Exp(-(p1+p2+p3+p4)) * TMath::Exp(ct*(p1+ct*(p2+ct*(p3+ct*p4))));
517  }
518 
519 
520  /**
521  * Get K40 coincidence rate.
522  *
523  * \param pair pair of addresses
524  * \return rate [Hz]
525  */
526  Double_t getValue(const pair_type& pair) const
527  {
528  const Double_t ct = getDot(pair);
529 
530  return (getValue(ct) *
531  getQE(pair.first) *
532  getQE(pair.second));
533  }
534 
535 
536  /**
537  * Get K40 coincidence rate.
538  *
539  * \param pair pair of addresses
540  * \param dt_ns time difference [ns]
541  * \return rate [Hz/ns]
542  */
543  Double_t getValue(const pair_type& pair, const Double_t dt_ns) const
544  {
545  const Double_t t0 = getT0 (pair);
546  const Double_t sigma = getSigma(pair);
547 
548  return getValue(pair) * TMath::Gaus(dt_ns, t0, sigma, kTRUE);
549  }
550 
551 
552  /**
553  * Fit histogram.
554  *
555  * Note that the PMT parameters which are part of the model are reset before the fit according the status of each PMT and
556  * the obtained fit parameters are copied back to the model parameters after the fit.
557  *
558  * \param h2 ROOT 2D-histogram
559  * \param option fit option
560  */
561  TFitResultPtr operator()(TH2& h2, const std::string& option)
562  {
563  for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
564 
565  parameters[pmt] = JPMTParameters_t();
566 
567  if (disable[pmt]) {
568 
569  parameters[pmt].QE = 0.0;
570 
574 
575  } else {
576 
577  // Note that setting limits to a parameter will also release it
578 
579  if (!isParameterFixed(*this, this->getModelParameter(pmt, &JPMTParameters_t::QE))) {
581  }
582  if (!isParameterFixed(*this, this->getModelParameter(pmt, &JPMTParameters_t::TTS))) {
584  }
585  if (!isParameterFixed(*this, this->getModelParameter(pmt, &JPMTParameters_t::t0))) {
586  setParLimits(*this, this->getModelParameter(pmt, &JPMTParameters_t::t0), h2.GetYaxis()->GetXmin(), h2.GetYaxis()->GetXmax());
587  }
588  }
589  }
590 
591  if (index_of_average_t0 != -1) {
592 
593  this->setT0(index_of_average_t0, 0.0);
594 
596  }
597 
598  this->SetParameters(this->getModelParameters());
599 
600  getInstance() = *this;
601 
602  const TFitResultPtr result = h2.Fit(this, option.c_str());
603 
604  this->setModelParameters(this->GetParameters());
605 
606  return result;
607  }
608 
609 
610  /**
611  * Get K40 coincidence rate as a function of the fit parameters.
612  *
613  * To speed up the calculation, it is assumed that the parameter values do not
614  * change unless also the x[0] value changes (i.e. the index of the PMT pair).
615  *
616  * \param x pointer to data
617  * \param data pointer to parameter values
618  * \return rate [Hz/ns]
619  */
620  static Double_t getRate(const Double_t* x, const Double_t* data)
621  {
622  static int id = -1;
623  static Double_t t0;
624  static Double_t sigma;
625  static Double_t rate;
626 
627  const int ix = (int) x[0];
628  const Double_t dt_ns = x[1];
629 
630  if (ix != id) {
631 
633 
634  const pair_type& pair = getInstance().getPair(ix);
635 
636  t0 = getInstance().getT0 (pair);
637  sigma = getInstance().getSigma(pair);
638  rate = getInstance().getValue(pair);
639  id = ix;
640  }
641 
642  return getInstance().bg + rate * (getInstance().cc + TMath::Gaus(dt_ns, t0, sigma, kTRUE));
643  }
644 
645  private:
646 
647  Double_t sigmaK40_ns; //!< intrinsic K40 arrival time spread [ns]
648  int index_of_average_t0; //!< index of t0 used for average time offset
649  bool disable[NUMBER_OF_PMTS]; //!< disable PMT from fit
650 
651  /**
652  * Default constructor.
653  */
655  {}
656 
657 
658  /**
659  * Get unique instance of fit object.
660  *
661  * \return reference to fit object.
662  */
664  {
665  static JFitK40 object;
666 
667  return object;
668  }
669  };
670 }
671 
672 #endif
Double_t bg
remaining constant background
Definition: JFitK40.hh:261
Double_t TTS
transition-time spread [ns]
Definition: JFitK40.hh:53
const pair_type & getPair(const int index) const
Get pair of indices for given index.
JFitParameter_t getModelParameter(Double_t JFitK40Parameters::*p) const
Get model parameter.
Definition: JFitK40.hh:157
Double_t getT0(const int pmt) const
Get time offset of given PMT.
Definition: JFitK40.hh:378
Double_t getQE(const int pmt) const
Get QE of given PMT.
Definition: JFitK40.hh:186
Exceptions.
void setT0(const int pmt, const Double_t t0)
Set time offset of given PMT.
Definition: JFitK40.hh:248
Auxiliary class to convert pair of indices to unique index and back.
Auxiliary methods for geometrical methods.
void configure(const int numberOfIndices)
Configure.
Data structure for a composite optical module.
Definition: JModule.hh:47
Double_t t0
time offset [ns]
Definition: JFitK40.hh:54
Parametrisation of two-fold coincidence rate due to K40 and other radioactive decays.
Definition: JFitK40.hh:273
Double_t sigmaK40_ns
intrinsic K40 arrival time spread [ns]
Definition: JFitK40.hh:647
Double_t getSigmaK40() const
Get intrinsic K40 arrival time spread.
Definition: JFitK40.hh:328
Double_t QE
quantum efficiency [unit]
Definition: JFitK40.hh:52
void disablePMT(const int pmt)
Disable PMT.
Definition: JFitK40.hh:432
JFitK40()
Default constructor.
Definition: JFitK40.hh:654
Double_t getValue(const pair_type &pair, const Double_t dt_ns) const
Get K40 coincidence rate.
Definition: JFitK40.hh:543
JFitK40Parameters(const Double_t *data)
Copy constructor.
Definition: JFitK40.hh:85
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:633
Double_t getTTS(const int pmt) const
Get time resolution of given PMT.
Definition: JFitK40.hh:210
bool disable[NUMBER_OF_PMTS]
disable PMT from fit
Definition: JFitK40.hh:649
static const double FITK40_QE_MAX
Maximal quantum efficiency [unit].
Definition: JFitK40.hh:33
bool isParameterFixed(TF1 &f1, const Int_t index)
Check if fit parameter is fixed.
TFitResultPtr operator()(TH2 &h2, const std::string &option)
Fit histogram.
Definition: JFitK40.hh:561
void sort(JComparator_t comparator)
Sort address pairs.
Double_t p3
angle dependence coincidence rate
Definition: JFitK40.hh:259
JPMTParameters_t()
Default constructor.
Definition: JFitK40.hh:45
Double_t getT0(const pair_type &pair) const
Get time offset of given PMT pair.
Definition: JFitK40.hh:484
bool is_average_t0(int pmt) const
Test PMT status.
Definition: JFitK40.hh:363
const Double_t * getModelParameters() const
Get model parameters.
Definition: JFitK40.hh:109
Double_t getT0(const int pmt) const
Get time offset of given PMT.
Definition: JFitK40.hh:236
JCombinatorics::pair_type pair_type
Data structure for a pair of addresses.
Definition: JFitK40.hh:282
static Double_t getRate(const Double_t *x, const Double_t *data)
Get K40 coincidence rate as a function of the fit parameters.
Definition: JFitK40.hh:620
Auxiliary data structure for a parameter index and its value.
Auxiliary class to sort pairs of PMT addresses within optical module.
void setModelParameters(const Double_t *data)
Set model parameters.
Definition: JFitK40.hh:131
Double_t getModelParameter(Int_t i) const
Get model parameter.
Definition: JFitK40.hh:145
int index_of_average_t0
index of t0 used for average time offset
Definition: JFitK40.hh:648
JPMTParameters_t parameters[NUMBER_OF_PMTS]
Definition: JFitK40.hh:264
double getDot(const JFirst_t &first, const JSecond_t &second)
Get dot product of objects.
static Int_t getNumberOfModelParameters()
Get number of model parameters.
Definition: JFitK40.hh:98
static JFitK40 & getInstance()
Get unique instance of fit object.
Definition: JFitK40.hh:663
Double_t getValue(const pair_type &pair) const
Get K40 coincidence rate.
Definition: JFitK40.hh:526
double getDot(const pair_type &pair) const
Get cosine of space angle between PMT axes.
Definition: JFitK40.hh:457
JFitParameter_t getModelParameter(Int_t pmt, Double_t JPMTParameters_t::*p) const
Get model parameter.
Definition: JFitK40.hh:172
void setSigmaK40(const Double_t sigma)
Set intrinsic K40 arrival time spread.
Definition: JFitK40.hh:339
Double_t p4
angle dependence coincidence rate
Definition: JFitK40.hh:260
const JPMT & getPMT(const int index) const
Get PMT.
Definition: JModule.hh:141
bool setParLimits(TF1 &f1, const Int_t index, Double_t xmin, Double_t xmax)
Set fit parameter limits.
Fit parameters for single PMT.
Definition: JFitK40.hh:41
static const double FITK40_QE_MIN
Minimal quantum efficiency [unit].
Definition: JFitK40.hh:32
bool is_disabled(int pmt) const
Test PMT status.
Definition: JFitK40.hh:351
void enablePMT(const int pmt)
Enable PMT.
Definition: JFitK40.hh:418
static const double FITK40_TTS_MIN_NS
Minimal transition-time spread [ns].
Definition: JFitK40.hh:34
void setQE(const int pmt, const Double_t QE)
Set QE of given PMT.
Definition: JFitK40.hh:198
Double_t Rate_Hz
maximal coincidence rate [Hz]
Definition: JFitK40.hh:256
bool fixParameter(TF1 &f1, const JFitParameter_t &parameter)
Fix fit parameter.
void setTTS(const int pmt, const Double_t TTS)
Set time resolution of given PMT.
Definition: JFitK40.hh:222
JFitK40(const JModule &module, const Double_t xmin, const Double_t xmax, const Double_t ymin, const Double_t ymax, const bool option)
Constructor.
Definition: JFitK40.hh:295
static const double FITK40_TTS_MAX_NS
Maximal transition-time spread [ns].
Definition: JFitK40.hh:35
Double_t p1
angle dependence coincidence rate
Definition: JFitK40.hh:257
Double_t p2
angle dependence coincidence rate
Definition: JFitK40.hh:258
Double_t getSigma(const pair_type &pair) const
Get time resolution of given PMT pair.
Definition: JFitK40.hh:470
Exception for accessing an index in a collection that is outside of its range.
Definition: JException.hh:90
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Definition: JDAQ.hh:26
Fit parameters for two-fold coincidence rate due to K40.
Definition: JFitK40.hh:61
Double_t getValue(const Double_t ct) const
Get K40 coincidence rate as a function of cosine angle between PMT axes.
Definition: JFitK40.hh:514
Double_t * getModelParameters()
Get model parameters.
Definition: JFitK40.hh:120
Double_t cc
fraction of signal correlated background
Definition: JFitK40.hh:262
JFitK40Parameters()
Default constructor.
Definition: JFitK40.hh:69
Data structure for a composite optical module.