def taylor_mode_max(hist, bins, var=None, mode_guess=None, n_bins=5, poissonLL=False): """ Get the max and mode of a peak based on Taylor exp near the max Returns the amplitude and position of a peak based on a poly fit over n_bins in the vicinity of the maximum of the hist (or the max near mode_guess, if provided) Parameters ---------- hist : array-like The values of the histogram to be fit. Often: send in a slice around a peak bins : array-like The bin edges of the histogram to be fit var : array-like (optional) The variances of the histogram values. If not provided, square-root variances are assumed. mode_guess : float (optional) An x-value (not a bin index!) near which a peak is expected. The algorithm fits around the maximum within +/- n_bins of the guess. If not provided, the center of the max bin of the histogram is used. n_bins : int The number of bins (including the max bin) to be used in the fit. Also used for searching for a max near mode_guess Returns ------- (maximum, mode) : tuple (float, float) maximum : the estimated maximum value of the peak mode : the estimated x-position of the maximum (pars, cov) : tuple (array, matrix) pars : 2-tuple with the parameters (mode, max) of the fit mode : the estimated x-position of the maximum maximum : the estimated maximum value of the peak cov : 2x2 matrix of floats The covariance matrix for the 2 parameters in pars Examples -------- >>> import pygama.analysis.histograms as pgh >>> from numpy.random import normal >>> import pygama.analysis.peak_fitting as pgf >>> hist, bins, var = pgh.get_hist(normal(size=10000), bins=100, range=(-5,5)) >>> pgf.taylor_mode_max(hist, bins, var, n_bins=5) """ if mode_guess is not None: i_0 = ph.find_bin(mode_guess, bins) else: i_0 = np.argmax(hist) i_0 -= int(np.floor(n_bins/2)) i_n = i_0 + n_bins wts = None if var is None else 1/np.sqrt(var[i_0:i_n]) pars, cov = np.polyfit(ph.get_bin_centers(bins)[i_0:i_n], hist[i_0:i_n], 2, w=wts, cov='unscaled') mode = -pars[1] / 2 / pars[0] maximum = pars[2] - pars[0] * mode**2 # build the jacobian to compute the output covariance matrix jac = np.array( [ [pars[1]/2/pars[0]**2, -1/2/pars[0], 0], [pars[1]**2/4/pars[0]**2, -pars[1]/2/pars[0], 1] ] ) cov_jact = np.matmul(cov, jac.transpose()) cov = np.matmul(jac, cov_jact) return (mode, maximum), cov
def gauss_mode_width_max(hist, bins, var=None, mode_guess=None, n_bins=5, poissonLL=False, inflate_errors=False, gof_method='var'): """ Get the max, mode, and width of a peak based on gauss fit near the max Returns the parameters of a gaussian fit over n_bins in the vicinity of the maximum of the hist (or the max near mode_guess, if provided). This is equivalent to a Taylor expansion around the peak maximum because near its maximum a Gaussian can be approximated by a 2nd-order polynomial in x: A exp[ -(x-mu)^2 / 2 sigma^2 ] ~= A [ 1 - (x-mu)^2 / 2 sigma^2 ] = A - (1/2!) (A/sigma^2) (x-mu)^2 The advantage of using a gaussian over a polynomial directly is that the gaussian parameters are the ones we care about most for a peak, whereas for a poly we would have to extract them after the fit, accounting for covariances. The guassian also better approximates most peaks farther down the peak. However, the gauss fit is nonlinear and thus less stable. Parameters ---------- hist : array-like The values of the histogram to be fit bins : array-like The bin edges of the histogram to be fit var : array-like (optional) The variances of the histogram values. If not provided, square-root variances are assumed. mode_guess : float (optional) An x-value (not a bin index!) near which a peak is expected. The algorithm fits around the maximum within +/- n_bins of the guess. If not provided, the center of the max bin of the histogram is used. n_bins : int (optional) The number of bins (including the max bin) to be used in the fit. Also used for searching for a max near mode_guess poissonLL : bool (optional) Flag passed to fit_hist() inflate_errors : bool (optional) If true, the parameter uncertainties are inflated by sqrt(chi2red) if it is greater than 1 gof_method : str (optional) method flag for goodness_of_fit Returns ------- (pars, cov) : tuple (array, matrix) pars : 3-tuple containing the parameters (mode, sigma, maximum) of the gaussian fit mode : the estimated x-position of the maximum sigma : the estimated width of the peak. Equivalent to a guassian width (sigma), but based only on the curvature within n_bins of the peak. Note that the Taylor-approxiamted curvature of the underlying function in the vicinity of the max is given by max / sigma^2 maximum : the estimated maximum value of the peak cov : 3x3 matrix of floats The covariance matrix for the 3 parameters in pars """ bin_centers = ph.get_bin_centers(bins) if mode_guess is not None: i_0 = ph.find_bin(mode_guess, bins) else: i_0 = np.argmax(hist) mode_guess = bin_centers[i_0] amp_guess = hist[i_0] i_0 -= int(np.floor(n_bins / 2)) i_n = i_0 + n_bins width_guess = (bin_centers[i_n] - bin_centers[i_0]) vv = None if var is None else var[i_0:i_n] guess = (mode_guess, width_guess, amp_guess) try: pars, cov = fit_hist(gauss_basic, hist[i_0:i_n], bins[i_0:i_n + 1], vv, guess=guess, poissonLL=poissonLL) except: return None, None if pars[1] < 0: pars[1] = -pars[1] if inflate_errors: chi2, dof = goodness_of_fit(hist, bins, var, gauss_basic, pars) if chi2 > dof: cov *= chi2 / dof return pars, cov