Home | News | Documentation | Download

Problem fitting a graph

Hello! I have a TGraphErrors, i’m trying to fit with the following function:

Double_t fitf(Double_t *x, Double_t *par, Double_t *beta)
{
Int_t i;

Double_t fitval=par[1]*pow((x[0]/700),-beta[i])*pow((1+x[0]/700),-beta[i]);

return fitval;
}

I plot the points with the TGrapherrors class. The vector beta is a random Gaussian vector, so I have to fit my points 50 times, so I do:
TF1 *func = new TF1(“fit”,fitf,0.0,2500.0,3);

for (int i=0; i<Events; i++)
{
gr.Fit(&func);
gr.DrawClone(“SAME”);
}

for the fitting, but when I try to ejecute the macro, it appears the errors:

error: no matching member function for call to 'Fit’

and

candidate function not viable: no known conversion from ‘TF1 **’ to
‘const char *’ for 1st argument
virtual TFitResultPtr Fit(const char *formula ,Option_t *option="" ,O…

and I don’t know how to fix it.

Thank you in advance!

First: TF1 → 4 - A general C function with parameters

Then: you must set initial values for all parameters (before trying to fit).

Finally: gr.Fit(func);

I keep having mistakes
I have just done:

TF1 *func = new TF1(“fit”,fitf,0.0,2500.0,3);

func->SetParameters(0,1);
func->SetParNames("constant","coefficient");
func->Draw();

    
for (int i=0; i<Events; i++)
{
   gr.Fit(func);
   gr.DrawClone("SAME");
}

And the error is:

/Users/root_install/include/TF1.h:726:104: error: type ‘double (double *, double *, double )’ cannot be used prior to ‘::’
because it has no members
…ROOT::Internal::GetFunctorType<decltype(ROOT::Internal::GetTheRightOp(&F…
^
/Users/root_install/include/TF1.h:370:41: note: in instantiation of member function 'ROOT::Internal::TF1Builder<double
(
)(double *, double *, double )>::Build’ requested here
ROOT::Internal::TF1Builder::Build(this, f);
^
/Users/root_install/macros/signal.C:62:21: note: in instantiation of function template specialization 'TF1::TF1<double (
)(double
*, double *, double )>’ requested here
TF1 func = new TF1(“fit”,fitf,0.0,2500.0,3);
^
In module ‘MathCore’:
/Users/root_install/include/Math/ParamFunctor.h:125:39: error: too few arguments to function call, expected 3, have 2
return (f)((T)x, (double
)p);
~~~~ ^
/Users/root_install/include/Math/ParamFunctor.h:95:45: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::FuncEvaluator<double ()(double
*, double *, double ), int>::EvalConst’ requested here
return FuncEvaluator<Func, EvalType>::EvalConst(fFunc,x,p);
^
/Users/root_install/include/Math/ParamFunctor.h:73:4: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::operator()’ requested here
ParamFunctorHandler(const Func & fun) : fFunc(fun) {}
^
/Users/root_install/include/Math/ParamFunctor.h:304:17: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::ParamFunctorHandler’ requested
here
fImpl(new ParamFunctorHandler<ParamFunctorTempl,Func>(f) )
^
/Users/root_install/include/TF1.h:728:66: note: in instantiation of function template specialization
'ROOT::Math::ParamFunctorTempl::ParamFunctorTempl<double (
)(double
*, double *, double )>’ requested here
f->fFunctor.reset(new TF1::TF1FunctorPointerImpl<Fnc_t>(ROOT::M…
^
/Users/root_install/include/TF1.h:370:41: note: in instantiation of member function 'ROOT::Internal::TF1Builder<double
(
)(double *, double *, double )>::Build’ requested here
ROOT::Internal::TF1Builder::Build(this, f);
^
/Users/root_install/macros/signal.C:62:21: note: in instantiation of function template specialization 'TF1::TF1<double (
)(double
*, double *, double *)>’ requested here
TF1 func = new TF1(“fit”,fitf,0.0,2500.0,3);
^
In module ‘MathCore’:
/Users/root_install/include/Math/ParamFunctor.h:121:26: error: too few arguments to function call, expected 3, have 2
return (*f)(x, p);
~~~~ ^
/Users/root_install/include/Math/ParamFunctor.h:91:45: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::FuncEvaluator<double ()(double
*, double *, double ), int>::Eval’ requested here
return FuncEvaluator<Func, EvalType>::Eval(fFunc,x,p);
^
/Users/root_install/include/Math/ParamFunctor.h:73:4: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::operator()’ requested here
ParamFunctorHandler(const Func & fun) : fFunc(fun) {}
^
/Users/root_install/include/Math/ParamFunctor.h:304:17: note: in instantiation of member function
'ROOT::Math::ParamFunctorHandler<ROOT::Math::ParamFunctorTempl,
double (
)(double *, double *, double )>::ParamFunctorHandler’ requested
here
fImpl(new ParamFunctorHandler<ParamFunctorTempl,Func>(f) )
^
/Users/root_install/include/TF1.h:728:66: note: in instantiation of function template specialization
'ROOT::Math::ParamFunctorTempl::ParamFunctorTempl<double (
)(double
*, double *, double )>’ requested here
f->fFunctor.reset(new TF1::TF1FunctorPointerImpl<Fnc_t>(ROOT::M…
^
/Users/root_install/include/TF1.h:370:41: note: in instantiation of member function 'ROOT::Internal::TF1Builder<double
(
)(double *, double *, double )>::Build’ requested here
ROOT::Internal::TF1Builder::Build(this, f);
^
/Users/root_install/macros/signal.C:62:21: note: in instantiation of function template specialization 'TF1::TF1<double (
)(double
*, double *, double *)>’ requested here
TF1 *func = new TF1(“fit”,fitf,0.0,2500.0,3);

Hi @marguiitar,

I think that the fitf function (quoted below) should only take 2 arguments. However, I am sure @jonas can you provide a more detailed answer to your issue.

Cheers,
J.

Hi! But the problem is that my fitting function depends on a random vector that I have to pass as a parameter… how could I do it?

Thank you in advance!

TF1 → 5 - A general C++ function object (functor) with parameters
TF1 → 6 - A member function with parameters of a general C++ class

Thank you very much!
I have just define the random number inside the function:

Double_t fitf(Double_t *x, Double_t *par)
{
Int_t i;
TRandom3 r;

Double_t fitval=par[1]*pow((x[0]/700),-r.Gaus(2.4,0.24))*pow((1+x[0]/700),-r.Gaus(2.4,0.24));

return fitval;
}

However I have to fit my points 50 times, so I do:

TF1 *func = new TF1(“fit”,fitf,0.0,2500.0,2);

func->SetParameters(0,1.0);
func->SetParameters(1,1.0);

for (int i=0; i<50; i++)
{
   gr.Fit(func);
   gr.DrawClone("SAME");
}

It fit my points but only one time, could you tell me if are there any error?

Thank you very much

If you fit 50 times the same graph with the same function, why do you expect to see different results?

Because r.Gaus(2.4,0.24) is random, so if I call it 50 times it should be 50 different functions, isn’t it?

TRandom3 r(0); // make it really random

// root -l trial.cxx
#include <cmath>
#include "TF1.h"
#include "TRandom3.h"
#include "TPad.h"
Double_t fitf(Double_t *x, Double_t *p) {
  return p[0] * std::pow((x[0] / 700.), -p[1]) * std::pow((1. + x[0] / 700.), -p[1]);
}
void trial(void) {
  TF1 *func = new TF1("fit", fitf, 1.0, 2500.0, 2);
  func->SetParNames("constant", "beta");
  func->SetNpx(10000);
  TRandom3 r(0); // make it really random
  for (int i = 0; i < 50; i++) {
    func->SetParameter(0, 1.0); // free parameter ("constant")
    func->FixParameter(1, r.Gaus(2.4, 0.24)); // fixed parameter ("beta")
#if 1 /* 0 or 1 */
    func->DrawClone(i ? "SAME" : "");
#else /* 0 or 1 */
    gr.Fit(func);
    gr.DrawClone(i ? "SAME" : "ALP");
#endif /* 0 or 1 */
  }
  if (gPad) gPad->SetLogy(1);
}

Thank you very much!!
My last question, what really means func->DrawClone(gPad ? “SAME” : “”);?
is not the same as gr.DrawClone(“SAME”)? gr is my TGraphErrors gr(…)

You may need something like this (also, using “i” instead of “gPad” will make it more reliable):
gr.DrawClone(i ? "SAME" : "ALP");