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]
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