Ejemplo n.º 1
0
def read_spec(ispec):
    '''Parse spectrum out of the input
    Parameters:
    -----------
    ispec: Spectrum1D, str, list of files (ordered blue to red), 
       or tuple of arrays

    Returns:
    -----------
    spec: XSpectrum1D 
    spec_file: str
    '''
    from specutils.spectrum1d import Spectrum1D
    from astropy.nddata import StdDevUncertainty
    from linetools.spectra import xspectrum1d as lsx 
    from linetools.spectra import io as lsi 
    from xastropy.stats import basic as xsb
    #
    if isinstance(ispec,basestring):
        spec_fil = ispec
        spec = lsx.XSpectrum1D.from_file(spec_fil)
    elif isinstance(ispec,Spectrum1D):
        spec = ispec 
        spec_fil = spec.filename # Grab from Spectrum1D 
    elif isinstance(ispec,tuple):
        spec = lsx.XSpectrum1D.from_tuple(ispec)
        spec_fil = 'none'
    elif isinstance(ispec,list): # Multiple file names
        # Loop on the files
        for kk,ispecf in enumerate(ispec):
            jspec = lsx.XSpectrum1D.from_file(ispecf)
            if kk == 0:
                spec = jspec
                xper1 = xsb.perc(spec.flux, per=0.9)
            else: 
                # Scale flux for convenience of plotting (sig is not scaled)
                xper2 = xsb.perc(jspec.flux, per=0.9)
                scl = xper1[1]/xper2[1]
                # Splice
                spec = spec.splice(jspec,scale=scl)
            # Filename
            spec_fil = ispec[0]
            spec.filename=spec_fil
    else:
        raise ValueError('Bad input to read_spec')

    # Return
    return spec, spec_fil
Ejemplo n.º 2
0
def xq100_example(outfil='fig_xq100_example.pdf'):

    # Load spectrum
    spec_fil = os.getenv('DROPBOX_DIR') + '/XQ-100/data/J0030-5159_uvb.fits'
    spec = load_spectrum(spec_fil)

    # Start the plot
    if outfil is not None:
        pp = PdfPages(outfil)

    plt.figure(figsize=(8, 5))
    plt.clf()
    gs = gridspec.GridSpec(1, 1)
    fsz = 17.

    # Read and plot full spectrum
    ax_full = plt.subplot(gs[0])

    # Limits
    wvmnx = [3500., 7000.]
    gdpix = np.where(spec.dispersion < wvmnx[1] * u.AA)[0]
    perc = xsb.perc(spec.flux[gdpix])
    ax_full.set_xlim(wvmnx)
    #ax_full.set_ylim(-0.05*perc[1], 1.1*perc[1])
    ax_full.set_ylim(-1e-18, 7e-17)

    # Plot
    ax_full.plot(spec.dispersion, spec.flux, color='black', lw=1.0)
    ax_full.plot(wvmnx, [0., 0.], '--', color='green')

    # Label
    ax_full.set_xlabel('Wavelength')
    ax_full.set_ylabel('Relative Flux')
    ax_full.text(0.05,
                 0.9,
                 'XQ100 J0030-5159',
                 transform=ax_full.transAxes,
                 color='black',
                 size='x-large',
                 ha='left',
                 va='center',
                 bbox={'facecolor': 'white'})

    # Font size
    xputils.set_fontsize(ax_full, fsz)

    # Finish page
    plt.tight_layout(pad=0.2, h_pad=0.3, w_pad=0.0)
    pp.savefig()
    plt.close()
    print('Wrote: {:s}'.format(outfil))
    # Finish
    pp.close()
