Esempio n. 1
0
def test_collate(spec,spec2):
    coll_spec = ltsu.collate([spec,spec2], masking='edges')
    assert coll_spec.nspec == 2
    assert coll_spec.totpix == 20379
    # Now a 2 and a 1
    coll_spec2 = ltsu.collate([coll_spec,spec2], masking='edges')
    assert coll_spec2.nspec == 3
    assert coll_spec2.totpix == 20379
Esempio n. 2
0
def test_collate(spec, spec2):
    coll_spec = ltsu.collate([spec, spec2], masking='edges')
    assert coll_spec.nspec == 2
    assert coll_spec.totpix == 20379
    # Now a 2 and a 1
    coll_spec2 = ltsu.collate([coll_spec, spec2], masking='edges')
    assert coll_spec2.nspec == 3
    assert coll_spec2.totpix == 20379
Esempio n. 3
0
def coadd_cos_from_x1dfiles(filenames, wv_array=None, A_pix=0.01*u.AA):
    spec_list = []
    #TODO: mask out x1d spectral regions with bad values.
    for filename in filenames:
        sp = readspec(filename)
        import pdb; pdb.set_trace()
        # mask =
        spec_list += [sp]

    # spec_list contains all individual spectra
    specs = collate(spec_list)  # now all in a single XSpectrum1D object

    #rebin
    if wv_array is None:
        # bring them to a unique native wavelength grid using PYPIT
        A_pix = A_pix.to("AA").value
        cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='pixel', A_pix=A_pix)
    else:
        cat_wave = wv_array.to('AA').value

    specs = specs.rebin(cat_wave*u.AA, all=True, do_sig=True, masking='none',grow_bad_sig=True)

    # estimate weights for coaddition (PYPYT)
    sn2, weights = arco.sn_weight(specs)

    # coaddition
    spec1d = arco.one_d_coadd(specs, weights)
    return spec1d
Esempio n. 4
0
def load_spec(files, iextensions=None, extract='opt', flux=True):
    """ Load a list of spectra into one XSpectrum1D object

    Parameters
    ----------
    files : list
      List of filenames
    iextensions : int or list, optional
      List of extensions, 1 per filename
      or an int which is the extension in each file
    extract : str, optional
      Extraction method ('opt', 'box')
    flux : bool, optional
      Apply to fluxed spectra?

    Returns
    -------
    spectra : XSpectrum1D
      -- All spectra are collated in this one object
    """
    from linetools.spectra.utils import collate
    # Extensions
    if iextensions is None:
        msgs.warn("Extensions not provided.  Assuming first extension for all")
        extensions = np.ones(len(files), dtype='int8')
    elif isinstance(iextensions, int):
        extensions = np.ones(len(files), dtype='int8') * iextensions
    else:
        extensions = np.array(iextensions)

    # Load spectra
    spectra_list = []
    for ii, fname in enumerate(files):
        msgs.info("Loading extension {:d} of spectrum {:s}".format(
            extensions[ii], fname))
        spectrum = arload.load_1dspec(fname,
                                      exten=extensions[ii],
                                      extract=extract,
                                      flux=flux)
        # Polish a bit -- Deal with NAN, inf, and *very* large values that will exceed
        #   the floating point precision of float32 for var which is sig**2 (i.e. 1e38)
        bad_flux = np.any([
            np.isnan(spectrum.flux),
            np.isinf(spectrum.flux),
            np.abs(spectrum.flux) > 1e30,
            spectrum.sig**2 > 1e10,
        ],
                          axis=0)
        if np.sum(bad_flux):
            msgs.warn(
                "There are some bad flux values in this spectrum.  Will zero them out and mask them (not ideal)"
            )
            spectrum.data['flux'][spectrum.select][bad_flux] = 0.
            spectrum.data['sig'][spectrum.select][bad_flux] = 0.
        # Append
        spectra_list.append(spectrum)
    # Join into one XSpectrum1D object
    spectra = collate(spectra_list)
    # Return
    return spectra
Esempio n. 5
0
def ech_load_spec(files, objid=None, order=None, extract='OPT', flux=True):
    """Loading Echelle spectra from a list of PypeIt 1D spectrum fits files
    Parameters:
        files (str) : The list of file names of your spec1d file
        objid (str) : The id (one per fits file) of the object you want to load. (default is the first object)
        order (int) : which order you want to load (default is None, loading all orders)
        extract (str) : 'OPT' or 'BOX'
        flux (bool) : default is True, loading fluxed spectra
    returns:
        spectrum_out : XSpectrum1D
    """

    nfiles = len(files)
    if objid is None:
        objid = ['OBJ0000'] * nfiles
    elif len(objid) == 1:
        objid = objid * nfiles
    elif len(objid) != nfiles:
        msgs.error(
            'The length of objid should be either 1 or equal to the number of spectra files.'
        )

    fname = files[0]
    ext_final = fits.getheader(fname, -1)
    norder = ext_final['ECHORDER'] + 1
    msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder))
    if norder <= 1:
        msgs.error(
            'The number of orders have to be greater than one for echelle. Longslit data?'
        )

    # Load spectra
    spectra_list = []
    for ii, fname in enumerate(files):

        if order is None:
            msgs.info('Loading all orders into a gaint spectra')
            for iord in range(norder):
                spectrum = load_spec_order(fname,
                                           objid=objid[ii],
                                           order=iord,
                                           extract=extract,
                                           flux=flux)
                # Append
                spectra_list.append(spectrum)
        elif order >= norder:
            msgs.error(
                'order number cannot greater than the total number of orders')
        else:
            spectrum = load_spec_order(fname,
                                       objid=objid[ii],
                                       order=order,
                                       extract=extract,
                                       flux=flux)
            # Append
            spectra_list.append(spectrum)
    # Join into one XSpectrum1D object
    spectra = collate(spectra_list)
    # Return
    return spectra
Esempio n. 6
0
def coadd_cos_from_x1dfiles(filenames, wv_array=None, A_pix=0.01 * u.AA):
    spec_list = []
    #TODO: mask out x1d spectral regions with bad values.
    for filename in filenames:
        sp = readspec(filename)
        import pdb
        pdb.set_trace()
        # mask =
        spec_list += [sp]

    # spec_list contains all individual spectra
    specs = collate(spec_list)  # now all in a single XSpectrum1D object

    #rebin
    if wv_array is None:
        # bring them to a unique native wavelength grid using PYPIT
        A_pix = A_pix.to("AA").value
        cat_wave = arco.new_wave_grid(specs.data['wave'],
                                      wave_method='pixel',
                                      A_pix=A_pix)
    else:
        cat_wave = wv_array.to('AA').value

    specs = specs.rebin(cat_wave * u.AA,
                        all=True,
                        do_sig=True,
                        masking='none',
                        grow_bad_sig=True)

    # estimate weights for coaddition (PYPYT)
    sn2, weights = arco.sn_weight(specs)

    # coaddition
    spec1d = arco.one_d_coadd(specs, weights)
    return spec1d
Esempio n. 7
0
def dummy_spectra(s2n=10., seed=1234, wvmnx=None, npix=None):
    """ Generate a set of normalized spectra with varying wavelength
    and noise

    Parameters
    ----------
    s2n : float, optional

    Returns
    -------
    dspec : XSpectrum1D

    """
    rstate=np.random.RandomState(seed)
    if wvmnx is None:
        wvmnx = [[5000., 6000.],
                [4000.5, 5800.5],
                [4500.8, 6300.8],
                ]
    if npix is None:
        npix = [1000, 1001, 1100]
    slist = []
    for ii, inpix in enumerate(npix):
        wave = np.linspace(wvmnx[ii][0], wvmnx[ii][1], inpix)
        #flux = np.ones_like(wave)
        #sig = np.ones_like(wave) / s2n
        #spec = XSpectrum1D.from_tuple((wave,flux,sig))
        ## Noise and append
        #slist.append(spec.add_noise(seed=seed))
        slist.append(dummy_spectrum(wave=wave, s2n=s2n, rstate=rstate))
    # Collate
    dspec = collate(slist, masking='edges')
    #
    return dspec
