458 assert(h !=
nullptr);
461 stream <<
"im = " << im <<
", iM = " << iM <<
'\n';
463 unsigned int nbins = iM-im+1;
465 stream <<
"nbins = " << nbins <<
'\n';
468 double m = h->GetBinLowEdge(im),
469 M = h->GetBinLowEdge(iM+1);
471 stream <<
"m = " << m <<
", M = " << M <<
'\n';
473 Polynomial<T,Log,Exp> pol(maxdegree, m, M, stream);
474 Correlator cor(h, cov, im, iM, pol, stream);
475 ROOT::Math::Functor functor(cor, pol.npars);
477 auto minimiser = ROOT::Math::Factory::CreateMinimizer(
"Minuit2",
"Migrad");
478 const int Ncalls = 1e6;
479 minimiser->SetMaxFunctionCalls(Ncalls);
480 minimiser->SetFunction(functor);
481 minimiser->SetTolerance(0.001);
482 minimiser->SetPrintLevel(
verbose);
484 double fm = Log(h->GetBinContent(im)),
485 fM = Log(h->GetBinContent(iM));
487 double p0 = (fM+fm)/2, p1 = (fM-fm)/2;
488 minimiser->SetVariable(0,
"p0",p0,step);
489 minimiser->SetVariable(1,
"p1",p1,step);
490 for (
unsigned int d = 2; d <= maxdegree; ++d) {
491 minimiser->SetVariable(d,Form(
"p%d", d),0.,step);
492 minimiser->FixVariable(d);
497 chi2s.push_back({
false,
inf, nbins-2, {p0,p1}});
500 while (
chi2s.size() <= maxdegree) {
501 unsigned int degree =
chi2s.size();
502 minimiser->ReleaseVariable(degree);
503 bool valid = minimiser->Minimize();
505 const double * X = minimiser->X();
506 assert(X !=
nullptr);
507 double chi2 = cor(X);
509 assert(isnormal(chi2));
510 unsigned int npars = minimiser->NFree(),
512 assert(npars == degree+1);
514 const auto& former =
chi2s.back();
515 chi2s.push_back({valid, chi2, ndf, vector<double>(X,X+npars)});
516 auto& current =
chi2s.back();
518 switch (minimiser->Status()) {
519 case 0: stream << current;
522 bool plateau = current.x2n() > former.x2n(),
523 goodchi2 = abs(current.x2n()-1) <= stopParam*current.x2nErr();
525 stream <<
red <<
"Chi2/ndf has increased.\n" <<
def;
527 stream <<
green <<
"Chi2 ~ ndf.\n" <<
def;
533 ftestRes =
Ftest(former, current);
534 stream <<
"F-test result: " << ftestRes <<
'\n';
536 catch (
double) { stream <<
red <<
"No F-test possible.\n" <<
def; }
537 bool fvalid = ftestRes > stopParam;
542 current.chi2sT.reserve(nrep);
543 current.chi2sV.reserve(nrep);
544 for (UInt_t seed = 1; seed <= nrep; ++seed) {
545 cor.SetReplica(seed);
546 for (
unsigned int i = 0; i <= degree; ++i)
547 minimiser->SetVariableValue(i, current.X[i]);
548 const double * X = minimiser->X();
549 assert(X !=
nullptr);
550 current.chi2sT.push_back(cor(X));
551 cor.SetReplica(seed+nrep);
552 current.chi2sV.push_back(cor(X));
555 for (
unsigned int i = 0; i <= degree; ++i)
556 minimiser->SetVariableValue(i, current.X[i]);
558 xvalFrac =
Xval(current, former);
560 bool xvalid = 1.-xvalFrac > stopParam;
562 stream <<
"Fraction of validation replicas with better fit Chi2/ndf = " << (xvalid ?
green :
red) << xvalFrac <<
def <<
'\n';
568 found = plateau || goodchi2;
583 case 1: stream <<
red <<
"Warning: Fit parameter covariance was made positive defined\n" <<
def;
584 for (
unsigned int i = 0; i < npars; ++i) {
585 for (
unsigned int j = 0; j < npars; ++j)
586 stream << setw(12) << minimiser->CovMatrix(i,j);
590 case 2: stream <<
red <<
"Warning: Hesse is invalid\n" <<
def;
592 double * hessian =
nullptr;
593 minimiser->GetHessianMatrix(hessian);
594 assert(hessian !=
nullptr);
595 for (
unsigned int i = 0; i < npars; ++i) {
596 for (
unsigned int j = 0; j < npars; ++j)
597 stream << setw(12) << hessian[i*pol.npars + j];
602 case 3: stream <<
red <<
"Warning: Expected Distance reached from the Minimum (EDM = " << minimiser->Edm() <<
") is above max\n" <<
def;
604 case 4: stream <<
red <<
"Warning: Reached call limit (Ncalls = " << Ncalls <<
")\n" <<
def;
607 default: stream <<
red <<
"Warning: Unknown failure\n" <<
def;
613 stream <<
"Correlations of the fit parameters:\n";
614 for (
unsigned int i = 0; i < npars; ++i) {
615 for (
unsigned int j = 0; j < npars; ++j)
616 stream << setw(12) << minimiser->Correlation(i,j);
621 if (current.ndf == 2) {
622 stream <<
red <<
"Only 2 d.o.f. left. Stopping.\n" <<
def;
630 const char *
name = Form(
"smooth_%s", h->GetName());
632 stream <<
"Best result: " <<
f->GetTitle() <<
"\n-----\n";
634 stream <<
bold <<
"Running F-test:\n" <<
def;
638 stream <<
bold <<
"Running Cross-validation:\n" <<
def;