Esempio n. 1
0
def test_name_to_ion():
    Zion = ions.name_to_ion('Si II')
    assert Zion == (14, 2)
    # bad input
    with pytest.raises(ValueError):
        aux = ions.name_to_ion(4)  # not a string
    # Deuterium
    aux = ions.name_to_ion('DI')
Esempio n. 2
0
def test_name_to_ion():
    Zion = ions.name_to_ion('Si II')
    assert Zion == (14,2)
    # bad input
    with pytest.raises(ValueError):
        aux = ions.name_to_ion(4)  # not a string
    # Deuterium
    aux = ions.name_to_ion('DI')
Esempio n. 3
0
    def component_tbl(self, Zion):
        """ Generate a Table of line measurements for an input ion broken
        down by component.

        Parameters
        ----------
        Zion : tuple or str
            E.g., (8,6) or 'OVI'

        Returns
        -------
        tbl : astropy.Table
        """
        from linetools.abund.ions import name_to_ion
        from linetools.isgm import utils as ltiu
        from astropy.table import Table, vstack, Column

        if isinstance(Zion, basestring):
            Zion = name_to_ion(Zion)
        newcomptab = Table()
        rhos = []
        names = []
        for i, isys in enumerate(self.cgm_abs):
            isys.igm_sys.update_component_vel()
            comptab = ltiu.table_from_complist(isys.igm_sys._components)
            comptab = comptab[(comptab['Z'] == Zion[0])
                              & (comptab['ion'] == Zion[1])]
            if len(comptab) == 0:
                continue
            newcomptab = vstack([newcomptab, comptab])
            rhos.extend([isys.rho.value] * len(comptab))
            names.extend([isys.name] * len(comptab))
        newcomptab.add_column(Column(names, name='cgm_name'))
        newcomptab.add_column(Column(rhos * u.kpc, name='rho_impact'))
        return newcomptab
Esempio n. 4
0
    def ion_tbl(self, Zion, fill_ion=True):
        """ Generate a Table of Ionic column densities for an input ion

        Parameters
        ----------
        Zion : tuple or str
        fill_ion : bool, optional
          Fill each ionN table in the survey (a bit slow)

        Returns
        -------
        tbl : astropy.Table
        """
        from linetools.abund.ions import name_to_ion
        if isinstance(Zion, basestring):
            Zion = name_to_ion(Zion)
        # Generate dummy IGMSurvey
        dumb = GenericIGMSurvey()
        names = []
        for cgmabs in self.cgm_abs:
            if fill_ion:
                cgmabs.igm_sys.fill_ionN()
            if cgmabs.igm_sys._ionN is not None:
                dumb._abs_sys.append(cgmabs.igm_sys)
                # Names
                names.append(cgmabs.name)
        # Run ions
        tbl = dumb.ions(Zion)
        # Add CGM name
        tbl.add_column(Column(names, name='cgm_name'))
        # Return
        return tbl
Esempio n. 5
0
def get_components(obj, ion, zrange=None):
    """Return list of components from AbsSystem or IGMSightline for given ion

    Parameters
    ----------
    obj : AbsSystem or IGMSightline
        Object that has attribute 'Zion'
    ion : tuple or str, optional
        Zion tuple or ion name; e.g., (8,6) for OVI
    zrange : tuple, optional
        Range in redshift over which to look for components

    Returns
    -------
    complist : list
        List of components with given ion
    """
    if isinstance(ion, str):
        from linetools.abund.ions import name_to_ion
        Zion = name_to_ion(ion)
    else:
        Zion = ion
    if zrange is None:
        complist = [comp for comp in obj._components if comp.Zion == Zion]
    else:
        complist = [
            comp for comp in obj._components
            if ((comp.Zion == Zion) & (comp.zcomp > zrange[0])
                & (comp.zcomp < zrange))
        ]
    return complist
Esempio n. 6
0
def main(args=None):
    pargs = parser(options=args)
    if pargs.inp is None and pargs.all is False:
        print("No option selected.  Use -h for Help")
        return
    # Setup
    from astropy import units as u
    from astropy.table import Column
    from linetools.lists.linelist import LineList
    from linetools.abund import ions as ltai
    import numpy as np
    if pargs.llist in ['CO']:
        cols = ['mol', 'label', 'wrest', 'f']
    elif pargs.llist in ['H2']:
        cols = ['mol', 'name', 'wrest', 'f']
    else:
        cols = ['name', 'wrest', 'f', 'A', 'Ref']
    # LineList
    llist = LineList(pargs.llist)
    # Redshift?
    if float(pargs.redshift) != 0.:
        z = llist._data['wrest']*(1+float(pargs.redshift))
        llist._data.add_column(Column(z, name='z'))
        cols += ['z']
    # All?
    if pargs.all:
        try:
            llist._data[cols].pprint(99999)
        except ValueError:
            pdb.set_trace()
        return
    # Grab line(s)
    if ustr(pargs.inp[0]).isdecimal():  # Input rest wavelength
        wrest = float(pargs.inp)*u.AA
        mtch = np.abs(wrest-llist.wrest) < pargs.toler*u.AA
        llist._data[cols][mtch].pprint(99999)
    else:  # Either ion or transition
        istrans = False
        for jj,char in enumerate(pargs.inp):
            if char.isdigit():
                istrans = True
                i0 = jj
                break
        if istrans:
            trans = pargs.inp[0:i0]+' '+pargs.inp[i0:]
            tdict = llist[trans]
            for key,value in tdict.items():
                if key in cols:
                    print('{:s}: {}'.format(key,value))
        else:  # Ion
            Zion = ltai.name_to_ion(pargs.inp)
            mtion = (llist.Z == Zion[0]) & (llist.ion == Zion[1])
            llist._data[cols][mtion].pprint(99999)