Esempio n. 8
0
def test_rebin_to_rest(spec,spec2):
    zarr = np.array([2.1,2.2])
    # Build spectra array
    coll_spec = ltsu.collate([spec,spec2])
    rest_spec = ltsu.rebin_to_rest(coll_spec, zarr, 100*u.km/u.s, debug=False)
    # Test
    assert rest_spec.totpix == 3716
    np.testing.assert_allclose(rest_spec.wvmin.value, 986.3506403, rtol=1e-5)
Esempio n. 9
0
    def spectra_from_meta(self, meta, subset=False, debug=False, **kwargs):
        """ Returns one spectrum per row in the input meta data table
        This meta data table should have been generated by a meta query

        Parameters
        ----------
        meta : Table
          Must include a column 'GROUP' indicating the group for each row
          This automatically generated by any of the meta query methods
        subset : bool, optional
          Return a subset of the spectra if only a fraction of the meta rows have them
          Otherwise raise an Error

        Returns
        -------
        spec : XSpectrum1D
          An object containing all of the spectra
          These are aligned with the input meta table
        sub_meta : Table, optional
          Returned if subset=True
        """
        from linetools.spectra import utils as ltsu
        # Checks
        if 'GROUP' not in meta.keys():
            print("Input meta data table must include a GROUP column")
            print("We suspect yours was not made by a meta query.  Try one")
            raise IOError("And then try again.")
        #
        groups = np.unique(meta['GROUP'].data)
        all_spec = []
        sv_rows = []
        for group in groups:
            sub_meta = meta['GROUP'] == group
            # Grab
            spec = self[group].spec_from_meta(meta[sub_meta])
            if (spec is None) and (not subset):
                print(
                    "One or more rows of your input meta does *not* have spectra"
                )
                raise ValueError(
                    "Use subset=True to return only the subset that do")
            else:
                if spec is not None:
                    all_spec.append(spec)
                    sv_rows.append(np.where(sub_meta)[0])
        # Collate
        spec = ltsu.collate(all_spec, masking='edges')
        # Re-order
        idx = np.concatenate(sv_rows)
        srt = np.argsort(idx)
        spec2 = spec[srt]
        # Return
        if subset:
            return spec2, meta[idx[srt]]
        else:
            return spec2
Esempio n. 10
0
def test_median_ratio_flux():
    """ Test median ratio flux algorithm """
    # Setup
    spec1 = dummy_spectrum(s2n=10)
    spec2 = dummy_spectrum(s2n=10)
    spec2.data['flux'][0,:] *= 2.
    spec = collate([spec1,spec2])
    smask = spec.data['sig'].filled(0.) > 0.
    # Put in a bad pixel
    med_flux = coadd.median_ratio_flux(spec, smask, 1, 0)
    np.testing.assert_allclose(med_flux, 0.5, atol=0.05)
Esempio n. 11
0
def test_smash_spectra(spec,spec2):
    # Try to stack 2 spectra with different wavelengths
    coll_spec = ltsu.collate([spec,spec2])
    with pytest.raises(AssertionError):
        stack = ltsu.smash_spectra(coll_spec)
    # Stack rebinned
    zarr = np.array([2.1,2.2])
    rest_spec = ltsu.rebin_to_rest(coll_spec, zarr, 100*u.km/u.s, debug=False)
    stack = ltsu.smash_spectra(rest_spec, method='average')
    # Test
    assert stack.totpix == 3716
    np.testing.assert_allclose(stack.flux[1].value, -3.3213510, rtol=1e-5)
Esempio n. 12
0
def coadd_stis_from_x1dfiles(filenames, wv_array=None, rebin=None, debug=True):
    """

    Parameters
    ----------
    filenames : list
        List of filenames with x1d STIS data
        Must be of the same object and same
        configuration
    wv_array : Quantity array
        Wavelength array to perform the co-add
    rebin : int, optional
        If given, it rebins the current sampling by
        rebin number of pixels

    Returns
    -------
    spec1d : XSpectrum1D
        Co-added version of all the spectra
    """

    spec_list = []
    for filename in filenames:
        aux = load_single_x1d_stis(filename, debug=debug)
        for sp in aux:
            spec_list += [sp]
    # spec_list contains all echelle orders from different files and multi-extensions
    specs = collate(spec_list)  # now all in a single XSpectrum1D object

    if wv_array is None:
        # bring them to a unique native wavelength grid using PYPIT
        cat_wave = arco.new_wave_grid(specs.data['wave'],
                                      wave_method='velocity')
    else:
        cat_wave = wv_array.to('AA').value
    if rebin is not None:
        rebin = int(rebin)
        cat_wave = cat_wave[::rebin]
    specs = specs.rebin(cat_wave * u.AA,
                        all=True,
                        do_sig=True,
                        masking='none',
                        grow_bad_sig=True)

    # estimate weights for coaddition (PYPYT)
    sn2, weights = arco.sn_weight(specs, smask=None)

    # coaddition
    spec1d = arco.one_d_coadd(specs, None, weights)

    # spec1d = arco.coadd_spectra(specs, wave_grid_method='velocity', scale_method='auto')
    return spec1d
Esempio n. 13
0
def write_magecube_as_xspectrum1d(magecube_filename, airvac='air'):
    magecube = Cube(magecube_filename)
    nw, ny, nx = magecube.shape
    assert nx == 1, "Your magecube does not have the conventional astrometry, where the slit is aligned in the y-axis"

    spec_list = []
    for ii in range(ny):
        sp = magecube[:, ii, 0]
        spec = ntu.xspectrum1d_from_mpdaf_spec(sp, airvac=airvac)
        spec_list += [spec]
    specs = collate(spec_list)
    new_name = magecube_filename.replace('.fits', '_xspec.fits')
    specs.write(new_name)
    return specs
Esempio n. 14
0
def write_magecube_as_xspectrum1d(magecube_filename, airvac='air'):
    magecube = Cube(magecube_filename)
    nw, ny, nx = magecube.shape
    assert nx == 1, "Your magecube does not have the conventional astrometry, where the slit is aligned in the y-axis"

    spec_list = []
    for ii in range(ny):
        sp = magecube[:,ii-1,0]
        spec = ntu.xspectrum1d_from_mpdaf_spec(sp, airvac=airvac)
        spec_list += [spec]
    specs = collate(spec_list)
    new_name = magecube_filename.replace('.fits','_xspec.fits')
    specs.write(new_name)
    return specs
Esempio n. 15
0
def test_readwrite_meta_as_dicts(spec):
    sp = XSpectrum1D.from_tuple((np.array([5,6,7]), np.ones(3), np.ones(3)*0.1))
    sp.meta['headers'][0] = dict(a=1, b='abc')
    sp2 = XSpectrum1D.from_tuple((np.array([8,9,10]), np.ones(3), np.ones(3)*0.1))
    sp2.meta['headers'][0] = dict(c=2, d='efg')
    spec = ltsu.collate([sp,sp2])
    # Write
    spec.write_to_fits(data_path('tmp.fits'))
    spec.write_to_hdf5(data_path('tmp.hdf5'))
    # Read and test
    newspec = io.readspec(data_path('tmp.hdf5'))
    assert newspec.meta['headers'][0]['a'] == 1
    assert newspec.meta['headers'][0]['b'] == 'abc'
    newspec2 = io.readspec(data_path('tmp.fits'))
    assert 'METADATA' in newspec2.meta['headers'][0].keys()
