1 #ifndef __JCALIBRATE_JGANDALFK40__
2 #define __JCALIBRATE_JGANDALFK40__
102 public std::map<pair_type, std::vector<rate_type> >
110 public JMath<JParameter_t>
359 operator double()
const
388 return in >>
object.value;
403 out <<
FIXED(12,6) <<
object.get() <<
' '
404 << setw(5) << (
object.isFixed() ?
"fixed" :
" ") <<
' ';
407 out <<
FIXED(12,6) <<
object.value <<
' ';
408 out <<
FIXED(12,6) <<
object.range.getLowerLimit() <<
' '
409 <<
FIXED(12,6) <<
object.range.getUpperLimit();
427 static constexpr
double QE_MIN = 0.0;
428 static constexpr
double QE_MAX = 2.0;
429 static constexpr
double TTS_NS = 2.0;
467 parameters.
QE .
set(1.0);
468 parameters.
TTS.
set(TTS_NS);
469 parameters.
t0 .
set(0.0);
470 parameters.
bg .
set(0.0);
483 return ((QE.
isFree() ? 1 : 0) +
484 (TTS.isFree() ? 1 : 0) +
485 (t0 .isFree() ? 1 : 0) +
486 (bg .isFree() ? 1 : 0));
498 if (!(this->*p).
isFree()) {
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;
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);
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));
688 if (!(this->*p).
isFree()) {
713 return R * exp(ct*(
p1+ct*(p2+ct*(p3+ct*p4))) - (
p1+p2+p3+p4));
728 const double ct2 = ct * ct;
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; }
794 setK40Parameters(parameters);
800 for (JTDC_t::const_iterator i = TDC.first; i != TDC.second; ++i) {
804 this->parameters[i->second].t0.fix();
809 this->parameters[i].t0.fix();
831 setK40Parameters(parameters);
868 parameters[i].bg.fix();
878 parameters[i].bg.fix();
902 parameters[i].QE.fix();
903 parameters[i].bg.fix();
913 parameters[i].QE.fix();
914 parameters[i].t0.fix();
915 parameters[i].bg.fix();
951 if (parameters[i].t0.isFree()) {
952 t0 += parameters[i].t0;
981 if (parameters[i].status) {
985 parameters[index].t0.fix();
1006 N += parameters[i].getN();
1023 for (
int i = 0; i != pmt; ++i) {
1024 N += parameters[i].getN();
1040 return getIndex(pmt) + parameters[pmt].getIndex(p);
1051 return this->sigmaK40_ns;
1062 this->sigmaK40_ns =
sigma;
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());
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());
1084 real.signal = this->parameters[
pair.first].QE() * this->parameters[
pair.second].QE();
1086 real.background = this->parameters[
pair.first].bg() + this->parameters[
pair.second].bg();
1101 using namespace std;
1102 using namespace JPP;
1109 const double R2 =
gauss.getValue(dt_ns);
1123 using namespace std;
1124 using namespace JPP;
1129 const double R2 = real.
signal;
1144 using namespace std;
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;
1157 out <<
"PMT[" <<
FILL(2,
'0') << i <<
FILL() <<
"]." <<
object.parameters[i].status << endl <<
object.parameters[i];
1167 double sigmaK40_ns = 0.54;
1199 using namespace JPP;
1213 using namespace std;
1214 using namespace JPP;
1219 const size_t N =
value.getN();
1227 for (data_type::const_iterator ix =
data.begin(); ix !=
data.end(); ++ix) {
1231 if (
value.parameters[
pair.first ].status &&
1234 ndf += ix->second.size();
1238 ndf -=
value.getN();
1241 lambda = LAMBDA_MIN;
1243 double precessor = numeric_limits<double>::max();
1245 for (numberOfIterations = 0; numberOfIterations != MAXIMUM_ITERATIONS; ++numberOfIterations) {
1247 DEBUG(
"step: " << numberOfIterations << endl);
1251 DEBUG(
"lambda: " <<
FIXED(12,5) << lambda << endl);
1252 DEBUG(
"chi2: " <<
FIXED(12,3) << successor << endl);
1254 if (successor < precessor) {
1256 if (numberOfIterations != 0) {
1258 if (fabs(precessor - successor) < EPSILON*fabs(precessor)) {
1259 return { successor / estimator->getRho(1.0), ndf };
1262 if (lambda > LAMBDA_MIN) {
1263 lambda /= LAMBDA_DOWN;
1267 precessor = successor;
1273 lambda *= LAMBDA_UP;
1275 if (lambda > LAMBDA_MAX) {
1276 return { precessor / estimator->getRho(1.0), ndf };
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; }
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; }
1303 for (
size_t i = 0; i != N; ++i) {
1305 if (V(i,i) < PIVOT) {
1309 h[i] = 1.0 / sqrt(V(i,i));
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];
1321 for (
size_t i = 0; i != N; ++i) {
1322 V(i,i) = 1.0 + lambda;
1327 for (
size_t col = 0; col != N; ++col) {
1334 catch (
const exception& error) {
1336 ERROR(
"JGandalf: " << error.what() << endl << V << endl);
1343 const double factor = 2.0;
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; }
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; }
1362 return { precessor / estimator->getRho(1.0), ndf };
1366 static constexpr
int MAXIMUM_ITERATIONS = 10000;
1367 static constexpr
double EPSILON = 1.0e-5;
1368 static constexpr
double LAMBDA_MIN = 0.01;
1369 static constexpr
double LAMBDA_MAX = 100.0;
1370 static constexpr
double LAMBDA_UP = 10.0;
1371 static constexpr
double LAMBDA_DOWN = 10.0;
1390 using namespace std;
1391 using namespace JPP;
1434 const int index =
model.getIndex(pmt);
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; }
1455 for (data_type::const_iterator ix =
data.begin(); ix !=
data.end(); ++ix) {
1459 if (
value.parameters[
pair.first ].status &&
1462 const real_type& real =
value.getReal(
pair);
1464 const JGauss gauss(real.t0, real.sigma, real.signal);
1466 const double R1 =
value.getValue (real.ct);
1472 for (
const rate_type& iy : ix->second) {
1477 const double R = real.background +
R1 * (
value.cc() + R2);
1479 const double w = -estimator->getPsi(
u) / iy.
error;
1481 successor += estimator->getRho(
u);
1501 for (buffer_type::const_iterator row = buffer.begin(); row != buffer.end(); ++row) {
1503 Y[row->first] += row->second;
1505 V[row->first][row->first] += row->second * row->second;
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];
JDAQPMTIdentifier PMT
Command line options.
KM3NeT DAQ constants, bit handling, etc.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Maximum likelihood estimator (M-estimators).
Base class for data structures with artithmetic capabilities.
General purpose messaging.
#define DEBUG(A)
Message macros.
Data structure for optical module.
Auxiliary class to define a range between two values.
result_type operator()(const data_type &data)
Fit.
JFit(const int option, const int debug)
Constructor.
std::shared_ptr< JMEstimator > estimator_type
void evaluate(const data_type &data)
Evaluation of fit.
estimator_type estimator
M-Estimator function.
Auxiliary class for fit parameter with optional limits.
JParameter_t & div(const double factor)
Scale parameter.
JParameter_t & operator=(double value)
Assignment operator.
void set(const double value)
Set value.
friend std::istream & operator>>(std::istream &in, JParameter_t &object)
Read parameter from input stream.
void fix()
Fix current value.
JParameter_t & negate()
Negate parameter.
bool isFree() const
Check if parameter is free.
friend std::ostream & operator<<(std::ostream &out, const JParameter_t &object)
Write parameter to output stream.
double operator()() const
Type conversion operator.
void set()
Set current value.
JParameter_t(const double value, const range_type &range=range_type::DEFAULT_RANGE())
Constructor.
JParameter_t & mul(const double factor)
Scale parameter.
JParameter_t()
Default constructor.
JParameter_t & mul(const JParameter_t &first, const JParameter_t &second)
Scale parameter.
double getDerivative() const
Get derivative of value.
JParameter_t & sub(const JParameter_t ¶meter)
Subtract parameter.
JParameter_t & add(const JParameter_t ¶meter)
Add parameter.
void fix(const double value)
Fix value.
double get() const
Get value.
JTOOLS::JRange< double > range_type
Type definition for range of parameter values.
bool isBound() const
Check if parameter is bound.
bool isFixed() const
Check if parameter is fixed.
Data structure for a composite optical module.
Exception for accessing a value in a collection that is outside of its range.
double getDot(const JNeutrinoDirection &first, const JNeutrinoDirection &second)
Dot product.
Auxiliary classes and methods for PMT calibration.
static const int INVALID_INDEX
invalid index
@ FIT_PMTS_QE_FIXED_t
fit parameters of PMTs with QE fixed
@ FIT_PMTS_AND_ANGULAR_DEPENDENCE_t
fit parameters of PMTs and angular dependence of K40 rate
@ FIT_MODEL_t
fit parameters of K40 rate and TTSs of PMTs
@ FIT_PMTS_AND_BACKGROUND_t
fit parameters of PMTs and background
@ FIT_PMTS_t
fit parameters of PMTs
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
JMEstimator * getMEstimator(const int type)
Get M-Estimator.
int getIndex()
Get index for user I/O manipulation.
double gauss(const double x, const double sigma)
Gauss function (normalised to 1 at x = 0).
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
std::vector< JHitW0 > buffer_type
hits
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Auxiliary data structure for sequence of same character.
Auxiliary data structure for floating point format specification.
PMT combinatorics for optical module.
Fit parameters for two-fold coincidence rate due to K40.
JParameter_t R
maximal coincidence rate [Hz]
JParameter_t p1
1st order angle dependence coincidence rate
JParameter_t p2
2nd order angle dependence coincidence rate
JParameter_t p3
3rd order angle dependence coincidence rate
JParameter_t p4
4th order angle dependence coincidence rate
JParameter_t cc
fraction of signal correlated background
JK40Parameters_t()
Default constructor.
Fit parameters for two-fold coincidence rate due to K40.
size_t getN() const
Get number of fit parameters.
const JK40Parameters & getK40Parameters() const
Get K40 parameters.
JK40Parameters_t gradient
int getIndex(JParameter_t JK40Parameters::*p) const
Get index of parameter.
double getValue(const double ct) const
Get K40 coincidence rate as a function of cosine angle between PMT axes.
JK40Parameters()
Default constructor.
const JK40Parameters_t & getGradient(const double ct) const
Get gradient.
static const JK40Parameters & getInstance()
Get default values.
void setK40Parameters(const JK40Parameters_t ¶meters)
Set K40 parameters.
Auxiliary data structure for derived quantities of a given PMT pair.
double signal
combined signal
double sigma
total width [ns]
double background
combined background
double t0
time offset [ns]
double ct
cosine angle between PMT axes
JModel()
Default constructor.
int getIndex(int pmt, JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
int getIndex(int pmt) const
Get index of parameter.
size_t getN() const
Get number of fit parameters.
double getValue(const pair_type &pair) const
Get K40 coincidence rate.
JOption_t getOption() const
Get fit option.
double getFixedTimeOffset() const
Get time offset.
void setSigmaK40(const double sigma)
Set intrinsic K40 arrival time spread.
const real_type & getReal(const pair_type &pair) const
Get derived parameters.
int getIndex() const
Get index of PMT used for fixed time offset.
double getSigmaK40() const
Get intrinsic K40 arrival time spread.
void setOption(const int option)
Set fit option.
JModel(const JModule &module, const JK40Parameters ¶meters)
Constructor.
double getValue(const pair_type &pair, const double dt_ns) const
Get K40 coincidence rate.
void setIndex()
Set index of PMT used for fixed time offset.
JModel(const JModule &module, const JK40Parameters ¶meters, const JTDC_t::range_type &TDC, const int option)
Constructor.
friend std::ostream & operator<<(std::ostream &out, const JModel &object)
Write model parameters to output stream.
bool hasFixedTimeOffset() const
Check if time offset is fixed.
int index
index of PMT used for fixed time offset
Fit parameters for single PMT.
JParameter_t t0
time offset [ns]
JParameter_t TTS
transition-time spread [ns]
void disable()
Disable PMT.
size_t getN() const
Get number of fit parameters.
friend std::ostream & operator<<(std::ostream &out, const JPMTParameters_t &object)
Write PMT parameters to output stream.
JPMTParameters_t()
Default constructor.
JParameter_t bg
background [Hz/ns]
int getIndex(JParameter_t JPMTParameters_t::*p) const
Get index of parameter.
JParameter_t QE
relative quantum efficiency [unit]
static const JPMTParameters_t & getInstance()
Get default values.
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Data structure for measured coincidence rate of pair of PMTs.
rate_type(double dt_ns, double value, double error)
Constructor.
double error
error of rate [Hz/ns]
double value
value of rate [Hz/ns]
rate_type()
Default constructor.
double dt_ns
time difference [ns]
Interface for maximum likelihood estimator (M-estimator).
Auxiliary base class for aritmetic operations of derived class types.
JMatrixND & reset()
Set matrix to the null matrix.