Ejemplo n.º 3
0
def desi_qso_templates(z_wind=0.2, zmnx=(0.4,4.), outfil=None, Ntempl=500,
                       boss_pca_fil=None, wvmnx=(3500., 10000.),
                       sdss_pca_fil=None, no_write=False):
    '''
    Generate 9000 templates for DESI from z=0.4 to 4 

    Parameters
    ----------
    z_wind: float (0.2) 
      Window for sampling
    zmnx: tuple  ( (0.5,4) )
      Min/max for generation
    Ntempl: int  (500)
      Number of draws per redshift window
    '''
    # Cosmology
    from astropy import cosmology 
    cosmo = cosmology.core.FlatLambdaCDM(70., 0.3)

    # PCA values
    if boss_pca_fil is None:
        boss_pca_fil = 'BOSS_DR10Lya_PCA_values_nocut.fits.gz'
    hdu = fits.open(boss_pca_fil)
    boss_pca_coeff = hdu[1].data

    if sdss_pca_fil is None:
        sdss_pca_fil = 'SDSS_DR7Lya_PCA_values_nocut.fits.gz'
    hdu2 = fits.open(sdss_pca_fil)
    sdss_pca_coeff = hdu2[1].data
    

    # Eigenvectors
    eigen, eigen_wave = fbq.read_qso_eigen()
    npix = len(eigen_wave)
    chkpix = np.where((eigen_wave > 900.) & (eigen_wave < 5000.) )[0]
    lambda_912 = 911.76
    pix912 = np.argmin( np.abs(eigen_wave-lambda_912) )

    # Open the BOSS catalog file
    boss_cat_fil = os.environ.get('BOSSPATH')+'/DR10/BOSSLyaDR10_cat_v2.1.fits.gz'
    bcat_hdu = fits.open(boss_cat_fil)
    t_boss = bcat_hdu[1].data
    boss_zQSO = t_boss['z_pipe']

    # Open the SDSS catalog file
    sdss_cat_fil = os.environ.get('SDSSPATH')+'/DR7_QSO/dr7_qso.fits.gz'
    scat_hdu = fits.open(sdss_cat_fil)
    t_sdss = scat_hdu[1].data
    sdss_zQSO = t_sdss['z']
    if len(sdss_pca_coeff) != len(sdss_zQSO):
        print('Need to finish running the SDSS models!')
        sdss_zQSO = sdss_zQSO[0:len(sdss_pca_coeff)]

    # Outfil
    if outfil is None:
        outfil = 'DESI_QSO_Templates_v1.1.fits'

    # Loop on redshift
    z0 = np.arange(zmnx[0],zmnx[1],z_wind)
    z1 = z0 + z_wind

    pca_list = ['PCA0', 'PCA1', 'PCA2', 'PCA3']
    PCA_mean = np.zeros(4)
    PCA_sig = np.zeros(4)
    PCA_rand = np.zeros( (4,Ntempl*2) )

    final_spec = np.zeros( (npix, Ntempl * len(z0)) )
    final_wave = np.zeros( (npix, Ntempl * len(z0)) )
    final_z = np.zeros( Ntempl * len(z0) )

    seed = -1422
    for ii in range(len(z0)):

        # BOSS or SDSS?
        if z0[ii] > 1.99:
            zQSO = boss_zQSO
            pca_coeff = boss_pca_coeff
        else:
            zQSO = sdss_zQSO
            pca_coeff = sdss_pca_coeff

        # Random z values and wavelengths
        zrand = np.random.uniform( z0[ii], z1[ii], Ntempl*2)
        wave = np.outer(eigen_wave, 1+zrand)

        # MFP (Worseck+14)
        mfp = 37. * ( (1+zrand)/5. )**(-5.4) # Physical Mpc

        # Grab PCA mean + sigma
        idx = np.where( (zQSO >= z0[ii]) & (zQSO < z1[ii]) )[0]
        print('Making z=({:g},{:g}) with {:d} input quasars'.format(z0[ii],z1[ii],len(idx)))

        # Get PCA stats and random values
        for ipca in pca_list:
            jj = pca_list.index(ipca)
            if jj == 0: # Use bounds for PCA0 [avoids negative values]
                xmnx = xstat_b.perc( pca_coeff[ipca][idx], per=0.95 )
                PCA_rand[jj,:] = np.random.uniform( xmnx[0], xmnx[1], Ntempl*2)
            else:
                PCA_mean[jj] = np.mean(pca_coeff[ipca][idx])
                PCA_sig[jj] = np.std(pca_coeff[ipca][idx])
                # Draws
                PCA_rand[jj,:] = np.random.uniform( PCA_mean[jj] - 2*PCA_sig[jj],
                                        PCA_mean[jj] + 2*PCA_sig[jj], Ntempl*2)

        # Generate the templates (2*Ntempl)
        spec = np.dot(eigen.T,PCA_rand)

        # Take first good Ntempl

        # Truncate, MFP, Fill
        ngd = 0
        for kk in range(2*Ntempl):
            # Any zero values?
            mn = np.min(spec[chkpix,kk])
            if mn < 0.:
                continue

            # MFP
            if z0[ii] > 2.39:
                z912 = wave[0:pix912,kk]/lambda_912 - 1.
                phys_dist = np.fabs( cosmo.lookback_distance(z912) -
                                cosmo.lookback_distance(zrand[kk]) ) # Mpc
                spec[0:pix912,kk] = spec[0:pix912,kk] * np.exp(-phys_dist.value/mfp[kk]) 

            # Write
            final_spec[:, ii*Ntempl+ngd] = spec[:,kk]
            final_wave[:, ii*Ntempl+ngd] = wave[:,kk]
            final_z[ii*Ntempl+ngd] = zrand[kk]
            ngd += 1
            if ngd == Ntempl:
                break
        if ngd != Ntempl:
            print('Did not make enough!')
            xdb.set_trace()

    if no_write is True: # Mainly for plotting
        return final_wave, final_spec, final_z

    # Rebin 
    light = 2.99792458e5        # [km/s]
    velpixsize = 10.            # [km/s]
    pixsize = velpixsize/light/np.log(10) # [pixel size in log-10 A]
    minwave = np.log10(wvmnx[0])          # minimum wavelength [log10-A]
    maxwave = np.log10(wvmnx[1])          # maximum wavelength [log10-A]
    r_npix = np.round((maxwave-minwave)/pixsize+1)

    log_wave = minwave+np.arange(r_npix)*pixsize # constant log-10 spacing

    totN = Ntempl * len(z0)
    rebin_spec = np.zeros((r_npix, totN))
    
    from scipy.interpolate import interp1d
    
    for ii in range(totN):
        # Interpolate (in log space)
        f1d = interp1d(np.log10(final_wave[:,ii]), final_spec[:,ii])
        rebin_spec[:,ii] = f1d(log_wave)
        #xdb.xplot(final_wave[:,ii], final_spec[:,ii], xtwo=10.**log_wave, ytwo=rebin_spec[:,ii])
        #xdb.set_trace()

    # Transpose for consistency
    out_spec = np.array(rebin_spec.T, dtype='float32')

    # Write
    hdu = fits.PrimaryHDU(out_spec)
    hdu.header.set('PROJECT', 'DESI QSO TEMPLATES')
    hdu.header.set('VERSION', '1.1')
    hdu.header.set('OBJTYPE', 'QSO')
    hdu.header.set('DISPAXIS',  1, 'dispersion axis')
    hdu.header.set('CRPIX1',  1, 'reference pixel number')
    hdu.header.set('CRVAL1',  minwave, 'reference log10(Ang)')
    hdu.header.set('CDELT1',  pixsize, 'delta log10(Ang)')
    hdu.header.set('LOGLAM',  1, 'log10 spaced wavelengths?')
    hdu.header.set('AIRORVAC', 'vac', ' wavelengths in vacuum (vac) or air')
    hdu.header.set('VELSCALE', velpixsize, ' pixel size in km/s')
    hdu.header.set('WAVEUNIT', 'Angstrom', ' wavelength units')
    hdu.header.set('BUNIT', '1e-17 erg/s/cm2/A', ' flux unit')

    idval = range(totN)
    col0 = fits.Column(name='TEMPLATEID',format='K', array=idval)
    col1 = fits.Column(name='Z',format='E',array=final_z)
    cols = fits.ColDefs([col0, col1])
    tbhdu = fits.BinTableHDU.from_columns(cols)
    tbhdu.header.set('EXTNAME','METADATA')

    hdulist = fits.HDUList([hdu, tbhdu])
    hdulist.writeto(outfil, clobber=True)

    return final_wave, final_spec, final_z
