Sum of Coefficients is less than the printed sum

Hello Rooters, I am having a problem with my fit. I preform a fit and then I did model -> evaluate(), which sums the coefficients of the fit This printed value is less than the value I sum when looking at the printed final coefficients or when I grab the coefficients and add them.

Some relevant code:

RooRealVar q1(*fix, "emp");
RooRealVar q2("dy", "coeff",  0.5,0.0, 1.);
RooRealVar q3("jpsi", "coeff",  0.2,0.0, 1.);
RooRealVar q4("psip", "coeff",  0.1,0.0, 1.);
RooRealVar q5("jmix", "coeff",  0.3,0.0, 1.);

RooAddPdf *model = new RooAddPdf("model", "model", RooArgList(*rap[1], *rap[2], *rap[4], *rap[5], *rap[3]), RooArgList(q1, q2, q4, q5));

res -> Print();
printf("Sum of Coefficients(%f)\n", model -> evaluate());

Any help is much appreciated.

Hi scottmar1054,

Such normalization problems with a RooAddPdf can often be fixed using the following function:

RooAddPdf::fixAddCoefNormalization(…)

In order to help you further I’d need a minimal working example, whereas the code you provided references rap[1] etc. which is not defined.

Cheers,
Etienne

Hello @scottmar1054,

Two more ideas:

  • Evaluate will not yield the sum of coefficients. It yields Sum(coef * PDF(x, y, …)).
  • You never pass q3. You have the model calculate this one from 1 - sum(coef_i).
    This is explained here:
    RooAddPdf

Below is more of the code:

vector <RooDataSet *> rds(6);
vector <RooAbsPdf *> rap(6);
RooRealVar mass("mass", "mass", min, max);
RooRealVar sigweight("sigweight", "sigweight", 0., 1.e6);
RooArgSet var;
var.add(mass), var.add(sigweight);

TString oName = oname;
TFile *tfile = new TFile(oName);
RooWorkspace *work = (RooWorkspace *)tfile -> Get("work");
TString cuts = Form("(mass>%f) && (mass<%f)", min, max);
RooRealVar *fix = work -> var("fixedRatio");

for (int i = 0; i < inVec.size(); i++)
{
  tf[i] = new TFile(inVec[i],"read");
  TString tname = "background";
  if (inVec[i].Contains("mc")){tname = "signal";}
  tt[i] = (TTree *)tf[i] -> Get(tname);
  rds[i] = new RooDataSet(tsNom[i] + "_dset", tsNom[i], tt[i], var, cuts, "sigweight");
  rap[i] = work -> pdf(tsNom[i] + "_kpdf");
}

RooRealVar q1(*fix, "emp");
RooRealVar q2("dy", "coeff",  0.5,0.0, 1.);
RooRealVar q3("jpsi", "coeff",  0.2,0.0, 1.);
RooRealVar q4("psip", "coeff",  0.1,0.0, 1.);
RooRealVar q5("jmix", "coeff",  0.3,0.0, 1.);
RooDataHist rdh(tsNom[0] + "_dh", "", var, *rds[0]);

RooAddPdf *model = new RooAddPdf("model", "model", RooArgList(*rap[1], *rap[2], *rap[4], *rap[5], *rap[3]), RooArgList(q1, q2, q4, q5));
RooFitResult *res = model -> fitTo(*rds[0], RooFit::Save(), PrintLevel(0), NumCPU(2,0), Minimizer("Minuit2","migrad"));
model -> fixAddCoefNormalization(RooArgList(q1, q2, q4, q5), kTRUE);
printf("Sum of Coefficients(%f)\n", model -> evaluate());

I tried the fixAddCoefNormaization() both containing/not containing q3 and kTRUE/kFALSE and I get -nan as the answer for all of them.

But if the PDF’s are normalized to 1.0 then would not sum of the coefficients be the same as the Sum(coef_i*PDF_i)?

Hi,

it’s still not clear what the problem is. It might just be a misunderstanding, so I will try to clarify one or the other thing below.

RooAddPdf should always sum to 1?

Absolutely not! What you say would mean that all PDFs would be 1 for all values of x (or other variables). What we know is that the integral of each PDF with respect to all it’s variables over their currently defined range is one.

Example

If you evaluate a sum of multiple PDFs, you can expect any value as the result of evaluate(), because the result depends on the PDFs. Think of a Gaussian PDF: It is about 0.4 for x=0, and 0.24 for x=1. Whether or not there’s a coefficient in front of the Gaussian doesn’t change the fact that the result of a call to evaluate() will yield some number between 0 and 0.4. Now take two couple of Gaussians and sum them. Let’s say the coefficients are 0.5 and 0.5. You will get 0.4 for x=0 and 0.24 for x=1. When you start to shift them a bit or scale their widths, these numbers will change, but they won’t be 1 in general.

Evaluating models / parameters

You should not call evaluate on model. In fact, evaluate() should not be visible from the outside. This will be fixed in the next ROOT version. The reason you should not call it is that evaluate() yields only the (unnormalised) value of the model with the current state of the parameters. (Example with a Gaussian PDF: You would get any random value on the Gaussian distribution, depending on the value of x, sigma and mean, and the normalisation constant might be missing.)

What to do instead?

When you do a fit, you are normally not interested in evaluate(), that is, “what is the value of the PDF at the current value of x?”. What you want are the values of the parameters of the PDF. I.e. “What is sigma after the fit?” These values you get by either printing the fit result as you did, or by using something like q1.getVal(), q2.getVal(), ...

Interpretation of the Coefficients of a RooAddPdf

Maybe the problem is in the interpretation of the coefficients?
To understand a bit better what the coefficients for the RooAbsPdf mean, I will try to rephrase a bit the documentation I linked previously:

  • If the RooAddPdf is not extended (one coefficient less than PDFs), this implies that Sum(coef_i) is one. RooFit achieves this by calculating the last coefficient you didn’t give using coef_n = 1. - Sum(coef_i), i < n.
  • If the RooAddPdf is extended (give as many coefficients as PDFs), it is assumed that Sum(coef_i) is the number of events in the respective region.
1 Like

Ahhh, I see now. Yeah, I misunderstood your previous statement. Thanks.

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