Exemple #1
0
def test_sumlogn_limit():
    obj1 = dict(flag_N=3, logN=15., sig_logN=99.)
    obj2 = dict(flag_N=1, logN=14., sig_logN=0.3)
    flag_N, logN, sig_logN = sum_logN(obj1, obj2)
    # Test
    assert flag_N == 1
    np.testing.assert_allclose((logN, sig_logN), (obj2['logN'], obj2['sig_logN']))
Exemple #2
0
def synthesize_components(components, zcomp=None, vbuff=0 * u.km / u.s):
    """Synthesize a list of components into one

    Requires consistent RA/DEC, Zion, Ej, (A; future)
    Is agnostic about z+vlim
    Melds column densities
    Melds velocities with an optional buffer

    Note: Could make this a way to instantiate AbsComponent

    Parameters
    ----------
    components : list
      list of AbsComponent objects
    zcomp : float, optional
      Input z to reference the synthesized component
      If not input, the mean of the input components is used
    vbuff : Quantity, optional
      Buffer for synthesizing velocities.  Deals with round off, c, etc.
    """
    # Checks
    assert chk_components(components, chk_A_none=True, chk_match=True)

    # Meld column densities
    obj = dict(flag_N=components[0].flag_N,
               logN=components[0].logN,
               sig_logN=components[0].sig_logN)
    for comp in components[1:]:
        if comp.flag_N != 0:
            obj['flag_N'], obj['logN'], obj['sig_logN'] = ltaa.sum_logN(
                obj, comp)

    # zcomp
    if zcomp is None:
        zcomp = np.mean([comp.zcomp for comp in components])

    # Set vlim by min/max  [Using non-relativistic + buffer]
    vmin = u.Quantity([
        (comp.zcomp - zcomp) / (1 + zcomp) * const.c.to('km/s') + comp.vlim[0]
        for comp in components
    ])
    vmax = u.Quantity([
        (comp.zcomp - zcomp) / (1 + zcomp) * const.c.to('km/s') + comp.vlim[1]
        for comp in components
    ])
    vlim = u.Quantity([np.min(vmin) - vbuff, np.max(vmax) + vbuff])

    # Init final component
    synth_comp = AbsComponent(
        components[0].coord,
        components[0].Zion,
        zcomp,
        vlim,
        Ej=components[0].Ej,
        stars=components[0].stars,
        Ntup=(obj['flag_N'], obj['logN'],
              obj['sig_logN']))  # Should probably set attrib instead

    # Return
    return synth_comp
def test_sumlogn_limit():
    obj1 = dict(flag_N=3, logN=15., sig_logN=99.)
    obj2 = dict(flag_N=1, logN=14., sig_logN=0.3)
    flag_N, logN, sig_logN = sum_logN(obj1, obj2)
    # Test
    assert flag_N == 1
    np.testing.assert_allclose((logN, sig_logN),
                               (obj2['logN'], obj2['sig_logN']))
Exemple #4
0
def sum_ionN(tbl1, tbl2):
    """ Sum two ion column density tables

    Parameters
    ----------
    tbl1 : Table
    tbl2 : Table

    Returns
    -------
    sum_tbl : Table

    """
    # Instantiate and use data form original as starting point
    sum_tbl = tbl1.copy()

    # Loop through other
    for row2 in tbl2:
        # New?
        Zion = (row2['Z'], row2['ion'])
        try:
            row1 = sum_tbl[(sum_tbl['Z'] == Zion[0])
                           & (sum_tbl['ion'] == Zion[1])]
        except KeyError:
            # Add in the new row
            sum_tbl.add_row(row2)
        else:
            idx = np.where((sum_tbl['Z'] == Zion[0])
                           & (sum_tbl['ion'] == Zion[1]))[0][0]
            # Clm
            flagN, logN, siglogN = ltaa.sum_logN(row1, row2)
            sum_tbl['logN'][idx] = logN
            # Error
            sum_tbl['sig_logN'][idx] = siglogN
            # Flag
            flags = [row1['flag_N'], row2['flag_N']]
            if 2 in flags:  # At least one saturated
                flag = 2
            elif 1 in flags:  # None saturated; at least one detection
                flag = 1
            else:  # Both upper limits
                flag = 3
            sum_tbl['flag_N'][idx] = flag
            # Instrument (assuming binary flag)
            if 'flg_inst' in row1.keys():
                binflg = [0] * 10
                for jj in range(10):
                    if (row2['flg_inst'] % 2**(jj + 1)) >= 2**jj:
                        binflg[jj] = 1
                    if (row1['flg_inst'] % 2**(jj + 1)) >= 2**jj:
                        binflg[jj] = 1
                sum_tbl['flg_inst'][idx] = int(
                    np.sum([
                        2**kk for kk, ibinf in enumerate(binflg) if ibinf == 1
                    ]))
    # Return
    return sum_tbl
