Binned fit with GenericPdf Roofit

Dear all,

I am quite new in roofit. I would like to fit some binned data with: a pdf obtained with GenericPdf, multiplied by a pdf (let’s call it “bkgProd”) obtained from a histogram.

I am using these lines to build the first pdf:

RooRealVar x0("x0","x0",-2.e-01,-1.e-01);
RooRealVar x1("x1","x1",0.2e-06,2.2e-06);
RooRealVar x2("x2","x2",-4.0e-05,-0.1e-05);
RooArgSet set(y,x0,x1,x2);
RooGenericPdf TF_func("TF_func","TF_func","x0+x1 * y+TMath::Exp(x2 * y)", RooArgSet(set));

However, since data are binned, I built the histograms and the binned pdf of the genericpdf with the following:

RooDataHist* TF_func_histo=TF_func.generateBinned(y,2000000);
 RooHistPdf TF_func_pdf("TF_func_pdf","TF_func_pdf",y,*TF_func_histo,0);

Last, I built the final pdf with:
RooProdPdf allProduct("allProduct","bkgProd*TF_func_pdf",bkgProd,TF_func_pdf);

In the fit I would like to find the best x0, x1 and x2 that fits data.
Now, if I fit data with allProduct, Roofit fixes x0, x1 and x2 to the mean value of the parameter range, that I put before the RooGenericPdf declaration, and the results have no errors.
So, it seems like it does not do the fit.
Do you know how can I build allProduct lefting x0, x1 and x2 free to vary in the fit? Is it correct to build allProduct directly with the RooGeneratedPdf, such as:
RooProdPdf allProduct(“allProduct”,“bkgProd*TF_func”,bkgProd,TF_func);?
I tried to do it but allProduct has a very strange shape due to the fact that TF_func is not binned.

Thank you,


Welcome to the ROOT forum.

I think @moneta can help you.

Hi @LBuonincontri, and welcome!

Good that you asked, because your approach with the RooHistPdf is indeed not correct here.

The RooHistPdf is for when you want to use a fixed histogram as a template for a component in a fit.

That’s why x0, x1 and x2 are not considered in the fit: you only used their initial values to generate toy data for the TF_func_histo, and then you used that toy data as a template for the TF_func_pdf, never using x0, x1 and x2 again.

So yes, it would be correct to use the RooGenericPdf directly instead. It is unexpected that the final PDF has a “very strange shape” as you say. Maybe that’s because of other reasons? Are you sure that your model is correct?

I’m a bit alarmed by the fact that you seem to multiply a background PDF with a signal PDF. I have never seen a case where this makes sense, usually you add a signal PDF with a background PDF with a normalized sum, using the RooAddPdf. You can se an example for this in the rf201_composite.C tutorial. Maybe everything works fine if you add your background PDF and the TF_func instead of doing the product?

For the same reason, I’m worried that your background PDF is called bkgProd. How come that your background PDF is a product? Actually the only reason to have product PDFs is usually because you are multiplying two PDFs for two different observables, but you only have one observable: “y”.

So maybe the reason for getting strange shapes is that you confused product with addition, and not the binned fit?

Feel free to follow up here if this is not the right solution. For that case, it would be helpful if you could also share a complete reproducer code so we can see the “very strange shape” together.


Dear Jonas,

thank you a lot for your reply.
First, I want to give more details about the “strange shape”, I attached the allProduct plot

. You can see that it is the product of a pdf built from a histogram, times the exponential function TF_func. I was worried about the shape of the bins, that are not “horizontal” but follow the exponential fall.

Then, I have omitted some details in my question, since I thought they were not so relevant for it and the analysis strategy that I am following is a bit complex to explain.

However, my goal is to model the background pdf as a product of three pdfs which depend on the same observable y: the first one is built starting from a histogram, the second is built starting from a function with fixed parameters (fixed_func), and the third is what I called TF_func.

bkgProd is the product of the the first and the second terms. I did the product with
I obtained fixed_func with the same procedure I used for TF_func: RooGenericPdf, RooDataHist with generateBinned and RooHistPdf. However in this case the procedure should be correct,
since the function parameters are fixed.

For sure, after I multiplied TF_func to bkgProd, I built the total model by adding the signal.
The idea of what I am trying to do, is to left the TF_func part of background model “free to adapt” to the data when I do the fit, and then I would like to have x0,x1,x2 to be free.

Thank you,


Ah okay!

I see now what you mean. Indeed, if you do a binned fit it’s bad if your PDF changes rapidly in the bin.

But you should not try to wrap your RooGenericPdf in a RooHistPdf. You need to wrap it instead in a RooBinSamplingPdf: ROOT: RooBinSamplingPdf Class Reference.

And then use the RooBinSamplingPdf at every point where you used the RooGenericPdf before.

The RooBinSamplingPdf converts any PDF into a binned PDF by integrating over each bin on the fly to make it “horizontal”, and this is done each time the input PDF parameters change. So I think that should be what you need right?

Dear Jonas,

thank you, I took some time to play with RooBinSamplingPdf. I think that it is the right solution, so thank you!
However I still have some doubts, I tryed to do a simple exercise where I had to fit some points, to see how it works.
This is my code:

RooDataHist points("points","points",y,Import(*points_h));
RooRealVar x0("x0","x0",-2.,2.);
RooRealVar x1("x1","x1",0.,1.);
RooRealVar x2("x2","x2",-0.00005,0.);
RooArgSet set(y,x0,x1,x2);
RooGenericPdf Func("Func","Func","x0+x1*y+TMath::Exp(x2*y)", RooArgSet(set));
RooBinSamplingPdf binSampler("Name", "Plot Label", y, Func);
RooFitResult* res = binSampler.fitTo(points);
RooPlot* frame11 = y.frame(Title("Fit"));

In this case, when I plot binSampler, it is drawn still as a continuous line. Is it correct? Shouldn’t it be a binned pdf? Am I missing something?

For what concern the fit I had to do for the analysis, I implemented the code like above, and then I built the product pdf like this:

RooProdPdf allProduct("bkgProd","bkgProd*TF_func",bkgProd,binSampler);

And added it to the signal to build and fit data. Now I see that x0,x1,x2 are fitted and the allProduct shape now make sense, so I think that I am on the right track.
I have to do further checks on the fit, so I would like to leave this topic open for a few days in case I have further questions.

Thank you again!


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