def lmfit_ngauss(x,y, *params): params = params[0] mods = [] prefixes = [] for i in range(0, len(params), 3): pref = "g%02i_" % (i/3) gauss_i = GaussianModel(prefix=pref) if i == 0: pars = gauss_i.guess(y, x=x) else: pars.update(gauss_i.make_params()) A = params[i] l_cen = params[i+1] sigma = params[i+2] pars[pref+'amplitude'].set(A) pars[pref+'center'].set(l_cen) pars[pref+'sigma'].set(sigma) mods.append(gauss_i) prefixes.append(pref) mod = mods[0] if len(mods) > 1: for m in mods[1:]: mod += m print mod init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) return mod, out, init
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 init_dr_model(baseline=False, guess=None): """ Function to serialize a Model object for DR fits. Defaults to a Gaussian line shape, but the option to include a linear offset is available. Additionally, if a guess is provided in the lmfit convention then it will be incorporated. args: ----------------- baseline - boolean indicating if linear offset is included guess - nested dict with keys corresponding to parameter name and values corresponding to dicts with key/value indicating the parameter value, range, and constraints """ model = GaussianModel() if baseline: model += LinearModel() params = model.make_params() if guess: params.update(guess) # Constrain amplitude to always be negative # since we're measuring depletion. params["amplitude"].set(max=0.0) return model, params
def test_2gaussians(): x = np.linspace(0.0, 10.0, num=1000) y = gaussian(x, -1, 3, 0.75) + gaussian(x, -0.5, 5, 0.8) + np.random.normal(0, 0.01, x.shape[0]) gauss1 = GaussianModel(prefix='g1_') pars = gauss1.guess(y, x=x) pars['g1_amplitude'].set(-0.9) pars['g1_center'].set(2.5) pars['g1_sigma'].set(0.5) gauss2 = GaussianModel(prefix='g2_') pars.update(gauss2.make_params()) pars['g2_amplitude'].set(-0.4) pars['g2_center'].set(5) pars['g2_sigma'].set(0.5) mod = gauss1 + gauss2 init = mod.eval(pars, x=x) plt.plot(x, y) plt.plot(x, init, 'k--') out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.5)) plt.plot(x, out.best_fit, 'r-') plt.show()
def fit_profile(profile, guess): "Fit a profile to a Gaussian + Contant" x = np.arange(len(profile)) model = GaussianModel(missing='drop') + ConstantModel(missing='drop') result = model.fit(profile, x=x, verbose=False, **guess) return result
def gaussian(x, y): # Gaussian fit to a curve x_shifted = x - x.min() # Shifting to 0 y_shifted = y - y.min() # Shifting to 0 mod = GaussianModel() # Setting model type pars = mod.guess(y_shifted, x=x_shifted) # Estimating fit out = mod.fit(y_shifted, pars, x=x_shifted) # Fitting fit print(out.fit_report(min_correl=0.25)) # Outputting best fit results #print("Gaussian FWHM = ", out.params['fwhm'].value) # Outputting only FWHM out.plot() # Plotting fit std = np.std(x_shifted) mux = np.mean(x_shifted) h_y = np.max(out.best_fit) #print(std, mux, h_y) y_x = h_y/2 x_i = mux - np.sqrt(2*(std**2)* np.log((np.sqrt(2*np.pi)*y_x*std)/ (h_y))) x_f = mux + np.sqrt(2*(std**2)* np.log((np.sqrt(2*np.pi)*y_x*std)/ (h_y))) fwhm = x_f-x_i print(x_i, x_f, 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 fit_and_plot_scan(self): # self.ui.result_textBrowser.append("Starting Scan Fitting") print("Starting Scan Fitting") try: """Define starting and stopping wavelength values here""" start_nm = int(self.ui.start_nm_spinBox.value()) stop_nm = int(self.ui.stop_nm_spinBox.value()) ref = self.bck_file index = (ref[:, 0] > start_nm) & (ref[:, 0] < stop_nm) x = self.wavelengths x = x[index] data_array = self.intensities result_dict = {} for i in range(data_array.shape[0]): y = data_array[i, index] # intensity yref = ref[index, 1] y = y - yref # background correction y = y - np.mean( y[(x > start_nm) & (x < start_nm + 25)]) # removing any remaining bckgrnd gmodel = GaussianModel(prefix='g1_') # calling gaussian model pars = gmodel.guess(y, x=x) # parameters - center, width, height result = gmodel.fit(y, pars, x=x, nan_policy='propagate') result_dict["result_" + str(i)] = result # self.ui.result_textBrowser.append("Scan Fitting Complete!") print("Scan Fitting Complete!") filename = QtWidgets.QFileDialog.getSaveFileName(self) pickle.dump(result_dict, open(filename[0] + "_fit_result_dict.pkl", "wb")) # self.ui.result_textBrowser.append("Data Saved!") print("Data Saved!") except Exception as e: self.ui.result_textBrowser2.append(str(e)) pass # self.ui.result_textBrowser.append("Loading Fit Data and Plotting") print("Loading Fit Data and Plotting") try: self.fit_scan_file = pickle.load( open(filename[0] + "_fit_result_dict.pkl", 'rb')) self.plot_fit_scan() except Exception as e: self.ui.result_textBrowser2.append(str(e)) pass
def gaussian_model(self): composite_model = None composite_pars = None x, y = self.background_correction() for i in range(self.num_of_gaussians): model = GaussianModel(prefix='g' + str(i + 1) + '_') if composite_pars is None: composite_pars = model.guess(y, x=x) # composite_pars = model.make_params() else: composite_pars.update(model.make_params()) if composite_model is None: composite_model = model else: composite_model += model result = composite_model.fit(y, composite_pars, x=x, nan_policy='propagate') return result
def test_default_inputs_gauss(): area = 1 cen = 0 std = 0.2 x = np.arange(-3, 3, 0.01) y = gaussian(x, area, cen, std) g = GaussianModel() fit_option1 = {'maxfev': 5000, 'xtol': 1e-2} result1 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option1) fit_option2 = {'maxfev': 5000, 'xtol': 1e-6} result2 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option2) assert result1.values != result2.values
def lmfit_ngauss(x, y, *params): params = params[0] mods = [] prefixes = [] for i in range(0, len(params), 3): pref = "g%02i_" % (i / 3) gauss_i = GaussianModel(prefix=pref) if i == 0: pars = gauss_i.guess(y, x=x) else: pars.update(gauss_i.make_params()) A = params[i] l_cen = params[i + 1] sigma = params[i + 2] pars[pref + 'amplitude'].set(A) pars[pref + 'center'].set(l_cen) pars[pref + 'sigma'].set(sigma) mods.append(gauss_i) prefixes.append(pref) mod = mods[0] if len(mods) > 1: for m in mods[1:]: mod += m print mod init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) return mod, out, init
def gaussFitFunction(fitOut,minimum,maximum,ptNumber=100,prefix=None): x = np.linspace(minimum,maximum,ptNumber) gaussian = GaussianModel() if prefix==None: params = fitOut.best_values else: params = getKeysWithoutPrefix(fitOut.best_values,prefix) gauss = gaussian.func(x=x,center=params["center"],sigma=params["sigma"],amplitude=params["amplitude"]) return x, gauss
def fit(les_x_init, les_y_init, remove): les_x = [] les_y = [] for i in range(len(les_x_init)): if les_x_init[i] not in remove: les_x.append(les_x_init[i]) les_y.append(les_y_init[i]) x = scipy.asarray(les_x) y = scipy.asarray(les_y) gmod = GaussianModel() param = gmod.guess(y, x=x) amplitude = param['amplitude'].value center = param['center'].value sigma = param['sigma'].value the_fit = gmod.fit(y, x=x, amplitude=amplitude, center=center, sigma=sigma) best_res = the_fit.chisqr amplitude = the_fit.params['amplitude'].value center = the_fit.params['center'].value sigma = the_fit.params['sigma'].value best_sol = [amplitude, center, sigma] y_fit = [] for i in range(len(les_x_init)): y_fit.append( gmod.eval(x=les_x_init[i], amplitude=amplitude, center=center, sigma=sigma)) return [best_sol, best_res, y_fit]
def peakFit(self, x, y, model = 'gau', pi = None, di = None): ti = time.time() if pi: NumPeaks = len(pi) center = [] fwhm = [] amp = [] numVal = len(x) for i in range(NumPeaks): pImin = pi[i]-di if pImin < 0: pImin = 0 pImax = pi[i] + di if pImax > (numVal-1): pImax = numVal-1 __y = y[pImin:pImax] __x = x[pImin:pImax] __y = np.power(10,__y/10) #np.array(y)- np.min(y) mod = GaussianModel() pars = mod.guess(__y, x=__x) out = mod.fit(__y, pars, x=__x) center.append(out.best_values['center']) fwhm.append(out.best_values['sigma']*2.3548) amp.append(out.best_values['amplitude']) #print 'fit:', time.time()-ti return center, fwhm ,amp
def refine_energies(self, frame_width: int = 20) -> List[Tuple[float, Any]]: """ Refine energy locations using curve fitting. For every peak in `.energies`, a small slice of the data around it is curve fitted to a gaussian and the center used as the refined energy location. Will set the property `.refined_energies` equal to function output Note: The detector energy channel is a `float` here Parameters: frame_width (int): The width of the slice of data around the peak used for curve fitting Returns: (List[Tuple[float, Any]]): List of energy locations as tuple (detector energy channel, actual energy) """ model = GaussianModel() refined = [] for energy in self.energies: domain = (int(max(energy[0] - frame_width / 2, 0)), int( min(energy[0] + frame_width / 2, self.data.shape[0] - 1))) frame = self.data[domain[0]:domain[1]] pars = model.guess(frame, x=np.arange(0, 20)) out = model.fit(frame, pars, x=np.arange(0, 20)) refined.append((out.params["center"].value + domain[0], energy[1])) self.refined_energies = refined self.polynomial_coefficients = None return refined
def test_lmfit(): """ load data """ wave, flux, flux_err = np.loadtxt( '/hydrogen/projects/song/delCep_order20.dat').T flux_sine = 1 - flux flux_sine = flux_sine * sinebell_like(flux, 1.0) flux_obs = flux_sine + np.random.randn(*flux_sine.shape) * 0.1 wave_mod = wave wave_obs = wave flux_mod = flux_sine rv_grid = np.linspace(-500, 500, 1000) # z_grid = rv_grid / constants.c.value * 1000 ccfv = xcorr_rvgrid(wave_obs, flux_obs, wave_mod, flux_mod, mask_obs=None, rv_grid=rv_grid, sinebell_idx=1) # Gaussian fit using LMFIT from lmfit.models import GaussianModel mod = GaussianModel() x, y = ccfv[0], ccfv[1] # pars = mod.guess(y, x=x) out = mod.fit(y, None, x=x, method="least_squares") # out = mod.fit(y, pars, x=x, method="leastsq") plt.figure() plt.plot(x, y) plt.plot(x, out.best_fit) print(out.fit_report())
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 find_fraunhofer_center(field: np.ndarray, ic: np.ndarray, debug: bool = False) -> float: """Extract the field at which the Fraunhofer is centered. Parameters ---------- field : np.ndarray 1D array of the magnetic field applied of the JJ. ic : np.ndarray 1D array of the JJ critical current. Returns ------- float Field at which the center of the pattern is located. """ max_loc = np.argmax(ic) width, *_ = peak_widths(ic, [max_loc], rel_height=0.5) width_index = int(round(width[0] * 0.65)) subset_field = field[max_loc - width_index:max_loc + width_index + 1] subset_ic = ic[max_loc - width_index:max_loc + width_index + 1] model = GaussianModel() params = model.guess(subset_ic, subset_field) out = model.fit(subset_ic, params, x=subset_field) if debug: plt.figure() plt.plot(field, ic) plt.plot(subset_field, out.best_fit) plt.show() return out.best_values["center"]
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 _fit_gauss(xval, yval): model = GaussianModel() result = model.fit(yval, model.guess(yval, x=xval, amplitude=np.max(yval)), x=xval) return result
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 gauss_peak_fit(energy_data, cnts_data, energy_spectrum, channel_width): ''' spectrum_gauss_fit takes an input spectrum and finds the peaks of the spectrum and fits a gaussian curve to the photopeaks and returns the amplitude and sigma of the gaussian peak. Make sure the spectrum is calibrated first. sigma_list, amplitude_list = spectrum_gauss_fit(energy_data, cnts_data, energy_spectrum, channel_width) energy_data: .energies_kev that has been calibrated from becquerel cnts_data: .cps_vals from becquerel spectrum energy_spectrum: an array of gamma energies generated from gamma_energies channel_width: width of the peak for analysis purposes ''' sigma_list = [] amplitude_list = [] for erg in energy_spectrum: x_loc = list( filter(lambda x: (erg - 3) < energy_data[x] < (erg + 3), range(len(energy_data)))) x_loc_pk = range(int(x_loc[0] - 5), int(x_loc[0] + 5)) pk_cnt = np.argmax(cnts_data[x_loc_pk]) ch_width = range(int(x_loc_pk[pk_cnt] - channel_width), int(x_loc_pk[pk_cnt] + channel_width)) calibration = energy_data[ch_width] real_y_gauss = cnts_data[ch_width] x = np.asarray(calibration) real_y = np.asarray(real_y_gauss) mod_gauss = GaussianModel(prefix='g1_') line_mod = LinearModel(prefix='line') pars = mod_gauss.guess(real_y, x=x) pars.update(line_mod.make_params(intercept=real_y.min(), slope=0)) pars.update(mod_gauss.make_params()) pars['g1_center'].set(x[np.argmax(real_y)], min=x[np.argmax(real_y)]\ - 3) pars['g1_sigma'].set(3, min=0.25) pars['g1_amplitude'].set(max(real_y), min=max(real_y) - 10) mod = mod_gauss + line_mod out = mod.fit(real_y, pars, x=x) #print("The amplitude sum is %0.2f" % sum(real_y)) gauss_x = [] gauss_y = [] parameter_list_1 = [] real_y_gauss = [] #print(out.fit_report(min_correl=10)) sigma = out.params['g1_sigma'].value amplitude = out.params['g1_amplitude'].value sigma_list.append(sigma) amplitude_list.append(amplitude) fit_params = {} #gauss_fit_parameters = [out.params[key].value for k in out.params] #print(key, "=", out.params[key].value, "+/-", out.params[key].stderr) gauss_fit_parameters = [] return sigma_list, amplitude_list
def call_gauss(x, y, cen, count, pars): label='g'+str(count)+'_' gauss = GaussianModel(prefix=label) pars.update(gauss.make_params()) pars[label+'center'].set(cen, min=cen-0.01, max=cen+0.01) pars[label+'amplitude'].set(-0.5, min=-10., max=0.0001) pars[label+'sigma'].set(0.1, min=0.005, max=0.25) return gauss
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 call_gauss(x, y, cen, count, pars): label='g'+str(count)+'_' gauss = GaussianModel(prefix=label) pars.update(gauss.make_params()) pars[label+'center'].set(cen, min=cen-0.01, max=cen+0.01) pars[label+'amplitude'].set(0, min=-(max(y)-min(y))*1.5, max=0.0001) pars[label+'sigma'].set(fw_set/4, min=0.005, max=fw_set/2.3548) return gauss
def get_plume_gaussian_model(dat, img_width): '''returns a single gaussian fit for the pd series provided dat = horizontal row of plume time average df''' mod = GaussianModel() pars = mod.guess(dat, x=img_width) # guesses starting value for gaussian out = mod.fit(dat, pars, x=img_width) # finds best fit of gaussian return out
def label_diff_lmfit(label1, label2, bins='auto', bin_std=3, plot=False, emcee=True): label1 = np.array(label1) label2 = np.array(label2) assert label1.shape == label2.shape n_obs, n_dim = label1.shape amp = np.zeros((n_dim, ), dtype=float) bias = np.zeros((n_dim, ), dtype=float) scatter = np.zeros((n_dim, ), dtype=float) frs = np.zeros((n_dim, ), dtype=object) for i_dim in range(n_dim): data = label2[:, i_dim] - label1[:, i_dim] theta, frs[i_dim] = \ gfit_bin_lmfit(data, bins=bins, bin_std=bin_std, plot=False) amp[i_dim], bias[i_dim], scatter[i_dim] = theta params = [fr.params for fr in frs] if emcee: frs = Parallel(n_jobs=-1)( delayed(run_mcmc)(fr, steps=1000, nwalkers=50, burn=300, workers=1) for fr in frs) for i_dim in range(n_dim): bias[i_dim] = np.median(frs[i_dim].mcmc.flatchain["center"]) scatter[i_dim] = np.median(frs[i_dim].mcmc.flatchain["sigma"]) params = [fr.mcmc.params for fr in frs] histdata = [] if plot: gm = GaussianModel() fig = plt.figure(figsize=(3 * n_dim, 4)) for i_dim in range(n_dim): ax = fig.add_subplot(1, n_dim, i_dim + 1) data = label2[:, i_dim] - label1[:, i_dim] # binned statistics if bins == 'robust': bins = np.arange(np.min(data), np.max(data), np.std(data) / bin_std) hist, bin_edges = np.histogram(data, bins=bins) histdata.append((hist, bin_edges, data)) # bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2 # bin_xx = np.linspace(bin_edges[0], bin_edges[-1], 100) ax.hist(data, bins=bin_edges, histtype='step') ax.plot(bin_edges, gm.eval(params[i_dim], x=bin_edges)) ax.set_title("{:5f}+-{:5f}".format(bias[i_dim], scatter[i_dim])) else: for i_dim in range(n_dim): data = label2[:, i_dim] - label1[:, i_dim] hist, bin_edges = np.histogram(data, bins=bins) histdata.append((hist, bin_edges, data)) return bias, scatter, frs, histdata
def fitSimpleHist(array, title='E5XX', nbins=25, xlabel='mytit', verbose=False, savedir=None, fileappendix='', ax=None): """ Simple Gaussian fit to an array of datapoints. Output can be saved to file if wanted Input Argument: array -- np.array of input points title -- title of graph. Will also be the filename nbins -- number of histogram bins xlabel -- label on x-axis verbose -- T/F print the fit report savedir -- Directory to save output to, if not specified nothing will be saved. Suggest os.getcwd() or '.' fileappendix -- will add "_fileappendix" to the filename specified by title. """ gausfit = GaussianModel() if (ax == None): fig, ax = plt.subplots(figsize=(15, 3), nrows=1, ncols=1) redarray = array[array >= (array.mean() - 5 * array.std() )] # and array<= (array.mean()+ 5*array.std())] n, bins, patches = ax.hist( redarray[redarray <= array.mean() + 5 * array.std()], nbins) cbins = np.zeros(len(bins) - 1) for k in (range(0, len(bins) - 1)): cbins[k] = (bins[k] + bins[k + 1]) / 2 pars = gausfit.guess(n, x=cbins) fitresult = gausfit.fit(n, pars, x=cbins) if (verbose): print(fitresult.fit_report()) ax.plot(cbins, fitresult.best_fit, 'r-', linewidth=2) mean = fitresult.best_values['center'] fwhm = 2.35 * fitresult.best_values['sigma'] textstring = ' Mean : ' + '{:4.3f}'.format(mean) + '\n' textstring += ' FWHM : ' + '{:4.3f}'.format(fwhm) props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) ax.text(0.05, 0.95, textstring, transform=ax.transAxes, fontsize=14, verticalalignment='top', bbox=props) ax.set_xlabel(xlabel) ax.set_ylabel('Frequency') ax.set_title(title) if savedir != None: filename = os.path.join(savedir, title) if (fileappendix != ''): filename += '_' + fileappendix filename += '.png' plt.savefig(filename, dpi=200, bbox_inches='tight') # plt.show() # return return fitresult
def fit_gaussian(self, array_x, array_y, figure_number): mod = GaussianModel() pars = mod.guess(array_y, x=array_x) out = mod.fit(array_y, pars, x=array_x) self.sigma_temp = out.params['sigma'].value self.amplitude_temp = out.params['amplitude'].value self.center_temp = out.params['center'].value self.plot_fit_function(array_x, figure_number) return self.sigma_temp, self.amplitude_temp, self.center_temp
def test_guess_requires_x(): """Regression test for GH #747.""" x = np.arange(100) y = np.exp(-(x - 50)**2 / (2 * 10**2)) mod = GaussianModel() msg = r"guess\(\) missing 1 required positional argument: 'x'" with pytest.raises(TypeError, match=msg): mod.guess(y)
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 test_report_modelpars(fitresult): """Verify that model_values are shown when modelpars are given.""" model = GaussianModel() params = model.make_params(amplitude=35, center=7, sigma=0.9) report_split = fitresult.fit_report(modelpars=params).split('\n') indices = [i for i, val in enumerate(report_split) if ('sigma:' in val or 'center:' in val or 'amplitude:' in val)] for indx in indices: assert 'model_value' in report_split[indx]
def gaussian_model_w_lims(self, peak_pos, sigma, min_max_range): x, y = self.background_correction() gmodel = GaussianModel(prefix='g1_') # calling gaussian model pars = gmodel.guess(y, x=x) # parameters - center, width, height pars['g1_center'].set(peak_pos, min=min_max_range[0], max=min_max_range[1]) pars['g1_sigma'].set(sigma) result = gmodel.fit(y, pars, x=x, nan_policy='propagate') return result #770 760 780 sigma 15
def fit_gaussian(self): mod = GaussianModel() pars = mod.guess(self.result[:, 1], x=self.result[:, 0]) out = mod.fit(self.result[:, 1], pars, x=self.result[:, 0]) self.sigma = out.params['sigma'].value self.amp = out.params['amplitude'].value self.center = out.params['center'].value print('sigma:' + str(self.sigma), 'amp:' + str(self.amp), 'center' + str(self.center)) self.plot_fit_function(1) return self.sigma, self.amp, self.center
def gauss_shoulder(self, fitv, par_g: list, bounds_g: list, Ng: int = 1): gauss2 = GaussianModel(prefix='g' + str(Ng) + '_') pars = fitv.params pars.update(gauss2.make_params()) for k, p, b in zip(gauss2.param_names, par_g, bounds_g): pars[k].set(value=p, min=b[0], max=b[1]) mod = fitv.model + gauss2 return self.finish_fit(self, mod, pars)
def gauss_mod(N): ''' Returns a model consisting of N gaussian curves ''' # initialize model model = GaussianModel(prefix='gau1_') # Add N-1 gaussians for i in range(N - 1): model += GaussianModel(prefix='gau' + str(i + 2) + '_') return model
def SPErough(data, n_channel_s): fit_input, bins, check = SPE_input(data) amplitude = get_amp(data) gauss = GaussianModel(prefix='g_') s, bins = np.histogram(amplitude, bins=bins) topnoise = fit_input[0] valley = fit_input[1] endvalley = fit_input[2] spebump = fit_input[3] endbin = fit_input[4] idx_1 = endvalley idx_2 = spebump + (spebump-endvalley) if idx_1 < endvalley: idx_1 = endvalley if idx_2 > endbin: idx_2 = endbin if check == 1: gauss.set_param_hint('g_height', value=s[spebump], min=s[spebump]-30, max=s[spebump]+30) gauss.set_param_hint('g_center', value=bins[spebump], min=bins[spebump]-30, max=bins[spebump]+30) gauss.set_param_hint('g_sigma', value=idx_2-idx_1, max=(idx_2-idx_1)+30) result = gauss.fit(s[idx_1:idx_2], x=bins[idx_1:idx_2], weights=1.0/np.sqrt(s[idx_1:idx_2])) else: gauss = 0 result = 0 return gauss, result
def gaussian_fit(x, y, title_name): mod = GaussianModel() pars = mod.guess(y, x=x) out = mod.fit(y, pars, x=x) plt.figure() plt.plot(x, y) plt.plot(x, out.best_fit, 'r-') plt.title(title_name) print(out.fit_report(min_correl = 0.25)) print('Center at ' + str(out.best_values['center']) + ' Angstrom') plt.show()
def get_gaussianmodel(amplitude=1.0, center=5.0, sigma=1.0, noise=0.1): # create data to be fitted np.random.seed(7392) x = np.linspace(-20, 20, 201) y = gaussian(x, amplitude, center=center, sigma=sigma) y = y + np.random.normal(size=len(x), scale=noise) model = GaussianModel() params = model.make_params(amplitude=amplitude/5.0, center=center-1.0, sigma=sigma*2.0) return x, y, model, params
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' eknown = xray_line(elem, family)[0]/1000.0 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] 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 gaussian_fit(x, y, title_name): mod = GaussianModel() pars = mod.guess(y, x=x) #pars = mod.make_params(amplitude = -2000, sigma = 1, center = 6562.801) out = mod.fit(y, pars, x=x) plt.figure() plt.plot(x, y) plt.plot(x, out.best_fit, 'r-') plt.title(title_name) print(out.fit_report(min_correl = 0.25)) print('Center at ' + str(out.best_values['center']) + ' Angstrom') plt.show()
def fluxError(counts, wavelength, error, continuum): flux_vector = [] E_W_vector = [] cont_avg = np.mean(continuum) #plt.close('all') for i in range(100): #plt.errorbar(wavelength, counts, yerr=error) new_counts=[] j = 0 for point in counts: new_counts.append(np.random.normal(point, error[j])) j = j + 1 new_counts = np.array(new_counts) #So for each N in 1000 a new counts vector is generated randomly #Take this data against the wavelength values and fit a gaussian #each time to compute the flux. Append this to a vector and then #find the standard deviation to get the flux error for that emission line #Note this is to be encorporated in the fitLines module so that each of the emission #lines is fit in turn. Next step here is to construct the model with lmfit, #guess the initial parameters and then fit the gaussian and take #out.best_values('amplitude') as the flux and store in flux_vector #Now use the lmfit package to perform gaussian fits to the data #Construct the gaussian model mod = GaussianModel() #Take an initial guess at what the model parameters are #In this case the gaussian model has three parameters, #Which are amplitude, center and sigma pars = mod.guess(new_counts, x=wavelength) #We know from the redshift what the center of the gaussian is, set this #And choose the option not to vary this parameter #Leave the guessed values of the other parameters pars['center'].set(value = np.mean(wavelength)) #Now perform the fit to the data using the set and guessed parameters #And the inverse variance weights form the fits file out = mod.fit(new_counts, pars, x=wavelength) flux = out.best_values['amplitude'] E_W = out.best_values['amplitude'] / cont_avg flux_vector.append(flux) E_W_vector.append(E_W) #plt.scatter(wavelength, new_counts) #plt.plot(wavelength, out.best_fit) print 'Hello', flux_vector #Now return the standard deviation of the flux_vector as the flux error return {'flux_error' : np.std(flux_vector), 'E_W_error' : np.std(E_W_vector)}
def fit_gaussian(y,x): x=array(x) y=array(y) mod=GaussianModel() pars=mod.guess(y,x=x) result=mod.fit(y,pars,x=x) a=result.params['amplitude'].value b=result.params['center'].value c=result.params['sigma'].value best=result.best_fit chsqred=result.redchi chisq=result.chisqr fwhm=result.params['fwhm'].value return a,b,c,best,fwhm,chisq,chsqred
def peakFit(self, x, y): if len(x) == 0: y = self.getdBmSpec() y = y[self.__scalePos] x = self.__scaledWavelength y = np.power(10,y/10) mod = GaussianModel() pars = mod.guess(y, x=x) out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.25)) center = out.best_values['center'] fwhm = out.best_values['sigma']*2.3548 return center, fwhm#, amp
def lmfit_ngauss_constrains(x,y, params, constrains): """ INPUT: x - is the wavelength array y - is the normalized flux params - is a list/array of initial guess values for the parameters (this controls the number of gaussians to be fitted number of gaussians: len(params)/3 - 3 parameters per Gaussian) contrains - the limits of the constrains for the fit of the parameters OUTPUT: mod - the lmfit model object used for the fit out - the lmfit fit object that contains all the results of the fit init- array with the initial guess model (usefull to see the initial guess when plotting) """ mods = [] prefixes = [] for i in range(0, len(params), 3): pref = "g%02i_" % (i/3) gauss_i = GaussianModel(prefix=pref) if i == 0: pars = gauss_i.guess(y, x=x) else: pars.update(gauss_i.make_params()) A = params[i] limA = constrains[i] l_cen = params[i+1] limL = constrains[i+1] sigma = params[i+2] limS = constrains[i+2] pars[pref+'amplitude'].set(A, min=limA[0], max=limA[1]) pars[pref+'center'].set(l_cen, min=limL[0], max=limL[1]) pars[pref+'sigma'].set(sigma, min=limS[0], max=limS[1]) mods.append(gauss_i) prefixes.append(pref) mod = mods[0] if len(mods) > 1: for m in mods[1:]: mod += m init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) return mod, out, init
def test_default_inputs_gauss(): area = 1 cen = 0 std = 0.2 x = np.arange(-3, 3, 0.01) y = gaussian(x, area, cen, std) g = GaussianModel() fit_option1 = {'maxfev': 5000, 'xtol': 1e-2} result1 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option1) fit_option2 = {'maxfev': 5000, 'xtol': 1e-6} result2 = g.fit(y, x=x, amplitude=1, center=0, sigma=0.5, fit_kws=fit_option2) assert_true(result1.values!=result2.values) return
def test_itercb(): x = np.linspace(0, 20, 401) y = gaussian(x, amplitude=24.56, center=7.6543, sigma=1.23) y = y - .20*x + 3.333 + np.random.normal(scale=0.23, size=len(x)) mod = GaussianModel(prefix='peak_') + LinearModel(prefix='bkg_') pars = mod.make_params(peak_amplitude=21.0, peak_center=7.0, peak_sigma=2.0, bkg_intercept=2, bkg_slope=0.0) out = mod.fit(y, pars, x=x, iter_cb=per_iteration) assert(out.nfev == 23) assert(out.aborted) assert(not out.errorbars) assert(not out.success)
def create_model_params(x, y): """Create the model and parameters.""" exp_mod = ExponentialModel(prefix='exp_') params = exp_mod.guess(y, x=x) gauss1 = GaussianModel(prefix='g1_') params.update(gauss1.make_params()) gauss2 = GaussianModel(prefix='g2_') params.update(gauss2.make_params()) params['g1_center'].set(value=105, min=75, max=125) params['g1_sigma'].set(value=15, min=3) params['g1_amplitude'].set(value=2000, min=10) params['g2_center'].set(value=155, min=125, max=175) params['g2_sigma'].set(value=15, min=3) params['g2_amplitude'].set(value=2000, min=10) model = gauss1 + gauss2 + exp_mod return model, params
def fitTwoGaussians(x,y): background = PolynomialModel(2) pars = background.make_params() peak1 = GaussianModel(prefix='p1_') pars.update( peak1.make_params()) peak2 = GaussianModel(prefix='p2_') pars.update( peak2.make_params()) # Guess some parameters from data to help the fitting span = max(x)-min(x) c1Guess = (y[-1]-y[0])/(x[-1]-x[0]) c0Guess = y[0]-c1Guess*x[0] bgGuess = background.func(x=x,c0=c0Guess,c1=c1Guess,c2=0.) signalGuess=min(y-bgGuess) sigmaGuess = span/30. amplitudeGuess = signalGuess*(sigmaGuess*np.sqrt(2.0*np.pi)) # Fit variables initialization # pars.add('splitting',0.0001,max=span) pars['c2'].set(0.,min=-0.000001,max=0.001) pars['c1'].set(c1Guess) pars['c0'].set(c0Guess) pars['p1_center'].set(min(x)+span*0.35,min=min(x),max=max(x)) pars['p2_center'].set(min(x)+span*0.55,min=min(x),max=max(x)) # pars['p2_center'].set(min(x)+span*0.65,expr='p1_center+splitting') pars['p1_amplitude'].set(amplitudeGuess,max=amplitudeGuess/10000.) pars['p2_amplitude'].set(amplitudeGuess,max=amplitudeGuess/10000.) pars['p1_sigma'].set(sigmaGuess, min=sigmaGuess/100.,max=sigmaGuess*10000.) pars['p2_sigma'].set(sigmaGuess, min=sigmaGuess/100.,max=sigmaGuess*10000.) #Add some useful parameters to evaluate pars.add('p1_signal', expr='p1_amplitude/(p1_sigma*sqrt(2.0*pi))') pars.add('p2_signal', expr='p2_amplitude/(p2_sigma*sqrt(2.0*pi))') pars.add('p1_contrast', expr='-p1_amplitude/(p1_sigma*sqrt(2.0*pi)*(c0+c1*p1_center+c2*p1_center**2))') pars.add('p2_contrast', expr='-p2_amplitude/(p2_sigma*sqrt(2.0*pi)*(c0+c1*p2_center+c2*p2_center**2))') pars.add('splitting',pars['p2_center']-pars['p1_center'],expr='p2_center-p1_center',min=0.00001) model = peak1 + peak2 + background init = model.eval(pars, x=x) out = model.fit(y, pars, x=x) # print out.fit_report() return init,out
def gaussian_fit(x, y, bounds=None): """Fit a gaussian background to `field` in `scan` Parameters ---------- x : array independent variable y : array dependent variable bounds : iterable The +/- range to fit the data to Returns ------- fit : lmfit.model.ModelFit The results of fitting the data to a gaussian peak Examples -------- >>> fit = fit_gaussian(scan.scan_data) >>> fit.plot() """ gaussian = GaussianModel() center = x[np.argmax(y)] if bounds is None: lower, upper = 0, len(x) else: lower = center - bounds upper = center + bounds if lower < 0: lower = 0 if upper > len(x): upper = len(x) bounds = slice(lower, upper) y = y[bounds] x = x[bounds] gaussian_params = gaussian.guess(y, x=x, center=center) model = gaussian return model.fit(y, x=x, params=gaussian_params)
def GaussConst(signal, guess): """ Fits a Gaussian function Plots fwhm and 2*sigma gap widths for comparison with the analytically calculated one """ 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-', label="Sigma * 2") pl.plot(np.repeat(centr - fwhm * 2.3548 / 2., len(Y)), np.arange(len(Y)), 'y--') pl.plot(np.repeat(centr + fwhm * 2.3548 / 2., len(Y)), np.arange(len(Y)), 'y--', label="FWHM") return X, result.best_fit, result.best_values['gauss_sigma'] * 4, centr
def measure_line_index_recover_spectrum(wave, params, norm=False): """ recover the fitted line profile from params Parameters ---------- wave: array-like the wavelength to which the recovered flux correspond params: 5-element tuple the 1 to 5 elements are: mod_linear_slope mod_linear_intercept mod_gauss_amplitude mod_gauss_center mod_gauss_sigma norm: bool if True, linear model (continuum) is deprecated else linear + Gaussian model is used """ from lmfit.models import LinearModel, GaussianModel mod_linear = LinearModel(prefix='mod_linear_') mod_gauss = GaussianModel(prefix='mod_gauss_') par_linear = mod_linear.make_params() par_gauss = mod_gauss.make_params() par_linear['mod_linear_slope'].value = params[0] par_linear['mod_linear_intercept'].value = params[1] par_gauss['mod_gauss_amplitude'].value = params[2] par_gauss['mod_gauss_center'].value = params[3] par_gauss['mod_gauss_sigma'].value = params[4] if not norm: flux = 1 - mod_gauss.eval(params=par_gauss, x=wave) else: flux = \ (1 - mod_gauss.eval(params=par_gauss, x=wave)) * \ mod_linear.eval(params=par_linear, x=wave) return flux
def lmfit_ngauss_constrains(x,y, params, constrains): #params = params[0] #constrains = constrains[0] mods = [] prefixes = [] for i in range(0, len(params), 3): pref = "g%02i_" % (i/3) gauss_i = GaussianModel(prefix=pref) if i == 0: pars = gauss_i.guess(y, x=x) else: pars.update(gauss_i.make_params()) A = params[i] limA = constrains[i] l_cen = params[i+1] limL = constrains[i+1] sigma = params[i+2] limS = constrains[i+2] pars[pref+'amplitude'].set(A, min=limA[0], max=limA[1]) pars[pref+'center'].set(l_cen, min=limL[0], max=limL[1]) pars[pref+'sigma'].set(sigma, min=limS[0], max=limS[1]) mods.append(gauss_i) prefixes.append(pref) mod = mods[0] if len(mods) > 1: for m in mods[1:]: mod += m init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) return mod, out, init
def test_reports_created(): """do a simple Model fit but with all the bells-and-whistles and verify that the reports are created """ x = np.linspace(0, 12, 601) data = gaussian(x, amplitude=36.4, center=6.70, sigma=0.88) data = data + np.random.normal(size=len(x), scale=3.2) model = GaussianModel() params = model.make_params(amplitude=50, center=5, sigma=2) params['amplitude'].min = 0 params['sigma'].min = 0 params['sigma'].brute_step = 0.001 result = model.fit(data, params, x=x) report = result.fit_report() assert(len(report) > 500) html_params = result.params._repr_html_() assert(len(html_params) > 500) html_report = result._repr_html_() assert(len(html_report) > 1000)
def test_example_2_Gaussians_1_exp(): dat = np.loadtxt('NIST_Gauss2.dat') x = dat[:, 1] y = dat[:, 0] exp_mod = ExponentialModel(prefix='exp_') pars = exp_mod.guess(y, x=x) gauss1 = GaussianModel(prefix='g1_') pars.update(gauss1.make_params()) pars['g1_center'].set(105, min=75, max=125) pars['g1_sigma'].set(15, min=3) pars['g1_amplitude'].set(2000, min=10) gauss2 = GaussianModel(prefix='g2_') pars.update(gauss2.make_params()) pars['g2_center'].set(155, min=125, max=175) pars['g2_sigma'].set(15, min=3) pars['g2_amplitude'].set(2000, min=10) mod = gauss1 + gauss2 + exp_mod init = mod.eval(pars, x=x) plt.plot(x, y) plt.plot(x, init, 'k--') out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.5)) plt.plot(x, out.best_fit, 'r-') plt.show()
#!/usr/bin/env python # <examples/doc_builtinmodels_nistgauss.py> import matplotlib.pyplot as plt import numpy as np from lmfit.models import ExponentialModel, GaussianModel dat = np.loadtxt('NIST_Gauss2.dat') x = dat[:, 1] y = dat[:, 0] exp_mod = ExponentialModel(prefix='exp_') pars = exp_mod.guess(y, x=x) gauss1 = GaussianModel(prefix='g1_') pars.update(gauss1.make_params()) pars['g1_center'].set(105, min=75, max=125) pars['g1_sigma'].set(15, min=3) pars['g1_amplitude'].set(2000, min=10) gauss2 = GaussianModel(prefix='g2_') pars.update(gauss2.make_params()) pars['g2_center'].set(155, min=125, max=175) pars['g2_sigma'].set(15, min=3) pars['g2_amplitude'].set(2000, min=10) mod = gauss1 + gauss2 + exp_mod
def measure_line_index(wave, flux, flux_err=None, mask=None, z=None, line_info=None, num_refit=(100, None), filepath=None, return_type='dict', verbose=False): """ Measure line index / EW and have it plotted Parameters ---------- wave: array-like wavelength vector flux: array-like flux vector flux_err: array-like flux error vector (optional) If un-specified, auto-generate an np.ones array mask: array-like andmask or ormask (optional) If un-specified, auto-generate an np.ones array (evenly weighted) line_info: dict information about spectral line, eg: line_info_dib5780 = {'line_center': 5780, 'line_range': (5775, 5785), 'line_shoulder_left': (5755, 5775), 'line_shoulder_right': (5805, 5825)} num_refit: non-negative integer number of refitting. If 0, no refit will be performed If positive, refits will be performed after adding normal random noise z: float redshift (only specify when z is large) filepath: string path of the diagnostic figure if None, do nothing, else print diagnostic figure return_type: string 'dict' or 'array' if 'array', np.array(return dict.values()) verbose: bool if True, print details Returns ------- line_indx: dict A dictionary type result of line index. If any problem encountered, return the default result (filled with nan). """ try: # 0. do some input check # 0.1> check line_info line_info_keys = line_info.keys() assert 'line_range' in line_info_keys assert 'line_shoulder_left' in line_info_keys assert 'line_shoulder_right' in line_info_keys # 0.2> check line range/shoulder in spectral range assert np.min(wave) <= line_info['line_shoulder_left'][0] assert np.max(wave) >= line_info['line_shoulder_right'][0] # 1. get line information # line_center = line_info['line_center'] # not used line_range = line_info['line_range'] line_shoulder_left = line_info['line_shoulder_left'] line_shoulder_right = line_info['line_shoulder_right'] # 2. shift spectra to rest-frame wave = np.array(wave) flux = np.array(flux) if z is not None: wave /= 1. + z # 3. estimate the local continuum # 3.1> shoulder wavelength range ind_shoulder = np.any([ np.all([wave > line_shoulder_left[0], wave < line_shoulder_left[1]], axis=0), np.all([wave > line_shoulder_right[0], wave < line_shoulder_right[1]], axis=0)], axis=0) wave_shoulder = wave[ind_shoulder] flux_shoulder = flux[ind_shoulder] # 3.2> integrated/fitted wavelength range ind_range = np.logical_and(wave > line_range[0], wave < line_range[1]) wave_range = wave[ind_range] flux_range = flux[ind_range] # flux_err_range = flux_err[ind_range] # not used mask_range = mask[ind_range] flux_err_shoulder = flux_err[ind_shoulder] # mask_shoulder = mask[ind_shoulder] # not used # 4. linear model mod_linear = LinearModel(prefix='mod_linear_') par_linear = mod_linear.guess(flux_shoulder, x=wave_shoulder) # ############################################# # # to see the parameter names: # # model_linear.param_names # # {'linear_fun_intercept', 'linear_fun_slope'} # # ############################################# # out_linear = mod_linear.fit(flux_shoulder, par_linear, x=wave_shoulder, method='leastsq') # 5. estimate continuum cont_shoulder = out_linear.best_fit noise_std = np.std(flux_shoulder / cont_shoulder) cont_range = mod_linear.eval(out_linear.params, x=wave_range) resi_range = 1 - flux_range / cont_range # 6.1 Integrated EW ( # estimate EW_int wave_diff = np.diff(wave_range) wave_step = np.mean(np.vstack([np.hstack([wave_diff[0], wave_diff]), np.hstack([wave_diff, wave_diff[-1]])]), axis=0) EW_int = np.dot(resi_range, wave_step) # estimate EW_int_err num_refit_ = num_refit[0] if num_refit_ is not None and num_refit_>0: EW_int_err = np.std(np.dot( (resi_range.reshape(1, -1).repeat(num_refit_, axis=0) + np.random.randn(num_refit_, resi_range.size) * noise_std), wave_step)) # 6.2 Gaussian model # estimate EW_fit mod_gauss = GaussianModel(prefix='mod_gauss_') par_gauss = mod_gauss.guess(resi_range, x=wave_range) out_gauss = mod_gauss.fit(resi_range, par_gauss, x=wave_range) line_indx = collections.OrderedDict([ ('SN_local_flux_err', np.median(flux_shoulder / flux_err_shoulder)), ('SN_local_flux_std', 1. / noise_std), ('num_bad_pixel', np.sum(mask_range != 0)), ('EW_int', EW_int), ('EW_int_err', EW_int_err), ('mod_linear_slope', out_linear.params[mod_linear.prefix + 'slope'].value), ('mod_linear_slope_err', out_linear.params[mod_linear.prefix + 'slope'].stderr), ('mod_linear_intercept', out_linear.params[mod_linear.prefix + 'intercept'].value), ('mod_linear_intercept_err', out_linear.params[mod_linear.prefix + 'intercept'].stderr), ('mod_gauss_amplitude', out_gauss.params[mod_gauss.prefix + 'amplitude'].value), ('mod_gauss_amplitude_err', out_gauss.params[mod_gauss.prefix + 'amplitude'].stderr), ('mod_gauss_center', out_gauss.params[mod_gauss.prefix + 'center'].value), ('mod_gauss_center_err', out_gauss.params[mod_gauss.prefix + 'center'].stderr), ('mod_gauss_sigma', out_gauss.params[mod_gauss.prefix + 'sigma'].value), ('mod_gauss_sigma_err', out_gauss.params[mod_gauss.prefix + 'sigma'].stderr), ('mod_gauss_amplitude_std', np.nan), ('mod_gauss_center_std', np.nan), ('mod_gauss_sigma_std', np.nan)]) # estimate EW_fit_err num_refit_ = num_refit[1] if num_refit_ is not None and num_refit_ > 2: # {'mod_gauss_amplitude', # 'mod_gauss_center', # 'mod_gauss_fwhm', # 'mod_gauss_sigma'} out_gauss_refit_amplitude = np.zeros(num_refit_) out_gauss_refit_center = np.zeros(num_refit_) out_gauss_refit_sigma = np.zeros(num_refit_) # noise_fit = np.random.randn(num_refit,resi_range.size)*noise_std for i in range(int(num_refit_)): # resi_range_with_noise = resi_range + noise_fit[i,:] resi_range_with_noise = resi_range + \ np.random.randn(resi_range.size) * noise_std out_gauss_refit = mod_gauss.fit(resi_range_with_noise, par_gauss, x=wave_range) out_gauss_refit_amplitude[i],\ out_gauss_refit_center[i],\ out_gauss_refit_sigma[i] =\ out_gauss_refit.params[mod_gauss.prefix + 'amplitude'].value,\ out_gauss_refit.params[mod_gauss.prefix + 'center'].value,\ out_gauss_refit.params[mod_gauss.prefix + 'sigma'].value print(out_gauss_refit_amplitude[i], out_gauss_refit_center[i], out_gauss_refit_sigma[i]) line_indx.update({'mod_gauss_amplitude_std': np.nanstd(out_gauss_refit_amplitude), 'mod_gauss_center_std': np.nanstd(out_gauss_refit_center), 'mod_gauss_sigma_std': np.nanstd(out_gauss_refit_sigma)}) # 7. plot and save image if filepath is not None and os.path.exists(os.path.dirname(filepath)): save_image_line_indice(filepath, wave, flux, ind_range, cont_range, ind_shoulder, line_info) # if necessary, convert to array # NOTE: for a non-ordered dict the order of keys and values may change! if return_type == 'array': return np.array(line_indx.values()) return line_indx except Exception: return measure_line_index_null_result(return_type)
# ax_res_y2.set_yticks((ax_res.get_yticks() / 100) * yNorm) for xticklabel in ax.get_xticklabels(): xticklabel.set_visible(False) for xticklabel in axy2.get_xticklabels(): xticklabel.set_visible(False) ax.get_yticklabels()[0].set_visible(False) axy2.get_yticklabels()[0].set_visible(False) ax_res.get_yticklabels()[-1].set_visible(False) ax_res_y2.get_yticklabels()[-1].set_visible(False) if legend: ax.legend(loc='best') ax_res.set_xlabel(xlabel) ax.set_ylabel(ylabel) return fig, [ax, axy2, ax_res, ax_res_y2] if __name__ == '__main__': from functions import gaussian from lmfit.models import GaussianModel x = np.linspace(-3, 3, 200) y = gaussian(x, sigma=0.5) * (1 + np.random.normal(0, 0.1, len(x))) gmod = GaussianModel() para = gmod.guess(y, x=x) gfit = gmod.fit(y, para, x=x) models = [gfit.init_fit, gfit.best_fit] plt.close('all') fig, axes = plotResidual(x, y, models, yNorm=1.0, yThresh=0.1) axes[0].set_ylabel('relative [%]') axes[1].set_ylabel('absolute') axes[2].set_xlabel('xxx') plt.show()
from lmfit.models import GaussianModel, LorentzianModel, VoigtModel data = loadtxt('test_peak.dat') x = data[:, 0] y = data[:, 1] gamma_free = False MODEL = 'gauss' # MODEL = 'loren' # MODEL = 'voigt' # gamma_free = True if MODEL.lower().startswith('g'): mod = GaussianModel() gamma_free = False figname = '../doc/_images/models_peak1.png' elif MODEL.lower().startswith('l'): mod = LorentzianModel() gamma_free = False figname = '../doc/_images/models_peak2.png' elif MODEL.lower().startswith('v'): mod = VoigtModel() figname = '../doc/_images/models_peak3.png' pars = mod.guess(y, x=x) if gamma_free: pars['gamma'].set(value=0.7, vary=True, expr='') figname = '../doc/_images/models_peak4.png'