Hi @moneta,

I’ve also been digging into the `WL`

fit, and I was wondering how ROOT actually calculates the weighted negative log-likelihood (NLL) to be minimized.

According to the code you shared, the NLL is computed through lines 1567-1586 with the `WL`

option.

The only difference between the standard `L`

fit is that you multiply `weight = (error * error) / y;`

(Line 1577) to the NLL for each bin (leaving aside when the bin content (y) is 0 for the moment).

So I ran a quick test to compare the NLL for the `L`

fit and `NL`

fit.

Here are my codes:

```
int nbins = 10;
double c_true = 4.5;
TH1F* h = new TH1F("h", "", nbins, 0, nbins);
TF1* f = new TF1("f", "[0]", 0, nbins);
TRandom3* rng = new TRandom3(seed);
for (int i=0; i<nbins; i++) {
for (int j=0; j<rng->Poisson(c_true); j++) {
h->Fill(i, rng->Rndm());
}
}
TFitResultPtr r1 = h->Fit("f", "QSR0"); // Chi-square fit
TFitResultPtr r2 = h->Fit("f", "QSRL0"); // Likelihood fit
TFitResultPtr r3 = h->Fit("f", "QSRWL0"); // Weighted likelihood fit
TGraph* g1 = new TGraph();
TGraph* g2 = new TGraph();
TGraph* g3 = new TGraph();
double theta_start = 0.1;
double theta_end = 3;
f->FixParameter(0, 0);
for (double theta=theta_start; theta<theta_end; theta+=0.01)
{
f->SetParameter(0, theta);
double nll = 0;
for (int i=0; i<nbins; i++) {
double y_i = h->GetBinContent(i+1);
double e_i = h->GetBinError(i+1);
double sum_of_weights = y_i;
double sum_of_weight_squared = e_i * e_i;
double scale_factor = sum_of_weight_squared / sum_of_weights;
nll += scale_factor * (y_i * (log(y_i) - log(theta)) + theta - y_i); // Weighted likelihood fit.
}
TFitResultPtr r1_ = h->Fit("f", "QSRL0");
g1->SetPoint(g1->GetN(), theta, r1_->MinFcnValue());
TFitResultPtr r2_ = h->Fit("f", "QSRWL0");
g2->SetPoint(g2->GetN(), theta, r2_->MinFcnValue());
g3->SetPoint(g3->GetN(), theta, nll);
}
std::cout << "\nChi-squared fit" << std::endl;
std::cout << "Fit\t" << r1->Parameter(0) << "\t" << r1->ParError(0) << std::endl;
std::cout << "\nLikelihood fit" << std::endl;
std::cout << "Fit\t" << r2->Parameter(0) << "\t" << r2->ParError(0) << std::endl;
std::cout << "\nWeighted likelihood fit" << std::endl;
std::cout << "Fit\t" << r3->Parameter(0) << "\t" << r3->ParError(0) << std::endl;
TCanvas* c = new TCanvas("c", "", 800, 600);
g1->SetLineColor(kBlue);
g1->SetLineWidth(2);
g1->Draw("apl");
g2->SetLineColor(kRed);
g2->Draw("same");
g3->SetLineColor(kGreen);
g3->Draw("same");
```

I made a simple histogram with weighted Poisson variables and fitted it with a constant (theta).

`g1`

is the NLL vs. theta in the likelihood fit (blue),

`g2`

is the NLL vs. theta in the weighted likelihood fit (red), and

`g3`

is the NLL vs. theta from the same formula used in ROOT for the `WL`

fit (green).

I expected that red and green are the same, and they are different from blue.

However, the resulting plot shows that red is the same as blue.

It suggests that your NLL for the `WL`

fit is exactly the same as that for the `L`

fit, in contrast to what’s implemented in lines 1567-1586 of your code, which confused me.

And it is unclear to me how the `WL`

fit calculates the covariance matrix.

This could be a separate question, but I also have a doubt about the NLL for the weighted Poisson case.

I followed the references you put and derived that the scale factor should be divided, not multiplied, in the likelihood.

So I believe the line 1577 should be `weight = y / (error * error);`

instead of `weight = (error * error) / y;`

To sum up, I have 3 questions:

- The NLL in the
`WL`

fit seems to be exactly the same as that in the `L`

fit, as opposed to what’s written in the source code. There might be a bug.
- Still, the variance of parameters from the
`WL`

fit is different from the `L`

fit. How the covariance matrix is computed in the `WL`

case?
- The weight
`weight = (error * error) / y;`

seems to be corrected to `weight = y / (error * error);`

Best regards,

On