Jpp  master_rocky-40-g5f0272dcd
the software that should make you happy
JFitK40.hh
Go to the documentation of this file.
1 #ifndef __JCALIBRATE_JGANDALFK40__
2 #define __JCALIBRATE_JGANDALFK40__
3 
4 #include <vector>
5 #include <map>
6 #include <memory>
7 #include <limits>
8 #include <cmath>
9 
11 
12 #include "JLang/JException.hh"
13 #include "JLang/JManip.hh"
14 
15 #include "Jeep/JMessage.hh"
16 
17 #include "JTools/JRange.hh"
18 
19 #include "JDetector/JModule.hh"
20 
21 #include "JMath/JVectorND.hh"
22 #include "JMath/JMatrixNS.hh"
23 #include "JMath/JMath.hh"
24 #include "JMath/JGauss.hh"
25 #include "JMath/JMathToolkit.hh"
26 
27 #include "JFit/JMEstimator.hh"
28 
30 #include "JCalibrate/JTDC_t.hh"
31 
32 
33 /**
34  * \author mdejong
35  */
36 
37 namespace JCALIBRATE {}
38 namespace JPP { using namespace JCALIBRATE; }
39 
40 namespace JCALIBRATE {
41 
44  using JDETECTOR::JModule;
45  using JMATH::JMath;
46  using JFIT::JMEstimator;
47 
48 
49  /**
50  * Fit options.
51  */
52  enum JOption_t {
53  FIT_PMTS_t = 1, //!< fit parameters of PMTs
54  FIT_PMTS_AND_ANGULAR_DEPENDENCE_t = 2, //!< fit parameters of PMTs and angular dependence of K40 rate
55  FIT_PMTS_AND_BACKGROUND_t = 3, //!< fit parameters of PMTs and background
56  FIT_PMTS_QE_FIXED_t = 4, //!< fit parameters of PMTs with QE fixed
57  FIT_MODEL_t = 5 //!< fit parameters of K40 rate and TTSs of PMTs
58  };
59 
60  static const int INVALID_INDEX = -1; //!< invalid index
61 
62 
63  /**
64  * Data structure for measured coincidence rate of pair of PMTs.
65  */
66  struct rate_type {
67  /**
68  * Default constructor.
69  */
71  dt_ns(0.0),
72  value(0.0),
73  error(0.0)
74  {}
75 
76 
77  /**
78  * Constructor.
79  *
80  * \param dt_ns time difference [ns]
81  * \param value value of rate [Hz/ns]
82  * \param error error of rate [Hz/ns]
83  */
84  rate_type(double dt_ns,
85  double value,
86  double error) :
87  dt_ns(dt_ns),
88  value(value),
89  error(error)
90  {}
91 
92  double dt_ns; //!< time difference [ns]
93  double value; //!< value of rate [Hz/ns]
94  double error; //!< error of rate [Hz/ns]
95  };
96 
97 
98  /**
99  * Data structure for measured coincidence rates of all pairs of PMTs in optical module.
100  */
101  struct data_type :
102  public std::map<pair_type, std::vector<rate_type> >
103  {};
104 
105 
106  /**
107  * Auxiliary class for fit parameter with optional limits.
108  */
109  class JParameter_t :
110  public JMath<JParameter_t>
111  {
112  public:
113  /**
114  * Fit options.
115  */
116  enum FIT_t {
117  FREE_t = 0, //!< free
118  FIXED_t //!< fixed
119  };
120 
121 
122  /**
123  * Type definition for range of parameter values.
124  */
126 
127 
128  /**
129  * Default constructor.
130  */
132  {
133  set(0.0);
134  }
135 
136 
137  /**
138  * Constructor.
139  *
140  * \param value value
141  * \param range range
142  */
143  JParameter_t(const double value,
145  range(range)
146  {
147  set(value);
148  }
149 
150 
151  /**
152  * Negate parameter.
153  *
154  * \return this parameter
155  */
157  {
158  set(-get());
159 
160  return *this;
161  }
162 
163 
164  /**
165  * Add parameter.
166  *
167  * \param parameter parameter
168  * \return this parameter
169  */
170  JParameter_t& add(const JParameter_t& parameter)
171  {
172  set(get() + parameter.get());
173 
174  return *this;
175  }
176 
177 
178  /**
179  * Subtract parameter.
180  *
181  * \param parameter parameter
182  * \return this parameter
183  */
184  JParameter_t& sub(const JParameter_t& parameter)
185  {
186  set(get() - parameter.get());
187 
188  return *this;
189  }
190 
191 
192  /**
193  * Scale parameter.
194  *
195  * \param factor multiplication factor
196  * \return this parameter
197  */
198  JParameter_t& mul(const double factor)
199  {
200  set(get() * factor);
201 
202  return *this;
203  }
204 
205 
206  /**
207  * Scale parameter.
208  *
209  * \param factor division factor
210  * \return this parameter
211  */
212  JParameter_t& div(const double factor)
213  {
214  set(get() / factor);
215 
216  return *this;
217  }
218 
219 
220  /**
221  * Scale parameter.
222  *
223  * \param first first parameter
224  * \param second second parameter
225  * \return this parameter
226  */
227  JParameter_t& mul(const JParameter_t& first, const JParameter_t& second)
228  {
229  set(first.get() * second.get());
230 
231  return *this;
232  }
233 
234 
235  /**
236  * Check if parameter is free.
237  *
238  * \return true if free; else false
239  */
240  bool isFree() const
241  {
242  return option == FREE_t;
243  }
244 
245 
246  /**
247  * Check if parameter is fixed.
248  *
249  * \return true if fixed; else false
250  */
251  bool isFixed() const
252  {
253  return option == FIXED_t;
254  }
255 
256 
257  /**
258  * Check if parameter is bound.
259  *
260  * \return true if bound; else false
261  */
262  bool isBound() const
263  {
264  return range.is_valid();
265  }
266 
267 
268  /**
269  * Set current value.
270  */
271  void set()
272  {
273  option = FREE_t;
274  }
275 
276 
277  /**
278  * Fix current value.
279  */
280  void fix()
281  {
282  option = FIXED_t;
283  }
284 
285 
286  /**
287  * Get value.
288  *
289  * \return value
290  */
291  double get() const
292  {
293  if (isBound())
294  return range.getLowerLimit() + 0.5 * range.getLength() * (sin(value) + 1.0);
295  else
296  return value;
297  }
298 
299 
300  /**
301  * Set value.
302  *
303  * \param value value
304  */
305  void set(const double value)
306  {
307  if (isBound())
308  this->value = asin(2.0 * (range.constrain(value) - range.getLowerLimit()) / range.getLength() - 1.0);
309  else
310  this->value = value;
311 
312  set();
313  }
314 
315 
316  /**
317  * Fix value.
318  *
319  * \param value value
320  */
321  void fix(const double value)
322  {
323  set(value);
324 
325  fix();
326  }
327 
328 
329  /**
330  * Get derivative of value.
331  *
332  * \return derivative of value
333  */
334  double getDerivative() const
335  {
336  if (isBound())
337  return 0.5 * range.getLength() * cos(value);
338  else
339  return 1.0;
340  }
341 
342 
343  /**
344  * Type conversion operator.
345  *
346  * \return value
347  */
348  double operator()() const
349  {
350  return get();
351  }
352 
353 
354  /**
355  * Type conversion operator.
356  *
357  * \return value
358  */
359  operator double() const
360  {
361  return get();
362  }
363 
364 
365  /**
366  * Assignment operator.
367  *
368  * \param value value
369  * \return this parameter
370  */
372  {
373  set(value);
374 
375  return *this;
376  }
377 
378 
379  /**
380  * Read parameter from input stream.
381  *
382  * \param in input stream
383  * \param object parameter
384  * \return input stream
385  */
386  friend inline std::istream& operator>>(std::istream& in, JParameter_t& object)
387  {
388  return in >> object.value;
389  }
390 
391 
392  /**
393  * Write parameter to output stream.
394  *
395  * \param out output stream
396  * \param object parameter
397  * \return output stream
398  */
399  friend inline std::ostream& operator<<(std::ostream& out, const JParameter_t& object)
400  {
401  using namespace std;
402 
403  out << FIXED(12,6) << object.get() << ' '
404  << setw(5) << (object.isFixed() ? "fixed" : " ") << ' ';
405 
406  if (object.isBound()) {
407  out << FIXED(12,6) << object.value << ' ';
408  out << FIXED(12,6) << object.range.getLowerLimit() << ' '
409  << FIXED(12,6) << object.range.getUpperLimit();
410  }
411 
412  return out;
413  }
414 
415 
416  double value = 0.0;
419  };
420 
421 
422  /**
423  * Fit parameters for single PMT.
424  */
426 
427  static constexpr double QE_MIN = 0.0; //!< minimal QE
428  static constexpr double QE_MAX = 2.0; //!< maximal QE
429  static constexpr double TTS_NS = 2.0; //!< start value transition-time spread [ns]
430 
431  /**
432  * Default constructor.
433  */
435  {
436  reset();
437  }
438 
439 
440  /**
441  * Reset.
442  */
443  void reset()
444  {
445  status = true;
446 
447  QE .set(0.0);
448  TTS.set(0.0);
449  t0 .set(0.0);
450  bg .set(0.0);
451  }
452 
453 
454  /**
455  * Get default values.
456  *
457  * \return parameters
458  */
460  {
461  static JPMTParameters_t parameters;
462 
463  parameters.QE.range = JParameter_t::range_type(QE_MIN, QE_MAX);
464 
465  parameters.status = true;
466 
467  parameters.QE .set(1.0);
468  parameters.TTS.set(TTS_NS);
469  parameters.t0 .set(0.0);
470  parameters.bg .set(0.0);
471 
472  return parameters;
473  }
474 
475 
476  /**
477  * Get number of fit parameters.
478  *
479  * \return number of parameters
480  */
481  inline size_t getN() const
482  {
483  return ((QE. isFree() ? 1 : 0) +
484  (TTS.isFree() ? 1 : 0) +
485  (t0 .isFree() ? 1 : 0) +
486  (bg .isFree() ? 1 : 0));
487  }
488 
489 
490  /**
491  * Get index of parameter.
492  *
493  * \param p pointer to data member
494  * \return index
495  */
497  {
498  if (!(this->*p).isFree()) {
499  return INVALID_INDEX;
500  }
501 
502  int N = 0;
503 
504  if (p == &JPMTParameters_t::QE ) { return N; }; if (QE .isFree()) { ++N; }
505  if (p == &JPMTParameters_t::TTS) { return N; }; if (TTS.isFree()) { ++N; }
506  if (p == &JPMTParameters_t::t0 ) { return N; }; if (t0 .isFree()) { ++N; }
507  if (p == &JPMTParameters_t::bg ) { return N; }; if (bg .isFree()) { ++N; }
508 
509  return INVALID_INDEX;
510  }
511 
512 
513  /**
514  * Disable PMT.
515  */
516  void disable()
517  {
518  status = false;
519 
520  QE .fix(0.0);
521  TTS.fix(TTS);
522  t0 .fix(0.0);
523  bg .fix(0.0);
524  }
525 
526 
527  /**
528  * Enable PMT.
529  */
530  void enable()
531  {
532  status = true;
533 
534  QE .set();
535  TTS.set();
536  t0 .set();
537  bg .set();
538  }
539 
540 
541  /**
542  * Write PMT parameters to output stream.
543  *
544  * \param out output stream
545  * \param object PMT parameters
546  * \return output stream
547  */
548  friend inline std::ostream& operator<<(std::ostream& out, const JPMTParameters_t& object)
549  {
550  using namespace std;
551 
552  out << "QE " << FIXED(7,3) << object.QE << endl;
553  out << "TTS " << FIXED(7,3) << object.TTS << endl;
554  out << "t0 " << FIXED(7,3) << object.t0 << endl;
555  out << "bg " << FIXED(7,3) << object.bg << endl;
556 
557  return out;
558  }
559 
560 
561  bool status; //!< status
562  JParameter_t QE; //!< relative quantum efficiency [unit]
563  JParameter_t TTS; //!< transition-time spread [ns]
564  JParameter_t t0; //!< time offset [ns]
565  JParameter_t bg; //!< background [Hz/ns]
566  };
567 
568 
569  /**
570  * Fit parameters for two-fold coincidence rate due to K40.
571  */
573  /**
574  * Default constructor.
575  */
577  {
578  reset();
579  }
580 
581 
582  /**
583  * Reset.
584  */
585  void reset()
586  {
587  R .set(0.0);
588  p1.set(0.0);
589  p2.set(0.0);
590  p3.set(0.0);
591  p4.set(0.0);
592  cc.set(0.0);
593  }
594 
595 
596  JParameter_t R; //!< maximal coincidence rate [Hz]
597  JParameter_t p1; //!< 1st order angle dependence coincidence rate
598  JParameter_t p2; //!< 2nd order angle dependence coincidence rate
599  JParameter_t p3; //!< 3rd order angle dependence coincidence rate
600  JParameter_t p4; //!< 4th order angle dependence coincidence rate
601  JParameter_t cc; //!< fraction of signal correlated background
602  };
603 
604 
605  /**
606  * Fit parameters for two-fold coincidence rate due to K40.
607  */
608  struct JK40Parameters :
610  {
611  /**
612  * Default constructor.
613  */
615  {}
616 
617 
618  /**
619  * Get default values.
620  *
621  * The default parameter values are set to those obtained from a designated simulation
622  * of K40 decays (see http://wiki.km3net.de/index.php/OMGsim_simulations_for_K40_fit).\n
623  * If you change these values, you may also want to change the corresponding values in JK40DefaultSimulator.hh.
624  *
625  * \return parameters
626  */
627  static const JK40Parameters& getInstance()
628  {
629  static JK40Parameters parameters;
630 
631  parameters.R .set(18.460546);
632  parameters.p1.set( 3.0767);
633  parameters.p2.set(-1.2078);
634  parameters.p3.set( 0.9905);
635  parameters.p4.set( 0.9379);
636  parameters.cc.set( 0.0);
637 
638  return parameters;
639  }
640 
641 
642  /**
643  * Get K40 parameters.
644  *
645  * \return K40 parameters
646  */
648  {
649  return static_cast<const JK40Parameters&>(*this);
650  }
651 
652 
653  /**
654  * Set K40 parameters.
655  *
656  * \param parameters K40 parameters
657  */
658  void setK40Parameters(const JK40Parameters_t& parameters)
659  {
660  static_cast<JK40Parameters_t&>(*this) = parameters;
661  }
662 
663 
664  /**
665  * Get number of fit parameters.
666  *
667  * \return number of parameters
668  */
669  inline size_t getN() const
670  {
671  return ((R .isFree() ? 1 : 0) +
672  (p1.isFree() ? 1 : 0) +
673  (p2.isFree() ? 1 : 0) +
674  (p3.isFree() ? 1 : 0) +
675  (p4.isFree() ? 1 : 0) +
676  (cc.isFree() ? 1 : 0));
677  }
678 
679 
680  /**
681  * Get index of parameter.
682  *
683  * \param p pointer to data member
684  * \return index
685  */
687  {
688  if (!(this->*p).isFree()) {
689  return INVALID_INDEX;
690  }
691 
692  int N = 0;
693 
694  if (p == &JK40Parameters::R) { return N; } if (R .isFree()) { ++N; }
695  if (p == &JK40Parameters::p1) { return N; } if (p1.isFree()) { ++N; }
696  if (p == &JK40Parameters::p2) { return N; } if (p2.isFree()) { ++N; }
697  if (p == &JK40Parameters::p3) { return N; } if (p3.isFree()) { ++N; }
698  if (p == &JK40Parameters::p4) { return N; } if (p4.isFree()) { ++N; }
699  if (p == &JK40Parameters::cc) { return N; } if (cc.isFree()) { ++N; }
700 
701  return INVALID_INDEX;
702  }
703 
704 
705  /**
706  * Get K40 coincidence rate as a function of cosine angle between PMT axes.
707  *
708  * \param ct cosine angle between PMT axes
709  * \return rate [Hz]
710  */
711  double getValue(const double ct) const
712  {
713  return R * exp(ct*(p1+ct*(p2+ct*(p3+ct*p4))) - (p1+p2+p3+p4));
714  }
715 
716 
717  /**
718  * Get gradient.
719  *
720  * \param ct cosine angle between PMT axes
721  * \return gradient
722  */
723  const JK40Parameters_t& getGradient(const double ct) const
724  {
725  gradient.reset();
726 
727  const double rate = getValue(ct);
728  const double ct2 = ct * ct;
729 
730  if (R .isFree()) { gradient.R = rate / R; }
731  if (p1.isFree()) { gradient.p1 = rate * ct - rate; }
732  if (p2.isFree()) { gradient.p2 = rate * ct2 - rate; }
733  if (p3.isFree()) { gradient.p3 = rate * ct2 * ct - rate; }
734  if (p4.isFree()) { gradient.p4 = rate * ct2 * ct2 - rate; }
735  if (cc.isFree()) { gradient.cc = rate; }
736 
737  return gradient;
738  }
739 
740  private:
742  };
743 
744 
745  /**
746  * Fit model.
747  *
748  * In the absence of TDC constraints, the average time offset is fixed to zero.
749  */
750  struct JModel :
751  public JK40Parameters,
752  public JModule,
753  public JCombinatorics_t
754  {
758 
759 
760  /**
761  * Auxiliary data structure for derived quantities of a given PMT pair.
762  */
763  struct real_type {
764  double ct; //!< cosine angle between PMT axes
765  double t0; //!< time offset [ns]
766  double sigma; //!< total width [ns]
767  double signal; //!< combined signal
768  double background; //!< combined background
769  };
770 
771 
772  /**
773  * Default constructor.
774  */
776  {}
777 
778 
779  /**
780  * Constructor.
781  *
782  * \param module detector module
783  * \param parameters K40 parameters
784  * \param TDC TDC constraints
785  * \param option option
786  */
787  JModel(const JModule& module,
788  const JK40Parameters& parameters,
789  const JTDC_t::range_type& TDC,
790  const int option) :
791  JModule (module),
792  JCombinatorics_t(module)
793  {
794  setK40Parameters(parameters);
795 
796  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
797  this->parameters[i] = JPMTParameters_t::getInstance();
798  }
799 
800  for (JTDC_t::const_iterator i = TDC.first; i != TDC.second; ++i) {
801 
802  if (i->second != JTDC_t::WILDCARD) {
803 
804  this->parameters[i->second].t0.fix();
805 
806  } else {
807 
808  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
809  this->parameters[i].t0.fix();
810  }
811  }
812  }
813 
814  this->index = (TDC.first == TDC.second ? 0 : INVALID_INDEX);
815 
816  setOption(option);
817  }
818 
819 
820  /**
821  * Constructor.
822  *
823  * \param module detector module
824  * \param parameters K40 parameters
825  */
826  JModel(const JModule& module,
827  const JK40Parameters& parameters) :
828  JModule (module),
829  JCombinatorics_t(module)
830  {
831  setK40Parameters(parameters);
832 
833  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
834  this->parameters[i] = JPMTParameters_t::getInstance();
835  }
836  }
837 
838 
839  /**
840  * Get fit option.
841  *
842  * \return option
843  */
845  {
846  return option;
847  }
848 
849 
850  /**
851  * Set fit option.
852  *
853  * \param option option
854  */
855  inline void setOption(const int option)
856  {
857  switch (option) {
858 
859  case FIT_PMTS_t:
860 
861  R .fix();
862  p1.fix();
863  p2.fix();
864  p3.fix();
865  p4.fix();
866 
867  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
868  parameters[i].bg.fix();
869  }
870 
871  break;
872 
874 
875  R .fix();
876 
877  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
878  parameters[i].bg.fix();
879  }
880 
881  break;
882 
884 
885  R .fix();
886  p1.fix();
887  p2.fix();
888  p3.fix();
889  p4.fix();
890 
891  break;
892 
893  case FIT_PMTS_QE_FIXED_t:
894 
895  R .fix();
896  p1.fix();
897  p2.fix();
898  p3.fix();
899  p4.fix();
900 
901  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
902  parameters[i].QE.fix();
903  parameters[i].bg.fix();
904  }
905 
906  break;
907 
908  case FIT_MODEL_t:
909 
910  cc.fix();
911 
912  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
913  parameters[i].QE.fix();
914  parameters[i].t0.fix();
915  parameters[i].bg.fix();
916  }
917 
918  break;
919 
920  default:
921 
922  THROW(JValueOutOfRange, "Invalid option " << option);
923  }
924 
925  this->option = static_cast<JOption_t>(option);
926  }
927 
928 
929  /**
930  * Check if time offset is fixed.
931  *
932  * \return true if time offset fixed; else false
933  */
934  bool hasFixedTimeOffset() const
935  {
936  return index != INVALID_INDEX;
937  }
938 
939 
940  /**
941  * Get time offset.
942  *
943  * \return time offset
944  */
945  double getFixedTimeOffset() const
946  {
947  double t0 = 0.0;
948  size_t N = 0;
949 
950  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
951  if (parameters[i].t0.isFree()) {
952  t0 += parameters[i].t0;
953  N += 1;
954  }
955  }
956 
957  return t0 /= N;
958  }
959 
960 
961  /**
962  * Get index of PMT used for fixed time offset.
963  *
964  * \return index
965  */
966  int getIndex() const
967  {
968  return index;
969  }
970 
971 
972  /**
973  * Set index of PMT used for fixed time offset.
974  */
975  void setIndex()
976  {
977  if (index != INVALID_INDEX) {
978 
979  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
980 
981  if (parameters[i].status) {
982 
983  index = i;
984 
985  parameters[index].t0.fix();
986 
987  return;
988  }
989  }
990 
991  THROW(JValueOutOfRange, "No valid index.");
992  }
993  }
994 
995 
996  /**
997  * Get number of fit parameters.
998  *
999  * \return number of parameters
1000  */
1001  inline size_t getN() const
1002  {
1003  size_t N = JK40Parameters::getN();
1004 
1005  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1006  N += parameters[i].getN();
1007  }
1008 
1009  return N;
1010  }
1011 
1012 
1013  /**
1014  * Get index of parameter.
1015  *
1016  * \param pmt PMT
1017  * \return index
1018  */
1019  int getIndex(int pmt) const
1020  {
1021  int N = JK40Parameters::getN();
1022 
1023  for (int i = 0; i != pmt; ++i) {
1024  N += parameters[i].getN();
1025  }
1026 
1027  return N;
1028  }
1029 
1030 
1031  /**
1032  * Get index of parameter.
1033  *
1034  * \param pmt PMT
1035  * \param p pointer to data member
1036  * \return index
1037  */
1038  int getIndex(int pmt, JParameter_t JPMTParameters_t::*p) const
1039  {
1040  return getIndex(pmt) + parameters[pmt].getIndex(p);
1041  }
1042 
1043 
1044  /**
1045  * Get intrinsic K40 arrival time spread.
1046  *
1047  * \return sigma [ns]
1048  */
1049  double getSigmaK40() const
1050  {
1051  return this->sigmaK40_ns;
1052  }
1053 
1054 
1055  /**
1056  * Set intrinsic K40 arrival time spread.
1057  *
1058  * \param sigma sigma [ns]
1059  */
1060  void setSigmaK40(const double sigma)
1061  {
1062  this->sigmaK40_ns = sigma;
1063  }
1064 
1065 
1066  /**
1067  * Get derived parameters.
1068  *
1069  * \param pair PMT pair
1070  * \return parameters
1071  */
1072  const real_type& getReal(const pair_type& pair) const
1073  {
1074  real.ct = JPP::getDot((*this)[pair.first].getDirection(), (*this)[pair.second].getDirection());
1075 
1076  real.t0 = (pair.first == this->index ? -this->parameters[pair.second].t0() :
1077  pair.second == this->index ? +this->parameters[pair.first ].t0() :
1078  this->parameters[pair.first].t0() - this->parameters[pair.second].t0());
1079 
1080  real.sigma = sqrt(this->parameters[pair.first ].TTS() * this->parameters[pair.first ].TTS() +
1081  this->parameters[pair.second].TTS() * this->parameters[pair.second].TTS() +
1082  this->getSigmaK40() * this->getSigmaK40());
1083 
1084  real.signal = this->parameters[pair.first].QE() * this->parameters[pair.second].QE();
1085 
1086  real.background = this->parameters[pair.first].bg() + this->parameters[pair.second].bg();
1087 
1088  return real;
1089  }
1090 
1091 
1092  /**
1093  * Get K40 coincidence rate.
1094  *
1095  * \param pair PMT pair
1096  * \param dt_ns time difference [ns]
1097  * \return rate [Hz/ns]
1098  */
1099  double getValue(const pair_type& pair, const double dt_ns) const
1100  {
1101  using namespace std;
1102  using namespace JPP;
1103 
1104  const real_type& real = getReal(pair);
1105 
1106  const JGauss gauss(real.t0, real.sigma, real.signal);
1107 
1108  const double R1 = this->getValue(real.ct);
1109  const double R2 = gauss.getValue(dt_ns);
1110 
1111  return real.background + R1 * (cc() + R2);
1112  }
1113 
1114 
1115  /**
1116  * Get K40 coincidence rate.
1117  *
1118  * \param pair PMT pair
1119  * \return rate [Hz]
1120  */
1121  double getValue(const pair_type& pair) const
1122  {
1123  using namespace std;
1124  using namespace JPP;
1125 
1126  const real_type& real = getReal(pair);
1127 
1128  const double R1 = this->getValue(real.ct);
1129  const double R2 = real.signal;
1130 
1131  return real.background + R1 * (cc() + R2);
1132  }
1133 
1134 
1135  /**
1136  * Write model parameters to output stream.
1137  *
1138  * \param out output stream
1139  * \param object model parameters
1140  * \return output stream
1141  */
1142  friend inline std::ostream& operator<<(std::ostream& out, const JModel& object)
1143  {
1144  using namespace std;
1145 
1146  out << "Module " << setw(10) << object.getID() << endl;
1147  out << "option " << object.option << endl;
1148  out << "index " << object.index << endl;
1149  out << "Rate [Hz] " << FIXED(12,6) << object.R << endl;
1150  out << "p1 " << FIXED(12,6) << object.p1 << endl;
1151  out << "p2 " << FIXED(12,6) << object.p2 << endl;
1152  out << "p3 " << FIXED(12,6) << object.p3 << endl;
1153  out << "p4 " << FIXED(12,6) << object.p4 << endl;
1154  out << "cc " << FIXED(12,6) << object.cc << endl;
1155 
1156  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1157  out << "PMT[" << FILL(2,'0') << i << FILL() << "]." << object.parameters[i].status << endl << object.parameters[i];
1158  }
1159 
1160  return out;
1161  }
1162 
1164 
1165  private:
1166  int index; //!< index of PMT used for fixed time offset
1167  double sigmaK40_ns = 0.54; //!< intrinsic K40 arrival time spread [ns]
1169  mutable real_type real;
1170  };
1171 
1172 
1173  /**
1174  * Fit.
1175  */
1176  class JFit
1177  {
1178  public:
1179  /**
1180  * Result type.
1181  */
1182  struct result_type {
1183  double chi2;
1184  int ndf;
1185  };
1186 
1187  typedef std::shared_ptr<JMEstimator> estimator_type;
1188 
1189 
1190  /**
1191  * Constructor
1192  *
1193  * \param option M-estimator
1194  * \param debug debug
1195  */
1196  JFit(const int option, const int debug) :
1197  debug(debug)
1198  {
1199  using namespace JPP;
1200 
1201  estimator.reset(getMEstimator(option));
1202  }
1203 
1204 
1205  /**
1206  * Fit.
1207  *
1208  * \param data data
1209  * \return chi2, NDF
1210  */
1212  {
1213  using namespace std;
1214  using namespace JPP;
1215 
1216 
1217  value.setIndex();
1218 
1219  const size_t N = value.getN();
1220 
1221  V.resize(N);
1222  Y.resize(N);
1223  h.resize(N);
1224 
1225  int ndf = 0;
1226 
1227  for (data_type::const_iterator ix = data.begin(); ix != data.end(); ++ix) {
1228 
1229  const pair_type& pair = ix->first;
1230 
1231  if (value.parameters[pair.first ].status &&
1232  value.parameters[pair.second].status) {
1233 
1234  ndf += ix->second.size();
1235  }
1236  }
1237 
1238  ndf -= value.getN();
1239 
1240 
1241  lambda = LAMBDA_MIN;
1242 
1243  double precessor = numeric_limits<double>::max();
1244 
1245  for (numberOfIterations = 0; numberOfIterations != MAXIMUM_ITERATIONS; ++numberOfIterations) {
1246 
1247  DEBUG("step: " << numberOfIterations << endl);
1248 
1249  evaluate(data);
1250 
1251  DEBUG("lambda: " << FIXED(12,5) << lambda << endl);
1252  DEBUG("chi2: " << FIXED(12,3) << successor << endl);
1253 
1254  if (successor < precessor) {
1255 
1256  if (numberOfIterations != 0) {
1257 
1258  if (fabs(precessor - successor) < EPSILON*fabs(precessor)) {
1259  return { successor / estimator->getRho(1.0), ndf };
1260  }
1261 
1262  if (lambda > LAMBDA_MIN) {
1263  lambda /= LAMBDA_DOWN;
1264  }
1265  }
1266 
1267  precessor = successor;
1268  previous = value;
1269 
1270  } else {
1271 
1272  value = previous;
1273  lambda *= LAMBDA_UP;
1274 
1275  if (lambda > LAMBDA_MAX) {
1276  return { precessor / estimator->getRho(1.0), ndf }; // no improvement found
1277  }
1278 
1279  evaluate(data);
1280  }
1281 
1282  if (debug >= debug_t) {
1283 
1284  size_t row = 0;
1285 
1286  if (value.R .isFree()) { cout << "R " << FIXED(12,5) << Y[row] << endl; ++row; }
1287  if (value.p1.isFree()) { cout << "p1 " << FIXED(12,5) << Y[row] << endl; ++row; }
1288  if (value.p2.isFree()) { cout << "p2 " << FIXED(12,5) << Y[row] << endl; ++row; }
1289  if (value.p3.isFree()) { cout << "p3 " << FIXED(12,5) << Y[row] << endl; ++row; }
1290  if (value.p4.isFree()) { cout << "p4 " << FIXED(12,5) << Y[row] << endl; ++row; }
1291  if (value.cc.isFree()) { cout << "cc " << FIXED(12,3) << Y[row] << endl; ++row; }
1292 
1293  for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1294  if (value.parameters[pmt].QE .isFree()) { cout << "PMT[" << setw(2) << pmt << "].QE " << FIXED(12,5) << Y[row] << endl; ++row; }
1295  if (value.parameters[pmt].TTS.isFree()) { cout << "PMT[" << setw(2) << pmt << "].TTS " << FIXED(12,5) << Y[row] << endl; ++row; }
1296  if (value.parameters[pmt].t0 .isFree()) { cout << "PMT[" << setw(2) << pmt << "].t0 " << FIXED(12,5) << Y[row] << endl; ++row; }
1297  if (value.parameters[pmt].bg .isFree()) { cout << "PMT[" << setw(2) << pmt << "].bg " << FIXED(12,5) << Y[row] << endl; ++row; }
1298  }
1299  }
1300 
1301  // force definite positiveness
1302 
1303  for (size_t i = 0; i != N; ++i) {
1304 
1305  if (V(i,i) < PIVOT) {
1306  V(i,i) = PIVOT;
1307  }
1308 
1309  h[i] = 1.0 / sqrt(V(i,i));
1310  }
1311 
1312  // normalisation
1313 
1314  for (size_t i = 0; i != N; ++i) {
1315  for (size_t j = 0; j != i; ++j) {
1316  V(j,i) *= h[i] * h[j];
1317  V(i,j) = V(j,i);
1318  }
1319  }
1320 
1321  for (size_t i = 0; i != N; ++i) {
1322  V(i,i) = 1.0 + lambda;
1323  }
1324 
1325  // solve A x = b
1326 
1327  for (size_t col = 0; col != N; ++col) {
1328  Y[col] *= h[col];
1329  }
1330 
1331  try {
1332  V.solve(Y);
1333  }
1334  catch (const exception& error) {
1335 
1336  ERROR("JGandalf: " << error.what() << endl << V << endl);
1337 
1338  break;
1339  }
1340 
1341  // update value
1342 
1343  const double factor = 2.0;
1344 
1345  size_t row = 0;
1346 
1347  if (value.R .isFree()) { value.R -= factor * h[row] * Y[row]; ++row; }
1348  if (value.p1.isFree()) { value.p1 -= factor * h[row] * Y[row]; ++row; }
1349  if (value.p2.isFree()) { value.p2 -= factor * h[row] * Y[row]; ++row; }
1350  if (value.p3.isFree()) { value.p3 -= factor * h[row] * Y[row]; ++row; }
1351  if (value.p4.isFree()) { value.p4 -= factor * h[row] * Y[row]; ++row; }
1352  if (value.cc.isFree()) { value.cc -= factor * h[row] * Y[row]; ++row; }
1353 
1354  for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1355  if (value.parameters[pmt].QE .isFree()) { value.parameters[pmt].QE -= factor * h[row] * Y[row]; ++row; }
1356  if (value.parameters[pmt].TTS.isFree()) { value.parameters[pmt].TTS -= factor * h[row] * Y[row]; ++row; }
1357  if (value.parameters[pmt].t0 .isFree()) { value.parameters[pmt].t0 -= factor * h[row] * Y[row]; ++row; }
1358  if (value.parameters[pmt].bg .isFree()) { value.parameters[pmt].bg -= factor * h[row] * Y[row]; ++row; }
1359  }
1360  }
1361 
1362  return { precessor / estimator->getRho(1.0), ndf };
1363  }
1364 
1365 
1366  static constexpr int MAXIMUM_ITERATIONS = 10000; //!< maximal number of iterations.
1367  static constexpr double EPSILON = 1.0e-5; //!< maximal distance to minimum.
1368  static constexpr double LAMBDA_MIN = 0.01; //!< minimal value control parameter
1369  static constexpr double LAMBDA_MAX = 100.0; //!< maximal value control parameter
1370  static constexpr double LAMBDA_UP = 10.0; //!< multiplication factor control parameter
1371  static constexpr double LAMBDA_DOWN = 10.0; //!< multiplication factor control parameter
1372  static constexpr double PIVOT = std::numeric_limits<double>::epsilon(); //!< minimal value diagonal element of matrix
1373 
1374  int debug;
1375  estimator_type estimator; //!< M-Estimator function
1376 
1377  double lambda;
1381 
1382  private:
1383  /**
1384  * Evaluation of fit.
1385  *
1386  * \param data data
1387  */
1388  void evaluate(const data_type& data)
1389  {
1390  using namespace std;
1391  using namespace JPP;
1392 
1393  typedef JModel::real_type real_type;
1394 
1395 
1396  successor = 0.0;
1397 
1398  V.reset();
1399  Y.reset();
1400 
1401 
1402  // model parameter indices
1403 
1404  const struct M_t {
1405  M_t(const JModel& model)
1406  {
1407  R = model.getIndex(&JK40Parameters_t::R);
1408  p1 = model.getIndex(&JK40Parameters_t::p1);
1409  p2 = model.getIndex(&JK40Parameters_t::p2);
1410  p3 = model.getIndex(&JK40Parameters_t::p3);
1411  p4 = model.getIndex(&JK40Parameters_t::p4);
1412  cc = model.getIndex(&JK40Parameters_t::cc);
1413  }
1414 
1415  int R;
1416  int p1;
1417  int p2;
1418  int p3;
1419  int p4;
1420  int cc;
1421 
1422  } M(value);
1423 
1424 
1425  // PMT parameter indices
1426 
1427  struct I_t {
1428  I_t(const JModel& model, const int pmt) :
1429  QE (INVALID_INDEX),
1430  TTS(INVALID_INDEX),
1431  t0 (INVALID_INDEX),
1432  bg (INVALID_INDEX)
1433  {
1434  const int index = model.getIndex(pmt);
1435 
1436  int N = 0;
1437 
1438  if (model.parameters[pmt].QE .isFree()) { QE = index + N; ++N; }
1439  if (model.parameters[pmt].TTS.isFree()) { TTS = index + N; ++N; }
1440  if (model.parameters[pmt].t0 .isFree()) { t0 = index + N; ++N; }
1441  if (model.parameters[pmt].bg .isFree()) { bg = index + N; ++N; }
1442  }
1443 
1444  int QE;
1445  int TTS;
1446  int t0;
1447  int bg;
1448  };
1449 
1450 
1452 
1453  buffer_type buffer;
1454 
1455  for (data_type::const_iterator ix = data.begin(); ix != data.end(); ++ix) {
1456 
1457  const pair_type& pair = ix->first;
1458 
1459  if (value.parameters[pair.first ].status &&
1460  value.parameters[pair.second].status) {
1461 
1462  const real_type& real = value.getReal(pair);
1463 
1464  const JGauss gauss(real.t0, real.sigma, real.signal);
1465 
1466  const double R1 = value.getValue (real.ct);
1467  const JK40Parameters_t& R1p = value.getGradient(real.ct);
1468 
1469  const std::pair<I_t, I_t> PMT(I_t(value, pair.first),
1470  I_t(value, pair.second));
1471 
1472  for (const rate_type& iy : ix->second) {
1473 
1474  const double R2 = gauss.getValue (iy.dt_ns);
1475  const JGauss& R2p = gauss.getGradient(iy.dt_ns);
1476 
1477  const double R = real.background + R1 * (value.cc() + R2);
1478  const double u = (iy.value - R) / iy.error;
1479  const double w = -estimator->getPsi(u) / iy.error;
1480 
1481  successor += estimator->getRho(u);
1482 
1483  buffer.clear();
1484 
1485  if (M.R != INVALID_INDEX) { buffer.push_back({M.R, w * (value.cc() + R2) * R1p.R () * value.R .getDerivative()}); }
1486  if (M.p1 != INVALID_INDEX) { buffer.push_back({M.p1, w * (value.cc() + R2) * R1p.p1() * value.p1.getDerivative()}); }
1487  if (M.p2 != INVALID_INDEX) { buffer.push_back({M.p2, w * (value.cc() + R2) * R1p.p2() * value.p2.getDerivative()}); }
1488  if (M.p3 != INVALID_INDEX) { buffer.push_back({M.p3, w * (value.cc() + R2) * R1p.p3() * value.p3.getDerivative()}); }
1489  if (M.p4 != INVALID_INDEX) { buffer.push_back({M.p4, w * (value.cc() + R2) * R1p.p4() * value.p4.getDerivative()}); }
1490  if (M.cc != INVALID_INDEX) { buffer.push_back({M.cc, w * R1 * R1p.cc() * value.cc.getDerivative()}); }
1491 
1492  if (PMT.first .QE != INVALID_INDEX) { buffer.push_back({PMT.first .QE , w * R1 * R2p.signal * value.parameters[pair.second].QE () * value.parameters[pair.first ].QE .getDerivative()}); }
1493  if (PMT.second.QE != INVALID_INDEX) { buffer.push_back({PMT.second.QE , w * R1 * R2p.signal * value.parameters[pair.first ].QE () * value.parameters[pair.second].QE .getDerivative()}); }
1494  if (PMT.first .TTS != INVALID_INDEX) { buffer.push_back({PMT.first .TTS, w * R1 * R2p.sigma * value.parameters[pair.first ].TTS() * value.parameters[pair.first ].TTS.getDerivative() / real.sigma}); }
1495  if (PMT.second.TTS != INVALID_INDEX) { buffer.push_back({PMT.second.TTS, w * R1 * R2p.sigma * value.parameters[pair.second].TTS() * value.parameters[pair.second].TTS.getDerivative() / real.sigma}); }
1496  if (PMT.first .t0 != INVALID_INDEX) { buffer.push_back({PMT.first .t0, w * R1 * R2p.mean * value.parameters[pair.first ].t0 .getDerivative() * +1.0}); }
1497  if (PMT.second.t0 != INVALID_INDEX) { buffer.push_back({PMT.second.t0, w * R1 * R2p.mean * value.parameters[pair.second].t0 .getDerivative() * -1.0}); }
1498  if (PMT.first .bg != INVALID_INDEX) { buffer.push_back({PMT.first .bg, w * value.parameters[pair.first ].bg .getDerivative()}); }
1499  if (PMT.second.bg != INVALID_INDEX) { buffer.push_back({PMT.second.bg, w * value.parameters[pair.second].bg .getDerivative()}); }
1500 
1501  for (buffer_type::const_iterator row = buffer.begin(); row != buffer.end(); ++row) {
1502 
1503  Y[row->first] += row->second;
1504 
1505  V[row->first][row->first] += row->second * row->second;
1506 
1507  for (buffer_type::const_iterator col = buffer.begin(); col != row; ++col) {
1508  V[row->first][col->first] += row->second * col->second;
1509  V[col->first][row->first] = V[row->first][col->first];
1510  }
1511  }
1512  }
1513  }
1514  }
1515  }
1516 
1517  JMATH::JVectorND Y; // gradient
1518  double successor;
1520  std::vector<double> h; // normalisation vector
1521  };
1522 }
1523 
1524 #endif
1525 
1526 
JDAQPMTIdentifier PMT
Command line options.
KM3NeT DAQ constants, bit handling, etc.
TPaveText * p1
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
Maximum likelihood estimator (M-estimators).
I/O manipulators.
Auxiliary methods for geometrical methods.
Base class for data structures with artithmetic capabilities.
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
#define ERROR(A)
Definition: JMessage.hh:66
int debug
debug level
Definition: JSirene.cc:69
Data structure for optical module.
Auxiliary class to define a range between two values.
std::vector< double > h
Definition: JFitK40.hh:1520
result_type operator()(const data_type &data)
Fit.
Definition: JFitK40.hh:1211
int numberOfIterations
Definition: JFitK40.hh:1379
JMATH::JMatrixNS V
Definition: JFitK40.hh:1380
JFit(const int option, const int debug)
Constructor.
Definition: JFitK40.hh:1196
std::shared_ptr< JMEstimator > estimator_type
Definition: JFitK40.hh:1187
void evaluate(const data_type &data)
Evaluation of fit.
Definition: JFitK40.hh:1388
double successor
Definition: JFitK40.hh:1518
estimator_type estimator
M-Estimator function.
Definition: JFitK40.hh:1375
JMATH::JVectorND Y
Definition: JFitK40.hh:1517
Auxiliary class for fit parameter with optional limits.
Definition: JFitK40.hh:111
JParameter_t & div(const double factor)
Scale parameter.
Definition: JFitK40.hh:212
JParameter_t & operator=(double value)
Assignment operator.
Definition: JFitK40.hh:371
void set(const double value)
Set value.
Definition: JFitK40.hh:305
friend std::istream & operator>>(std::istream &in, JParameter_t &object)
Read parameter from input stream.
Definition: JFitK40.hh:386
void fix()
Fix current value.
Definition: JFitK40.hh:280
JParameter_t & negate()
Negate parameter.
Definition: JFitK40.hh:156
bool isFree() const
Check if parameter is free.
Definition: JFitK40.hh:240
friend std::ostream & operator<<(std::ostream &out, const JParameter_t &object)
Write parameter to output stream.
Definition: JFitK40.hh:399
double operator()() const
Type conversion operator.
Definition: JFitK40.hh:348
void set()
Set current value.
Definition: JFitK40.hh:271
JParameter_t(const double value, const range_type &range=range_type::DEFAULT_RANGE())
Constructor.
Definition: JFitK40.hh:143
JParameter_t & mul(const double factor)
Scale parameter.
Definition: JFitK40.hh:198
JParameter_t()
Default constructor.
Definition: JFitK40.hh:131
JParameter_t & mul(const JParameter_t &first, const JParameter_t &second)
Scale parameter.
Definition: JFitK40.hh:227
double getDerivative() const
Get derivative of value.
Definition: JFitK40.hh:334
JParameter_t & sub(const JParameter_t &parameter)
Subtract parameter.
Definition: JFitK40.hh:184
JParameter_t & add(const JParameter_t &parameter)
Add parameter.
Definition: JFitK40.hh:170
void fix(const double value)
Fix value.
Definition: JFitK40.hh:321
double get() const
Get value.
Definition: JFitK40.hh:291
JTOOLS::JRange< double > range_type
Type definition for range of parameter values.
Definition: JFitK40.hh:125
bool isBound() const
Check if parameter is bound.
Definition: JFitK40.hh:262
bool isFixed() const
Check if parameter is fixed.
Definition: JFitK40.hh:251
Data structure for a composite optical module.
Definition: JModule.hh:75
Exception for accessing a value in a collection that is outside of its range.
Definition: JException.hh:180
int getIndex(const int first, const int second) const
Get index of pair of indices.
bool is_valid() const
Check validity of range.
Definition: JRange.hh:311
T getLength() const
Get length (difference between upper and lower limit).
Definition: JRange.hh:289
T constrain(argument_type x) const
Constrain value to range.
Definition: JRange.hh:350
T getLowerLimit() const
Get lower limit.
Definition: JRange.hh:202
static JRange< double, std::less< double > > DEFAULT_RANGE()
Default range.
Definition: JRange.hh:555
#define R1(x)
const double sigma[]
Definition: JQuadrature.cc:74
const double epsilon
Definition: JQuadrature.cc:21
double getDot(const JNeutrinoDirection &first, const JNeutrinoDirection &second)
Dot product.
Definition: JAstronomy.hh:676
Auxiliary classes and methods for PMT calibration.
static const int INVALID_INDEX
invalid index
Definition: JFitK40.hh:60
JOption_t
Fit options.
Definition: JFitK40.hh:52
@ FIT_PMTS_QE_FIXED_t
fit parameters of PMTs with QE fixed
Definition: JFitK40.hh:56
@ FIT_PMTS_AND_ANGULAR_DEPENDENCE_t
fit parameters of PMTs and angular dependence of K40 rate
Definition: JFitK40.hh:54
@ FIT_MODEL_t
fit parameters of K40 rate and TTSs of PMTs
Definition: JFitK40.hh:57
@ FIT_PMTS_AND_BACKGROUND_t
fit parameters of PMTs and background
Definition: JFitK40.hh:55
@ FIT_PMTS_t
fit parameters of PMTs
Definition: JFitK40.hh:53
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
Definition: JScale.hh:47
@ debug_t
debug
Definition: JMessage.hh:29
JMEstimator * getMEstimator(const int type)
Get M-Estimator.
Definition: JMEstimator.hh:203
int getIndex()
Get index for user I/O manipulation.
Definition: JManip.hh:26
double gauss(const double x, const double sigma)
Gauss function (normalised to 1 at x = 0).
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
std::vector< JHitW0 > buffer_type
hits
Definition: JPerth.cc:71
data_type w[N+1][M+1]
Definition: JPolint.hh:867
double u[N+1]
Definition: JPolint.hh:865
int j
Definition: JPolint.hh:792
void reset(T &value)
Reset value.
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Definition: JDAQ.hh:26
Definition: JSTDTypes.hh:14
Auxiliary data structure for sequence of same character.
Definition: JManip.hh:330
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:448
PMT combinatorics for optical module.
Fit parameters for two-fold coincidence rate due to K40.
Definition: JFitK40.hh:572
JParameter_t R
maximal coincidence rate [Hz]
Definition: JFitK40.hh:596
JParameter_t p1
1st order angle dependence coincidence rate
Definition: JFitK40.hh:597
JParameter_t p2
2nd order angle dependence coincidence rate
Definition: JFitK40.hh:598
JParameter_t p3
3rd order angle dependence coincidence rate
Definition: JFitK40.hh:599
JParameter_t p4
4th order angle dependence coincidence rate
Definition: JFitK40.hh:600
JParameter_t cc
fraction of signal correlated background
Definition: JFitK40.hh:601
JK40Parameters_t()
Default constructor.
Definition: JFitK40.hh:576
Fit parameters for two-fold coincidence rate due to K40.
Definition: JFitK40.hh:610
size_t getN() const
Get number of fit parameters.
Definition: JFitK40.hh:669
const JK40Parameters & getK40Parameters() const
Get K40 parameters.
Definition: JFitK40.hh:647
JK40Parameters_t gradient
Definition: JFitK40.hh:741
int getIndex(JParameter_t JK40Parameters::*p) const
Get index of parameter.
Definition: JFitK40.hh:686
double getValue(const double ct) const
Get K40 coincidence rate as a function of cosine angle between PMT axes.
Definition: JFitK40.hh:711
JK40Parameters()
Default constructor.
Definition: JFitK40.hh:614
const JK40Parameters_t & getGradient(const double ct) const
Get gradient.
Definition: JFitK40.hh:723
static const JK40Parameters & getInstance()
Get default values.
Definition: JFitK40.hh:627
void setK40Parameters(const JK40Parameters_t &parameters)
Set K40 parameters.
Definition: JFitK40.hh:658
Auxiliary data structure for derived quantities of a given PMT pair.
Definition: JFitK40.hh:763
double signal
combined signal
Definition: JFitK40.hh:767
double sigma
total width [ns]
Definition: JFitK40.hh:766
double background
combined background
Definition: JFitK40.hh:768
double t0
time offset [ns]
Definition: JFitK40.hh:765
double ct
cosine angle between PMT axes
Definition: JFitK40.hh:764
Fit model.
Definition: JFitK40.hh:754
JModel()
Default constructor.
Definition: JFitK40.hh:775
int getIndex(int pmt, JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
Definition: JFitK40.hh:1038
int getIndex(int pmt) const
Get index of parameter.
Definition: JFitK40.hh:1019
size_t getN() const
Get number of fit parameters.
Definition: JFitK40.hh:1001
double getValue(const pair_type &pair) const
Get K40 coincidence rate.
Definition: JFitK40.hh:1121
real_type real
Definition: JFitK40.hh:1169
JOption_t getOption() const
Get fit option.
Definition: JFitK40.hh:844
double getFixedTimeOffset() const
Get time offset.
Definition: JFitK40.hh:945
void setSigmaK40(const double sigma)
Set intrinsic K40 arrival time spread.
Definition: JFitK40.hh:1060
const real_type & getReal(const pair_type &pair) const
Get derived parameters.
Definition: JFitK40.hh:1072
int getIndex() const
Get index of PMT used for fixed time offset.
Definition: JFitK40.hh:966
double getSigmaK40() const
Get intrinsic K40 arrival time spread.
Definition: JFitK40.hh:1049
void setOption(const int option)
Set fit option.
Definition: JFitK40.hh:855
JModel(const JModule &module, const JK40Parameters &parameters)
Constructor.
Definition: JFitK40.hh:826
double getValue(const pair_type &pair, const double dt_ns) const
Get K40 coincidence rate.
Definition: JFitK40.hh:1099
void setIndex()
Set index of PMT used for fixed time offset.
Definition: JFitK40.hh:975
JOption_t option
Definition: JFitK40.hh:1168
JModel(const JModule &module, const JK40Parameters &parameters, const JTDC_t::range_type &TDC, const int option)
Constructor.
Definition: JFitK40.hh:787
friend std::ostream & operator<<(std::ostream &out, const JModel &object)
Write model parameters to output stream.
Definition: JFitK40.hh:1142
bool hasFixedTimeOffset() const
Check if time offset is fixed.
Definition: JFitK40.hh:934
int index
index of PMT used for fixed time offset
Definition: JFitK40.hh:1166
Fit parameters for single PMT.
Definition: JFitK40.hh:425
JParameter_t t0
time offset [ns]
Definition: JFitK40.hh:564
JParameter_t TTS
transition-time spread [ns]
Definition: JFitK40.hh:563
void disable()
Disable PMT.
Definition: JFitK40.hh:516
size_t getN() const
Get number of fit parameters.
Definition: JFitK40.hh:481
friend std::ostream & operator<<(std::ostream &out, const JPMTParameters_t &object)
Write PMT parameters to output stream.
Definition: JFitK40.hh:548
JPMTParameters_t()
Default constructor.
Definition: JFitK40.hh:434
JParameter_t bg
background [Hz/ns]
Definition: JFitK40.hh:565
void enable()
Enable PMT.
Definition: JFitK40.hh:530
int getIndex(JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
Definition: JFitK40.hh:496
JParameter_t QE
relative quantum efficiency [unit]
Definition: JFitK40.hh:562
static const JPMTParameters_t & getInstance()
Get default values.
Definition: JFitK40.hh:459
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Definition: JFitK40.hh:103
Data structure for measured coincidence rate of pair of PMTs.
Definition: JFitK40.hh:66
rate_type(double dt_ns, double value, double error)
Constructor.
Definition: JFitK40.hh:84
double error
error of rate [Hz/ns]
Definition: JFitK40.hh:94
double value
value of rate [Hz/ns]
Definition: JFitK40.hh:93
rate_type()
Default constructor.
Definition: JFitK40.hh:70
double dt_ns
time difference [ns]
Definition: JFitK40.hh:92
Interface for maximum likelihood estimator (M-estimator).
Definition: JMEstimator.hh:20
double signal
Definition: JGauss.hh:163
double mean
Definition: JGauss.hh:161
Gauss function object.
Definition: JGauss.hh:175
double sigma
sigma
Definition: JMathlib.hh:1665
Auxiliary base class for aritmetic operations of derived class types.
Definition: JMath.hh:347
JMatrixND & reset()
Set matrix to the null matrix.
Definition: JMatrixND.hh:459
N x N symmetric matrix.
Definition: JMatrixNS.hh:30
Nx1 matrix.
Definition: JVectorND.hh:23
Data structure for a pair of indices.