Esempio n. 7
0
def dict_to_ions(idict):
    """  Manipulate dict into an ion astropy Table

    Will likely be deprecated

    Parameters
    ----------
    idict : dict

    Returns
    -------
    table : astropy.Table

    """
    #  Could probably use add_row or dict instantiation
    table = None
    for ion in idict.keys():
        Zion = ltai.name_to_ion(ion)
        if table is None:
            tkeys = idict[ion].keys()
            lst = [[idict[ion][tkey]] for tkey in tkeys]
            table = Table(lst, names=tkeys)
            # Extra columns
            if 'Z' not in tkeys:
                table.add_column(Column([Zion[0]], name='Z'))
                table.add_column(Column([Zion[1]], name='ion'))
        else:
            tdict = idict[ion]
            tkeys = idict[ion].keys()
            if 'Z' not in tkeys:
                tdict['Z'] = Zion[0]
                tdict['ion'] = Zion[1]
            # Add
            table.add_row(tdict)
    # Finish
    try:  # Historical keys
        table.rename_column('clm', 'logN')
    except:
        pass
    else:
        table.rename_column('sig_clm', 'sig_logN')
        table.rename_column('flg_clm', 'flag_N')
    # Return
    return table
Esempio n. 8
0
    def ion_tbl(self, Zion, fill_ion=True, vrange=None, **kwargs):
        """ Generate a Table of Ionic column densities for an input ion

        Parameters
        ----------
        Zion : tuple or str
        fill_ion : bool, optional
          Fill each ionN table in the survey (a bit slow)
        vrange : Quantity, optional
          Velocity range of components to sum column densities

        Returns
        -------
        tbl : astropy.Table
           Returns None if there are no matches to input Zion
        """
        from linetools.abund.ions import name_to_ion
        if isinstance(Zion, basestring):
            Zion = name_to_ion(Zion)

        # Generate dummy IGMSurvey
        dumb = GenericIGMSurvey()
        names = []
        rhos = []
        for cgmabs in self.cgm_abs:
            if fill_ion:
                cgmabs.igm_sys.fill_ionN(vrange=vrange, summed_ion=True)
            if cgmabs.igm_sys._ionN is not None:
                dumb._abs_sys.append(cgmabs.igm_sys)
                # Names
                names.append(cgmabs.name)
                # Impact parameters
                rhos.append(cgmabs.rho.to(u.kpc).value)
        # Run ions
        tbl = dumb.ions(Zion, skip_null=False, **kwargs)
        if tbl is None:
            return None
        tbl.add_column(Column(names, name='cgm_name'))
        # Add impact parameter
        tbl.add_column(Column(rhos * u.kpc, name='rho_impact'))
        # Return
        return tbl
Esempio n. 9
0
def tripp2005():
    '''Tripp, T. et al. 2005, ApJ, 2005, 619, 714
    PG 1216+069 (LLS in Virgo)
    HST/STIS, FUSE
    Metal columns parsed from Tables 2 and 3
    Total NHI from damping wings
    M/H from O/H
    '''
    # Grab ASCII files from ApJ
    tab_fils = [
        pyigm_path + "/data/LLS/tripp2005.tb3.ascii",
        pyigm_path + "/data/LLS/tripp2005.tb2.ascii"
    ]
    urls = [
        'http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb3.txt',
        'http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb2.txt'
    ]
    for jj, tab_fil in enumerate(tab_fils):
        chk_fil = glob.glob(tab_fil)
        if len(chk_fil) > 0:
            tab_fil = chk_fil[0]
        else:
            url = urls[jj]
            print('LLSSurvey: Grabbing table file from {:s}'.format(url))
            f = urlopen(url)
            with open(tab_fil, "wb") as code:
                code.write(f.read())
    # Setup
    radec = '121920.9320+063838.476'  # SIMBAD
    lls = LLSSystem(name='PG1216+069_z0.006',
                    radec=radec,
                    zem=0.3313,
                    zabs=0.00632,
                    vlim=[-100., 100.] * u.km / u.s,
                    NHI=19.32,
                    ZH=-1.6,
                    sig_NHI=np.array([0.03, 0.03]))

    # Columns
    # Start with Table 3 (VPFIT)
    with open(tab_fils[0], 'r') as f:
        flines3 = f.readlines()
    ion_dict = {}
    for iline in flines3:
        if (len(iline.strip()) == 0):
            continue
        isplit = iline.split('\t')
        # Ion
        flg = 2
        if (len(isplit[0].strip()) > 0):  # & (isplit[0][0] not in ['1','2']):
            ipos = isplit[0].find('1')
            ionc = isplit[0][0:ipos - 1].strip()
            try:
                Zion = ltai.name_to_ion(ionc)
            except KeyError:
                pdb.set_trace()
            flg = 1
        # Column
        csplit = isplit[3].split(' ')
        clm = float(csplit[0])
        sig = float(csplit[2])
        if flg == 1:
            ion_dict[ionc] = dict(logN=clm,
                                  sig_logN=sig,
                                  flag_N=1,
                                  Z=Zion[0],
                                  ion=Zion[1])
        else:  # Add it in
            tmp_dict = dict(logN=clm,
                            sig_logN=sig,
                            flag_N=1,
                            Z=Zion[0],
                            ion=Zion[1])
            flagN, logN, siglogN = ltaa.sum_logN(ion_dict[ionc], tmp_dict)
            ion_dict[ionc]['logN'] = logN
            ion_dict[ionc]['sig_logN'] = siglogN
    ions = ion_dict.keys()

    # Now Table 2 for the extras
    with open(tab_fils[1], 'r') as f:
        flines2 = f.readlines()
    # Trim the first 10 lines
    flines2 = flines2[10:]
    # Loop
    for iline in flines2:
        isplit = iline.split('\t')
        #
        ionc = isplit[0].strip()
        if (len(ionc) == 0) or (ionc in ions):
            continue
        #
        Zion = ltai.name_to_ion(ionc)
        ion_dict[ionc] = dict(Z=Zion[0], ion=Zion[1], sig_logN=0.)
        if isplit[4][0] == '<':
            ion_dict[ionc]['logN'] = float(isplit[4][1:])
            ion_dict[ionc]['flag_N'] = 3
        else:
            raise ValueError('Should not get here')

    # Finish
    lls._ionN = pyiau.dict_to_ions(ion_dict)
    lls.Refs.append('Tri05')
    return lls
