Example #1
0
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
Example #2
0
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