Esempio n. 16
0
def test_readwrite_meta_as_dicts(spec):
    sp = XSpectrum1D.from_tuple((np.array([5, 6,
                                           7]), np.ones(3), np.ones(3) * 0.1))
    sp.meta['headers'][0] = dict(a=1, b='abc')
    sp2 = XSpectrum1D.from_tuple(
        (np.array([8, 9, 10]), np.ones(3), np.ones(3) * 0.1))
    sp2.meta['headers'][0] = dict(c=2, d='efg')
    spec = ltsu.collate([sp, sp2])
    # Write
    spec.write_to_fits(data_path('tmp.fits'))
    spec.write_to_hdf5(data_path('tmp.hdf5'))
    # Read and test
    newspec = io.readspec(data_path('tmp.hdf5'))
    assert newspec.meta['headers'][0]['a'] == 1
    assert newspec.meta['headers'][0]['b'] == 'abc'
    newspec2 = io.readspec(data_path('tmp.fits'))
    assert 'METADATA' in newspec2.meta['headers'][0].keys()
Esempio n. 17
0
def test_slice():
    spec = io.readspec(data_path('UM184_nF.fits'))
    spec2 = io.readspec(data_path('PH957_f.fits'))
    spec3 = spec2.copy()
    # Collate to make a multispec spectrum
    mspec = lsu.collate([spec,spec2,spec3])
    # Array
    newspec = mspec[np.array([0,1])]
    # Test
    assert newspec.nspec == 2
    assert not newspec.co_is_set
    # Int
    newspec2 = mspec[1]
    assert newspec2.nspec == 1
    # Slice
    newspec3 = mspec[0:2]
    assert newspec3.nspec == 2
Esempio n. 18
0
def test_slice():
    spec = io.readspec(data_path('UM184_nF.fits'))
    spec2 = io.readspec(data_path('PH957_f.fits'))
    spec3 = spec2.copy()
    # Collate to make a multispec spectrum
    mspec = lsu.collate([spec, spec2, spec3])
    # Array
    newspec = mspec[np.array([0, 1])]
    # Test
    assert newspec.nspec == 2
    assert not newspec.co_is_set
    # Int
    newspec2 = mspec[1]
    assert newspec2.nspec == 1
    # Slice
    newspec3 = mspec[0:2]
    assert newspec3.nspec == 2
Esempio n. 19
0
def coadd_stis_from_x1dfiles(filenames, wv_array=None, rebin=None, debug=False):
    """

    Parameters
    ----------
    filenames : list
        List of filenames with x1d STIS data
        Must be of the same object and same
        configuration
    wv_array : Quantity array
        Wavelength array to perform the co-add
    rebin : int, optional
        If given, it rebins the current sampling by
        rebin number of pixels

    Returns
    -------
    spec1d : XSpectrum1D
        Co-added version of all the spectra
    """
    spec_list = []
    for filename in filenames:
        aux = load_single_x1d_stis(filename, debug=debug)
        for sp in aux:
            spec_list += [sp]
    # spec_list contains all echelle orders from different files and multi-extensions
    specs = collate(spec_list)  # now all in a single XSpectrum1D object

    if wv_array is None:
        # bring them to a unique native wavelength grid using PYPIT
        cat_wave = arco.new_wave_grid(specs.data['wave'], wave_method='velocity')
    else:
        cat_wave = wv_array.to('AA').value
    if rebin is not None:
        rebin = int(rebin)
        cat_wave = cat_wave[::rebin]
    specs = specs.rebin(cat_wave*u.AA, all=True, do_sig=True, masking='none',grow_bad_sig=True)

    # estimate weights for coaddition (PYPYT)
    sn2, weights = arco.sn_weight(specs, smask=None)

    # coaddition
    spec1d = arco.one_d_coadd(specs, weights)
    return spec1d
Esempio n. 20
0
def ech_load_spec(files,objid=None,order=None,extract='OPT',flux=True):
    """
    files: A list of file names
    objid:
    extract:
    flux:
    """

    nfiles = len(files)
    if objid is None:
        objid = ['OBJ0000'] * nfiles
    elif len(objid) == 1:
        objid = objid * nfiles
    elif len(objid) != nfiles:
        msgs.error('The length of objid should be either 1 or equal to the number of spectra files.')

    fname = files[0]
    ext_final = fits.getheader(fname, -1)
    norder = ext_final['ORDER'] + 1
    msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder))
    if norder <= 1:
        msgs.error('The number of orders have to be greater than one for echelle. Longslit data?')

    # Load spectra
    spectra_list = []
    for ii, fname in enumerate(files):

        if order is None:
            msgs.info('Loading all orders into a gaint spectra')
            for iord in range(norder):
                spectrum = load_spec_order(fname,objid=objid[ii],order=iord,extract=extract,flux=flux)
                # Append
                spectra_list.append(spectrum)
        elif order >= norder:
            msgs.error('order number cannot greater than the total number of orders')
        else:
            spectrum = load_spec_order(fname, objid=objid[ii], order=order, extract=extract, flux=flux)
            # Append
            spectra_list.append(spectrum)
    # Join into one XSpectrum1D object
    spectra = collate(spectra_list)
    # Return
    return spectra
Esempio n. 21
0
def clean(spec, red):
    """
    :param spec: (numpy array) XSpectrum1D objects
    :param red: (numpy array) their redshift values (z)

    :returns:
        rest_spec: (numpy array) truncatted, normalized and restframed XSpectrum1D objects
    """

    import numpy as np
    import astropy.units as u
    from linetools.spectra import utils as ltsu
    from linetools.spectra.xspectrum1d import XSpectrum1D

    r = range(len(spec))

    temp = [np.asarray(spec[i].wavelength / (1 + red[i])) for i in r]
    # truncating each spectra to only include wavelength values from 1000 to 1450
    wv_coverage = [(1000 < entry) & (entry < 1450) for entry in temp]

    wave = np.asarray([spec[i].wavelength[wv_coverage[i]] for i in r])
    flux = np.asarray([spec[i].flux[wv_coverage[i]] for i in r])
    error = np.asarray([spec[i].sig[wv_coverage[i]] for i in r])

    temp = [np.asarray(wave[i] / (1 + red[i])) for i in r]
    # normalizing just between the SiII lines
    wv_norm = [(1260 < entry) & (entry < 1304)
               for entry in temp]  # just between the SiII lines

    flux_range = np.asarray([flux[i][wv_norm[i]] for i in r])
    medians = np.asarray([np.median(flux_range[i]) for i in r])
    norm_flux = np.asarray([(flux[i] / medians[i]) for i in r])

    # getting a single XSpec object to feed into the stack
    spec = [XSpectrum1D(wave[i], norm_flux[i], error[i]) for i in r]
    collate = ltsu.collate(spec)
    rest_spec = ltsu.rebin_to_rest(collate,
                                   red,
                                   300 * u.km / u.s,
                                   grow_bad_sig=True)

    return rest_spec
