Example #1
0
def makeTelluricModel(lsf,
                      airmass,
                      pwv,
                      flux_offset,
                      wave_offset,
                      data,
                      deg=2,
                      niter=None):
    """
    Make a continuum-corrected telluric model as a function of LSF, airmass, pwv, and flux and wavelength offsets.

    The model assumes a second-order polynomail for the continuum.
    """
    data2 = copy.deepcopy(data)
    data2.wave = data2.wave + wave_offset
    telluric_model = convolveTelluric(lsf, airmass, pwv, data2)

    model = smart.continuum(data=data2, mdl=telluric_model, deg=deg)
    if niter is not None:
        for i in range(niter):
            model = smart.continuum(data=data2, mdl=model, deg=deg)

    model.flux += flux_offset

    return model
Example #2
0
    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
Example #3
0
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]
Example #4
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
Example #5
0
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
Example #6
0
                    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)
fig = plt.figure(figsize=(20, 8))
ax1 = fig.add_subplot(111)
ax1.plot(model.wave, model.flux, c='C3', ls='-', alpha=0.5)
Example #7
0
def makeModel(teff,
              logg=5,
              metal=0,
              vsini=1,
              rv=0,
              tell_alpha=1.0,
              airmass=1.0,
              pwv=0.5,
              wave_offset=0,
              flux_offset=0,
              **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')
    veiling = kwargs.get('veiling', 0)  # flux veiling parameter
    lsf = kwargs.get('lsf', 4.5)  # instrumental LSF
    if instrument == 'apogee':
        try:
            import apogee_tools as ap
        except ImportError:
            print(
                'Need to install the package "apogee_tools" (https://github.com/jbirky/apogee_tools) \n'
            )
        xlsf = kwargs.get('xlsf',
                          np.linspace(-7., 7.,
                                      43))  # APOGEE instrumental LSF sampling
        wave_off1 = kwargs.get('wave_off1')  # wavelength offset for chip a
        wave_off2 = kwargs.get('wave_off2')  # wavelength offset for chip b
        wave_off3 = kwargs.get('wave_off3')  # wavelength offset for chip c
        c0_1 = kwargs.get('c0_1')  # constant flux offset for chip a
        c0_2 = kwargs.get('c0_2')  # linear flux offset for chip a
        c1_1 = kwargs.get('c1_1')  # constant flux offset for chip b
        c1_2 = kwargs.get('c1_2')  # linear flux offset for chip b
        c2_1 = kwargs.get('c2_1')  # constant flux offset for chip c
        c2_2 = kwargs.get('c2_2')  # linear flux offset for chip c

    tell = kwargs.get('tell', True)  # apply telluric
    #tell_alpha = kwargs.get('tell_alpha', 1.0) # Telluric alpha power
    binary = kwargs.get('binary', False)  # make a binary model

    # assume the secondary has the same metallicity
    if binary:
        teff2 = kwargs.get('teff2')
        logg2 = kwargs.get('logg2')
        rv2 = kwargs.get('rv2')
        vsini2 = kwargs.get('vsini2')
        flux_scale = kwargs.get('flux_scale', 0.8)

    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 = smart.Model(teff=teff,
                            logg=logg,
                            metal=metal,
                            order=str(order),
                            modelset=modelset,
                            instrument=instrument)

    #elif data is not None and instrument == 'apogee':
    elif instrument == 'apogee':
        model = smart.Model(teff=teff,
                            logg=logg,
                            metal=metal,
                            modelset=modelset,
                            instrument=instrument)
        # Dirty fix here
        model.wave = model.wave[np.where(model.flux != 0)]
        model.flux = model.flux[np.where(model.flux != 0)]

        # apply vmicro
        vmicro = 2.478 - 0.325 * logg
        model.flux = smart.broaden(wave=model.wave,
                                   flux=model.flux,
                                   vbroad=vmicro,
                                   rotate=False,
                                   gaussian=True)

    elif data is None and instrument == 'nirspec':
        model = smart.Model(teff=teff,
                            logg=logg,
                            metal=metal,
                            order=str(order),
                            modelset=modelset,
                            instrument=instrument)

    # wavelength offset
    #model.wave += wave_offset

    # apply vsini
    model.flux = smart.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)

    # flux veiling
    model.flux += veiling

    ## if binary is True: make a binary model
    if binary:
        model2 = smart.Model(teff=teff2,
                             logg=logg2,
                             metal=metal,
                             order=str(order),
                             modelset=modelset,
                             instrument=instrument)
        # apply vsini
        model2.flux = smart.broaden(wave=model2.wave,
                                    flux=model2.flux,
                                    vbroad=vsini2,
                                    rotate=True,
                                    gaussian=False)
        # apply rv (including the barycentric correction)
        model2.wave = rvShift(model2.wave, rv=rv2)
        # linearly interpolate the model2 onto the model1 grid
        fit = interp1d(model2.wave, model2.flux)

        select_wavelength = np.where((model.wave < model2.wave[-1])
                                     & (model.wave > model2.wave[0]))
        model.flux = model.flux[select_wavelength]
        model.wave = model.wave[select_wavelength]

        # combine the models together and scale the secondary flux
        model.flux += flux_scale * fit(model.wave)

    if output_stellar_model:
        stellar_model = copy.deepcopy(model)
        if binary:
            model2.flux = flux_scale * fit(model.wave)

    # apply telluric
    if tell is True:
        model = smart.applyTelluric(model=model,
                                    tell_alpha=tell_alpha,
                                    airmass=airmass,
                                    pwv=pwv)

    # instrumental LSF
    if instrument == 'nirspec':
        model.flux = smart.broaden(wave=model.wave,
                                   flux=model.flux,
                                   vbroad=lsf,
                                   rotate=False,
                                   gaussian=True)
    elif instrument == 'apogee':
        model.flux = ap.apogee_hack.spec.lsf.convolve(model.wave,
                                                      model.flux,
                                                      lsf=lsf,
                                                      xlsf=xlsf).flatten()
        model.wave = ap.apogee_hack.spec.lsf.apStarWavegrid()
        # Remove the NANs
        model.wave = model.wave[~np.isnan(model.flux)]
        model.flux = model.flux[~np.isnan(model.flux)]

    if output_stellar_model:
        stellar_model.flux = smart.broaden(wave=stellar_model.wave,
                                           flux=stellar_model.flux,
                                           vbroad=lsf,
                                           rotate=False,
                                           gaussian=True)
        if binary:
            model2.flux = smart.broaden(wave=model2.wave,
                                        flux=model2.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
        if binary:
            model2.wave = stellar_model.wave

    # integral resampling
    if data is not None:
        if instrument == 'nirspec':
            model.flux = np.array(
                smart.integralResample(xh=model.wave,
                                       yh=model.flux,
                                       xl=data.wave))
            model.wave = data.wave

            if output_stellar_model:
                stellar_model.flux = np.array(
                    smart.integralResample(xh=stellar_model.wave,
                                           yh=stellar_model.flux,
                                           xl=data.wave))
                stellar_model.wave = data.wave
                if binary:
                    model2.flux = np.array(
                        smart.integralResample(xh=model2.wave,
                                               yh=model2.flux,
                                               xl=data.wave))
                    model2.wave = data.wave

        # contunuum correction
        if data.instrument == 'nirspec':
            niter = 5  # continuum iteration
            if output_stellar_model:
                model, cont_factor = smart.continuum(data=data,
                                                     mdl=model,
                                                     prop=True)
                for i in range(niter):
                    model, cont_factor2 = smart.continuum(data=data,
                                                          mdl=model,
                                                          prop=True)
                    cont_factor *= cont_factor2
                stellar_model.flux *= cont_factor
                if binary:
                    model2.flux *= cont_factor
            else:
                model = smart.continuum(data=data, mdl=model)
                for i in range(niter):
                    model = smart.continuum(data=data, mdl=model)
        elif data.instrument == 'apogee':
            ## 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)

            # wavelength offset
            model0.wave += wave_off1

            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]
            if data0.wave[0] > data0.wave[-1]:
                data0.wave = data0.wave[::-1]
                data0.flux = data0.flux[::-1]
            model0.flux = np.array(
                smart.integralResample(xh=model0.wave,
                                       yh=model0.flux,
                                       xl=data0.wave))
            model0.wave = data0.wave
            model0 = smart.continuum(data=data0, mdl=model0, deg=deg)
            # flux corrections
            model0.flux = (model0.flux + c0_1) * np.e**(-c0_2)

            data1 = copy.deepcopy(data)
            model1 = copy.deepcopy(model)

            # wavelength offset
            model1.wave += wave_off2

            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]
            if data1.wave[0] > data1.wave[-1]:
                data1.wave = data1.wave[::-1]
                data1.flux = data1.flux[::-1]
            model1.flux = np.array(
                smart.integralResample(xh=model1.wave,
                                       yh=model1.flux,
                                       xl=data1.wave))
            model1.wave = data1.wave
            model1 = smart.continuum(data=data1, mdl=model1, deg=deg)

            # flux corrections
            model1.flux = (model1.flux + c1_1) * np.e**(-c1_2)

            data2 = copy.deepcopy(data)
            model2 = copy.deepcopy(model)

            # wavelength offset
            model2.wave += wave_off3

            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]
            if data2.wave[0] > data2.wave[-1]:
                data2.wave = data2.wave[::-1]
                data2.flux = data2.flux[::-1]

            model2.flux = np.array(
                smart.integralResample(xh=model2.wave,
                                       yh=model2.flux,
                                       xl=data2.wave))
            model2.wave = data2.wave
            model2 = smart.continuum(data=data2, mdl=model2, deg=deg)
            # flux corrections
            model2.flux = (model2.flux + c2_1) * np.e**(-c2_2)

            ## scale the flux to be the same as the data
            #model0.flux *= (np.std(data0.flux)/np.std(model0.flux))
            #model0.flux -= np.median(model0.flux) - np.median(data0.flux)

            #model1.flux *= (np.std(data1.flux)/np.std(model1.flux))
            #model1.flux -= np.median(model1.flux) - np.median(data1.flux)

            #model2.flux *= (np.std(data2.flux)/np.std(model2.flux))
            #model2.flux -= np.median(model2.flux) - np.median(data2.flux)

            model.flux = np.array(
                list(model2.flux) + list(model1.flux) + list(model0.flux))
            model.wave = np.array(
                list(model2.wave) + list(model1.wave) + list(model0.wave))

    if instrument == 'nirspec':
        # flux offset
        model.flux += flux_offset
        if output_stellar_model:
            stellar_model.flux += flux_offset
            if binary:
                model2.flux += flux_offset
    #model.flux **= (1 + flux_exponent_offset)

    if output_stellar_model:
        if not binary:
            return model, stellar_model
        else:
            return model, stellar_model, model2
    else:
        return model
Example #8
0
fig = corner.corner(
    triangle_samples,
    labels=ylabels,
    truths=[lsf_mcmc[0], airmass_mcmc[0], pwv_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 = tellurics.convolveTelluric(lsf_mcmc[0], airmass_mcmc[0],
                                            pwv_mcmc[0], data)
model, pcont = smart.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,