コード例 #1
0
def bkgfit(data_hist,
           bkgfunction,
           bkgname,
           doFloatZ=False,
           signal_hist=None,
           z_hist=None):
    isBkgPlusZFit = False
    isSpuriousFit = False

    binning = HistBinsToList(data_hist)
    data_x = HistToList(data_hist)
    data_error = HistErrorList(data_hist)

    z_x = []
    signal_x = []

    if z_hist != None:
        isBkgPlusZFit = True
        z_x = HistToList(z_hist)

    if signal_hist != None:
        isSpuriousFit = True
        signal_x = HistToList(signal_hist)

    parfunction = bkgfunction.GetNumberFreeParameters()
    partot = bkgfunction.GetNumberFreeParameters() + 2

    ### the fucntion used for TMinuit
    def fcn(npar, gin, f, par, ifag):
        L = 0

        # calculate likelihood, input par[0] is the N_B, par[1] is N_C, par[2] is N_L
        for ibin in range(len(binning)):
            if (data_x[ibin] < 0.5):
                continue

            bincen = binning[ibin]

            bkg = 0
            data = data_x[ibin]

            if bkgname == "BernsteinO2":
                bkg = (par[0] * (1 - (bincen - fit_start) / fit_range)**2 +
                       2 * par[1] * (1 - (bincen - fit_start) / fit_range) *
                       ((bincen - fit_start) / fit_range) + par[2] *
                       ((bincen - fit_start) / fit_range)**2)

            if bkgname == "BernsteinO3":
                bkg = par[0] * (1 - (
                    (bincen - fit_start) / fit_range))**3 + par[1] * (
                        3 * ((bincen - fit_start) / fit_range) *
                        (1 -
                         ((bincen - fit_start) / fit_range))**2) + par[2] * (
                             3 * ((bincen - fit_start) / fit_range)**2 *
                             (1 -
                              ((bincen - fit_start) / fit_range))) + par[3] * (
                                  (bincen - fit_start) / fit_range)**3

            if bkgname == "BernsteinO4":
                bkg = par[0] * (1 - (
                    (bincen - fit_start) / fit_range))**4 + par[1] * (
                        4 * ((bincen - fit_start) / fit_range) *
                        (1 -
                         ((bincen - fit_start) / fit_range))**3) + par[2] * (
                             6 * ((bincen - fit_start) / fit_range)**2 *
                             (1 - ((bincen - fit_start) / fit_range))**2
                         ) + par[3] * (
                             4 * ((bincen - fit_start) / fit_range)**3 *
                             (1 -
                              ((bincen - fit_start) / fit_range))) + par[4] * (
                                  (bincen - fit_start) / fit_range)**4

            if bkgname == "BernsteinO5":
                bkg = par[0] * (1 - (
                    (bincen - fit_start) / fit_range))**5 + par[1] * (5 * (
                        (bincen - fit_start) / fit_range) * (1 - (
                            (bincen - fit_start) / fit_range))**4) + par[2] * (
                                10 * ((bincen - fit_start) / fit_range)**2 *
                                (1 - ((bincen - fit_start) / fit_range))**3
                            ) + par[3] * (10 * (
                                (bincen - fit_start) / fit_range)**3 * (1 - (
                                    (bincen - fit_start) / fit_range
                                ))**2) + par[4] * (5 * (
                                    (bincen - fit_start) / fit_range)**4 *
                                                   (1 -
                                                    ((bincen - fit_start) /
                                                     fit_range))) + par[5] * (
                                                         (bincen - fit_start) /
                                                         fit_range)**5

            if bkgname == "BernsteinO6":
                bkg = (par[0] * (1 - ((bincen - fit_start) / fit_range))**6 +
                       par[1] * (6 * ((bincen - fit_start) / fit_range)**1 *
                                 (1 - ((bincen - fit_start) / fit_range))**5) +
                       par[2] * (15 * ((bincen - fit_start) / fit_range)**2 *
                                 (1 - ((bincen - fit_start) / fit_range))**4) +
                       par[3] * (20 * ((bincen - fit_start) / fit_range)**3 *
                                 (1 - ((bincen - fit_start) / fit_range))**3) +
                       par[4] * (15 * ((bincen - fit_start) / fit_range)**4 *
                                 (1 - ((bincen - fit_start) / fit_range))**2) +
                       par[5] * (6 * ((bincen - fit_start) / fit_range)**5 *
                                 (1 - ((bincen - fit_start) / fit_range))**1) +
                       par[6] * ((bincen - fit_start) / fit_range)**6)

            if bkgname == "ExpoBernsteinO2":
                try:
                    bkg = exp(par[0] * (bincen - fit_start) / fit_range) * (
                        par[1] *
                        (1 -
                         (bincen - fit_start) / fit_range)**2 + 2 * par[2] *
                        (1 - (bincen - fit_start) / fit_range) *
                        ((bincen - fit_start) / fit_range) + par[3] *
                        ((bincen - fit_start) / fit_range)**2)
                except OverflowError:
                    bkg = 0

            if bkgname == "ExpoBernsteinO3":
                try:
                    bkg = exp(par[0] * (bincen - fit_start) / fit_range) * (
                        par[1] *
                        (1 - ((bincen - fit_start) / fit_range))**3 + par[2] *
                        (3 * ((bincen - fit_start) / fit_range) *
                         (1 -
                          ((bincen - fit_start) / fit_range))**2) + par[3] *
                        (3 * ((bincen - fit_start) / fit_range)**2 *
                         (1 - ((bincen - fit_start) / fit_range))) + par[4] *
                        ((bincen - fit_start) / fit_range)**3)
                except OverflowError:
                    bkg = 0

            if bkgname == "ExpoBernsteinO4":
                try:
                    bkg = exp(par[0] * (bincen - fit_start) / fit_range) * (
                        par[1] *
                        (1 - ((bincen - fit_start) / fit_range))**4 + par[2] *
                        (4 * ((bincen - fit_start) / fit_range) *
                         (1 -
                          ((bincen - fit_start) / fit_range))**3) + par[3] *
                        (6 * ((bincen - fit_start) / fit_range)**2 *
                         (1 -
                          ((bincen - fit_start) / fit_range))**2) + par[4] *
                        (4 * ((bincen - fit_start) / fit_range)**3 *
                         (1 - ((bincen - fit_start) / fit_range))) + par[5] *
                        ((bincen - fit_start) / fit_range)**4)
                except OverflowError:
                    bkg = 0

            if bkgname == "ExpoBernsteinO5":
                try:
                    bkg = exp(par[0] * (bincen - fit_start) / fit_range) * (
                        par[1] *
                        (1 - ((bincen - fit_start) / fit_range))**5 + par[2] *
                        (5 * ((bincen - fit_start) / fit_range) *
                         (1 -
                          ((bincen - fit_start) / fit_range))**4) + par[3] *
                        (10 * ((bincen - fit_start) / fit_range)**2 *
                         (1 -
                          ((bincen - fit_start) / fit_range))**3) + par[4] *
                        (10 * ((bincen - fit_start) / fit_range)**3 *
                         (1 -
                          ((bincen - fit_start) / fit_range))**2) + par[5] *
                        (5 * ((bincen - fit_start) / fit_range)**4 *
                         (1 - ((bincen - fit_start) / fit_range))) + par[6] *
                        ((bincen - fit_start) / fit_range)**5)
                except OverflowError:
                    bkg = 0

            if bkgname == "ExpoPolO2":
                bkg = exp(-(par[0] + par[1] *
                            ((bincen - fit_start) / fit_range) + par[2] *
                            ((bincen - fit_start) / fit_range)**2))

            if bkgname == "ExpoPolO3":
                bkg = exp(-(par[0] + par[1] *
                            ((bincen - fit_start) / fit_range) + par[2] *
                            ((bincen - fit_start) / fit_range)**2 + par[3] *
                            ((bincen - fit_start) / fit_range)**3))

            if bkgname == "ExpoPolO4":
                bkg = exp(-(par[0] + par[1] *
                            ((bincen - fit_start) / fit_range) + par[2] *
                            ((bincen - fit_start) / fit_range)**2 + par[3] *
                            ((bincen - fit_start) / fit_range)**3 + par[4] *
                            ((bincen - fit_start) / fit_range)**4))

            mu_x = bkg

            #if isBkgPlusZFit:
            #    mu_x = mu_x + (par[partot-1] *z_x[ibin])

            if isSpuriousFit:
                mu_x = mu_x + par[partot - 2] * signal_x[ibin]

            #L = L + mu_x - data*log(mu_x)

            L = L + ((mu_x - data) / data_error[ibin])**2

        f[0] = L

    # initialize the TMinuit object
    arglist_p = 10 * [0]

    arglist = array.array('d')
    arglist.fromlist(arglist_p)
    ierflag = Long(0)
    maxiter = 1000000000

    arglist_p = [1]
    gMinuit = TMinuit(partot)
    gMinuit.mnexcm('SET PRIntout', arglist, 0, ierflag)

    gMinuit.SetPrintLevel(1)
    gMinuit.SetErrorDef(1.0)
    gMinuit.SetFCN(fcn)

    arglist_p = [2]
    arglist = array.array('d')
    arglist.fromlist(arglist_p)
    gMinuit.mnexcm('SET STRategy', arglist, 1, ierflag)

    arglist_p = [maxiter, 0.0000001]
    arglist = array.array('d')
    arglist.fromlist(arglist_p)
    gMinuit.mnexcm('MIGrad', arglist, 2, ierflag)
    gMinuit.SetMaxIterations(maxiter)

    # initialize fitting the variables
    vstart = [100.0] * partot
    # start alpha_z with 1
    vstart[partot - 1] = 1.0
    vstart[partot - 2] = 0

    step = [0.1] * partot
    upper = [100000] * partot
    lower = [0.1] * partot
    varname = []

    if "ExpoPol" in bkgname:
        upper = [1000] * partot
        lower = [-1000] * partot

    if "ExpoBernstein" in bkgname:
        vstart[0] = -1
        upper[0] = 0
        lower[0] = -10

    for i in range(parfunction):
        varname.append("p" + str(i))

    varname.append("alpha_sig")
    varname.append("alpha_z")

    if doFloatZ:
        vstart[partot - 1] = 1.0
        upper[partot - 1] = 2
        lower[partot - 1] = 0
        step[partot - 1] = 0.01

    if isSpuriousFit:
        upper[partot - 2] = 10.0
        lower[partot - 2] = -10.0
        step[partot - 2] = 0.1
        vstart[partot - 2] = 1

    for i in range(partot):
        gMinuit.mnparm(i, varname[i], vstart[i], step[i], lower[i], upper[i],
                       ierflag)

    if not isSpuriousFit:
        vstart[partot - 2] = 0
        gMinuit.FixParameter(partot - 2)

    if not doFloatZ:
        lower[partot - 1] = 1
        upper[partot - 1] = 1
        gMinuit.FixParameter(partot - 1)

    if not isBkgPlusZFit:
        vstart[partot - 1] = 0.0
        gMinuit.FixParameter(partot - 1)

    # fitting procedure
    migradstat = gMinuit.Command('MIGrad ' + str(maxiter) + ' ' + str(0.001))
    improvestat = gMinuit.Command('IMProve ' + str(maxiter) + ' ' + str(0.01))

    for i in range(partot):
        arglist_p.append(i + 1)

    arglist = array.array('d')
    arglist.fromlist(arglist_p)

    #gMinuit.mnmnos()

    # get fitting parameters
    fitval_p = [Double(0)] * partot
    fiterr_p = [Double(0)] * partot
    errup_p = [Double(0)] * partot
    errdown_p = [Double(0)] * partot
    eparab_p = [Double(0)] * partot
    gcc_p = [Double(0)] * partot

    fmin_p = [Double(0)]
    fedm_p = [Double(0)]
    errdef_p = [Double(0)]
    npari_p = Long(0)
    nparx_p = Long(0)
    istat_p = Long(0)

    fitval = array.array('d')
    fiterr = array.array('d')
    errup = array.array('d')
    errdown = array.array('d')
    eparab = array.array('d')
    gcc = array.array('d')

    for i in range(partot):
        gMinuit.GetParameter(i, fitval_p[i], fiterr_p[i])
        fitval.append(fitval_p[i])
        fiterr.append(fiterr_p[i])
        errup.append(errup_p[i])
        errdown.append(errdown_p[i])
        eparab.append(eparab_p[i])
        gcc.append(gcc_p[i])

    gMinuit.mnstat(fmin_p[0], fedm_p[0], errdef_p[0], npari_p, nparx_p,
                   istat_p)

    for p in range(bkgfunction.GetNumberFreeParameters()):
        bkgfunction.SetParameter(p, fitval[p])
        print "fit uncert", fiterr_p[p]

    bkgfunction.SetChisquare(fmin_p[0])

    return fitval[partot - 1], fitval[partot - 2]
