def profile(self, parameter_name, bins=21, bound=2, args=None, subtract_min=False): if self.__gMinuit is None: raise MinimizerROOTTMinuitException("Need to perform a fit before calling profile()!") MAX_ITERATIONS = 6000 _error_code = Long(0) _minuit_id = Long(self.parameter_names.index(parameter_name) + 1) _par_min = Double(0) _par_err = Double(0) self.__gMinuit.GetParameter(_minuit_id - 1, _par_min, _par_err) _x = np.linspace(start=_par_min - bound * _par_err, stop=_par_min + bound * _par_err, num=bins, endpoint=True) self.__gMinuit.mnexcm("FIX", arr('d', [_minuit_id]), 1, _error_code) _y = np.zeros(bins) for i in range(bins): self.__gMinuit.mnexcm("SET PAR", arr('d', [_minuit_id, Double(_x[i])]), 2, _error_code) self.__gMinuit.mnexcm("MIGRAD", arr('d', [MAX_ITERATIONS, self.tolerance]), 2, _error_code) _y[i] = self.get_fit_info("fcn") self.__gMinuit.mnexcm("RELEASE", arr('d', [_minuit_id]), 1, _error_code) self._migrad() self.__gMinuit.mnexcm("SET PAR", arr('d', [_minuit_id, Double(_par_min)]), 2, _error_code) return np.asarray((_x, _y))
def _recreate_gMinuit(self): self.__gMinuit = TMinuit(self.n_pars) self.__gMinuit.SetPrintLevel(-1) self.__gMinuit.mncomd("SET STRATEGY {}".format(self._strategy), Long(0)) self.__gMinuit.SetFCN(self._minuit_fcn) self.__gMinuit.SetErrorDef(self._err_def) # set gMinuit parameters error_code = Long(0) for _pid, (_pn, _pv, _pe) in enumerate(zip(self._par_names, self._par_val, self._par_err)): self.__gMinuit.mnparm(_pid, _pn, _pv, 0.1 * _pe, 0, 0, error_code) err_code = Long(0) # set fixed parameters for _par_id, _pf in enumerate(self._par_fixed_mask): if _pf: self.__gMinuit.mnfixp(_par_id, err_code) # set parameter limits for _par_id, _pl in enumerate(self._par_limits): if _pl is not None: _lo_lim, _up_lim = _pl self.__gMinuit.mnexcm("SET LIM", arr('d', [_par_id + 1, _lo_lim, _up_lim]), 3, error_code)
def test2PassBuiltinsByNonConstRef(self): """Test parameter passing of builtins through non-const reference""" SetLongThroughRef = ROOT.SetLongThroughRef SetDoubleThroughRef = ROOT.SetDoubleThroughRef SetIntThroughRef = ROOT.SetIntThroughRef if sys.hexversion < 0x3000000: l = Long(pylong(42)) SetLongThroughRef(l, 41) self.assertEqual(l, 41) if sys.hexversion >= 0x2050000: import ctypes l = ctypes.c_long(42) SetLongThroughRef(l, 41) self.assertEqual(l.value, 41) d = Double(3.14) SetDoubleThroughRef(d, 3.1415) self.assertEqual(d, 3.1415) if sys.hexversion < 0x3000000: i = Long(pylong(42)) SetIntThroughRef(i, 13) self.assertEqual(i, 13) if sys.hexversion >= 0x2050000: i = ctypes.c_int(42) SetIntThroughRef(i, 13) self.assertEqual(i.value, 13)
def test1MinuitFit(self): """Test minuit callback and fit""" # setup minuit and callback gMinuit = TMinuit(5) gMinuit.SetPrintLevel(-1) # quiet gMinuit.SetGraphicsMode(ROOT.kFALSE) gMinuit.SetFCN(fcn) arglist = array('d', 10 * [0.]) ierflg = Long() arglist[0] = 1 gMinuit.mnexcm("SET ERR", arglist, 1, ierflg) # set starting values and step sizes for parameters vstart = array('d', [3, 1, 0.1, 0.01]) step = array('d', [0.1, 0.1, 0.01, 0.001]) gMinuit.mnparm(0, "a1", vstart[0], step[0], 0, 0, ierflg) gMinuit.mnparm(1, "a2", vstart[1], step[1], 0, 0, ierflg) gMinuit.mnparm(2, "a3", vstart[2], step[2], 0, 0, ierflg) gMinuit.mnparm(3, "a4", vstart[3], step[3], 0, 0, ierflg) # now ready for minimization step arglist[0] = 500 arglist[1] = 1. gMinuit.mnexcm("MIGRAD", arglist, 2, ierflg) # verify results amin, edm, errdef = Double(), Double(), Double() nvpar, nparx, icstat = Long(), Long(), Long() gMinuit.mnstat(amin, edm, errdef, nvpar, nparx, icstat) # gMinuit.mnprin( 3, amin ) self.assertEqual(nvpar, 4) self.assertEqual(nparx, 4) # success means that full covariance matrix is available (icstat==3) self.assertEqual(icstat, 3) # check results (somewhat debatable ... ) par, err = Double(), Double() gMinuit.GetParameter(0, par, err) self.assertEqual(round(par - 2.15, 2), 0.) self.assertEqual(round(err - 0.10, 2), 0.) gMinuit.GetParameter(1, par, err) self.assertEqual(round(par - 0.81, 2), 0.) self.assertEqual(round(err - 0.25, 2), 0.) gMinuit.GetParameter(2, par, err) self.assertEqual(round(par - 0.17, 2), 0.) self.assertEqual(round(err - 0.40, 2), 0.) gMinuit.GetParameter(3, par, err) self.assertEqual(round(par - 0.10, 2), 0.) self.assertEqual(round(err - 0.16, 2), 0.)
def __init__(self, myFCN, params, **kwargs): from ROOT import TMinuit, Long, Double self.limits = np.zeros((len(params), 2)) self.steps = .04 * np.ones( len(params)) # about 10 percent in log10 space self.tolerance = .001 self.maxcalls = 10000 self.printMode = 0 self.up = 0.5 self.param_names = ['p%i' % i for i in xrange(len(params))] self.erflag = Long() self.npars = len(params) self.args = () self.gradient = None self.force_gradient = 0 self.strategy = 1 self.fixed = np.zeros_like(params) self.__dict__.update(kwargs) self.params = np.asarray(params, dtype='float') self.fixed = np.asarray(self.fixed, dtype=bool) self.fcn = FCN(myFCN, self.params, args=self.args, gradient=self.gradient) self.fval = self.fcn.fval self.minuit = TMinuit(self.npars) self.minuit.SetPrintLevel(self.printMode) self.minuit.SetFCN(self.fcn) if self.gradient: self.minuit.mncomd('SET GRA %i' % (self.force_gradient), self.erflag) self.minuit.mncomd('SET STR %i' % self.strategy, Long()) for i in xrange(self.npars): if self.limits[i][0] is None: self.limits[i][0] = 0.0 if self.limits[i][1] is None: self.limits[i][1] = 0.0 self.minuit.DefineParameter(i, self.param_names[i], self.params[i], self.steps[i], self.limits[i][0], self.limits[i][1]) self.minuit.SetErrorDef(self.up) for index in np.where(self.fixed)[0]: self.minuit.FixParameter(int(index))
def _migrad(self, max_calls=6000): # need to set the FCN explicitly before every call self._get_gMinuit().SetFCN(self._minuit_fcn) error_code = Long(0) self._get_gMinuit().mnexcm("MIGRAD", arr('d', [max_calls, self.tolerance]), 2, error_code)
def runMinuit(numParameters): minuit = TMinuit(numParameters) minuit.SetPrintLevel(0) minuit.SetFCN(fcn) arglist = np.zeros(numParameters) + 0.01 internalFlag, arglist[0] = Long(0), 0.5 minuit.mnexcm("SET ERR", arglist, 1, internalFlag) initialValues = np.zeros(numParameters) + 0.01 steps = np.zeros(numParameters) + 0.0001 for i in xrange(numParameters): name = "epsilon%s" % i minuit.mnparm(i, name, initialValues[i], steps[i], 0, 1, internalFlag) # arglist[0] = 2 # minuit.mnexcm("SET STR", arglist, 1, internalFlag) arglist[0], arglist[1] = 10000, 0.1 minuit.mnexcm("SIMPLEX", arglist, 1, internalFlag) minuit.mnexcm("MIGRAD", arglist, 1, internalFlag) print "FIT STATUS is " +str(minuit.GetStatus()) return ratesAndErrors(numParameters, minuit)
def test2PassBuiltinsByNonConstRef(self): """Test parameter passing of builtins through non-const reference""" SetLongThroughRef = ROOT.SetLongThroughRef SetDoubleThroughRef = ROOT.SetDoubleThroughRef SetIntThroughRef = ROOT.SetIntThroughRef l = Long(pylong(42)) SetLongThroughRef(l, 41) self.assertEqual(l, 41) d = Double(3.14) SetDoubleThroughRef(d, 3.1415) self.assertEqual(d, 3.1415) i = Long(pylong(42)) SetIntThroughRef(i, 13) self.assertEqual(i, 13)
def get_fit_info(self, info): '''Retrieves other info from `Minuit`. **info** : string Information about the fit to retrieve. This can be any of the following: - ``'fcn'``: `FCN` value at minimum, - ``'edm'``: estimated distance to minimum - ``'err_def'``: `Minuit` error matrix status code - ``'status_code'``: `Minuit` general status code ''' # declare vars in which to retrieve other info fcn_at_min = Double(0) edm = Double(0) err_def = Double(0) n_var_param = Long(0) n_tot_param = Long(0) status_code = Long(0) # Tell TMinuit to update the variables declared above self.__gMinuit.mnstat(fcn_at_min, edm, err_def, n_var_param, n_tot_param, status_code) if info == 'fcn': return fcn_at_min elif info == 'edm': return edm elif info == 'err_def': return err_def elif info == 'status_code': try: return D_MATRIX_ERROR[status_code] except: return status_code
def set_err(self, up_value=1.0): '''Sets the ``UP`` value for Minuit. *up_value* : float (optional, default: 1.0) This is the value by which `FCN` is expected to change. ''' # Tell TMinuit to use an up-value of 1.0 error_code = Long(0) # execute SET ERR command self.__gMinuit.mnexcm("SET ERR", arr('d', [up_value]), 1, error_code)
def Get1DHisto(self, bat=False): nbins = self.histo3D.GetNbinsZ() nbins_merge = int(floor(nbins / 64)) print 'Merge {n} bins'.format(n=nbins_merge) self.histo3D.RebinZ(nbins_merge) if self.fidcut == 0: self.CreateFidCut() if bat: gROOT.SetBatch(True) if len(self.fidpoints) == 5: self.histo3D.GetXaxis().SetRangeUser(self.fidpoints[0]['x'], self.fidpoints[2]['x']) self.histo3D.GetYaxis().SetRangeUser(self.fidpoints[0]['y'], self.fidpoints[2]['y']) self.histo1D = self.histo3D.Project3D('z') else: self.histo1D = TH1F('hChargeVsFidCut_z', 'hChargeVsFidCut_z', 64, 0, 4096) nbins3D = (self.histo3D.GetNbinsY() * self.histo3D.GetNbinsX() * self.histo3D.GetNbinsZ() + 1) for bin in xrange(1, nbins3D): x, y, z = Long(0), Long(0), Long(0) if self.histo3D.GetBinContent(bin) >= 1: self.histo3D.GetBinXYZ(bin, x, y, z) point = { 'x': self.histo3D.GetXaxis().GetBinCenter(x), 'y': self.histo3D.GetYaxis().GetBinCenter(y) } # if self.WindingIsPointInPoly(point): if bool(int(self.fidcut.IsInside(point['x'], point['y']))): self.histo1D.Fill( self.histo3D.GetZaxis().GetBinCenter(z)) canvas_name = 'c_s_1D_{r}_{n}'.format(r=self.run, n=self.nameFid) canvas = self.CreateCanvas(canvas_name) gStyle.SetOptStat('nemr') canvas.cd() self.histo1D.SetLineWidth(3) self.histo1D.GetYaxis().SetTitle('entries') self.histo1D.Draw() name = 'histo1D_charge_sel_{r}_{n}'.format(r=self.run, n=self.nameFid) self.SaveCanvas(canvas, name) self.bla.append(canvas) if bat: gROOT.SetBatch(False)
def set_strategy(self, strategy_id=1): '''Sets the strategy Minuit. *strategy_id* : int (optional, default: 1 (optimized)) Tells ``TMinuit`` to use a certain strategy. Refer to ``TMinuit``'s documentation for available strategies. ''' error_code = Long(0) # execute SET STRATEGY command self.__gMinuit.mnexcm("SET STRATEGY", arr('d', [strategy_id]), 1, error_code)
def test1CheckEnumCalls(self): """Be able to pass enums as function arguments""" gROOT.LoadMacro("Till.C+") a = ROOT.Monkey() self.assertEqual(ROOT.fish, a.testEnum1(ROOT.fish)) self.assertEqual(ROOT.cow, a.testEnum2(ROOT.cow)) self.assertEqual(ROOT.bird, a.testEnum3(ROOT.bird)) self.assertEqual(ROOT.marsupilami, a.testEnum4(ROOT.marsupilami)) self.assertEqual(ROOT.marsupilami, a.testEnum4(Long(ROOT.marsupilami)))
def fix_parameter(self, parameter_number): ''' Fix parameter number <`parameter_number`>. **parameter_number** : int Number of the parameter to fix. ''' error_code = Long(0) logger.info("Fixing parameter %d in Minuit" % (parameter_number,)) # execute FIX command self.__gMinuit.mnexcm("FIX", arr('d', [parameter_number+1]), 1, error_code)
def unlimit(self, parameter_name): # set local flag _par_id = self.parameter_names.index(parameter_name) if self._par_limits[_par_id] is None: return # parameter is already unlimited self._par_limits[_par_id] = None if self.__gMinuit is not None: # also update Minuit instance error_code = Long(0) self.__gMinuit.mnexcm("SET LIM", arr('d', [_par_id+1]), 1, error_code) self._min_result_stale = True
def SimulateScan(self, c, pos, nbins=95): """Generate a toy BI scan. c: Index of the position parameter of the BI scan steps. pos: Lists of the scan steps of the beam. Returns: Histogram. """ p = array(pos) nevents = Long(0) result = RootToyGenerator.GenerateToys(self, len(pos), c, p, nbins, nevents) return result, float(nevents)
def release_parameter(self, parameter_number): ''' Release parameter number <`parameter_number`>. **parameter_number** : int Number of the parameter to release. ''' error_code = Long(0) logger.info("Releasing parameter %d in Minuit" % (parameter_number,)) # execute RELEASE command self.__gMinuit.mnexcm("RELEASE", arr('d', [parameter_number+1]), 1, error_code)
def Get2DMapFiducial(self): if self.fidcut == 0: self.CreateFidCut() self.histo3D.GetXaxis().SetRangeUser(self.sel_old['x_low'], self.sel_old['x_high']) self.histo3D.GetYaxis().SetRangeUser(self.sel_old['y_low'], self.sel_old['y_high']) if self.map == 0: self.map = self.histo3D.Project3DProfile('yx') self.map.GetZaxis().SetTitle('charge/ADC') self.map.GetZaxis().SetRangeUser(0, 3000) gStyle.SetOptStat('n') self.map_fid = self.map.Clone( '{n}_FidRegion'.format(n=self.map.GetName())) self.map_fid.SetTitle(self.map_fid.GetName()) nbinsMap = (self.map.GetNbinsY() * self.map.GetNbinsX() + 1) for bin in xrange(1, nbinsMap): x, y, z = Long(0), Long(0), Long(0) if self.map.GetBinContent(bin) >= 0: self.map.GetBinXYZ(bin, x, y, z) point = { 'x': self.map.GetXaxis().GetBinCenter(x), 'y': self.map.GetYaxis().GetBinCenter(y) } # if not self.WindingIsPointInPoly(point): if not bool(int(self.fidcut.IsInside(point['x'], point['y']))): self.map_fid.SetBinContent(bin, 0) canvas_name = 'c_s_2D_{r}_fid_{n}'.format(r=self.run, n=self.nameFid) canvas = self.CreateCanvas(canvas_name) gStyle.SetOptStat('n') canvas.cd() self.map_fid.GetXaxis().SetTitle('Silicon X/ch') self.map_fid.GetYaxis().SetTitle('Silicon Y/ch') self.map_fid.Draw('colz') self.fidcut.Draw('same') self.bla.append(canvas) name = 'histo2D_charge_sel_{r}_fid_{n}'.format(r=self.run, n=self.nameFid) self.SaveCanvas(canvas, name)
def fix(self, parameter_name): # set local flag _par_id = self.parameter_names.index(parameter_name) if self._par_fixed_mask[_par_id]: return # par is already fixed self._par_fixed_mask[_par_id] = True if self.__gMinuit is not None: # also update Minuit instance err_code = Long(0) self.__gMinuit.mnfixp(_par_id, err_code) # self.__gMinuit.mnexcm("FIX", # arr('d', [_par_id+1]), 1, error_code) self._min_result_stale = True
def minos_errors(self, log_print_level=1): ''' Get (asymmetric) parameter uncertainties from MINOS algorithm. This calls `Minuit`'s algorithms ``MINOS``, which determines parameter uncertainties using profiling of the chi2 function. returns : tuple A tuple of [err+, err-, parabolic error, global correlation] ''' # Set the FCN again. This HAS to be done EVERY # time the minimize method is called because of # the implementation of SetFCN, which is not # object-oriented but sets a global pointer!!! logger.debug("Updating current FCN") self.__gMinuit.SetFCN(self.FCN_wrapper) # save the old stdout stream if (log_print_level >= 0): old_out_stream = os.dup(sys.stdout.fileno()) os.dup2(self.out_file.fileno(), sys.stdout.fileno()) self.__gMinuit.SetPrintLevel(log_print_level) logger.debug("Running MINOS") error_code = Long(0) self.__gMinuit.mnexcm("MINOS", arr('d', [self.max_iterations]), 1, error_code) # return to normal print level self.__gMinuit.SetPrintLevel(self.print_level) # restore the previous output stream if (log_print_level >= 0): os.dup2(old_out_stream, sys.stdout.fileno()) output = [] errpos = Double(0) # positive parameter error errneg = Double(0) # negative parameter error err = Double(0) # parabolic error gcor = Double(0) # global correlation coefficient for i in xrange(0, self.number_of_parameters): self.__gMinuit.mnerrs(i, errpos, errneg, err, gcor) output.append( [float(errpos), float(errneg), float(err), float(gcor)]) return output
def Get1DHisto(self): if self.fidcut_1 == 0 or self.fidcut_2 == 0: self.fidcut_1, self.fidcut_2 = 0, 0 self.CreateFidCut() self.histo1D_1 = TH1F('hChargeTransp1OutOf10VsFidCut_z', 'hChargeTransp1OutOf10VsFidCut_z', 64, 0, 4096) nbins2D_1 = (self.histo2D_1.GetNbinsY() * self.histo2D_1.GetNbinsX() + 1) for bin in xrange(1, nbins2D_1): x, y, z = Long(0), Long(0), Long(0) self.histo2D_1.GetBinXYZ(bin, x, y, z) point = { 'x': self.histo2D_1.GetXaxis().GetBinCenter(x), 'y': self.histo2D_1.GetYaxis().GetBinCenter(y) } # if self.WindingIsPointInPoly(point): if bool(int(self.fidcut_1.IsInside(point['x'], point['y']))): self.histo1D_1.Fill(self.histo2D_1.GetBinContent(bin)) canvas_name_1 = 'c_t_1D_1_out_of_10_{r}_{n}'.format(r=self.run, n=self.nameFid) canvas_1 = self.CreateCanvas(canvas_name_1) gStyle.SetOptStat('nemr') canvas_1.cd() self.histo1D_1.SetLineWidth(3) self.histo1D_1.GetYaxis().SetTitle('entries') self.histo1D_1.Draw() name_1 = 'histo1D_charge_transp_1_out_of_10_{r}_{n}'.format( r=self.run, n=self.nameFid) self.SaveCanvas(canvas_1, name_1) self.bla.append(canvas_1) self.histo1D_2 = TH1F('hChargeTransp2OutOf10VsFidCut_z', 'hChargeTransp2OutOf10VsFidCut_z', 64, 0, 4096) nbins2D_2 = (self.histo2D_2.GetNbinsY() * self.histo2D_2.GetNbinsX() + 1) for bin in xrange(1, nbins2D_2): x, y, z = Long(0), Long(0), Long(0) self.histo2D_2.GetBinXYZ(bin, x, y, z) point = { 'x': self.histo2D_2.GetXaxis().GetBinCenter(x), 'y': self.histo2D_2.GetYaxis().GetBinCenter(y) } # if self.WindingIsPointInPoly(point): if bool(int(self.fidcut_2.IsInside(point['x'], point['y']))): self.histo1D_2.Fill(self.histo2D_2.GetBinContent(bin)) canvas_name_2 = 'c_t_1D_2_out_of_10_{r}_{n}'.format(r=self.run, n=self.nameFid) canvas_2 = self.CreateCanvas(canvas_name_2) gStyle.SetOptStat('nemr') canvas_2.cd() self.histo1D_2.SetLineWidth(3) self.histo1D_2.GetYaxis().SetTitle('entries') self.histo1D_2.Draw() name_2 = 'histo1D_charge_transp_2_out_of_10_{r}_{n}'.format( r=self.run, n=self.nameFid) self.SaveCanvas(canvas_2, name_2) self.bla.append(canvas_2)
def decode_larcv2_evimage2d(io, producername, imgdata_np, imgmeta_np): # make evcontainer evout = io.get_data("image2d", producername) # make meta nimgs = imgdata_np.shape[1] for i in xrange(nimgs): nrows = Long(imgmeta_np[0, i, 0, 1]) ncols = Long(imgmeta_np[0, i, 0, 0]) planeid = Long(imgmeta_np[0, i, 0, 6]) lcvmeta = larcv.ImageMeta(imgmeta_np[0, i, 0, 2], imgmeta_np[0, i, 0, 3], imgmeta_np[0, i, 0, 4], imgmeta_np[0, i, 0, 5], nrows, ncols, planeid) # convert image outarr = np.flip(imgdata_np[0, i, :, :].transpose((1, 0)), 0) lcvimg = larcv.as_image2d_meta(outarr, lcvmeta) evout.append(lcvimg) return
def limit(self, parameter_name, parameter_bounds): assert len(parameter_bounds) == 2 # set local flag _par_id = self.parameter_names.index(parameter_name) if self._par_limits[_par_id] == parameter_bounds: return # same limits already set self._par_limits[_par_id] = parameter_bounds if self.__gMinuit is not None: _lo_lim, _up_lim = self._par_limits[_par_id] # also update Minuit instance error_code = Long(0) self.__gMinuit.mnexcm("SET LIM", arr('d', [_par_id+1, _lo_lim, _up_lim]), 3, error_code) self._min_result_stale = True
def _calculate_asymmetric_parameter_errors(self): self._get_gMinuit().mnmnos() _asymm_par_errs = np.zeros(shape=(self.num_pars, 2)) for _n in range(self.num_pars): _number = Long(_n) _eplus = ctypes.c_double(0) _eminus = ctypes.c_double(0) _eparab = ctypes.c_double(0) _gcc = ctypes.c_double(0) self._get_gMinuit().mnerrs(_number, _eplus, _eminus, _eparab, _gcc) _asymm_par_errs[_n, 0] = _eminus.value _asymm_par_errs[_n, 1] = _eplus.value self.minimize() return _asymm_par_errs
def minimize(self, final_fit=True, log_print_level=2): '''Do the minimization. This calls `Minuit`'s algorithms ``MIGRAD`` for minimization and, if `final_fit` is `True`, also ``HESSE`` for computing/checking the parameter error matrix.''' # Set the FCN again. This HAS to be done EVERY # time the minimize method is called because of # the implementation of SetFCN, which is not # object-oriented but sets a global pointer!!! logger.debug("Updating current FCN") self.__gMinuit.SetFCN(self.FCN_wrapper) # Run minimization algorithm (MIGRAD + HESSE) error_code = Long(0) prefix = "Minuit run on" # set the timestamp prefix # insert timestamp self.out_file.write('\n') self.out_file.write('#' * (len(prefix) + 4 + 20)) self.out_file.write('\n') self.out_file.write("# %s " % (prefix, ) + strftime("%Y-%m-%d %H:%M:%S #\n", gmtime())) self.out_file.write('#' * (len(prefix) + 4 + 20)) self.out_file.write('\n\n') self.out_file.flush() # save the old stdout stream if (log_print_level >= 0): old_out_stream = os.dup(sys.stdout.fileno()) os.dup2(self.out_file.fileno(), sys.stdout.fileno()) self.__gMinuit.SetPrintLevel(log_print_level) # set Minuit print level logger.debug("Running MIGRAD") self.__gMinuit.mnexcm("MIGRAD", arr('d', [self.max_iterations, self.tolerance]), 2, error_code) if (final_fit): logger.debug("Running HESSE") self.__gMinuit.mnexcm("HESSE", arr('d', [self.max_iterations]), 1, error_code) # return to normal print level self.__gMinuit.SetPrintLevel(self.print_level) # restore the previous output stream if (log_print_level >= 0): os.dup2(old_out_stream, sys.stdout.fileno()) os.close(old_out_stream)
def get_chi2_probability(self, n_deg_of_freedom): ''' Returns the probability that an observed :math:`\chi^2` exceeds the calculated value of :math:`\chi^2` for this fit by chance, even for a correct model. In other words, returns the probability that a worse fit of the model to the data exists. If this is a small value (typically <5%), this means the fit is pretty bad. For values below this threshold, the model very probably does not fit the data. n_def_of_freedom : int The number of degrees of freedom. This is typically :math:`n_\text{datapoints} - n_\text{parameters}`. ''' chi2 = Double(self.get_fit_info('fcn')) ndf = Long(n_deg_of_freedom) return TMath.Prob(chi2, ndf)
def update_parameter_data(self, show_warnings=False): """ (Re-)Sets the parameter names, values and step size on the C++ side of Minuit. """ error_code = Long(0) try: # Set up the starting fit parameters in TMinuit for i in xrange(0, self.number_of_parameters): self.__gMinuit.mnparm(i, self.parameter_names[i], self.current_parameters[i], 0.1 * self.parameter_errors[i], 0, 0, error_code) # use 10% of the par. 1-sigma errors as the initial step size except AttributeError, e: if show_warnings: logger.warn("Cannot update Minuit data on the C++ side. " "AttributeError: %s" % (e, ))
X_predictions_for_fit = np.column_stack([x for x in X_predicted_all]) mpvs=[] print 'here' fit_quantile=[] gMinuit = TMinuit(4) gMinuit.SetPrintLevel(-1) gMinuit.SetFCN( fcn ) arglist = np.array( 10*[0.] ) ierflg = 0 arglist[0] = 1 gMinuit.mnexcm( "SET ERR", arglist, 1, Long(ierflg) ) arglist[0] = 0 gMinuit.mnexcm("SET PRINT", arglist ,0,Long(ierflg)); vstart = np.array( [ -2 , 4,-1, 0.5] ) step = np.array( [ 0.001, 0.001, 0.01, 0.01 ] ) gMinuit.mnparm( 0, "a1", vstart[0], step[0], 0, 0, Long(ierflg) ) gMinuit.mnparm( 1, "a2", vstart[1], step[1], 0, 0, Long(ierflg) ) gMinuit.mnparm( 2, "a3", vstart[2], step[2], 0, 0, Long(ierflg) ) gMinuit.mnparm( 3, "a4", vstart[3], step[3], 0, 0, Long(ierflg) ) arglist[0] = 500 arglist[1] = 1. fParamVal = Double(0.) fParamErr = Double(0.) for i in range(5): changeme(X_predictions_for_fit[i]) gMinuit.mnexcm( "MIGRAD", arglist, 2, Long(ierflg) )
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 main(): #The first part of the script is to input the root files# canvas = TCanvas("Canvas_d", "Canvas_d", 533, 76, 1383, 852) input_datafile = TFile(args["input_data"]) EV_data = input_datafile.Get("EventCategorizer subtask 0 stats/ExpecValue") entries_data = EV_data.GetSize() print "# of Entries in Data file:", entries_data print "Experimental Data Inputed" data_arr = [] canvas = TCanvas("Canvas_mc", "Canvas_mc", 533, 76, 1383, 852) input_mcfile = TFile(args["input_mc"]) EV_mc = input_mcfile.Get( "EventCategorizer subtask 0 stats/ExpecValue_Smeared") entries_mc = EV_mc.GetSize() print "# of Entries in MC file:", entries_mc print "MC Data Inputed" mc_arr = [] bin_arr = [] for x in range(entries_data): Data_i = EV_data.GetBinContent(x) MC_i = EV_mc.GetBinContent(x) data_arr.append(Data_i) mc_arr.append(MC_i) Bin_i = EV_data.GetBinCenter(x) bin_arr.append(Bin_i) #print Data_i #print MC_i #print data_arr #print mc_arr #print bin_arr # --> Set parameters and function to f i t name = ["c", "d"] #variable names vstart = arr('d', (1.0, 1.0)) #the initial values step = arr('d', (0.001, 0.001)) #the initial step size npar = len(name) # --> Defining the Chi-Square function to be minimized# def Chi_Induced(Data, MC, BinCenter, C, D): chi = 0. for i in range(0, entries_data): #num1 = Data[i] #num2 = D*((1-(C*BinCenter[i]))*MC[i]) #num = (num1 - num2)**2 #num = 0. #den1 = ((Data[i])**(1/2))**2 #den2 = (D*((1-(C*BinCenter[i])))*((MC[i])**(1/2)))**2 num = 2 den = 2 #den = den1 + den2 chi = chi + num / den return chi # --> set up MINUIT myMinuit = TMinuit( npar) # initialize TMinuit with maximum of npar parameters myMinuit.SetFCN(Chi_Induced) # set function to minimize ierflg = Long(0) arglist = arr('d', 2 * [0.01]) # set error definition arglist[0] = 6000 # Number of calls for FCN before gving up arglist[1] = 0.3 # Toleranceierflg = Long(0) myMinuit.mnexcm("SET ERR", arglist, 1, ierflg) for i in range(0, npar): myMinuit.mnparm(i, name[i], vstart[i], step[i], 0, 0, ierflg) myMinuit.mnexcm("MIGRAD", arglist, 1, ierflg) # execute the minimisation # --> check TMinuit status amin, edm, errdef = Double(0.), Double(0.), Double(0.) nvpar, nparx, icstat = Long(0), Long(0), Long(0) myMinuit.mnstat(amin, edm, errdef, nvpar, nparx, icstat)