Plotting 1D function with arguments

Hello,
I would like to plot simple 1D function with some arguments.

Example:
def myf(x,a=3,b=4,c=7):
y=sin(x)*a-b+x/c
return y

How can I plot this function with pyroot ?
I tried:

from ROOT import *
f=TF1(‘f’,myf,0.,10.)
f.Draw()

which give a segmentation violation.
I tried with x[0] with no success.

With PAW, it was simple:
a=3.; b=4.; c=7.
f/pl sin(x)*[a]-[b]+x/[c] 0. 3.

Thanks for help,
Cheers,
Olivier

PS: the following works, but is heavy with many parameters:
def myfun(x,par) :
y = x[0]*par[0]
return y

from ROOT import *
f=TF1(‘f’,myfun,0.,100.,1)
f.SetParameter(0,3.)
f.Draw()

see example in tutorial fitExclude.C

TF1 *f1 = new TF1("f1","[0] +[1]*x +gaus(2)",0,5); f1->SetParameters(6,-1,5,3,0.2);
and adapt it to your python script

Rene[/code]

Hi,

which version of ROOT are you using? There’s a release where the default variable to the TF1 ctor isn’t properly checked, which causes a segfault. The workaround is to add the default argument (0) to the end of your TF1 ctor call. That’d be:f=TF1('f',myf,0.,10.,0)
Other than that, you will need x[0], as x is a double*, following the TF1 interface. Technically, I could unroll x (and x, y for TF2; x, y, z for TF3) but then a TF1 is no longer a TF1 (etc.) …

Best regards,
Wim

Dear Rene,

Your solution works, but does not excatly answer my question.
I would like to put a predefine function (myf) in the TF1 argument, and not putting directly the function as in the example you gave.
Also I find the command “f1.SetParameters(6,-1,5,3,0.2)” not very convienient as one as to remember the name and the order of the parameters.
Is there another syntax closer to:
a=3.; b=4.; c=7.
f=TF1(‘f’,myf,0.,10.)
f.Draw()


Dear Wim,

I’m using python 2.4 and root 5.06
I tried:
def myf(x,a=3,b=4,c=7):
y=sin(x[0])*a-b+x[0]/c
return y

from ROOT import *
f=TF1(‘f’,myf,0.,100.,1)
f.Draw()

which gives:
: created default TCanvas with name c1
Traceback (most recent call last):
File “”, line 2, in myf
TypeError: can’t multiply sequence by non-int
Traceback (most recent call last):
File “”, line 1, in ?
File “/home/oleroy/installedByOL/root/lib/ROOT.py”, line 232, in _displayhook
gInterpreter.EndOfLineAction()
Exception: TFN python function call failed (C++ exception)

Thanks for help,
Cheers,
Olivier

Well, this is totally trivial. Simply do

double a,b,c;
double myf(double *x, double par) {
return a
sin(x[0]/b)+c;
}
void test() {
TF1 *f1 = new TF1(“f1”,myf,0,10,0);
a=3; b=4; c=7;
f1->Draw();
}

However, this looks naively simple but not very practical.
You will not be able to save your function to a file.
You better do as I suggested, and to answer your second question
you can do something like:

double myf(double *x, double *par) { double a = par[0]; double b = par[0]; double c = par[0]; return a*sin(x[0]/b)+c; } void test() { TF1 *f1 = new TF1("f1",myf,0,10,3); f1->SetParNames("a","b","c"); f1->SetParameter("a",3); f1->SetParameter("b",4); f1->SetParameter("c",7); f1->Draw(); }

Wim,

In your previous post you said:

[quote]There’s a release where the default variable to the TF1 ctor isn’t
properly checked, which causes a segfault.
[/quote]I assume that the problem was in the python interface. I do not remember
fixing such a problem in TF1.

Rene

Dear Rene,

Thanks for help, but I’ve posted my question under “pyroot” hoping for a python solution, not a C++ one.
Let me reformulate it more clearly.

I’m looking for pyroot equivalent of the PAW instructions:

null 0 10 -2 5
do i=1,3
f/pl myf.f(x,0.1+[i]) 0 10 s
enddo

where myf.f is:
real function myf simple(x,a)
real x,a
myf = sin(a*x)/x
end

Thanks,
Cheers,
Olivier

PS: I tried however to copy and paste your code on root prompt which gives:
root [0]
root [0] double a,b,c;
root [1] double myf(double *x, double *par) {
end with ‘;’, ‘@’:abort >

I tried to put it all in a “test.C” file and then .x test.C without more success.
As you see, I’m really beginning !

Rene,

The problem was in Pythonize.cxx, where I was off by 1 when counting arguments. I’m pretty sure that 5.06 has the problem.

Oliver,

when you set the number of parameters to 1 (default is 0) like you do here:f=TF1('f',myf,0.,100.,1):
then your function will get 2 arguments, the first will be a double* array of size 4 for the coordinates, the second will be a double* array for the parameters, with size as given to the constructor. So, if the number of parameters is > 0, your function needs to be at least:def myf(x,par,a=3,b=4,c=7): y=sin(x[0])*a-b+x[0]/c return y
Where the callback will fill in x[0] only (it is a TF1, after all), and any parameters that you set through SetParameters will appear in par (maximum 1, as that was your choice in the ctor).

In my previous posting, I used the example of 0 for the number of parameters, in which case there will be no “par” (as above) to the function.

Now, in order to be more “pythonistic” here’s another example:[code]from math import sin
from ROOT import TF1

class MyF:
def init( self, a, b, c ):
self.a = a
self.b = b
self.c = c

def call( self, x ):
y=sin(x[0])*self.a-self.b+x[0]/self.c
return y

myf = MyF( 3, 4, 7 )

f = TF1( ‘f’, myf, 0., 100., 0 )
f.Draw()
[/code]
after which you can get/set your parameters through “myf.a”, “myf.b”, and “myf.c”.

Cheers,
Wim