KAHIBARO
Discord Login Register

11.5. Fit Parameters

Reading parameter values

When you fit a histogram or graph in ROOT, the fit function is a TF1 object. The numerical results of the fit, such as the best fit parameters and their uncertainties, are stored inside that TF1. You rarely need to extract anything from the histogram or graph itself; you read the results from the associated TF1.

There are two common ways to get the TF1 after a fit. The first way is to create the TF1 yourself, pass it to Fit, and keep the pointer:

cpp
TH1F *h = new TH1F("h", "Example", 100, -5, 5);
// ... fill h ...
TF1 *fgaus = new TF1("fgaus", "gaus", -2, 2);
h->Fit(fgaus, "R");  // R = use function range

Now fgaus holds the fit result. You can access the fitted parameter values with

cpp
double p0 = fgaus->GetParameter(0);
double p1 = fgaus->GetParameter(1);
double p2 = fgaus->GetParameter(2);

The parameter index starts at 0. For standard ROOT functions the meaning of each index is fixed. For example, for "gaus" the convention is:

IndexMeaning
0Amplitude
1Mean
2Sigma

You can give the parameters names and then access them by name instead of by index. You typically do this right after creating the TF1:

cpp
TF1 *fgaus = new TF1("fgaus", "gaus", -2, 2);
fgaus->SetParName(0, "Amplitude");
fgaus->SetParName(1, "Mean");
fgaus->SetParName(2, "Sigma");
h->Fit(fgaus, "R");
double mean  = fgaus->GetParameter("Mean");
double sigma = fgaus->GetParameter("Sigma");

You can also query the number of parameters and loop over them. This is useful for generic code that should work with different models:

cpp
int npar = fgaus->GetNpar();
for (int i = 0; i < npar; ++i) {
    const char *name = fgaus->GetParName(i);
    double value = fgaus->GetParameter(i);
    std::cout << i << "  " << name << "  " << value << "\n";
}

If you let ROOT create the TF1 internally, for example by calling

cpp
h->Fit("gaus");

ROOT automatically creates a TF1 with name "gaus" and attaches it to the histogram. You can retrieve it later with:

cpp
TF1 *fitfunc = h->GetFunction("gaus");
double mean  = fitfunc->GetParameter(1);
double sigma = fitfunc->GetParameter(2);

Or, if you used a custom name

cpp
h->Fit("myfit", "R");
TF1 *fitfunc = h->GetFunction("myfit");

The same logic works for fits to graphs. For example:

cpp
TGraphErrors *g = new TGraphErrors(/* ... */);
// Define a linear function
TF1 *fline = new TF1("fline", "[0] + [1]*x", 0.0, 10.0);
fline->SetParName(0, "Intercept");
fline->SetParName(1, "Slope");
g->Fit(fline, "R");
double slope     = fline->GetParameter("Slope");
double intercept = fline->GetParameter("Intercept");

For many analyses you will print the final physics result, for example a mean lifetime, to the screen or a file. You typically combine the value and its uncertainty, which you read with GetParameter and GetParError:

cpp
double tau     = fexp->GetParameter(1);
double tauErr  = fexp->GetParError(1);
std::cout << "Tau = " << tau << " +/- " << tauErr << "\n";

If you need the full fit result, including the covariance matrix, you can ask ROOT to return a TFitResultPtr:

cpp
TFitResultPtr r = h->Fit(fgaus, "RS"); // R = range, S = return result
double p0 = r->Parameter(0);
double p1 = r->Parameter(1);
double p2 = r->Parameter(2);

The parameters inside TFitResultPtr are the same values as in the TF1. This object is especially useful when you need correlations or the covariance matrix, which are described in more detail in the chapter about goodness of fit.

Fit parameter values are always stored in the TF1 object. Use GetParameter(i) or GetParameter("name") to read them after the fit.

Parameter uncertainties

Every fitted parameter has a statistical uncertainty that comes from the shape and size of your data sample. These uncertainties quantify how precisely the fit determines the parameters. In ROOT these are given as 1 standard deviation (1 sigma) errors and are stored alongside the parameter values.

For each parameter you can retrieve its uncertainty from the TF1 with

cpp
double value = fgaus->GetParameter(i);
double error = fgaus->GetParError(i);

or with parameter names:

cpp
double mean     = fgaus->GetParameter("Mean");
double meanErr  = fgaus->GetParError("Mean");
double sigma    = fgaus->GetParameter("Sigma");
double sigmaErr = fgaus->GetParError("Sigma");

A typical printout after a Gaussian fit might look like:

cpp
std::cout << "Mean  = " << mean  << " +/- " << meanErr  << "\n";
std::cout << "Sigma = " << sigma << " +/- " << sigmaErr << "\n";

The interpretation is purely statistical. If the errors are computed with standard assumptions, then in many common situations there is about a 68 percent probability that the true parameter value lies within one error of the fitted value. This interpretation depends on the model and on the validity of the fit, topics covered in the chapter on goodness of fit.

There is a direct relation between parameter uncertainties and the quality or amount of data. If you have more entries or a sharper feature, the errors tend to be smaller. If the model is a poor description of the data, the parameter uncertainties may be misleading. It is good practice to examine the chi square or other goodness of fit indicators before you trust the reported errors.

By default ROOT uses the chosen minimizer, for example MINUIT, to compute the parameter errors. If you ask for a TFitResultPtr as described above, you can also access richer error information. For example, you can get the error and the covariance matrix:

cpp
TFitResultPtr r = h->Fit(fgaus, "RS");
// Parameter errors
for (int i = 0; i < fgaus->GetNpar(); ++i) {
    double val = r->Parameter(i);
    double err = r->ParError(i);
    std::cout << fgaus->GetParName(i) << " = " << val
              << " +/- " << err << "\n";
}
// Covariance between parameter 0 and 1
double cov01 = r->CovMatrix(0, 1);

The diagonal elements of the covariance matrix are the variances of each parameter, so the errors are

$$
\sigma_i = \sqrt{\text{CovMatrix}(i, i)}.
$$

ROOT already computes these for you, so in practice you use GetParError or ParError instead of this formula, but it is useful to know what is behind it.

Use GetParError(i) or GetParError("name") to obtain the 1 sigma statistical uncertainty of a fit parameter. These errors come from the fit covariance matrix and are meaningful only if the fit model describes the data adequately.

When you propagate parameter uncertainties to derived quantities, for example when you compute a lifetime from a slope, you need more than just the individual parameter errors. You may also need their correlations, because fit parameters are often not independent. The details of uncertainty propagation and correlation use are covered later, but the starting point is always the parameter values and their errors stored in the TF1 and, optionally, the full TFitResult.

Views: 11

Comments

Please login to add a comment.

Don't have an account? Register now!