Esempio n. 22
0
    def spectra_from_meta(self, meta, debug=False):
        """ Returns one spectrum per row in the input meta data table
        This meta data table should have been generated by a meta query

        Parameters
        ----------
        meta : Table
          Must include a column 'GROUP' indicating the group for each row
          This automatically generated by any of the meta query methods

        Returns
        -------
        spec : XSpectrum1D
          An object containing all of the spectra
          These are aligned with the input meta table
        """
        from linetools.spectra import utils as ltsu
        # Checks
        if 'GROUP' not in meta.keys():
            print("Input meta data table must include a GROUP column")
            print("We suspect yours was not made by a meta query.  Try one")
            raise IOError("And then try again.")
        #
        groups = np.unique(meta['GROUP'].data)
        all_spec = []
        sv_rows = []
        for group in groups:
            sub_meta = meta['GROUP'] == group
            sv_rows.append(np.where(sub_meta)[0])
            # Grab
            all_spec.append(self[group].spec_from_meta(meta[sub_meta]))
        # Collate
        spec = ltsu.collate(all_spec)
        # Re-order
        idx = np.concatenate(sv_rows)
        srt = np.argsort(idx)
        spec2 = spec[srt]
        #
        return spec2
Esempio n. 23
0
def specm(spec,spec2):
    specm = ltsu.collate([spec,spec2], masking='edges')
    return specm
def specmr(specr, spec2):  # With bad pixels replaced
    specmr = ltsu.collate([specr, spec2])
    return specmr
Esempio n. 25
0
def make_set(ntrain,
             slines,
             outroot=None,
             tol=1 * u.arcsec,
             igmsp_survey='SDSS_DR7',
             frac_without=0.,
             seed=1234,
             zmin=None,
             zmax=4.5,
             high=False,
             slls=False,
             mix=False,
             low_s2n=False):
    """ Generate a training set

    Parameters
    ----------
    ntrain : int
      Number of training sightlines to generate
    slines : Table
      Table of sightlines without DLAs (usually from SDSS or BOSS)
    igmsp_survey : str, optional
      Dataset name for spectra
    frac_without : float, optional
      Fraction of sightlines (on average) without a DLA
    seed : int, optional
    outroot : str, optional
      Root for output filenames
        root+'.fits' for spectra
        root+'.json' for DLA info
    zmin : float, optional
      Minimum redshift for training; defaults to min(slines['ZEM'])
    zmax : float, optional
      Maximum redshift to train on
    mix : bool, optional
      Mix of SLLS and DLAs
    low_s2n : bool, optional
      Reduce the S/N artificially, i.e. add noise

    Returns
    -------

    """
    from linetools.spectra.utils import collate

    # Init and checks
    igmsp = IgmSpec()
    assert igmsp_survey in igmsp.groups
    rstate = np.random.RandomState(seed)
    rfrac = rstate.random_sample(ntrain)
    if zmin is None:
        zmin = np.min(slines['ZEM'])
    rzem = zmin + rstate.random_sample(ntrain) * (zmax - zmin)
    fNHI = init_fNHI(slls=slls, mix=mix, high=high)

    all_spec = []
    full_dict = {}
    # Begin looping
    for qq in range(ntrain):
        print("qq = {:d}".format(qq))
        full_dict[qq] = {}
        # Grab sightline
        isl = np.argmin(np.abs(slines['ZEM'] - rzem[qq]))
        full_dict[qq]['sl'] = isl  # sightline
        specl, meta = igmsp.spectra_from_coord(
            (slines['RA'][isl], slines['DEC'][isl]),
            groups=['SDSS_DR7'],
            tol=tol,
            verbose=False)
        assert len(meta) == 1
        spec = specl
        # Meta data for header
        mdict = {}
        for key in meta.keys():
            mdict[key] = meta[key][0]
        mhead = Header(mdict)
        # Clear?
        if rfrac[qq] < frac_without:
            spec.meta['headers'][0] = mdict.copy()  #mhead
            all_spec.append(spec)
            full_dict[qq]['nDLA'] = 0
            continue
        # Insert at least one DLA
        spec, dlas = insert_dlas(spec,
                                 mhead['zem_GROUP'],
                                 rstate=rstate,
                                 fNHI=fNHI,
                                 slls=slls,
                                 mix=mix,
                                 high=high,
                                 low_s2n=low_s2n)
        spec.meta['headers'][0] = mdict.copy()  #mhead
        all_spec.append(spec)
        full_dict[qq]['nDLA'] = len(dlas)
        for kk, dla in enumerate(dlas):
            full_dict[qq][kk] = {}
            full_dict[qq][kk]['NHI'] = dla.NHI
            full_dict[qq][kk]['zabs'] = dla.zabs

    # Generate one object
    final_spec = collate(all_spec)
    # Write?
    if outroot is not None:
        # Spectra
        final_spec.write_to_hdf5(outroot + '.hdf5')
        # Dict -> JSON
        gdict = ltu.jsonify(full_dict)
        ltu.savejson(outroot + '.json', gdict,
                     overwrite=True)  #, easy_to_read=True)
    # Return
    return final_spec, full_dict