Esempio n. 10
0
def complist_from_table(table):
    """
    Returns a list of AbsComponents from an input astropy.Table.

    Parameters
    ----------
    table : Table
        Table with component information (each row must correspond
        to a component). Each column is expecting a unit when
        appropriate.

    Returns
    -------
    complist : list
        List of AbsComponents defined from the input table.

    Notes
    -----
    Mandatory column names: 'RA', 'DEC', 'ion_name', 'z_comp', 'vmin', 'vmax'
        These column are required.
    Special column names: 'name', 'comment', 'logN', 'sig_logN', 'flag_logN'
        These columns will fill internal attributes when corresponding.
        In order to fill in the Ntuple attribute all three 'logN', 'sig_logN', 'flag_logN'
        must be present. For convenience 'logN' and 'sig_logN' are expected to be floats
        corresponding to their values in np.log10(1/cm^2).

    Other columns: 'any_column_name'
        These will be added as attributes within the AbsComponent.attrib dictionary,
        with their respective units if given.

    """
    # Convert to QTable to handle units in individual entries more easily
    table = QTable(table)

    # mandatory and optional columns
    min_columns = ['RA', 'DEC', 'ion_name', 'z_comp', 'vmin', 'vmax']
    special_columns = ['name', 'comment', 'logN', 'sig_logN', 'flag_logN']
    for colname in min_columns:
        if colname not in table.keys():
            raise IOError(
                '{} is a mandatory column. Please make sure your input table has it.'
                .format(colname))

    #loop over rows
    complist = []
    for row in table:
        # mandatory
        coord = SkyCoord(row['RA'].to('deg').value,
                         row['DEC'].to('deg').value,
                         unit='deg')  # RA y DEC must both come with units
        Zion = name_to_ion(row['ion_name'])
        zcomp = row['z_comp']
        vlim = [row['vmin'].to('km/s').value, row['vmax'].to('km/s').value
                ] * u.km / u.s  # units are expected here too

        # special columns
        try:
            Ntuple = (row['flag_logN'], row['logN'], row['sig_logN']
                      )  # no units expected
        except KeyError:
            Ntuple = None
        try:
            comment = row['comment']
        except KeyError:
            comment = ''
        try:
            name = row['name']
        except KeyError:
            name = None

        # define the component
        comp = AbsComponent(coord,
                            Zion,
                            zcomp,
                            vlim,
                            Ntup=Ntuple,
                            comment=comment,
                            name=name)

        # other columns will be filled in comp.attrib dict
        for colname in table.keys():
            if (colname not in special_columns) and (colname
                                                     not in min_columns):
                kms_cols = ['b', 'sig_b']
                if colname in kms_cols:  # check units for parameters expected in velocity units
                    try:
                        val_aux = row[colname].to('km/s').value * u.km / u.s
                    except u.UnitConversionError:
                        raise IOError(
                            'If `{}` column is present, it must have velocity units.'
                            .format(colname))
                    comp.attrib[colname] = val_aux
                # parameters we do not care about units much
                else:
                    comp.attrib[colname] = row[colname]

        # append
        complist += [comp]
    return complist
Esempio n. 11
0
def dessauges09():
    '''Dessauges-Zavadsky et al. 2009, MNRAS, 396, L96
    SLLS with UVES
    Zn,Fe abundances from Table 1 from astro-ph (LateX) by JXP [AODM]
     Taken from the Zn/H and Fe/H assuming *no* ionization corrections
    RA/DEC from the 'other' name 
    '''
    # Solar abundances
    eZn = 4.63
    eFe = 7.45
    sol = [eFe, eZn]
    #
    all_lls = []
    # Table 1
    tab_fil = pyigm_path + "/data/LLS/Literature/dessauges09.tb1.ascii"
    with open(tab_fil, 'r') as f:
        flines1 = f.readlines()
    # Trim the first few lines
    flines1 = flines1[3:]
    for iline in flines1:
        # Parse
        isplit = iline.split('&')
        # QSO
        if iline[0:2] == 'QS':
            # QSO, RA/DEC, zem
            qso = isplit[0][4:].strip()
            radec = isplit[1].strip()[1:].replace('$', '')
            zem = float(isplit[3].strip())
        # NHI, zabs
        zabs = float(isplit[4].strip())
        is2 = isplit[6].strip()
        NHI = float(is2[1:6])
        sigNHI = np.array([float(is2[10:14])] * 2)
        # name
        name = qso + 'z_{:.3f}'.format(zabs)
        lls = LLSSystem(name=name,
                        radec=radec,
                        vlim=[-500, 500] * u.km / u.s,
                        zem=zem,
                        zabs=zabs,
                        NHI=NHI,
                        sig_NHI=sigNHI)
        # ADOM Columns
        ion_dict = {}
        for kk, ion in enumerate(['Fe II', 'Zn II']):
            Zion = ltai.name_to_ion(ion)
            is2 = isplit[7 + kk].strip()
            if is2[0:2] == '$>':
                ion_dict[ion] = dict(sig_clm=0.,
                                     flg_clm=2,
                                     Z=Zion[0],
                                     ion=Zion[1])
                ion_dict[ion]['clm'] = float(is2[2:7]) + NHI - 12 + sol[kk]
            elif is2[0:2] == '$<':
                ion_dict[ion] = dict(sig_clm=0.,
                                     flg_clm=3,
                                     Z=Zion[0],
                                     ion=Zion[1])
                ion_dict[ion]['clm'] = float(is2[2:7]) + NHI - 12 + sol[kk]
            elif is2[0:2] == '..':
                pass
            else:
                ion_dict[ion] = dict(flg_clm=1, Z=Zion[0], ion=Zion[1])
                ion_dict[ion]['clm'] = float(is2[1:6]) + NHI - 12 + sol[kk]
                ion_dict[ion]['sig_clm'] = float(is2[10:14])
        #xdb.set_trace()
        # Finish
        lls._ionN = pyiau.dict_to_ions(ion_dict)
        lls.Refs.append('DZ09')
        all_lls.append(lls)

    # Return SLLS only
    fin_slls = [ills for ills in all_lls if ills.NHI < 20.3]
    return fin_slls
