def bestParams2(theta, data): i, alpha, c2, c0, c1 = theta data2 = copy.deepcopy(data) data2.wave = data2.wave * c1 + c0 telluric_model = smart.convolveTelluric(i, data2, alpha=alpha) model = smart.continuum(data=data2, mdl=telluric_model) return np.sum(data.flux - (model.flux + c2))**2
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 = smart.convolveTelluric(i, data2, alpha=alpha) model = smart.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 = smart.convolveTelluric(i, data2, alpha=alpha) model = smart.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 = smart.convolveTelluric(popt[0], data, alpha=popt[1]) model = smart.continuum(data=data, mdl=telluric_model) #model.flux * np.e**(-popt[2]) + popt[3] model.flux + popt[2] return popt[0]
def bestParams(data, i, alpha, c2, c0): data2 = copy.deepcopy(data) data2.wave = data2.wave + c0 telluric_model = smart.convolveTelluric(i, data2, alpha=alpha) model = smart.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 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 = smart.continuumTelluric(data=tell_sp, order=tell_sp.order) ## get a telluric model lsf = smart.getLSF(tell_sp) alpha = smart.getAlpha(tell_sp, lsf) tell_mdl = smart.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.lismartace(0.01,10,100000) f = np.lismartace(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 = smart.getLSF(data) alpha = smart.getAlpha(data, lsf) tell_mdl2 = smart.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.lismartace(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]
def makeTelluricModel(lsf, alpha, flux_offset, wave_offset, data=data, pwv=pwv, airmass=airmass, deg=cont_deg): """ Make a telluric model as a function of LSF, alpha, and flux offset. ## Note: The function "convolveTelluric " used is from the model_fit.py, not in the tellurics!s """ niter = 5 # continuum iteration data2 = copy.deepcopy(data) data2.wave = data2.wave + wave_offset #data2.wave = data2.wave * (1 + wave_offset1) + wave_offset telluric_model = smart.convolveTelluric(lsf, data2, alpha=alpha, pwv=pwv) #if data.order == 35: # from scipy.optimize import curve_fit # data_flux_avg = np.average(data2.flux) # popt, pcov = curve_fit(smart.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 = smart.continuum(data=data2, mdl=telluric_model, deg=2) # model = telluric_model # max_model_flux = np.max(smart.voigt_profile(data2.wave, *popt)) # model.flux *= smart.voigt_profile(data2.wave, *popt)/max_model_flux # model = smart.continuum(data=data2, mdl=model, deg=deg) #else: model = smart.continuum(data=data2, mdl=telluric_model, deg=deg) for i in range(niter): model = smart.continuum(data=data2, mdl=model, deg=deg) model.flux += flux_offset return model
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() deg = cont_deg niter = 5 data2 = copy.deepcopy(data) data2.wave = data2.wave + B_mcmc[0] telluric_model = smart.convolveTelluric(lsf_mcmc[0], data, alpha=alpha_mcmc[0]) model, pcont = smart.continuum(data=data, mdl=telluric_model, deg=deg, tell=True) polyfit = np.polyval(pcont, model.wave) for i in range(niter): model, pcont2 = smart.continuum(data=data2, mdl=model, deg=deg, tell=True) polyfit2 = np.polyval(pcont2, model.wave) polyfit *= polyfit2 polyfit += A_mcmc[0] model.flux += A_mcmc[0] plt.tick_params(labelsize=20)
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 = smart.continuumTelluric(data=data) for i in test_alpha: telluric_model = smart.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 = smart.chisquare(data2, tell_mdl) else: chisquare = smart.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 = smart.continuumTelluric(data=data) data.flux **= alpha for i in test_lsf: telluric_model = smart.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 = smart.chisquare(data2, tell_mdl) else: chisquare = smart.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
def writeto(self, save_to_path, method='ascii', tell_sp=None): """ Save the data as an ascii or a fits file. Parameters ---------- save_to_path : str the path to save the output file method : 'ascii' or 'fits' the output file format, either in a single ascii file or several fits files labeled in the order of wavelength Optional Parameters ------------------- tell_sp : Spectrum object the telluric data for the corresponding wavelength calibration Returns ------- ascii or fits : see the method keyword The wavelength is in microns """ #pixel = np.delete(np.arange(1024),list(self.mask)) pixel = np.arange(len(self.oriWave)) ## create the output mask array 0=good; 1=bad if self.applymask: mask = np.zeros((len(self.oriWave), ), dtype=int) np.put(mask, self.mask, int(1)) else: mask = np.zeros((len(self.oriWave), ), dtype=int) if method == 'fits': #fullpath = self.path + '/' + self.name + '_' + str(self.order) + '_all.fits' #hdulist = fits.open(fullpath, ignore_missing_end=True) #hdulist.writeto(save_to_path) #hdulist.close() if self.header['NAXIS1'] == 1024: save_to_path2 = save_to_path + self.header['FILENAME'].split('.')[0]\ + '_O' + str(self.order) else: save_to_path2 = save_to_path + self.header['OFNAME'].split('.')[0]\ + '_O' + str(self.order) ## wavelength hdu1 = fits.PrimaryHDU(self.wave / 10000, header=self.header) save_to_path2_1 = save_to_path2 + '_wave.fits' hdu1.writeto(save_to_path2_1) ## flux hdu2 = fits.PrimaryHDU(self.flux, header=self.header) save_to_path2_2 = save_to_path2 + '_flux.fits' hdu2.writeto(save_to_path2_2) ## uncertainty hdu3 = fits.PrimaryHDU(self.noise, header=self.header) save_to_path2_3 = save_to_path2 + '_uncertainty.fits' hdu3.writeto(save_to_path2_3) ## pixel hdu4 = fits.PrimaryHDU(pixel, header=self.header) save_to_path2_4 = save_to_path2 + '_pixel.fits' hdu4.writeto(save_to_path2_4) ## mask hdu5 = fits.PrimaryHDU(mask, header=self.header) save_to_path2_5 = save_to_path2 + '_mask.fits' hdu5.writeto(save_to_path2_5) if tell_sp is not None: tell_sp2 = copy.deepcopy(tell_sp) # the telluric standard model wavelow = tell_sp2.wave[0] - 20 wavehigh = tell_sp2.wave[-1] + 20 tell_mdl = smart.getTelluric(wavelow=wavelow, wavehigh=wavehigh) # continuum correction for the data tell_sp2 = smart.continuumTelluric(data=tell_sp2, model=tell_mdl, order=tell_sp2.order) # telluric flux hdu6 = fits.PrimaryHDU(tell_sp.flux, header=tell_sp.header) save_to_path2_6 = save_to_path2 + '_telluric_flux.fits' hdu5.writeto(save_to_path2_6) # telluric uncertainty hdu7 = fits.PrimaryHDU(tell_sp.noise, header=tell_sp.header) save_to_path2_7 = save_to_path2 + '_telluric_uncertainty.fits' hdu5.writeto(save_to_path2_7) # telluric model hdu8 = fits.PrimaryHDU(tell_mdl.flux, header=tell_sp.header) save_to_path2_8 = save_to_path2 + '_telluric_model.fits' hdu5.writeto(save_to_path2_8) elif method == 'ascii': if self.header['NAXIS1'] == 1024: save_to_path2 = save_to_path + self.header['FILENAME'].split('.')[0]\ + '_O' + str(self.order) + '.txt' else: save_to_path2 = save_to_path + self.header['OFNAME'].split('.')[0]\ + '_O' + str(self.order) + '.txt' if tell_sp is None: df = pd.DataFrame( data={ 'wavelength': list(self.oriWave / 10000), 'flux': list(self.oriFlux), 'uncertainty': list(self.oriNoise), 'pixel': list(pixel), 'mask': list(mask) }) df.to_csv(save_to_path2, index=None, sep='\t', mode='a', header=True, columns=[ 'wavelength', 'flux', 'uncertainty', 'pixel', 'mask' ]) elif tell_sp is not None: tell_sp2 = copy.deepcopy(tell_sp) tell_sp2 = smart.continuumTelluric(data=tell_sp2, order=self.order) lsf0 = smart.getLSF(tell_sp2) tell_sp2.flux = tell_sp2.oriFlux tell_sp2.wave = tell_sp2.oriWave tell_mdl = smart.convolveTelluric(lsf0, tell_sp2) print(len(self.oriWave), len(self.oriFlux), len(self.oriNoise), len(tell_sp.oriFlux), len(tell_sp.oriNoise), len(tell_mdl.flux), len(pixel), len(mask)) df = pd.DataFrame( data={ 'wavelength': list(self.oriWave / 10000), 'flux': list(self.oriFlux), 'uncertainty': list(self.oriNoise), 'telluric_flux': list(tell_sp.oriFlux), 'telluric_uncertainty': list(tell_sp.oriNoise), 'telluric_model': list(tell_mdl.flux), 'pixel': list(pixel), 'mask': list(mask) }) df.to_csv(save_to_path2, index=None, sep='\t', mode='a', header=True, columns=[ 'wavelength', 'flux', 'uncertainty', 'telluric_flux', 'telluric_uncertainty', 'telluric_model', 'pixel', 'mask' ])