Jpp master_rocky-44-g75b7c4f75
the software that should make you happy
Loading...
Searching...
No Matches
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
37namespace JCALIBRATE {}
38namespace JPP { using namespace JCALIBRATE; }
39
40namespace JCALIBRATE {
41
42 using KM3NETDAQ::NUMBER_OF_PMTS;
45 using JMATH::JMath;
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 */
85 double value,
86 double error) :
87 dt_ns(dt_ns),
88 value(value),
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 */
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
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 */
610 {
611 /**
612 * Default constructor.
613 */
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 */
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,
789 const JTDC_t::range_type& TDC,
790 const int option) :
791 JModule (module),
792 JCombinatorics_t(module)
793 {
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
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 {
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
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 */
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
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 */
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]
1170 };
1171
1172
1173 /**
1174 * Fit.
1175 */
1176 class JFit
1177 {
1178 public:
1179 /**
1180 * Result type.
1181 */
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
1242
1243 double precessor = numeric_limits<double>::max();
1244
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) {
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
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
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.
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
Data structure for optical module.
Auxiliary class to define a range between two values.
std::shared_ptr< JMEstimator > estimator_type
Definition JFitK40.hh:1187
std::vector< double > h
Definition JFitK40.hh:1520
static constexpr double LAMBDA_MIN
minimal value control parameter
Definition JFitK40.hh:1368
static constexpr double LAMBDA_DOWN
multiplication factor control parameter
Definition JFitK40.hh:1371
result_type operator()(const data_type &data)
Fit.
Definition JFitK40.hh:1211
static constexpr double LAMBDA_MAX
maximal value control parameter
Definition JFitK40.hh:1369
static constexpr double LAMBDA_UP
multiplication factor control parameter
Definition JFitK40.hh:1370
JMATH::JMatrixNS V
Definition JFitK40.hh:1380
static constexpr double EPSILON
maximal distance to minimum.
Definition JFitK40.hh:1367
JFit(const int option, const int debug)
Constructor.
Definition JFitK40.hh:1196
void evaluate(const data_type &data)
Evaluation of fit.
Definition JFitK40.hh:1388
static constexpr int MAXIMUM_ITERATIONS
maximal number of iterations.
Definition JFitK40.hh:1366
static constexpr double PIVOT
minimal value diagonal element of matrix
Definition JFitK40.hh:1372
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 & mul(const double factor)
Scale parameter.
Definition JFitK40.hh:198
void set(const double value)
Set value.
Definition JFitK40.hh:305
void fix()
Fix current value.
Definition JFitK40.hh:280
JParameter_t & sub(const JParameter_t &parameter)
Subtract parameter.
Definition JFitK40.hh:184
JParameter_t & operator=(double value)
Assignment operator.
Definition JFitK40.hh:371
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
friend std::istream & operator>>(std::istream &in, JParameter_t &object)
Read parameter from input stream.
Definition JFitK40.hh:386
JParameter_t & div(const double factor)
Scale parameter.
Definition JFitK40.hh:212
JParameter_t & mul(const JParameter_t &first, const JParameter_t &second)
Scale parameter.
Definition JFitK40.hh:227
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 & negate()
Negate parameter.
Definition JFitK40.hh:156
JParameter_t()
Default constructor.
Definition JFitK40.hh:131
JTOOLS::JRange< double > range_type
Type definition for range of parameter values.
Definition JFitK40.hh:125
double getDerivative() const
Get derivative of value.
Definition JFitK40.hh:334
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
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.
int getIndex(const int first, const int second) const
Get index of pair of indices.
Range of values.
Definition JRange.hh:42
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
static JRange< double, std::less< double > > DEFAULT_RANGE()
Definition JRange.hh:555
T getLowerLimit() const
Get lower limit.
Definition JRange.hh:202
#define R1(x)
double getDot(const JNeutrinoDirection &first, const JNeutrinoDirection &second)
Dot product.
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
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
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_t & getGradient(const double ct) const
Get gradient.
Definition JFitK40.hh:723
JK40Parameters_t gradient
Definition JFitK40.hh:741
static const JK40Parameters & getInstance()
Get default values.
Definition JFitK40.hh:627
const JK40Parameters & getK40Parameters() const
Get K40 parameters.
Definition JFitK40.hh:647
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
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
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
friend std::ostream & operator<<(std::ostream &out, const JModel &object)
Write model parameters to output stream.
Definition JFitK40.hh:1142
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
double sigmaK40_ns
intrinsic K40 arrival time spread [ns]
Definition JFitK40.hh:1167
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
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
const real_type & getReal(const pair_type &pair) const
Get derived parameters.
Definition JFitK40.hh:1072
JModel(const JModule &module, const JK40Parameters &parameters)
Constructor.
Definition JFitK40.hh:826
JPMTParameters_t parameters[NUMBER_OF_PMTS]
Definition JFitK40.hh:1163
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
JModel(const JModule &module, const JK40Parameters &parameters, const JTDC_t::range_type &TDC, const int option)
Constructor.
Definition JFitK40.hh:787
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
static constexpr double QE_MIN
minimal QE
Definition JFitK40.hh:427
friend std::ostream & operator<<(std::ostream &out, const JPMTParameters_t &object)
Write PMT parameters to output stream.
Definition JFitK40.hh:548
JParameter_t t0
time offset [ns]
Definition JFitK40.hh:564
static constexpr double TTS_NS
start value transition-time spread [ns]
Definition JFitK40.hh:429
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
JPMTParameters_t()
Default constructor.
Definition JFitK40.hh:434
JParameter_t bg
background [Hz/ns]
Definition JFitK40.hh:565
static constexpr double QE_MAX
maximal QE
Definition JFitK40.hh:428
void enable()
Enable PMT.
Definition JFitK40.hh:530
int getIndex(JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
Definition JFitK40.hh:496
static const JPMTParameters_t & getInstance()
Get default values.
Definition JFitK40.hh:459
JParameter_t QE
relative quantum efficiency [unit]
Definition JFitK40.hh:562
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).
Auxiliary base class for aritmetic operations of derived class types.
Definition JMath.hh:347
void resize(const size_t size)
Resize matrix.
Definition JMatrixND.hh:446
JMatrixND & reset()
Set matrix to the null matrix.
Definition JMatrixND.hh:459
N x N symmetric matrix.
Definition JMatrixNS.hh:30
void solve(JVectorND_t &u)
Get solution of equation A x = b.
Definition JMatrixNS.hh:308
Nx1 matrix.
Definition JVectorND.hh:23
void reset()
Reset.
Definition JVectorND.hh:45
Data structure for a pair of indices.