# [RooFit] Why does 2D RooAddPdf use Numerical Integration?

Hi,

I am trying to understand the following behaviour in RooFit. I construct a RooAddPdf from 2D RooHistPdfs (signal and background). I want to plot the model and data projected onto 1D.

The original RooHistPdf getAnalyticalIntegral returns 1 (as I expect as I am doing no interpolation). When I plot it produces the message:

``[#1] INFO:Plotting -- RooAbsReal::plotOn(histPdf_signal) plot on x integrates over variables (y)``

However, the RooAddPdf model getAnalyticalIntegral returns 0 and when I plot informs me that it is using numerical integration.

``````[#1] INFO:Plotting -- RooAbsReal::plotOn(model) plot on x integrates over variables (y)
[#1] INFO:NumericIntegration -- RooRealIntegral::init(model_Int[y]_Norm[x,y]) using numeric integrator RooIntegrator1D to calculate Int(y)``````

However, if I understand correctly the RooAddPdf should calculate the integral as c1int(pdf1)+c2int(pdf2) which (since pdf1 and pdf2 can be integrated analytically) should be exact.

How can I make the projection calculation be performed analytically (i.e. summing over bins rather than applying some generic numerical integration algorithm)?

My full code demonstrating the problem follows.

Cheers,
Dave.

``````from ROOT import TH2F, TRandom3, RooArgSet, RooArgList, RooRealVar, RooDataHist, RooHistPdf, RooAddPdf, TCanvas

#set signal and backgroun event rate
nSignal = 1000
nBackground = 1000
#define binning
binsX, minX, maxX = 2, -3., 3.
binsY, minY, maxY = 2, -3., 3.

#declare histograms
rawSignalHist = TH2F("signal","signal",binsX, minY, maxY, binsY, minY, maxY)
rawBackgroundHist = TH2F("background","background",binsX, minY, maxY, binsY, minY, maxY)
#fill with some fake data
rand = TRandom3(21343)
for i in xrange(nSignal):
x = rand.Gaus(1.,0.5)
y = rand.Gaus(1.,0.5)
rawSignalHist.Fill(x,y)
for i in xrange(nBackground):
x = rand.Gaus(-1.,1.0)
y = rand.Gaus(-1.,1.0)
rawBackgroundHist.Fill(x,y)

#the observables
x = RooRealVar("x","x", minX, maxX)
y = RooRealVar("y","y", minY, maxY)
#make the RooHistPdfs
dataHistSignal = RooDataHist("dataHist_signal","data hist for signal",RooArgList(x,y),rawSignalHist)
histPdfSignal = RooHistPdf("histPdf_signal","histPdf for signal", RooArgSet(x,y), dataHistSignal)
dataHistBackground = RooDataHist("dataHist_background","data hist for background", RooArgList(x,y),rawBackgroundHist)
histPdfBackground = RooHistPdf("histPdf_background","histPdf for background", RooArgSet(x,y), dataHistBackground)
#the parameters
weightSignal = RooRealVar("weightSignal","weightSignal",nSignal,0.,nSignal*2.)
weightBackground = RooRealVar("weightBackground","weightBackground",nBackground,0.,nBackground*2.)
model = RooAddPdf("model","model", RooArgList(histPdfSignal,histPdfBackground), RooArgList(weightSignal, weightBackground))
#make fake data
data = model.generate(RooArgSet(x,y), nSignal+nBackground)

#plot the components of the model
frame = x.frame()
data.plotOn(frame)
print "can integrate RooHistPdf:",histPdfSignal.getAnalyticalIntegral(RooArgSet(x), RooArgSet())#returns 1, can integrate analytically
histPdfSignal.plotOn(frame) # no numeric integration
print "can integrate RooAddPdf:",model.getAnalyticalIntegral(RooArgSet(x), RooArgSet())#returns 0, cannot integrate analytically
model.plotOn(frame)
#plot the model
frame.Draw()

#produces the following output:
# can integrate RooHistPdf: 1
# [#1] INFO:Plotting -- RooAbsReal::plotOn(histPdf_signal) plot on x integrates over variables (y)