Hist template fit


I’m trying to fit a 2D histogram to a linear combination of 4 2D template histograms and I was wondering what’s the easiest way to do it in ROOT.
i.e. data->Fit( w1* h_temp1 + w2h_temp2 + w3h_temp3 + w4*h_temp4);


You need to create your own C function that would return the value of your fit function for some weight parameters. From that you can create a TF* that can be fit to your data histogram.

To give you an idea how to fit two histograms to a 1D histogram:

double double_gaussian(double* x, double* pars) {
  // Here I just create the histograms I would like to fit with weights.
  // You don't have to do this here, all that is needed is that the histograms
  // are visible in this function.
  static bool initialized = false;
  static TH1D h1("h1", "", 100, -10, 10);
  static TH1D h2("h2", "", 100, -10, 10);
  if (!initialized) {
    int n = 100000;
    for (int i=0; i<n; ++i) h1.Fill(gRandom->Gaus(-3));
    for (int i=0; i<n; ++i) h2.Fill(gRandom->Gaus(+3));
    initialized = true;

  const double xx = x[0]; // use x[1] to get 2nd dimension, x[2] for 3rd ...
  // the fit parameters, i.e. the histogram weights
  const double w1 = pars[0];
  const double w2 = pars[1];

  // get content of the histograms for this point
  const double y1 = h1.GetBinContent(h1.GetXaxis()->FindFixBin(xx));
  const double y2 = h2.GetBinContent(h2.GetXaxis()->FindFixBin(xx));

  return w1*y1 + w2*y2;

void fit() {
  TH1D h("h", "data", 100, -10, 10);
  for (int i=0; i<100; ++i) h.Fill(gRandom->Gaus(-3));
  for (int i=0; i<100; ++i) h.Fill(gRandom->Gaus(+3));

  // create a fit function from a C function
  TF1 f("double_gaussian", double_gaussian, -10, 10, 2);

  h.Fit(&f, "L");


I’ve tried to follow this example, but my fit is behaving very strangely.
Essentially, I define a function using a template. I then fill a histogram at random from this template and refer to it as data. When trying to fit the data to c*Template (when c is a floating parameter) the result I get is well off.

I’ve attached a short version of my code together with the template and the graphical result of this fit: fitplot.pdf (171 KB)

What am I doing wrong here?

TempFitStandalone.C (4.8 KB)
template.root (72.2 KB)

Hi Nir,

I think I was able to make this succeed (i.e. got pretty plots without understanding too much of the code) by either 1) narrowing the parlimits to something like [-2,2] since the fit wants 0.02 on l.134, or b) dropping all fit options on l.135. Not sure why it failed otherwise.



Hi Benjamin,

I did the same thing, yet the fit still fails (very consistently). Is there some obvious trick I’m missing when fitting templates?
I should add that when the fit is 1-dimensional (i.e. changing one of the NBINS in line 157 to 1) the fit is spot-on.


Okay, I understand the problem. When there’s too few events in the 2D bin, the error on this bin is small, relatively, and so the minimization drags the fit down towards the lower bins. Using Log Likelihood fixes that.