Esempio n. 26
0
    def __init__(self,
                 redrock_file,
                 parent=None,
                 zdict=None,
                 coadd_dict=None,
                 outfile='tmp.json',
                 unit_test=False,
                 screen_scale=1.,
                 **kwargs):
        QMainWindow.__init__(self, parent)
        """
        redrock_file = str
          Input RedRock output FITS file from our redrock script
        parent : Widget parent, optional
        zsys : float, optional
          intial redshift either from a previous vet_rr json or the original
          rr guesses
        screen_scale : float, optional
          Scale the default sizes for the gui size
        """

        # Load up
        self.outfile = outfile
        self.rr_hdul = fits.open(redrock_file)
        if coadd_dict is not None:
            self.slit_info = {}
            for key in coadd_dict.keys():
                if isinstance(coadd_dict[key], dict):
                    if '2D_xval' in coadd_dict[key].keys():
                        name = coadd_dict[key]['outfile'].replace('.fits', '')
                        self.slit_info[name] = {}
                        self.slit_info[name]['xval'] = coadd_dict[key][
                            '2D_xval']
                        self.slit_info[name]['Gslit'] = coadd_dict[key][
                            'Gemini_slit']
        else:
            self.slit_info = None

        # names, spectra, zs = [], [], []
        names, spectra = [], []
        if zdict is None:
            self.zdict = OrderedDict()
            load_z = True
        else:
            self.zdict = OrderedDict()
            load_z = False
        for hdu in self.rr_hdul[1:]:
            # Grab the spectrum
            spec_file = hdu.name
            # tmp = XSpectrum1D.from_file(spec_file.replace('FITS','fits'))
            spectra.append(
                XSpectrum1D.from_file(spec_file.replace('FITS', 'fits'),
                                      masking='edges'))
            names.append(spec_file.replace('.FITS', ''))
            # RedRock
            data = hdu.data
            # Init the dict
            if load_z:
                self.zdict[names[-1]] = {}
                self.zdict[names[-1]]['zRR'] = data['z']
                self.zdict[names[-1]]['ZQ'] = -99
                self.zdict[names[-1]]['Comment'] = ''
                self.zdict[names[-1]]['z'] = data['z'][0]
            else:
                self.zdict[names[-1]] = zdict[names[-1]]
        # Collate
        ispec = lspu.collate(spectra, masking='edges')
        # Fill
        ispec.labels = names
        ispec.stypes = ['galaxy'] * ispec.nspec
        # ispec.z = zs  # DO NOT SET THE REDSHIFT HERE

        self.RRi = 0

        self.scale = screen_scale

        # Needed to avoid crash in large spectral files
        rcParams['agg.path.chunksize'] = 20000
        # avoid scientific notation in axes tick labels
        rcParams['axes.formatter.useoffset'] = False

        # Build a widget combining several others
        self.main_widget = QWidget()

        # Status bar
        self.create_status_bar()

        # ZQ window
        self.ZQ_widg = ltgsm.EditBox(-99, 'ZQ', '{:d}')
        self.ZQ_values = [-99, -1, 0, 1, 3, 4]
        # Comment window
        self.comment_widg = ltgsm.EditBox('', 'Comment', '{:s}')

        # Grab the pieces and tie together
        self.pltline_widg = ltgl.PlotLinesWidget(status=self.statusBar,
                                                 screen_scale=self.scale)
        self.pltline_widg.setMaximumWidth(300 * self.scale)

        # Hook the spec widget to Plot Line
        self.spec_widg = ltgsp.ExamineSpecWidget(ispec,
                                                 status=self.statusBar,
                                                 parent=self,
                                                 llist=self.pltline_widg.llist,
                                                 screen_scale=self.scale,
                                                 **kwargs)
        # Reset redshift from spec
        # Auto set line list if spec has proper object type
        if hasattr(self.spec_widg.spec, 'stypes'):
            if self.spec_widg.spec.stypes[
                    self.spec_widg.select].lower() == 'galaxy':
                self.pltline_widg.llist = ltgu.set_llist(
                    'Galaxy', in_dict=self.pltline_widg.llist)
            elif self.spec_widg.spec.stypes[
                    self.spec_widg.select].lower() == 'absorber':
                self.pltline_widg.llist = ltgu.set_llist(
                    'Strong', in_dict=self.pltline_widg.llist)
            self.pltline_widg.llist['Plot'] = True
            idx = self.pltline_widg.lists.index(
                self.pltline_widg.llist['List'])
            self.pltline_widg.llist_widget.setCurrentRow(idx)
        #
        self.pltline_widg.spec_widg = self.spec_widg
        # Multi spec
        self.mspec_widg = ltgsp.MultiSpecWidget(self.spec_widg,
                                                extra_method=self)

        self.spec_widg.canvas.mpl_connect('key_press_event', self.on_key)
        self.spec_widg.canvas.mpl_connect('button_press_event', self.on_click)

        self.prev_select = 0  # Index of previous spectrum;  starts at 0

        # Legend -- specific to this GUI
        self.legend = {}
        self.wv_dict = {'*': 3727., '(': 3950., ')': 4940., '_': 6564.}
        self.legend['zoom'] = self.wv_dict
        self.legend['&'] = 'Toggle through ZQ'
        self.legend[
            '#'] = 'Toggle through zRR (WARNING: will not necessary start at the first one)'
        self.legend['%'] = 'Set z=0 (for stars)'
        self.legend['9'] = 'Skip to next spectrum with ZQ=-99'
        self.legend['x'] = 'Next spectrum'
        for key, value in self.legend.items():
            print(key, value)

        # Extras
        extras = QWidget()
        extras.setMinimumWidth(180 * self.scale)
        extras.setMaximumWidth(280 * self.scale)
        vbox = QVBoxLayout()
        qbtn = QPushButton(self)
        qbtn.setText('Quit')
        qbtn.clicked.connect(self.quit)
        vbox.addWidget(self.pltline_widg)
        vbox.addWidget(self.ZQ_widg)
        vbox.addWidget(self.comment_widg)
        vbox.addWidget(self.mspec_widg)
        vbox.addWidget(qbtn)
        extras.setLayout(vbox)

        # Main window
        hbox = QHBoxLayout()
        hbox.addWidget(self.spec_widg)
        hbox.addWidget(extras)

        self.main_widget.setLayout(hbox)

        # Point MainWindow
        self.setCentralWidget(self.main_widget)
        if unit_test:
            self.quit()

        # Giddy up
        self.run_with_select(save=False)
Esempio n. 27
0
def order_phot_scale(spectra,
                     phot_scale_dicts,
                     nsig=3.0,
                     niter=5,
                     debug=False):
    '''
    Scale coadded spectra with photometric data.
    Parameters:
      spectra: XSpectrum1D spectra (longslit) or spectra list (echelle)
      phot_scale_dicts: A dict contains photometric information of each orders (if echelle).
        An example is given below.
        phot_scale_dicts = {0: {'filter': None, 'mag': None, 'mag_type': None, 'masks': None},
                            1: {'filter': 'UKIRT-Y', 'mag': 20.33, 'mag_type': 'AB', 'masks': None},
                            2: {'filter': 'UKIRT-J', 'mag': 20.19, 'mag_type': 'AB', 'masks': None},
                            3: {'filter': 'UKIRT-H', 'mag': 20.02, 'mag_type': 'AB', 'masks': None},
                            4: {'filter': 'UKIRT-K', 'mag': 19.92, 'mag_type': 'AB', 'masks': None}}
      Show QA plot if debug=True
    Return a new scaled XSpectrum1D spectra
    '''

    from pypeit.core.flux_calib import scale_in_filter

    norder = spectra.nspec

    # scaling spectrum order by order.
    spectra_list_new = []
    for iord in range(norder):
        phot_scale_dict = phot_scale_dicts[iord]
        if (phot_scale_dict['filter'] is not None) & (phot_scale_dict['mag']
                                                      is not None):
            speci = scale_in_filter(spectra[iord], phot_scale_dict)
        else:
            #ToDo: Think a better way to do the following
            try:
                spec0 = scale_in_filter(spectra[iord - 1],
                                        phot_scale_dicts[iord - 1])
                speci = spectra[iord]
                med_flux = spec0.data['flux'] / speci.data['flux']
                mn_scale, med_scale, std_scale = stats.sigma_clipped_stats(
                    med_flux, sigma=nsig, iters=niter)
                med_scale = np.minimum(med_scale, 5.0)
                spectra.data['flux'] *= med_scale
                spectra.data['sig'] *= med_scale
                msgs.warn(
                    "Not enough photometric information given. Scaled order {:d} to order {:d}"
                    .format(iord, iord - 1))
            except KeyError:
                msgs.warn(
                    "Not enough photometric information given. Scale order {:d} to order {:d} failed"
                    .format(iord, iord - 1))
                try:
                    spec0 = scale_in_filter(spectra[iord + 1],
                                            phot_scale_dicts[iord + 1])
                    speci = spectra[iord]
                    med_flux = spec0.data['flux'] / speci.data['flux']
                    mn_scale, med_scale, std_scale = stats.sigma_clipped_stats(
                        med_flux, sigma=nsig, iters=niter)
                    med_scale = np.minimum(med_scale, 5.0)
                    speci.data['flux'] *= med_scale
                    speci.data['sig'] *= med_scale
                    msgs.warn(
                        "Not enough photometric information given. Scaled order {:d} to order {:d}"
                        .format(iord, iord + 1))
                except:
                    msgs.warn(
                        "Not enough photometric information given. No scaling on order {:d}"
                        .format(iord))
                    speci = spectra[iord]
        spectra_list_new.append(speci)

        if debug:
            gdp = speci.sig > 0
            plt.plot(spectra[iord].wavelength[gdp],
                     spectra[iord].flux[gdp],
                     'k-',
                     label='raw spectrum')
            plt.plot(speci.wavelength[gdp],
                     speci.flux[gdp],
                     'b-',
                     label='scaled spectrum')
            mny, medy, stdy = stats.sigma_clipped_stats(speci.flux[gdp],
                                                        sigma=3,
                                                        iters=5)
            plt.ylim([0.1 * medy, 4.0 * medy])
            plt.legend()
            plt.xlabel('wavelength')
            plt.ylabel('Flux')
            plt.show()

    return collate(spectra_list_new)
