Home | News | Documentation | Download

Import several RooTFnBinding objects in the RooWorkspace

Hi,
I wanted to import several RooTFnBindings in the WS in the following way

    for(int cat=0;cat<4;++cat)  {
        for(int iObj=0;iObj<objName.size();++iObj)  {
            TGraph* graph=(TGraph*)graphFile->Get(Form("%sC%d",objName[iObj].Data(),cat));
            TF1* graphFun=new TF1(Form("%sC%dFun",objName[iObj].Data(),cat),[&](double* x,double* p){return p[0]*graph->Eval(x[0],0,"S");},-20.,20.,1);
            graphFun->SetTitle(Form("%sC%dFun",objName[iObj].Data(),cat));
            graphFun->SetParameter(0,1);

            RooTFnBinding* param=new RooTFnBinding(Form("%s_HH_%sParam",objName[iObj].Data(),catName[cat].Data()),Form("%s_HH_%sParam",objName[iObj].Data(),catName[cat].Data()),graphFun,*kLambda);              

            newWS->import(*graph);
            newWS->import(*graphFun);
            newWS->import(*param);
        }       
    } 

After that, I saved the WS in the output file. But I found all RooTFnBinding objects in the output are overwritten. Even they have different names, their magnitudes are the same. Like this

functions
--------
RooTFnBinding::muCBNom_HH_tightScore_HMassParam[ TFn={muCBNomC0Fun=muCBNomC0Fun} obs=(kLambda) params=() ] = 1.32132
RooTFnBinding::sigmaCBNom_HH_tightScore_HMassParam[ TFn={sigmaCBNomC0Fun=sigmaCBNomC0Fun} obs=(kLambda) params=() ] = 1.32132

...
generic objects
---------------
TGraph::muCBNomC0
TF1::muCBNomC0Fun
TGraph::sigmaCBNomC0
TF1::sigmaCBNomC0Fun

I checked the graphs “muCBNomC0” and “sigmaCBNomC0” and TF1 “muCBNomC0Fun” and “sigmaCBNomC0Fun” in the output. They are both as expected and different with each other. But the RooTFnBinding objects are the same. May I ask I did something wrong here? Thanks a lot!

Cheers,
Kunlin Ran

Hi,

I think the problem is that you cannot save TF1 object based on C++ code in a file. This does not work, because the functions are based on a function or functor pointer that cannot be stored.
The solution is either to make functions based on a class that you need to import in the workspace or to make a TFormula based TF1 that can be stored. For example you might try doing:

TF1* graphFun=new TF1(Form("%sC%dFun",objName[iObj].Data(),cat),"[&](double* x,double* p){return p[0]*graph->Eval(x[0],0,"S");}",-20.,20.,1); 

but you need to be sure that graph is a valid pointer. Probably you need to replace in the function definition with (TGraph*)w->obj("muCBNomC0"), where w is the current pointer that you have when reading the workspace from the file.

Lorenzo

Thanks Lorenzo! I managed to solve it. I need to import the TF1 in the newWS first, then get it from the WS to generate the bindingfunction, like this

newWS->import(*graphFun);
TF1* graphFunWS=(TF1*)newWS->obj(Form("%sC%dFun",objName[iObj].Data(),cat));

RooTFnBinding* param=(RooTFnBinding*)bindFunction(graphFunWS,*kLambda);

Then everything should be fine now. Thanks!