How can I get the fitting result from RooKeysPdf

Dear ROOT experts,

I use the RooKeysPdf to fit the invariant mass spectrum of the Z boson. I can plot the curve of the PDF, but I don’t understand how to see the PDF and the fitting result. How can I get the mass and width (and errors) of the Z boson?

Best regards,
Zhuolin

I think @jonas or @moneta can help

Hi!

There are several ways to do this.

If you are fitting with RooAbsPdf::fitTo(), you can use the Save() keyword to return a valid fit result object e.g. like this:

RooFitResult *r = model.fitTo(*data, RooFit::Save());  // r is owning pointer

You can then use for example r->Print() to get the parameters and their errors printed out.

Furthermore, your model parameters will have the post-fit values and errors after calling fitTo. So if you have a parameter called mass for example, you can simply inspect its value and error with getVal() and getError() respectively.

Hope that helps!

Jonas

Thank you for your kind help!

But it seems like there is always an error when I use fitTo in the model (the RooKeysPdf actually). I glanced at the paper in ROOT: RooKeysPdf Class Reference. The RooKeysPdf is a kind of non-parametric fitting. I don’t know much about it.

How can we get the fitting result from the invariant mass of the Z boson from the non-parametric fitting?

P.S. The error of fitTo is like

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [4], in <cell line: 1>()
----> 1 kest.fitTo(ds)

File ~/miniforge3/envs/my_root/lib/python3.10/site-packages/ROOT/_pythonization/_roofit/_rooabspdf.py:40, in RooAbsPdf.fitTo(self, *args, **kwargs)
     38 # Redefinition of `RooAbsPdf.fitTo` for keyword arguments.
     39 args, kwargs = _kwargs_to_roocmdargs(*args, **kwargs)
---> 40 return self._fitTo(*args, **kwargs)

TypeError: none of the 2 overloaded methods succeeded. Full details:
  RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooCmdArg& arg1 = RooCmdArg::none(), const RooCmdArg& arg2 = RooCmdArg::none(), const RooCmdArg& arg3 = RooCmdArg::none(), const RooCmdArg& arg4 = RooCmdArg::none(), const RooCmdArg& arg5 = RooCmdArg::none(), const RooCmdArg& arg6 = RooCmdArg::none(), const RooCmdArg& arg7 = RooCmdArg::none(), const RooCmdArg& arg8 = RooCmdArg::none()) =>
    AbortSignal: abort from C++; program state was reset
  RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooLinkedList& cmdList) =>
    TypeError: takes at least 2 arguments (1 given)

Hi @zzl0024!

Okay the problem is not getting the fit result, but getting the fit to run to begin with :smiley:

From what you post here, we can only see that there is a crash in RooAbsPdf::fitTo(). But that’s enough to understand the problem. Could you please provide us a full reproducer for the problem?

Thanks and cheers,
Jonas

Hi @jonas,

Here is a simple macro,

import ROOT

f = ROOT.TFile("DYTreeNoBCut2018Skim.root", "read")
zhTree = f.Get("dyTree")
zM = ROOT.RooRealVar("z_mass_roccor", "z_mass_roccor", 75, 105)
ds = ROOT.RooDataSet("ds", "ds", zhTree, ROOT.RooArgSet(zM))
kest = ROOT.RooKeysPdf("kest", "kest", zM, ds, ROOT.RooKeysPdf.MirrorBoth)
kest.fitTo(ds)

The output is like