Ejemplo n.º 4
0
def xq100_plls_ex(outfil='fig_xq100_plls_ex.pdf'):

    # Load spectrum
    spec_fil = os.getenv('DROPBOX_DIR') + '/XQ-100/data/J0030-5159_uvb.fits'
    spec = load_spectrum(spec_fil)

    # Generate model
    model_file = os.getenv(
        'DROPBOX_DIR') + '/XQ-100/LLS/convg_J0030-5159_llsfit.json'
    with open(model_file) as data_file:
        lls_dict = json.load(data_file)
    # Continuum
    basec = Quantity(lls_dict['conti'])
    telfer_spec = XSpectrum1D.from_tuple((spec.dispersion.value, basec.value))

    # Start the plot
    if outfil is not None:
        pp = PdfPages(outfil)

    plt.figure(figsize=(8, 4))
    plt.clf()
    gs = gridspec.GridSpec(1, 1)
    fsz = 17.

    # Read and plot full spectrum
    ax_full = plt.subplot(gs[0])

    # Limits
    wvmnx = [3600., 5000.]
    gdpix = np.where(spec.dispersion < wvmnx[1] * u.AA)[0]
    perc = xsb.perc(spec.flux[gdpix])
    ax_full.set_xlim(wvmnx)
    #ax_full.set_ylim(-0.05*perc[1], 1.1*perc[1])
    ax_full.set_ylim(-1e-18, 4e-17)

    # Plot
    ax_full.plot(spec.dispersion, spec.flux, color='black', lw=1.0)
    ax_full.plot(wvmnx, [0., 0.], '--', color='green')

    # Label
    ax_full.set_xlabel('Wavelength')
    ax_full.set_ylabel('Relative Flux')
    ax_full.text(0.05,
                 0.9,
                 'XQ100 J0030-5159',
                 transform=ax_full.transAxes,
                 color='black',
                 size='x-large',
                 ha='left',
                 va='center',
                 bbox={'facecolor': 'white'})

    all_ills = []
    all_lls = []
    all_zlls = []
    for key in lls_dict['LLS'].keys():
        new_sys = LLSSystem(NHI=lls_dict['LLS'][key]['NHI'])
        new_sys.zabs = lls_dict['LLS'][key]['z']
        new_sys.fill_lls_lines(bval=lls_dict['LLS'][key]['bval'] * u.km / u.s)
        #
        all_ills.append(new_sys)
        all_lls.append(new_sys)
        all_zlls.append(new_sys.zabs)
    # Model
    norm_flux = lls_model(spec.dispersion, all_ills, smooth=lls_dict['smooth'])
    continuum = telfer_spec.flux * lls_dict['conti_model']['Norm'] * (
        spec.dispersion.value /
        lls_dict['conti_model']['piv_wv'])**lls_dict['conti_model']['tilt']

    #  Model
    ax_full.plot(spec.dispersion, continuum * norm_flux)

    # Font size
    xputils.set_fontsize(ax_full, fsz)

    # Finish page
    plt.tight_layout(pad=0.2, h_pad=0.3, w_pad=0.0)
    pp.savefig()
    plt.close()
    print('Wrote: {:s}'.format(outfil))
    # Finish
    pp.close()