TMinuit in PyRoot

Hi,
I want to fit several histograms with a shared parameter, so I’m doing it by using TMinuit directly.
To speed up the fitting I’m using a compiled function as the minimization function while I still want to do the setup in PyRoot. I get an exception.
I’ve reduced the problem to this:
in fit.cxx:

void My_FCN(Int_t&, Double_t*, Double_t&f, Double_t*par, Int_t){
	f=par[0]*par[0];
}

in fit.py:

import ROOT
ROOT.gROOT.ProcessLine(".L fit.cxx+")
fitter=ROOT.TMinuit(1)
fitter.SetFCN(ROOT.My_FCN)
fitter.DefineParameter(0,"p0",1,1,0,0)
fitter.Migrad()

After the setup phase I get the following output:

...
 **********
 **    1 **MIGRAD
 **********
 FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.
TypeError: void ::My_FCN(Int_t&, Double_t*, Double_t& f, Double_t* par, Int_t) =>
    could not convert argument 1
Traceback (most recent call last):
  File "fit.py", line 6, in <module>
    fitter.Migrad()
Exception: TMinuit python fit function call failed (C++ exception)

The strange thing is that the following c++ code works both compiled and interpreted:

#include "fit.cxx" #include <TMinuit.h> void FitROOT(){ TMinuit* fit= new TMinuit(1); fit->SetFCN(My_FCN); fit->DefineParameter(0,"p0",1,1,0,0); fit->Migrad(); }
I would have regarded the c++ code and the Python code to be equivalent.
My ROOT version is
ROOT 5.29/01 (trunk@38210, Feb 25 2011, 09:57:26 on macosx64)
my python version is Python 2.7.1.
Any thoughts on why this fails?

Hi,

there are a couple of issues, but what it comes down to is that the parameters created by the stub function to had to python are expected to work in a real python function.

Now fixed in trunk, but do note that this setting does not peel away the python layer (it’s not trying to locate the C++ function and passing that). Consequently, you’re unlikely to get a speedup this way.

Cheers,
Wim

Hi, thanks a lot Wim,
I have noticed that I might want to use Minuit2 anyways. I’ve set up a quick testcase following the example in math/minuit2/test/testMinimize.cxx, again compiling the function and doing the configuring in PyRoot. This seems to work perfectly well.
What are your thoughts on speed there?
Cheers
Simon

Simon,

same problem. If you put the function in C++ anyway, you’re better of calling the SetFCN on the C++ side as well.

At issue is that the calling of python functions works by setting up a custom stub for CINT and handing that to SetFCN. Since creating C++ functions on the fly isn’t supported by the language (it’s easy to do, but not easy to do without setting off virus scanners :slight_smile: ), I’m reusing one stub function wherein the python callable is looked up. On top of that, there’s the translation of variables from C++ -> python -> C++ in your case. All that is much more than the code in the fit function itself.

This is actually a great case to solve with PyPy. Now only if I had time to work on that. :frowning:

Cheers,
Wim