Esempio n. 12
0
def tumlinson11():
    """Tumlinson, J. et al. 2011, ApJ, 733, 111
    J1009+0713
    HST/COS
    Metal columns parsed from Table 1
    NHI from LL+Lyman series (uncertain)
    """
    # Grab ASCII file from ApJ
    tab_fil = pyigm_path + "/data/LLS/Literature/tumlinson11.tb1.ascii"
    url = 'http://iopscience.iop.org/0004-637X/733/2/111/suppdata/apj388927t1_ascii.txt'
    chk_fil = glob.glob(tab_fil)
    if len(chk_fil) > 0:
        tab_fil = chk_fil[0]
    else:
        print('LLSSurvey: Grabbing table file from {:s}'.format(url))
        f = urlopen(url)
        with open(tab_fil, "wb") as code:
            code.write(f.read())
    # Setup
    radec = '100902.06+071343.8'  # From paper
    lls = LLSSystem(name='J1009+0713_z0.356',
                    radec=radec,
                    zem=0.456,
                    zabs=0.3558,
                    vlim=[-200., 250.] * u.km / u.s,
                    NHI=18.4,
                    sig_NHI=np.array([0.41, 0.41]))

    # Columns
    # Start with Table 3 (VPFIT)
    with open(tab_fil, 'r') as f:
        flines1 = f.readlines()
    # Trim
    flines1 = flines1[18:]
    #
    ion_dict = {}
    line_dict = dict(OI='1302',
                     OVI='1038',
                     MgII='2803^b',
                     SiII='1190',
                     CaII='3934',
                     FeII='2586')
    ion = None
    for iline in flines1:
        isplit = iline.split('\t')
        if ion == 'FeIII':  # Last line
            break
        # Ion
        is2 = isplit[0].split(' ')
        ion = is2[0] + is2[1]
        try:
            gdl = line_dict[ion]
        except:
            pass
            #print('Taking {:s}'.format(isplit[0]))
        else:
            if is2[2] != gdl:
                continue
        Zion = ltai.name_to_ion(ion)
        ion_dict[ion] = dict(logN=0.,
                             sig_logN=0.,
                             flag_N=0,
                             Z=Zion[0],
                             ion=Zion[1])
        # Combine components [could replace with SubSystems some day]
        for iis in isplit[1:-1]:
            # Upper limit
            if (iis.strip()[0] == '<') & (ion_dict[ion]['flag_N'] == 0):
                ion_dict[ion]['flag_N'] = 3
                ion_dict[ion]['logN'] = float(iis[1:])
            elif (iis.strip()[0] == '>'):  # Saturated
                ion_dict[ion]['flag_N'] = 2
                ion_dict[ion]['logN'] = log_sum(
                    [ion_dict[ion]['logN'],
                     float(iis[1:5])])
            elif iis.strip()[0] in ['.', '<']:
                pass
            else:
                if ion_dict[ion]['flag_N'] == 2:  # Add to saturated
                    ion_dict[ion]['logN'] = log_sum(
                        [ion_dict[ion]['logN'],
                         float(iis[0:4])])
                else:
                    ion_dict[ion]['flag_N'] = 1
                    obj = dict(logN=float(iis[0:4]),
                               sig_logN=float(iis[-4:]),
                               flag_N=1)
                    # Add
                    flag, N, sig = ltaa.sum_logN(ion_dict[ion], obj)
                    ion_dict[ion]['logN'] = N
                    ion_dict[ion]['sig_logN'] = sig
    # Finish
    lls._ionN = pyiau.dict_to_ions(ion_dict)
    lls.Refs.append('Tum11')
    return lls
Esempio n. 13
0
def meiring09():
    '''Meiring et al. 2009, MNRAS, 393, 1513
    SLLS with Magellan
    Abundances from Table 3 from astro-ph (LateX) by JXP [AODM]
    RA/DEC from Table 1
    '''
    all_lls = []
    # Table 1
    tab_fil = pyigm_path + "/data/LLS/Literature/meiring09.tb1.ascii"
    with open(tab_fil, 'r') as f:
        flines1 = f.readlines()
    # Grab RA/DEC
    qso_dict = {}
    for iline in flines1:
        if iline[0:3] in [' QS', '\hl', '$\\c', ' J2', '   ']:
            continue
        # Parse
        isplit = iline.split('&')
        #xdb.set_trace()
        if '$' in isplit[3].strip():
            isplit[3] = '-' + (isplit[3].strip())[3:]
        radec = isplit[2].strip() + isplit[3].strip()
        radec = radec.replace(':', '')
        # zem
        zem = float(isplit[5].strip())
        # Save
        qso_dict[isplit[0].strip()] = dict(radec=radec,
                                           zem=zem,
                                           vlim=[-500, 500.] * u.km / u.s)

    # Abundances (AODM)
    # Table 3
    tab_fil = pyigm_path + "/data/LLS/Literature/meiring09.tb3.ascii"
    with open(tab_fil, 'r') as f:
        flines3 = f.readlines()
    #
    for iline in flines3:
        if iline[0:2] in ['\h', '  ']:
            continue
        # Parse
        isplit = iline.split('&')
        # Ions
        if iline[0:2] == 'QS':
            ioncs = []
            Zions = []
            for iis in isplit[3:-1]:  # Skipping HI
                # Parse
                #is2 = iis.split('\\')
                #ip2 = is2[2].find('}')
                ionc = iis.strip()
                # Zion
                Zion = ltai.name_to_ion(ionc)
                # Append
                ioncs.append(ionc)
                Zions.append(Zion)
            continue
        if iline[0] == 'Q':
            # QSO
            qso = isplit[0].strip()
            if qso[-1] in ['A', 'B', 'C']:
                qso = qso[0:-1]
            # zabs and name
            zabs = float(isplit[1].strip())
            qso_dict[qso]['name'] = qso + 'z_{:.3f}'.format(zabs)
            qso_dict[qso]['zabs'] = zabs
            # NHI
            is2 = isplit[2].strip()
            if is2[0] == '$':
                qso_dict[qso]['NHI'] = 99.99  # THROW OUT Q1436-0051B
                qso_dict[qso]['sig_NHI'] = np.array([0., 0.])
            else:
                qso_dict[qso]['NHI'] = float(is2[0:5])
                qso_dict[qso]['sig_NHI'] = np.array([float(is2[10:])] * 2)
            #if qso_dict[qso]['NHI'] >= 20.3:
            #    print('Uh oh.  DLA')
            # Generate LLS
            lls = LLSSystem(**qso_dict[qso])
            continue
        else:
            # ADOM Columns
            ion_dict = {}
            for kk, iis in enumerate(isplit[3:-1]):
                is2 = iis.strip()
                if is2[0:3] == '$>$':
                    ion_dict[ioncs[kk]] = dict(sig_clm=0.,
                                               flg_clm=2,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[3:])
                elif is2[0:3] == '$<$':
                    ion_dict[ioncs[kk]] = dict(sig_clm=0.,
                                               flg_clm=3,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[3:])
                elif len(is2) == 0:
                    pass
                else:
                    ion_dict[ioncs[kk]] = dict(flg_clm=1,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[0:5])
                    ion_dict[ioncs[kk]]['sig_clm'] = float(is2[10:])
            # Finish
            lls._ionN = pyiau.dict_to_ions(ion_dict)
            lls.Refs.append('Mei09')
            all_lls.append(lls)

    # Return SLLS only
    fin_slls = [ills for ills in all_lls if ills.NHI < 20.3]
    return fin_slls
