RooCategory inside a RooAbsReal

Good morning
I’m using RooFit to fit a pdf with several observables, with one of them being a RooCategory, with possible values (-1,0,1).

Part of the final pdf is a RooRealSumPdf, with some of the coefficients changing sign depending on the RooCategory. This was implemented by multiplying the coefficients by the category value inside a RooFormulaVar.

The fit runs fine, but when trying to plot it crashes with a cryptic backtrace (segfault inside ostream::sentry…). Investigating the crash it appear that the plotting code of RooFormulaVar, when searching for a proper sampling, assumes that every variable inside the function is a RooAbsReal and static_casts to that, which breaks in the case of my coefficient.

What is the proper way to do this? The simple solution for now is lie about the continuity of the discrete variable and make it a RooRealVar, which is something I can still do at this point of the analysis, but as we add new features in the fit I will need the discrete variable to be actually discrete.

Additionally, would it be possible to add a diagnostic during the construction of the formulavar? Since the fit was running fine and giving correct results I didn’t think the error was on the coefficients at the beginning, I had to inspect the RooFormulaVar source code to understand that placing a RooCategory inside was not supported.

Thanks in advance
Enrico

Hi Enrico,

It sounds like your use case hadn’t been foreseen when the class was designed. Could you point me to the location of the crash, maybe even include a 5 line demo?

I assume that the proper way is to dynamic_cast in RooFormulaVar::plotSamplingHint(). I changed that already locally, but I don’t have a model to test if the plotting works now.

Hello and thanks for the answer.

I made a short example which crashes

void testFormulaCrash()
{
    RooRealVar x("x", "x", 0, 1);
    RooCategory c("c", "c");
    c.defineType("p", 1);
    c.defineType("n", -1);
    c.setIndex(1);
    
    RooFormulaVar f("test", "x*c", RooArgList(x,c));
    
    // works
    cout << f.getVal() << endl;
    
    auto frame = x.frame();
    // crashes
    f.plotOn(frame);
    
    frame->Draw();
}

On my computer when inside plotSamplingHint, when forwarding the call to the subvariables (line 230 of RooFormulaVar.cxx on the master), the function calls instead RooAbsArg::printArgs (due to the corrupted vtable probably). Since there is no actual ostream object the first string printed crashes the macro.

Another fix might be doing something similar to RooProduct, which keeps separate collections for real and category values (something that sadly I noticed only just now, it’s a good workaround).

Enrico

I fixed it, your example plots nicely. I will deploy the fix to master next week.

Is deploying it for root 6.20 enough, or should I backport to older versions?

https://sft.its.cern.ch/jira/browse/ROOT-10367

I don’t control the root version this code will be run on, so I don’t think I will be able to use the fix in any case.

In the meantime I will introduce intermediate variables for each coefficient absolute value and use RooProduct.

Thanks for the help

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