TF2: how to pass additional parameters into fitting function

Hi,

In my C++ code I am creating a TF2 object:

that will be used for fitting later:

And I define “func” like this:

Double_t func( Double_t* x, Double_t* params ) { Int_t myMethod = 2; ... }

The problem is with this “myMethod”: here I hard-code it inside the “func”, but I need it to be passed from outside.

Question: What is the elegant way of doing this?

I am asking this question, because the signature of such a function (“func”) seems to be the only one.

Many thanks in advance!

  • Anatoly

Hi,

You can create a TF1 (and also a TF2) from a object (using a Functor or as a member function of the class).
In this way you hide all the extra parameters inside that object that you can set before using the function.
See root.cern.ch/root/htmldoc/TF1.html#F4 (case D or E)

Best Regards

Lorenzo

Hi Lorenzo,

Now I see. Yes, it is it !

Many thanks again (and again, and again… ) !

Best,

Hi Lorenzo,

[quote]Anatoly:
Now I see. Yes, it is it ! [/quote]

Not quite, I must confess.

I’m testing the following:

[code]#include “TF1.h”

class MyEvalFunc {

public :

MyEvalFunc(double ep) : externalParam(ep) {}

double Evaluate(double* x, double* p) {
return externalParam * x[0] * p[0] * p[1];
}

double externalParam;
};

int main() {

double xmin = -10; double xmax = 10;
double myParam(2.0);

MyEvalFunc* eval = new MyEvalFunc(myParam);

TF1* f3 = new TF1(“f3”, eval, &MyEvalFunc::Evaluate, xmin, xmax, 2);

f3->SetMinimum(-2); f3->SetMaximum(6);
f3->SetParameters(-1.0, 0.5);
f3->SetLineColor(kRed);
f3->Draw();

return 0;
}
[/code]

But getting error:

[lxplus428] ~/private/C++ $ make -f Makefile testFunctorExtPar
g++ -O2 -Wall -fPIC -pthread -m64 -I/afs/cern.ch/sw/lcg/app/releases/ROOT/5.28.00b/x86_64-slc5-gcc43-opt/root/include -O2 -m64 testFunctorExtPar.C -o testFunctorExtPar
/tmp/asolomin/ccqF9wDN.o: In function global constructors keyed to testFunctorExtPar.C': testFunctorExtPar.C:(.text+0x11): undefined reference toTVersionCheck::TVersionCheck(int)’
/tmp/asolomin/ccqF9wDN.o: In function main': testFunctorExtPar.C:(.text+0x6c): undefined reference toTStorage::ObjectAlloc(unsigned long)'
testFunctorExtPar.C:(.text+0x77): undefined reference to TFormula::TFormula()' testFunctorExtPar.C:(.text+0x86): undefined reference toTAttLine::TAttLine()'
testFunctorExtPar.C:(.text+0x95): undefined reference to TAttFill::TAttFill()' testFunctorExtPar.C:(.text+0xa4): undefined reference toTAttMarker::TAttMarker()'
testFunctorExtPar.C:(.text+0xab): undefined reference to vtable for TF1' testFunctorExtPar.C:(.text+0x233): undefined reference toTF1::CreateFromFunctor(char const*, int)'
testFunctorExtPar.C:(.text+0x2e5): undefined reference to TObject::operator delete(void*)' testFunctorExtPar.C:(.text+0x304): undefined reference toTAttMarker::~TAttMarker()'
testFunctorExtPar.C:(.text+0x30c): undefined reference to TAttFill::~TAttFill()' testFunctorExtPar.C:(.text+0x314): undefined reference toTAttLine::~TAttLine()'
testFunctorExtPar.C:(.text+0x31c): undefined reference to `TFormula::~TFormula()'
collect2: ld returned 1 exit status
make: *** [testFunctorExtPar] Error 1
[lxplus428] ~/private/C++ $

At the same time, your exampleFunctor.C (turned into a program) builds OK.

What am I missing after all?

Many thanks !!

Hi,

You are missing to link with the ROOT libraries. Do:

g++ -O2 -I`root-config --cflags --libs` testFunctorExtPar.C -o testFunctorExtPar

Lorenzo

Oh yes, now it works as it should ! Thanks a lot again !

PS to the RootTalk: So my code in my previous post is the answer to my question. It gives an example how to pass additional external parameters (not involved in the fitting) into the fitting function. Thanks to Lorenzo who suggested the solution and explained how to build as a C++ program.

PPS to the RootTalk: I must add that in two-dimensional case, even in the C++ compiled code one should retain className and methodName at the end of the argument list, e.g.:

TF2* f = new TF2("f", eval, &MyEvalFunc::Evaluate, xmin, xmax, ymin, ymax, 2, "MyEvalFunc", "Evaluate");

If I understand it correctly. At least it does not work for me without className and methodName at the end.

Hi,

It is correct , when constructing a TF2 you need to pass two extra string. This is needed to avoid a conflict with another constructor signature. When compiling the code (with AClic or a C++ application) the class and method names are not used, but they are needed when using the code in CINT (in interpreted mode)

Thank you for your comments

Lorenzo