rf104_classfactory

Basic functionality: the class factory for functions and pdfs

NOTE: This demo uses code that is generated by the macro, which can be compiled on the fly (set to MyPdfV3 below). To use MyPdfV1 or MyPdfV2, adjust lines below accordingly.

Author: Clemens Lange, Wouter Verkerke (C++ version)
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Wednesday, November 30, 2022 at 11:21 AM.

In [1]:
import ROOT
Welcome to JupyROOT 6.27/01

Write class skeleton code

Write skeleton pdf class with variable x,a,b To use this class,

  • Edit the file MyPdfV1.cxx and implement the evaluate() method in terms of x,a and b
  • Compile and link class with '.x MyPdfV1.cxx+'
In [2]:
ROOT.RooClassFactory.makePdf("MyPdfV1", "x,A,B")
Out[2]:
False

With added initial value expression

Write skeleton pdf class with variable x,a,b and given formula expression To use this class,

  • Compile and link class with '.x MyPdfV2.cxx+'
In [3]:
ROOT.RooClassFactory.makePdf("MyPdfV2", "x,A,B", "", "A*fabs(x)+pow(x-B,2)")
Out[3]:
False

With added analytical integral expression

Write skeleton pdf class with variable x,a,b, given formula expression and given expression for analytical integral over x To use this class,

  • Compile and link class with '.x MyPdfV3.cxx+'
In [4]:
ROOT.RooClassFactory.makePdf(
    "MyPdfV3",
    "x,A,B",
    "",
    "A*fabs(x)+pow(x-B,2)",
    True,
    False,
    "x:(A/2)*(pow(x.max(rangeName),2)+pow(x.min(rangeName),2))+(1./3)*(pow(x.max(rangeName)-B,3)-pow(x.min(rangeName)-B,3))",
)
Out[4]:
False

Use instance of created class

Compile MyPdfV3 class

In [5]:
ROOT.gROOT.ProcessLineSync(".x MyPdfV3.cxx+")
Out[5]:
161032976
(MyPdfV3) An instance of MyPdfV3.
Info in <TUnixSystem::ACLiC>: creating shared library /home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/./MyPdfV3_cxx.so
In file included from input_line_9:6:
In file included from ././MyPdfV3.cxx:11:
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/MyPdfV3.h:24:20: warning: 'clone' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  virtual TObject* clone(const char* newname) const { return new MyPdfV3(*this,newname); }
                   ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsArg.h:82:20: note: overridden virtual function is here
  virtual TObject* clone(const char* newname=nullptr) const = 0 ;
                   ^
In file included from input_line_9:6:
In file included from ././MyPdfV3.cxx:11:
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/MyPdfV3.h:27:9: warning: 'getAnalyticalIntegral' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;
        ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsReal.h:166:17: note: overridden virtual function is here
  virtual Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=nullptr) const ;
                ^
In file included from input_line_9:6:
In file included from ././MyPdfV3.cxx:11:
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/MyPdfV3.h:28:10: warning: 'analyticalIntegral' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  double analyticalIntegral(Int_t code, const char* rangeName=0) const ;
         ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsReal.h:167:18: note: overridden virtual function is here
  virtual double analyticalIntegral(Int_t code, const char* rangeName=nullptr) const ;
                 ^
In file included from input_line_9:6:
In file included from ././MyPdfV3.cxx:11:
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/MyPdfV3.h:36:10: warning: 'evaluate' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  double evaluate() const ;
         ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsReal.h:436:18: note: overridden virtual function is here
  virtual double evaluate() const = 0;
                 ^

Creat instance of MyPdfV3 class

In [6]:
a = ROOT.RooRealVar("a", "a", 1)
b = ROOT.RooRealVar("b", "b", 2, -10, 10)
y = ROOT.RooRealVar("y", "y", -10, 10)
pdf = ROOT.MyPdfV3("pdf", "pdf", y, a, b)

Generate toy data from pdf and plot data and pdf on frame