Exemple #5
0
    def add_ion_to_data(self, inp_ion):
        """ Add columns for ion info (column density)
        to the Table

        Parameters
        ----------
        inp_ion

        Returns
        -------

        """
        from linetools.analysis import absline as ltaa
        ion = inp_ion.replace(' ', '')
        # Check for previous
        if 'flag_N_{:s}'.format(ion) in self._data.keys():
            print("Ion data is already in the _data table")
            return
        # Loop on the systems
        flagNs, Ns, sigNs = [], [], []
        for key in self._dict.keys():
            igm_comp = self._dict[key]['igm_sys']['components']
            comps = []  # Allow for more than one
            for comp in igm_comp.keys():
                sion = comp.split('_')[0]
                if sion == ion:
                    if 'attrib' in igm_comp[comp].keys():
                        attrib = igm_comp[comp]['attrib']
                        attrib['sig_logN'] = np.array(attrib['sig_logN'])
                        comps.append(attrib.copy())
                    else:  # Deprecated
                        comps.append(
                            dict(logN=igm_comp[comp]['logN'],
                                 flag_N=igm_comp[comp]['flag_N'],
                                 sig_logN=np.array(
                                     [igm_comp[comp]['sig_logN']] * 2)))
            # Now sum em up
            if len(comps) == 0:
                flagNs.append(0)
                Ns.append(0.)
                sigNs.append(np.array([0.] * 2))
                continue
            obj = dict(flag_N=comps[0]['flag_N'],
                       logN=comps[0]['logN'],
                       sig_logN=comps[0]['sig_logN'])
            for comp in comps[1:]:
                if comp['flag_N'] != 0:
                    obj['flag_N'], obj['logN'], obj[
                        'sig_logN'] = ltaa.sum_logN(obj, comp)
            # Save
            flagNs.append(obj['flag_N'])
            Ns.append(obj['logN'])
            sigNs.append(obj['sig_logN'])
        # Add to Table
        self._data.add_column(Column(flagNs, name='flag_N_{:s}'.format(ion)))
        self._data.add_column(Column(Ns, name='logN_{:s}'.format(ion)))
        self._data.add_column(Column(sigNs, name='sig_logN_{:s}'.format(ion)))
Exemple #6
0
    def sum(self,other):
        '''Sum two IonClms classes
        Parameters:
        ----------
        other: IonClms Class  
          Another one

        Returns:
        --------
        A new instance of IonClms with the column densities summed
        '''
        # Instantiate and use data form original as starting point
        newIC = IonClms()
        newIC._data = copy.deepcopy(self._data)
        # Loop through other
        for row in other._data:
            # New?
            Zion = (row['Z'], row['ion'])
            try:
                sdict = newIC[Zion]
            except KeyError:
                # Add in the new row
                newIC._data.add_row(row)
            else:
                idx = np.where((newIC.Z==Zion[0]) & (newIC.ion==Zion[1]))[0][0]
                # Clm
                logN, siglogN = ltaa.sum_logN(sdict,row)
                newIC._data['logN'][idx] = logN
                # Error
                newIC._data['sig_logN'][idx] = siglogN
                '''
                np.sqrt(
                    np.sum([(sdict['sig_clm']*(10.**sdict['clm']))**2,
                    (row['sig_clm']*(10.**row['clm']))**2]))/(10.**newIC._data['clm'][idx])
                '''
                # Flag
                flags = [sdict['flg_clm'], row['flg_clm']]
                if 2 in flags:   # At least one saturated
                    flag = 2
                elif 1 in flags: # None saturated; at least one detection
                    flag = 1
                else:            # Both upper limits
                    flag = 3  
                newIC._data['flg_clm'][idx] = flag
                # Instrument (assuming binary flag)
                if 'flg_inst' in sdict.keys():
                    binflg = [0]*10
                    for jj in range(10):
                        if (row['flg_inst'] % 2**(jj+1)) >= 2**jj:
                            binflg[jj] = 1
                        if (sdict['flg_inst'] % 2**(jj+1)) >= 2**jj:
                            binflg[jj] = 1
                    newIC._data['flg_inst'][idx] = int(np.sum(
                        [2**kk for kk,ibinf in enumerate(binflg) if ibinf==1]))
            # Return
        return newIC
