def _residual(data, model): """ Return a residual flux array with the length of the data. (deprecated) """ residual = [] # find the region where the model is in the range of the data data_model_range = np.where(np.logical_and(np.array(model.wave) >= data.wave[0], \ np.array(model.wave) <= data.wave[-1]))[0] #residual = np.zeros(len(data_model_range)) for i in data_model_range: model_wave = model.wave[i] j = np.isclose(np.array(data.wave), model_wave) if len(np.where(j)[0]) is 1: residual.append(float(data.flux[j] - model.flux[i])) #residual[i] = float(data.flux[j] - model.flux[i]) else: # take the average of the wavelength if there are more than # one data point close to the model data_flux = np.average(data.flux[j]) residual.append(float(data_flux - model.flux[i])) #residual[i] = float(data_flux - model.flux[i]) residual_model = nsp.Model() residual_model.wave = model.wave[data_model_range] residual_model.flux = np.asarray(residual) # reject fluxes larger than 5 sigmas #residual_model.flux = residual_model.flux[np.absolute(residual_model.flux)<5*np.std(residual_model.flux)] #residual_model.wave = residual_model.wave[np.absolute(residual_model.flux)<5*np.std(residual_model.flux)] return residual_model
def residual(data, model): """ Return a residual flux array with the length of the data. """ if np.array_equal(data.wave, model.wave): residual_model = nsp.Model() residual_model.flux = data.flux - model.flux residual_model.wave = data.wave return residual_model else: print("The wavelength arrays of the data and model are not equal.") return None
def convolveTelluric(lsf, airmass, pwv, telluric_data): """ Return a convolved telluric transmission model given a telluric data and lsf. """ # get a telluric standard model wavelow = telluric_data.wave[0] - 50 wavehigh = telluric_data.wave[-1] + 50 modelwave, modelflux = InterpTelluricModel(wavelow=wavelow, wavehigh=wavehigh, airmass=airmass, pwv=pwv) #modelflux **= alpha # lsf modelflux = nsp.broaden(wave=modelwave, flux=modelflux, vbroad=lsf, rotate=False, gaussian=True) # resample modelflux = np.array(nsp.integralResample(xh=modelwave, yh=modelflux, xl=telluric_data.wave)) modelwave = telluric_data.wave telluric_model = nsp.Model() telluric_model.flux = modelflux telluric_model.wave = modelwave return telluric_model
def GetModel(wavelow, wavehigh, method='pwv', wave=False, **kwargs): """ Get a telluric spectrum using the atmosphere models in Moehler et al. (2014). Parameters ---------- wavelow : int lower bound of the wavelength range wavehigh : int upper bound of the wavelength range Optional Parameters ------------------- airmass : str airmass of the telluric model, either 1.0 or 1.5 alpha : float the power alpha parameter of the telluric model method : str 'pwv' or 'season' The defulat method is 'pwv', with airmasses 1.0, 1.5, 2.0, 2.5, 3.0, and PWV (in mm) of 0.5, 1.0, 1.5, 2.5, 3.5, 5.0, 7.5, 10.0, and 20.0 Another method is 'season', with airmasses 1.0, 1.5, 2.0, 2.5, 3.0, and bi-monthly average PWV values (1 = December/January ...6 = October/November) Returns ------- telluric: model object a telluric model with wavelength and flux Examples -------- >>> import nirspec_pip as nsp >>> telluric = nsp.getTelluric(wavelow=22900, wavehigh=23250) """ FULL_PATH = os.path.realpath(__file__) BASE, NAME = os.path.split(FULL_PATH) airmass = kwargs.get('airmass', 1.5) alpha = kwargs.get('alpha', 1.0) # keyword argument for pwv pwv = kwargs.get('pwv', 0.5) # keyword argument for season season = kwargs.get('season', 0) airmass_str = str(int(10*airmass)) pwv_str = str(int(10*pwv)).zfill(3) if method == 'pwv': tfile = BASE + '/../libraries/telluric/pwv_R300k_airmass{}/LBL_A{}_s0_w{}_R0300000_T.fits'.format(airmass, airmass_str, pwv_str) #elif method == 'season': # tfile = '/../libraries/telluric/season_R300k_airmass{}/LBL_A{}_s{}_R0300000_T.fits'.format(airmass, # airmass_str, season_str) tellurics = fits.open(tfile) telluric = nsp.Model() telluric.wave = np.array(tellurics[1].data['lam'] * 10000) telluric.flux = np.array(tellurics[1].data['trans'])**(alpha) # select the wavelength range criteria = (telluric.wave > wavelow) & (telluric.wave < wavehigh) telluric.wave = telluric.wave[criteria] telluric.flux = telluric.flux[criteria] if wave: return telluric.wave else: return telluric.flux
def makeModel(teff, logg, z, vsini, rv, alpha, wave_offset, flux_offset, **kwargs): """ Return a forward model. Parameters ---------- params : a dictionary that specifies the parameters such as teff, logg, z. data : an input science data used for continuum correction Returns ------- model: a synthesized model """ # read in the parameters order = kwargs.get('order', 33) modelset = kwargs.get('modelset', 'btsettl08') lsf = kwargs.get('lsf', 6.0) # instrumental LSF tell = kwargs.get('tell', True) # apply telluric data = kwargs.get('data', None) # for continuum correction and resampling if data is not None: order = data.order # read in a model #model = nsp.Model(teff=teff, logg=logg, feh=z, order=order, modelset=modelset) model = nsp.Model() model.wave, model.flux = InterpModel(teff, logg, modelset=modelset, order=order) model.wave *= 10000 # wavelength offset #model.wave += wave_offset # apply vsini model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=vsini, rotate=True, gaussian=False) # apply rv (including the barycentric correction) model.wave = nsp.rvShift(model.wave, rv=rv) # apply telluric if tell is True: model = nsp.applyTelluric(model=model, alpha=alpha, airmass='1.5') # NIRSPEC LSF model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=lsf, rotate=False, gaussian=True) # add a fringe pattern to the model #model.flux *= (1+amp*np.sin(freq*(model.wave-phase))) # wavelength offset model.wave += wave_offset # integral resampling if data is not None: model.flux = np.array( nsp.integralResample(xh=model.wave, yh=model.flux, xl=data.wave)) model.wave = data.wave # contunuum correction model = nsp.continuum(data=data, mdl=model) # flux offset model.flux += flux_offset #model.flux **= (1 + flux_exponent_offset) return model
plt.close() teff = teff_mcmc[0] logg = logg_mcmc[0] z = 0.0 vsini = vsini_mcmc[0] rv = rv_mcmc[0] alpha = alpha_mcmc[0] A = A_mcmc[0] N = N_mcmc[0] ## new plotting model ## read in a model model = nsp.Model(teff=teff, logg=logg, feh=z, order=data.order, modelset=modelset) # apply vsini model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=vsini, rotate=True) # apply rv (including the barycentric correction) model.wave = nsp.rvShift(model.wave, rv=rv) model_notell = copy.deepcopy(model) # apply telluric model = nsp.applyTelluric(model=model, alpha=alpha) # NIRSPEC LSF
def makeModel(teff, logg, z, vsini, rv, wave_offset, flux_offset, **kwargs): """ Return a forward model. Parameters ---------- teff : effective temperature data : an input science data used for continuum correction Optional Parameters ------------------- Returns ------- model: a synthesized model """ # read in the parameters order = kwargs.get('order', 33) modelset = kwargs.get('modelset', 'btsettl08') instrument = kwargs.get('instrument', 'nirspec') lsf = kwargs.get('lsf', 6.0) # instrumental LSF tell = kwargs.get('tell', True) # apply telluric data = kwargs.get('data', None) # for continuum correction and resampling if data is not None and instrument == 'nirspec': order = data.order # read in a model #print('teff ',teff,'logg ',logg, 'z', z, 'order', order, 'modelset', modelset) #print('teff ',type(teff),'logg ',type(logg), 'z', type(z), 'order', type(order), 'modelset', type(modelset)) model = nsp.Model(teff=teff, logg=logg, feh=z, order=order, modelset=modelset, instrument=instrument) elif data is not None and instrument == 'apogee': model = nsp.Model(teff=teff, logg=logg, feh=z, modelset=modelset, instrument=instrument) # wavelength offset #model.wave += wave_offset # apply vsini model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=vsini, rotate=True, gaussian=False) # apply rv (including the barycentric correction) model.wave = nsp.rvShift(model.wave, rv=rv) # instrumental LSF model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=lsf, rotate=False, gaussian=True) # add a fringe pattern to the model #model.flux *= (1+amp*np.sin(freq*(model.wave-phase))) # wavelength offset model.wave += wave_offset # integral resampling if data is not None: model.flux = np.array( nsp.integralResample(xh=model.wave, yh=model.flux, xl=data.wave)) model.wave = data.wave # contunuum correction model = nsp.continuum(data=data, mdl=model) # flux offset model.flux += flux_offset #model.flux **= (1 + flux_exponent_offset) return model
plt.show() plt.close() teff = teff_mcmc[0] logg = logg_mcmc[0] z = 0.0 vsini = vsini_mcmc[0] rv = rv_mcmc[0] A = A_mcmc[0] N = N_mcmc[0] ## new plotting model ## read in a model model = nsp.Model(teff=teff, logg=logg, feh=z, order=data.order, modelset=modelset, instrument=instrument) # apply vsini model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=vsini, rotate=True) # apply rv (including the barycentric correction) model.wave = nsp.rvShift(model.wave, rv=rv) # NIRSPEC LSF model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=lsf,
def makeModel(teff,logg,z,vsini,rv,alpha,wave_offset,flux_offset,**kwargs): """ Return a forward model. Parameters ---------- teff : effective temperature data : an input science data used for continuum correction Optional Parameters ------------------- Returns ------- model: a synthesized model """ # read in the parameters order = kwargs.get('order', 33) modelset = kwargs.get('modelset', 'btsettl08') instrument = kwargs.get('instrument', 'nirspec') lsf = kwargs.get('lsf', 6.0) # instrumental LSF tell = kwargs.get('tell', True) # apply telluric data = kwargs.get('data', None) # for continuum correction and resampling output_stellar_model = kwargs.get('output_stellar_model', False) if data is not None and instrument == 'nirspec': order = data.order # read in a model #print('teff ',teff,'logg ',logg, 'z', z, 'order', order, 'modelset', modelset) #print('teff ',type(teff),'logg ',type(logg), 'z', type(z), 'order', type(order), 'modelset', type(modelset)) model = nsp.Model(teff=teff, logg=logg, feh=z, order=order, modelset=modelset, instrument=instrument) #elif data is not None and instrument == 'apogee': elif instrument == 'apogee': model = nsp.Model(teff=teff, logg=logg, feh=z, modelset=modelset, instrument=instrument) elif data is None and instrument == 'nirspec': model = nsp.Model(teff=teff, logg=logg, feh=z, order=order, modelset=modelset, instrument=instrument) # wavelength offset #model.wave += wave_offset # apply vsini model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=vsini, rotate=True, gaussian=False) # apply rv (including the barycentric correction) model.wave = rvShift(model.wave, rv=rv) if output_stellar_model: stellar_model = copy.deepcopy(model) # apply telluric if tell is True: model = nsp.applyTelluric(model=model, alpha=alpha, airmass='1.5') # instrumental LSF model.flux = nsp.broaden(wave=model.wave, flux=model.flux, vbroad=lsf, rotate=False, gaussian=True) if output_stellar_model: stellar_model.flux = nsp.broaden(wave=stellar_model.wave, flux=stellar_model.flux, vbroad=lsf, rotate=False, gaussian=True) # add a fringe pattern to the model #model.flux *= (1+amp*np.sin(freq*(model.wave-phase))) # wavelength offset model.wave += wave_offset if output_stellar_model: stellar_model.wave += wave_offset # integral resampling if data is not None: model.flux = np.array(nsp.integralResample(xh=model.wave, yh=model.flux, xl=data.wave)) model.wave = data.wave if output_stellar_model: stellar_model.flux = np.array(nsp.integralResample(xh=stellar_model.wave, yh=stellar_model.flux, xl=data.wave)) stellar_model.wave = data.wave # contunuum correction if data.instrument == 'nirspec': if output_stellar_model: model, cont_factor = nsp.continuum(data=data, mdl=model, prop=True) stellar_model.flux *= cont_factor else: model = nsp.continuum(data=data, mdl=model) elif data.instrument == 'apogee' and data.datatype =='apvisit': ## set the order in the continuum fit deg = 5 ## because of the APOGEE bands, continuum is corrected from three pieces of the spectra data0 = copy.deepcopy(data) model0 = copy.deepcopy(model) range0 = np.where((data0.wave >= data.oriWave0[0][-1]) & (data0.wave <= data.oriWave0[0][0])) data0.wave = data0.wave[range0] data0.flux = data0.flux[range0] data0.noise = data0.noise[range0] model0.wave = model0.wave[range0] model0.flux = model0.flux[range0] model0 = nsp.continuum(data=data0, mdl=model0, deg=deg) data1 = copy.deepcopy(data) model1 = copy.deepcopy(model) range1 = np.where((data1.wave >= data.oriWave0[1][-1]) & (data1.wave <= data.oriWave0[1][0])) data1.wave = data1.wave[range1] data1.flux = data1.flux[range1] data1.noise = data1.noise[range1] model1.wave = model1.wave[range1] model1.flux = model1.flux[range1] model1 = nsp.continuum(data=data1, mdl=model1, deg=deg) data2 = copy.deepcopy(data) model2 = copy.deepcopy(model) range2 = np.where((data2.wave >= data.oriWave0[2][-1]) & (data2.wave <= data.oriWave0[2][0])) data2.wave = data2.wave[range2] data2.flux = data2.flux[range2] data2.noise = data2.noise[range2] model2.wave = model2.wave[range2] model2.flux = model2.flux[range2] model2 = nsp.continuum(data=data2, mdl=model2, deg=deg) model.flux = np.array( list(model0.flux) + list(model1.flux) + list(model2.flux) ) model.wave = np.array( list(model0.wave) + list(model1.wave) + list(model2.wave) ) elif data.instrument == 'apogee' and data.datatype =='apstar': model = nsp.continuum(data=data, mdl=model) # flux offset model.flux += flux_offset if output_stellar_model: stellar_model.flux += flux_offset #model.flux **= (1 + flux_exponent_offset) if output_stellar_model: return model, stellar_model else: return model