def makeTelluricModel(lsf, alpha, flux_offset, wave_offset0, data=data): """ Make a telluric model as a function of LSF, alpha, and flux offset. """ data2 = copy.deepcopy(data) data2.wave = data2.wave + wave_offset0 #data2.wave = data2.wave * (1 + wave_offset1) + wave_offset0 telluric_model = nsp.convolveTelluric(lsf, data2, alpha=alpha) if data.order == 35: from scipy.optimize import curve_fit data_flux_avg = np.average(data2.flux) popt, pcov = curve_fit(nsp.voigt_profile,data2.wave[0:-10], data2.flux[0:-10], p0=[21660,data_flux_avg,0.1,0.1,0.01,0.1,10000,1000], maxfev=10000) #model = nsp.continuum(data=data2, mdl=telluric_model, deg=2) model = telluric_model max_model_flux = np.max(nsp.voigt_profile(data2.wave, *popt)) model.flux *= nsp.voigt_profile(data2.wave, *popt)/max_model_flux model = nsp.continuum(data=data2, mdl=model, deg=2) else: model = nsp.continuum(data=data2, mdl=telluric_model, deg=2) model.flux += flux_offset return model
def bestParams2(theta, data): i, alpha, c2, c0, c1 = theta data2 = copy.deepcopy(data) data2.wave = data2.wave*c1 + c0 telluric_model = nsp.convolveTelluric(i, data2, alpha=alpha) model = nsp.continuum(data=data2, mdl=telluric_model) return np.sum(data.flux - (model.flux + c2))**2
def bestParams(data, i, alpha, c2, c0): data2 = copy.deepcopy(data) data2.wave = data2.wave + c0 telluric_model = nsp.convolveTelluric(i, data2, alpha=alpha) model = nsp.continuum(data=data2, mdl=telluric_model) #plt.figure(2) #plt.plot(model.wave, model.flux+c2, 'r-', alpha=0.5) #plt.plot(data.wave*c1+c0, data.flux, 'b-', alpha=0.5) #plt.close() #plt.show() #sys.exit() return model.flux + c2
def getLSF2(telluric_data, continuum=True, test=False, save_path=None): """ Return a best LSF value from a telluric data. """ data = copy.deepcopy(telluric_data) def bestParams(data, i, alpha, c2, c0): data2 = copy.deepcopy(data) data2.wave = data2.wave + c0 telluric_model = nsp.convolveTelluric(i, data2, alpha=alpha) model = nsp.continuum(data=data2, mdl=telluric_model) #plt.figure(2) #plt.plot(model.wave, model.flux+c2, 'r-', alpha=0.5) #plt.plot(data.wave*c1+c0, data.flux, 'b-', alpha=0.5) #plt.close() #plt.show() #sys.exit() return model.flux + c2 def bestParams2(theta, data): i, alpha, c2, c0, c1 = theta data2 = copy.deepcopy(data) data2.wave = data2.wave*c1 + c0 telluric_model = nsp.convolveTelluric(i, data2, alpha=alpha) model = nsp.continuum(data=data2, mdl=telluric_model) return np.sum(data.flux - (model.flux + c2))**2 from scipy.optimize import curve_fit, minimize popt, pcov = curve_fit(bestParams, data, data.flux, p0=[4.01, 1.01, 0.01, 1.01], maxfev=1000000, epsfcn=0.1) #nll = lambda *args: bestParams2(*args) #results = minimize(nll, [3., 1., 0.1, -10., 1.], args=(data)) #popt = results['x'] data.wave = data.wave+popt[3] telluric_model = nsp.convolveTelluric(popt[0], data, alpha=popt[1]) model = nsp.continuum(data=data, mdl=telluric_model) #model.flux * np.e**(-popt[2]) + popt[3] model.flux + popt[2] return popt[0]
def getFringeFrequecy(tell_data, test=False): """ Use the Lomb-Scargle Periodogram to identify the fringe pattern. """ tell_sp = copy.deepcopy(tell_data) ## continuum correction tell_sp = nsp.continuumTelluric(data=tell_sp, order=tell_sp.order) ## get a telluric model lsf = nsp.getLSF(tell_sp) alpha = nsp.getAlpha(tell_sp,lsf) tell_mdl = nsp.convolveTelluric(lsf=lsf, telluric_data=tell_sp,alpha=alpha) ## fit the fringe pattern in the residual pgram_x = np.array(tell_sp.wave,float)[10:-10] pgram_y = np.array(tell_sp.flux - tell_mdl.flux,float)[10:-10] offset = np.mean(pgram_y) pgram_y -= offset mask = np.where(pgram_y - 1.5 * np.absolute(np.std(pgram_y)) > 0) pgram_x = np.delete(pgram_x, mask) pgram_y = np.delete(pgram_y, mask) pgram_x = np.array(pgram_x, float) pgram_y = np.array(pgram_y, float) #f = np.linspace(0.01,10,100000) f = np.linspace(1.0,10,100000) ## Lomb Scargle Periodogram pgram = signal.lombscargle(pgram_x, pgram_y, f) if test: fig, ax = plt.subplots(figsize=(16,6)) ax.plot(f,pgram, 'k-', label='residual',alpha=0.5) ax.set_xlabel('frequency') plt.legend() plt.show() plt.close() return f[np.argmax(pgram)]
def fringeTelluric(data): """ Model the fringe pattern for telluric data. Note: The input data should be continuum corrected before using this function. """ lsf = nsp.getLSF(data) alpha = nsp.getAlpha(data, lsf) tell_mdl2 = nsp.convolveTelluric(lsf=lsf, telluric_data=data, alpha=alpha) pgram_x = np.array(data.wave, float)[10:-10] pgram_y = np.array(data.flux - tell_mdl2.flux, float)[10:-10] offset = np.mean(pgram_y) pgram_y -= offset mask = np.where(np.absolute(pgram_y) - 1. * np.std(pgram_y) > 0) pgram_x = np.delete(pgram_x, mask) pgram_y = np.delete(pgram_y, mask) pgram_x = np.array(pgram_x, float) pgram_y = np.array(pgram_y, float) f = np.linspace(0.01, 10, 100000) ## Lomb Scargle Periodogram pgram = signal.lombscargle(pgram_x, pgram_y, f) freq = f[np.argmax(pgram)] ## initial guess for the sine fit amp0 = np.absolute(np.std(pgram_y)) p0 = [freq, amp0, 0, 0] popt, pcov = curve_fit(sineFit, pgram_x, pgram_y, p0=p0, maxfev=100000) #data.wave = pgram_x #data.flux = np.delete(data.flux[10:-10], # mask)-(sineFit(pgram_x,*popt)-popt[-1]) #data.noise = np.delete(data.noise[10:-10],mask) data.flux -= (sineFit(data.wave, *popt) - popt[-1]) return data, sineFit(data.wave, *popt) - popt[-1]
fig = corner.corner(triangle_samples, labels=ylabels, truths=[lsf_mcmc[0], alpha_mcmc[0], A_mcmc[0], B_mcmc[0]], quantiles=[0.16, 0.84], label_kwargs={"fontsize": 20}) plt.minorticks_on() fig.savefig(save_to_path+'/triangle.png', dpi=300, bbox_inches='tight') #plt.show() plt.close() data2 = copy.deepcopy(data) data2.wave = data2.wave + B_mcmc[0] telluric_model = nsp.convolveTelluric(lsf_mcmc[0], data, alpha=alpha_mcmc[0]) model, pcont = nsp.continuum(data=data, mdl=telluric_model, deg=2, tell=True) model.flux += A_mcmc[0] plt.tick_params(labelsize=20) fig = plt.figure(figsize=(20,8)) ax1 = fig.add_subplot(111) ax1.plot(model.wave, model.flux, c='C3', ls='-', alpha=0.5) ax1.plot(model.wave, np.polyval(pcont, model.wave) + A_mcmc[0], c='C1', ls='-', alpha=0.5) ax1.plot(data.wave, data.flux, 'k-', alpha=0.5) ax1.plot(data.wave, data.flux-(model.flux+A_mcmc[0]),'k-', alpha=0.5) ax1.minorticks_on() plt.figtext(0.89,0.86,"{} O{}".format(tell_data_name, order), color='k', horizontalalignment='right', verticalalignment='center',
def getAlpha(telluric_data,lsf,continuum=True,test=False,save_path=None): """ Return a best alpha value from a telluric data. """ alpha_list = [] test_alpha = np.arange(0.1,7,0.1) data = copy.deepcopy(telluric_data) if continuum is True: data = nsp.continuumTelluric(data=data, order=data.order) for i in test_alpha: telluric_model = nsp.convolveTelluric(lsf,data, alpha=i) #telluric_model.flux **= i if data.order == 59: # mask hydrogen absorption feature data2 = copy.deepcopy(data) tell_mdl = copy.deepcopy(telluric_model) mask_pixel = 450 data2.wave = data2.wave[mask_pixel:] data2.flux = data2.flux[mask_pixel:] data2.noise = data2.noise[mask_pixel:] tell_mdl.wave = tell_mdl.wave[mask_pixel:] tell_mdl.flux = tell_mdl.flux[mask_pixel:] chisquare = nsp.chisquare(data2,tell_mdl) else: chisquare = nsp.chisquare(data,telluric_model) alpha_list.append([chisquare,i]) if test is True: plt.plot(telluric_model.wave,telluric_model.flux+i*10, 'k-',alpha=0.5) if test is True: plt.plot(telluric_data.wave,telluric_data.flux, 'r-',alpha=0.5) plt.rc('font', family='sans-serif') plt.title("Test Alpha",fontsize=15) plt.xlabel("Wavelength ($\AA$)",fontsize=12) plt.ylabel("Transmission + Offset",fontsize=12) plt.minorticks_on() if save_path is not None: plt.savefig(save_path+\ "/{}_O{}_alpha_data_mdl.png"\ .format(telluric_data.name, telluric_data.order)) plt.show() plt.close() fig, ax = plt.subplots() plt.rc('font', family='sans-serif') for i in range(len(alpha_list)): ax.plot(alpha_list[i][1],alpha_list[i][0],'k.',alpha=0.5) ax.plot(min(alpha_list)[1],min(alpha_list)[0],'r.', label="best alpha {}".format(min(alpha_list)[1])) ax.set_xlabel(r"$\alpha$",fontsize=12) ax.set_ylabel("$\chi^2$",fontsize=12) plt.minorticks_on() plt.legend(fontsize=10) if save_path is not None: plt.savefig(save_path+\ "/{}_O{}_alpha_chi2.png"\ .format(telluric_data.name, telluric_data.order)) plt.show() plt.close() alpha = min(alpha_list)[1] return alpha
def getLSF(telluric_data, alpha=1.0, continuum=True,test=False,save_path=None): """ Return a best LSF value from a telluric data. """ lsf_list = [] test_lsf = np.arange(3.0,13.0,0.1) data = copy.deepcopy(telluric_data) if continuum is True: data = nsp.continuumTelluric(data=data) data.flux **= alpha for i in test_lsf: telluric_model = nsp.convolveTelluric(i,data) if telluric_data.order == 59: telluric_model.flux **= 3 # mask hydrogen absorption feature data2 = copy.deepcopy(data) tell_mdl = copy.deepcopy(telluric_model) mask_pixel = 450 data2.wave = data2.wave[mask_pixel:] data2.flux = data2.flux[mask_pixel:] data2.noise = data2.noise[mask_pixel:] tell_mdl.wave = tell_mdl.wave[mask_pixel:] tell_mdl.flux = tell_mdl.flux[mask_pixel:] chisquare = nsp.chisquare(data2,tell_mdl) else: chisquare = nsp.chisquare(data,telluric_model) lsf_list.append([chisquare,i]) if test is True: plt.plot(telluric_model.wave,telluric_model.flux+(i-3)*10+1, 'r-',alpha=0.5) if test is True: plt.plot(data.wave,data.flux, 'k-',label='telluric data',alpha=0.5) plt.title("Test LSF",fontsize=15) plt.xlabel("Wavelength ($\AA$)",fontsize=12) plt.ylabel("Transmission + Offset",fontsize=12) plt.minorticks_on() if save_path is not None: plt.savefig(save_path+\ "/{}_O{}_lsf_data_mdl.png"\ .format(data.name, data.order)) #plt.show() plt.close() fig, ax = plt.subplots() for i in range(len(lsf_list)): ax.plot(lsf_list[i][1],lsf_list[i][0],'k.',alpha=0.5) ax.plot(min(lsf_list)[1],min(lsf_list)[0],'r.', label="best LSF {} km/s".format(min(lsf_list)[1])) ax.set_xlabel("LSF (km/s)",fontsize=12) ax.set_ylabel("$\chi^2$",fontsize=11) plt.minorticks_on() plt.legend(fontsize=10) if save_path is not None: plt.savefig(save_path+\ "/{}_O{}_lsf_chi2.png"\ .format(data.name, data.order)) #plt.show() plt.close() lsf = min(lsf_list)[1] if telluric_data.order == 61 or telluric_data.order == 62 \ or telluric_data.order == 63: #or telluric_data.order == 64: lsf = 5.5 print("The LSF is obtained from orders 60 and 65 (5.5 km/s).") return lsf