TH1::Fit -- Call user-defined function when params change?

Hello Rooters,

I am using TH1::Fit to regress a complicated function on a histogram, like this:

Double_t yAll (Double_t*, Double_t*);
...
TF1 *fyAll = new TF1("fyAll", yAll, 0.0, tMax, nPars);
...
fyAll -> SetParameters(par);
...
TFitResultPtr fit = h1 -> Fit("fyAll", options);
...
Double_t yAll (Double_t *x, Double_t *p) { ...complicated function... }

The Fit routine, of course, starts with some values of the parameters, then evaluates fyAll on the domain (~1000 calls to yAll), then updates the parameters and re-evaluates fyAll on the domain, and so on.

My function yAll is complicated in the sense that it is the sum of many component functions. All of the component functions need access to a set of parameter-dependent values (PDV’s) that depend only on the parameters. Right now I am calculating the PDV’s in every component function, every time yAll is called. So the PDV’s are re-calculated many thousands of times for every one time that they actually change (ie. when the parameters are changed). This shortcut has turned into an appreciable amount of execution time.

My thought would be to make the PDV’s global and write a function that updates the PDV’s and is called immediately after the parameters are updated under Fit. Does ROOT provide a facility for doing this? I have not found such a thing described in the TH1 or TMinuit documentation. I have also tried looking through the source code a bit, but I’m not an expert programmer. Any help would be most appreciated!

I would be glad to make a code example if that would help.

Many thanks,
Shane

Hi,

I understand your problem. You would like to cache for the PDV in your yALL (x,p) function, so when the function is evaluated for the same parameter values the PDV are not re-computed.
Currently this is not supported in the TF1 object, I am planning to introduce this in the future for this reasons. It helps for example when a normalisation integral of the function needs to be computed and this depends only on the parameters p and not on the observables x.
The only solution for you right now is to check inside your yALL function that the parameter values are the same of the previous function call.
I remind you that you can make your yALL function as a class (a functor object) and create the TF1 from this object. You can store the parameter values of the previous call in the class together with the cache PDF.
See root.cern.ch/root/html/TF1.html#F4

Best Regards

Lorenzo

Thanks!