RooFit: VisualizeError does not contain central value

Dear RooFit Experts,

I am having trouble with the VisualizeError(using the sampling method) producing error bands that do not contain the central value of the fit. I can reproduce this ugliness in the attached code, error_failure.py in the version of RooFit included with ROOT 5.28/00g. The resulting plot that I see is also attached in error_failure_plot.jpg.

The content of the code is as follows:

#!/usr/bin/env python

import sys
from ROOT import gSystem
gSystem.Load('libRooFit')
from ROOT import *
x = RooRealVar("x","x",400,2000) 

values = [...]
errors = [...]

c1 = RooRealVar("constant1","exponential constant 1",-1,0)
efrac1 = RooRealVar("e1f","e1f",0,1)
exp1 = RooExponential("expo1","exponential PDF1",x,c1)
c2 = RooRealVar("constant2","exponential constant 2",-1,0)
exp2 = RooExponential("expo2","exponential PDF2",x,c2)

sum = RooAddPdf("sum","name",RooArgList(exp1,exp2),RooArgList(efrac1))

a_histo = TH1F("allhisto","allhisto",50,0,2000)
a_histo.SetDirectory(0)
a_histo.Sumw2()
for i in xrange(a_histo.GetNbinsX()):
  a_histo.SetBinContent(i,values[i])
  a_histo.SetBinError(i,errors[i])

roo_histo = RooDataHist("name","title",RooArgList(x),a_histo)

efrac1.setVal(0.99)
c1.setVal(0.01)
c2.setVal(0.001)
result = sum.fitTo(roo_histo,RooFit.Save(),RooFit.SumW2Error(kTRUE))

c = TCanvas()
c.SetFillColor(0)

xframe = x.frame() 
roo_histo.plotOn(xframe, RooFit.DataError(RooAbsData.SumW2)) 
sum.plotOn(xframe,RooFit.VisualizeError(result,1,kFALSE),RooFit.FillColor(kYellow))
sum.plotOn(xframe)
roo_histo.plotOn(xframe, RooFit.DataError(RooAbsData.SumW2) ) 
xframe.SetMinimum(0.00001)
xframe.SetMaximum(100)
c.SetLogy()
xframe.Draw()

import os
os.environ["PYTHONINSPECT"] = '1'

The example code fills a histogram and then tries to fit its tail with the sum of two exponential functions. The fit works fine. If the linear method is used for the errors, the results cover the central value. Because of significant correlations between the parameters, the sampling method error method produces a significantly different result. In some instances of this fit, such as the example code attached, the sampling method error method produces an error band that does not contain the central value, which is clearly problematic. It is not at all obvious to me how what is breaking down here, or what I am doing wrong to cause this issue.

Thank you,

-Peter



error_failure.py (2.64 KB)

Self-fixed… somewhat:

This seems to be a novel failure mode of the minimization package. Setting the parameter constraints more tightly fixes this, eg:

c1 = RooRealVar("constant1","exponential constant 1",-0.03,0)
efrac1 = RooRealVar("e1f","e1f",0,1)
exp1 = RooExponential("expo1","exponential PDF1",x,c1)
c2 = RooRealVar("constant2","exponential constant 2",-0.03,0)
exp2 = RooExponential("expo2","exponential PDF2",x,c2)

Alternatively, choosing a different minimization algorithm also seems to fix this:

result = sum.fitTo(roo_histo,RooFit.Save(),RooFit.SumW2Error(kTRUE),RooFit.Minimizer("Minuit2"))

n.b. that with this minimizer chosen, sufficiently large parameter constraints (say -100,0) will cause the fit to segfault.

I am still interested in precisely why the error band is so finicky given these inputs, I’m assuming it is related to the strong correlation between the fit parameters, but this does seem to be a fixable problem.