def signalfit(data_hist, signalfunction, signalname, process): binning = HistBinsToList(data_hist) data_x = HistToList(data_hist) data_error = HistErrorList(data_hist) parfunction = signalfunction.GetNumberFreeParameters() partot = signalfunction.GetNumberFreeParameters() print partot ### 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): # continue bincen = binning[ibin] mu_x = 0 data = data_x[ibin] if data_error[ibin] == 0: continue #if data<0.1: # continue if signalname == "CrystalBall": if par[3] < 0: mu_x = 0 else: t = (bincen - par[2]) / (par[3]) if (par[0] < 0): t = -t absAlpha = abs(par[0]) if (t >= -absAlpha): mu_x = par[4] * exp(-0.5 * t * t) else: nDivAlpha = par[1] / absAlpha AA = exp(-0.5 * absAlpha * absAlpha) B = nDivAlpha - absAlpha arg = nDivAlpha / (B - t) mu_x = par[4] * (arg**par[1]) if signalname == "CrystalBallGaus": if par[3] < 0: mu_x = 0 else: t = (bincen - par[2]) / (par[3]) if (par[0] < 0): t = -t absAlpha = abs(par[0]) if (t >= -absAlpha): mu_x = par[4] * exp(-0.5 * t * t + exp(-(bincen - par[5])**2 / (2 * par[6]**2))) else: nDivAlpha = par[1] / absAlpha AA = exp(-0.5 * absAlpha * absAlpha) B = nDivAlpha - absAlpha arg = nDivAlpha / (B - t) mu_x = par[4] * (arg**par[1] + exp(-(bincen - par[5])**2 / (2 * par[6]**2))) #print mu_x, data, data_error[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 = [125.0] * partot step = [0.1] * partot upper = [1000000] * partot lower = [-100] * partot varname = [] lower[3] = 0 lower[4] = 0 lower[1] = 0 vstart[4] = data_hist.Integral() if process == "signal": vstart[2] = 125 lower[2] = 110 upper[2] = 140 vstart[3] = 10 lower[3] = 2 upper[3] = 25 if len(vstart) > 5: vstart[5] = 125 lower[5] = 110 upper[5] = 140 vstart[6] = 10 lower[6] = 5 upper[6] = 20 if process == "z": vstart[2] = 90 lower[2] = 70 upper[2] = 110 vstart[3] = 10 lower[3] = 2 upper[3] = 30 if len(vstart) > 5: vstart[5] = 90 lower[5] = 70 upper[5] = 110 vstart[6] = 10 lower[6] = 2 upper[6] = 30 for i in range(parfunction): varname.append("p" + str(i)) for i in range(partot): gMinuit.mnparm(i, varname[i], vstart[i], step[i], lower[i], upper[i], ierflag) # 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(signalfunction.GetNumberFreeParameters()): signalfunction.SetParameter(p, fitval[p]) print "fit uncert", fiterr_p[p] signalfunction.SetChisquare(fmin_p[0]) print fmin_p[0] return fitval[partot - 1], fitval[partot - 2]
def fit(self): numberOfParameters = len(self.samples) gMinuit = TMinuit(numberOfParameters) if self.method == 'logLikelihood': # set function for minimisation gMinuit.SetFCN(self.logLikelihood) gMinuit.SetMaxIterations(1000000000000) # set Minuit print level # printlevel = -1 quiet (also suppress all warnings) # = 0 normal # = 1 verbose # = 2 additional output giving intermediate results. # = 3 maximum output, showing progress of minimizations. gMinuit.SetPrintLevel(-1) # Error definition: 1 for chi-squared, 0.5 for negative log likelihood # SETERRDEF<up>: Sets the value of UP (default value= 1.), defining parameter errors. # Minuit defines parameter errors as the change in parameter value required to change the function value by UP. # Normally, for chisquared fits UP=1, and for negative log likelihood, UP=0.5. gMinuit.SetErrorDef(0.5) # error flag for functions passed as reference.set to as 0 is no error errorFlag = Long(2) N_min = 0 N_max = self.fit_data_collection.max_n_data() * 2 param_index = 0 # MNPARM # Implements one parameter definition: # mnparm(k, cnamj, uk, wk, a, b, ierflg) # K (external) parameter number # CNAMK parameter name # UK starting value # WK starting step size or uncertainty # A, B lower and upper physical parameter limits # and sets up (updates) the parameter lists. # Output: IERFLG =0 if no problems # >0 if MNPARM unable to implement definition for sample in self.samples: # all samples but data if self.n_distributions > 1: gMinuit.mnparm( param_index, sample, self.normalisation[self.distributions[0]][sample], 10.0, N_min, N_max, errorFlag) else: gMinuit.mnparm(param_index, sample, self.normalisation[sample], 10.0, N_min, N_max, errorFlag) param_index += 1 arglist = array('d', 10 * [0.]) # minimisation strategy: 1 standard, 2 try to improve minimum (a bit slower) arglist[0] = 2 # minimisation itself # SET STRategy<level>: Sets the strategy to be used in calculating first and second derivatives and in certain minimization methods. # In general, low values of <level> mean fewer function calls and high values mean more reliable minimization. # Currently allowed values are 0, 1 (default), and 2. gMinuit.mnexcm("SET STR", arglist, 1, errorFlag) gMinuit.Migrad() gMinuit.mnscan( ) # class for minimization using a scan method to find the minimum; allows for user interaction: set/change parameters, do minimization, change parameters, re-do minimization etc. gMinuit.mnmatu(1) # prints correlation matrix (always needed) self.module = gMinuit self.performedFit = True if not self.module: raise Exception( 'No fit results available. Please run fit method first') results = {} param_index = 0 for sample in self.samples: temp_par = Double(0) temp_err = Double(0) self.module.GetParameter(param_index, temp_par, temp_err) if (math.isnan(temp_err)): self.logger.warning( 'Template fit error is NAN, setting to sqrt(N).') temp_err = math.sqrt(temp_par) # gMinuit.Command("SCAn %i %i %i %i" % ( param_index, 100, N_min, N_total ) ); # scan = gMinuit.GetPlot() # results[sample] = ( temp_par, temp_err, scan ) results[sample] = (temp_par, temp_err) param_index += 1 # # gMinuit.Command("CONtour 1 2 3 50") # gMinuit.SetErrorDef(1) # results['contour'] = [gMinuit.Contour(100, 0, 1)] # gMinuit.SetErrorDef(4) # results['contour'].append(gMinuit.Contour(100, 0, 1)) self.results = results
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]