Esempio n. 14
0
def meiring07():
    """Meiring et al. 2007, MNRAS, 376, 557
    SLLS with Magellan
    Abundances from Table 11 from astro-ph (LateX) by JXP [AODM]
    RA/DEC from Table 1
    """
    all_lls = []
    # Table 1
    tab_fil = pyigm_path + "/data/LLS/Literature/meiring07.tb1.ascii"
    with open(tab_fil, 'r') as f:
        flines1 = f.readlines()
    # Grab RA/DEC
    qso_dict = {}
    for iline in flines1:
        if iline[0:2] in ['QS', '\h', '$\\', 'J2']:
            continue
        # Parse
        isplit = iline.split('&')
        if '-' not in isplit[3]:
            sgn = '+'
        else:
            sgn = ''
        radec = isplit[2].strip() + sgn + isplit[3].strip()
        radec = radec.replace(':', '')
        # zem
        if isplit[0].strip() != 'Q0826-2230':
            zem = float(isplit[5].strip())
        else:
            zem = 0.911
        # Save
        qso_dict[isplit[0].strip()] = dict(radec=radec,
                                           zem=zem,
                                           vlim=[-500., 500] * u.km / u.s)
    # Abundances (AODM)
    # Table 11
    tab_fil = pyigm_path + "/data/LLS/Literature/meiring07.tb11.ascii"
    with open(tab_fil, 'r') as f:
        flines11 = f.readlines()
    #
    for iline in flines11:
        if iline[0:2] in ['\h', '  ']:
            continue
        # Parse
        isplit = iline.split('&')
        # Ions
        if iline[0:2] == 'QS':
            ioncs = []
            Zions = []
            for iis in isplit[3:-1]:  # Skipping HI
                # Parse
                is2 = iis.split('\\')
                ip2 = is2[2].find('}')
                ionc = is2[1][2:].strip() + ' ' + is2[2][0:ip2].strip()
                # Zion
                Zion = ltai.name_to_ion(ionc)
                # Append
                ioncs.append(ionc)
                Zions.append(Zion)
            continue
        if iline[0] == 'Q':
            # QSO
            qso = isplit[0].strip()
            # zabs and name
            zabs = float(isplit[1].strip())
            qso_dict[qso]['name'] = qso + 'z_{:.3f}'.format(zabs)
            qso_dict[qso]['zabs'] = zabs
            # NHI
            is2 = isplit[2].strip()
            qso_dict[qso]['NHI'] = float(is2[0:5])
            #if qso_dict[qso]['NHI'] >= 20.3:
            #    print('Uh oh.  DLA')
            qso_dict[qso]['sig_NHI'] = np.array([float(is2[10:])] * 2)
            # Generate LLS
            lls = LLSSystem(**qso_dict[qso])
            continue
        else:
            # ADOM Columns
            ion_dict = {}
            for kk, iis in enumerate(isplit[3:-1]):
                is2 = iis.strip()
                if is2[0:3] == '$>$':
                    ion_dict[ioncs[kk]] = dict(sig_clm=0.,
                                               flg_clm=2,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[3:])
                elif is2[0:3] == '$<$':
                    ion_dict[ioncs[kk]] = dict(sig_clm=0.,
                                               flg_clm=3,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[3:])
                elif len(is2) == 0:
                    pass
                else:
                    ion_dict[ioncs[kk]] = dict(flg_clm=1,
                                               Z=Zions[kk][0],
                                               ion=Zions[kk][1])
                    ion_dict[ioncs[kk]]['clm'] = float(is2[0:5])
                    ion_dict[ioncs[kk]]['sig_clm'] = float(is2[10:])
            # Finish
            lls._ionN = pyiau.dict_to_ions(ion_dict)
            lls.Refs.append('Mei07')
            all_lls.append(lls)

    # Return SLLS only
    fin_slls = [ills for ills in all_lls if ills.NHI < 20.3]
    return fin_slls
