Hello,
After fitting a TF1 to a dataset, I want to obtain the standard deviation of its predictions.
Following the ConfidenceIntervals.C tutorial and the ROOT::Fit::FitResult documentation, I tried the non-deprecated GetConfidenceIntervals()
functions with no success:
std::vector<double> GetConfidenceIntervals(double cl, bool norm)
returns an empty vector.void GetConfidenceIntervals(unsigned int n, unsigned int stride1, unsigned int stride2, const double * x, double * ci, double cl, bool norm)
doesn’t change the value ofci
.- When trying to re-implement the latter function by myself, I noticed
const IModelFunction * FittedFunction()
is returning a null, which may be intended behavior according to the following sentence in the class’ documentation:
only with FCN only fits, when fFitFunc=0
The following snippet should reproduce my issue:
#include <iostream>
#include <Fit/BinData.h>
#include <Fit/DataOptions.h>
#include <Fit/Fitter.h>
#include <Fit/FitResult.h>
#include <Fit/Chi2FCN.h>
#include <Math/WrappedMultiTF1.h>
#include <HFitInterface.h>
#include <TF1.h>
#include <TH1D.h>
double Constant(double const *const /*x*/, double const *const par)
{
return par[0];
}
int Example()
{
constexpr size_t nevents{10000};
constexpr size_t nbins{100};
constexpr double xmin{0}, xmax{15};
constexpr size_t npar{1};
constexpr double initial_parameters[npar]{2};
TF1 *func_gen{new TF1{"func_gen", Constant, xmin, xmax, npar}};
func_gen->SetParameters(initial_parameters);
TH1D *hist{new TH1D{"hist", "Random", nbins, xmin, xmax}};
hist->FillRandom(func_gen->GetName(), nevents);
hist->Scale(func_gen->Integral(xmin, xmax) / nevents * nbins / (xmax - xmin));
ROOT::Fit::Fitter fitter{};
fitter.Config().SetParamsSettings(npar, initial_parameters);
ROOT::Fit::DataOptions opt{};
ROOT::Fit::DataRange range{xmin, xmax};
ROOT::Fit::BinData bindata{opt, range};
ROOT::Fit::FillData(bindata, hist);
TF1 *func_fit{new TF1{"func_fit", Constant, xmin, xmax, npar}};
ROOT::Math::WrappedMultiTF1 wf{*func_fit, 1};
ROOT::Fit::Chi2Function fcn{bindata, wf};
fitter.FitFCN(npar, fcn, 0, bindata.Size(), true);
const auto result{fitter.Result()};
func_fit->SetFitResult(result);
func_gen->SetLineColor(kRed);
hist->GetListOfFunctions()->Add(func_gen);
func_fit->SetLineColor(kBlue);
hist->GetListOfFunctions()->Add(func_fit);
hist->Draw();
result.Print(std::cout);
std::cout << "result.GetConfidenceIntervals().size() = " << result.GetConfidenceIntervals().size() << std::endl;
double x{1.}, err{42.};
result.GetConfidenceIntervals(1, 1, 1, &x, &err);
std::cout << "err [result.GetConfidenceIntervals(1, 1, 1, &x, &err)] = " << err << std::endl;
std::cout << "result.FittedFunction() = " << result.FittedFunction() << std::endl;
return 0;
}
In this case, replacing the use of ROOT::Fit
with hist->Fit(func_fit)
and (TVirtualFitter::GetFitter())->GetConfidenceIntervals(grint)
is likely enough to get the results I want.
However my particular application is is derived from the combinedFit.C tutorial for fitting two functions with common parameters.
Best regards,
Bruno Oliveira
ROOT Version: 6.26/06 (pacman -S root
)
Platform: Arch Linux
Compiler: Cling