Esempio n. 28
0
def ech_coadd(files,
              objids=None,
              extract='OPT',
              flux=True,
              giantcoadd=False,
              orderscale='median',
              mergeorder=True,
              wave_grid_method='velocity',
              niter=5,
              wave_grid_min=None,
              wave_grid_max=None,
              v_pix=None,
              scale_method='auto',
              do_offset=False,
              sigrej_final=3.,
              do_var_corr=False,
              SN_MIN_MEDSCALE=0.5,
              overlapfrac=0.01,
              num_min_pixels=10,
              phot_scale_dicts=None,
              qafile=None,
              outfile=None,
              do_cr=True,
              debug=False,
              **kwargs):
    """
    routines for coadding spectra observed with echelle spectrograph.
    parameters:
        files (list): file names
        objids (str): objid
        extract (str): 'OPT' or 'BOX'
        flux (bool): fluxed or not
        giantcoadd (bool): coadding order by order or do it at once?
        wave_grid_method (str): default velocity
        niter (int): number of iteration for rejections
        wave_grid_min (float): min wavelength, None means it will find the min value from your spectra
        wave_grid_max (float): max wavelength, None means it will find the max value from your spectra
        v_pix (float): delta velocity, see coadd.py
        scale_method (str): see coadd.py
        do_offset (str): see coadd.py, not implemented yet.
        sigrej_final (float): see coadd.py
        do_var_corr (bool): see coadd.py, default False. It seems True will results in a large error
        SN_MIN_MEDSCALE (float): minimum SNR for scaling different orders
        overlapfrac (float): minimum overlap fraction for scaling different orders.
        qafile (str): name of qafile
        outfile (str): name of coadded spectrum
        do_cr (bool): remove cosmic rays?
        debug (bool): show debug plots?
        kwargs: see coadd.py
    returns:
        spec1d: coadded XSpectrum1D
    """

    nfile = len(files)
    if nfile <= 1:
        msgs.info('Only one spectrum exits coadding...')
        return

    fname = files[0]
    ext_final = fits.getheader(fname, -1)
    norder = ext_final['ECHORDER'] + 1
    msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder))
    if norder <= 1:
        msgs.error(
            'The number of orders have to be greater than one for echelle. Longslit data?'
        )

    if giantcoadd:
        msgs.info('Coadding all orders and exposures at once')
        spectra = load.ech_load_spec(files,
                                     objid=objids,
                                     order=None,
                                     extract=extract,
                                     flux=flux)
        wave_grid = np.zeros((2, spectra.nspec))
        for i in range(spectra.nspec):
            wave_grid[0, i] = spectra[i].wvmin.value
            wave_grid[1, i] = spectra[i].wvmax.value
        ech_kwargs = {
            'echelle': True,
            'wave_grid_min': np.min(wave_grid),
            'wave_grid_max': np.max(wave_grid),
            'v_pix': v_pix
        }
        kwargs.update(ech_kwargs)
        # Coadding
        spec1d = coadd.coadd_spectra(spectra,
                                     wave_grid_method=wave_grid_method,
                                     niter=niter,
                                     scale_method=scale_method,
                                     do_offset=do_offset,
                                     sigrej_final=sigrej_final,
                                     do_var_corr=do_var_corr,
                                     qafile=qafile,
                                     outfile=outfile,
                                     do_cr=do_cr,
                                     debug=debug,
                                     **kwargs)
    else:
        msgs.info('Coadding individual orders first and then merge order')
        spectra_list = []
        # Keywords for Table
        rsp_kwargs = {}
        rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract)
        rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract)
        rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract)
        #wave_grid = np.zeros((2,norder))
        for iord in range(norder):
            spectra = load.ech_load_spec(files,
                                         objid=objids,
                                         order=iord,
                                         extract=extract,
                                         flux=flux)
            ech_kwargs = {
                'echelle': False,
                'wave_grid_min': spectra.wvmin.value,
                'wave_grid_max': spectra.wvmax.value,
                'v_pix': v_pix
            }
            #wave_grid[0,iord] = spectra.wvmin.value
            #wave_grid[1,iord] = spectra.wvmax.value
            kwargs.update(ech_kwargs)
            # Coadding the individual orders
            if qafile is not None:
                qafile_iord = qafile + '_%s' % str(iord)
            else:
                qafile_iord = None
            spec1d_iord = coadd.coadd_spectra(
                spectra,
                wave_grid_method=wave_grid_method,
                niter=niter,
                scale_method=scale_method,
                do_offset=do_offset,
                sigrej_final=sigrej_final,
                do_var_corr=do_var_corr,
                qafile=qafile_iord,
                outfile=None,
                do_cr=do_cr,
                debug=debug,
                **kwargs)
            spectrum = spec_from_array(spec1d_iord.wavelength,
                                       spec1d_iord.flux, spec1d_iord.sig,
                                       **rsp_kwargs)
            spectra_list.append(spectrum)

        spectra_coadd = collate(spectra_list)

        # Rebin the spectra
        # ToDo: we should read in JFH's wavelength grid here.
        # Join into one XSpectrum1D object
        # Final wavelength array
        kwargs['wave_grid_min'] = np.min(
            spectra_coadd.data['wave'][spectra_coadd.data['wave'] > 0])
        kwargs['wave_grid_max'] = np.max(
            spectra_coadd.data['wave'][spectra_coadd.data['wave'] > 0])
        wave_final = coadd.new_wave_grid(spectra_coadd.data['wave'],
                                         wave_method=wave_grid_method,
                                         **kwargs)
        # The rebin function in linetools can not work on collated spectra (i.e. filled 0).
        # Thus I have to rebin the spectra first and then collate again.
        spectra_list_new = []
        for i in range(spectra_coadd.nspec):
            speci = spectra_list[i].rebin(wave_final * units.AA,
                                          all=True,
                                          do_sig=True,
                                          grow_bad_sig=True,
                                          masking='none')
            spectra_list_new.append(speci)
        spectra_coadd_rebin = collate(spectra_list_new)

        ## Note
        if orderscale == 'photometry':
            # Only tested on NIRES.
            if phot_scale_dicts is not None:
                spectra_coadd_rebin = order_phot_scale(spectra_coadd_rebin,
                                                       phot_scale_dicts,
                                                       debug=debug)
            else:
                msgs.warn(
                    'No photometric information is provided. Will use median scale.'
                )
                orderscale = 'median'
        elif orderscale == 'median':
            #rmask = spectra_coadd_rebin.data['sig'].filled(0.) > 0.
            #sn2, weights = coadd.sn_weights(fluxes, sigs, rmask, wave)
            ## scaling different orders
            order_median_scale(spectra_coadd_rebin,
                               nsig=sigrej_final,
                               niter=niter,
                               overlapfrac=overlapfrac,
                               num_min_pixels=num_min_pixels,
                               SN_MIN_MEDSCALE=SN_MIN_MEDSCALE,
                               debug=debug)
        else:
            msgs.warn('No any scaling is performed between different orders.')

        if mergeorder:
            fluxes, sigs, wave = coadd.unpack_spec(spectra_coadd_rebin,
                                                   all_wave=False)
            ## Megering orders
            msgs.info('Merging different orders')
            ## ToDo: Joe claimed not to use pixel depedent weighting.
            weights = 1.0 / sigs**2
            weights[~np.isfinite(weights)] = 0.0
            weight_combine = np.sum(weights, axis=0)
            weight_norm = weights / weight_combine
            weight_norm[np.isnan(weight_norm)] = 1.0
            flux_final = np.sum(fluxes * weight_norm, axis=0)
            sig_final = np.sqrt(np.sum((weight_norm * sigs)**2, axis=0))
            spec1d_final = spec_from_array(wave_final * units.AA, flux_final,
                                           sig_final, **rsp_kwargs)

            if outfile is not None:
                msgs.info(
                    'Saving the final calibrated spectrum as {:s}'.format(
                        outfile))
                coadd.write_to_disk(spec1d_final, outfile)

            if (qafile is not None) or (debug):
                # plot and save qa
                plt.figure(figsize=(12, 6))
                ax1 = plt.axes([0.07, 0.13, 0.9, 0.4])
                ax2 = plt.axes([0.07, 0.55, 0.9, 0.4])
                plt.setp(ax2.get_xticklabels(), visible=False)

                medf = np.median(spec1d_final.flux)
                ylim = (np.sort([0. - 0.3 * medf, 5 * medf]))
                cmap = plt.get_cmap('RdYlBu_r')
                for idx in range(spectra_coadd_rebin.nspec):
                    spectra_coadd_rebin.select = idx
                    color = cmap(float(idx) / spectra_coadd_rebin.nspec)
                    ind_good = spectra_coadd_rebin.sig > 0
                    ax1.plot(spectra_coadd_rebin.wavelength[ind_good],
                             spectra_coadd_rebin.flux[ind_good],
                             color=color)

                if (np.max(spec1d_final.wavelength) > (9000.0 * units.AA)):
                    skytrans_file = resource_filename(
                        'pypeit',
                        '/data/skisim/atm_transmission_secz1.5_1.6mm.dat')
                    skycat = np.genfromtxt(skytrans_file, dtype='float')
                    scale = 0.85 * ylim[1]
                    ax2.plot(skycat[:, 0] * 1e4,
                             skycat[:, 1] * scale,
                             'm-',
                             alpha=0.5)

                ax2.plot(spec1d_final.wavelength,
                         spec1d_final.sig,
                         ls='steps-',
                         color='0.7')
                ax2.plot(spec1d_final.wavelength,
                         spec1d_final.flux,
                         ls='steps-',
                         color='b')

                ax1.set_xlim([
                    np.min(spec1d_final.wavelength.value),
                    np.max(spec1d_final.wavelength.value)
                ])
                ax2.set_xlim([
                    np.min(spec1d_final.wavelength.value),
                    np.max(spec1d_final.wavelength.value)
                ])
                ax1.set_ylim(ylim)
                ax2.set_ylim(ylim)
                ax1.set_xlabel('Wavelength (Angstrom)')
                ax1.set_ylabel('Flux')
                ax2.set_ylabel('Flux')

                plt.tight_layout(pad=0.2, h_pad=0., w_pad=0.2)

                if len(qafile.split('.')) == 1:
                    msgs.info(
                        "No fomat given for the qafile, save to PDF format.")
                    qafile = qafile + '.pdf'
                if qafile:
                    plt.savefig(qafile)
                    msgs.info("Wrote coadd QA: {:s}".format(qafile))
                if debug:
                    plt.show()
                plt.close()

            ### Do NOT remove this part althoug it is deprecated.
            # we may need back to using this pieces of code after fixing the coadd.coadd_spectra problem on first order.
            #kwargs['echelle'] = True
            #kwargs['wave_grid_min'] = np.min(wave_grid)
            #kwargs['wave_grid_max'] = np.max(wave_grid)
            #spec1d_final = coadd.coadd_spectra(spectra_coadd_rebin, wave_grid_method=wave_grid_method, niter=niter,
            #                                  scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final,
            #                                  do_var_corr=do_var_corr, qafile=qafile, outfile=outfile,
            #                                  do_cr=do_cr, debug=debug, **kwargs)
            return spec1d_final
        else:
            msgs.warn('Skipped merging orders')
            if outfile is not None:
                for iord in range(len(spectra_list)):
                    outfile_iord = outfile.replace(
                        '.fits', '_ORDER{:04d}.fits'.format(iord))
                    msgs.info(
                        'Saving the final calibrated spectrum of order {:d} as {:s}'
                        .format(iord, outfile))
                    spectra_list[iord].write_to_fits(outfile_iord)
            return spectra_list
