def test_html_params_with_limits(): m = Minuit(f1, x=3, y=5) m.fixed["x"] = True m.errors = (0.2, 0.1) m.limits = ((0, None), (0, 10)) # fmt: off assert m.init_params._repr_html_() == r"""<table>
def test_params(): m = Minuit(func0, x=1, y=2) m.errordef = Minuit.LEAST_SQUARES m.errors = (3, 4) m.fixed["x"] = True m.limits["y"] = (None, 10) # these are the initial param states expected = ( Param(0, "x", 1.0, 3.0, None, False, True, False, False, False, None, None), Param(1, "y", 2.0, 4.0, None, False, False, True, False, True, None, 10), ) assert m.params == expected m.migrad() m.minos() assert m.init_params == expected expected = [ Namespace(number=0, name="x", value=1.0, error=3.0, merror=(-3.0, 3.0)), Namespace(number=1, name="y", value=5.0, error=1.0, merror=(-1.0, 1.0)), ] params = m.params for i, exp in enumerate(expected): p = params[i] assert p.number == exp.number assert p.name == exp.name assert p.value == approx(exp.value, rel=1e-2) assert p.error == approx(exp.error, rel=1e-2) assert p.error == approx(exp.error, rel=1e-2)
def MinForReplica(): global totalN,setDY,initialValues,initialErrors,searchLimits,parametersToMinimize def repchi_2(x): global totalN startT=time.time() harpy.setNPparameters(x) print('np set =',["{:8.3f}".format(i) for i in x], end =" ") ccDY2,cc2=DataProcessor.harpyInterface.ComputeChi2(repDataDY) if(usePenaltyTerm): ccDY2+=totalN*PenaltyTerm(x) cc=(ccDY2)/totalN endT=time.time() print(':->',cc,' t=',endT-startT) return ccDY2 repDataDY=setDY.GenerateReplica() localM = Minuit(repchi_2, initialValues) localM.errors=initialErrors localM.limits=searchLimits localM.fixed=parametersToMinimize localM.errordef=1 localM.tol=0.0001*totalN*10000 ### the last 0.0001 is to compensate MINUIT def localM.strategy=1 localM.migrad() ### [chi^2, NP-parameters] return [localM.fval,list(localM.values)]
def test_text_params_with_limits(): m = Minuit( f1, x=3, y=5, ) m.fixed["x"] = True m.errors = (0.2, 0.1) m.limits = ((0, None), (0, 10)) assert _repr_text.params(m.params) == ref("params_with_limits")
def test_array_func_1(): m = Minuit(func_np, (2, 1)) m.errors = (1, 1) assert m.parameters == ("x0", "x1") assert m.values == (2, 1) assert m.errors == (1, 1) m.migrad() assert_allclose(m.values, (1, 1), rtol=1e-2) c = m.covariance assert_allclose(np.diag(c), (1, 1), rtol=1e-2)
def minimize( self, initial_param_values: np.ndarray, verbose: bool = False, error_def: float = 0.5, additional_args: Optional[Tuple[Any, ...]] = None, get_hesse: bool = True, check_success: bool = True, ) -> MinimizeResult: m = Minuit( self._fcn, initial_param_values, name=self.params.names, ) m.errors = 0.05 * initial_param_values m.errordef = error_def m.limits = self._param_bounds for i in range(len(m.params)): m.fixed[i] = self._get_fixed_params()[i] m.print_level = 1 if verbose else 0 # perform minimization twice! fmin = m.migrad(ncall=100000, iterate=2).fmin self._fcn_min_val = m.fval self._params.values = np.array(m.values) self._params.errors = np.array(m.errors) fixed_params = tuple( ~np.array(self._get_fixed_params())) # type: Tuple[bool, ...] self._params.covariance = np.array( m.covariance)[fixed_params, :][:, fixed_params] self._params.correlation = np.array( m.covariance.correlation())[fixed_params, :][:, fixed_params] self._success = fmin.is_valid and fmin.has_valid_parameters and fmin.has_covariance if check_success and not self._success: raise RuntimeError(f"Minimization was not successful.\n" f"{fmin}\n") assert self._success is not None return MinimizeResult(fcn_min_val=m.fval, params=self._params, success=self._success)
def test_array_func_2(): m = Minuit(func_np, (2, 1), grad=func_np_grad, name=("a", "b")) m.fixed = (False, True) m.errors = (0.5, 0.5) m.limits = ((0, 2), (-np.inf, np.inf)) assert m.values == (2, 1) assert m.errors == (0.5, 0.5) assert m.fixed == (False, True) assert m.limits["a"] == (0, 2) m.migrad() assert_allclose(m.values, (1, 1), rtol=1e-2) c = m.covariance assert_allclose(c, ((1, 0), (0, 0)), rtol=1e-2) m.minos() assert len(m.merrors) == 1 assert m.merrors[0].lower == approx(-1, abs=1e-2) assert m.merrors[0].name == "a"
def test_use_array_call(): inf = float("infinity") m = Minuit( func_np, (1, 1), name=("a", "b"), ) m.fixed = False m.errors = 1 m.limits = (0, inf) m.migrad() assert m.parameters == ("a", "b") assert_allclose(m.values, (1, 1)) m.hesse() c = m.covariance assert_allclose((c[("a", "a")], c[("b", "b")]), (1, 1)) with pytest.raises(RuntimeError): Minuit(lambda *args: 0, [1, 2], name=["a", "b", "c"])
def func_test_helper(f, grad=None, errordef=None): m = Minuit(f, x=0, y=0, grad=grad) if errordef: m.errordef = errordef m.migrad() val = m.values assert_allclose(val["x"], 2.0, rtol=2e-3) assert_allclose(val["y"], 5.0, rtol=2e-3) assert_allclose(m.fval, 11.0 * m.errordef, rtol=1e-3) assert m.valid assert m.accurate m.hesse() err = m.errors assert_allclose(err["x"], 2.0, rtol=1e-3) assert_allclose(err["y"], 1.0, rtol=1e-3) m.errors = (1, 2) assert_allclose(err["x"], 1.0, rtol=1e-3) assert_allclose(err["y"], 2.0, rtol=1e-3) return m
def get_minuit(self, event, guess): def fcn(x, y, angle, length, t0): pars = {'x': x, 'y': y, 'angle': angle, 'length': length, 't0': t0} neg_log = -1. * self.ln_likelihood(event, pars) #print(pars,neg_log) return neg_log fcn.errordef = Minuit.LIKELIHOOD #print(guess) m = Minuit(fcn, x=guess['x'], y=guess['y'], angle=guess['angle'], length=guess['length'], t0=guess['t0']) m.limits = [(-5000., 0.), (0., 5000.), (None, None), (0.1, 3000.), (-100., 100.)] m.errors = (10., 10., 0.01, 10., 0.5) return m
initialErrors = (0.1, 10., 10., 0.1, 0.1, 0.3, 0.5, 1., 1., 1., 1., 1., 1., 0.1) # searchLimits=((0.0001,2.),(0.01,80), (0.0,400), None,None, # (-2.,2.),(-0.99,2.5), (-10.,10.), # (-20.,20.),(-0.99,6.), (-15.,15.), # (-5.,5.),(-0.99,8), None) searchLimits = ((0, None), (0, None), (0, None), None, None, (-5., 5.), (-0.99, 30), (-30., 30.), (-5., 5.), (-0.99, 60.), (-30., 30.), (-5., 15.), (-0.99, 30.), (-5, 5)) parametersToMinimize = (False, False, False, True, True, False, False, False, False, False, False, False, False, False) m = Minuit(chi_2, initialValues) m.errors = initialErrors m.limits = searchLimits m.fixed = parametersToMinimize m.errordef = 1 print(m.params) m.tol = 0.0001 * totalN * 10000 ### the last 0.0001 is to compensate MINUIT def m.strategy = 1 #%% # m.tol=0.0001*totalN*10000 ### the last 0.0001 is to compensate MINUIT def # m.strategy=1 m.migrad() #ncall=150)
# Initialize the fit; parameter starting values and limits if iminuit_version_f < 2.0: m = Minuit(getL, CV=1, limit_CV=(0, 3), CF=1, limit_CF=(0, 3), print_level=0, errordef=1, error_CV=0.2, error_CF=0.2) else: m = Minuit(getL, CV=1, CF=1) m.limits = [(0, 3), (0, 3)] m.errordef = 1 # 1 for -2LogL (or least square), 0.5 for -LogL m.errors = [0.2, 0.2] m.print_level = 0 # Minimization and error estimation m.migrad() m.hesse() # run covariance estimator m.minos() print("\nbest-fit point:", m.values) print("\nHesse errors:", m.errors) print("\nMinos errors:") for key, value in list(m.merrors.items()): print(key, value) if iminuit_version_f < 2.0: print("\nCorrelation matrix:\n", m.matrix(correlation=True))
# Initialize the fit; parameter starting values and limits if iminuit_version_f < 2.0: m = Minuit(getL_CGaCg, CGa=0.9, limit_CGa=(0, 3), Cg=0.9, limit_Cg=(0, 3), print_level=0, errordef=1, error_CGa=1, error_Cg=1) else: m = Minuit(getL_CGaCg, CGa=0.9, Cg=0.9) m.limits = [(0, 3), (0, 3)] m.errordef = 1 # 1 for -2LogL (or least square), 0.5 for -LogL m.errors = [1, 1] m.print_level = 0 # Fit the model m.migrad() # Display parameter values at the best-fit point print("Best-fit point: ") print("Cgamma =", m.values["CGa"]) print("Cgluon =", m.values["Cg"]) bestfit_CGa_Cg_minus2logL = m.fval print("-2LogL =", bestfit_CGa_Cg_minus2logL) print("\n***** model comparison *****")
def laplace_approximate(self, num_global_samples=400, verbose=True): """ Find maximum and derive a Laplace approximation there. Parameters ---------- num_global_samples: int Number of samples to draw from the prior to find a good starting point (see `init_globally`). verbose: bool If true, print out maximum likelihood value and point """ if not hasattr(self, 'optu'): self.init_globally(num_global_samples=num_global_samples) # starting point is: startu = np.copy(self.optu) ndim = len(startu) # this part is not parallelised. if self.mpi_rank == 0: # choose a jump distance that does not go over the space border # because Minuit does not support that. deltau = 0.9999 * np.min( [np.abs(startu - 1), np.abs(startu)], axis=0) deltau[deltau > 0.04] = 0.04 assert deltau.shape == startu.shape def negloglike(u): """ negative log-likelihood to minimize """ p = self.transform(u) return -self.loglike(p) if self.log: self.logger.debug(" starting optimization...") self.logger.info(" from: %s" % startu) self.logger.info(" error: %s" % deltau) if hasattr(Minuit, 'from_array_func'): m = Minuit.from_array_func(negloglike, startu, errordef=0.5, error=deltau, limit=[(0, 1)] * ndim) else: m = Minuit(negloglike, startu) m.errordef = Minuit.LIKELIHOOD m.errors = deltau m.limits = np.array([(0, 1)] * ndim) m.migrad() if hasattr(m, 'fval'): optL = -m.fval else: optL = -m.get_fmin().val if verbose: print("Maximum likelihood: L = %.1f at:" % optL) optu = [ max(1e-10, min(1 - 1e-10, m.values[i])) for i in range(ndim) ] optp = self.transform(np.asarray(optu)) umax = [ max(1e-6, min(1 - 1e-6, m.values[i] + m.errors[i])) for i in range(ndim) ] umin = [ max(1e-6, min(1 - 1e-6, m.values[i] - m.errors[i])) for i in range(ndim) ] pmax = self.transform(np.asarray(umax)) pmin = self.transform(np.asarray(umin)) perr = (pmax - pmin) / 2 for name, med, sigma in zip(self.paramnames, optp, perr): if sigma > 0: i = max(0, int(-np.floor(np.log10(sigma))) + 1) else: i = 3 fmt = '%%.%df' % i fmts = '\t'.join([' %-20s' + fmt + " +- " + fmt]) if verbose: print(fmts % (name, med, sigma)) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") try: m.hesse() hesse_failed = getattr(m, 'hesse_failed', False) except: hesse_failed = True if not hesse_failed: hesse_failed = any((issubclass(warning.category, HesseFailedWarning) for warning in w)) if not hesse_failed: hesse_failed = not getattr(m, 'has_covariance', True) # check if full rank matrix: if not hesse_failed: if hasattr(m, 'np_matrix'): cov = m.np_matrix() else: cov = np.asarray(m.covariance) if cov.shape != (ndim, ndim): self.logger.debug(" hesse failed, not full rank") del cov hesse_failed = True else: self.logger.debug(" hesse failed") if not hesse_failed: self.logger.info(" using correlated errors ...") invcov = np.linalg.inv(cov) if hesse_failed: self.logger.info(" using uncorrelated errors ...") cov = np.diag(np.clip(perr, a_min=1e-10, a_max=1)**2) invcov = np.linalg.inv(cov) assert cov.shape == (ndim, ndim), (cov.shape, ndim) assert invcov.shape == (ndim, ndim), (invcov.shape, ndim) if hasattr(m, 'nfcn'): self.ncall += m.nfcn elif hasattr(m, 'ncalls_total'): self.ncall += m.ncalls_total else: self.ncall += m.ncalls else: cov = np.empty((ndim, ndim)) invcov = np.empty((ndim, ndim)) optu = np.empty(ndim) optp = np.empty(ndim) optL = np.empty(1) if self.use_mpi: # inform other processes about the results. cov = self.comm.bcast(cov) invcov = self.comm.bcast(invcov) optu = self.comm.bcast(optu) optp = self.comm.bcast(optp) optL = self.comm.bcast(optL) self.ncall += self.comm.bcast(self.ncall) self.invcov, self.cov = invcov, cov self.optu, self.optp, self.optL = optu, optp, optL
def run_minuit(nll, pars, use_gradient=True, use_hesse=False, use_minos=False, get_covariance=False): """ Run IMinuit to minimise NLL function nll : python callable representing the negative log likelihood to be minimised pars : list of FitParameters use_gradient : if True, use analytic gradient use_hesse : if True, uses HESSE for error estimation use_minos : if True, use MINOS for asymmetric error estimation get_covariance: if True, get the covariance matrix from the fit returns the dictionary with the values and errors of the fit parameters """ float_pars = [p for p in pars if p.floating()] fixed_pars = [p for p in pars if not p.floating()] def func(par): for i, p in enumerate(float_pars): p.update(par[i]) kwargs = {p.name: p() for p in float_pars + fixed_pars} func.n += 1 nll_val = nll(kwargs).numpy() if func.n % 10 == 0: print(func.n, nll_val, par) return nll_val def gradient(par): for i, p in enumerate(float_pars): p.update(par[i]) kwargs = {p.name: p() for p in float_pars + fixed_pars} float_vars = [i() for i in float_pars] gradient.n += 1 with tf.GradientTape() as gt: gt.watch(float_vars) nll_val = nll(kwargs) g = gt.gradient(nll_val, float_vars, unconnected_gradients=tf.UnconnectedGradients.ZERO) g_val = [i.numpy() for i in g] return g_val func.n = 0 gradient.n = 0 start = [p.init_value for p in float_pars] error = [p.step_size for p in float_pars] limit = [(p.lower_limit, p.upper_limit) for p in float_pars] name = [p.name for p in float_pars] if use_gradient: minuit = Minuit(func, start, grad=gradient, name=name) else: minuit = Minuit(func, start, name=name) minuit.errordef = Minuit.LIKELIHOOD minuit.errors = error minuit.limits = limit initlh = func(start) starttime = timer() minuit.migrad() if use_hesse: minuit.hesse() if use_minos: minuit.minos() endtime = timer() par_states = minuit.params f_min = minuit.fmin #print the nice tables of fit results print(f_min) print(par_states) print(minuit.covariance.correlation()) results = {"params": {}} # Get fit results and update parameters for n, p in enumerate(float_pars): p.update(par_states[n].value) p.fitted_value = par_states[n].value p.error = par_states[n].error results["params"][p.name] = (p.fitted_value, p.error) for p in fixed_pars: results["params"][p.name] = (p.numpy(), 0.0) # return fit results results["initlh"] = initlh results["loglh"] = f_min.fval results["iterations"] = f_min.nfcn results["func_calls"] = func.n results["grad_calls"] = gradient.n results["time"] = endtime - starttime #results["covariance"] = [(k, v) for k, v in minuit.covariance.items()] #is_valid == (has_valid_parameters & !has_reached_call_limit & !is_above_max_edm) results["is_valid"] = int(f_min.is_valid) results["has_parameters_at_limit"] = int(f_min.has_parameters_at_limit) results["has_accurate_covar"] = int(f_min.has_accurate_covar) results["has_posdef_covar"] = int(f_min.has_posdef_covar) results["has_made_posdef_covar"] = int(f_min.has_made_posdef_covar) results["has_reached_call_limit"] = int(f_min.has_reached_call_limit) #store covariance matrix of parameters if get_covariance: covarmatrix = {} for p1 in float_pars: covarmatrix[p1.name] = {} for p2 in float_pars: covarmatrix[p1.name][p2.name] = minuit.covariance[p1.name, p2.name] results["covmatrix"] = covarmatrix return results
def _fitdidv(freq, didv, poles, priors, invpriorscov, p0, yerr=None): """ Function to directly fit the small signal TES parameters with the knowledge of prior known values any number of the parameters. In order for the degeneracy of the parameters to be broken, at least 2 fit parameters should have priors knowledge. This is usually rsh, rp, and r0, as these can be known from IV data. """ def _residual(params): """ Define a residual for the nonlinear least squares algorithm for the priors fit. """ if poles == 1: rsh, rp, L, dt = params ci = DIDVPriors._onepolescaledadmittance( freq, rsh, rp, L, ) * np.exp(-2.0j * pi * freq * dt) elif poles == 2: rsh, rp, r0, beta, l, L, tau0, dt = params ci = DIDVPriors._twopolescaledadmittance( freq, rsh, rp, r0, beta, l, L, tau0, ) * np.exp(-2.0j * pi * freq * dt) elif poles == 3: rsh, rp, r0, beta, l, L, tau0, gratio, tau3, dt = params ci = DIDVPriors._threepolescaledadmittance( freq, rsh, rp, r0, beta, l, L, tau0, gratio, tau3, ) * np.exp(-2.0j * pi * freq * dt) # the difference between the data and the fit diff = didv - ci # get the weights from yerr, these should be # 1/(standard deviation) for real and imaginary parts if (yerr is None): weights = 1.0 + 1.0j else: weights = 1.0 / yerr.real + 1.0j / yerr.imag # create the residual vector, splitting up real and # imaginary parts of the residual separately z1d = np.zeros(freq.size * 2, dtype=np.float64) z1d[0:z1d.size:2] = diff.real * weights.real z1d[1:z1d.size:2] = diff.imag * weights.imag return z1d def _residualpriors(params): """Helper function to incude the priors in the residual.""" z1dpriors = np.sqrt( (priors - params).dot(invpriorscov).dot(priors - params)) return z1dpriors def _neg_log_likelihood(params): """Negative log likelihood with priors included.""" return np.sum( (_residual(params))**2 / 2) + _residualpriors(params)**2 / 2 m = Minuit( _neg_log_likelihood, p0, ) m.limits = (len(p0) - 1) * ((0, None), ) + ((None, None), ) m.errors = np.abs(p0) m.errordef = 0.5 m.migrad() popt = np.asarray(m.values) pcov = np.asarray(m.covariance) cost = m.fval return popt, pcov, cost
def fit_data_minuit(self, spectrum_only=False, minimizer_args={}): from iminuit import Minuit def chi2(deltaE, xmax_shift, *norms): norms = np.array(norms) # norms = np.array(norms) if spectrum_only == True: result = self.get_chi2_spectrum(norms=norms, deltaE=deltaE) elif spectrum_only == 'xmax': result = self.get_chi2_spectrum( norms=norms, deltaE=deltaE) + self.get_chi2_Xmax( norms=norms, deltaE=deltaE, xmax_shift=xmax_shift) else: result = self.get_chi2_total(norms=norms, deltaE=deltaE, xmax_shift=xmax_shift) return result init_norm = self.spectrum['spectrum'][14] / self.res_spectrum[ 14] / len(self.ncoids) # trick if spectrum is zero, will iMinuit will give nan anyway init_norm = init_norm if np.isfinite(init_norm) else 1. m_best = None if 'fix_deltaE' in minimizer_args and not minimizer_args['fix_deltaE']: delta_tries = [-0.13, -0.8, 0., 0.8, 0.13] #delta_tries = [-0.12, 0., 0.12] fix_deltaE = False else: delta_tries = [0.] fix_deltaE = True if 'fix_xmax_shift' in minimizer_args and not minimizer_args[ 'fix_xmax_shift']: pass shift_tries = [-0.9, -0.5, 0., 0.5, 0.9] #shift_tries = [-0.9, 0., 0.9] fix_xmax_shift = False else: shift_tries = [0.] fix_xmax_shift = True for delta_start in delta_tries: for shift_start in shift_tries: arg_names = ['deltaE'] + ['xmax_shift'] + [ 'norm{:}'.format(pid) for pid in self.ncoids ] start = [delta_start] + [shift_start ] + [init_norm] * len(self.ncoids) error = [0.1] + [0.2] + [init_norm / 100] * len(self.ncoids) limit = [(-0.14, 0.14)] + [ (-1., 1.) ] + [(init_norm / 1e6, init_norm * 1e6)] * len(self.ncoids) fixed = [fix_deltaE] + [fix_xmax_shift ] + [False] * len(self.ncoids) params = {name: val for name, val in zip(arg_names, start)} m = Minuit(chi2, name=arg_names, **params) m.errordef = Minuit.LEAST_SQUARES m.limits = limit m.errors = error m.fixed = fixed # m.print_param() m.migrad(ncall=100000) if m_best == None: m_best = m if m.fval < m_best.fval: m_best = m return m_best
m = Minuit(getL, CGa=1, limit_CGa=(0, 3), Cg=1, limit_Cg=(0, 3), BRinv=0.2, limit_BRinv=(0, 0.9), errordef=1, error_CGa=0.1, error_Cg=0.1, error_BRinv=0.1) else: m = Minuit(getL, CGa=1, Cg=1, BRinv=0.2) m.limits = [(0, 3), (0, 3), (0, 0.9)] m.errordef = 1 # 1 for -2LogL (or least square), 0.5 for -LogL m.errors = [0.1, 0.1, 0.1] print("\n***** performing model fit with iminuit *****") # Minimization and error estimation m.migrad() m.minos() print("\n***** fit summary *****") print("\nbest-fit point:", m.values) print("\nHesse errors:", m.errors) print("\nMinos errors:") for key, value in list(m.merrors.items()): print(key, value)
def promptfit(self,mplot, mprint = False): ''' launches t0 prompts fit:: fits peak positions prints migrad results plots prompts and their fit (if plot checked, mprint not implemented) stores bins for background and t0 refactored for run addition and suite of runs WARNING: this module is for PSI only ''' from numpy import array, where, arange, zeros, mean, ones, sqrt, linspace from iminuit import Minuit, cost import matplotlib.pyplot as P from mujpy.mucomponents.muprompt import muprompt from mujpy.mucomponents.muedge import muedge from mujpy.aux.aux import TauMu_mus, scanms, step, set_fig if mplot: # setup figure window font = {'family' : 'Ubuntu','size' : 8} P.rc('font', **font) dpi = 100. # conventional screen dpi num = 0 # unique window number if self.datafile[-3:] == 'bin': nrow, ncol = 2,3 kwargs = {'figsize':(7.5,5),'dpi':dpi} title = 'Prompts t0 fit' prompt_fit_text = [None]*self._the_runs_[0][0].get_numberHisto_int() elif self.datafile[-3:] =='mdu': # PSI HIFI nrow, ncol = 3,3 ################### # set figure, axes (8 real counters, python number 1 2 3 4 5 6 7 8 ################### # fig_counters,ax_counters = P.subplots(3,3,figsize=(9.5,9.5),dpi=dpi) kwargs = {'figsize':(9.5,9.5),'dpi':dpi} title = 'HIFI start histo guess' elif self.filespecs[1].value=='nxs': # ISIS nrow, ncol = 3,3 ################### # set figure, axes ################### kwargs = {'figsize':(5,4),'dpi':dpi} title = 'Edge t0 fit' fig_counters,ax_counters = set_fig(num,nrow,ncol,title,**kwargs) fig_counters.canvas.set_window_title(title) if self.datafile[-3:] == 'bin': # PSI gps, flame, dolly, gpd second_plateau = 100 peakheight = 100000. peakwidth = 1. ################################################### # fit a peak with different left and right plateaus ################################################### ############################# # guess prompt peak positions ############################# npeaks = [] for counter in range(self._the_runs_[0][0].get_numberHisto_int()): histo = zeros(self._the_runs_[0][0].get_histoLength_bin()) for k in range(len(self._the_runs_[0])): # may add runs histo += array(self._the_runs_[0][k].get_histo_vector(counter,1)) binpeak = where(histo==histo.max())[0][0] npeaks.append(binpeak) npeaks = array(npeaks) ############### # right plateau ############### nbin = int(max(npeaks) + second_plateau) # this sets a counter dependent second plateau bin interval x = arange(0,nbin,dtype=int) # nbin bins from 0 to nbin-1 self.lastbin, np3s = npeaks.min() - self.prepostpk[0], int(npeaks.max() + self.prepostpk[1]) # final bin for background average, first bin for right plateau estimate (last is nbin) x0 = zeros(self._the_runs_[0][0].get_numberHisto_int()) # for center of peaks if mplot: for counter in range(self._the_runs_[0][0].get_numberHisto_int(),sum(ax_counters.shape)): ax_counters[divmod(counter,3)].cla() ax_counters[divmod(counter,3)].axis('off') for counter in range(self._the_runs_[0][0].get_numberHisto_int()): # prepare for muprompt fit histo = zeros(self._the_runs_[0][0].get_histoLength_bin()) for k in range(len(self._the_runs_[0])): # may add runs histo += self._the_runs_[0][k].get_histo_vector(counter,1) p = [ peakheight, float(npeaks[counter]), peakwidth, mean(histo[self.firstbin:self.lastbin]), mean(histo[np3s:nbin])] y = histo[:nbin] ############## # guess values ############## mm = muprompt() mm._init_(x,y) mm.errordef = Minuit.LEAST_SQUARES m = Minuit(mm,a=p[0],x0=p[1],dx=p[2],ak1=p[3],ak2=p[4]) # m.values = p m.errors = (p[0]/100,p[1]/100,0.01,p[3]/100,p[4]/100) m.migrad() A,X0,Dx,Ak1,Ak2 = m.values x0[counter] = X0 # store float peak bin position (fractional) if mplot: # do plot n1 = npeaks[counter]-50 n2 = npeaks[counter]+50 x3 = arange(n1,n2,1./10.) ax_counters[divmod(counter,3)].cla() ax_counters[divmod(counter,3)].plot(x[n1:n2],y[n1:n2],'.') ax_counters[divmod(counter,3)].plot(x3,mm.f(x3,A,X0,Dx,Ak1,Ak2)) x_text,y_text = npeaks[counter]+10,0.8*max(y) prompt_fit_text[counter] = ax_counters[ divmod(counter,3)].text(x_text,y_text, 'Det #{}\nt0={}bin\n$\delta$t0={:.2f}'.format(counter+1, x0.round().astype(int)[counter],x0[counter]-x0.round().astype(int)[counter])) ############################################################################## # Simple cases: # # 1) Assume the prompt is entirely in bin nt0. # # (python convention, the bin index is 0,...,n,... # # The content of bin nt0 will be the t=0 value for this case and dt0 = 0. # # The center of bin nt0 will correspond to time t = 0, # # time = (n-nt0 + mufit.offset + mufit.dt0)*mufit.binWidth_ns/1000. # # 2) Assume the prompt is equally distributed between n and n+1. # # Then nt0 = n and dt0 = 0.5, the same formula applies # # 3) Assume the prompt is 0.45 in n and 0.55 in n+1. # # Then nt0 = n+1 and dt0 = -0.45, the same formula applies. # ############################################################################## # these three are the sets of parameters used by other methods self.nt0 = x0.round().astype(int) # bin of peak, nd.array of shape run.get_numberHisto_int() self.dt0 = x0-self.nt0 # fraction of bin, nd.array of shape run.get_numberHisto_int() self.lastbin = self.nt0.min() - self.prepostpk[0] # nd.array of shape run.get_numberHisto_int() elif self.datafile[-3:] =='mdu': # PSI HIFI first_plateau = - 500 second_plateau = 1500 ############################# # very rough guess of histo start bin # then # fit a step ############################# ncounters = self._the_runs_[0][0].get_numberHisto_int() npeaks = [] a = 0.5*ones(ncounters) b = 30*ones(ncounters) dn = 5*ones(ncounters) for counter in range(ncounters): histo = zeros(self._the_runs_[0][0].get_histoLength_bin()) for k in range(len(self._the_runs_[0])): # may add runs histo += self._the_runs_[0][k].get_histo_vector(counter,1) npeakguess = scanms(histo,100) # simple search for a step pattern if npeakguess>0: npeaks.append(npeakguess) elif counter != 0: self.console('**** WARNING: step in hifi detector {} not found'.format(counter)) self.console(' set to arbitrary bin 20000') npeaks.append(20000) else: npeaks.append(where(histo==histo.max())[0][0]) ############### # now fit it ############### if counter != 0: n2 = npeaks[counter] + second_plateau # counter dependent bin interval n1 = npeaks[counter] + first_plateau x = arange(n1,n2+1,dtype=int) # n2-n1+1 bins from n1 to n2 included for plotting y = histo[n1:n2+1] # next will try likelihood c = cost.LeastSquares(x,y,1,step) m = Minuit(c,a=a[counter],n=npeaks[counter],dn=dn[counter],b=b[counter]) # m.errors(1.,10.,1.) m.migrad() a[counter],n,dn[counter],b[counter] = m.values if m.valid: npeaks.pop() npeaks.append(n) else: self.console('**** step fit not converged for detector {}'.format(counter)) x0 = array(npeaks).astype(int) self.lastbin = x0.min() - self.prepostpk[0].value # final bin for background average ############################ # just show where this is and save parameters ############################ if mplot: # do plot prompt_fit_text = [None]*ncounters n2 = x0.max() + second_plateau # counter independent bin interval n1 = x0.min() + first_plateau for counter in range(ncounters): ax_counters[divmod(counter,3)].cla() # ax_counters[divmod(counter,3)].axis('off') histo = zeros(self._the_runs_[0][0].get_histoLength_bin()) for k in range(len(self._the_runs_[0])): # may add runs histo += self._the_runs_[0][k].get_histo_vector(counter,1) x = arange(n1,n2+1,dtype=int) # n2-n1+1 bins from n1 to n2 included for plotting y = histo[n1:n2+1] x3 = arange(n1,n2) ax_counters[divmod(counter,3)].plot(x,y,'.') ax_counters[divmod(counter3)].plot(x, step(x,a[counter],npeaks[counter],dn[counter],b[counter]),'r-') x_text,y_text = npeaks[counter]+10,0.8*histo.max() prompt_fit_text[counter] = ax_counters[divmod(counter,3)].text(x_text, y_text,'Det #{}\nt0={}bin'.format(counter+1,x0[counter])) self.nt0 = x0 # bin of peak, nd.array of shape run.get_numberHisto_int() self.dt0 = zeros(x0.shape) # fraction of bin, nd.array of shape run.get_numberHisto_int() elif self.filespecs[1].value=='nxs': # ISIS histo = zeros(self._the_runs_[0][0].get_histoLength_bin()) for counter in range(self._the_runs_[0][0].get_numberHisto_int()): for k in range(len(self._the_runs_[0])): # may add runs histo += self._the_runs_[0][k].get_histo_vector(counter,1) error = sqrt(histo) error[where(error==0)]=1 dh = histo[1:]-histo[:-1] kt0 = where(dh==dh.max())[0] # [0] musbin = float(self.nsbin.value)/1e3 t0 = kt0*musbin N = histo[int(kt0)+10]*TauMu_mus() D = 0.080 n1 = 0 n2 = 101 t = musbin*linspace(n1,n2-1,n2) mm = muedge() mm._init_(t,histo[n1:n2]) m = Minuit(mm,t00=t0,N=N,D=D) m.errors=(t0/100,N/100,0.8) m.print_level = 1 if mprint else 0 m.migrad() t0,N,D = m.values if mplot: # do plot ax_counters.plot(t,histo[n1:n2],'.') ax_counters.plot(t,mm.f(t,t0,N,D)) x_text,y_text = t[int(2*n2/3)],0.2*max(histo[n1:n2]) ax_counters.text(x_text,y_text,'t0 = {:.1f} mus'.format(t0)) self.nt0 = array([t0/float(self.nsbin.value)]).round().astype(int) # bin of peak, # nd.array of shape run.get_numberHisto_int() self.dt0 = array(t0-self.nt0) # fraction of bin, in ns if mplot: # show results fig_counters.canvas.manager.window.tkraise() P.draw() self.console('Succesfully completed prompt Minuit fit, check plots') else: self.console('Succesfully completed prompt Minuit fit, check nt0, dt0 ') self.console('****************END OF SUITE*****************')