Using bindFunction and bindPdf

I am trying to understand how to use bindFunction and bindPdf from RootFnBinding. I have been trying to implement example rf105_funcbinding.C as a standalone C++ program, but from the lines

// Bind one-dimensional TMath::Erf function as RooAbsReal function

   RooRealVar x("x", "x", -3, 3);
   RooAbsReal *errorFunc = bindFunction("erf", TMath::Erf, x);

I get the error:

g++ -Wall -c  -O2 -g -pthread -std=c++1z -m64 -I/cvmfs/sft.cern.ch/lcg/releases/LCG_96b/ROOT/6.18.04/x86_64-centos7-gcc8-opt/include -c -o ExFnBinding.o ExFnBinding.C
ExFnBinding.C: In member function 'void ExFnBinding::rf105_funcbinding()':
ExFnBinding.C:122:68: error: no matching function for call to 'bindPdf(const char [5], double (&)(double, double, double), RooRealVar&, RooRealVar&, RooRealVar&)'
    RooAbsPdf *beta = bindPdf("beta", ROOT::Math::beta_pdf, x2, a, b);

While this example works in CINT, there seems to be a problem with passing arguments
…for example in

 auto c1 = new TCanvas("c1", "Parabola", 200,10,700,500);
  TF1 *fa1 = new TF1("fa1", parabola, 0., 20., 3);
   //   fa1->SetNpx(500);
  double p1 = 1;
  double p2 = 2;
  double p3  =2;
   fa1->SetParameter(0,p1);
   fa1->SetParameter(1,p2);
   fa1->SetParameter(2,p3);

The arguments (parameters) do not get passed to the function parabola