Esempio n. 15
0
def jenkins2005():
    """Jenkins, E. et al. 2005, ApJ, 2005, 623, 767
    PHL 1811
    HST/STIS, FUSE
    Metals parsed from Table 1
      OI taken from text
      Had to input error on columns by hand (JXP)
    Total NHI from Lyman series. see Fig 3
    M/H from O/H
    """
    # Grab ASCII file from ApJ
    tab_fil = pyigm_path + "/data/LLS/Literature/jenkins2005.tb1.ascii"
    chk_fil = glob.glob(tab_fil)
    if len(chk_fil) > 0:
        tab_fil = chk_fil[0]
    else:
        url = 'http://iopscience.iop.org/0004-637X/623/2/767/fulltext/61520.tb1.txt'
        print('LLSSurvey: Grabbing table file from {:s}'.format(url))
        f = urlopen(url)
        with open(tab_fil, "wb") as code:
            code.write(f.read())
    # Setup
    radec = '215501.5152-092224.688'  # SIMBAD
    lls = LLSSystem(name='PHL1811_z0.081',
                    radec=radec,
                    zem=0.192,
                    zabs=0.080923,
                    vlim=[-100., 100.] * u.km / u.s,
                    NHI=17.98,
                    ZH=-0.19,
                    sig_NHI=np.array([0.05, 0.05]))
    lls.lines = []  # Probably not used

    # AbsLines
    ism = LineList('ISM')
    Nsig = {
        'C IV': 0.4,
        'N II': 0.4,
        'Si II': 0.05,
        'Si IV': 0.25,
        'S II': 0.2,
        'Fe II': 0.12,
        'H I': 0.05,
        'S III': 0.06
    }

    # Parse Table
    with open(tab_fil, 'r') as f:
        flines = f.readlines()
    ion_dict = {}
    for iline in flines:
        iline = iline.strip()
        if (len(iline) == 0):
            continue
        # Split on tabs
        isplit = iline.split('\t')
        # Offset?
        ioff = 0
        if isplit[0][0] in ['1', '2']:
            ioff = -1
        # Catch bad lines
        if (isplit[1 + ioff][0:6]
                in ['1442.0', '1443.7',
                    '1120.9']):  # Skip goofy CII line and CII*
            continue
        if len(isplit[2 + ioff]) == 0:
            continue
        # Ion
        if (len(isplit[0].strip()) > 0) & (isplit[0][0] not in ['1', '2']):
            ionc = isplit[0].strip()
            try:
                Zion = ltai.name_to_ion(ionc)
            except (KeyError, RecursionError):
                pdb.set_trace()
        # Generate the Line
        try:
            newline = AbsLine(float(isplit[2 + ioff]) * u.AA,
                              linelist=ism,
                              closest=True)
        except ValueError:
            pdb.set_trace()
        newline.attrib['z'] = lls.zabs
        # Spectrum
        newline.analy['datafile'] = 'STIS' if 'S' in isplit[1] else 'FUSE'
        # EW
        try:
            EWvals = isplit[4 + ioff].split(' ')
        except IndexError:
            pdb.set_trace()
        newline.attrib['EW'] = float(EWvals[0]) * u.AA / 1e3
        newline.attrib['sig_EW'] = float(EWvals[2]) * u.AA / 1e3
        newline.attrib['flag_EW'] = 1
        if len(isplit) < (5 + ioff + 1):
            continue
        # Colm?
        #xdb.set_trace()
        newline.attrib['sig_logN'] = 0.
        if (len(isplit[5 + ioff].strip()) > 0) & (isplit[5 + ioff].strip() !=
                                                  '\\ldots'):
            if isplit[5 + ioff][0] == '\\':
                ipos = isplit[5 + ioff].find(' ')
                newline.attrib['logN'] = float(isplit[5 + ioff][ipos + 1:])
                newline.attrib['flag_N'] = 2
            elif isplit[5 + ioff][0] == '<':
                ipos = 0
                newline.attrib['logN'] = float(isplit[5 + ioff][ipos + 1:])
                newline.attrib['flag_N'] = 3
            elif isplit[5 + ioff][0] == '1':
                try:
                    newline.attrib['logN'] = float(isplit[5 + ioff][0:5])
                except ValueError:
                    pdb.set_trace()
                newline.attrib['flag_N'] = 1
                try:
                    newline.attrib['sig_logN'] = Nsig[ionc]
                except KeyError:
                    print('No error for {:s}'.format(ionc))
            else:
                raise ValueError('Bad character')
            # ion_dict
            ion_dict[ionc] = dict(clm=newline.attrib['logN'],
                                  sig_clm=newline.attrib['sig_logN'],
                                  flg_clm=newline.attrib['flag_N'],
                                  Z=Zion[0],
                                  ion=Zion[1])
        # Append
        lls.lines.append(newline)
    # Fix NI, OI
    ion_dict['O I']['clm'] = 14.47
    ion_dict['O I']['sig_clm'] = 0.05
    ion_dict['N I']['flg_clm'] = 3
    lls._ionN = pyiau.dict_to_ions(ion_dict)

    lls.Refs.append('Jen05')
    # Return
    return lls
Esempio n. 16
0
def complist_from_table(table):
    """
    Returns a list of AbsComponents from an input astropy.Table.

    Parameters
    ----------
    table : Table
        Table with component information (each row must correspond
        to a component). Each column is expecting a unit when
        appropriate.

    Returns
    -------
    complist : list
        List of AbsComponents defined from the input table.

    Notes
    -----
    Mandatory column names: 'RA', 'DEC', 'ion_name', 'z_comp', 'vmin', 'vmax'
        These column are required.
    Special column names: 'name', 'comment', 'logN', 'sig_logN', 'flag_logN'
        These columns will fill internal attributes when corresponding.
        In order to fill in the Ntuple attribute all three 'logN', 'sig_logN', 'flag_logN'
        must be present. For convenience 'logN' and 'sig_logN' are expected to be floats
        corresponding to their values in np.log10(1/cm^2).

    Other columns: 'any_column_name'
        These will be added as attributes within the AbsComponent.attrib dictionary,
        with their respective units if given.

    """
    # Convert to QTable to handle units in individual entries more easily
    table = QTable(table)

    # mandatory and optional columns
    min_columns = ['RA', 'DEC', 'ion_name', 'z_comp', 'vmin', 'vmax']
    special_columns = ['name', 'comment', 'logN', 'sig_logN', 'flag_logN']
    for colname in min_columns:
        if colname not in table.keys():
            raise IOError('{} is a mandatory column. Please make sure your input table has it.'.format(colname))

    #loop over rows
    complist = []
    for row in table:
        # mandatory
        coord = SkyCoord(row['RA'].to('deg').value, row['DEC'].to('deg').value, unit='deg')  # RA y DEC must both come with units
        Zion = name_to_ion(row['ion_name'])
        zcomp = row['z_comp']
        vlim =[row['vmin'].to('km/s').value, row['vmax'].to('km/s').value] * u.km / u.s  # units are expected here too

        # special columns
        try:
            Ntuple = (row['flag_logN'], row['logN'], row['sig_logN'])  # no units expected
        except KeyError:
            Ntuple = None
        try:
            comment = row['comment']
        except KeyError:
            comment = ''
        try:
            name = row['name']
        except KeyError:
            name = None

        # define the component
        comp = AbsComponent(coord, Zion, zcomp, vlim, Ntup=Ntuple, comment=comment, name=name)

        # other columns will be filled in comp.attrib dict
        for colname in table.keys():
            if (colname not in special_columns) and (colname not in min_columns):
                kms_cols = ['b', 'sig_b']
                if colname in kms_cols:  # check units for parameters expected in velocity units
                    try:
                        val_aux = row[colname].to('km/s').value * u.km / u.s
                    except u.UnitConversionError:
                        raise IOError('If `{}` column is present, it must have velocity units.'.format(colname))
                    comp.attrib[colname] = val_aux
                # parameters we do not care about units much
                else:
                    comp.attrib[colname] = row[colname]

        # append
        complist += [comp]
    return complist
