Fit a Functor implementing :Math::IParamGradFunction to TH1?

Hello Dear ROOT Math Team,

I would like to fit a Function to a histogram which I implemented using an c++ object.

I suppose I could create a TF1* Object using a static or global c function, but i don’t really like that (there will be many functors and histos, and i would need to fiddle around with the one global function, would I?)

Also I had a look on how the fitting is implemnted in root 5.22, and I found out, that the TF1 is wrapped by an Object implementing the ROOT::Math::IParamGradFunction interface.

As this is pretty much how I like to write the code, I’m considering to directly implement this interface and use the classes i found in the ROOT::Fit namespace (ROOT::Fit::Fitter, ROOT::Fit::FitConfig, ROOT::Fit::BinData, ROOT::Fit::ParameterSettings) to do the fit.

Do you think that this is advisable, or will these classes change in coming versions? is there documentation about these objects, interfaces, which i missed? (I only found the classes in doxygen, I think.)

Advice is very welcome, kind regards
Dirk

P.S. Also, I’m not sure wether to implement IParamFunction or IParamGradFunction, I’'d have to compute the gradient numerically…

Hello Dirk,

you can create also a TF1 now from a C++ functor implementing
operator() (double *, double *) or from a member function.
See the tutorial $ROOTSYS/math/exampleFunctor.C

For fitting, you can use also directly the ROOT::Fit classes via a function implementing the ROOT::Math::IParamMultiFunction interfaces.
(see the documentation of the ROOT::Fit::Fitter class)
I attach an example of using the derivatives, if you know them analytically it is normally better, since you can minimize a potential numerical error.

At the moment there is no extra doc than the reference one.
I should probably add some more, like online page and some tutorials. There are some tests program in $ROOTSYS/math/mathcore/test/fit
I am not expecting to change these classes in the coming versions, there will be only bug fixes and maybe some small improvements.

Best Regards

Lorenzo
exampleGradFit.C (4.09 KB)

Ah, thanks for your reply, I overlooked that possibility (TF1 from functor), its working fine now!

I have a related question:
I might want to use my own version of a likelihood, (because i want to assign an uncertainty to the model/fit function, which depends on the x-axis/bin)

I found the ROOT::Math::Minimizer plugin functionality allowing to use Minuit (or other minimizers) for minimizing a function inheriting from IBaseFunctionMultiDim.

This is indeed very neat and convenient, the only problem I have is, that the function evaluation in IBaseFunctionMultiDim is constrained to be a const function and I cannot comply to this without a major change of my models…
(virtual double DoEval(const double* x) const)

Have, I missed something again, or is this restriction actually valid?

Thanks for your help

P.S. actually… it just comes to my mind… how does WrappedTF1 work then, because the TF1::EvalPar is not const …?

Hi,
this restriction is there, because the minimization code might use this in same cases like when performing parallel calculations using multiple threads on a shared function object. The function object might contain all your fitting data, so you don;t want to copy it.

However, if in your case you need a non const pointer, you should be able to go around with some C++ tricks, from using a mutable objects inside or by forcing it with a const_cast.

Best Regards

Lorenzo

Thanks for that clarification, as I’m not using threads at all, I assume I can safely circumvent this!

Nevertheless, from my restricted point of view a non-multithreading version of this interface allowing to avoid a mutuable/const-cast construction seems desirable :slight_smile:

Thanks alot for the support, I apreciate it!