Write user defined function in ROOT file

So my problem is that I coudn’t succeed to write in ROOT file the following function:

Double_t f(Double_t* x, Double_t* par)
{
	TFile file("file.root", "read");

	file.Close();
		
	return 0;
}

the next code will generate error because i’m going back to Rint: directory after calling Write(). Is there any solution?

void
write()
{
	TFile file("file1.root", "recreate");

	TF1 f1("f", f, 0, 0, 0);

	f1.Write();
}

Hi,TF1 f1("f", &f, 0, 0, 0);works for me with 4.03/01. Note you have to pass the address of f.
Axel.

Its stupid mistake of mine i wrote Double_t instead of Double_t* have to sleep more:)
and as far as there was not error message or something i was thinking whats going on here :slight_smile: there is one more problem i have which i’ll post here because its similar:

Double_t* f1(Double_t* x, Double_t* par)
{
	return x[0];
}

Double_t* f2(Double_t* x, Double_t* par)
{
	return x[0] + x[1];
}

Double_t* f3(Double_t* x, Double_t* par)
{
	return x[0] + x[1] + x[2];
}

void
write()
{
	TFile f("func.root", "recreate");
	
	TF1* user_f1 = new TF1("user_f1", f1, -1, 1, 0);
	TF2* user_f2 = new TF2("user_f2", f2, -1, 1, -1, 1, 0);
	TF3* user_f3 = new TF3("user_f3", f3, -1, 1, -1, 1, -1, 1, 0);

	TF1* form_f1 = new TF1("form_f1", "x", -1, 1);
	TF2* form_f2 = new TF2("form_f2", "x + y", -1, 1, -1, 1);
	TF3* form_f3 = new TF3("form_f3", "x + y + z", -1, 1, -1, 1, -1, 1);

	cout << user_f1->Eval(-1) << ' '
	     << user_f1->Eval(0) << ' '
	     << user_f1->Eval(1) << endl
		
	     << user_f2->Eval(0, -1) << ' '
	     << user_f2->Eval(0, 0) << ' '
	     << user_f2->Eval(0, 11) << endl
		
	     << user_f3->Eval(0, 0, -1) << ' '
	     << user_f3->Eval(0, 0, 0) << ' '
	     << user_f3->Eval(0, 0, 11) << endl

	     << form_f1->Eval(-1) << ' '
	     << form_f1->Eval(0) << ' '
	     << form_f1->Eval(1) << endl
		
	     << form_f2->Eval(0, -1) << ' '
	     << form_f2->Eval(0, 0) << ' '
	     << form_f2->Eval(0, 11) << endl
		
	     << form_f3->Eval(0, 0, -1) << ' '
	     << form_f3->Eval(0, 0, 0) << ' '
	     << form_f3->Eval(0, 0, 11) << endl;
	
	user_f1->Write();
	user_f2->Write();
	user_f3->Write();

	form_f1->Write();
	form_f2->Write();
	form_f3->Write();
	
	f.Close();
}
	
void
read()
{
	TFile f("func.root", "read");
	
	TF1* user_f1 = (TF1*)f.Get("user_f1");
	TF2* user_f2 = (TF2*)f.Get("user_f2");
	TF3* user_f3 = (TF3*)f.Get("user_f3");

	TF1* form_f1 = (TF1*)f.Get("form_f1");
	TF2* form_f2 = (TF2*)f.Get("form_f2");
	TF3* form_f3 = (TF3*)f.Get("form_f3");

	cout << user_f1->Eval(-1) << ' '
	     << user_f1->Eval(0) << ' '
	     << user_f1->Eval(1) << endl
		
	     << user_f2->Eval(0, -1) << ' '
	     << user_f2->Eval(0, 0) << ' '
	     << user_f2->Eval(0, 11) << endl
		
	     << user_f3->Eval(0, 0, -1) << ' '
	     << user_f3->Eval(0, 0, 0) << ' '
	     << user_f3->Eval(0, 0, 11) << endl

	     << form_f1->Eval(-1) << ' '
	     << form_f1->Eval(0) << ' '
	     << form_f1->Eval(1) << endl
		
	     << form_f2->Eval(0, -1) << ' '
	     << form_f2->Eval(0, 0) << ' '
	     << form_f2->Eval(0, 11) << endl
		
	     << form_f3->Eval(0, 0, -1) << ' '
	     << form_f3->Eval(0, 0, 0) << ' '
	     << form_f3->Eval(0, 0, 11) << endl;
}

and the output is:

root [32] write()
-1 0 1
-1 0 11
-1 0 11
-1 0 1
-1 0 11
-1 0 11
root [33] read()
-1 2.08167e-17 1
-1 -2.78785e-17 0
1130.79 1130.79 1130.79
-1 0 1
-1 0 11
-1 0 11

whats wrong?

Hi,
what you are trying to do cannot work. There is not way for root to store your methods to a file. The only way out is to define them via a string (see the other TF1 constructor).

If your real methods are not that simple: could you explain what the goal of these saved methods is? Why don’t you compile them and call them? What exactly do you want to do?
Axel.

so I was expecting no difference between user defined functions and those defined with some formula. so I wanted to have these functions as input for some other program but ok if not possible not possible they have to be compiled but if its not possible why its allowed? thanks anyway

Hi,

Good point, I’ll check.
Axel.

Hi Axel, I think I made some mistake in the above example
so instead

Double_t* func(Double_t* x, Double_t* par)

Double_t func(Double_t* x, Double_t* par)

should be used and then called with &func as you said.

I got confused because in the tutorial in example 19 Fitting with a user-defined function there is

Double_t fitf(Double_t *x, Double_t *par)
{
   Double_t arg = 0;
   if (par[2] != 0) arg = (x[0] - par[1])/par[2];

   Double_t fitval = par[0]*TMath::Exp(-0.5*arg*arg);
   return fitval;
}

and then

// Creates a Root function based on function fitf above
   TF1 *func = new TF1("fitf",fitf,-2,2,3);

this should be changed probably?

so basicaly my intenion was to write TF3 function in a ROOT file then using this file as an input but then I saw that the writen function is independend of z probably its writen in the 0.5 * (zmin+zmax) value