Esempio n. 17
0
def battisti12():
    '''Battisti, A. et al. 2012, ApJ, 744, 93
    HST/COS
    QSO info from Table 1
    Metal columns parsed from Table 3
    NHI from Lya
    '''
    all_lls = []
    # Grab ASCII files from ApJ
    tab_fils = [
        pyigm_path + "/data/LLS/Literature/battisti12.tb1.ascii",
        pyigm_path + "/data/LLS/Literature/battisti12.tb3.ascii"
    ]
    urls = [
        'http://iopscience.iop.org/0004-637X/744/2/93/suppdata/apj413924t1_ascii.txt',
        'http://iopscience.iop.org/0004-637X/744/2/93/suppdata/apj413924t3_ascii.txt'
    ]
    for jj, tab_fil in enumerate(tab_fils):
        chk_fil = glob.glob(tab_fil)
        if len(chk_fil) > 0:
            tab_fil = chk_fil[0]
        else:
            url = urls[jj]
            print('LLSSurvey: Grabbing table file from {:s}'.format(url))
            f = urlopen(url)
            with open(tab_fil, "wb") as code:
                code.write(f.read())
    # QSO info
    with open(tab_fils[0], 'r') as f:
        flines1 = f.readlines()
    # Grab RA/DEC
    all_idict = []
    for iline in flines1:
        if iline[0:2] != 'SD':
            continue
        # Parse
        isplit = iline.split('\t')
        name = isplit[0].split(' ')[1]
        radec = name[1:]
        zem = float(isplit[1].strip())
        zabs = float(isplit[2].strip())
        NHI = float(isplit[3].strip()[0:4])
        sigNHI = np.array([float(isplit[3].strip()[11:])] * 2)
        # Save
        lls = LLSSystem(name=name,
                        radec=radec,
                        zem=zem,
                        zabs=zabs,
                        NHI=NHI,
                        sig_NHI=sigNHI,
                        vlim=[-500, 500] * u.km / u.s)
        #
        all_lls.append(lls)
        all_idict.append({})

    # Abundances
    with open(tab_fils[1], 'r') as f:
        flines3 = f.readlines()
    flines3 = flines3[5:]
    ion = None
    for iline in flines3:
        if ion == 'Ni II':
            break
        isplit = iline.split('\t')
        if isplit[0] == 'C II*':  # Skipping CII*
            continue
        # ion
        ipos = -1
        while (isplit[0][ipos] not in ['I', 'V']):
            ipos -= 1
        ion = isplit[0][0:ipos + 1 + len(isplit[0])]
        Zion = ltai.name_to_ion(ion)
        # Loop on systems
        for kk, iis in enumerate(isplit[1:-1]):
            if iis.strip()[0] == '.':
                continue
            all_idict[kk][ion] = dict(Z=Zion[0], ion=Zion[1], sig_clm=0.)
            if iis[0] == '>':
                all_idict[kk][ion]['flg_clm'] = 2
                all_idict[kk][ion]['clm'] = float(iis[1:6])
            elif iis[0] == '<':
                all_idict[kk][ion]['flg_clm'] = 3
                all_idict[kk][ion]['clm'] = float(iis[1:])
            else:
                all_idict[kk][ion]['flg_clm'] = 1
                all_idict[kk][ion]['clm'] = float(iis[0:5])
                all_idict[kk][ion]['sig_clm'] = float(iis[-4:])

    # Return SLLS only
    for kk, lls in enumerate(all_lls):
        try:
            lls._ionN = pyiau.dict_to_ions(all_idict[kk])
        except ValueError:
            pdb.set_trace()
        lls.Refs.append('Bat12')
    fin_slls = [ills for ills in all_lls if ills.NHI < 20.3]
    return fin_slls