In [7]:
frame1 = y.frame(Title="Compiled class MyPdfV3")
data = pdf.generate({y}, 1000)
pdf.fitTo(data)
data.plotOn(frame1)
pdf.plotOn(frame1)
Out[7]:
<cppyy.gbl.RooPlot object at 0x9fe8090>
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
 **********
 **    1 **SET PRINT           1
 **********
 **********
 **    2 **SET NOGRAD
 **********
 PARAMETER DEFINITIONS:
    NO.   NAME         VALUE      STEP SIZE      LIMITS
     1 b            2.00000e+00  2.00000e+00   -1.00000e+01  1.00000e+01
 **********
 **    3 **SET ERR         0.5
 **********
 **********
 **    4 **SET PRINT           1
 **********
 **********
 **    5 **SET STR           1
 **********
 NOW USING STRATEGY  1: TRY TO BALANCE SPEED AGAINST RELIABILITY
 **********
 **    6 **MIGRAD         500           1
 **********
 FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.
 START MIGRAD MINIMIZATION.  STRATEGY  1.  CONVERGENCE WHEN EDM .LT. 1.00e-03
 FCN=2568.49 FROM MIGRAD    STATUS=INITIATE        4 CALLS           5 TOTAL
                     EDM= unknown      STRATEGY= 1      NO ERROR MATRIX       
  EXT PARAMETER               CURRENT GUESS       STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  b            2.00000e+00   2.00000e+00   2.05758e-01   5.02230e+01
                               ERR DEF= 0.5
 MIGRAD MINIMIZATION HAS CONVERGED.
 MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.
 COVARIANCE MATRIX CALCULATED SUCCESSFULLY
 FCN=2568.28 FROM MIGRAD    STATUS=CONVERGED      17 CALLS          18 TOTAL
                     EDM=9.63237e-09    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                   STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  b            1.91995e+00   1.24398e-01   4.43576e-04   7.74259e-03
                               ERR DEF= 0.5
 EXTERNAL ERROR MATRIX.    NDIM=  25    NPAR=  1    ERR DEF=0.5
  1.548e-02 
 **********
 **    7 **SET ERR         0.5
 **********
 **********
 **    8 **SET PRINT           1
 **********
 **********
 **    9 **HESSE         500
 **********
 COVARIANCE MATRIX CALCULATED SUCCESSFULLY
 FCN=2568.28 FROM HESSE     STATUS=OK              5 CALLS          23 TOTAL
                     EDM=9.63457e-09    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                INTERNAL      INTERNAL  
  NO.   NAME      VALUE            ERROR       STEP SIZE       VALUE   
   1  b            1.91995e+00   1.24398e-01   1.77431e-05   1.93194e-01
                               ERR DEF= 0.5
 EXTERNAL ERROR MATRIX.    NDIM=  25    NPAR=  1    ERR DEF=0.5
  1.548e-02 
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization

/ Compiled version of example rf103# /

Declare observable x

In [8]:
x = ROOT.RooRealVar("x", "x", -20, 20)

The ROOT.RooClassFactory.makePdfInstance() function performs code writing, compiling, linking and object instantiation in one go and can serve as a straight replacement of ROOT.RooGenericPdf

In [9]:
alpha = ROOT.RooRealVar("alpha", "alpha", 5, 0.1, 10)
genpdf = ROOT.RooClassFactory.makePdfInstance("GenPdf", "(1+0.1*fabs(x)+sin(sqrt(fabs(x*alpha+0.1))))", [x, alpha])
Info in <TUnixSystem::ACLiC>: creating shared library /home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/master_TMP/notebooks/RooGenPdfPdf_cxx.so
In file included from input_line_9:6:
In file included from ./RooGenPdfPdf.cxx:11:
./RooGenPdfPdf.h:23:20: warning: 'clone' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  virtual TObject* clone(const char* newname) const { return new RooGenPdfPdf(*this,newname); }
                   ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsArg.h:82:20: note: overridden virtual function is here
  virtual TObject* clone(const char* newname=nullptr) const = 0 ;
                   ^
In file included from input_line_9:6:
In file included from ./RooGenPdfPdf.cxx:11:
./RooGenPdfPdf.h:31:10: warning: 'evaluate' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  double evaluate() const ;
         ^
/home/sftnight/build/workspace/root-makedoc-master/rootspi/rdoc/src/master.build/include/RooAbsReal.h:436:18: note: overridden virtual function is here
  virtual double evaluate() const = 0;
                 ^

Generate a toy dataset from the interpreted pdf

