Dear experts,
I’m trying to create my own roofit p.d.f. with PyROOT to fit some distribution. It should be a two-body phase space multiplied by a polynomial function, which does not look to be easily written in one line, so I’ve chosen to do the following:
- write a python function
- make a TF1 out of it
- turn it in a RooFit p.d.f.
I’m attaching a code example and a small dataset in the end of this post, but briefly it looks as the following:
import ROOT, math
...
def my_function(x, par):
xx = x[0]
a1 = par[0]
a2 = par[1]
...
f = f(x, a1, a2,...)
return f
## name, function, left limit, right limit, number of parameters
f_ps = ROOT.TF1("f_ps", my_function, mass_left, mass_right, 3)
m_x = ROOT.RooRealVar("m_x", "m_x", mass_left, mass_right)
roo_ps_func = ROOT.RooFit.bindFunction(f_ps_pol2, m_x, pars)
roo_ps_pdf1 = ROOT.RooFit.bindPdf("roo_ps_pdf1",f_ps_pol2, m_x, a1, a2, a3)
roo_ps_pdf2 = ROOT.RooFit.bindPdf(f_ps_pol2, m_x)
where a1, a2 and a3 are RooRealVars for model parameters. I tried several methods but unfortunately none of them seems to allow fitting:
-
bound as a function
roo_ps_func.fitTo(ds)
leads to an error
AttributeError: 'RooTFnBinding' object has no attribute 'fitTo' -
bound as a pdf
roo_ps_pdf1.fitTo(ds)
leads to an error
File /snap/root-framework/954/usr/local/lib/ROOT/_pythonization/_roofit/_rooabspdf.py:64, in RooAbsPdf.fitTo(self, *args, **kwargs)
60 The RooAbsPdf::fitTo() function is pythonized with the command argument pythonization.
61 The keywords must correspond to the CmdArgs of the function.
62
63 # Redefinition of `RooAbsPdf.fitTo` for keyword arguments.
--> 64 return self._fitTo["RooLinkedList const&"](args[0], _pack_cmd_args(*args[1:], **kwargs))
TypeError: Could not find "fitTo<RooLinkedList const&>" (set cppyy.set_debug() for C++ errors):
Template method resolution failed:
math domain error
math domain error
Failed to instantiate "operator()(double,double,double,double)"
- other way of binding pdf
roo_ps_pdf2.fitTo(ds)
does not seem to see the parameters:
[#1] INFO:Fitting -- RooAbsPdf::fitTo(f_ps_pol2_over_f_ps_pol2_Int[m_x]) fixing normalization set for coefficient determination to observables in data
[#1] INFO:Fitting -- Creation of NLL object took 9.0357 ms
[#1] INFO:Fitting -- RooAddition::defaultErrorLevel(nll_f_ps_pol2_over_f_ps_pol2_Int[m_x]_background) Summation contains a RooNLLVar, using its error level
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
[#0] ERROR:Minimization -- RooMinimizer::fitFCN(): FCN function has zero parameters
[#0] ERROR:Minimization -- RooMinimizer: all function calls during minimization gave invalid NLL values!
[#0] WARNING:Minimization -- RooMinimizer::hesse: Error, run Migrad before Hesse!
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: deactivating const optimization
So, it seems I’m missing something here. Please, could you give a hint of how to write a model to fit a distribution? Any other workaround would also be very appriciated.
If it is a necessary information, I’m using ROOT 6.36.04.
pdf_from_tf1.py (3.1 KB)
ds_bkg.root (59.8 KB)
Cheers,
Dasha.