Passing a function defined in python to TF1

I am stuck on how to use a function defined in python as a user defined function input to TF1 ideally I would like to do something like this:


def crystalball(x,n,alpha,c,sigma,sa,ba,slope):
    if (x-c)/sigma < -alpha:
        bgkd = ba+slope*x
        term1 = ((n/abs(alpha))**n)
        term2 = math.exp(-(alpha**2)/2)
        term3 = n/abs(alpha)-abs(alpha)-(x-c)/sigma
        term4 = term3**n
        y = (bgkd+sa*term1*term2/term4)
    else:
        y = ((ba+x*slope)+sa*math.exp(-(((x-c)/sigma)**2)/2))
    return y


#low and high previously calculated
fit1 = TF1( 'fit1', crystalball(x,[0],[1],[2],[3],[4],[5],[6]),  low,  high )
#TH1I initialized as h previously

h.Fit( fit1 , 'R' )

Is this possible?

thanks in advance,

Cameron

Some progress. From reading previous forum posts I defined the function with just two inputs:


def crystalball(x,par):
    """
    n:par[0]
    alpha:par[1]
    centroid:par[2]
    sigma:par[3]
    peak amplitude:par[4]
    background amplitude:par[5]
    slope:par[6]
    """
    if (x[0]-par[2])/par[3] < -par[1]:
        #print x
        bgkd = par[5]+par[6]*x[0]
        term1 = ((par[0]/abs(par[1]))**par[0])
        term2 = math.exp(-(par[1]**2)/2)
        term3 = par[0]/abs(par[1])-abs(par[1])-(x[0]-par[2])/par[3]
        #print bgkd
        term4 = pow(float(term3),float(par[0]))
        y = (bgkd+par[5]*term1*term2/term4)
    else:
        y = ((par[5]+x[0]*par[6])+par[4]*math.exp(-(((x[0]-par[2])/par[3])**2)/2))
    return y


fit1 = TF1( 'fit1', crystalball,  low,  high, 7)

fit1.SetParameters(1,1,energy,energy*1.5/(662*2.34),spectra.returnheight(energy),100,0)

h.Fit( fit1 , 'R' )

but I get the error :
File “python/peakfit.py”, line 189, in fitpeaks
h.Fit( fit1 , ‘R’ )
TypeError: none of the 2 overloaded methods succeeded. Full details:
TFitResultPtr TH1::Fit(const char* formula, Option_t* option = “”, Option_t* goption = “”, Double_t xmin = 0, Double_t xmax = 0) =>
could not convert argument 1 (expected string or Unicode object, TF1 found)
TFN python function call failed (C++ exception)

again thanks in advance

Cameron

Cameron,

is there no earlier error originating from the chrystalball function? That would be printed just above the portion that you quote?

In the code itself, I can’t see anything wrong directly (assuming ‘math’ has been imported above).

A working example can be found in the ROOT nightly tests: https://root.cern.ch/svn/roottest/trunk/python/function/PyROOT_functiontests.py. Look for ‘pygaus’.

Cheers,
Wim

Wim,

thanks for the quick response. You were correct I had not set the limits on my parameters well and it was crashing when trying to take a negative number to a non-integer power, after I fixed that there were no problems. Thanks for the link to the example code too, its given me some ideas on how to simplify and extend the analysis.

-Cameron

Link to https://root.cern.ch/svn/roottest/trunk/python/function/PyROOT_functiontests.py is broken.