Different normalisation of one component alone than the same component in pdf

Hi, I have a problem with different normalisation when I try to plot sum of pdf’s and one component alone. I want to generate data from background only, and I need exactly the same pdf as in the signal + backgroung model. Red line is the background alone. My sum pdf is defined as:
RooAddPdf bkg(“bkg”,“bkg” , RooArgList(expo1, expo2, pol), RooArgList(nbkg1, nbkg2, nbkg3));
RooAddPdf signal(“signal”,“signal” , RooArgList(fit_eta), RooArgList(nsig_eta));

RooAddPdf sum(“sum”,“sum” , RooArgList(bkg, signal));

I tried several options to obtain the same parameters for bkg:
First:
I simply drew bkg.
Second:
RooWorkspace w = new RooWorkspace(“w”,kTRUE);
w->import(sum);
w->Print();
RooAbsPdf bkg1 = w->pdf(“bkg”);
Third:
RooArgSet
comps = sum.getComponents();
RooAbsArg
bkg_arg = comps->find(“bkg”);
RooAddPdf bkg_comp(“bkg_comp”,“bkg_comp” , *bkg_arg);

All options give the same results. What can I do whit this?

Or maybe I can generate pseudo-data from component of pdf? I tried this way:
RooDataSet data_bkg = (RooDataSet) bkg.generate(Photon_M, sample_bkg);
RooDataHist data_h_bkg = (RooDataHist) data_bkg->binnedClone();
I haven’t find any solution.

Hello,

@moneta or @jonas will surely be able to give you an answer, please bear in mind that delays in replying might be bigger in holiday season.

Hi @Justyna, welcome to the ROOT forum!

It’s true, the normalization of the component alone is different from the normalization when you plot the same component in a RooAddPdf. That is the expected behavior. In RooFit, a pdf is always normalized to one in the defined observable range. If you plot a pdf on a frame where you have already plotted data, the normalization is scaled up to the number of events in the dataset.

You should now understand why the red line in your plot doesn’t match what you expect. If you plot the background component alone, it is automatically rescaled to the total number of events.

Now, if you plot only the background component with sum.plotOn(frame, Components("bkg")), the component gets rescaled by the coefficient with which it contributes to the total model. This is equivalent to plotting the background directly, but rescaling it manually:

double nsigVal = signal.expectedEvents(x);
double nbkgVal = bkg.expectedEvents(x);
double fracBkg = nbkgVal / (nsigVal + nbkgVal);
bkg.plotOn(frame, Normalization(fracBkg));

See also the documentation of RooAbsPdf::plotOn(). Of course you can also add you number of expected events together manually from nbkg1, nbkg2, nbkg3, nsig_eta if you want (instead of using RooAbsPdf::expectedEvents()).

Anyway, that’s for plotting. Now about your request “I want to generate data from background only”: why don’t you just do that? Your background pdf is already an extended pdf even, so it knows how many events are expected in the background. Why not simply RooAbsPdf::generate() your background only sample with (replacing x with your actual observable):

RooDataSet *dataBkgOnly = bkg.generate(x);

Here you also have a code snippet based on this example on the ROOT website that you can run in a macro standalone. It should illustrate all I explained before.

using namespace RooFit;

// Observable:
RooRealVar mes("mes", "m_{ES} (GeV)", 5.20, 5.30);

// Parameters:
RooRealVar sigmean("sigmean", "B^{#pm} mass", 5.28, 5.20, 5.30);
RooRealVar sigwidth("sigwidth", "B^{#pm} width", 0.0027, 0.001, 1.);
RooRealVar nsig("nsig", "#signal events", 400, 0., 10000);
RooRealVar nbkg("nbkg", "#background events", 1600, 0., 10000);

// Build a Gaussian PDF:
RooGaussian signalModel("signal", "signal PDF", mes, sigmean, sigwidth);
RooAddPdf signalModelExt("signal_ext",
                         "signal PDF",
                         {signalModel},
                         {nsig});

// Build Argus background PDF:
RooRealVar argpar("argpar", "argus shape parameter", -20.0, -100., -1.);
RooArgusBG background(
    "background", "Argus PDF", mes, RooConst(5.291), argpar);
RooAddPdf backgroundExt("background_ext",
                        "Argus PDF",
                        {background},
                        {nbkg});

// Construct a signal and background PDF:
RooAddPdf model("model", "g+a", {signalModelExt, backgroundExt});

// Generate a toy sample from the background hypothesis only
RooDataSet* dataBkgOnly = backgroundExt.generate(mes);

//model.coefList().Print("V");
double nsigVal = signalModelExt.expectedEvents(mes);
double nbkgVal = backgroundExt.expectedEvents(mes);
double fracBkg = nbkgVal / (nsigVal + nbkgVal);

// Plot backgroun-only toy data
RooPlot* mesframe = mes.frame();
dataBkgOnly->plotOn(mesframe);

// Plot background-only pdf
background.plotOn(mesframe, LineColor(kRed));
// Plot total pdf and backgrund-only pdf as component, both upscaled by
// 1./fracBkg such that the normalization of the background compoment
// matches the data
model.plotOn(mesframe, Normalization(1. / fracBkg));
model.plotOn(mesframe,
             Components(background),
             LineStyle(ELineStyle::kDashed),
             Normalization(1. / fracBkg));

mesframe->Draw();

The plot looks like expected now.

I hope this helps!

Cheers,
Jonas

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