Fit with composite models and get functions of each composite

I do the fitting with composite models,the Xe127 and Xe133 background, as shown in the plots.I hope to get the function of my model,so I use TF1* func = model.asTF(RooArgList(mes), RooArgList(nbkg_xe127, nbkg_xe133));.But the result seems strange.func->Eval(90) return 72.9776 ,it’s not consistant with the plot.

The main question is how can I transform the fitted RooFit pdf into TF1 of each background rather than only the model with all backgrounds as TF1.

Thanks for your help!

test_asTF.C (2.4 KB)
allBKG_twoGaus_lowXe133_set45.root (10.1 KB)

The data file is missing:

Processing test_asTF.C...
Error in <TFile::TFile>: file /Users/couet/Downloads/allBKG_twoGaus_lowXe133_set45.root does not exist
Error in <TH1D::Add>: Attempt to add a non-existing histogram

Sorry,I add the data file. Please check. Hope for our advice.

@moneta might help.

Hi, @moneta. Can you give some advice?Thanks!


If you want to plot your function representing the model on top of the data you need to re-scale to the data normalisation (i.e. number of data points * bin width).
You can do this using the asTF function, but as following, by first getting the normalised pdf as a TF1 and then rescaing it:

TF1* normFunc = model.asTF(RooArgList(mes), RooArgList(nbkg_xe127, nbkg_xe133), RooArgList(mes));
TF1 * func = new TF1("plotFunc",[&](double *x, double *p) { return p[0]* normFunc->EvalPar(x);},E_min,E_max,1);
func->SetParameter(0, data->sumEntries() * mes.getBinWidth(1));

And you can do the same for the two components of your model (the signal pdf and the background pdf).
I think we should probably add an option in RooAbsReal::asTF to return directly a TF1 with a normalisation parameter.



1 Like

Hi, @moneta . I’m very grateful for your reply.
But I still have three questions.

  1. Can you explain the normalisation method number of data points * bin width?
  2. How can I draw the function func? I tried func->Draw(""); But it didn’t work.
  3. I tried to get the funciton of background,eg: Xe127, but it didn’t work. The code is shown as following:
   TF1* normFunc_127 = pdf_Xe127.asTF(RooArgList(mes), RooArgList(nbkg_xe127), RooArgList(mes));
   TF1 * func_127 = new TF1("plotFunc",[&](double *x, double *p) { return p[0]* normFunc_127->EvalPar(x);},E_min,E_max,1);
   func_127->SetParameter(0, 30 * mes.getBinWidth(1)); // 30 is the number of Xe127 background after fitting.

Hope for your reply again.


  1. RooFit provides you a probability density function. If you want the expected yield in each bin (i.e. the expected number of events) this is equal to the probability for each bin, i.e. is the integral of the pdf in the bin which can be approximated by the pdf at the bin centre times the bin width.
    Assuming the total number of expected events is equal to the observed one, then we multiply this probability by the total number of events to get the number for each bin.
  2. It is possible that when you exit the macro the pdf used to create the TF1 is deleted. Use the func->DrawClone("")
  3. For the same reason as abov, use nc_127->DrawClone



1 Like

Hi, @moneta . Thanks for your reply. I understand.
But as for the third question, I still can’t get the component’s function. For example, while trying to get the function of Xe127 part(line 86 87 88).I got the following error:

[#0] ERROR:InputArguments -- RooAbsReal::functor(pdf_Xe127) ERROR: one or more specified parameters are not variables of this p.d.f

I still don’t know how to do this part clearly.

Another question is that, func->Integral(20,145) (line 74)will give some error:

 Error in <GSLError>: Error 11 in qags.c at 543 : number of iterations was insufficient
Warning in <TF1::IntegralOneDim>: Error found in integrating function plotFunc in [20.000000,145.000000] using AdaptiveSingular. Result = 2500.000495 +/- 0.000688  - status = 11

Even though I can get the expected value.So this error seems strange to me.

My updated code is in the attachment. Hope for your reply again.

test_asTF_v2.C (3.2 KB)


When creating the TF1 for pdf_Xe127, which is a RooHistPdf, you should not provide as second argument the parameter nbkg_xe127 because it is not a variable of that pdf. You are passing the parameter later when you define its normalisation by creating function_127.
Just do:

TF1* normFunc_127 = pdf_Xe127.asTF(RooArgList(mes), RooArgList(), RooArgList(mes));

The second error is maybe related to the ill defined function. If not you can also try to use a different integration algorithm for TF1, by doing before calling func->Integral:


or if that one does not work, you can try also "GAUSSLEGENDRE" or "NONADAPTIVE".


1 Like

Hi, @moneta ,
I’m very grateful for your reply, all my problems have been solved.

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