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
P.S. Also, I’m not sure wether to implement IParamFunction or IParamGradFunction, I’'d have to compute the gradient numerically…
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.
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 …?
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.