PyRoot Fitting Error

Hi, I’m looking into fitting with pyroot and got an example which I cannot make work.

In the example I try to fit a gaus to a histogram but I keep getting Error messages.

The code looks like this:

class myGaus:
    def __call__( self, t, par ):
        a = par[0] #amplitude
        c = par[1] #center
        s = par[2] #sigma
        x = t[0]   
        tmp = -1.*(x-c)*(x-c)/2. /(s*s)
        return a * math.exp( tmp )


c1 = ROOT.TCanvas( 'c1', 'canvas title' )


xbin = 100
xmin = -3.
xmax =  3.
h1 = ROOT.TH1F( 'h1', 'histogram 1; x axis; y axis', xbin, xmin, xmax )

center = 0.1
sigma  = 0.5 
for i in range( 10000 ):
    g = ROOT.gRandom.Gaus(center, sigma)
    h1.Fill(g)

fit_range1 = -3.
fit_range2 =  3.
parN = 3
func = ROOT.TF1("myfunction1", myGaus(), fit_range1, fit_range2, parN )

func.SetParameters(1., 0.1, 0.5)

h1.Fit(func)

It is the last line h1.Fit(func) that gives me the error:

TypeError: none of the 2 overloaded methods succeeded. Full details:
  TFitResultPtr TH1::Fit(TF1* f1, const char* option = "", const char* goption = "", double xmin = 0, double xmax = 0) =>
    TypeError: myGaus() takes no arguments
  TFitResultPtr TH1::Fit(const char* formula, const char* option = "", const char* goption = "", double xmin = 0, double xmax = 0) =>
    TypeError: could not convert argument 1 (bad argument type for built-in operation)

I don’t see what could be wrong. Any ideas?

Weird… Maybe @etejedor has an idea?

Hello,

The problem is in this line:

func = ROOT.TF1("myfunction1", myGaus(), fit_range1, fit_range2, parN )

myGaus() is creating the Python callable to pass it as an argument for the TF1 constructor, but it is a temporary (i.e. it will be immediately garbage collected by Python after the call to the constructor). This means it will not be alive when you call Fit, hence the error.

To fix the code, you can do:

mygaus = myGaus()
func = ROOT.TF1("myfunction1", mygaus, fit_range1, fit_range2, parN )
2 Likes

That did the trick! Many thanks!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.