def gaussian_fit(x, y, num_gauss, range_1, ax, peak): x = np.array(x) y = np.array(y) for n_gaussians in range(1, num_gauss): # compute the best-fit linear combination w_best, rms, locs, widths = sum_of_norms(x, y, n_gaussians, spacing='linear', full_output=True) norms = w_best * norm(x[:, None], locs, widths) if rms <= 0.00000001: print('Number of Gaussians: ', n_gaussians) break y_1 = norms.sum(1) grad = np.gradient(y_1) ax.plot(x, y_1) peaks, _ = find_peaks(y_1[:-800], height=0.01, width=1) #Set 0.19 for GeSe_flake results_half = peak_widths(y_1, peaks, rel_height=0.005) print('Total number of peaks: ', len(peaks)) print('-----------------------------------') lines_gaus = [] for i in range(len(peaks)): peak_start = np.where( x >= abs(x[peaks[i]] - float(results_half[0][i]) / 2))[0] peak_end = np.where( x >= abs(x[peaks[i]] + float(results_half[0][i]) / 2))[0] ax.plot(x[peaks[i]], y[peaks[i]], 'o', markersize=3, color='black') mu = x[peaks[i]] sigma = np.std(x[peak_start[0]:peak_end[0]], ddof=1) Gaus = 0.5 * y_1[peaks[i]] * np.exp(-(x - mu)**2 / (2 * sigma**2)) gaus_shift = [i - min(Gaus) for i in Gaus] lines = ax.fill_between(x, gaus_shift, alpha=0.4) lines_gaus.append(lines) return lines_gaus
# Fetch the data x, y = fetch_vega_spectrum() # truncate the spectrum mask = (x >= 2000) & (x < 10000) x = x[mask] y = y[mask] for n_gaussians in (10, 50, 100): # compute the best-fit linear combination w_best, rms, locs, widths = sum_of_norms(x, y, n_gaussians, spacing='linear', full_output=True) norms = w_best * norm(x[:, None], locs, widths) # plot the results plt.figure() plt.plot(x, y, '-k', label='input spectrum') ylim = plt.ylim() plt.plot(x, norms, ls='-', c='#FFAAAA') plt.plot(x, norms.sum(1), '-r', label='sum of gaussians') plt.ylim(-0.1 * ylim[1], ylim[1]) plt.legend(loc=0) plt.text(0.97, 0.8, "rms error = %.2g" % rms, ha='right', va='top', transform=plt.gca().transAxes)
def gaussian_fit(x, y, num_gauss, range_1, peak, sigma): x = np.array(x) y = np.array(y) y1 = minmax_scale(np.array(y)) for n_gaussians in range(1, num_gauss): # compute the best-fit linear combination w_best, rms, locs, widths = sum_of_norms(x, y1, n_gaussians, spacing='linear', full_output=True) norms = w_best * norm(x[:, None], locs, widths) if rms <= 10e-10: print('Number of Gaussians: ', n_gaussians) break y_1 = norms.sum(1) # compute second derivative #second_derivative = np.gradient(np.gradient(y_1[:-1100])) # find switching points #infls = np.where(np.diff(np.sign(second_derivative)))[0] #print(np.sign(second_derivative)) #ax.plot([x[infls], x[infls]], [0,1]) peaks, _ = find_peaks(y_1[:-930], height=0.01, width=1) results_half = peak_widths(y_1, peaks, rel_height=0.001) #peaks = np.delete(peaks, 2) #Deleting peaks by index print('Total number of peaks: ', len(peaks)) print('-----------------------------------') #peaks = peaks[:3] + peaks[3+1 :] center = [] mu_1 = [] sigma_1 = [] y_peak = [] Gaussian_func = [] for i in range(len(peaks)): peak_start = np.where( x >= abs(x[peaks[i]] - float(results_half[0][i]) / 2))[0] peak_end = np.where( x >= abs(x[peaks[i]] + float(results_half[0][i]) / 2))[0] mu = x[peaks[i]] #sigma = np.std(x[peak_start[0]: peak_end[0]], ddof=1) Gaus = 0.5 * y[peaks[i]] * np.exp(-(x - mu)**2 / (2 * sigma[i]**2)) Gaussian_func.append(Gaus) center.append(x[peaks[i]]) mu_1.append(mu) sigma_1.append(sigma[i]) y_peak.append(y[peaks[i]]) print('-------------------------') print('Gaussian peak nr: ', i + 1) print('Center: ', x[peaks[i]]) print('mu: ', mu) print('sigma: ', sigma) print('rms: ', rms) print('x-span: ', x[peak_start[0]], x[peak_end[0]]) print('Rel Intensity: ', y_1[peaks[i]]) xGaus = x[peaks[peak] - range_1:peaks[peak] + range_1] norm_new = y_1[peaks[peak] - range_1:peaks[peak] + range_1] return xGaus, y_1, center, mu_1, sigma_1, y_peak, n_gaussians, rms, Gaussian_func
def extend_sens(sens_file='/Users/brammer/3DHST/Spectra/Work/CONF/WFC3.IR.G141.3rd.sens.2.fits'): """ Some of the "v2" sensitivity files are cut off at the wavelength extremes for no apparent reason. Here, extend them with multi-gaussian component fits """ import os import matplotlib.pyplot as plt from astroML.sum_of_norms import sum_of_norms, norm from threedhst import catIO #sens = catIO.Table('/Users/brammer/3DHST/Spectra/Work/CONF/WFC3.IR.G102.2nd.sens.2.fits') #sens = catIO.Table('/Users/brammer/3DHST/Spectra/Work/CONF/WFC3.IR.G102.3rd.sens.2.fits') if 'G102' in sens_file: xarr = np.arange(7100,1.19e4) n_gaussians, spacing = 20, 'linear' else: xarr = np.arange(9700,1.75e4) n_gaussians, spacing = 20, 'log' #sens = catIO.Table('/Users/brammer/3DHST/Spectra/Work/CONF/WFC3.IR.G141.2nd.sens.2.fits') sens = catIO.Table(sens_file) ok = sens['SENSITIVITY'] > 0 x = sens['WAVELENGTH'][ok] y = sens['SENSITIVITY'][ok] ye = sens['ERROR'][ok] out = {} fig = plt.figure() for i, col in enumerate(['SENSITIVITY', 'ERROR']): ax = fig.add_subplot(211+i) y = sens[col][ok] w_best, rms, locs, widths = sum_of_norms(x, y, n_gaussians, spacing=spacing, full_output=True) norms = w_best * norm(xarr[:, None], locs, widths) out[col] = norms*1 ax.plot(sens['WAVELENGTH'], sens[col], '-k', linewidth=3, label=col) ylim = ax.get_ylim() if col == 'SENSITIVITY': g = out[col].sum(1) keep = g > 1.e-4*g.max() ax.set_title(os.path.basename(sens.filename)) ax.plot(xarr[keep], out[col][keep,:], ls='-', c='#FFAAAA') ax.plot(xarr[keep], out[col][keep,:].sum(1), '-r', linewidth=3, alpha=0.7) ax.set_ylim(-0.1 * ylim[1], 1.05*ylim[1]) ax.legend(loc='upper right', fontsize=9) ax.set_xlabel('wavelength') fig.tight_layout(pad=1) t = catIO.table_base() t.add_column(catIO.Column(name='WAVELENGTH', data=xarr[keep])) for i, col in enumerate(['SENSITIVITY', 'ERROR']): t.add_column(catIO.Column(name=col, data=out[col][keep,:].sum(1))) outfile = sens.filename.replace('sens.2.fits', 'sens.X.fits') if os.path.exists(outfile): os.remove(outfile) t.write(outfile) print outfile plt.savefig(outfile.replace('.fits', '.png'))