Esempio n. 29
0
def test_collate(spec,spec2):
    coll_spec = ltsu.collate([spec,spec2])
    assert coll_spec.nspec == 2
    assert coll_spec.totpix == 20379
Esempio n. 30
0
def specmr(specr, spec2):  # With bad pixels replaced
    specmr = ltsu.collate([specr, spec2], masking='edges')
    return specmr
Esempio n. 31
0
def specm(spec, spec2):
    specm = ltsu.collate([spec, spec2], masking='edges')
    return specm
Esempio n. 32
0
def stacks(spec, red, N, zbin, plot=False):
    """
    :param spec: (numpy array) XSpectrum1D objects
    :param red: (numpy array) their redshift values (z)
    :param N: (int) number of bootstrap iterations
    :param zbin: (str) redshift bin "lowz" or "hiz"
    """

    import numpy as np
    from astropy.io import fits
    from numpy import random as ran
    from linetools.spectra import utils as ltsu
    from linetools.spectra.xspectrum1d import XSpectrum1D

    print("Number of spectra provided =", spec.nspec)

    # the actual stack
    stack = ltsu.smash_spectra(spec)
    z_med = np.median(red)

    # the bootstrap
    R = (spec.nspec)  # restraints on the random variable
    N_stack = []
    N_z_med = []

    for i in np.arange(N):  # this might take a while

        if i % 10 == 0:
            print(i)
        choice = np.asarray(ran.randint(0, R, R))  # the shuffle

        rand_spec = np.asarray([spec[index] for index in choice])
        rand_red = np.asarray([red[index] for index in choice])

        rand_collate = ltsu.collate(rand_spec)  # collate and stack
        N_stack.append(ltsu.smash_spectra(rand_collate))
        N_z_med.append(np.median(rand_red))

    # matrix math to create the error array
    N_flux = np.array([entry.flux for entry in N_stack])
    N_matrix = np.array([N_flux[i] - stack.flux for i in range(N)])

    tranpose = np.transpose(N_matrix)  # matrix math
    covariance = np.dot(tranpose, N_matrix)
    sigma = np.sqrt(np.diagonal(covariance) / (N - 1))  # the final error array

    composite = XSpectrum1D(stack.wavelength, stack.flux, sig=sigma)
    # plot with bootstrap generated error
    if plot == True:
        composite.plot()

    # writing out the stack
    hdr = fits.Header()
    hdr["REDSHIFT"] = z_med
    hdr["NSPEC"] = spec.nspec
    header = fits.PrimaryHDU(header=hdr)

    c_wave = fits.Column(name='WAVELENGTH', array=stack.wavelength, unit="angstroms", format="E")
    c_flux = fits.Column(name='FLUX', array=stack.flux, unit="relative flux", format="E")
    c_noise = fits.Column(name='FLUX_ERR', array=sigma, unit="relative flux", format="E")
    table = fits.BinTableHDU.from_columns([c_wave, c_flux, c_noise])

    full_hdu = fits.HDUList([header, table])
    full_hdu.writeto("../../fits/composites/" + zbin + "/composite.fits")

    # writing out the boostrap
    hdr = fits.Header()
    hdr["NSPEC"] = spec.nspec
    hdr["NBOOT"] = N
    header = fits.PrimaryHDU(header=hdr)

    c_wave = fits.Column(name='WAVELENGTH', array=stack.wavelength, unit="angstroms", format="E")
    c_noise = fits.Column(name='FLUX_ERR', array=sigma, unit="relative flux", format="E")
    table = fits.BinTableHDU.from_columns([c_wave, c_noise])

    flux_data = fits.ImageHDU(N_flux, name="FLUX_ITERATIONS")

    full_hdu = fits.HDUList([header, table, flux_data])
    full_hdu.writeto("../../fits/bootstrap/" + zbin + "/stacks.fits")