double parabola(double *t, double *par){
  // par[0]=1;
  //par[1]=2;
  //par[2]=2;
  cout << "Par 0     " << par[0] << endl;
  cout  << "t[0]    "  << t[0]  << endl;
  return par[0]+par[1]*t[0]+par[2]*t[0]*t[0] ;

Hi,

Can you please post exactly the macro that does not work ?
And tell as the ROOT version ? Are you using version 5 ?
Cint is not anymore available in ROOT version 6

I can run for example without any problem these lines:

RooRealVar x(“x”, “x”, -3, 3);
RooAbsReal *errorFunc = RooFit::bindFunction(“erf”, TMath::Erf, x);

Best regards

Lorenzo

Hi :
I’m using LCG_96b/ROOT/6.18.04/x86_64-centos7-gcc8-opt on a CERN virtual machine

First I tried to modify the example macro. See the whole thing at the end of this. When I run it, the function parabola does not seem to get its arguments.

More importantly (to me) when I try to make the macro a standalone C++ program. Where I basically just add a main() - It seems too long to post all of that. But the relevant lines are

  // Bind one-dimensional TMath::Erf function as RooAbsReal function
   RooRealVar x("x", "x", -3, 3);
   RooAbsReal *errorFunc = bindFunction("erf", TMath::Erf, x);
   // Print erf definition
   errorFunc->Print();
   // Plot erf on frame
   RooPlot *frame1 = x.frame(Title("TMath::Erf bound as RooFit function"));
   errorFunc->plotOn(frame1);
   // B i n d   R O O T : : M a t h : : b e t a _ p d f   C   f u n c t i o n
   // -----------------------------------------------------------------------
   */   // Bind pdf ROOT::Math::Beta with three variables as RooAbsPdf function
   RooRealVar x2("x2", "x2", 0, 0.999);
   RooRealVar a("a", "a", 5, 0, 10);
   RooRealVar b("b", "b", 2, 0, 10);
   RooAbsPdf *beta = bindPdf("beta", ROOT::Math::beta_pdf, x2, a, b);

I get the make errors

[orr@localhost Parabola]$ make
g++ -Wall -c  -O2 -g -pthread -std=c++1z -m64 -I/cvmfs/sft.cern.ch/lcg/releases/LCG_96b/ROOT/6.18.04/x86_64-centos7-gcc8-opt/include -c -o ExFnBinding.o ExFnBinding.C
ExFnBinding.C: In member function 'void ExFnBinding::rf105_funcbinding()':
ExFnBinding.C:110:61: error: no matching function for call to 'bindFunction(const char [4], Double_t (&)(Double_t), RooRealVar&)'
    RooAbsReal *errorFunc = bindFunction("erf", TMath::Erf, x);
                                                             ^
In file included from ExFnBinding.C:56:
/cvmfs/sft.cern.ch/lcg/releases/LCG_96b/ROOT/6.18.04/x86_64-centos7-gcc8-opt/include/RooTFnBinding.h:44:13: note: candidate: 'RooAbsReal* RooFit::bindFunction(TF1*, RooAbsReal&)'
 RooAbsReal* bindFunction(TF1* func,RooAbsReal& x) ;

Follows the macro. It executes, but it doesn’t pass the arguments to parabola

#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <iostream>
#include <fstream>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <TCanvas.h>
#include <TROOT.h>
#include <TDirectory.h>
#include <TStyle.h>
#include <TH1.h>
#include <TH2.h>
#include <TF1.h>
#include <TRegexp.h>
#include <TSystem.h>
#include <TGraphErrors.h>
#include <algorithm>
#include "TProfile.h"
#include "TFile.h"
//#include "AsciiRoot.h"
#include "TVirtualFitter.h"
//#include "MollFit.h"


#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooGaussian.h"
#include "RooLandau.h"
#include "RooDataHist.h"
#include "RooFFTConvPdf.h"
#include "RooPlot.h"
#include "RooNLLVar.h"
#include "RooAddPdf.h"
#include "RooGenericPdf.h"
#include "TAxis.h"
#include "TH1.h"
#include "TRandom.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooPolyVar.h"
#include "RooConstVar.h"
#include "RooChi2Var.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooGaussian.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "RooPlot.h"
#include "TMath.h"
#include "TF1.h"
#include "Math/DistFunc.h"
#include "RooTFnBinding.h"

using namespace std;
using namespace RooFit;


//double parabola(double *t, double *par[]){
//  return par[0] + par[1]*t + par[2]*t ;
//}
//double short_term(double *t, double *par) {
//  return (par[0]*par[1]*exp(-t[0]/par[2]));
//}

//double const_term(double *t, double *par) {
//  return par[5]*par[0];
//}
//
//double long_term(double *t, double *par) {
//  return par[0]*par[6]*par[3]*( 1 - exp(-t[0]/par[4]));
//}



double parabola(double *t, double *par){
  // par[0]=1;
  //par[1]=2;
  //par[2]=2;
  cout << "Par 0     " << par[0] << endl;
  cout  << "t[0]    "  << t[0]  << endl;
  return par[0]+par[1]*t[0]+par[2]*t[0]*t[0] ;
}


void rf105_funcbinding()
{


   // B i n d   T M a t h : : E r f   C   f u n c t i o n
   // ---------------------------------------------------
   // Bind one-dimensional TMath::Erf function as RooAbsReal function
   RooRealVar x("x", "x", -3, 3);
   RooAbsReal *errorFunc = bindFunction("erf", TMath::Erf, x);
   // Print erf definition
   errorFunc->Print();
   // Plot erf on frame
   RooPlot *frame1 = x.frame(Title("TMath::Erf bound as RooFit function"));
   errorFunc->plotOn(frame1);
   // B i n d   R O O T : : M a t h : : b e t a _ p d f   C   f u n c t i o n
   // -----------------------------------------------------------------------
   // Bind pdf ROOT::Math::Beta with three variables as RooAbsPdf function
   RooRealVar x2("x2", "x2", 0, 0.999);
   RooRealVar a("a", "a", 5, 0, 10);
   RooRealVar b("b", "b", 2, 0, 10);
   RooAbsPdf *beta = bindPdf("beta", ROOT::Math::beta_pdf, x2, a, b);
   // Perf beta definition
   beta->Print();
   // Generate some events and fit
   RooDataSet *data = beta->generate(x2, 10000);
   beta->fitTo(*data);
   // Plot data and pdf on frame
   RooPlot *frame2 = x2.frame(Title("ROOT::Math::Beta bound as RooFit pdf"));
   data->plotOn(frame2);
   beta->plotOn(frame2);
   // B i n d   R O O T   T F 1   a s   R o o F i t   f u n c t i o n
   // ---------------------------------------------------------------
   // Create a ROOT TF1 function
   // RooRealVar f("f", "f", 5, 0, 10);
   //RooRealVar g("g", "g", 2, 0, 10);

   double f;
   double g;
  auto c1 = new TCanvas("c1", "Parabola", 200,10,700,500);
  TF1 *fa1 = new TF1("fa1", parabola, 0., 20., 3);
   //   fa1->SetNpx(500);
  double p1 = 1;
  double p2 = 2;
  double p3  =2;
   fa1->SetParameter(0,p1);
   fa1->SetParameter(1,p2);
   fa1->SetParameter(2,p3);

fa1->SetLineColor(kBlue);
fa1->SetTitle( "Formula 1.64");
 cout << "Draw fa1    " << endl;
fa1->Draw();

// TLegend leg(.6,.8,.4,.9, "1/Neff");
// leg.SetFillColor(0);
// fa1->SetFillColor(0);
// leg.DrawClone("Same");
//     c1->SaveAs("Plot.eps");

   // Create an observable
   RooRealVar x3("x3", "x3", 0.01, 20);
   // Create binding of TF1 object to above observable
   RooAbsReal *rfa1 = bindFunction(fa1, x3);
   // Print rfa1 definition
   rfa1->Print();
   // Make plot frame in observable, plot TF1 binding function
   RooPlot *frame3 = x3.frame(Title("TF1 bound as RooFit function"));
   cout << "Plot rfa1     " <<endl;
   rfa1->plotOn(frame3);
   TCanvas *c = new TCanvas("rf105_funcbinding", "rf105_funcbinding", 1200, 400);
   c->Divide(3);
   c->cd(1);
   gPad->SetLeftMargin(0.15);
   frame1->GetYaxis()->SetTitleOffset(1.6);
   frame1->Draw();
   c->cd(2);
   gPad->SetLeftMargin(0.15);
   frame2->GetYaxis()->SetTitleOffset(1.6);
   frame2->Draw();
   c->cd(3);
   gPad->SetLeftMargin(0.15);
   frame3->GetYaxis()->SetTitleOffset(1.6);
   frame3->Draw();
}

#ifndef __CINT__

#endif

Hi,

Thank you for uploading the macro. It is maybe easier if you add as attachment next time.
I see your two isssues:

  1. Problem with bindFunction working in interpreted mode (in CINT) but not in compiled mode.
    This is due to some missing include files. You need to add the right ones, the one that define the bindFunction signature for free C function. In your case you are using functions with 1 (TMath::Erf) and 3 arguments ( ROOT::Math::beta_pdf).
    You need to include:
#include "RooCFunction1Binding.h"
#include "RooCFunction3Binding.h"
  1. Error binding a TF1 object in a RooABsReal. There you need to specify also the TF1 parameters as RooRealVar and pass them in the RooFit::bindFunction. Do something like:
   RooRealVar rp1("p1","p1",p1,0,10);
   RooRealVar rp2("p2","p2",p2,0,10);
   RooRealVar rp3("p3","p3",p3,0,10);
   RooArgSet pars(rp1,rp2,rp3); 
   RooAbsReal *rfa1 = bindFunction(fa1, x3, pars);

I attach your modified macro working for me in both interpreted and compiled mode

Best Regards

Lorenzo

rootForum_39294.C (4.8 KB)

Thaks for taking the time to help me!

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