[#1] INFO:DataHandling -- RooTreeDataStore::loadValues(ds) Skipping event #2887 because z_mass_roccor cannot accommodate the value 105.694
[#1] INFO:DataHandling -- RooTreeDataStore::loadValues(ds) Skipping event #14014 because z_mass_roccor cannot accommodate the value 105.341
[#1] INFO:DataHandling -- RooTreeDataStore::loadValues(ds) Skipping event #29568 because z_mass_roccor cannot accommodate the value 105.015
[#1] INFO:DataHandling -- RooTreeDataStore::loadValues(ds) Skipping event #35699 because z_mass_roccor cannot accommodate the value 105.244
[#1] INFO:DataHandling -- RooTreeDataStore::loadValues(ds) Skipping ...
[#0] WARNING:DataHandling -- RooTreeDataStore::loadValues(ds) Ignored 46 out-of-range events
[#1] INFO:Minimization -- RooAbsMinimizerFcn::setOptimizeConst: activating const optimization
[#1] INFO:Minimization --  The following expressions have been identified as constant and will be precalculated and cached: (kest)
Error in <ROOT::Math::Fitter::SetFCN>: FCN function has zero parameters 
Assertion failed: (fResult.get()), function Result, file /tmp/test/root-feedstock/miniforge3/conda-bld/root_base_1649916745549/work/root-source/math/mathcore/inc/Fit/Fitter.h, line 385.
 *** Break *** abort
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libCore.6.26.02.so] TUnixSystem::DispatchSignals(ESignals) (no debug info)
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/usr/lib/system/libsystem_pthread.dylib] pthread_kill (no debug info)
[/usr/lib/system/libsystem_c.dylib] abort (no debug info)
[/usr/lib/system/libsystem_c.dylib] err (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libRooFitCore.6.26.02.so] RooMinimizer::profileStart() (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libRooFitCore.6.26.02.so] RooAbsPdf::minimizeNLL(RooAbsReal&, RooAbsData const&, RooAbsPdf::MinimizerConfig const&) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libRooFitCore.6.26.02.so] RooAbsPdf::fitTo(RooAbsData&, RooLinkedList const&) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libRooFitCore.6.26.02.so] RooAbsPdf::fitTo(RooAbsData&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&, RooCmdArg const&) (no debug info)
[<unknown binary>] (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy_backend3_10.6.26.02.so] WrapperCall(long, unsigned long, void*, void*, void*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy_backend3_10.6.26.02.so] Cppyy::CallR(long, void*, unsigned long, void*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy3_10.6.26.02.so] CPyCppyy::(anonymous namespace)::InstancePtrExecutor::Execute(long, void*, CPyCppyy::CallContext*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy3_10.6.26.02.so] CPyCppyy::CPPMethod::ExecuteFast(void*, long, CPyCppyy::CallContext*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy3_10.6.26.02.so] CPyCppyy::CPPMethod::ExecuteProtected(void*, long, CPyCppyy::CallContext*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy3_10.6.26.02.so] CPyCppyy::CPPMethod::Call(CPyCppyy::CPPInstance*&, _object*, _object*, CPyCppyy::CallContext*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/lib/libcppyy3_10.6.26.02.so] CPyCppyy::(anonymous namespace)::mp_call(CPyCppyy::CPPOverload*, _object*, _object*) (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyObject_Call (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyEval_EvalFrameDefault (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyEval_Vector (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] call_function (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyEval_EvalFrameDefault (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyEval_Vector (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyRun_SimpleFileObject (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] _PyRun_AnyFileObject (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] Py_RunMain (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] pymain_main (no debug info)
[/Users/zhangzhuolin/miniforge3/envs/my_root/bin/python3.10] main (no debug info)
[/usr/lib/dyld] start (no debug info)
Traceback (most recent call last):
  File "/Users/zhangzhuolin/Hbb/MuonTnP/fitTest.py", line 8, in <module>
    kest.fitTo(ds)
  File "/Users/zhangzhuolin/miniforge3/envs/my_root/lib/python3.10/site-packages/ROOT/_pythonization/_roofit/_rooabspdf.py", line 40, in fitTo
    return self._fitTo(*args, **kwargs)
TypeError: none of the 2 overloaded methods succeeded. Full details:
  RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooCmdArg& arg1 = RooCmdArg::none(), const RooCmdArg& arg2 = RooCmdArg::none(), const RooCmdArg& arg3 = RooCmdArg::none(), const RooCmdArg& arg4 = RooCmdArg::none(), const RooCmdArg& arg5 = RooCmdArg::none(), const RooCmdArg& arg6 = RooCmdArg::none(), const RooCmdArg& arg7 = RooCmdArg::none(), const RooCmdArg& arg8 = RooCmdArg::none()) =>
    AbortSignal: abort from C++; program state was reset
  RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooLinkedList& cmdList) =>
    TypeError: takes at least 2 arguments (1 given)

I run the macro on my Mac M1 in ROOT 6.26/02. The ROOT file is in the CERNBox link, you can check the macro by yourself.

File Link: CERNBox

Hi @zzl0024,

you get a hint to the problem in this output line:

Error in <ROOT::Math::Fitter::SetFCN>: FCN function has zero parameters

A RooKeysPdf is a kernel density estimation pdf, so the shape is completely determined by the dataset ds you pass to its constructor. It doesn’t have any parameters, and you can’t fit a pdf with no parameters.

What did you expect to get from the call to fitTo? What’s the point of trying to fit a template pdf based on a dataset to exactly the same dataset? Maybe your model is incomplete?

Hope this helps!
Jonas

Thank you @jonas !

Because I can’t fit the invariant mass spectrum of Z boson by voigtian function well. My colleague advised me to use RooKeysPdf, however, I didn’t know the non-parametric fitting before. Perhaps I need to use the parametric fitting to get the invariant mass of the Z boson again.

Hi! I think you should ask again your colleague what he meant exactly.

For sure it doesn’t make much sense to fit any distribution with a RooKeysPdf that is based on the distribution itself.