Esempio n. 33
0
def build_spectra(tpe, spec_tbl=None, outfil=None):
    """ Generate an XSpectrum1D object of TPE spectra
    Parameters
    ----------
    tpe : Table
    spec_tbl : str or Table, optional
    outfil : str, optional

    Returns
    -------
    spec : XSpectrum1D

    """
    from specdb.build import utils as spbu
    from linetools.spectra import utils as ltspu
    # Grab spectra table -- might read from disk eventually
    if spec_tbl is not None:
        if isinstance(spec_tbl, Table):
            pass
        elif isinstance(spec_tbl, basestring):
            spec_tbl = Table.read(spec_tbl)
    else:
        spec_tbl = get_spec_meta(tpe)
    assert len(tpe) == len(spec_tbl)
    # Load spectral sets
    igmsp = IgmSpec()
    qpq = IgmSpec(db_file=qpq_file, skip_test=True)
    # Grab igmspec spectra
    iigms = spec_tbl['DBASE'] == 'igmspec'
    sub_meta = spec_tbl[['GROUP', 'GROUP_ID']][iigms]
    igm_spec = igmsp.spectra_from_meta(sub_meta)
    # Grab QPQ
    iqpq = spec_tbl['DBASE'] == 'qpq'
    sub_meta = spec_tbl[['GROUP', 'GROUP_ID']][iqpq]
    qpq_spec = qpq.spectra_from_meta(sub_meta)
    # Cut TPE
    gdtpe = spec_tbl['GROUP_ID'] >= 0
    cut_tpe = tpe[gdtpe]
    cut_stbl = spec_tbl[gdtpe]
    if np.sum(~gdtpe) > 0:
        print("These pairs had no good b/g spectrum")
        print(tpe[['BG_RA', 'BG_DEC']][~gdtpe])
    # Collate
    coll_spec = ltspu.collate([igm_spec, qpq_spec])
    # Reorder to match cut_tpe
    idxi = np.where(iigms)[0]
    idxq = np.where(iqpq)[0]
    alli = np.concatenate([idxi, idxq])
    isrt = np.argsort(alli)
    fin_spec = coll_spec[isrt]
    # Check continua
    has_co = chk_continua(fin_spec, cut_tpe['FG_Z'])
    cut_stbl['HAS_CO'] = has_co
    if np.sum(~has_co) > 0:
        print("These spectra need a continuum")
        print(cut_stbl[['SPEC_FILE']][~has_co])
    # Write
    if outfil is not None:
        hdf = h5py.File(outfil, 'w')
        fin_spec.write_to_hdf5('dumb', hdf5=hdf)
        # Add Tables
        spbu.clean_table_for_hdf(cut_tpe)
        hdf['TPE'] = cut_tpe
        spbu.clean_table_for_hdf(cut_stbl)
        hdf['SPEC_TBL'] = cut_stbl
        # Close
        hdf.close()
        print("Wrote: {:s}".format(outfil))
    return cut_tpe, cut_stbl, fin_spec
Esempio n. 34
0
def specm(spec, spec2):
    specm = ltsu.collate([spec, spec2])
    return specm
Esempio n. 35
0
def specmr(specr,spec2):  # With bad pixels replaced
    specmr = ltsu.collate([specr,spec2], masking='edges')
    return specmr
Esempio n. 36
0
def ech_coadd(files,objids=None,extract='OPT',flux=True,giantcoadd=False,
              wave_grid_method='velocity', niter=5,wave_grid_min=None, wave_grid_max=None,v_pix=None,
              scale_method='auto', do_offset=False, sigrej_final=3.,do_var_corr=False,
              qafile=None, outfile=None,do_cr=True, debug=False,**kwargs):

    nfile = len(files)
    if nfile <=1:
        msgs.info('Only one spectrum exits coadding...')
        return

    fname = files[0]
    ext_final = fits.getheader(fname, -1)
    norder = ext_final['ORDER'] + 1
    msgs.info('spectrum {:s} has {:d} orders'.format(fname, norder))
    if norder <= 1:
        msgs.error('The number of orders have to be greater than one for echelle. Longslit data?')

    if giantcoadd:
        msgs.info('Coadding all orders and exposures at once')
        spectra = ech_load_spec(files, objid=objids,order=None, extract=extract, flux=flux)
        wave_grid = np.zeros((2,spectra.nspec))
        for i in range(spectra.nspec):
            wave_grid[0, i] = spectra[i].wvmin.value
            wave_grid[1, i] = spectra[i].wvmax.value
        ech_kwargs = {'echelle': True, 'wave_grid_min': np.min(wave_grid), 'wave_grid_max': np.max(wave_grid),
                      'v_pix': v_pix}
        kwargs.update(ech_kwargs)
        # Coadding
        spec1d = coadd.coadd_spectra(spectra, wave_grid_method=wave_grid_method, niter=niter,
                                          scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final,
                                          do_var_corr=do_var_corr, qafile=qafile, outfile=outfile,
                                          do_cr=do_cr, debug=debug,**kwargs)
    else:
        msgs.info('Coadding individual orders first and then merge order')
        spectra_list = []
        # Keywords for Table
        rsp_kwargs = {}
        rsp_kwargs['wave_tag'] = '{:s}_WAVE'.format(extract)
        rsp_kwargs['flux_tag'] = '{:s}_FLAM'.format(extract)
        rsp_kwargs['sig_tag'] = '{:s}_FLAM_SIG'.format(extract)
        wave_grid = np.zeros((2,norder))
        for iord in range(norder):
            spectra = ech_load_spec(files, objid=objids, order=iord, extract=extract, flux=flux)
            ech_kwargs = {'echelle': False, 'wave_grid_min': spectra.wvmin.value, 'wave_grid_max': spectra.wvmax.value, 'v_pix': v_pix}
            wave_grid[0,iord] = spectra.wvmin.value
            wave_grid[1,iord] = spectra.wvmax.value
            kwargs.update(ech_kwargs)
            # Coadding the individual orders
            if qafile is not None:
                qafile_iord = qafile+'_%s'%str(iord)
            else:
                qafile_iord =  None
            spec1d_iord = coadd.coadd_spectra(spectra, wave_grid_method=wave_grid_method, niter=niter,
                                       scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final,
                                       do_var_corr=do_var_corr, qafile=qafile_iord, outfile=outfile,
                                       do_cr=do_cr, debug=debug, **kwargs)
            spectrum = spec_from_array(spec1d_iord.wavelength, spec1d_iord.flux, spec1d_iord.sig,**rsp_kwargs)
            spectra_list.append(spectrum)
        # Join into one XSpectrum1D object
        spectra_coadd = collate(spectra_list)
        kwargs['echelle'] = True
        kwargs['wave_grid_min'] = np.min(wave_grid)
        kwargs['wave_grid_max'] = np.max(wave_grid)
        # ToDo: Currently I'm not using the first order due to some problem. Need to add it back after fix the problem.
        spec1d = coadd.coadd_spectra(spectra_coadd[1:], wave_grid_method=wave_grid_method, niter=niter,
                                          scale_method=scale_method, do_offset=do_offset, sigrej_final=sigrej_final,
                                          do_var_corr=do_var_corr, qafile=qafile, outfile=outfile,
                                          do_cr=do_cr, debug=debug, **kwargs)

    return spec1d
Esempio n. 37
0
def specm(spec,spec2):
    specm = ltsu.collate([spec,spec2])
    return specm