Esempio n. 18
0
    def stack_plot(self,
                   to_plot,
                   pvlim=None,
                   maxtrans=3,
                   return_fig=True,
                   add_missing_lines=False,
                   spec=None,
                   **kwargs):
        '''Show a stack plot of the CGM absorption system

        Parameters
        ----------
        to_plot : List of AbsLines, AbsComponents, tuples, or strs
           If AbsLines, pass list on to linetools.analysis.plots.stack_plot()
           If not Abslines, will plot up to maxtrans of strongest transitions
           covered by spectra for components of some species.
             If tuples or strs, should be Zion value or ion name: (8,6) or 'OVI'
        pvlim : Quantities, optional
           Override system vlim for plotting
        maxtrans : int, optional
           Maximum number of lines per transition to plot
        add_missing_lines : bool, optional
           If True, plot transitions that do not have associated AbsLine objects
        spec : XSpectrum1D, optional
           Spectrum to plot in regions of requested lines; required if assoc.
           AbsLine objects do not have their analy['specfile'] attributes set

        Returns
        -------
        fig : matplotlib Figure, optional
           Figure instance containing stack plot with subplots, axes, etc.
        '''

        from linetools.analysis import plots as ltap
        from linetools.spectralline import AbsLine
        from linetools.isgm.abscomponent import AbsComponent
        from linetools.spectra.io import readspec
        from linetools.lists.linelist import LineList
        from linetools.abund import ions as ltai
        from pyigm import utils as pu

        ilist = LineList('ISM')

        if not isinstance(to_plot[0], AbsLine):
            lines2plot = []  # Master list of lines to plot
            for i, tp in enumerate(to_plot):
                if isinstance(tp, AbsComponent):
                    comp = to_plot
                else:  # Pick components in system closest to z_cgm
                    thesecomps = pu.get_components(self, tp)
                    if len(thesecomps) == 0:
                        if add_missing_lines is True:
                            # Add components
                            if isinstance(tp, str):
                                tup = ltai.name_to_ion(tp)
                            else:
                                tup = tp
                            comp = AbsComponent(self.coord,
                                                tup,
                                                zcomp=self.z,
                                                vlim=[-100., 100.] * u.km /
                                                u.s)
                            comp.add_abslines_from_linelist()
                            if spec is not None:
                                for al in comp._abslines:
                                    al.analy['spec'] = spec
                            else:
                                raise ValueError('spec must be provided if '
                                                 'requesting species without'
                                                 ' existing components.')
                        else:
                            continue
                    else:
                        # Find component with redshift closest to systemic
                        compvels = np.array(
                            [np.median(tc.vlim.value) for tc in thesecomps])
                        comp = thesecomps[np.argmin(np.abs(compvels))]

                    ### Get strongest transitions covered
                    wmins = []
                    wmaxs = []
                    for j, al in enumerate(comp._abslines):
                        # Load spectrum if not already loaded
                        if al.analy['spec'] is None:
                            try:
                                if spec is not None:
                                    al.analy['spec'] = spec
                                else:
                                    al.analy['spec'] = readspec(
                                        al.analy['spec_file'])
                            except:
                                raise LookupError("spec must be defined or "
                                                  "analy['specfile'] must be "
                                                  "declared for AbsLines")
                        # Get wavelength limits to know where to look
                        wmins.append(al.analy['spec'].wvmin.value)
                        wmaxs.append(al.analy['spec'].wvmax.value)
                    wlims = (np.min(np.array(wmins)), np.max(
                        np.array(wmaxs))) * u.Angstrom
                    # ID the strong transitions
                    strong = ilist.strongest_transitions(tp,
                                                         wvlims=wlims /
                                                         (1. + comp.zcomp),
                                                         n_max=maxtrans)
                    if strong is None:  #  No lines covered in the spectra
                        warnings.warn(
                            'No lines for {} are covered by the spectra'
                            'provided.'.format(tp))
                        continue
                    # Grab the AbsLines from this AbsComponent and their names
                    complines = comp._abslines
                    complines = np.array(complines)  # For the indexing
                    compnames = np.array([ll.name for ll in complines])
                    ### Add the lines found to the master list
                    if isinstance(strong, dict):  # Only one line covered
                        lines2plot.append(
                            complines[compnames == strong['name']][0])
                    else:  # Multiple lines covered
                        for i, sn in enumerate(strong['name']):
                            # Handle case where relevant components are defined
                            if sn in compnames:
                                tokeep = [complines[compnames == sn][0]]
                                lines2plot.extend(tokeep)
                            # Now case where components were not attached to sys
                            elif add_missing_lines is True:
                                # Add line to the existing comp to preserve z, etc.
                                compcopy = comp.copy(
                                )  #Copy to add dummy lines
                                # Set up observed wavelength range
                                obswave = strong['wrest'][i] * (1. +
                                                                compcopy.zcomp)
                                wvrange = [obswave - 0.1, obswave + 0.1
                                           ] * u.Angstrom
                                # Add this line to the component
                                compcopy.add_abslines_from_linelist(
                                    wvlim=wvrange)
                                al = compcopy._abslines[-1]
                                # Set the spectrum
                                if spec is not None:
                                    al.analy['spec'] = spec
                                else:
                                    al.analy['spec'] = comp._abslines[0].analy[
                                        'spec']
                                # Add the line
                                lines2plot.append(al)
                            else:
                                warnings.warn(
                                    '{} covered by spectra but not in'
                                    'components list'.format(sn))
        else:
            lines2plot = to_plot

        # Deal with velocity limits
        if pvlim is not None:
            vlim = pvlim
        else:
            vlim = self.vlim
        ### Make the plot!
        fig = ltap.stack_plot(lines2plot,
                              vlim=vlim,
                              return_fig=return_fig,
                              zref=self.z,
                              **kwargs)
        fig.subplots_adjust(bottom=0.,
                            left=0.1,
                            right=0.95,
                            hspace=0.,
                            wspace=0.35)
        return fig
Esempio n. 19
0
def peroux06b():
    """Peroux, C. et al. 2006b, A&A, 450, 53
    SDSS J1323-0021
    Metal rich
    Metal columns copied by JXP from Table 1 
    Total NHI from damping wings
    """
    # Setup
    radec = '132323.78-002155.2'  # SDSS Name
    lls = LLSSystem(name='SDSSJ1323-0021_z0.716',
                    radec=radec,
                    zem=1.390,
                    zabs=0.716,
                    vlim=[-200., 200.] * u.km / u.s,
                    NHI=20.21,
                    sig_NHI=np.array([0.20, 0.20]))
    # Parse table file
    tab_fil = pyigm_path + "/data/LLS/Literature/peroux06b.tb1.ascii"
    with open(tab_fil, 'r') as f:
        flines = f.readlines()
    ion_dict = {}
    for iline in flines:
        isplit = iline.split('\t')
        if len(isplit[0]) == 0:
            # Grab ions and init
            ions = isplit[3:10]
            for ion in ions:
                Zion = ltai.name_to_ion(ion)
                ion_dict[ion] = dict(clm=0.,
                                     sig_clm=0.,
                                     flg_clm=1,
                                     Z=Zion[0],
                                     ion=Zion[1])
            continue
        # Column or sigma?
        if isplit[0][0] == 'N':  # Column
            for kk, iis in enumerate(isplit[3:10]):
                ion = ions[kk]
                if iis[0] == '>':
                    ion_dict[ion]['flg_clm'] = 2
                    ion_dict[ion]['clm'] += float(iis[1:])
                elif iis[0] == '<':
                    pass
                elif iis[0] == '.':
                    pass
                else:
                    ion_dict[ion]['clm'] += float(iis)
        else:  # Sigma
            for kk, iis in enumerate(isplit[3:10]):
                ion = ions[kk]
                if iis[0] == '.':
                    pass
                else:
                    ion_dict[ion]['sig_clm'] += float(iis)**2
    # Convert to log
    for ion in ions:
        N = ion_dict[ion]['clm']
        sig = np.sqrt(ion_dict[ion]['sig_clm'])
        #
        ion_dict[ion]['clm'] = np.log10(N)
        if ion_dict[ion]['flg_clm'] == 2:
            ion_dict[ion]['sig_clm'] = 0.
        else:
            ion_dict[ion]['sig_clm'] = sig / N / np.log(10)
    # Finish
    lls._ionN = pyiau.dict_to_ions(ion_dict)
    lls.Refs.append('Prx06b')
    return lls