RooAddPdf.plotOn with negative components

Dear experts,

Does it exists in RooFit a trick which allows to show negative components in a valid RooAddPdf when

model.plotOn( frame, Components("negcomp")

is used ?

See attached script and results

import ROOT as r 
x = r.RooRealVar('x', 'x', 0, -10, 10)
mean1 = r.RooRealVar('mean1', 'mean1',  4,  -5, 5)
mean2 = r.RooRealVar('mean2', 'mean2', -4,  -5, 5)
mean3 = r.RooRealVar('mean3', 'mean3',  0,  0, 10)

sigma1 = r.RooRealVar('sigma1', 'sigma1',   2, 0.1, 5)
sigma2 = r.RooRealVar('sigma2', 'sigma2',   2, 0.1, 5)
sigma3 = r.RooRealVar('sigma3', 'sigma3',   1, 0.5, 5)

gaus1 = r.RooGaussian('gaus1', 'gaus1', x, mean1, sigma1)
gaus2 = r.RooGaussian('gaus2', 'gaus2', x, mean2, sigma2)
gaus3 = r.RooGaussian('gaus3', 'gaus3', x, mean3, sigma3)
gaus4 = r.RooGaussian('gaus4', 'gaus4', x, mean3, sigma3)

yield1 = r.RooRealVar('frac1', 'frac1', 0.5, -1,1)
yield2 = r.RooRealVar('frac2', 'frac2', 0.5, -1,1)
yield3 = r.RooRealVar('frac3', 'frac3', -0.2, -1,1)
yield4 = r.RooRealVar('frac4', 'frac4',  0.2, -1,1)

pdf = r.RooAddPdf('sum', 'sum', r.RooArgList(gaus1, gaus2, gaus3, gaus4), r.RooArgList(yield1, yield2,yield3, yield4))
cc = r.TCanvas()
frame = x.frame()
pdf.plotOn(frame)
pdf.plotOn( frame,r.RooFit.Components("gaus1"), r.RooFit.LineColor(r.kRed))
pdf.plotOn( frame,r.RooFit.Components("gaus2"), r.RooFit.LineColor(r.kGreen))
pdf.plotOn( frame,r.RooFit.Components("gaus4"), r.RooFit.LineColor(r.kYellow))
pdf.plotOn( frame,r.RooFit.Components("gaus3"), r.RooFit.LineColor(r.kCyan))

frame.Draw()
cc.Draw()

Thanks
Renato

It sees to me that the plotON for the full model works as expected for pdfs, having negative components, but the expected entries in each x-values being still positive defined, however, when Components is used it doesn’t allow to draw the negative one.
Of course one can patch things to grab rooCurves, and draw negative entries, but i wonder if there are special options one can use for those cases.

After some tweaks, i found that i can plot correctly things with

	
    pdfGEN.pdfList().find("gaus1").plotOn( frame, r.RooFit.LineColor(r.kRed),   r.RooFit.Normalization(yield1.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus2").plotOn( frame, r.RooFit.LineColor(r.kBlue),   r.RooFit.Normalization(yield2.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus3").plotOn( frame, r.RooFit.LineColor(r.kCyan),   r.RooFit.Normalization(yield3.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus4").plotOn( frame, r.RooFit.LineColor(r.kViolet),   r.RooFit.Normalization(yield4.getVal(),r.RooAbsReal.NumEvent))

However if i use the Components(“gaus1”) and the same logic on Normalization, it doesn’t work.

I copy here an updated script showing what i am doing

import ROOT as r 

def test() : 
    x = r.RooRealVar('x', 'x', 0, -10, 10)
    mean1 = r.RooRealVar('mean1', 'mean1',  4,  -5, 5)
    mean2 = r.RooRealVar('mean2', 'mean2', -4,  -5, 5)
    mean3 = r.RooRealVar('mean3', 'mean3',  0,  0, 10)

    sigma1 = r.RooRealVar('sigma1', 'sigma1',   2, 0.1, 5)
    sigma2 = r.RooRealVar('sigma2', 'sigma2',   2, 0.1, 5)
    sigma3 = r.RooRealVar('sigma3', 'sigma3',   1, 0.5, 5)

    gaus1 = r.RooGaussian('gaus1', 'gaus1', x, mean1, sigma1)
    gaus2 = r.RooGaussian('gaus2', 'gaus2', x, mean2, sigma2)
    gaus3 = r.RooGaussian('gaus3', 'gaus3', x, mean3, sigma3)
    gaus4 = r.RooGaussian('gaus4', 'gaus4', x, mean3, sigma3)

    yield1 = r.RooRealVar('frac1', 'frac1',  5000, -40000,100000)
    yield2 = r.RooRealVar('frac2', 'frac2',  5000, -40000,100000)
    yield3 = r.RooRealVar('frac3', 'frac3',  1000, -40000,100000)
    yield4 = r.RooRealVar('frac4', 'frac4', -1000, -40000,100000)

    pdfFIT = r.RooAddPdf('sum', 'sum', r.RooArgList(gaus1, gaus2), r.RooArgList(yield1, yield2))
    ds = pdfFIT.generate(r.RooArgList(x),10000)


    pdfGEN = r.RooAddPdf('sumG', 'sumG', r.RooArgList(gaus1, gaus2, gaus3, gaus4), r.RooArgList(yield1, yield2,yield3, yield4))
    pdfGEN.fitTo( ds) 

    cc = r.TCanvas()
    frame = x.frame()
    ds.plotOn(frame)
    pdfGEN.plotOn(frame)
    # gaus1.plotOn(frame)
    # gaus2.plotOn(frame)
    print(yield1.getVal())
    print(yield2.getVal())
    pdfGEN.pdfList().find("gaus1").plotOn( frame, r.RooFit.LineColor(r.kRed),   r.RooFit.Normalization(yield1.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus2").plotOn( frame, r.RooFit.LineColor(r.kBlue),   r.RooFit.Normalization(yield2.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus3").plotOn( frame, r.RooFit.LineColor(r.kCyan),   r.RooFit.Normalization(yield3.getVal(),r.RooAbsReal.NumEvent))
    pdfGEN.pdfList().find("gaus4").plotOn( frame, r.RooFit.LineColor(r.kViolet),   r.RooFit.Normalization(yield4.getVal(),r.RooAbsReal.NumEvent))

    #     gaus2.plotOn( frame, r.RooFit.LineColor(r.kGreen), r.RooFit.Normalization(yield2.getVal(),r.RooAbsReal.NumEvent))
    #     if yield3.getVal() < 0 : 
    #         pdfGEN.plotOn( frame,r.RooFit.Components("gaus3"), r.RooFit.LineColor(r.kYellow), r.RooFit.Normalization(yield3.getVal(),r.RooAbsReal.NumEvent) ) #yield3.getVal()))
    #     else : 
    #         pdfGEN.plotOn( frame,r.RooFit.Components("gaus3"), r.RooFit.LineColor(r.kViolet) ,  r.RooFit.LineColor(r.kViolet))
    #     if yield4.getVal() < 0 : 
    #         pdfGEN.plotOn( frame,r.RooFit.Components("gaus4"), r.RooFit.LineColor(r.kCyan), r.RooFit.Normalization(yield4.getVal(),r.RooAbsReal.NumEvent) ) #yield3.getVal()))
    #     else:
    #         pdfGEN.plotOn( frame,r.RooFit.Components("gaus4"), r.RooFit.LineColor(r.kCyan) ,  r.RooFit.LineColor(r.kCyan))      
    frame.Draw()
    cc.Draw()
    
    wait(1000)
test() 

It would be great to achieve a similar behaviour using the fullModel.plotOn( Components(“XX”)

Hi @RENATO_QUAGLIANI ,
thank you for the follow-up.

I think we need @moneta or @jonas 's help here.

Cheers,
Enrico

1 Like

Hi,
I think this is a limitation of plotting “Components”.
When selecting a components, instead of plotting the corresponding pdf, the evaluation of the RooAddPdf is modified to include the selected components.
See ROOT: roofit/roofitcore/src/RooAddPdf.cxx Source File

This will then result in a negative pdf, that will make RooFit complaining. I don’t know how to fix this easily. It would be great if you can open a GitHub issue on this and we can address in the future. I don’t think is high priority, since workaround exists, for example plotting directly the corresponding component pdf’s.

Cheers
Lorenzo

1 Like

Thanks a lot @moneta to confirm that a direct workaround for Components doesn’t exists, however i guess that the full model drawing is also affected by this issue right?

I am asking this because in some toys i was getting negative components , which generally is fine, but on the plotting things were going crazy not showing me the truth of what the minimizer did, and for fast debugging how correlations of models etc talk each other the plot with negative component is something very useful to have I think. (expecially in very complex fits with > 400 parameters as in my analysis and >20 simultaneous datasets )

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