Ejemplo n.º 1
0
def quick_fit_peak(x, y, shape="pv", ymin_on_ymax=0.001, **kwargs):
    """
    Estiamtes and fits a single peak to a set of data
    
    Parameters
    ----------
    x : array_like of floats
        independent variable (energy, q, tth) of spectrum
    y : array_like of floats
        intensity data of spectrum
    shape : {'g', 'l', 'pv','ag', 'al', 'apv'}
        The desired peak shape. Gaussian, lorentzian and pseudovoigt (default), 
        with asymmetric versions, are available. 
    ymin_on_ymax: (optional)
        The ratio of intensity, relative to the peak maximum, over which to 
        calculate the peak intensity.
    
    Returns
    -------
    yfit :   array_like of floats
        The best fit to the provided data
    result : dictionary
        The refined parameter values (as ufloats)
    """

    peak = estimate_peak(x, y, shape=shape, ymin_on_ymax=ymin_on_ymax)
    pf = PeakFitter(x, [peak])
    pf.refine(y)

    return pf.lastfit, pf.lastresult.popitem()[1]
Ejemplo n.º 2
0
    def refine(self, y, reestimate=False):
        """Refines the peak parameters to get a best fit with the data. 

        Parameters
        ----------
        y : array_like of floats
            counts data for the spectrum
        reestimate : bool
            If True the starting parameters for the peaks will be estimated 
            from the data before starting the refinement
            
        Returns
        -------
        fit : array_like of floats
            final output of fitting function 
        results : dictionary
            the refined parameters of all the peaks as ufloats
        
        """
        if not self.ready:
            self.initialise()

        # see if we can get errors if a uarray has been sent
        unc = unumpy.std_devs(y)
        unc[unc == 0] = 1.0  # if not then errors are zero and need to be 1 (unweighted)
        y = unumpy.nominal_values(y)

        if reestimate:  # try to get a better estimate of peak values before refinement
            for peak in self.peaks:
                npeak = estimate_peak(self.x, y, peak.centre)
                peak.centre = npeak.centre
                peak.width = npeak.width
                peak.area = npeak.area
                # print peak.centre.value-peak.limits[0],peak.limits[1]-peak.centre.value

        # cut the x,y and unc data down to the minimum we need
        l, h = self.x.searchsorted([self.peaks[0].limits[0], self.peaks[-1].limits[1]])
        # if (h-l) < 10:print '-->',
        # print l,h
        _x = self.x[l : h + 1]
        _y = y[l : h + 1]

        if self.use_weights:
            weights = 1.0 / unc[l : h + 1]
        else:
            weights = np.ones_like(_y)

        # do the actual fit by least squares
        self._lastminimizer = minimize(
            self._residual,
            self._fit_params,
            args=(_x, self.peaks, self.functions),
            kws={"data": _y, "w": weights},
            **self.lsqkwargs
        )

        yfit = np.zeros_like(y)
        yfit[l : h + 1] = self._residual(self._fit_params, _x, self.peaks, self.functions)

        self._lastresult = OrderedDict([(p.name, p.items()) for p in self.peaks])
        self._lastfit = yfit
        #        for func in self.functions:
        #            for arg in inspect.getargspec(func).args[1:]:
        #                d[arg] = (self._fit_params[arg].value ,self._fit_params[arg].stderr)

        return self.lastfit, self.lastresult