Jpp 20.0.0-195-g190c9e876
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/JBell.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 * Set range.
318 *
319 * \param xmin minimal value
320 * \param xmax maximal value
321 */
322 void setRange(const double xmin, const double xmax)
323 {
324 const double x = get();
325
326 range = range_type(xmin, xmax);
327
328 set(x);
329 }
330
331
332 /**
333 * Check if parameter is at limit;.
334 *
335 * \param precision precision
336 * \return true if at limit; else false
337 */
338 bool atLimit(const double precision) const
339 {
340 if (isBound())
341 return (get() - range.getLowerLimit() <= precision ||
342 range.getUpperLimit() - get() <= precision);
343 else
344 return false;
345 }
346
347
348 /**
349 * Fix value.
350 *
351 * \param value value
352 */
353 void fix(const double value)
354 {
355 set(value);
356
357 fix();
358 }
359
360
361 /**
362 * Get derivative of value.
363 *
364 * \return derivative of value
365 */
366 double getDerivative() const
367 {
368 if (isBound())
369 return 1.0 / (0.5 * range.getLength() * cos(value));
370 else
371 return 1.0;
372 }
373
374
375 /**
376 * Type conversion operator.
377 *
378 * \return value
379 */
380 double operator()() const
381 {
382 return get();
383 }
384
385
386 /**
387 * Type conversion operator.
388 *
389 * \return value
390 */
391 operator double() const
392 {
393 return get();
394 }
395
396
397 /**
398 * Assignment operator.
399 *
400 * \param value value
401 * \return this parameter
402 */
404 {
405 set(value);
406
407 return *this;
408 }
409
410
411 /**
412 * Read parameter from input stream.
413 *
414 * \param in input stream
415 * \param object parameter
416 * \return input stream
417 */
418 friend inline std::istream& operator>>(std::istream& in, JParameter_t& object)
419 {
420 return in >> object.value;
421 }
422
423
424 /**
425 * Write parameter to output stream.
426 *
427 * \param out output stream
428 * \param object parameter
429 * \return output stream
430 */
431 friend inline std::ostream& operator<<(std::ostream& out, const JParameter_t& object)
432 {
433 using namespace std;
434
435 out << FIXED(12,6) << object.get() << ' '
436 << setw(5) << (object.isFixed() ? "fixed" : " ") << ' ';
437
438 if (object.isBound()) {
439 out << "[" << FIXED(12,6) << object.range.getLowerLimit() << "," << FIXED(12,6) << object.range.getUpperLimit() << "]";
440 }
441
442 return out;
443 }
444
445
446 double value = 0.0;
449 };
450
451
452 /**
453 * Fit parameters for single PMT.
454 */
456
457 static constexpr double QE_MIN = 0.0; //!< minimal QE
458 static constexpr double QE_MAX = 2.0; //!< maximal QE
459 static constexpr double TTS_NS = 2.0; //!< start value transition-time spread [ns]
460
461 /**
462 * Default constructor.
463 */
465 {
466 reset();
467 }
468
469
470 /**
471 * Get default values.
472 *
473 * \return parameters
474 */
476 {
477 static JPMTParameters_t parameters;
478
480
481 parameters.status = true;
482
483 parameters.QE .set(1.0);
484 parameters.TTS.set(TTS_NS);
485 parameters.t0 .set(0.0);
486 parameters.bg .set(0.0);
487
488 return parameters;
489 }
490
491
492 /**
493 * Reset.
494 */
495 void reset()
496 {
497 status = true;
498
499 QE .set(0.0);
500 TTS.set(0.0);
501 t0 .set(0.0);
502 bg .set(0.0);
503 }
504
505
506 /**
507 * Set parameters that are free to given values.
508 *
509 * \param parameters parameters
510 */
511 void set(const JPMTParameters_t& parameters)
512 {
513 if (QE .isFree()) { QE .set(parameters.QE); }
514 if (TTS.isFree()) { TTS.set(parameters.TTS); }
515 if (t0 .isFree()) { t0 .set(parameters.t0); }
516 if (bg .isFree()) { bg .set(parameters.bg); }
517 }
518
519
520 /**
521 * Get number of fit parameters.
522 *
523 * \return number of parameters
524 */
525 inline size_t getN() const
526 {
527 return ((QE. isFree() ? 1 : 0) +
528 (TTS.isFree() ? 1 : 0) +
529 (t0 .isFree() ? 1 : 0) +
530 (bg .isFree() ? 1 : 0));
531 }
532
533
534 /**
535 * Get index of parameter.
536 *
537 * \param p pointer to data member
538 * \return index
539 */
541 {
542 if (!(this->*p).isFree()) {
543 return INVALID_INDEX;
544 }
545
546 int N = 0;
547
548 if (p == &JPMTParameters_t::QE ) { return N; }; if (QE .isFree()) { ++N; }
549 if (p == &JPMTParameters_t::TTS) { return N; }; if (TTS.isFree()) { ++N; }
550 if (p == &JPMTParameters_t::t0 ) { return N; }; if (t0 .isFree()) { ++N; }
551 if (p == &JPMTParameters_t::bg ) { return N; }; if (bg .isFree()) { ++N; }
552
553 return INVALID_INDEX;
554 }
555
556
557 /**
558 * Disable PMT.
559 */
560 void disable()
561 {
562 status = false;
563
564 QE .fix(0.0);
565 TTS.fix(TTS_NS);
566 t0 .fix(0.0);
567 bg .fix(0.0);
568 }
569
570
571 /**
572 * Enable PMT.
573 */
574 void enable()
575 {
576 status = true;
577
578 QE .set();
579 TTS.set();
580 t0 .set();
581 bg .set();
582 }
583
584
585 /**
586 * Write PMT parameters to output stream.
587 *
588 * \param out output stream
589 * \param object PMT parameters
590 * \return output stream
591 */
592 friend inline std::ostream& operator<<(std::ostream& out, const JPMTParameters_t& object)
593 {
594 using namespace std;
595
596 out << "QE " << FIXED(7,3) << object.QE << endl;
597 out << "TTS " << FIXED(7,3) << object.TTS << endl;
598 out << "t0 " << FIXED(7,3) << object.t0 << endl;
599 out << "bg " << FIXED(7,3) << object.bg << endl;
600
601 return out;
602 }
603
604
605 bool status; //!< status
606 JParameter_t QE; //!< relative quantum efficiency [unit]
607 JParameter_t TTS; //!< transition-time spread [ns]
608 JParameter_t t0; //!< time offset [ns]
609 JParameter_t bg; //!< background [Hz/ns]
610 };
611
612
613 /**
614 * Fit parameters for two-fold coincidence rate due to K40.
615 */
617 /**
618 * Default constructor.
619 */
621 {
622 reset();
623 }
624
625
626 /**
627 * Get K40 parameters.
628 *
629 * \return K40 parameters
630 */
632 {
633 return static_cast<const JK40Parameters_t&>(*this);
634 }
635
636
637 /**
638 * Set K40 parameters.
639 *
640 * \param parameters K40 parameters
641 */
642 void setK40Parameters(const JK40Parameters_t& parameters)
643 {
644 static_cast<JK40Parameters_t&>(*this) = parameters;
645 }
646
647
648 /**
649 * Reset.
650 */
651 void reset()
652 {
653 R .set(0.0);
654 p1.set(0.0);
655 p2.set(0.0);
656 p3.set(0.0);
657 p4.set(0.0);
658 cc.set(0.0);
659 bc.set(0.0);
660 }
661
662
663 /**
664 * Print model parameters to output stream conform include files.
665 *
666 * \param out output stream
667 */
668 void print(std::ostream& out) const
669 {
670 using namespace std;
671
672 out << "JFitK40.hh" << endl;
673 out << "parameters.R .set(" << FIXED(9,6) << this->R () << ");" << endl;
674 out << "parameters.p1.set(" << FIXED(9,6) << this->p1() << ");" << endl;
675 out << "parameters.p2.set(" << FIXED(9,6) << this->p2() << ");" << endl;
676 out << "parameters.p3.set(" << FIXED(9,6) << this->p3() << ");" << endl;
677 out << "parameters.p4.set(" << FIXED(9,6) << this->p4() << ");" << endl;
678 out << "cc " << FIXED(9,6) << this->cc() << endl;
679 out << "bc " << FIXED(9,6) << this->bc() << endl;
680 out << endl;
681
682 out << "JK40DefaultSimulator.hh" << endl;
683 out << "static constexpr double p1 = " << FIXED(9,6) << this->p1() << ";" << endl;
684 out << "static constexpr double p2 = " << FIXED(9,6) << this->p2() << ";" << endl;
685 out << "static constexpr double p3 = " << FIXED(9,6) << this->p3() << ";" << endl;
686 out << "static constexpr double p4 = " << FIXED(9,6) << this->p4() << ";" << endl;
687 out << endl;
688 }
689
690
691 /**
692 * Write model parameters to output stream.
693 *
694 * \param out output stream
695 * \param object model parameters
696 * \return output stream
697 */
698 friend inline std::ostream& operator<<(std::ostream& out, const JK40Parameters_t& object)
699 {
700 using namespace std;
701
702 out << "Rate [Hz] " << FIXED(12,6) << object.R << endl;
703 out << "p1 " << FIXED(12,6) << object.p1 << endl;
704 out << "p2 " << FIXED(12,6) << object.p2 << endl;
705 out << "p3 " << FIXED(12,6) << object.p3 << endl;
706 out << "p4 " << FIXED(12,6) << object.p4 << endl;
707 out << "cc " << FIXED(12,6) << object.cc << endl;
708 out << "bc " << FIXED(12,6) << object.bc << endl;
709 out << endl;
710
711 return out;
712 }
713
714 JParameter_t R; //!< maximal coincidence rate [Hz]
715 JParameter_t p1; //!< 1st order angle dependence coincidence rate
716 JParameter_t p2; //!< 2nd order angle dependence coincidence rate
717 JParameter_t p3; //!< 3rd order angle dependence coincidence rate
718 JParameter_t p4; //!< 4th order angle dependence coincidence rate
719 JParameter_t cc; //!< fraction of signal correlated background
720 JParameter_t bc; //!< constant background
721 };
722
723
724 /**
725 * Fit parameters for two-fold coincidence rate due to K40.
726 */
729 {
730 /**
731 * Default constructor.
732 */
735
736
737 /**
738 * Get default values.
739 *
740 * Values obtained with $JPP_DIR/examples/JCalibrate/JOMGsim.sh type B (see $JPP_DIR/examples/JCalibrate/README.md).
741 * If you change these values, you may also want to change the corresponding values in JK40DefaultSimulator.hh.
742 *
743 * \return parameters
744 */
746 {
747 static JK40Parameters parameters;
748
749 parameters.R .set(18.473257);
750 parameters.p1.set( 3.030307);
751 parameters.p2.set(-0.965429);
752 parameters.p3.set( 1.290367);
753 parameters.p4.set( 0.405618);
754 parameters.cc.set( 0.0);
755 parameters.bc.set( 0.0);
756
757 return parameters;
758 }
759
760
761 /**
762 * Get number of fit parameters.
763 *
764 * \return number of parameters
765 */
766 inline size_t getN() const
767 {
768 return ((R .isFree() ? 1 : 0) +
769 (p1.isFree() ? 1 : 0) +
770 (p2.isFree() ? 1 : 0) +
771 (p3.isFree() ? 1 : 0) +
772 (p4.isFree() ? 1 : 0) +
773 (cc.isFree() ? 1 : 0) +
774 (bc.isFree() ? 1 : 0));
775 }
776
777
778 /**
779 * Get index of parameter.
780 *
781 * \param p pointer to data member
782 * \return index
783 */
785 {
786 if (!(this->*p).isFree()) {
787 return INVALID_INDEX;
788 }
789
790 int N = 0;
791
792 if (p == &JK40Parameters::R) { return N; } if (R .isFree()) { ++N; }
793 if (p == &JK40Parameters::p1) { return N; } if (p1.isFree()) { ++N; }
794 if (p == &JK40Parameters::p2) { return N; } if (p2.isFree()) { ++N; }
795 if (p == &JK40Parameters::p3) { return N; } if (p3.isFree()) { ++N; }
796 if (p == &JK40Parameters::p4) { return N; } if (p4.isFree()) { ++N; }
797 if (p == &JK40Parameters::cc) { return N; } if (cc.isFree()) { ++N; }
798 if (p == &JK40Parameters::bc) { return N; } if (bc.isFree()) { ++N; }
799
800 return INVALID_INDEX;
801 }
802
803
804 /**
805 * Get K40 coincidence rate as a function of cosine angle between PMT axes.
806 *
807 * \param ct cosine angle between PMT axes
808 * \return rate [Hz]
809 */
810 double getValue(const double ct) const
811 {
812 return R * exp(ct*(p1+ct*(p2+ct*(p3+ct*p4))) - (p1+p2+p3+p4));
813 }
814
815
816 /**
817 * Get gradient.
818 *
819 * \param ct cosine angle between PMT axes
820 * \return gradient
821 */
822 const JK40Parameters_t& getGradient(const double ct) const
823 {
824 gradient.reset();
825
826 const double rate = getValue(ct);
827 const double ct2 = ct * ct;
828
829 if (R .isFree()) { gradient.R = rate / R; }
830 if (p1.isFree()) { gradient.p1 = rate * ct - rate; }
831 if (p2.isFree()) { gradient.p2 = rate * ct2 - rate; }
832 if (p3.isFree()) { gradient.p3 = rate * ct2 * ct - rate; }
833 if (p4.isFree()) { gradient.p4 = rate * ct2 * ct2 - rate; }
834 if (cc.isFree()) { gradient.cc = rate; }
835 if (bc.isFree()) { gradient.bc = 1.0; }
836
837 return gradient;
838 }
839
840 private:
842 };
843
844
845 /**
846 * Fit model.
847 */
848 struct JModel_t :
849 public JK40Parameters
850 {
852
853
854 /**
855 * Write model parameters to output stream.
856 *
857 * \param out output stream
858 * \param object model parameters
859 * \return output stream
860 */
861 friend inline std::ostream& operator<<(std::ostream& out, const JModel_t& object)
862 {
863 using namespace std;
864
865 out << static_cast<const JK40Parameters&>(object);
866
867 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
868 out << "PMT[" << FILL(2,'0') << i << FILL() << "]." << object.parameters[i].status << endl << object.parameters[i];
869 }
870
871 return out;
872 }
873 };
874
875
876 static double TEROSTAT_DZ = 0.40; //!< maximal PMT inclination
877 static double TEROSTAT_R1 = 1.00; //!< scaling factor
878 static double BELL_SHAPE = 1.55; //!< Bell shape
879
880 /**
881 * Fit model.
882 *
883 * In the absence of TDC constraints, the average time offset is fixed to zero.
884 */
885 struct JModel :
886 public JModel_t,
887 public JModule,
888 public JCombinatorics_t
889 {
893
894 /**
895 * Auxiliary data structure for derived quantities of a given PMT pair.
896 */
897 struct real_type {
898 double ct; //!< cosine angle between PMT axes
899 double t0; //!< time offset [ns]
900 double sigma; //!< total width [ns]
901 double signal; //!< combined signal
902 double background; //!< combined background
903 double cc; //!< correlated background
904 double bc; //!< uncorrelated background
905 };
906
907
908 /**
909 * Default constructor.
910 */
912 {}
913
914
915 /**
916 * Constructor.
917 *
918 * \param module detector module
919 * \param parameters K40 parameters
920 * \param TDC TDC constraints
921 * \param option option
922 */
923 JModel(const JModule& module,
925 const JTDC_t::range_type& TDC,
926 const int option) :
927 JModule (module),
928 JCombinatorics_t(module)
929 {
931
932 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
933 this->parameters[i] = JPMTParameters_t::getInstance();
934 }
935
936 for (JTDC_t::const_iterator i = TDC.first; i != TDC.second; ++i) {
937
938 if (i->second != JTDC_t::WILDCARD) {
939
940 this->parameters[i->second].t0.fix();
941
942 } else {
943
944 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
945 this->parameters[i].t0.fix();
946 }
947 }
948 }
949
950 this->index = (TDC.first == TDC.second ? 0 : INVALID_INDEX);
951
953 }
954
955
956 /**
957 * Constructor.
958 *
959 * \param module detector module
960 * \param parameters K40 parameters
961 */
962 JModel(const JModule& module,
963 const JK40Parameters& parameters) :
964 JModule (module),
965 JCombinatorics_t(module)
966 {
968
969 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
970 this->parameters[i] = JPMTParameters_t::getInstance();
971 }
972 }
973
974
975 /**
976 * Get fit option.
977 *
978 * \return option
979 */
981 {
982 return option;
983 }
984
985
986 /**
987 * Set fit option.
988 *
989 * \param option option
990 */
991 inline void setOption(const int option)
992 {
993 switch (option) {
994
995 case FIT_PMTS_t:
996
997 R .fix();
998 p1.fix();
999 p2.fix();
1000 p3.fix();
1001 p4.fix();
1002
1003 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1004 parameters[i].bg.fix();
1005 }
1006
1007 break;
1008
1010
1011 R .fix();
1012
1013 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1014 parameters[i].bg.fix();
1015 }
1016
1017 break;
1018
1020
1021 R .fix();
1022 p1.fix();
1023 p2.fix();
1024 p3.fix();
1025 p4.fix();
1026
1027 break;
1028
1030
1031 R .fix();
1032 p1.fix();
1033 p2.fix();
1034 p3.fix();
1035 p4.fix();
1036
1037 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1038 parameters[i].QE.fix();
1039 parameters[i].bg.fix();
1040 }
1041
1042 break;
1043
1044 case FIT_MODEL_t:
1045
1047
1048 //cc.fix();
1049 //bc.fix();
1050
1051 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1052 parameters[i].QE.fix();
1053 parameters[i].t0.fix();
1054 parameters[i].bg.fix();
1055 }
1056
1057 break;
1058
1059 default:
1060
1061 THROW(JValueOutOfRange, "Invalid option " << option);
1062 }
1063
1064 this->option = static_cast<JOption_t>(option);
1065 }
1066
1067
1068 /**
1069 * Check if time offset is fixed.
1070 *
1071 * \return true if time offset fixed; else false
1072 */
1074 {
1075 return index != INVALID_INDEX;
1076 }
1077
1078
1079 /**
1080 * Get time offset.
1081 *
1082 * \return time offset
1083 */
1084 double getFixedTimeOffset() const
1085 {
1086 double t0 = 0.0;
1087 size_t N = 0;
1088
1089 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1090 if (parameters[i].t0.isFree()) {
1091 t0 += parameters[i].t0;
1092 N += 1;
1093 }
1094 }
1095
1096 return t0 /= N;
1097 }
1098
1099
1100 /**
1101 * Get index of PMT used for fixed time offset.
1102 *
1103 * \return index
1104 */
1105 int getIndex() const
1106 {
1107 return index;
1108 }
1109
1110
1111 /**
1112 * Set index of PMT used for fixed time offset.
1113 */
1115 {
1116 if (index != INVALID_INDEX) {
1117
1118 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1119
1120 if (parameters[i].status) {
1121
1122 index = i;
1123
1125
1126 return;
1127 }
1128 }
1129
1130 THROW(JValueOutOfRange, "No valid index.");
1131 }
1132 }
1133
1134
1135 /**
1136 * Get number of fit parameters.
1137 *
1138 * \return number of parameters
1139 */
1140 inline size_t getN() const
1141 {
1142 size_t N = JK40Parameters::getN();
1143
1144 for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
1145 N += parameters[i].getN();
1146 }
1147
1148 return N;
1149 }
1150
1151
1152 /**
1153 * Get index of parameter.
1154 *
1155 * \param pmt PMT
1156 * \return index
1157 */
1158 int getIndex(int pmt) const
1159 {
1160 int N = JK40Parameters::getN();
1161
1162 for (int i = 0; i != pmt; ++i) {
1163 N += parameters[i].getN();
1164 }
1165
1166 return N;
1167 }
1168
1169
1170 /**
1171 * Get index of parameter.
1172 *
1173 * \param pmt PMT
1174 * \param p pointer to data member
1175 * \return index
1176 */
1178 {
1179 return getIndex(pmt) + parameters[pmt].getIndex(p);
1180 }
1181
1182
1183 /**
1184 * Get intrinsic K40 arrival time spread.
1185 *
1186 * \return sigma [ns]
1187 */
1188 double getSigmaK40() const
1189 {
1190 return this->sigmaK40_ns;
1191 }
1192
1193
1194 /**
1195 * Set intrinsic K40 arrival time spread.
1196 *
1197 * \param sigma sigma [ns]
1198 */
1199 void setSigmaK40(const double sigma)
1200 {
1201 this->sigmaK40_ns = sigma;
1202 }
1203
1204
1205 /**
1206 * Get derived quantities.
1207 *
1208 * \param pair PMT pair
1209 * \return quantities
1210 */
1211 const real_type& getReal(const pair_type& pair) const
1212 {
1213 real.ct = JPP::getDot((*this)[pair.first].getDirection(), (*this)[pair.second].getDirection());
1214
1215 real.t0 = (pair.first == this->index ? -this->parameters[pair.second].t0() :
1216 pair.second == this->index ? +this->parameters[pair.first ].t0() :
1217 this->parameters[pair.first].t0() - this->parameters[pair.second].t0());
1218
1219 real.sigma = sqrt(this->parameters[pair.first ].TTS() * this->parameters[pair.first ].TTS() +
1220 this->parameters[pair.second].TTS() * this->parameters[pair.second].TTS() +
1221 this->getSigmaK40() * this->getSigmaK40());
1222
1223 real.signal = this->parameters[pair.first].QE() * this->parameters[pair.second].QE();
1224
1225 real.background = this->parameters[pair.first].bg() + this->parameters[pair.second].bg();
1226
1227 real.cc = real.signal * this->cc();
1228 real.bc = this->bc();
1229
1230 const double z1 = (*this)[pair.first ].getDirection().getDZ();
1231 const double z2 = (*this)[pair.second].getDirection().getDZ();
1232
1233 if (fabs(z1) <= TEROSTAT_DZ &&
1234 fabs(z2) <= TEROSTAT_DZ &&
1235 signbit(z1) != signbit(z2)) {
1236
1238 }
1239
1240 return real;
1241 }
1242
1243
1244 /**
1245 * Get K40 coincidence rate.
1246 *
1247 * \param pair PMT pair
1248 * \param dt_ns time difference [ns]
1249 * \return rate [Hz/ns]
1250 */
1251 double getValue(const pair_type& pair, const double dt_ns) const
1252 {
1253 using namespace std;
1254 using namespace JPP;
1255
1256 const real_type& real = getReal(pair);
1257
1258 const JBell bell(real.t0, real.sigma, real.signal, 0.0, BELL_SHAPE);
1259
1260 const double R1 = this->getValue(real.ct);
1261 const double R2 = bell.getValue(dt_ns);
1262
1263 return real.bc + real.background + R1 * (real.cc + R2);
1264 }
1265
1266
1267 /**
1268 * Get K40 coincidence rate.
1269 *
1270 * \param pair PMT pair
1271 * \return rate [Hz]
1272 */
1273 double getValue(const pair_type& pair) const
1274 {
1275 using namespace std;
1276 using namespace JPP;
1277
1278 const real_type& real = getReal(pair);
1279
1280 const double R1 = this->getValue(real.ct);
1281 const double R2 = real.signal;
1282
1283 return real.bc + real.background + R1 * (real.cc + R2);
1284 }
1285
1286
1287 /**
1288 * Write model parameters to output stream.
1289 *
1290 * \param out output stream
1291 * \param object model parameters
1292 * \return output stream
1293 */
1294 friend inline std::ostream& operator<<(std::ostream& out, const JModel& object)
1295 {
1296 using namespace std;
1297
1298 out << "Module " << setw(10) << object.getID() << endl;
1299 out << "option " << object.option << endl;
1300 out << "index " << object.index << endl;
1301
1302 out << static_cast<const JModel_t&>(object);
1303
1304 return out;
1305 }
1306
1307 private:
1308 int index; //!< index of PMT used for fixed time offset
1309 double sigmaK40_ns = 0.54; //!< intrinsic K40 arrival time spread [ns]
1310 JOption_t option; //!< fit option (see JCALIBRATE::JOption_t)
1312 };
1313
1314
1315 /**
1316 * Fit.
1317 */
1318 class JFit
1319 {
1320 public:
1321 /**
1322 * Result type.
1323 */
1325 double chi2;
1326 int ndf;
1327 };
1328
1329 typedef std::shared_ptr<JMEstimator> estimator_type;
1330
1331
1332 /**
1333 * Constructor
1334 *
1335 * \param option M-estimator
1336 * \param debug debug
1337 */
1338 JFit(const int option, const int debug) :
1339 debug(debug)
1340 {
1341 using namespace JPP;
1342
1343 estimator.reset(getMEstimator(option));
1344 }
1345
1346
1347 /**
1348 * Fit.
1349 *
1350 * \param data data
1351 * \return chi2, NDF
1352 */
1354 {
1355 using namespace std;
1356 using namespace JPP;
1357
1358
1359 value.setIndex();
1360
1361 const size_t N = value.getN();
1362
1363 V.resize(N);
1364 Y.resize(N);
1365 h.resize(N);
1366
1367 double xmax = numeric_limits<double>::lowest();
1368 double xmin = numeric_limits<double>::max();
1369
1370 int ndf = 0;
1371
1372 for (data_type::const_iterator ix = data.begin(); ix != data.end(); ++ix) {
1373
1374 const pair_type& pair = ix->first;
1375
1376 if (value.parameters[pair.first ].status &&
1377 value.parameters[pair.second].status) {
1378
1379 ndf += ix->second.size();
1380
1381 for (const rate_type& iy : ix->second) {
1382 if (iy.dt_ns > xmax) { xmax = iy.dt_ns; }
1383 if (iy.dt_ns < xmin) { xmin = iy.dt_ns; }
1384 }
1385 }
1386 }
1387
1388 ndf -= value.getN();
1389
1390 if (ndf < 0) {
1391 return { 0.0, ndf };
1392 }
1393
1394 for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1395 if (value.parameters[pmt].t0.isFree()) {
1396 value.parameters[pmt].t0.setRange(xmin, xmax);
1397 }
1398 }
1399
1400
1402
1403 double precessor = numeric_limits<double>::max();
1404
1406
1407 DEBUG("step: " << numberOfIterations << endl);
1408
1409 evaluate(data);
1410
1411 DEBUG("lambda: " << FIXED(12,5) << lambda << endl);
1412 DEBUG("chi2: " << FIXED(12,3) << successor << endl);
1413
1414 if (successor < precessor) {
1415
1416 if (numberOfIterations != 0) {
1417
1418 if (fabs(precessor - successor) < EPSILON) {
1419
1420 seterr(data);
1421
1422 return { successor / estimator->getRho(1.0), ndf };
1423 }
1424
1425 if (lambda > LAMBDA_MIN) {
1427 }
1428 }
1429
1430 precessor = successor;
1431 previous = value;
1432
1433 } else {
1434
1435 value = previous;
1436 lambda *= LAMBDA_UP;
1437
1438 if (lambda > LAMBDA_MAX) {
1439 break;
1440 }
1441
1442 evaluate(data);
1443 }
1444
1445 if (debug >= debug_t) {
1446
1447 size_t row = 0;
1448
1449 if (value.R .isFree()) { cout << "R " << FIXED(12,5) << Y[row] << endl; ++row; }
1450 if (value.p1.isFree()) { cout << "p1 " << FIXED(12,5) << Y[row] << endl; ++row; }
1451 if (value.p2.isFree()) { cout << "p2 " << FIXED(12,5) << Y[row] << endl; ++row; }
1452 if (value.p3.isFree()) { cout << "p3 " << FIXED(12,5) << Y[row] << endl; ++row; }
1453 if (value.p4.isFree()) { cout << "p4 " << FIXED(12,5) << Y[row] << endl; ++row; }
1454 if (value.cc.isFree()) { cout << "cc " << FIXED(12,3) << Y[row] << endl; ++row; }
1455
1456 for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1457 if (value.parameters[pmt].QE .isFree()) { cout << "PMT[" << setw(2) << pmt << "].QE " << FIXED(12,5) << Y[row] << endl; ++row; }
1458 if (value.parameters[pmt].TTS.isFree()) { cout << "PMT[" << setw(2) << pmt << "].TTS " << FIXED(12,5) << Y[row] << endl; ++row; }
1459 if (value.parameters[pmt].t0 .isFree()) { cout << "PMT[" << setw(2) << pmt << "].t0 " << FIXED(12,5) << Y[row] << endl; ++row; }
1460 if (value.parameters[pmt].bg .isFree()) { cout << "PMT[" << setw(2) << pmt << "].bg " << FIXED(12,5) << Y[row] << endl; ++row; }
1461 }
1462 }
1463
1464 // force definite positiveness
1465
1466 for (size_t i = 0; i != N; ++i) {
1467
1468 if (V(i,i) < PIVOT) {
1469 V(i,i) = PIVOT;
1470 }
1471
1472 h[i] = 1.0 / sqrt(V(i,i));
1473 }
1474
1475 // normalisation
1476
1477 for (size_t i = 0; i != N; ++i) {
1478 for (size_t j = 0; j != i; ++j) {
1479 V(j,i) *= h[i] * h[j];
1480 V(i,j) = V(j,i);
1481 }
1482 }
1483
1484 for (size_t i = 0; i != N; ++i) {
1485 V(i,i) = 1.0 + lambda;
1486 }
1487
1488 // solve A x = b
1489
1490 for (size_t col = 0; col != N; ++col) {
1491 Y[col] *= h[col];
1492 }
1493
1494 try {
1495 V.solve(Y);
1496 }
1497 catch (const exception& error) {
1498
1499 ERROR("JGandalf: " << error.what() << endl << V << endl);
1500
1501 break;
1502 }
1503
1504 // update value
1505
1506 const double factor = 2.0;
1507
1508 size_t row = 0;
1509
1510 if (value.R .isFree()) { value.R -= factor * h[row] * Y[row]; ++row; }
1511 if (value.p1.isFree()) { value.p1 -= factor * h[row] * Y[row]; ++row; }
1512 if (value.p2.isFree()) { value.p2 -= factor * h[row] * Y[row]; ++row; }
1513 if (value.p3.isFree()) { value.p3 -= factor * h[row] * Y[row]; ++row; }
1514 if (value.p4.isFree()) { value.p4 -= factor * h[row] * Y[row]; ++row; }
1515 if (value.cc.isFree()) { value.cc -= factor * h[row] * Y[row]; ++row; }
1516 if (value.bc.isFree()) { value.bc -= factor * h[row] * Y[row]; ++row; }
1517
1518 for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1519 if (value.parameters[pmt].QE .isFree()) { value.parameters[pmt].QE -= factor * h[row] * Y[row]; ++row; }
1520 if (value.parameters[pmt].TTS.isFree()) { value.parameters[pmt].TTS -= factor * h[row] * Y[row]; ++row; }
1521 if (value.parameters[pmt].t0 .isFree()) { value.parameters[pmt].t0 -= factor * h[row] * Y[row]; ++row; }
1522 if (value.parameters[pmt].bg .isFree()) { value.parameters[pmt].bg -= factor * h[row] * Y[row]; ++row; }
1523 }
1524 }
1525
1526 seterr(data);
1527
1528 return { precessor / estimator->getRho(1.0), ndf };
1529 }
1530
1531
1532 static constexpr int MAXIMUM_ITERATIONS = 100000; //!< maximal number of iterations.
1533 static constexpr double EPSILON = 1.0e-3; //!< maximal distance to minimum.
1534 static constexpr double LAMBDA_MIN = 1.0e-2; //!< minimal value control parameter
1535 static constexpr double LAMBDA_MAX = 1.0e+4; //!< maximal value control parameter
1536 static constexpr double LAMBDA_UP = 10.0; //!< multiplication factor control parameter
1537 static constexpr double LAMBDA_DOWN = 10.0; //!< multiplication factor control parameter
1538 static constexpr double PIVOT = std::numeric_limits<double>::epsilon(); //!< minimal value diagonal element of matrix
1539
1541 estimator_type estimator; //!< M-Estimator function
1542
1543 double lambda;
1548
1549 private:
1550 /**
1551 * Evaluation of fit.
1552 *
1553 * \param data data
1554 */
1555 void evaluate(const data_type& data)
1556 {
1557 using namespace std;
1558 using namespace JPP;
1559
1560 typedef JModel::real_type real_type;
1561
1562
1563 successor = 0.0;
1564
1565 V.reset();
1566 Y.reset();
1567
1568
1569 // model parameter indices
1570
1571 const struct M_t {
1572 M_t(const JModel& model)
1573 {
1574 R = model.getIndex(&JK40Parameters_t::R);
1575 p1 = model.getIndex(&JK40Parameters_t::p1);
1576 p2 = model.getIndex(&JK40Parameters_t::p2);
1577 p3 = model.getIndex(&JK40Parameters_t::p3);
1578 p4 = model.getIndex(&JK40Parameters_t::p4);
1579 cc = model.getIndex(&JK40Parameters_t::cc);
1580 bc = model.getIndex(&JK40Parameters_t::bc);
1581 }
1582
1583 int R;
1584 int p1;
1585 int p2;
1586 int p3;
1587 int p4;
1588 int cc;
1589 int bc;
1590
1591 } M(value);
1592
1593
1594 // PMT parameter indices
1595
1596 struct I_t {
1597 I_t(const JModel& model, const int pmt) :
1598 QE (INVALID_INDEX),
1599 TTS(INVALID_INDEX),
1600 t0 (INVALID_INDEX),
1601 bg (INVALID_INDEX)
1602 {
1603 const int index = model.getIndex(pmt);
1604
1605 int N = 0;
1606
1607 if (model.parameters[pmt].QE .isFree()) { QE = index + N; ++N; }
1608 if (model.parameters[pmt].TTS.isFree()) { TTS = index + N; ++N; }
1609 if (model.parameters[pmt].t0 .isFree()) { t0 = index + N; ++N; }
1610 if (model.parameters[pmt].bg .isFree()) { bg = index + N; ++N; }
1611 }
1612
1613 int QE;
1614 int TTS;
1615 int t0;
1616 int bg;
1617 };
1618
1619
1621
1622 buffer_type buffer;
1623
1624 for (data_type::const_iterator ix = data.begin(); ix != data.end(); ++ix) {
1625
1626 const pair_type& pair = ix->first;
1627
1628 if (value.parameters[pair.first ].status &&
1629 value.parameters[pair.second].status) {
1630
1631 const real_type& real = value.getReal(pair);
1632
1633 const JBell bell(real.t0, real.sigma, real.signal, 0.0, BELL_SHAPE);
1634
1635 const double R1 = value.getValue (real.ct);
1636 const JK40Parameters_t& R1p = value.getGradient(real.ct);
1637
1638 const std::pair<I_t, I_t> PMT(I_t(value, pair.first),
1639 I_t(value, pair.second));
1640
1641 for (const rate_type& iy : ix->second) {
1642
1643 const double R2 = bell.getValue (iy.dt_ns);
1644 const JBell_t& R2p = bell.getGradient(iy.dt_ns);
1645
1646 const double R = real.bc + real.background + R1 * (real.cc + R2);
1647 const double u = (iy.value - R) / iy.error;
1648 const double w = -estimator->getPsi(u) / iy.error;
1649
1650 successor += estimator->getRho(u);
1651
1652 buffer.clear();
1653
1654 if (M.R != INVALID_INDEX) { buffer.push_back({M.R, w * (value.cc() + R2) * R1p.R () * value.R .getDerivative()}); }
1655 if (M.p1 != INVALID_INDEX) { buffer.push_back({M.p1, w * (value.cc() + R2) * R1p.p1() * value.p1.getDerivative()}); }
1656 if (M.p2 != INVALID_INDEX) { buffer.push_back({M.p2, w * (value.cc() + R2) * R1p.p2() * value.p2.getDerivative()}); }
1657 if (M.p3 != INVALID_INDEX) { buffer.push_back({M.p3, w * (value.cc() + R2) * R1p.p3() * value.p3.getDerivative()}); }
1658 if (M.p4 != INVALID_INDEX) { buffer.push_back({M.p4, w * (value.cc() + R2) * R1p.p4() * value.p4.getDerivative()}); }
1659 if (M.cc != INVALID_INDEX) { buffer.push_back({M.cc, w * R1 * R1p.cc() * value.cc.getDerivative()}); }
1660 if (M.bc != INVALID_INDEX) { buffer.push_back({M.bc, w * R1p.bc() * value.bc.getDerivative()}); }
1661
1662 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()}); }
1663 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()}); }
1664 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}); }
1665 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}); }
1666 if (PMT.first .t0 != INVALID_INDEX) { buffer.push_back({PMT.first .t0, w * R1 * R2p.mean * value.parameters[pair.first ].t0 .getDerivative() * +1.0}); }
1667 if (PMT.second.t0 != INVALID_INDEX) { buffer.push_back({PMT.second.t0, w * R1 * R2p.mean * value.parameters[pair.second].t0 .getDerivative() * -1.0}); }
1668 if (PMT.first .bg != INVALID_INDEX) { buffer.push_back({PMT.first .bg, w * value.parameters[pair.first ].bg .getDerivative()}); }
1669 if (PMT.second.bg != INVALID_INDEX) { buffer.push_back({PMT.second.bg, w * value.parameters[pair.second].bg .getDerivative()}); }
1670
1671 for (buffer_type::const_iterator row = buffer.begin(); row != buffer.end(); ++row) {
1672
1673 Y[row->first] += row->second;
1674
1675 V[row->first][row->first] += row->second * row->second;
1676
1677 for (buffer_type::const_iterator col = buffer.begin(); col != row; ++col) {
1678 V[row->first][col->first] += row->second * col->second;
1679 V[col->first][row->first] = V[row->first][col->first];
1680 }
1681 }
1682 }
1683 }
1684 }
1685 }
1686
1687
1688 /**
1689 * Set errors.
1690 *
1691 * \param data data
1692 */
1693 void seterr(const data_type& data)
1694 {
1695 using namespace std;
1696
1697 error.reset();
1698
1699 evaluate(data);
1700
1701 try {
1702 V.invert();
1703 }
1704 catch (const exception& error) {}
1705
1706#define SQRT(X) (X >= 0.0 ? sqrt(X) : std::numeric_limits<double>::max())
1707
1708 size_t i = 0;
1709
1710 if (value.R .isFree()) { error.R = SQRT(V(i,i)); ++i; }
1711 if (value.p1.isFree()) { error.p1 = SQRT(V(i,i)); ++i; }
1712 if (value.p2.isFree()) { error.p2 = SQRT(V(i,i)); ++i; }
1713 if (value.p3.isFree()) { error.p3 = SQRT(V(i,i)); ++i; }
1714 if (value.p4.isFree()) { error.p4 = SQRT(V(i,i)); ++i; }
1715 if (value.cc.isFree()) { error.cc = SQRT(V(i,i)); ++i; }
1716 if (value.bc.isFree()) { error.bc = SQRT(V(i,i)); ++i; }
1717
1718 for (int pmt = 0; pmt != NUMBER_OF_PMTS; ++pmt) {
1719 if (value.parameters[pmt].QE .isFree()) { error.parameters[pmt].QE = SQRT(V(i,i)); ++i; }
1720 if (value.parameters[pmt].TTS.isFree()) { error.parameters[pmt].TTS = SQRT(V(i,i)); ++i; }
1721 if (value.parameters[pmt].t0 .isFree()) { error.parameters[pmt].t0 = SQRT(V(i,i)); ++i; }
1722 if (value.parameters[pmt].bg .isFree()) { error.parameters[pmt].bg = SQRT(V(i,i)); ++i; }
1723 }
1724
1725#undef SQRT
1726 }
1727
1728
1729 JMATH::JVectorND Y; // gradient
1732 std::vector<double> h; // normalisation vector
1733 };
1734}
1735
1736#endif
1737
1738
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.
#define SQRT(X)
Maximum likelihood estimator (M-estimators).
I/O manipulators.
Binary methods for member 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:1329
std::vector< double > h
Definition JFitK40.hh:1732
static constexpr double LAMBDA_MIN
minimal value control parameter
Definition JFitK40.hh:1534
static constexpr double LAMBDA_DOWN
multiplication factor control parameter
Definition JFitK40.hh:1537
result_type operator()(const data_type &data)
Fit.
Definition JFitK40.hh:1353
void seterr(const data_type &data)
Set errors.
Definition JFitK40.hh:1693
static constexpr double LAMBDA_MAX
maximal value control parameter
Definition JFitK40.hh:1535
static constexpr double LAMBDA_UP
multiplication factor control parameter
Definition JFitK40.hh:1536
JMATH::JMatrixNS V
Definition JFitK40.hh:1547
static constexpr double EPSILON
maximal distance to minimum.
Definition JFitK40.hh:1533
JFit(const int option, const int debug)
Constructor.
Definition JFitK40.hh:1338
void evaluate(const data_type &data)
Evaluation of fit.
Definition JFitK40.hh:1555
static constexpr int MAXIMUM_ITERATIONS
maximal number of iterations.
Definition JFitK40.hh:1532
static constexpr double PIVOT
minimal value diagonal element of matrix
Definition JFitK40.hh:1538
estimator_type estimator
M-Estimator function.
Definition JFitK40.hh:1541
JMATH::JVectorND Y
Definition JFitK40.hh:1729
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:403
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:431
friend std::istream & operator>>(std::istream &in, JParameter_t &object)
Read parameter from input stream.
Definition JFitK40.hh:418
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:380
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
void setRange(const double xmin, const double xmax)
Set range.
Definition JFitK40.hh:322
JParameter_t & negate()
Negate parameter.
Definition JFitK40.hh:156
JParameter_t()
Default constructor.
Definition JFitK40.hh:131
bool atLimit(const double precision) const
Check if parameter is at limit;.
Definition JFitK40.hh:338
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:366
JParameter_t & add(const JParameter_t &parameter)
Add parameter.
Definition JFitK40.hh:170
void fix(const double value)
Fix value.
Definition JFitK40.hh:353
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:76
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
T getUpperLimit() const
Get upper limit.
Definition JRange.hh:213
#define R1(x)
Auxiliary classes and methods for PMT calibration.
static double TEROSTAT_R1
scaling factor
Definition JFitK40.hh:877
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
static double TEROSTAT_DZ
maximal PMT inclination
Definition JFitK40.hh:876
static double BELL_SHAPE
Bell shape.
Definition JFitK40.hh:878
double getDot(const JFirst_t &first, const JSecond_t &second)
Get dot product of objects.
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:616
JParameter_t bc
constant background
Definition JFitK40.hh:720
JParameter_t R
maximal coincidence rate [Hz]
Definition JFitK40.hh:714
JParameter_t p1
1st order angle dependence coincidence rate
Definition JFitK40.hh:715
JParameter_t p2
2nd order angle dependence coincidence rate
Definition JFitK40.hh:716
friend std::ostream & operator<<(std::ostream &out, const JK40Parameters_t &object)
Write model parameters to output stream.
Definition JFitK40.hh:698
JParameter_t p3
3rd order angle dependence coincidence rate
Definition JFitK40.hh:717
const JK40Parameters_t & getK40Parameters() const
Get K40 parameters.
Definition JFitK40.hh:631
JParameter_t p4
4th order angle dependence coincidence rate
Definition JFitK40.hh:718
JParameter_t cc
fraction of signal correlated background
Definition JFitK40.hh:719
JK40Parameters_t()
Default constructor.
Definition JFitK40.hh:620
void setK40Parameters(const JK40Parameters_t &parameters)
Set K40 parameters.
Definition JFitK40.hh:642
void print(std::ostream &out) const
Print model parameters to output stream conform include files.
Definition JFitK40.hh:668
Fit parameters for two-fold coincidence rate due to K40.
Definition JFitK40.hh:729
size_t getN() const
Get number of fit parameters.
Definition JFitK40.hh:766
const JK40Parameters_t & getGradient(const double ct) const
Get gradient.
Definition JFitK40.hh:822
JK40Parameters_t gradient
Definition JFitK40.hh:841
static const JK40Parameters & getInstance()
Get default values.
Definition JFitK40.hh:745
int getIndex(JParameter_t JK40Parameters::*p) const
Get index of parameter.
Definition JFitK40.hh:784
double getValue(const double ct) const
Get K40 coincidence rate as a function of cosine angle between PMT axes.
Definition JFitK40.hh:810
JK40Parameters()
Default constructor.
Definition JFitK40.hh:733
Auxiliary data structure for derived quantities of a given PMT pair.
Definition JFitK40.hh:897
double signal
combined signal
Definition JFitK40.hh:901
double sigma
total width [ns]
Definition JFitK40.hh:900
double cc
correlated background
Definition JFitK40.hh:903
double background
combined background
Definition JFitK40.hh:902
double t0
time offset [ns]
Definition JFitK40.hh:899
double bc
uncorrelated background
Definition JFitK40.hh:904
double ct
cosine angle between PMT axes
Definition JFitK40.hh:898
friend std::ostream & operator<<(std::ostream &out, const JModel_t &object)
Write model parameters to output stream.
Definition JFitK40.hh:861
JPMTParameters_t parameters[NUMBER_OF_PMTS]
Definition JFitK40.hh:851
JModel()
Default constructor.
Definition JFitK40.hh:911
int getIndex(int pmt, JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
Definition JFitK40.hh:1177
friend std::ostream & operator<<(std::ostream &out, const JModel &object)
Write model parameters to output stream.
Definition JFitK40.hh:1294
int getIndex(int pmt) const
Get index of parameter.
Definition JFitK40.hh:1158
size_t getN() const
Get number of fit parameters.
Definition JFitK40.hh:1140
double getValue(const pair_type &pair) const
Get K40 coincidence rate.
Definition JFitK40.hh:1273
double sigmaK40_ns
intrinsic K40 arrival time spread [ns]
Definition JFitK40.hh:1309
JOption_t getOption() const
Get fit option.
Definition JFitK40.hh:980
double getFixedTimeOffset() const
Get time offset.
Definition JFitK40.hh:1084
void setSigmaK40(const double sigma)
Set intrinsic K40 arrival time spread.
Definition JFitK40.hh:1199
int getIndex() const
Get index of PMT used for fixed time offset.
Definition JFitK40.hh:1105
double getSigmaK40() const
Get intrinsic K40 arrival time spread.
Definition JFitK40.hh:1188
void setOption(const int option)
Set fit option.
Definition JFitK40.hh:991
const real_type & getReal(const pair_type &pair) const
Get derived quantities.
Definition JFitK40.hh:1211
JModel(const JModule &module, const JK40Parameters &parameters)
Constructor.
Definition JFitK40.hh:962
double getValue(const pair_type &pair, const double dt_ns) const
Get K40 coincidence rate.
Definition JFitK40.hh:1251
void setIndex()
Set index of PMT used for fixed time offset.
Definition JFitK40.hh:1114
JOption_t option
fit option (see JCALIBRATE::JOption_t)
Definition JFitK40.hh:1310
JModel(const JModule &module, const JK40Parameters &parameters, const JTDC_t::range_type &TDC, const int option)
Constructor.
Definition JFitK40.hh:923
bool hasFixedTimeOffset() const
Check if time offset is fixed.
Definition JFitK40.hh:1073
int index
index of PMT used for fixed time offset
Definition JFitK40.hh:1308
Fit parameters for single PMT.
Definition JFitK40.hh:455
static constexpr double QE_MIN
minimal QE
Definition JFitK40.hh:457
friend std::ostream & operator<<(std::ostream &out, const JPMTParameters_t &object)
Write PMT parameters to output stream.
Definition JFitK40.hh:592
JParameter_t t0
time offset [ns]
Definition JFitK40.hh:608
static constexpr double TTS_NS
start value transition-time spread [ns]
Definition JFitK40.hh:459
JParameter_t TTS
transition-time spread [ns]
Definition JFitK40.hh:607
void disable()
Disable PMT.
Definition JFitK40.hh:560
size_t getN() const
Get number of fit parameters.
Definition JFitK40.hh:525
JPMTParameters_t()
Default constructor.
Definition JFitK40.hh:464
void set(const JPMTParameters_t &parameters)
Set parameters that are free to given values.
Definition JFitK40.hh:511
JParameter_t bg
background [Hz/ns]
Definition JFitK40.hh:609
static constexpr double QE_MAX
maximal QE
Definition JFitK40.hh:458
void enable()
Enable PMT.
Definition JFitK40.hh:574
int getIndex(JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
Definition JFitK40.hh:540
static const JPMTParameters_t & getInstance()
Get default values.
Definition JFitK40.hh:475
JParameter_t QE
relative quantum efficiency [unit]
Definition JFitK40.hh:606
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).
status_type status
Definition JStatus.hh:252
Bell function object.
Definition JBell.hh:32
const JBell_t & getGradient(const double x) const
Get gradient.
Definition JBell.hh:125
double getValue(const double x) const
Function value.
Definition JBell.hh:85
Gauss model.
Definition JGauss.hh:32
double background
Definition JGauss.hh:164
double signal
Definition JGauss.hh:163
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
void invert()
Invert matrix according LDU decomposition.
Definition JMatrixNS.hh:75
Nx1 matrix.
Definition JVectorND.hh:23
void reset()
Reset.
Definition JVectorND.hh:45
Data structure for a pair of indices.