def gauss(x, y): print( 'Selecione a regiao do fit gaussiano quantas vezes for necessario') l1, l2 = fit_gauss(x, y) index1 = np.where(abs(x - l1) == min(abs(x - l1)))[0] index1 = np.int(index1) index2 = np.where(abs(x - l2) == min(abs(x - l2)))[0] index2 = np.int(index2) print(index1, index2) x1 = x[index1:index2] y1 = y[index1:index2] mod = GaussianModel() pars = mod.guess(y1, x=x1) out = mod.fit(y1, pars, x=x1) xgauss = copy.copy(x1) ygauss = copy.copy(out.best_fit) #-####### x0 = x[0:index1] y0 = np.zeros(len(y[0:index1])) x2 = x[index2:] y2 = np.zeros(len(y[index2:])) x1 = np.append(x0, x1) x1 = np.append(x1, x2) y1 = np.append(y0, out.best_fit) y1 = np.append(y1, y2) print(out.fit_report(min_correl=0.25)) mod = GaussianModel() pars = mod.guess(y1, x=x1) out = mod.fit(y1, pars, x=x1) #-####### return x1, out.best_fit, xgauss, ygauss
def twoPeakGaussianFit(self): try: nRow, nCol = self.dockedOpt.fileInfo() self.binFitData = np.zeros((nRow, 0)) self.TwoPkGausFitData = np.zeros((nCol, 12)) # Creates the empty 2D List for j in range(nCol): yy1 = [] yy2 = [] yy = self.dockedOpt.TT[:, j] i = 0 for y in yy: if i < len(yy) / 2: yy1.append(y) else: yy2.append(y) i += 1 xx = np.arange(0, len(yy)) xx1 = np.arange(0, len(yy) / 2) xx2 = np.arange(len(yy) / 2, len(yy)) x1 = xx[0] x2 = xx[-1] y1 = yy[0] y2 = yy[-1] m = (y2 - y1) / (x2 - x1) b = y2 - m * x2 mod1 = GaussianModel(prefix='p1_') mod2 = GaussianModel(prefix='p2_') pars1 = mod1.guess(yy1, x=xx1) pars2 = mod2.guess(yy2, x=xx2) mod = mod1 + mod2 + LinearModel() pars = pars1 + pars2 pars.add('intercept', value=b, vary=True) pars.add('slope', value=m, vary=True) out = mod.fit(yy, pars, x=xx, slope=m) self.TwoPkGausFitData[j, :] = (out.best_values['p1_amplitude'], 0, out.best_values['p1_center'], 0, out.best_values['p1_sigma'], 0, out.best_values['p2_amplitude'], 0, out.best_values['p2_center'], 0, out.best_values['p2_sigma'], 0) # Saves fitted data of each fit fitData = out.best_fit binFit = np.reshape(fitData, (len(fitData), 1)) self.binFitData = np.concatenate((self.binFitData, binFit), axis=1) if self.continueGraphingEachFit == True: self.graphEachFitRawData(xx, yy, out.best_fit, 'G') return False except Exception as ex: qtWidgets.QMessageBox.warning(self.myMainWindow, "Error", "Please make sure the guesses are realistic when fitting." "\n\nException: " + str(ex)) return True
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 fit_gaussians_to_emission_lines(spectra, centers, x=None, verbose=False): # First, sort out x if x is None: x = np.arange(spectra.shape[0]) # we know which peaks to calibrate off, we still need to fit a Gaussian to them so we can get the exact peak position instead of just the highest pixel pars = [] Model = None gaussmodel = GaussianModel(prefix='f{:}_'.format(0)) pars = gaussmodel.guess(x, spectra) pars['f{:}_center'.format(0)].set(vary=True, value=centers[0], min=centers[0] - 2, max=centers[0] + 2) pars['f{:}_amplitude'.format(0)].set( vary=True, value=0.5, ) pars['f{:}_sigma'.format(0)].set(vary=True, value=2, min=0.9, max=5) for i in range(1, centers.shape[0]): gaussmodel_ = GaussianModel(prefix='f{:}_'.format(i)) pars_ = gaussmodel_.guess(x, spectra) pars_['f{:}_center'.format(i)].set(vary=True, value=centers[i], min=centers[i] - 5, max=centers[i] + 5) pars_['f{:}_amplitude'.format(i)].set(vary=True, value=0.5) pars_['f{:}_sigma'.format(i)].set(vary=True, value=2, min=0.9, max=5) gaussmodel = gaussmodel + gaussmodel_ pars = pars + pars_ out = gaussmodel.fit(spectra, pars, x=x, method='powell') if verbose: print('Gaussians fit to spectra:') print(out.fit_report()) centers = np.array([ float(out.params['f{:}_center'.format(i)].value) for i in range(len(centers)) ]) aplitudes = np.array([ float(out.params['f{:}_amplitude'.format(i)].value) for i in range(len(centers)) ]) sigmas = np.array([ float(out.params['f{:}_sigma'.format(i)].value) for i in range(len(centers)) ]) return centers, aplitudes, sigmas, out
def fit_gauss(graph=False, cdf=False, residuals=False): xranges, yranges, xrange, yrange, filename1, dat1 = range_to_list() FitVals = DataFrame(columns=['Sigma', 'Center', 'Amplitude', 'FWHM', 'Height', 'Intercept', 'Slope', 'ChiSq', 'RedChiSq', 'Akaike', 'Bayesian']) for i in range(0, len(xranges)): mdl = GaussianModel() params = mdl.guess(data=yranges[i], x=xranges[i]) result = mdl.fit(yranges[i], params, x=xranges[i]) print(result.fit_report()) FitVals.at[i, 'Sigma'] = ufloat(result.params['sigma'].value, result.params['sigma'].stderr) FitVals.at[i, 'Center'] = ufloat(result.params['center'].value, result.params['center'].stderr) FitVals.at[i, 'Amplitude'] = ufloat(result.params['amplitude'].value, result.params['amplitude'].stderr) FitVals.at[i, 'FWHM'] = ufloat(result.params['fwhm'].value, result.params['fwhm'].stderr) FitVals.at[i, 'Height'] = ufloat(result.params['height'].value, result.params['height'].stderr) FitVals.at[i, 'ChiSq'] = result.chisqr FitVals.at[i, 'RedChiSq'] = result.redchi FitVals.at[i, 'Akaike'] = result.aic FitVals.at[i, 'Bayesian'] = result.bic if graph: plt.plot(xranges[i], yranges[i], '.', markerfacecolor="None", color='#050505', mew=1.4, ms=1, antialiased=True, label='Data from frequency sweep') plt.plot(xranges[i], result.best_fit, lw=2, label='Gaussian + Line fit') plt.legend() plt.xlabel('Frequency (Hz)') plt.ylabel('Variance (a.u)') fullscreen() plt.show() if cdf: values, base = np.histogram(yranges[i], bins='auto') cumulative = np.cumsum(values) plt.plot(base[:-1], cumulative) plt.plot(base[:-1], values) fullscreen() plt.show() if residuals: values, base = np.histogram(result.residual, bins='fd') cumulative = np.cumsum(values) # plt.plot(xranges[i], result.residual) # plt.plot(base[:-1], cumulative, '.') mdl2 = GaussianModel() params2 = mdl2.guess(data=values, x=base[:-1]) model2 = mdl2 result2 = model2.fit(values, params2, x=base[:-1]) plt.plot(base[:-1], values, '.') plt.plot(base[:-1], result2.best_fit) plt.xlabel('Residuals') plt.ylabel('Counts') fullscreen() plt.show()
def GaussCalc(x, y, x1, y1): y = removerBackground(y) y1 = removerBackground(y1) mod = GaussianModel() pars = mod.guess(y, x=x) out = mod.fit(y, pars, x=x) mod = GaussianModel() pars1 = mod.guess(y1, x=x1) out1 = mod.fit(y1, pars1, x=x1) center = out.best_values['center'] sigma = Decon_Gau(out.best_values['sigma'], out1.best_values['sigma']) return ScherrerEquation(sigma, center)
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 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 NewFit2(amp1, amp2, mu1, mu2, sig1, sig2, x, y): '==========================================' 'Define the first gaussian' gauss1 = GaussianModel(prefix='g1_') # Model first as a gaussian pars = gauss1.guess(y, x=x) # Make a gautomatic guess of the parameters 'Set the Parameters values' pars['g1_center'].set(mu1, vary=True) pars['g1_sigma'].set(sig1, vary=True) pars['g1_amplitude'].set(amp1, vary=True) '===========================================' 'Define the second Gaussian' gauss2 = GaussianModel(prefix='g2_') pars.update( gauss2.make_params()) #update the parameter list with another gaussian pars['g2_center'].set(mu2, vary=True) pars['g2_sigma'].set(sig2, vary=True) pars['g2_amplitude'].set(amp2, vary=True) '===========================================' 'Make the model as the sum of gaussians' mod = gauss1 + gauss2 'Fit and print the data' out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.5)) plt.plot(x, out.best_fit, 'r-', linewidth=1.50) plt.show() return pars
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 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_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 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 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 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_w_lims(self, peak_pos, sigma, min_max_range): #center_initial_guesses - list containing initial guesses for peak centers. [center_guess1, center_guess2] #sigma_initial_guesses - list containing initial guesses for sigma. [sigma1, sigma2] #min_max_range - list containing lists of min and max for peak center. [ [min1, max1], [min2, max2] ] x, y = self.background_correction() gmodel_1 = GaussianModel(prefix='g1_') # calling gaussian model pars = gmodel_1.guess(y, x=x) # parameters - center, width, height pars['g1_center'].set(peak_pos[0], min=min_max_range[0][0], max=min_max_range[0][1]) pars['g1_sigma'].set(sigma[0]) pars['g1_amplitude'].set(min=0) gmodel_2 = GaussianModel(prefix='g2_') pars.update(gmodel_2.make_params() ) # update parameters - center, width, height pars['g2_center'].set(peak_pos[1], min=min_max_range[1][0], max=min_max_range[1][1]) pars['g2_sigma'].set(sigma[1], min=composite_pars['g1_sigma'].value) pars['g2_amplitude'].set(min=0) gmodel = gmodel_1 + gmodel_2 result = gmodel.fit(y, pars, x=x, nan_policy='propagate') return result
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 fit(self, xx, yy, fitType): xx = np.asarray(xx) yy = np.asarray(yy) print("XX", xx) print("YY", yy) print(len(xx)) print(len(yy)) print("XX", xx) x1 = xx[0] x2 = xx[-1] y1 = yy[0] y2 = yy[-1] m = (y2 - y1) / (x2 - x1) b = y2 - m * x2 if fitType == "Gaussian": mod = GaussianModel() elif fitType == "Lorentzian": mod = LorentzianModel() else: mod = VoigtModel() pars = mod.guess(yy, x=xx, slope=m) print(pars) mod = mod + LinearModel() pars.add('intercept', value=b, vary=True) pars.add('slope', value=m, vary=True) out = mod.fit(yy, pars, x=xx) return out.best_fit
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 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 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 fit_to_gaussian(self, x, y): gmodel = GaussianModel() params = gmodel.guess(y, x=x) c = params['center'].value n = len(y) q3 = ((np.max(x) - c) / 2) + c min_x = np.min(x) q1 = ((params['center'].value - min_x) / 2) + min_x s = params['sigma'].value h = params['height'].value max_y = np.max(y) if np.max([h, max_y]) < 0.5: amp = 1 / n diff_h = 0.6 - h gmodel.set_param_hint('amplitude', value=amp) gmodel.set_param_hint('amplitude', max=amp * (1 + diff_h)) gmodel.set_param_hint('amplitude', min=amp * diff_h) gmodel.set_param_hint('center', value=c) gmodel.set_param_hint('center', max=q3) gmodel.set_param_hint('center', min=q1) gmodel.set_param_hint('sigma', value=s) gmodel.set_param_hint('sigma', min=s / 2) gmodel.set_param_hint('sigma', max=s * 1.5) gmodel.set_param_hint('height', min=0.6) result = gmodel.fit(y, x=x) # gmodel.print_param_hints() report = result.fit_report() chi_re = re.compile(r'chi-square\s+=\s+([0-9.]+)') cor_re = re.compile(r'C\(sigma, amplitude\)\s+=\s+([0-9.-]+)') chis = np.float32(chi_re.findall(report)) cors = np.float32(cor_re.findall(report)) coeffs = np.concatenate((chis, cors)) mse_model = self.assess_fit(y, result.init_fit - result.best_fit) mse_yhat = self.assess_fit(y, result.residual) return mse_model, mse_yhat, result, report, coeffs
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 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 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 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 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 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 bootg(data, flareinds, ind, st=40, end=130, indiv=False, num=100, offset=0): '''Bootstrap gaussian fit for one flare. Inputs: ------- data: sog4 flareinds: flareinds ind: index of flare to bootstrap (used to get inds from flareinds if indiv False) st: used as start index if indiv True end: used as end index if indiv True indiv: use individual index arguments (st,end) rather than ind, which then references flareinds (default False) num: number of bootstrap iterations (default 100) offset: gaussian vertical offset Outputs: -------- bsouts: list of bootstrap model results bsfits: DataFrame with parameters from each bootstrap iteration ''' if indiv: ind1, ind2 = st, end else: ind1, ind2 = flareinds[ind][0], flareinds[ind][1] bsouts = [] for i in range(num): #bootstrap indices of first flare bs = sk.resample(np.arange(ind1, ind2)) bst = np.array(data['MJD-50000'][bs]) bsi = np.array(data['I mag'][bs]) x = bst #uses original (not detrended) data y = np.max(bsi) - bsi + offset mod = GaussianModel() pars = mod.guess(y, x=x) out = mod.fit(y, pars, x=x) bsouts.append(out) bsfits = pd.DataFrame(columns=['center', 'sigma', 'fwhm', 'height', 'amp']) bsfits['center'] = np.zeros(num) #adding to DataFrame i = 0 for b in bsouts: bsfits['center'][i] = b.params['center'].value bsfits['fwhm'][i] = b.params['fwhm'].value bsfits['height'][i] = b.params['height'].value bsfits['amp'][i] = b.params['amplitude'].value bsfits['sigma'][i] = b.params['sigma'].value i += 1 #returns list of model results and DataFrame with compiled best fit parameter values return bsouts, bsfits
def fit_curve(ps_list): #--input:ps_list, (x,y) x = np.array([r[0] for r in ps_list]) y = np.array([r[1] for r in ps_list]) mod = GaussianModel() pars = mod.guess(y, x=x) bestresult = mod.fit(y, pars, x=x) return (bestresult.best_fit,x,y,getfloat_attr(bestresult, 'chisqr'),bestresult)
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 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 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 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 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 fitLines(self, flux, wavelength, z, weights): #Convert all into numpy arrays flux = np.array(flux) wavelength = np.array(wavelength) z = np.array(z) weights = np.array(weights) error = np.sqrt(1 / weights) #Fit a polynomial to the continuum background emission of the galaxy #This is the crude way to do it continuum_poly = self.fitPoly(flux, wavelength) #Can also compute the continuum in the more advanced way #masking the emission lines and using a moving average #Define the wavelength values of the relevant emission lines OII3727 = 3727.092 OII3729 = 3729.875 H_beta = 4862.721 OIII4959 = 4960.295 OIII5007 = 5008.239 H_alpha = 6564.614 NII6585 = 6585.27 SII6718 = 6718.29 SII6732 = 6732.68 #Now apply the redshift formula to find where this will be observed #Note that for these SDSS spectra the OII doublet is not in range OII3727_shifted = OII3727 * (1 + z) OII3729_shifted = OII3729 * (1 + z) H_beta_shifted = H_beta * (1 + z) OIII4959_shifted = OIII4959 * (1 + z) OIII5007_shifted = OIII5007 * (1 + z) H_alpha_shifted = H_alpha * (1 + z) NII6585_shifted = NII6585 * (1 + z) SII6718_shifted = SII6718 * (1 + z) SII6732_shifted = SII6732 * (1 + z) #hellofriend #Will choose to mask pm 15 for each of the lines H_beta_index = np.where(np.logical_and(wavelength>=(H_beta_shifted - 15), wavelength<=(H_beta_shifted + 15))) OIII_one_index = np.where(np.logical_and(wavelength>=(OIII4959_shifted - 15), wavelength<=(OIII4959_shifted + 15))) OIII_two_index = np.where(np.logical_and(wavelength>=(OIII5007_shifted - 15), wavelength<=(OIII5007_shifted + 15))) NII_one_index = np.where(np.logical_and(wavelength>=(NII6585_shifted - 15), wavelength<=(NII6585_shifted + 15))) H_alpha_index = np.where(np.logical_and(wavelength>=(H_alpha_shifted - 15), wavelength<=(H_alpha_shifted + 15))) SII_one_index = np.where(np.logical_and(wavelength>=(SII6718_shifted - 15), wavelength<=(SII6718_shifted + 15))) SII_two_index = np.where(np.logical_and(wavelength>=(SII6732_shifted - 15), wavelength<=(SII6732_shifted + 15))) #define the mask 1 values from the index values mask = np.zeros(len(flux)) mask[H_beta_index] = 1 mask[OIII_one_index] = 1 mask[OIII_two_index] = 1 mask[NII_one_index] = 1 mask[H_alpha_index] = 1 mask[SII_one_index] = 1 mask[SII_two_index] = 1 #Now apply these to the flux to mask masked_flux = ma.masked_array(flux, mask=mask) #Make my own with np.mean() continuum = np.empty(len(masked_flux)) for i in range(len(masked_flux)): if (i + 5) < len(masked_flux): continuum[i] = ma.mean(masked_flux[i:i+5]) if np.isnan(continuum[i]): continuum[i] = continuum[i - 1] else: continuum[i] = ma.mean(masked_flux[i-5:i]) if np.isnan(continuum[i]): continuum[i] = continuum[i - 1] #Subtract the continuum from the flux, just use polynomial fit right now counts = flux - continuum_poly #Construct a dictionary housing these shifted emission line values #Note that values for the OII doublet are not present line_dict = {'H_beta' : H_beta_shifted, 'OIII4959' : OIII4959_shifted, 'OIII5007' : OIII5007_shifted, 'H_alpha' : H_alpha_shifted, 'NII6585' : NII6585_shifted, 'SII6718' : SII6718_shifted, 'SII6732' : SII6732_shifted} #Plot the initial continuum subtracted spectrum plt.plot(wavelength, counts) #Initialise a dictionary for the results in the for loop results_dict = {} #Begin for loop to fit an arbitrary number of emission lines for key in line_dict: ######################################################################## #FITTING EACH OF THE EMISSION LINES IN TURN ######################################################################## #We don't want to include all the data in the gaussian fit #Look for the indices of the points closes to the wavelength value #The appropriate range is stored in fit_wavelength etc. #Use np.where to find the indices of data surrounding the gaussian new_index = np.where(np.logical_and(wavelength > (line_dict[key] - 10) , wavelength < (line_dict[key] + 10))) #Select only data for the fit with these indices fit_wavelength = wavelength[new_index] fit_counts = counts[new_index] fit_weights = weights[new_index] fit_continuum = continuum[new_index] fit_error = error[new_index] #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(fit_counts, x=fit_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 = line_dict[key]) pars['center'].set(vary = 'False') #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(fit_counts, pars, weights = fit_weights, x=fit_wavelength) #print(out.fit_report(min_correl=0.25)) #Plot the results and the spectrum to check the fit plt.plot(fit_wavelength, out.best_fit, 'r-') #Return the error on the flux error_dict = self.fluxError(fit_counts, fit_wavelength, fit_error, continuum_poly) #Compute the equivalent width con_avg = np.mean(continuum_poly) E_w = out.best_values['amplitude'] / con_avg #The amplitude parameter is the area under the curve, equivalent to the flux results_dict[key] = [out.best_values['amplitude'], error_dict['flux_error'], out.best_values['sigma'], 2.3548200*out.best_values['sigma'], E_w, error_dict['E_W_error']] plt.show() #plt.savefig('fitted_spectrum.png') #The return dictionary for this method is a sequence of results vectors return results_dict
def lmfit_mngauss(x,y, *params): """ Fit multiple gaussians from two spectra that are multiplied together INPUT: x - is the wavelength array y - is the normalized flux params - is a tuple of 2 list/arrays of initial guess values for the each spectras parameters (this controls the number of gaussians to be fitted number of gaussians: len(params)/3 - 3 parameters per Gaussian) 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) """ m_params = params[0] m_mods = [] prefixes = [] for i in range(0, len(m_params), 3): pref = "gm%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 = m_params[i] l_cen = m_params[i+1] sigma = m_params[i+2] pars[pref+'amplitude'].set(A) pars[pref+'center'].set(l_cen) pars[pref+'sigma'].set(sigma) m_mods.append(gauss_i) prefixes.append(pref) m_mod = m_mods[0] if len(m_mods) > 1: for m in m_mods[1:]: m_mod += m m_one = ConstantModel(prefix="m_one_") prefixes.append("m_one_") pars.update(m_one.make_params()) pars['m_one_c'].set(value=1, vary=False) try: n_params = params[1] n_mods = [] #prefixes = [] for j in range(0, len(n_params), 3): pref = "gn%02i_" % (j/3) gauss_j = GaussianModel(prefix=pref) pars.update(gauss_j.make_params()) A = n_params[j] l_cen = n_params[j+1] sigma = n_params[j+2] pars[pref+'amplitude'].set(A) pars[pref+'center'].set(l_cen) pars[pref+'sigma'].set(sigma) n_mods.append(gauss_j) prefixes.append(pref) n_mod = n_mods[0] if len(n_mods) > 1: for n in n_mods[1:]: n_mod += n n_one = ConstantModel(prefix="n_one_") prefixes.append("n_one_") pars.update(n_one.make_params()) pars['n_one_c'].set(value=1, vary=False) mod = (m_one + m_mod) * (n_one + n_mod) except: print("Error with second spectra, only fitting first") mod = m_one + m_mod init = mod.eval(pars, x=x) out = mod.fit(y, pars, x=x) print("Printed prefixes", prefixes) #print(init) return mod, out, init
exp_mod = ExponentialModel(prefix='exp_') gauss1 = GaussianModel(prefix='g1_') gauss2 = GaussianModel(prefix='g2_') def index_of(arrval, value): "return index of array *at or below* value " if value < min(arrval): return 0 return max(np.where(arrval<=value)[0]) ix1 = index_of(x, 75) ix2 = index_of(x, 135) ix3 = index_of(x, 175) pars1 = exp_mod.guess(y[:ix1], x=x[:ix1]) pars2 = gauss1.guess(y[ix1:ix2], x=x[ix1:ix2]) pars3 = gauss2.guess(y[ix2:ix3], x=x[ix2:ix3]) pars = pars1 + pars2 + pars3 mod = gauss1 + gauss2 + exp_mod out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.5)) plt.plot(x, y) plt.plot(x, out.init_fit, 'k--') plt.plot(x, out.best_fit, 'r-') plt.show() #<end examples/doc_nistgauss2.py>
#Module Preparing import numpy as np import matplotlib.pyplot as plt ''' 也可以使用import pylab as pl ''' from lmfit.models import GaussianModel #Read data from file data=np.loadtxt('**实验数据文件**') x=data[:,0] y=data[:,1] #Preparing the Model model=GaussianModel() pars=model.guess(y,x=x) #Do the fit result=model.fit(y,pars,x=x) #Print the fit result print(result.fit_report(min_correl=0.25)) #Draw the plot pl.plot(x,y,color='red',linestyle='--') pl.plot(x,result.best_fit,color='blue',linestyle='-') #Tobe Continue
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()
da = s / (np.pi*fac) dmu = (2. * A * (xx-mu)*s)/(np.pi * fac**2) return np.array([ds, dmu, da]) if __name__ == '__main__': xs = np.linspace(-4, 4, 100) print('**********************************') print('***** Test Gaussian **************') print('**********************************') ys = gaussian(xs, 2.5, 0, 0.5) yn = ys + 0.1*np.random.normal(size=len(xs)) mod = GaussianModel() pars = mod.guess(yn, xs) out = mod.fit(yn, pars, x=xs) out2 = mod.fit(yn, pars, x=xs, fit_kws={'Dfun': dfunc_gaussian, 'col_deriv': 1}) print('lmfit without dfunc **************') print('number of function calls: ', out.nfev) print('params', out.best_values) print('lmfit with dfunc *****************') print('number of function calls: ', out2.nfev) print('params', out2.best_values) print('\n \n') out2.plot(datafmt='.') print('**********************************') print('***** Test Lorentzian ************') print('**********************************')
cont = 3.0 # continuum level randamp = 3. # amplitude of gaussian noise x = np.arange(0,xmax) y = randamp * np.random.randn(xmax) + jrr.spec.onegaus(x, aa, bb, cc, cont) err = randamp * np.random.randn(xmax) plt.plot(x, y, color='black') # Let's try fitting that gaussian w the python version of MPFIT p0 = (50., xmax/2, 5, 2) fa = {'x':x, 'y':y, 'err':err} m = mpfit.mpfit(myfunct, p0, functkw=fa) # There has got to be a less kludgy way to do line below bestfit = jrr.spec.onegaus(x, m.params[0], m.params[1], m.params[2], m.params[3]) plt.plot(x, bestfit, color='blue') # The same, but with LMFIT mod1 = GaussianModel() mod2 = ConstantModel() # The continuum level mod = mod1 + mod2 pars = mod1.guess(y, x=x) + mod2.guess(y, x=x) # This is cool. It made rough guesses for us. pars['c'].min = 0 # Set bounds on continuum pars['c'].max = 10 # Set bounds on continuum #pars['amplitude'].vary = False # Fix a parameter out = mod.fit(y, pars, x=x, weights=1/err**2) # Fitting is done here. plt.plot(x, out.best_fit, color='orange') print(out.fit_report(min_correl=0.25)) plt.show() # This is actually more elegant. I think I should learn LMFIT and use it...
def CurveFitting(self, frec, Pxx, iaf, ax): 'Non-Linear Least-Squares Minimization and Curve-Fitting for Python' # ----- adjusting a model to the obtained PSD ----- # model 1: constante g1 = ConstantModel(prefix = 'g1_') pars = g1.guess(Pxx, x = frec) pars['g1_c'].set(0) # model 2: k2/f^-1 g2 = PowerLawModel(prefix = 'g2_') pars += g2.guess(Pxx, x = frec) pars['g2_exponent'].set(-1) #model 3: probability density function g3 = GaussianModel(prefix = 'g3_') pars += g3.guess(Pxx, x = frec) pars['g3_center'].set(iaf, min = iaf-2, max = iaf+2) # model 4: probability density function g4 = GaussianModel(prefix = 'g4_') pars += g4.guess(Pxx, x = frec) pars['g4_center'].set(20, min = 16, max = 25) # final model gA = g1 + g2 + g3 + g4 outA = gA.fit(Pxx, pars, x = frec) diffA= np.sum(Pxx - outA.best_fit) gB = g1 + g2 + g3 outB = gB.fit(Pxx, pars, x = frec) diffB= np.sum(Pxx - outB.best_fit) gC = g1 + g2 outC = gC.fit(Pxx, pars, x = frec) diffC= np.sum(Pxx - outC.best_fit) diffs= np.abs([diffA, diffB, diffC]) idx = np.where(diffs == np.min(diffs))[0][0] out = [outA, outB, outC][idx] # ----- plotting the desire PSD ----- # original and fitted curves ax.plot(frec, Pxx, 'k', linewidth = 2, label = 'PSD') ax.plot(frec, out.best_fit, 'b.-', linewidth = 2, markersize = 9, label ='BestModel') ax.set_xlim(frec[0], 32) ax.set_ylim(ymin = 0) ax.tick_params(axis = 'both', labelsize = 16) ax.set_xlabel('Frequency [Hz]', fontsize = 'x-large') ax.grid() # components of the fitted curved comps = out.eval_components(x = frec) g12 = comps['g1_'] + comps['g2_'] ax.plot(frec, g12, 'g--', linewidth = 2, label = 'PowerLawModel') idx1, idx2 = np.where(frec >= 5)[0][0], np.where(frec <= 15)[0][-1] # final value on the subplot if out != outC: diffs = out.best_fit[idx1:idx2] - g12[idx1:idx2] peak1 = np.amax(diffs) idx = np.where(diffs == peak1)[0] idx+= len(out.best_fit[:idx1]) ax.plot((frec[idx],frec[idx]), (g12[idx],out.best_fit[idx]), 'r-o', linewidth = 3, markersize = 9) ax.text(frec[idx], g12[idx], str(np.around(peak1, decimals=2)), horizontalalignment='right', verticalalignment='top', color='r', fontsize='xx-large') else: peak1 = 0 # optional valued on the subplot diffs = Pxx[idx1:idx2] - g12[idx1:idx2] peak2 = np.amax(diffs) idx = np.where(peak2 == diffs)[0] idx+= len(Pxx[:idx1]) ax.plot((frec[idx],frec[idx]), (g12[idx], Pxx[idx]), 'r-*', linewidth = 3, markersize = 11) ax.text(frec[idx], Pxx[idx], str(np.around(peak2, decimals=2)), horizontalalignment='left', verticalalignment='top', color='r', fontsize='xx-large') ax.legend(loc='upper right', shadow=True) return peak1, peak2
# 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' out = mod.fit(y, pars, x=x) print(out.fit_report(min_correl=0.25)) plt.plot(x, y, 'b-') plt.plot(x, out.best_fit, 'r-') # plt.savefig(figname) plt.show() # <end examples/doc_builtinmodels_peakmodels.py>