Issues when cloning a TF1

Hello,

Recently I found an issue when I want to clone a TF1. The TF1 object is created from a TGraph. While after cloning, the evaluated value changes. I’m not sure why this would happen. Please have a look at my example code below.

void cloneBug()
{
    TFile* graphFile=new TFile("testGraph.root");
    TGraph* testGraph=(TGraph*)graphFile->Get("testGraph");

    TF1* graphFun=new TF1("graphFun",[&](double* x,double* p){return testGraph->Eval(x[0],0,"S");},-11,11,1);
    graphFun->FixParameter(0,1);
    cout<<graphFun->Eval(1)<<endl;
    cout<<((TF1*)(graphFun->Clone()))->Eval(1)<<endl;
}

And the output is

Processing cloneBug.C...
0.846551
0.847985

Please also find the test graph file attached. I’m asking this question is because I wanted to import this graph-created TF1 into an RooWorkspace. While I found that after importing, the values changed, that’s because the import() function will clone the object.

I would appreciate a lot you have any helpful suggestions. Thanks a lot!

Cheers,

Kunlin Ran

_ROOT Version: v6-18-04 or v6-22-06testGraph.root (5.4 KB)

1 Like

I do not see the point of creating a TF1 from a TGraph ? Why don’t you stay with TGraph ?

Hello,

The reason I want to use the TF1 is that I’d like to make graph interpolations and import such an interpolation into an RooWorkspace, where one of the RooRealVar should be the “x” defined in the function. So basically I need to transfer TGraph → TF1 → RooTFnBinding. I found that before importing TF1 or RooTFnBinding into the workspace, the evaluations are as expected. While after importing, I tried to get the RooTFnBinding from the workspace with “ws->obj(TFnBindingName)” and printed out the evaluations. I was surprised that the values changed. That’s due to this clone issue, because the import() function will clone the corresponding object.

Cheers,
Kunlin

I modified your macro to produces plots:

void cloneBug()
{
    auto graphFile=new TFile("testGraph.root");
    auto testGraph=(TGraph*)graphFile->Get("testGraph");
    cout << testGraph->Eval(1) << endl;

    auto graphFun = new TF1("graphFun",[&](double* x,double* p){return testGraph->Eval(x[0],0,"S");},-11,11,1);
    graphFun->FixParameter(0,1);
    cout << graphFun->Eval(1) << endl;

    auto graphFunClone = (TF1*)graphFun->Clone();
    cout << ((TF1*)(graphFunClone))->Eval(1 )<< endl;

    testGraph->Draw("a*");
    graphFunClone->Draw("same");
}

The clone and the original graph match quite well. It might be a precision issue. May be @moneta has an idea,

Thanks Oliver,

Yeah, I fully agree that the differences are quite small, mostly at 0.1% level. So I also guess it might be related to the precision issue. Let’s see what other experts think.

Cheers,
Kunlin

Compare “graphFun->Print();” with “graphFunClone->Print();” plus “cout << testGraph->GetN() << endl;”.

You can help yourself using:
auto graphFun = new TF1("graphFun", "[=](double *x, double *p){return testGraph->Eval(x[0],0,\"S\");}", -11, 11, 0);

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.