コード例 #2
0
class minuitSolver():
    def __init__(self, fcn, pars, parerrors, parnames, ndof, maxpars=50):

        if len(pars) > maxpars:
            raise MinuitError("More than 50 parameters, increase maxpars")
        self.__minuit = TMinuit(maxpars)
        self.minuitCommand("SET PRI -1")
        # Hold on to fcn or python will kill it after passing to TMinuit
        self.__fcn = fcn
        self.__minuit.SetFCN(fcn)
        self.__pars = pars
        self.__parerrors = parerrors
        self.__parnames = parnames
        self.__setParameters()
        self.__ndof = ndof
        return

    def __setParameters(self):
        for par, parerror, parname, i in zip(self.__pars, self.__parerrors,
                                             self.__parnames,
                                             range(len(self.__pars))):
            ierflg = self.__minuit.DefineParameter(i, parname, par, parerror,
                                                   0.0, 0.0)
        if ierflg != 0:
            message = "Minuit define parameter error: " + str(ierflg)
            raise MinuitError(message)
        return

    def minuitCommand(self, command):
        errorcode = self.__minuit.Command(command)
        if errorcode != 0:
            message = "Minuit command " + command + " failed: " + str(
                errorcode)
            raise MinuitError(message)
        return

    def solve(self, lBlobel=True):
        self.__setParameters()
        self.minuitCommand("MIGRAD")
        return

    def getChisq(self):
        hstat = self.__getStat()
        return hstat["min"]

    def getNdof(self):
        return self.__ndof

    def __printPars(self, par, parerrors, parnames, ffmt=".4f"):
        for ipar in range(len(par)):
            name = parnames[ipar]
            print("{0:>15s}:".format(name), end=" ")
            fmtstr = "{0:10" + ffmt + "} +/- {1:10" + ffmt + "}"
            print(fmtstr.format(par[ipar], parerrors[ipar]))
        return

    def printResults(self, ffmt=".4f", cov=False, corr=False):
        print("\nMinuit least squares")
        print("\nResults after minuit fit")
        hstat = self.__getStat()
        chisq = hstat["min"]
        ndof = self.__ndof
        fmtstr = "\nChi^2= {0:" + ffmt + "} for {1:d} d.o.f, Chi^2/d.o.f= {2:" + ffmt + "}, P-value= {3:" + ffmt + "}"
        print(
            fmtstr.format(chisq, ndof, chisq / float(ndof),
                          TMath.Prob(chisq, ndof)))
        fmtstr = "Est. dist. to min: {0:.3e}, minuit status: {1}"
        print(fmtstr.format(hstat["edm"], hstat["status"]))
        print("\nFitted parameters and errors")
        print("           Name       Value          Error")
        pars = self.getPars()
        parerrors = self.getParErrors()
        self.__printPars(pars, parerrors, self.__parnames, ffmt=ffmt)
        if cov:
            self.printCovariances()
        if corr:
            self.printCorrelations()
        return

    def __printMatrix(self, m, ffmt):
        mshape = m.shape
        print("{0:>10s}".format(""), end=" ")
        for i in range(mshape[0]):
            print("{0:>10s}".format(self.__parnames[i]), end=" ")
        print()
        for i in range(mshape[0]):
            print("{0:>10s}".format(self.__parnames[i]), end=" ")
            for j in range(mshape[1]):
                fmtstr = "{0:10" + ffmt + "}"
                print(fmtstr.format(m[i, j]), end=" ")
            print()
        return

    def printCovariances(self):
        print("\nCovariance matrix:")
        self.__printMatrix(self.getCovariancematrix(), ".3e")
        return

    def printCorrelations(self):
        print("\nCorrelation matrix:")
        self.__printMatrix(self.getCorrelationmatrix(), ".3f")
        return

    def getPars(self):
        pars, parerrors = self.__getPars()
        return pars

    def getUparv(self):
        pars = self.getPars()
        parv = matrix(pars)
        parv.shape = (len(pars), 1)
        return parv

    def getParErrors(self):
        pars, parerrors = self.__getPars()
        return parerrors

    def __getPars(self):
        pars = []
        parerrors = []
        for ipar in range(len(self.__pars)):
            par = c_double()
            pare = c_double()
            ivarbl = self.__minuit.GetParameter(ipar, par, pare)
            if ivarbl < 0:
                message = "Parameter " + str(ipar) + " not defined"
                raise MinuitError(message)
            pars.append(par.value)
            parerrors.append(pare.value)
        return pars, parerrors

    def getCovariancematrix(self):
        npar = len(self.__pars)
        covm = array(npar**2 * [0.0], dtype="double")
        self.__minuit.mnemat(covm, npar)
        covm.shape = (npar, npar)
        return covm

    def getCorrelationmatrix(self):
        covm = self.getCovariancematrix()
        corrm = covm.copy()
        npar = len(self.__pars)
        for i in range(npar):
            for j in range(npar):
                corrm[i, j] = covm[i, j] / sqrt(covm[i, i] * covm[j, j])
        return corrm

    def __getStat(self):
        fmin = c_double()
        fedm = c_double()
        errdef = c_double()
        npari = c_int()
        nparx = c_int()
        istat = c_int()
        self.__minuit.mnstat(fmin, fedm, errdef, npari, nparx, istat)
        hstat = {
            "min": fmin.value,
            "edm": fedm.value,
            "errdef": errdef.value,
            "npari": npari.value,
            "nparx": nparx.value,
            "status": istat.value
        }
        return hstat