Exemple #7
0
def sum_ionN(tbl1, tbl2):
    """ Sum two ion column density tables

    Parameters
    ----------
    tbl1 : Table
    tbl2 : Table

    Returns
    -------
    sum_tbl : Table

    """
    # Instantiate and use data form original as starting point
    sum_tbl = tbl1.copy()

    # Loop through other
    for row2 in tbl2:
        # New?
        Zion = (row2['Z'], row2['ion'])
        try:
            row1 = sum_tbl[(sum_tbl['Z'] == Zion[0])&(sum_tbl['ion'] == Zion[1])]
        except KeyError:
            # Add in the new row
            sum_tbl.add_row(row2)
        else:
            idx = np.where((sum_tbl['Z'] == Zion[0]) &
                           (sum_tbl['ion'] == Zion[1]))[0][0]
            # Clm
            flagN, logN, siglogN = ltaa.sum_logN(row1, row2)
            sum_tbl['logN'][idx] = logN
            # Error
            sum_tbl['sig_logN'][idx] = siglogN
            # Flag
            flags = [row1['flag_N'], row2['flag_N']]
            if 2 in flags:   # At least one saturated
                flag = 2
            elif 1 in flags:  # None saturated; at least one detection
                flag = 1
            else:            # Both upper limits
                flag = 3
            sum_tbl['flag_N'][idx] = flag
            # Instrument (assuming binary flag)
            if 'flg_inst' in row1.keys():
                binflg = [0]*10
                for jj in range(10):
                    if (row2['flg_inst'] % 2**(jj+1)) >= 2**jj:
                        binflg[jj] = 1
                    if (row1['flg_inst'] % 2**(jj+1)) >= 2**jj:
                        binflg[jj] = 1
                sum_tbl['flg_inst'][idx] = int(np.sum(
                    [2**kk for kk, ibinf in enumerate(binflg) if ibinf==1]))
    # Return
    return sum_tbl
Exemple #8
0
def synthesize_components(components, zcomp=None, vbuff=0*u.km/u.s):
    """Synthesize a list of components into one

    Requires consistent RA/DEC, Zion, Ej, (A; future)
    Is agnostic about z+vlim
    Melds column densities
    Melds velocities with an optional buffer

    Note: Could make this a way to instantiate AbsComponent

    Parameters
    ----------
    components : list
      list of AbsComponent objects
    zcomp : float, optional
      Input z to reference the synthesized component
      If not input, the mean of the input components is used
    vbuff : Quantity, optional
      Buffer for synthesizing velocities.  Deals with round off, c, etc.
    """
    # Checks
    assert chk_components(components, chk_A_none=True, chk_match=True)


    # Meld column densities
    obj = dict(flag_N=components[0].flag_N, logN=components[0].logN,
               sig_logN=components[0].sig_logN)
    for comp in components[1:]:
        if comp.flag_N != 0:
            obj['flag_N'], obj['logN'], obj['sig_logN'] = ltaa.sum_logN(obj, comp)

    # zcomp
    if zcomp is None:
        zcomp = np.mean([comp.zcomp for comp in components])

    # Set vlim by min/max  [Using non-relativistic + buffer]
    vmin = u.Quantity([(comp.zcomp-zcomp)/(1+zcomp)*const.c.to('km/s')+comp.vlim[0] for comp in components])
    vmax = u.Quantity([(comp.zcomp-zcomp)/(1+zcomp)*const.c.to('km/s')+comp.vlim[1] for comp in components])
    vlim = u.Quantity([np.min(vmin)-vbuff, np.max(vmax)+vbuff])

    # Init final component
    synth_comp = AbsComponent(components[0].coord, components[0].Zion, zcomp,
                              vlim, Ej=components[0].Ej, stars=components[0].stars,
                              Ntup=(obj['flag_N'], obj['logN'], obj['sig_logN']))  # Should probably set attrib instead

    # Return
    return synth_comp
Exemple #9
0
def synthesize_components(components, zcomp=None, vbuff=0 * u.km / u.s):
    """Synthesize a list of components into one

    Requires consistent RA/DEC, Zion, Ej, (A; future)
    Is agnostic about z+vlim
    Melds column densities
    Melds velocities with a small buffer (10 km/s)

    Note: Could make this a way to instantiate AbsComponent

    Parameters
    ----------
    components : list
      list of AbsComponent objects
    zcomp : float, optional
      Input z to reference the synthesized component
      If not input, the mean of the input components is used
    vbuff : Quantity, optional
      Buffer for synthesizing velocities.  Deals with round off, c, etc.
    """
    # Checks
    assert chk_components(components, chk_A_none=True, chk_match=True)

    # Init final component
    synth_comp = AbsComponent.from_component(
        components[0], Ntup=(components[0].flag_N, components[0].logN, components[0].sig_logN)
    )

    # Meld column densities
    for comp in components[1:]:
        synth_comp.flag_N, synth_comp.logN, synth_comp.sig_logN = ltaa.sum_logN(synth_comp, comp)

    # Meld z, vlim
    # zcomp
    if zcomp is None:
        zcomp = np.mean([comp.zcomp for comp in components])
    synth_comp.zcomp = zcomp
    # Set vlim by min/max  [Using non-relativistic + buffer]
    vmin = u.Quantity([(comp.zcomp - zcomp) / (1 + zcomp) * const.c.to("km/s") + comp.vlim[0] for comp in components])
    vmax = u.Quantity([(comp.zcomp - zcomp) / (1 + zcomp) * const.c.to("km/s") + comp.vlim[1] for comp in components])
    synth_comp.vlim = u.Quantity([np.min(vmin) - vbuff, np.max(vmax) + vbuff])

    # Return
    return synth_comp
Exemple #10
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_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
Exemple #11
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_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_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
Exemple #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 = urllib2.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_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
Exemple #13
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 = urllib2.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_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_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