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?

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)

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