Combined histogram fit using Log Likelihood

Hello all!

I am trying to fit a set of multiple histograms in PyROOT to the same (user-defined) function with some of the parameters free to vary and others forced to be the same for all histograms. It is similar to the combinedFit.py tutorial only the function is different and I defined a function that takes in any arbitrary number of histograms and fits them all to the same function. This code uses the Chi2 method to fit (as far as I understand) but I would like to do the exact same thing only with the Log Likelihood method instead. I have code below showing how I did the Chi2 fit:

import ROOT
from ROOT import TFile, TObject, TCanvas, TH1F, gROOT
import numpy as np
import os

ipars = []
for i in range (15):
    ipars.append(np.array([0, 1, 2*(i+1), (2*(i+1))+1], dtype=np.int32)) # C_TT, C_TN, alpha, kappa
print(ipars)

# Create GlobalChi2 structure
class GlobalChi2(object):
    def __init__(self, f_array):
        self._f = f_array
 
    def __call__(self, par):
        par_arr = np.frombuffer(par, dtype=np.float64, count=22)

        p = []
        for i in range(len(self._f)):
            p.append(par_arr[ipars[i]])

        s = self._f[0](p[0])
        for i in range(len(self._f)-1):
            s += self._f[i+1](p[i+1])
        return s


def ArcaneMultiFitPsi_Chi2(hists, C_TT=0.99, C_TN=-0.01):
    n = len(hists)
    fits, ranges, data, chi2 = np.zeros((n), dtype=object), np.zeros((n), dtype=object),np.zeros((n), dtype=object), np.zeros((n), dtype=object)
    opt = ROOT.Fit.DataOptions()
    for i in range(n):
        fits[i] = ROOT.TF1(f"f{i}", "[2] + [3]*([0]*cos(2*x) + [1]*sin(2*x))", -np.pi, np.pi)
        fits[i].SetParameters(1000., 10., 1., 0.)
        wfit = ROOT.Math.WrappedMultiTF1(fits[i], 1)
        
        ranges[i] = ROOT.Fit.DataRange()
        ranges[i].SetRange(-np.pi, np.pi)
        data[i] = ROOT.Fit.BinData(opt, ranges[i])
        ROOT.Fit.FillData(data[i], hists[i])
        chi2[i] = ROOT.Fit.Chi2Function(data[i], wfit)

    globalChi2 = GlobalChi2(chi2)

    fitter = ROOT.Fit.Fitter()

    Npar = 2 + n*2
    par0 = np.array([C_TT, C_TN])
    for i in range (n):
        par0 = np.append(par0, [1000.0])
        par0 = np.append(par0, [10.0])

    fitter.Config().SetParamsSettings(Npar, par0)
    fitter.Config().ParSettings(0).Fix()
    fitter.Config().ParSettings(1).Fix()
    fitter.Config().MinimizerOptions().SetPrintLevel(0)
    fitter.Config().SetMinimizer("Minuit2", "Migrad")

    globalChi2Functor = ROOT.Math.Functor(globalChi2, Npar)

    dataSize = 0
    for i in range(n):
        dataSize += data[i].Size()

    fitter.FitFCN(globalChi2Functor, 0, int(dataSize), True)
    
    return fitter, fits

The “hists” input object is an array of ROOT histogram files passed into the function. Running this function with input histograms works and fits nicely. However I have struggled to try to adapt this to do the log likelihood fit. If anyone could help show me how to do this that would be fantastic! If it becomes necessary to pass ntuples or branches of ntuples as inputs to make it work, I’m fine with that, just please explain exactly what is being inputted. I also would like to be able to extract the fit parameters, likelihood or log likelihood from the fit results.

@moneta I consulted your combinedFit.py script a lot while developing my Chi2 multi-histogram fit, so if you could give some input on this issue and how to do the same thing with a Log Likelihood fit, I would really appreciate it!

Thank you so much!

Best regards,
Matt

I gues @moneta can help.

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