53 template<
class GradFunc = IGradModelFunction>
99 deriv = 0.5 * ( f2 -
f1 )/
h;
102 deriv = (
f1 - f0 )/
h;
118 std::copy(p, p+
fN,
fVec.begin());
126 std::copy(p, p+
fN,
fVec.begin());
127 for (
unsigned int k = 0; k <
fN; ++k) {
133 void Gradient(
const double *
x,
const double * p,
double f0,
double *
g) {
136 for (
unsigned int k = 0; k <
fN; ++k) {
146 g[k] = 0.5 * ( f2 -
f1 )/
h;
149 g[k] = (
f1 - f0 )/
h;
162 mutable std::vector<double>
fVec;
169 if (rval > - std::numeric_limits<double>::max() && rval < std::numeric_limits<double>::max() )
173 return -std::numeric_limits<double>::max();
176 return + std::numeric_limits<double>::max();
183 if (rval > - std::numeric_limits<double>::max() && rval < std::numeric_limits<double>::max() )
187 rval = -std::numeric_limits<double>::max();
192 rval = + std::numeric_limits<double>::max();
201 template <
class GFunc>
203 const double *
x1,
const double *
x2,
const double * p,
double *
g) {
209 unsigned int npar = gfunc.NPar();
210 for (
unsigned int k = 0; k < npar; ++k ) {
212 g[k] = igDerEval(
x1,
x2 );
226 double FitUtil::EvaluateChi2(
const IModelFunction &func,
const BinData &data,
const double *p,
unsigned int &,
234 unsigned int n = data.Size();
238 (
const_cast<IModelFunction &
>(func)).SetParameters(p);
245 const DataOptions & fitOpt = data.Opt();
246 bool useBinIntegral = fitOpt.fIntegral && data.HasBinEdges();
247 bool useBinVolume = (fitOpt.fBinVolume && data.HasBinEdges());
248 bool useExpErrors = (fitOpt.fExpErrors);
249 bool isWeighted = data.IsWeighted();
252 std::cout <<
"\n\nFit data size = " <<
n << std::endl;
253 std::cout <<
"evaluate chi2 using function " << &func <<
" " << p << std::endl;
254 std::cout <<
"use empty bins " << fitOpt.fUseEmpty << std::endl;
255 std::cout <<
"use integral " << fitOpt.fIntegral << std::endl;
256 std::cout <<
"use all error=1 " << fitOpt.fErrors1 << std::endl;
257 if (isWeighted) std::cout <<
"Weighted data set - sumw = " << data.SumOfContent() <<
" sumw2 = " << data.SumOfError2() << std::endl;
266 IntegralEvaluator<> igEval( func, 0, useBinIntegral, igType);
268 IntegralEvaluator<> igEval( func, p, useBinIntegral, igType);
270 double maxResValue = std::numeric_limits<double>::max() /
n;
271 double wrefVolume = 1.0;
273 if (fitOpt.fNormBinVolume) wrefVolume /= data.RefVolume();
278 auto mapFunction = [&](
const unsigned i){
283 const auto x1 = data.GetCoordComponent(i, 0);
284 const auto y = data.Value(i);
285 auto invError = data.InvError(i);
289 const double *
x =
nullptr;
290 std::vector<double> xc;
291 double binVolume = 1.0;
293 unsigned int ndim = data.NDim();
294 xc.resize(data.NDim());
295 for (
unsigned int j = 0; j < ndim; ++j) {
296 double xx = *data.GetCoordComponent(i, j);
297 double x2 = data.GetBinUpEdgeComponent(i, j);
298 binVolume *= std::abs(
x2 - xx);
299 xc[j] = 0.5*(
x2 + xx);
303 binVolume *= wrefVolume;
304 }
else if(data.NDim() > 1) {
306 xc.resize(data.NDim());
308 for (
unsigned int j = 1; j < data.NDim(); ++j)
309 xc[j] = *data.GetCoordComponent(i, j);
316 if (!useBinIntegral) {
320 fval = func (
x, p );
326 std::vector<double>
x2(data.NDim());
327 data.GetBinUpEdgeCoordinates(i,
x2.data());
328 fval = igEval(
x,
x2.data());
331 if (useBinVolume) fval *= binVolume;
335 double invWeight = 1.0;
342 invWeight = data.SumOfContent()/ data.SumOfError2();
348 double invError2 = (fval > 0) ? invWeight / fval : 0.0;
349 invError = std::sqrt(invError2);
355 std::cout <<
x[0] <<
" " <<
y <<
" " << 1./invError <<
" params : ";
356 for (
unsigned int ipar = 0; ipar < func.NPar(); ++ipar)
357 std::cout << p[ipar] <<
"\t";
358 std::cout <<
"\tfval = " << fval <<
" bin volume " << binVolume <<
" ref " << wrefVolume << std::endl;
364 double tmp = (
y -fval )* invError;
365 double resval = tmp * tmp;
369 if ( resval < maxResValue )
380 auto redFunction = [](
const std::vector<double> & objs){
381 return std::accumulate(objs.begin(), objs.end(),
double{});
388 Warning(
"FitUtil::EvaluateChi2",
"Multithread execution policy requires IMT, which is disabled. Changing "
389 "to ROOT::EExecutionPolicy::kSequential.");
396 for (
unsigned int i=0; i<
n; ++i) {
397 res += mapFunction(i);
409 Error(
"FitUtil::EvaluateChi2",
"Execution policy unknown. Avalaible choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
424 unsigned int n = data.
Size();
427 std::cout <<
"\n\nFit data size = " <<
n << std::endl;
428 std::cout <<
"evaluate effective chi2 using function " << &func <<
" " << p << std::endl;
439 unsigned int ndim = func.
NDim();
444 double maxResValue = std::numeric_limits<double>::max() /
n;
448 for (
unsigned int i = 0; i <
n; ++ i) {
454 double fval = func(
x, p );
456 double delta_y_func =
y - fval;
460 const double *
ex = 0;
464 double eylow, eyhigh = 0;
466 if ( delta_y_func < 0)
474 while ( j < ndim &&
ex[j] == 0.) { j++; }
481 double kPrecision = 1.E-8;
482 for (
unsigned int icoord = 0; icoord < ndim; ++icoord) {
484 if (
ex[icoord] > 0) {
488 double x0=
x[icoord];
489 double h = std::max( kEps* std::abs(
ex[icoord]), 8.0*kPrecision*(std::abs(x0) + kPrecision) );
491 double edx =
ex[icoord] * deriv;
494 std::cout <<
"error for coord " << icoord <<
" = " <<
ex[icoord] <<
" deriv " << deriv << std::endl;
499 double w2 = (e2 > 0) ? 1.0/e2 : 0;
500 double resval = w2 * (
y - fval ) * (
y - fval);
503 std::cout <<
x[0] <<
" " <<
y <<
" ex " <<
ex[0] <<
" ey " <<
ey <<
" params : ";
504 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
505 std::cout << p[ipar] <<
"\t";
506 std::cout <<
"\tfval = " << fval <<
"\tresval = " << resval << std::endl;
511 if ( resval < maxResValue )
524 std::cout <<
"chi2 = " << chi2 <<
" n = " << nPoints << std::endl;
541 MATH_ERROR_MSG(
"FitUtil::EvaluateChi2Residual",
"Error on the coordinates are not used in calculating Chi2 residual");
548 double y, invError = 0;
559 unsigned int ndim = data.
NDim();
560 double binVolume = 1.0;
561 const double *
x2 = 0;
562 if (useBinVolume || useBinIntegral)
x2 = data.
BinUpEdge(i);
567 xc =
new double[ndim];
568 for (
unsigned int j = 0; j < ndim; ++j) {
569 binVolume *= std::abs(
x2[j]-
x1[j] );
570 xc[j] = 0.5*(
x2[j]+
x1[j]);
576 const double *
x = (useBinVolume) ? xc :
x1;
578 if (!useBinIntegral) {
579 fval = func (
x, p );
584 fval = igEval(
x1,
x2) ;
587 if (useBinVolume) fval *= binVolume;
598 double invError2 = (fval > 0) ? 1.0 / fval : 0.0;
599 invError = std::sqrt(invError2);
603 double resval = (
y -fval )* invError;
611 unsigned int npar = func.
NPar();
616 if (!useBinIntegral ) {
626 if (!useBinIntegral )
634 for (
unsigned int k = 0; k < npar; ++k) {
636 if (useBinVolume)
g[k] *= binVolume;
640 if (useBinVolume)
delete [] xc;
657 "Error on the coordinates are not used in calculating Chi2 gradient");
661 const IGradModelFunction *fg =
dynamic_cast<const IGradModelFunction *
>(&
f);
662 assert(fg !=
nullptr);
664 const IGradModelFunction &func = *fg;
667 std::cout <<
"\n\nFit data size = " <<
n << std::endl;
668 std::cout <<
"evaluate chi2 using function gradient " << &func <<
" " << p << std::endl;
671 const DataOptions &fitOpt = data.
Opt();
672 bool useBinIntegral = fitOpt.fIntegral && data.
HasBinEdges();
673 bool useBinVolume = (fitOpt.fBinVolume && data.
HasBinEdges());
675 double wrefVolume = 1.0;
677 if (fitOpt.fNormBinVolume) wrefVolume /= data.
RefVolume();
685 IntegralEvaluator<> igEval(func, p, useBinIntegral,igType);
687 unsigned int npar = func.NPar();
688 unsigned initialNPoints = data.
Size();
690 std::vector<bool> isPointRejected(initialNPoints);
692 auto mapFunction = [&](
const unsigned int i) {
694 std::vector<double> gradFunc(npar);
695 std::vector<double> pointContribution(npar);
698 const auto y = data.
Value(i);
699 auto invError = data.
Error(i);
701 invError = (invError != 0.0) ? 1.0 / invError : 1;
705 const double *
x =
nullptr;
706 std::vector<double> xc;
708 unsigned int ndim = data.
NDim();
709 double binVolume = 1;
712 for (
unsigned int j = 0; j < ndim; ++j) {
715 binVolume *= std::abs(x2_j - x1_j);
716 xc[j] = 0.5 * (x2_j + x1_j);
722 binVolume *= wrefVolume;
723 }
else if (ndim > 1) {
726 for (
unsigned int j = 1; j < ndim; ++j)
733 if (!useBinIntegral) {
735 func.ParameterGradient(
x, p, &gradFunc[0]);
737 std::vector<double>
x2(data.
NDim());
741 fval = igEval(
x,
x2.data());
748 std::cout <<
x[0] <<
" " <<
y <<
" " << 1. / invError <<
" params : ";
749 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
750 std::cout << p[ipar] <<
"\t";
751 std::cout <<
"\tfval = " << fval << std::endl;
754 isPointRejected[i] =
true;
756 return pointContribution;
760 unsigned int ipar = 0;
761 for (; ipar < npar; ++ipar) {
765 gradFunc[ipar] *= binVolume;
769 double dfval = gradFunc[ipar];
775 pointContribution[ipar] = -2.0 * (
y - fval) * invError * invError * gradFunc[ipar];
780 isPointRejected[i] =
true;
783 return pointContribution;
787 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
788 std::vector<double> result(npar);
790 for (
auto const &pointContribution : pointContributions) {
791 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
792 result[parameterIndex] += pointContribution[parameterIndex];
798 std::vector<double>
g(npar);
803 Warning(
"FitUtil::EvaluateChi2Gradient",
"Multithread execution policy requires IMT, which is disabled. Changing "
804 "to ROOT::EExecutionPolicy::kSequential.");
810 std::vector<std::vector<double>> allGradients(initialNPoints);
811 for (
unsigned int i = 0; i < initialNPoints; ++i) {
812 allGradients[i] = mapFunction(i);
814 g = redFunction(allGradients);
828 Error(
"FitUtil::EvaluateChi2Gradient",
829 "Execution policy unknown. Avalaible choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
838 nPoints = initialNPoints;
840 if (std::any_of(isPointRejected.begin(), isPointRejected.end(), [](
bool point) { return point; })) {
841 unsigned nRejected = std::accumulate(isPointRejected.begin(), isPointRejected.end(), 0);
842 assert(nRejected <= initialNPoints);
843 nPoints = initialNPoints - nRejected;
847 "Error - too many points rejected for overflow in gradient calculation");
851 std::copy(
g.begin(),
g.end(), grad);
871 const double *
x = data.
Coords(i);
872 double fval = func (
x, p );
875 if (
g == 0)
return logPdf;
891 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar) {
896 std::cout <<
x[i] <<
"\t";
897 std::cout <<
"\tpar = [ " << func.
NPar() <<
" ] = ";
898 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
899 std::cout << p[ipar] <<
"\t";
900 std::cout <<
"\tfval = " << fval;
901 std::cout <<
"\tgrad = [ ";
902 for (
unsigned int ipar = 0; ipar < func.
NPar(); ++ipar)
903 std::cout <<
g[ipar] <<
"\t";
904 std::cout <<
" ] " << std::endl;
912 int iWeight,
bool extended,
unsigned int &nPoints,
917 unsigned int n = data.
Size();
921 bool normalizeFunc =
false;
925 (
const_cast<IModelFunctionTempl<double> &
>(func)).SetParameters(p);
928 nPoints = data.
Size();
933 if (!normalizeFunc) {
934 if (data.
NDim() == 1) {
939 std::vector<double>
x(data.
NDim());
940 for (
unsigned int j = 0; j < data.
NDim(); ++j)
950 std::vector<double>
xmin(data.
NDim());
951 std::vector<double>
xmax(data.
NDim());
952 IntegralEvaluator<> igEval(func, p,
true);
956 for (
unsigned int ir = 0; ir < data.
Range().
Size(); ++ir) {
958 norm += igEval.Integral(
xmin.data(),
xmax.data());
964 if (func(
xmin.data(), p) != 0 || func(
xmax.data(), p) != 0) {
966 "A range has not been set and the function is not zero at +/- inf");
969 norm = igEval.Integral(&
xmin[0], &
xmax[0]);
975 auto mapFunction = [&](
const unsigned i) {
980 if (data.
NDim() > 1) {
981 std::vector<double>
x(data.
NDim());
982 for (
unsigned int j = 0; j < data.
NDim(); ++j)
985 fval = func(
x.data());
987 fval = func(
x.data(), p);
1001 fval = fval * (1 / norm);
1006 double weight = data.
Weight(i);
1013 W2 = weight * weight;
1017 return LikelihoodAux<double>(logval, W, W2);
1028 auto redFunction = [](
const std::vector<LikelihoodAux<double>> & objs){
1029 auto l0 = LikelihoodAux<double>(0.0,0.0,0.0);
1030 for (
auto &
l : objs ) {
1040 Warning(
"FitUtil::EvaluateLogL",
"Multithread execution policy requires IMT, which is disabled. Changing "
1041 "to ROOT::EExecutionPolicy::kSequential.");
1050 for (
unsigned int i=0; i<
n; ++i) {
1051 auto resArray = mapFunction(i);
1052 logl+=resArray.logvalue;
1053 sumW+=resArray.weight;
1054 sumW2+=resArray.weight2;
1061 logl=resArray.logvalue;
1062 sumW=resArray.weight;
1063 sumW2=resArray.weight2;
1069 Error(
"FitUtil::EvaluateLogL",
"Execution policy unknown. Avalaible choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1074 double extendedTerm = 0;
1078 if (!normalizeFunc) {
1079 IntegralEvaluator<> igEval( func, p,
true);
1080 std::vector<double>
xmin(data.
NDim());
1081 std::vector<double>
xmax(data.
NDim());
1086 for (
unsigned int ir = 0; ir < data.
Range().
Size(); ++ir) {
1088 nuTot += igEval.Integral(
xmin.data(),
xmax.data());
1094 if (func(
xmin.data(), p) != 0 || func(
xmax.data(), p) != 0) {
1095 MATH_ERROR_MSG(
"FitUtil::EvaluateLogLikelihood",
"A range has not been set and the function is not zero at +/- inf");
1098 nuTot = igEval.Integral(&
xmin[0],&
xmax[0]);
1104 extendedTerm = - nuTot;
1108 extendedTerm = - (sumW2 / sumW) * nuTot;
1117 logl += extendedTerm;
1122 std::cout <<
"Evaluated log L for parameters (";
1123 for (
unsigned int ip = 0; ip < func.NPar(); ++ip)
1124 std::cout <<
" " << p[ip];
1125 std::cout <<
") fval = " << -logl << std::endl;
1137 assert(fg !=
nullptr);
1141 unsigned int npar = func.
NPar();
1142 unsigned initialNPoints = data.Size();
1147 std::cout <<
"\n===> Evaluate Gradient for parameters ";
1148 for (
unsigned int ip = 0; ip < npar; ++ip)
1149 std::cout <<
" " << p[ip];
1153 const double kdmax1 = std::sqrt(std::numeric_limits<double>::max());
1154 const double kdmax2 = std::numeric_limits<double>::max() / (4 * initialNPoints);
1156 auto mapFunction = [&](
const unsigned int i) {
1157 std::vector<double> gradFunc(npar);
1158 std::vector<double> pointContribution(npar);
1161 const double *
x =
nullptr;
1162 std::vector<double> xc;
1163 if (data.NDim() > 1) {
1164 xc.resize(data.NDim() );
1165 for (
unsigned int j = 0; j < data.NDim(); ++j)
1166 xc[j] = *data.GetCoordComponent(i, j);
1169 x = data.GetCoordComponent(i, 0);
1172 double fval = func(
x, p);
1173 func.ParameterGradient(
x, p, &gradFunc[0]);
1178 if (i < 5 || (i > data.Size()-5) ) {
1179 if (data.NDim() > 1) std::cout << i <<
" x " <<
x[0] <<
" y " <<
x[1] <<
" func " << fval
1180 <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1181 else std::cout << i <<
" x " <<
x[0] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1186 for (
unsigned int kpar = 0; kpar < npar; ++kpar) {
1188 pointContribution[kpar] = -1. / fval * gradFunc[kpar];
1189 else if (gradFunc[kpar] != 0) {
1190 double gg = kdmax1 * gradFunc[kpar];
1192 gg = std::min(gg, kdmax2);
1194 gg = std::max(gg, -kdmax2);
1195 pointContribution[kpar] = -gg;
1200 return pointContribution;
1204 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
1205 std::vector<double> result(npar);
1207 for (
auto const &pointContribution : pointContributions) {
1208 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1209 result[parameterIndex] += pointContribution[parameterIndex];
1215 std::vector<double>
g(npar);
1220 Warning(
"FitUtil::EvaluateLogLGradient",
"Multithread execution policy requires IMT, which is disabled. Changing "
1221 "to ROOT::EExecutionPolicy::kSequential.");
1227 std::vector<std::vector<double>> allGradients(initialNPoints);
1228 for (
unsigned int i = 0; i < initialNPoints; ++i) {
1229 allGradients[i] = mapFunction(i);
1231 g = redFunction(allGradients);
1241 Error(
"FitUtil::EvaluateLogLGradient",
"Execution policy unknown. Avalaible choices:\n "
1242 "ROOT::EExecutionPolicy::kSequential (default)\n "
1243 "ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1252 std::copy(
g.begin(),
g.end(), grad);
1255 std::cout <<
"FitUtil.cxx : Final gradient ";
1256 for (
unsigned int param = 0; param < npar; param++) {
1257 std::cout <<
" " << grad[param];
1278 const double *
x2 = 0;
1280 double binVolume = 1;
1281 std::vector<double> xc;
1283 unsigned int ndim = data.
NDim();
1285 for (
unsigned int j = 0; j < ndim; ++j) {
1287 binVolume *= std::abs( x2j-
x1[j] );
1288 xc[j] = 0.5*(x2j+
x1[j]);
1294 const double *
x = (useBinVolume) ? &xc.front() :
x1;
1296 if (!useBinIntegral ) {
1297 fval = func (
x, p );
1301 std::vector<double> vx2(data.
NDim());
1303 fval = igEval(
x1, vx2.data() ) ;
1305 if (useBinVolume) fval *= binVolume;
1308 fval = std::max(fval, 0.0);
1309 double logPdf = - fval;
1319 if (
g == 0)
return logPdf;
1321 unsigned int npar = func.
NPar();
1327 if (!useBinIntegral )
1337 if (!useBinIntegral )
1345 for (
unsigned int k = 0; k < npar; ++k) {
1347 if (useBinVolume)
g[k] *= binVolume;
1351 g[k] *= (
y/fval - 1.) ;
1353 const double kdmax1 = std::sqrt( std::numeric_limits<double>::max() );
1362 std::cout <<
"x = " <<
x[0] <<
" logPdf = " << logPdf <<
" grad";
1363 for (
unsigned int ipar = 0; ipar < npar; ++ipar)
1364 std::cout <<
g[ipar] <<
"\t";
1365 std::cout << std::endl;
1393 unsigned int n = data.
Size();
1395#ifdef USE_PARAMCACHE
1396 (
const_cast<IModelFunction &
>(func)).SetParameters(p);
1399 nPoints = data.
Size();
1406 bool useW2 = (iWeight == 2);
1409 double wrefVolume = 1.0;
1416 std::cout <<
"Evaluate PoissonLogL for params = [ ";
1417 for (
unsigned int j = 0; j < func.NPar(); ++j) std::cout << p[j] <<
" , ";
1418 std::cout <<
"] - data size = " <<
n <<
" useBinIntegral " << useBinIntegral <<
" useBinVolume "
1419 << useBinVolume <<
" useW2 " << useW2 <<
" wrefVolume = " << wrefVolume << std::endl;
1428#ifdef USE_PARAMCACHE
1429 IntegralEvaluator<> igEval(func, 0, useBinIntegral, igType);
1431 IntegralEvaluator<> igEval(func, p, useBinIntegral, igType);
1434 auto mapFunction = [&](
const unsigned i) {
1438 const double *
x =
nullptr;
1439 std::vector<double> xc;
1441 double binVolume = 1.0;
1444 unsigned int ndim = data.
NDim();
1445 xc.resize(data.
NDim());
1446 for (
unsigned int j = 0; j < ndim; ++j) {
1449 binVolume *= std::abs(
x2 - xx);
1450 xc[j] = 0.5 * (
x2 + xx);
1454 binVolume *= wrefVolume;
1455 }
else if (data.
NDim() > 1) {
1456 xc.resize(data.
NDim());
1458 for (
unsigned int j = 1; j < data.
NDim(); ++j) {
1466 if (!useBinIntegral) {
1467#ifdef USE_PARAMCACHE
1475 std::vector<double>
x2(data.
NDim());
1477 fval = igEval(
x,
x2.data());
1479 if (useBinVolume) fval *= binVolume;
1485 if (i % NSAMPLE == 0) {
1486 std::cout <<
"evt " << i <<
" x = [ ";
1487 for (
unsigned int j = 0; j < func.NDim(); ++j) std::cout <<
x[j] <<
" , ";
1490 std::cout <<
"x2 = [ ";
1491 for (
unsigned int j = 0; j < func.NDim(); ++j) std::cout << data.
GetBinUpEdgeComponent(i, j) <<
" , ";
1494 std::cout <<
" y = " <<
y <<
" fval = " << fval << std::endl;
1501 fval = std::max(fval, 0.0);
1503 double nloglike = 0;
1512 double weight = 1.0;
1514 double error = data.
Error(i);
1515 weight = (error * error) /
y;
1523 nloglike += weight * ( fval -
y);
1531 if (extended) nloglike = fval -
y;
1540 std::cout <<
" nll = " << nloglike << std::endl;
1547 auto redFunction = [](
const std::vector<double> &objs) {
1548 return std::accumulate(objs.begin(), objs.end(),
double{});
1555 Warning(
"FitUtil::EvaluatePoissonLogL",
"Multithread execution policy requires IMT, which is disabled. Changing "
1556 "to ROOT::EExecutionPolicy::kSequential.");
1563 for (
unsigned int i = 0; i <
n; ++i) {
1564 res += mapFunction(i);
1576 Error(
"FitUtil::EvaluatePoissonLogL",
1577 "Execution policy unknown. Avalaible choices:\n ROOT::EExecutionPolicy::kSequential (default)\n ROOT::EExecutionPolicy::kMultiThread (requires IMT)\n");
1581 std::cout <<
"Loglikelihood = " << res << std::endl;
1593 assert(fg !=
nullptr);
1597#ifdef USE_PARAMCACHE
1601 const DataOptions &fitOpt = data.Opt();
1602 bool useBinIntegral = fitOpt.fIntegral && data.HasBinEdges();
1603 bool useBinVolume = (fitOpt.fBinVolume && data.HasBinEdges());
1605 double wrefVolume = 1.0;
1606 if (useBinVolume && fitOpt.fNormBinVolume)
1607 wrefVolume /= data.RefVolume();
1615 IntegralEvaluator<> igEval(func, p, useBinIntegral, igType);
1617 unsigned int npar = func.NPar();
1618 unsigned initialNPoints = data.Size();
1620 auto mapFunction = [&](
const unsigned int i) {
1622 std::vector<double> gradFunc(npar);
1623 std::vector<double> pointContribution(npar);
1625 const auto x1 = data.GetCoordComponent(i, 0);
1626 const auto y = data.Value(i);
1627 auto invError = data.Error(i);
1629 invError = (invError != 0.0) ? 1.0 / invError : 1;
1633 const double *
x =
nullptr;
1634 std::vector<double> xc;
1636 unsigned ndim = data.NDim();
1637 double binVolume = 1.0;
1642 for (
unsigned int j = 0; j < ndim; ++j) {
1643 double x1_j = *data.GetCoordComponent(i, j);
1644 double x2_j = data.GetBinUpEdgeComponent(i, j);
1645 binVolume *= std::abs(x2_j - x1_j);
1646 xc[j] = 0.5 * (x2_j + x1_j);
1652 binVolume *= wrefVolume;
1653 }
else if (ndim > 1) {
1656 for (
unsigned int j = 1; j < ndim; ++j)
1657 xc[j] = *data.GetCoordComponent(i, j);
1663 if (!useBinIntegral) {
1665 func.ParameterGradient(
x, p, &gradFunc[0]);
1669 std::vector<double>
x2(data.NDim());
1670 data.GetBinUpEdgeCoordinates(i,
x2.data());
1671 fval = igEval(
x,
x2.data());
1680 if (i < 5 || (i > data.Size()-5) ) {
1681 if (data.NDim() > 1) std::cout << i <<
" x " <<
x[0] <<
" y " <<
x[1] <<
" func " << fval
1682 <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1683 else std::cout << i <<
" x " <<
x[0] <<
" gradient " << gradFunc[0] <<
" " << gradFunc[1] <<
" " << gradFunc[3] << std::endl;
1689 for (
unsigned int ipar = 0; ipar < npar; ++ipar) {
1693 gradFunc[ipar] *= binVolume;
1697 pointContribution[ipar] = gradFunc[ipar] * (1. -
y / fval);
1698 else if (gradFunc[ipar] != 0) {
1699 const double kdmax1 = std::sqrt(std::numeric_limits<double>::max());
1700 const double kdmax2 = std::numeric_limits<double>::max() / (4 * initialNPoints);
1701 double gg = kdmax1 * gradFunc[ipar];
1703 gg = std::min(gg, kdmax2);
1705 gg = std::max(gg, -kdmax2);
1706 pointContribution[ipar] = -gg;
1711 return pointContribution;
1715 auto redFunction = [&](
const std::vector<std::vector<double>> &pointContributions) {
1716 std::vector<double> result(npar);
1718 for (
auto const &pointContribution : pointContributions) {
1719 for (
unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1720 result[parameterIndex] += pointContribution[parameterIndex];
1726 std::vector<double>
g(npar);
1731 Warning(
"FitUtil::EvaluatePoissonLogLGradient",
1732 "Multithread execution policy requires IMT, which is disabled. Changing "
1733 "to ROOT::EExecutionPolicy::kSequential.");
1739 std::vector<std::vector<double>> allGradients(initialNPoints);
1740 for (
unsigned int i = 0; i < initialNPoints; ++i) {
1741 allGradients[i] = mapFunction(i);
1743 g = redFunction(allGradients);
1758 Error(
"FitUtil::EvaluatePoissonLogLGradient",
1759 "Execution policy unknown. Avalaible choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
1768 std::copy(
g.begin(),
g.end(), grad);
1771 std::cout <<
"***** Final gradient : ";
1772 for (
unsigned int ii = 0; ii< npar; ++ii) std::cout << grad[ii] <<
" ";
1781 if (nEvents/ncpu < 1000)
return ncpu;
1782 return nEvents/1000;
#define MATH_ERROR_MSG(loc, str)
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
static const double x2[5]
static const double x1[5]
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
R__EXTERN TVirtualMutex * gROOTMutex
#define R__LOCKGUARD(mutex)
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
double SumOfContent() const
compute the total sum of the data content (sum of weights in case of weighted data set)
double RefVolume() const
retrieve the reference volume used to normalize the data when the option bin volume is set
double GetBinUpEdgeComponent(unsigned int ipoint, unsigned int icoord) const
returns a single coordinate error component of a point.
bool HasBinEdges() const
query if the data store the bin edges instead of the center
const double * GetPointError(unsigned int ipoint, double &errvalue) const
Retrieve the errors on the point (coordinate and value) for the given fit point It must be called onl...
const double * GetPoint(unsigned int ipoint, double &value) const
retrieve at the same time a pointer to the coordinate data and the fit value More efficient than call...
const double * BinUpEdge(unsigned int ipoint) const
return an array containing the upper edge of the bin for coordinate i In case of empty bin they could...
double Value(unsigned int ipoint) const
return the value for the given fit point
ErrorType GetErrorType() const
retrieve the errortype
bool HaveCoordErrors() const
flag to control if data provides error on the coordinates
const double * ValuePtr(unsigned int ipoint) const
return a pointer to the value for the given fit point
void GetBinUpEdgeCoordinates(unsigned int ipoint, double *x) const
Thread save version of function retrieving the bin up-edge in case of multidimensions.
double Error(unsigned int ipoint) const
bool HaveAsymErrors() const
flag to control if data provides asymmetric errors on the value
double SumOfError2() const
compute the total sum of the error square (sum of weight square in case of a weighted data set)
unsigned int Size(unsigned int icoord=0) const
return range size for coordinate icoord (starts from zero) Size == 0 indicates no range is present [-...
void GetRange(unsigned int irange, unsigned int icoord, double &xmin, double &xmax) const
get the i-th range for given coordinate.
unsigned int Size() const
return number of fit points
const double * GetCoordComponent(unsigned int ipoint, unsigned int icoord) const
returns a single coordinate component of a point.
unsigned int NDim() const
return coordinate data dimension
const DataOptions & Opt() const
access to options
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
const DataRange & Range() const
access to range
SimpleGradientCalculator(int gdim, const IModelFunction &func, double eps=2.E-8, int istrat=1)
const IModelFunction & fFunc
std::vector< double > fVec
double ParameterDerivative(const double *x, const double *p, int ipar) const
void Gradient(const double *x, const double *p, double f0, double *g)
unsigned int NDim() const
void ParameterGradient(const double *x, const double *p, double f0, double *g)
unsigned int NPar() const
double DoParameterDerivative(const double *x, const double *p, double f0, int k) const
Class describing the unbinned data sets (just x coordinates values) of any dimensions.
double Weight(unsigned int ipoint) const
return weight
unsigned int NDim() const
return coordinate data dimension
virtual unsigned int NDim() const =0
Retrieve the dimension of the function.
virtual void SetParameters(const double *p)=0
Set the parameter values.
virtual unsigned int NPar() const =0
Return the number of Parameters.
Interface (abstract class) for parametric gradient multi-dimensional functions providing in addition ...
virtual void ParameterGradient(const T *x, const double *p, T *grad) const
Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at ...
OneDimMultiFunctionAdapter class to wrap a multidimensional function in one dimensional one.
void SetCoord(int icoord)
User class for calculating the derivatives of a function.
double Derivative1(double x)
Returns the first derivative of the function at point x, computed by Richardson's extrapolation metho...
A pseudo container class which is a generator of indices.
This class provides a simple interface to execute the same task multiple times in parallel threads,...
auto MapReduce(F func, unsigned nTimes, R redfunc) -> typename std::result_of< F()>::type
Execute a function nTimes in parallel (Map) and accumulate the results into a single value (Reduce).
Type
enumeration specifying the integration types.
@ kGAUSS
simple Gauss integration method with fixed rule
@ kDEFAULT
default type specifiend in the static options
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *x, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the LogL gradient given a model function and the data at the point x.
ROOT::Math::IParamMultiGradFunction IGradModelFunction
ROOT::Math::IParamMultiFunction IModelFunction
double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *x, int iWeight, bool extended, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point x.
void CalculateGradientIntegral(const GFunc &gfunc, const double *x1, const double *x2, const double *p, double *g)
double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the residual contribution to the Chi2 given a model function and the BinPoint data and if th...
double CorrectValue(double rval)
double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
Chi2 Functions.
void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point x.
double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints)
evaluate the effective Chi2 given a model function and the data at the point x.
double EvaluatePoissonBinPdf(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the pdf contribution to the Poisson LogL given a model function and the BinPoint data.
bool CheckInfNaNValue(double &rval)
unsigned setAutomaticChunking(unsigned nEvents)
double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the LogL given a model function and the data at the point x.
void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ::ROOT::EExecutionPolicy executionPolicy=::ROOT::EExecutionPolicy::kSequential, unsigned nChunks=0)
evaluate the Chi2 gradient given a model function and the data at the point x.
double EvaluatePdf(const IModelFunction &func, const UnBinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the pdf contribution to the LogL given a model function and the BinPoint data.
T EvalLog(T x)
safe evaluation of log(x) with a protections against negative or zero argument to the log smooth line...
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
UInt_t GetThreadPoolSize()
Returns the size of ROOT's thread pool.
DataOptions : simple structure holding the options on how the data are filled.
bool fNormBinVolume
normalize data by the bin volume (it is used in the Poisson likelihood fits)
bool fExpErrors
use all errors equal to 1, i.e. fit without errors (default is false)
bool fBinVolume
use integral of bin content instead of bin center (default is false)
bool fCoordErrors
use expected errors from the function and not from the data
double operator()(const double *x, const double *p) const
void SetDerivComponent(unsigned int ipar)
unsigned int NDim() const
ParamDerivFunc(const GradFunc &f)