In [10]:
data2 = genpdf.generate({x}, 50000)
[#1] INFO:NumericIntegration -- RooRealIntegral::init(GenPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)
[#1] INFO:NumericIntegration -- RooRealIntegral::init(GenPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)

Fit the interpreted pdf to the generated data

In [11]:
genpdf.fitTo(data2)
Out[11]:
<cppyy.gbl.RooFitResult object at 0x(nil)>
[#1] INFO:NumericIntegration -- RooRealIntegral::init(GenPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
 **********
 **   10 **SET PRINT           1
 **********
 **********
 **   11 **SET NOGRAD
 **********
 PARAMETER DEFINITIONS:
    NO.   NAME         VALUE      STEP SIZE      LIMITS
     1 alpha        5.00000e+00  9.90000e-01    1.00000e-01  1.00000e+01
 **********
 **   12 **SET ERR         0.5
 **********
 **********
 **   13 **SET PRINT           1
 **********
 **********
 **   14 **SET STR           1
 **********
 NOW USING STRATEGY  1: TRY TO BALANCE SPEED AGAINST RELIABILITY
 **********
 **   15 **MIGRAD         500           1
 **********
 FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4.
 START MIGRAD MINIMIZATION.  STRATEGY  1.  CONVERGENCE WHEN EDM .LT. 1.00e-03
 FCN=178267 FROM MIGRAD    STATUS=INITIATE        6 CALLS           7 TOTAL
                     EDM= unknown      STRATEGY= 1      NO ERROR MATRIX       
  EXT PARAMETER               CURRENT GUESS       STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  alpha        5.00000e+00   9.90000e-01   2.01369e-01   2.50886e+02
                               ERR DEF= 0.5
 MIGRAD MINIMIZATION HAS CONVERGED.
 MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX.
 COVARIANCE MATRIX CALCULATED SUCCESSFULLY
 FCN=178266 FROM MIGRAD    STATUS=CONVERGED      14 CALLS          15 TOTAL
                     EDM=3.47331e-06    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                   STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  alpha        4.98248e+00   1.85558e-02   1.09523e-03  -4.97115e-01
                               ERR DEF= 0.5
 EXTERNAL ERROR MATRIX.    NDIM=  25    NPAR=  1    ERR DEF=0.5
  3.443e-04 
 **********
 **   16 **SET ERR         0.5
 **********
 **********
 **   17 **SET PRINT           1
 **********
 **********
 **   18 **HESSE         500
 **********
 COVARIANCE MATRIX CALCULATED SUCCESSFULLY
 FCN=178266 FROM HESSE     STATUS=OK              5 CALLS          20 TOTAL
                     EDM=3.46509e-06    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                INTERNAL      INTERNAL  
  NO.   NAME      VALUE            ERROR       STEP SIZE       VALUE   
   1  alpha        4.98248e+00   1.85557e-02   2.19047e-04  -1.36416e-02
                               ERR DEF= 0.5
 EXTERNAL ERROR MATRIX.    NDIM=  25    NPAR=  1    ERR DEF=0.5
  3.443e-04 
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization

Make a plot of the data and the pdf overlaid

In [12]:
frame2 = x.frame(Title="Compiled version of pdf of rf103")
data2.plotOn(frame2)
genpdf.plotOn(frame2)
Out[12]:
<cppyy.gbl.RooPlot object at 0xa6eac00>
[#1] INFO:NumericIntegration -- RooRealIntegral::init(GenPdf_Int[x]) using numeric integrator RooIntegrator1D to calculate Int(x)

Draw all frames on a canvas

In [13]:
c = ROOT.TCanvas("rf104_classfactory", "rf104_classfactory", 800, 400)
c.Divide(2)
c.cd(1)
ROOT.gPad.SetLeftMargin(0.15)
frame1.GetYaxis().SetTitleOffset(1.4)
frame1.Draw()
c.cd(2)
ROOT.gPad.SetLeftMargin(0.15)
frame2.GetYaxis().SetTitleOffset(1.4)
frame2.Draw()

c.SaveAs("rf104_classfactory.png")
Info in <TCanvas::Print>: png file rf104_classfactory.png has been created

Draw all canvases

In [14]:
from ROOT import gROOT 
gROOT.GetListOfCanvases().Draw()