// test fitting with a user provided fcn #include "TF1.h" #include "TGraph.h" #include "Fit/BinData.h" #include "TVirtualFitter.h" #include "TRandom2.h" #include "RVersion.h" #include "Math/Math.h" #include "HFitInterface.h" ROOT::Fit::BinData * data; void FCN(Int_t &, Double_t *, Double_t & chi2, Double_t * p, Int_t ) { // calculate chi2 from user provided FCN // chi2 is computed adding a regularization term assert(TVirtualFitter::GetFitter() ); TF1 * func = (TF1*) (TVirtualFitter::GetFitter() )->GetUserFunc(); chi2 = 0; double loglambda = -10; double lambda = exp(loglambda); int npar = func->GetNpar(); for (unsigned int i = 0; i < data->Size(); ++i) { const double * x = data->Coords(i); double y = data->Value(i); double w = data->InvError(i); double fval = func->EvalPar((double *)(x),p); double res = w * ( y - fval); chi2 += res*res; // add regularization term double pnorm = 0; for (int j = 0; j < npar; ++j) pnorm += p[j]*p[j]; chi2 += lambda * pnorm; } } void testFitUser() { // generate points according to a sin(pi); const int N = 100; double x[N]; double y[N]; TRandom2 r(0); double sig = 0.2; for (int i = 0; i < N; ++i) { x[i] = r.Uniform(0,1); y[i] = sin( 2 * M_PI * x[i]) + r.Gaus(0,sig); } TGraph * g = new TGraph(N,x,y); g->SetMarkerStyle(20); g->Draw("AP"); // now fit TF1 * f1 = new TF1("f1","pol9",0,1); // f1->SetLineColor(kBlue); // g->Fit(f1); // fit using FCN function data = new ROOT::Fit::BinData; ROOT::Fit::BinData & d = *data; ROOT::Fit::FillData(d, g,f1); TVirtualFitter::Fitter(g)->SetFCN(FCN); f1->SetLineColor(kRed); g->Fit(f1,"U+"); delete data; }