Pyroot and Minuit

Hello,
I’m trying to use PyRoot and Root’s minuit interface. The problem is that I don’t know how to tell minuit what function to minimize. In C++, I would just:

   chisqMinuit = new TMinuit(1);
   chisqMinuit->SetFCN(chisq_fcn);

where chisq_fcn() is defined like:

void chisq_fcn(Int_t &npar, Double_t *gin, Double_t &chisq, 
               Double_t *par, Int_t iflag)

Is it possible to write the equivalent function in python and have Minuit call it?

Is it possible to write and compile a C++ function and then tell PyRoot to use it?

Thanks,
Charles

Charles,

having C++ call Python functions is not trivial, because I need to have
a way of associating the Python callable with the C++ function.

You do not post which version of ROOT you are using, but version 4.01/02
allows you to initialize a TF1 with a Python callable and then use it to fit
histograms (where the fitting is done by minuit). Thus, something works,
but I don’t see whether you can actually use a TF1 directly with TMinuit.

As for use of C++ functions from Python … I’ll give you a decent chance
if you use class statics, and then pass the parameter to SetFCN(), but I
haven’t tried, so maybe it just goes boom.

Allow me some time to look into it later.

Best regards,
Wim

Hi Wim,

That was my guess. :frowning:

 I'm using 4.00/08 currently.   Do I need to upgrade to be able to initialize a TF1 with a Python callable?  This sounds pretty close to what I want to be able to do.
 Am I correct that as long as my makefile knows about both 'python.h' and the root libraries, that I ought to be able to write a mini-wrapper of Minuit (using static classes to hold the function and parameters)?  Do you have an example of a [b]Makefile[/b] that would let me do this?  (This solution isn't as "pretty" as making minuit call a python callable, but probably has a faster execution time.)

 Thanks for your help,
    Charles 

p.s. I’m currently trying to do this on cygwin. I’ll eventually want to be able to do it on Red Hat linux as well.

Hi,

I fit histogram in Perl like this:

# Create a Fit_jpsi_mass object
my $fit = new Jpsi::Fit_jpsi_mass ($histogram);

# initiallize the parameters
$fit->initialize_fit_parameters ();

# get a pointer on the fit function 
my $fit_function = $fit->get_fit_function ();

# Call Fit with this pointer
$histogram->Fit ($fit_function, "RV");

Jpsi is a C++ library wrapped in Perl, as Root.
The class Fit_jpsi_mass contains the fit method and utilities functions.

I think use Script function in fit procedure is to slow. So, the
best is to use an “extension” C++ library like this.

Charles,

just back from CHEP …

I’m using 4.00/08 currently. Do I need to upgrade to be able to initialize a TF1 with
a Python callable?

Yes, the code is not included in that release. Its first public appearance is 4.01/02.

Am I correct that as long as my makefile knows about both ‘python.h’ and the root
libraries, that I ought to be able to write a mini-wrapper of Minuit (using static
classes to hold the function and parameters)? Do you have an example of a Makefile
that would let me do this?

Ehrm, I’m not quite sure in which direction you’re thinking, but I simply (ab)use
ACLiC. First, have a test.h:

[code]class Hello {
public:
static double SayHi( double );
};

void test();[/code]

and then a test.cxx:

[code]#include “test.h”
#include

double Hello::SayHi( double d ) {
std::cout << “Hello World!” << std::endl;
return d;
}

void test() {
std::cout << “done processing” << std::endl;
}[/code]

using ACLiC:

$ root -b -q test.cxx++

which gives you test_cxx.so, and then use it like so:

$ python

from ROOT import *
gSystem.Load( “test_cxx” )
print Hello.SayHi( 1 )
Hello World!
1.0

Functions like this can be used in TF1, if they have a double () ( double, double* )
signature that is. But you can’t get hold of the pointer, though. Will implement …

Best regards,
Wim

Hi,

as a (belatedly) follow up: the TMinuit::SetFCN() accepts python functions in ROOT 5.04. Note however, that the usual caveats when using references to builtins in the function signature apply, and to be able to “push” results by reference out of the function, you’ll need to dereference them on assignment as if they were passed by pointer instead of by ref (they are, sortof).

The following function is a working example:

[code]def fcn( npar, gin, f, par, iflag ):
nbins = 5

calculate chisquare

chisq, delta = 0., 0.
for i in range(nbins):
delta = (z[i]-func(x[i],y[i],par))/errorz[i]
chisq += delta*delta

f[0] = chisq[/code]

See the attached file for the full example that I lifted from an Atlas colleague of mine (thanks Chris! :wink: ). More details will be written up in the manual with the next pro version of ROOT.

HTH,
Wim

Hi,

there was a technical problem … please see attach for the promised fit example.

Cheers,
Wim
testfit.py (2.31 KB)

Hi Wlav,
is there any chance that you have an
updated version of your “testfit.py

Many thanks,

  • Mauro.

testfit.py (2.39 KB)

Many thanks.

I have a couple of questions:

(1) I see that inside def fcn( npar, gin, f, par, iflag ):
You do not use all the parameters.
For instance, instead of using f you use func.

(2) You define nbins inside fcn, and not thorough calling sequence.

(3) Thee vectors x, y, z are global variables.

(4) Are the arrays strictly necessary? Can’t we use tuples.

Many thanks again.

  • Mauro.

Mauro,

you’re asking on an 11+ year old thread about a code example that I lifted at the time from someone else … Most likely the answer to all your questions is “because reasons” …

Here are some guesses …

Ad 1) f is a double&, and func is a python function. I don’t understand why you think one can be used instead of the other, so I think each is used where they are supposed to. When writing on this thread 11+ years ago, I already had not used minuit for years. I have no idea anymore what the other parameters are for.

Ad 2) Probably done as a speedup. The callback mechanism is slow. There’s some opportunity to fix this with Cling and CFFI but I’m no longer maintaining PyROOT so if that is of importance to you, I suggest you file a JIRA feature request ticket.

Ad 3) This is a simple example. One could also define a callable class (i.e. one that has a call function with the same signature as fcn) and make them (instance) data members.

Ad 4) ‘arglist’ yes, as it’s passed through C++ as a ‘double*’ (a tuple is, roughly speaking, an array of PyObject*, so type PyObject**). It can also be a numpy array, or more generally anything that exposes a proper PyBuffer or Capsule interface. The others are python-only, so can be anything you like.

Cheers,
Wim