def FWHM(counts, lower_bound, upper_bound): X = range(lower_bound, upper_bound) Y = counts[lower_bound:upper_bound] # Fit a guassian mean = sum(X * Y) / sum(Y) sigma = np.sqrt(sum(Y * (X - mean)**2) / sum(Y)) # pi = [max(Y),mean,sigma] # popt, pcov = curve_fit(gauss, X, Y, p0=pi) # print(popt) # fit_a, fit_mu, fit_stdev = popt # fit guassian using other method model = GaussianModel(prefix='peak_') + ConstantModel() # make a model that is a Gaussian + a constant: model = GaussianModel(prefix='peak_') + ConstantModel() # make parameters with starting values: params = model.make_params(c=1.0, peak_center=mean, peak_sigma=sigma, peak_amplitude=max(Y)) # run fit result = model.fit(Y, params, x=X) print('fwhm: ', result.params['peak_fwhm'].value, 'centroid: ', result.params['peak_center'].value) # find FWHM # fwhm = 2*np.sqrt(2*np.log(2))*np.abs(fit_stdev) # cent = fit_mu return result.params['peak_fwhm'].value, result.params['peak_center'].value
def fitNpeaks(f, y, npeaks=5, thres=0.02, min_dist=5, width=300, plot_prefix=None, model=SkewedGaussianModel, offset=True): # Guess initial peak centres using peakutils indexes = peakutils.indexes(y, thres=thres, min_dist=min_dist) peaksfound = len(indexes) assert peaksfound >= npeaks, "Looking for %s or more peaks only found %s of them!" % ( npeaks, peaksfound) peak_f = peakutils.interpolate(f, y, ind=indexes) # Oder peaks by decreaing height and keep only the first npeaks peak_heights = indexes peak_order = peak_heights.argsort()[::-1] peak_heights = peak_heights[peak_order[:npeaks]] peak_f = peak_f[peak_order[:npeaks]] amplitude_scale = 1.0 peak_amplitudes = peak_heights * amplitude_scale # This is lmfit's annoying definition of a Gaussian `amplitude' print('Initial peaks guessed at ', peak_f) # Make multipeak model peaks = [] for i in range(npeaks): prefix = 'g{:d}_'.format(i + 1) peaks.append(model(prefix=prefix)) if i == 0: pars = peaks[i].make_params(x=f) else: pars.update(peaks[i].make_params()) if model == SkewedGaussianModel: pars[prefix + 'center'].set(peak_f[i], min=f.min(), max=f.max()) pars[prefix + 'sigma'].set(width, min=0.1 * width, max=10 * width) pars[prefix + 'gamma'].set(0, min=-5, max=5) pars[prefix + 'amplitude'].set(peak_amplitudes[i]) elif model == GaussianModel: pars[prefix + 'center'].set(peak_f[i], min=f.min(), max=f.max()) pars[prefix + 'sigma'].set(width, min=0.1 * width, max=10 * width) pars[prefix + 'amplitude'].set(peak_amplitudes[i]) model = peaks[0] for i in range(1, npeaks): model += peaks[i] if offset: model += ConstantModel() pars.update(ConstantModel().make_params()) pars['c'].set(0) # Fit first spectrum, creating the ModelResult object which will be used over and over fit = model.fit(y, pars, x=f) return fit
def fit_peaks( x, y, peak_pos, bg="constant", sigma_guess=2, center_pm=20, sigma_min=0.5, amplitude_max_m=3.0, bg_pm=100, ): mod = ConstantModel() for i, p in enumerate(peak_pos): mod += LorentzianModel(prefix="p%s_" % i) pars = mod.make_params() for i, p in enumerate(peak_pos): pars["p%s_center" % i].set(p, min=p - center_pm, max=p + center_pm) pars["p%s_sigma" % i].set(sigma_guess, min=sigma_min) # pars['p%s_amplitude' % i].set(10**2, min=0.0) pars["p%s_amplitude" % i].set( amplitude_max_m * y[find_nearest_index(x, p)], min=0.0 ) pars["c"].set(0, min=-1 * bg_pm, max=bg_pm) out = mod.fit(y, pars, x=x, method="leastsq") out.peak_pos = peak_pos return out
def make_gaussian_model(self): """ This method creates a model of a gaussian with an offset. @return tuple: (object model, object params) Explanation of the objects: object lmfit.model.CompositeModel model: A model the lmfit module will use for that fit. Here a gaussian model. Returns an object of the class lmfit.model.CompositeModel. object lmfit.parameter.Parameters params: It is basically an OrderedDict, so a dictionary, with keys denoting the parameters as string names and values which are lmfit.parameter.Parameter (without s) objects, keeping the information about the current value. The used model has the Parameter with the meaning: 'amplitude' : amplitude 'center' : center 'sigm' : sigma 'fwhm' : full width half maximum 'c' : offset For further information have a look in: http://cars9.uchicago.edu/software/python/lmfit/builtin_models.html#models.GaussianModel """ model = GaussianModel() + ConstantModel() params = model.make_params() return model, params
def pyfxcor(inspec, template, vmin=-200., vmax=200., res=3, rej=1000): rv, cc = pyasl.crosscorrRV(inspec[0], inspec[1], template[0], template[1], vmin, vmax, res, skipedge=rej) cen_gs = np.argmax(cc) perfx, perfy = rv[cen_gs - 5:cen_gs + 6], cc[cen_gs - 5:cen_gs + 6] try: gauss = ConstantModel() + GaussianModel() pars = gauss.make_params() pars['center'].set(value=rv[np.argmax(cc)], vary=True) pars['amplitude'].set(value=max(cc), vary=True) pars['sigma'].set(vary=True) pars['c'].set(value=0, vary=True) out = gauss.fit(perfy, pars, x=perfx) ct = out.best_values['center'] cterr = out.params['center'].stderr except: return 'error', '' return ct, cterr
def GaussConst(signal, guess): if guess == False: return [0, 0, 0] else: amp, centre, stdev, offset = guess data = np.array([range(len(signal)), signal]).T X = data[:,0] Y = data[:,1] gauss_mod = GaussianModel(prefix='gauss_') const_mod = ConstantModel(prefix='const_') #pars = lorentz_mod.make_params(amplitude=amp, center=centre, sigma=stdev / 3.) #lorentz_mod.set_param_hint('sigma', value = stdev / 3., min=0., max=stdev) pars = gauss_mod.guess(Y, x=X, center=centre, sigma=stdev / 3., amplitude=amp) #pars += step_mod.guess(Y, x=X, center=centre) pars += const_mod.guess(Y, x=X) pars['gauss_sigma'].vary = False mod = gauss_mod + const_mod result = mod.fit(Y, pars, x=X) # write error report #print result.fit_report() fwhm = result.best_values['gauss_sigma'] * 2.3548 return X, result.best_fit, result.redchi, fwhm
def GaussConst(signal, guess): amp, centre, stdev, offset = guess data = np.array([range(len(signal)), signal]).T X = data[:, 0] Y = data[:, 1] gauss_mod = GaussianModel(prefix='gauss_') const_mod = ConstantModel(prefix='const_') pars = gauss_mod.make_params(center=centre, sigma=stdev, amplitude=amp) pars += const_mod.guess(Y, x=X) pars['gauss_center'].min = centre - 5. pars['gauss_center'].max = centre + 5. pars['gauss_sigma'].max = stdev + 5. mod = gauss_mod + const_mod result = mod.fit(Y, pars, x=X) fwhm = result.best_values['gauss_sigma'] #* 2.3548 centr = result.best_values['gauss_center'] # Values within two stdevs i.e. 95% pl.plot(np.repeat(centr - fwhm * 2, len(Y)), np.arange(len(Y)), 'b-') pl.plot(np.repeat(centr + fwhm * 2, len(Y)), np.arange(len(Y)), 'b-') return X, result.best_fit, result.best_values['gauss_sigma'] * 4
def gauss_step_const(signal, guess): """ Fits high contrast data very well """ if guess == False: return [0, 0] else: amp, centre, stdev, offset = guess data = np.array([range(len(signal)), signal]).T X = data[:,0] Y = data[:,1] # gauss_mod = Model(gaussian) gauss_mod = Model(gaussian) const_mod = ConstantModel() step_mod = StepModel(prefix='step') pars = gauss_mod.make_params(height=amp, center=centre, width=stdev / 3., offset=offset) # pars = gauss_mod.make_params(amplitude=amp, center=centre, sigma=stdev / 3.) gauss_mod.set_param_hint('sigma', value = stdev / 3., min=stdev / 2., max=stdev) pars += step_mod.guess(Y, x=X, center=centre) pars += const_mod.guess(Y, x=X) mod = const_mod + gauss_mod + step_mod result = mod.fit(Y, pars, x=X) # write error report #print result.fit_report() print "contrast fit", result.redchi return X, result.best_fit, result.redchi
def model_at_depth(tree, depth, property_name): r"""Generate a fit model at a particular tree depth Parameters ---------- tree : :class:`~idpflex.cnextend.Tree` Hierarchical tree depth: int depth level, starting from the tree's root (depth=0) property_name : str Name of the property to create the model for Returns ------- :class:`~lmfit.model.CompositeModel` A model composed of a :class:`~idpflex.bayes.TabulatedFunctionModel` for each node plus a :class:`~lmfit.models.ConstantModel` accounting for a flat background """ # noqa: E501 mod = ConstantModel() for node in tree.nodes_at_depth(depth): p = node[property_name] m = TabulatedFunctionModel(p.x, p.y, prefix='n{}_'.format(node.id)) m.set_param_hint('center', vary=False) m.set_param_hint('amplitude', value=1.0 / (1 + depth)) mod += m return mod
def Box(signal, guess): amp, centre, stdev, offset = guess data = np.array([range(len(signal)), signal]).T X = data[:, 0] Y = data[:, 1] gauss_mod = RectangleModel(prefix='gauss_', mode='logistic') const_mod = ConstantModel(prefix='const_') pars = gauss_mod.make_params(center1=centre - stdev * 3, center2=centre + stdev * 3, sigma1=0, sigma2=0, amplitude=amp) pars += const_mod.guess(Y, x=X) pars['gauss_center1'].min = centre - stdev * 3 - 3 pars['gauss_center2'].max = centre - stdev * 3 + 3 pars['gauss_center2'].min = centre + stdev * 3 - 3 pars['gauss_center2'].max = centre + stdev * 3 + 3 mod = gauss_mod + const_mod result = mod.fit(Y, pars, x=X) c1 = result.best_values['gauss_center1'] c2 = result.best_values['gauss_center2'] pl.legend() return X, result.best_fit, c2 - c1
def fitgaussian_sample(sample, components, svg, verbose, center, cmin, cmax, amp, amin, sigma, smin): '''Fits gaussian curve to dyad coverage for a single sample.''' print('Fits gaussian curve to dyad coverage of sample {}'.format(sample)) input = sample + '-dyad.txt' dyads = pd.read_csv(input, sep='\t', index_col=0, comment='#') x = dyads.index.values y = dyads['Relative Frequency'].values if not amp: amp = dyads['Relative Frequency'].max() * 100 if not center: center = 0.0 if not sigma: sigma = dyads.index.max() / 2 plt.figure() plt.title(sample) plt.xlabel('Position relative to dyad (bp)') plt.ylabel('Relative Frequency') plt.xlim(x[0], x[len(x) - 1]) plt.xticks(list(range(x[0], x[len(x) - 1] + 1, 25))) plt.plot(dyads.index.values, dyads['Relative Frequency'].values, color='red') plot_output = sample + '-dyad-gaussian.png' try: constant = ConstantModel(prefix='c_') pars = constant.make_params() pars['c_c'].set(value=dyads['Relative Frequency'].min(), min=0.0, max=dyads['Relative Frequency'].max()) gauss = GaussianModel(prefix='g_') pars.update(gauss.make_params()) pars['g_center'].set(value=center, min=cmin, max=cmax) pars['g_sigma'].set(value=sigma, min=smin) pars['g_amplitude'].set(value=amp, min=amin) mod = constant + gauss init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) if components: plt.plot(x, init, 'b--', label='Initial fit') if verbose: print(out.fit_report(min_correl=0.5)) plt.plot(x, out.best_fit, 'b-', label='Best fit') if components: comps = out.eval_components(x=x) plt.plot(x, np.repeat(comps['c_'], len(x)), 'g--', label='Constant component') plt.plot(x, comps['g_'], 'm--', label='Gaussian component') except Exception as e: logging.warning( 'could not fit gaussian curve to sample {}'.format(sample), e) if components: plt.legend(loc='lower right') plt.savefig(plot_output) if svg: plot_svg_output = sample + '-dyad-gaussian.svg' plt.savefig(plot_svg_output, transparent=True) plt.close()
def Rectangle(signal, guess): if guess == False: return [0, 0, 0] else: amp, centre, stdev, offset = guess data = np.array([range(len(signal)), signal]).T X = data[:,0] Y = data[:,1] step_mod = Rectangle() const_mod = ConstantModel() pars = step_mod.guess(Y, x=X, center=centre) pars += const_mod.guess(Y, x=X) mod = step_mod + const_mod result = mod.fit(Y, pars, x=X) # write error report #print result.fit_report() fwhm = result.best_values['sigma'] * 2.3548 print fwhm return X, result.best_fit, result.redchi, 0
def fit_s21mag(x_val, y_val): peak = LorentzianModel() offset = ConstantModel() model = peak pars = peak.guess(y_val, x=x_val, amplitude=-0.05) result = model.fit(y_val, pars, x=x_val) return result
def fit_s21mag(x_val, y_val): peak = GaussianModel() offset = ConstantModel() model = peak + offset pars = offset.make_params(c=np.median(y_val)) pars += peak.guess(y_val, x=x_val, amplitude=-0.5) result = model.fit(y_val, pars, x=x_val) return result
def __init__(self, nexp=0, moddef=" "): self.definition = moddef self.model = ConstantModel() self.nexp = 0 self.errors = None self.params = None self.res = None for _ in range(nexp): self.add_exp()
def xrf_calib_init_roi(mca, roiname): """initial calibration step for MCA: find energy locations for one ROI """ if not isLarchMCAGroup(mca): print('Not a valid MCA') return energy = 1.0 * mca.energy chans = 1.0 * np.arange(len(energy)) counts = mca.counts bgr = getattr(mca, 'bgr', None) if bgr is not None: counts = counts - bgr if not hasattr(mca, 'init_calib'): mca.init_calib = OrderedDict() roi = None for xroi in mca.rois: if xroi.name == roiname: roi = xroi break if roi is None: return words = roiname.split() elem = words[0].title() family = 'Ka' if len(words) > 1: family = words[1].title() if family == 'Lb': family = 'Lb1' try: eknown = xray_line(elem, family).energy / 1000.0 except: eknown = 0.001 llim = max(0, roi.left - roi.bgr_width) hlim = min(len(chans) - 1, roi.right + roi.bgr_width) segcounts = counts[llim:hlim] maxcounts = max(segcounts) ccen = llim + np.where(segcounts == maxcounts)[0][0] ecen = ccen * mca.slope + mca.offset bkgcounts = counts[llim] + counts[hlim] if maxcounts < 2 * bkgcounts: mca.init_calib[roiname] = (eknown, ecen, 0.0, ccen, None) else: model = GaussianModel() + ConstantModel() params = model.make_params(amplitude=maxcounts, sigma=(chans[hlim] - chans[llim]) / 2.0, center=ccen - llim, c=0.00) params['center'].min = -10 params['center'].max = hlim - llim + 10 params['c'].min = -10 out = model.fit(counts[llim:hlim], params, x=chans[llim:hlim]) ccen = llim + out.params['center'].value ecen = ccen * mca.slope + mca.offset fwhm = out.params['fwhm'].value * mca.slope mca.init_calib[roiname] = (eknown, ecen, fwhm, ccen, out)
def __init__(self, nexp=0, sum_one=False): self.sum_one_flag = sum_one self.model = ConstantModel() self.nexp = 0 self.errors = None self.params = None self.res = None for _ in range(nexp): self.add_exp()
def model(self): """Returns the sum of all peak models.""" model = ConstantModel(prefix="BASE_") model.set_param_hint("c", vary=False, value=0) self.params += model.make_params() for peak in self._peaks: model += peak.model return model
def fit_lm_g(x,y,inits): ##https://stackoverflow.com/questions/44573896/python-fit-gaussian-to-noisy-data-with-lmfit # gmodel = LorentzianModel() # gmodel = VoigtModel() gmodel = GaussianModel() cmodel = ConstantModel() model = gmodel + cmodel params = model.make_params(sigma = inits[2], amplitude = inits[0], center = inits[1]) result = model.fit(y, params, x=x) # print(params) return result
def fit_s21mag(x_val, y_val): x_val_midpoint = int(np.round(len(x_val) / 2)) peak = GaussianModel() offset = ConstantModel() model = peak + offset pars = offset.make_params(c=np.median(y_val)) pars += peak.guess(y_val, x=x_val, amplitude=-0.05, center=x_val[x_val_midpoint]) result = model.fit(y_val, pars, x=x_val) return result
def abel_invert(self, y_lim, x_range, parameters=None, model=None): if model is None: # Create the lmfit model model = GaussianModel() model += ConstantModel() params = model.make_params() params['c'].set(0.45) params['center'].set(0, vary=False) params['sigma'].set(min=0.001) if parameters is not None: for key, value in parameters.items(): params[key].set(**value) f = FloatProgress(min=0.3, max=4.5) display(f) fit_data = [] abel_data = [] xx = x_range self.abel_extent = [-xx, xx, y_lim[0], y_lim[1]] for yy in np.arange(y_lim[0], y_lim[1], 1 / self.scale): f.value = yy self.create_lineout(start=(yy, -xx), end=(yy, xx), lineout_width_mm=1 / self.scale) # The data obtained by the lineout y = self.lo x = self.mm out = model.fit(y, params, x=x) fit_data.append(out.best_fit) abel_data.append( self.abel_gauss(x, out.best_values['sigma'], out.best_values['amplitude']) * 10) #*10 converts from mm^-1 to cm^-1 # Change the lists to numpy arrays and flip them fit_data = np.array(fit_data)[::-1] abel_data = np.array(abel_data)[::-1] extent = [-x_range, x_range, y_lim[0], y_lim[1]] origin = [ int(len(fit_data) + y_lim[0] * self.scale), int(len(fit_data[0]) / 2) ] self.fit = DMFromArray(fit_data, self.scale, extent=extent, origin=origin) self.abel = DMFromArray(abel_data, self.scale, extent=extent, origin=origin) return self.fit, self.abel
def FitSpectrumInit(self, label): """ Fit the spectrum with the fit params of another spectrum (given by label) as initial values. Useful when you fit big number of similar spectra. """ borders = np.genfromtxt(label + '/spectrumborders_' + label + '.txt', unpack=True) np.savetxt(self.label + '/spectrumborders_' + self.label + '.txt', borders) self.y = self.y[(self.x > borders[0]) & (self.x < borders[-1])] self.x = self.x[(self.x > borders[0]) & (self.x < borders[-1])] FitData = np.load(label + '/fitparams_' + label + '.npz') baseline = FitData['c'] / self.maxyvalue ctr = FitData['x0'] sigma = FitData['sigma'] gamma = FitData['gamma'] ramanmodel = ConstantModel() ramanmodel.set_param_hint('c', value=baseline[0], min=0) for i in range(len(sigma)): prefix = 'p' + str(i + 1) tempvoigt = Model(func=voigt, prefix=prefix) tempvoigt.set_param_hint(prefix + 'x0', value=ctr[i], min=0) tempvoigt.set_param_hint(prefix + 'sigma', value=sigma[i], min=0) tempvoigt.set_param_hint(prefix + 'gamma', value=gamma[i], min=0) tempvoigt.set_param_hint(prefix + 'height', expr='wofz(((0) + 1j*' + prefix + 'gamma) / ' + prefix + 'sigma / sqrt(2)).real') tempvoigt.set_param_hint(prefix + 'fwhm', expr='0.5346 * 2 *' + prefix + 'gamma + sqrt(0.2166 * (2*' + prefix + 'gamma)**2 + (2 * ' + prefix + 'sigma * sqrt(2 * log(2) ) )**2 )') ramanmodel += tempvoigt pars = ramanmodel.make_params() fitresult = ramanmodel.fit(self.y, pars, x=self.x, scale_covar=True) plt.clf() comps = fitresult.eval_components() xplot = np.linspace(self.x[0], self.x[-1], 1000) plt.plot(self.x, self.y * self.maxyvalue, 'r-') plt.plot(self.x, fitresult.best_fit * self.maxyvalue) for i in range(0, len(sigma)): plt.plot( self.x, comps['p' + str(i + 1)] * self.maxyvalue + comps['constant'] * self.maxyvalue, 'k-') plt.savefig(self.label + '/rawplot_' + self.label + '.pdf') save_modelresult(fitresult, self.label + '/modelresult_' + self.label + '.sav') plt.clf()
def prepare_model(nexp): emodel = ConstantModel() + ExponentialModel(prefix='a') + ExponentialModel( prefix='b') pars.add('e', value=0, min=0) pars.add('cntrl', value=1, min=1 - 1e-5, max=1 + 1e-5) pars['cntrl'].expr = 'c' pars['cntrl'].vary = True expr = '{}amplitude' all_expr = '' for i in range(1, 1): pars['cntrl'].expr += ' + ' + expr.format(Prefixes[i]) return emodel, pars
def FitSpectrum(self): """ Fit Spectrum with initial values provided by SelectBaseline() and SelectPeaks() """ polyparams = self.Fitbaseline(self) base = polyparams[0].n ramanmodel = ConstantModel() ramanmodel.set_param_hint('c', value=base, min=0) globwidth = 1 xpeak, ypeak = np.genfromtxt(self.peakfile, unpack=True) if type(xpeak) == np.float64: xpeak = [xpeak] ypeak = [ypeak] for i in range(0, len(xpeak)): prefix = 'p' + str(i + 1) tempvoigt = Model(func=voigt, prefix=prefix) tempvoigt.set_param_hint(prefix + 'x0', value=xpeak[i], min=0) tempvoigt.set_param_hint(prefix + 'sigma', value=globwidth, min=0) tempvoigt.set_param_hint(prefix + 'gamma', value=globwidth, min=0) tempvoigt.set_param_hint(prefix + 'height', value=ypeak[i], expr='wofz(((0) + 1j*' + prefix + 'gamma) / ' + prefix + 'sigma / sqrt(2)).real') tempvoigt.set_param_hint(prefix + 'fwhm', expr='0.5346 * 2 *' + prefix + 'gamma + sqrt(0.2166 * (2*' + prefix + 'gamma)**2 + (2 * ' + prefix + 'sigma * sqrt(2 * log(2) ) )**2 )') ramanmodel += tempvoigt pars = ramanmodel.make_params() fitresult = ramanmodel.fit(self.y, pars, x=self.x, scale_covar=True) print(fitresult.fit_report(min_correl=0.5)) comps = fitresult.eval_components() xplot = np.linspace(self.x[0], self.x[-1], 1000) plt.plot(self.x, self.y * self.maxyvalue, 'rx') plt.plot(self.x, fitresult.best_fit * self.maxyvalue) for i in range(0, len(xpeak)): plt.plot( self.x, comps['p' + str(i + 1)] * self.maxyvalue + comps['constant'] * self.maxyvalue, 'k-') plt.show() plt.savefig(self.label + '/rawplot_' + self.label + '.pdf') save_modelresult(fitresult, self.label + '/modelresult_' + self.label + '.sav')
def BuiltInModels(self) : FitInfo = self.FitInfo ModelString = list() for key in FitInfo['Models'] : ModelString.append((key,FitInfo['Models'][key]['model'])) for Model in ModelString : try : FitModel except : if Model[1] == 'Constant' : FitModel = ConstantModel(prefix=Model[0]+'_') if Model[1] == 'Linear' : FitModel = LinearModel(prefix=Model[0]+'_') if Model[1] == 'Gaussian' : FitModel = GaussianModel(prefix=Model[0]+'_') if Model[1] == 'SkewedGaussian' : FitModel = SkewedGaussianModel(prefix=Model[0]+'_') if Model[1] == 'Voigt' : FitModel = VoigtModel(prefix=Model[0]+'_') else : if Model[1] == 'Constant' : FitModel = FitModel + ConstantModel(prefix=Model[0]+'_') if Model[1] == 'Linear' : FitModel = FitModel + LinearModel(prefix=Model[0]+'_') if Model[1] == 'Gaussian' : FitModel = FitModel + GaussianModel(prefix=Model[0]+'_') if Model[1] == 'SkewedGaussian' : FitModel = FitModel + SkewedGaussianModel(prefix=Model[0]+'_') if Model[1] == 'Voigt' : FitModel = FitModel + VoigtModel(prefix=Model[0]+'_') self.FitModel = FitModel self.ModelParameters = FitModel.make_params()
def fit_data(x, y, xmin=None, xmax=None): if y is None: return "No spectrum! Fit not performed!" else: if xmin is None: xmin = x.min() elif xmin < x.min(): xmin = x.min() if xmax is None: xmax = x.max() elif xmax < x.max(): xmax = x.max() y = np.copy(y[np.logical_and(x > xmin, x < xmax)]) x = np.copy(x[np.logical_and(x > xmin, x < xmax)]) x, y = remove_spike(y, x=x) mod = (ConstantModel() + PseudoVoigtModel(prefix="peak1_") + PseudoVoigtModel(prefix="peak2_")) params = mod.make_params() ymax_ind = np.argmax(y) xmax = x[ymax_ind] params["c"].set(0) params.add("psplit", value=1.5, vary=True, min=0.5, max=2.0) params["peak2_center"].set(xmax, min=xmax - 0.5, max=x.max()) params["peak2_sigma"].set(0.5, min=0.01) params["peak2_amplitude"].set(y[ymax_ind] * 0.5 * np.sqrt(2 * np.pi), min=0) params["peak2_fraction"].set(0.5, min=0, max=1) params["peak1_center"].set(vary=False, expr="peak2_center-psplit") params["peak1_sigma"].set(0.5, min=0.01) params["peak1_amplitude"].set(y[ymax_ind] * 0.5 * np.sqrt(2 * np.pi) / 2, min=0) params["peak1_fraction"].set(0.5, min=0, max=1) fit = mod.fit(y, params, x=x) return fit
def make_lorentzian_model(self): """ This method creates a model of lorentzian with an offset. The parameters are: 'amplitude', 'center', 'sigma, 'fwhm' and offset 'c'. For function see: http://cars9.uchicago.edu/software/python/lmfit/builtin_models.html#models.LorentzianModel @return lmfit.model.CompositeModel model: Returns an object of the class CompositeModel @return object params: lmfit.parameter.Parameters object, returns an object of the class Parameters with all parameters for the lorentzian model. """ model = LorentzianModel() + ConstantModel() params = model.make_params() return model, params
def fit_peak_df(df, model=GaussianModel, params=None, fit_range=(-np.inf, np.inf), x_field=None, fit_field='nphe2_mean', out_field='peak_fit'): """ Fits DataFrame with selected peak model. Appends residuals column to DataFrame. """ # Data fit_min, fit_max = fit_range df_ranged = df[(df.index > fit_min) & (df.index < fit_max)] if x_field: x = np.array(df_ranged[x_field]) full_x = np.array(df[x_field]) else: x = np.array(df_ranged.index.get_values()) full_x = np.array(df.index.get_values()) y = np.array(df_ranged[fit_field].values) full_y = np.array(df[fit_field].values) # Models if isinstance(model, str): try: model = PEAK_MODELS[model] except KeyError: print("Undefined model: {}, using default".format(model)) peak_mod = model(prefix='peak_') const_mod = ConstantModel(prefix='const_') result_model = const_mod + peak_mod # Parameters if not params: pars = const_mod.make_params(c=y.min()) pars += peak_mod.guess(y, x=x, center=0) else: pars = params # Fitting result = result_model.fit(y, params=pars, x=x) peak_eval = result.eval(x=full_x) y_res = full_y - peak_eval df[out_field] = pd.Series(peak_eval, index=df.index) df[out_field + '_res'] = pd.Series(y_res, index=df.index) return df, result
def gaussian_fit(self, x, y, paras=None, method=None): g1model = GaussianModel(prefix='g1_') g2model = GaussianModel(prefix='g2_') g3model = GaussianModel(prefix='g3_') cmodel = ConstantModel() paras_fit = g1model.guess(data=y, x=x) paras_fit.update(g2model.make_params()) paras_fit.update(g3model.make_params()) paras_fit['g1_amplitude'].set(min=0.) paras_fit['g2_amplitude'].set(min=0.) paras_fit['g3_amplitude'].set(min=0.) paras_fit['g1_center'].set(min=paras['g1_center'] - 300., value=paras['g1_center'], max=paras['g1_center'] + 300.) paras_fit['g2_center'].set(min=paras['g2_center'] - 300., value=paras['g2_center'], max=paras['g2_center'] + 300.) paras_fit['g3_center'].set(min=paras['g3_center'] - 300., value=paras['g3_center'], max=paras['g3_center'] + 300.) paras_fit['g1_sigma'].set(min=100, value=paras['g1_sigma'], max=paras['g1_sigma'] + 50.) paras_fit['g2_sigma'].set(min=100, value=paras['g2_sigma'], max=paras['g2_sigma'] + 50.) paras_fit['g3_sigma'].set(min=100, value=paras['g3_sigma'], max=paras['g3_sigma'] + 50.) paras_fit.update(cmodel.make_params()) model = g1model + g2model + g3model + cmodel result = model.fit(y, x=x, params=paras_fit, mothod=method) yfit = result.best_fit y_para = result.best_values residual = y - yfit return yfit, y_para, result, residual
def test_stepmodel_erf(): x, y = get_data() stepmod = StepModel(form='linear') const = ConstantModel() pars = stepmod.guess(y, x) pars = pars + const.make_params(c=3 * y.min()) mod = stepmod + const out = mod.fit(y, pars, x=x) assert (out.nfev > 5) assert (out.nvarys == 4) assert (out.chisqr > 1) assert (out.params['c'].value > 3) assert (out.params['center'].value > 1) assert (out.params['center'].value < 4) assert (out.params['amplitude'].value > 50) assert (out.params['sigma'].value > 0.2) assert (out.params['sigma'].value < 1.5)