示例#1
0
from __future__ import print_function, absolute_import, division, unicode_literals

from .. import joebgoodies as jbg
import numpy as np
from linetools.spectralline import AbsLine
from linetools.lists import parse as lilp
from linetools.lists.linelist import LineList
import astropy.units as u
import imp

ilist = LineList('ISM')

jbvp_path = imp.find_module('joebvp')[1]

vernerlist = np.genfromtxt(jbvp_path + '/atomicdata/verner6.txt',
                           dtype=None,
                           encoding=None,
                           delimiter=[10, 8, 3, 4, 3, 2, 9, 6])
vernlam = jbg.arrfromcol(vernerlist, 0)
vernion = jbg.arrfromcol(vernerlist, 1)
vernzatom = jbg.arrfromcol(vernerlist, 2)
vernnume = jbg.arrfromcol(vernerlist, 3)
verngl = jbg.arrfromcol(vernerlist, 4)
verngu = jbg.arrfromcol(vernerlist, 5)
vernosc = jbg.arrfromcol(vernerlist, 6)
vernp = jbg.arrfromcol(vernerlist, 7)

# A start to using the linetools atomic data framework
adata = lilp.parse_morton03()
vdata = lilp.parse_verner96()
示例#2
0
def test_lines_from_ion():
    ism = LineList('ISM')
    #
    lines = ism[(6, 2)]
    assert (1334.5323 in lines['wrest'])
示例#3
0
def test_closest():
    ism = LineList('ISM')
    ism.closest = True
    #
    line = ism[1250.584 * u.AA]  # dict with units
    np.testing.assert_allclose(line['wrest'], 1250.578 * u.AA, rtol=1e-7)
示例#4
0
    # Match the target with its properties by using RA and DEC cooords
    w = numpy.logical_and(targ_coord[0] == prop['RA'],
                          targ_coord[1] == prop['DEC'])
    data = prop[w]

    radec = SkyCoord(targ_coord[0] + ':00',
                     targ_coord[1] + ':00',
                     unit=(u.hourangle, u.deg))

    # Get the expected sodium transition wavelengths from the target properties
    line = data['Sod_line']

    #Define the wavelength range to search for redshifted Sodium lines
    wvlim = [line - 30.0, line + 30.0] * u.AA

    strong = LineList('Strong')  #Search for lines
    transitions = strong.available_transitions(wvlim / (1 + data['z']),
                                               n_max_tuple=None,
                                               min_strength=0.0)

    # Transform lines to the redshifted wavelength
    line1 = transitions['wrest'][0] * (1 + data['z'])
    line2 = transitions['wrest'][1] * (1 + data['z'])

    # plot the figure
    fig = plt.figure()
    fig.suptitle(name[42:-5] + '  z=' + str(data['z']))
    plt.axvline(x=line1, color='k', linestyle='--')
    plt.axvline(x=line2, color='k', linestyle='--')
    sp.plot(xlim=(line - 30, line + 30))
    fig.savefig(name + '.pdf')  # Save a copy of the figure
示例#5
0
    def load_abskin(self, flg=1, kin_file=None, kin_init_file=None):
        """ Load the absorption-line kinematic data for COS-Halos (or COS-Dwarfs)
        Calculate from scratch if needed

        Parameters
        ----------
        flg: int, optional 
          Flag indicating how to load the data
            0 = Load from file
            1 = Generate
        kin_init_file: str
          Name of kinematics driver file
        kin_file: str
          Name of kinematics output file [First made for John Forbes]
        """
        from linetools.lists.linelist import LineList
        ism = LineList('ISM')

        if flg == 0:  # Load
            if kin_file is None:
                kin_file = os.path.abspath(
                    os.environ.get('DROPBOX_DIR') + '/COS-Halos/Kin/' +
                    'COS-Halos_kin.fits')
            hdu = fits.open(kin_file)
            # Metals
            metals = Table(hdu[1].data)
            for row in metals:
                mt = np.where((row['field'] == self.field)
                              & (row['gal_id'] == self.gal_id))[0]
                pdb.set_trace()

        elif flg == 1:  # Generate
            # Read init file
            if kin_init_file is None:
                kin_init_file = self.kin_init_file
            kin_init = Table.read(kin_init_file, format='ascii')

            # Loop to my loop
            fgal = zip(self.field, self.gal_id)
            for qq, cgm_abs in enumerate(self.cgm_abs):
                # Match to kin_init
                mt = np.where((kin_init['QSO'] == cgm_abs.field)
                              & (kin_init['Galaxy'] == cgm_abs.gal_id))[0]
                if len(mt) == 0:
                    warnings.warn(
                        'load_kin: No kinematics for {:s}, {:s}'.format(
                            cgm_abs.field, cgm_abs.gal_id))
                    continue
                mt = mt[0]

                # Metals
                if kin_init['flgL'][mt] > 0:
                    wrest = kin_init['mtl_wr'][mt] * u.AA
                    if wrest.value <= 1:
                        pdb.set_trace()
                    spec = self.load_bg_cos_spec(qq, wrest)
                    vmnx = (kin_init['L_vmn'][mt],
                            kin_init['L_vmx'][mt]) * u.km / u.s
                    # Process
                    aline = AbsLine(wrest, linelist=ism)
                    aline.analy['spec'] = spec
                    aline.setz(cgm_abs.igm_sys.zabs)
                    aline.limits.set(vmnx)
                    fx, sig, cdict = aline.cut_spec()
                    # Kin
                    stau = laak.generate_stau(cdict['velo'], fx, sig)
                    cgm_abs.igm_sys.kin['Metal'] = laak.pw97_kin(cdict['velo'],
                                                                 stau,
                                                                 per=0.07)
                    cgm_abs.igm_sys.kin['Metal'].update(
                        laak.cgm_kin(cdict['velo'], stau, per=0.07))
                    # Save spec
                    #cgm_abs.igm_sys.kin['Metal']['spec'] = spec
                else:
                    cgm_abs.igm_sys.kin['Metal'] = {}

                # HI
                if kin_init['flgH'][mt] > 0:
                    wrest = kin_init['HI_wrest'][mt] * u.AA
                    if wrest.value <= 1:
                        pdb.set_trace()
                    spec = self.load_bg_cos_spec(qq, wrest)
                    if spec is None:
                        pdb.set_trace()
                    vmnx = (kin_init['HIvmn'][mt],
                            kin_init['HIvmx'][mt]) * u.km / u.s
                    # Process
                    aline = AbsLine(wrest, linelist=ism)
                    aline.analy['spec'] = spec
                    aline.setz(cgm_abs.igm_sys.zabs)
                    aline.limits.set(vmnx)
                    fx, sig, cdict = aline.cut_spec()
                    # Kin
                    stau = laak.generate_stau(cdict['velo'], fx, sig)
                    cgm_abs.igm_sys.kin['HI'] = laak.pw97_kin(cdict['velo'],
                                                              stau,
                                                              per=0.07)
                    cgm_abs.igm_sys.kin['HI'].update(
                        laak.cgm_kin(cdict['velo'], stau, per=0.07))
                else:
                    # Fill with zeros (for the keys)
                    cgm_abs.igm_sys.kin['HI'] = {}
示例#6
0
    def add_abslines_from_linelist(self,
                                   llist='ISM',
                                   init_name=None,
                                   wvlim=None,
                                   min_Wr=None,
                                   **kwargs):
        """
        It adds associated AbsLines satisfying some conditions (see parameters below).

        Parameters
        ----------
        llist : str, optional
            Name of the linetools.lists.linelist.LineList
            object where to look for the transition names.
            Default is 'ISM', which means the function looks
            within `list = LineList('ISM')`.
        init_name : str, optional
            Name of the initial transition used to define the AbsComponent
        wvlim : Quantity array, optional
            Observed wavelength limits for AbsLines to be added.
            e.g. [1200, 2000]*u.AA.
        min_Wr : Quantity, optional
            Minimum rest-frame equivalent with for AbsLines to be added.
            This is calculated in the very low optical depth regime tau0<<1,
            where Wr is independent of Doppler parameter or gamma (see eq. 9.15 of
            Draine 2011). Still, a column density attribute for the AbsComponent
            is needed.

        Returns
        -------
        Adds AbsLine objects to the AbsComponent._abslines list.

        Notes
        -----
        **kwargs are passed to AbsLine.add_absline() method.

        """
        # get the transitions from LineList
        llist = LineList(llist)
        if init_name is None:  # we have to guess it
            if (self.Zion) == (-1, -1):  # molecules
                # init_name must be in self.attrib (this is a patch)
                init_name = self.attrib['init_name']
            else:  # atoms
                init_name = ions.ion_to_name(self.Zion, nspace=0)
        transitions = llist.all_transitions(init_name)

        # unify output to be a Table
        if isinstance(transitions, dict):
            transitions = llist.from_dict_to_table(transitions)

        # check wvlims
        if wvlim is not None:
            # Deal with units
            wrest = transitions['wrest'].data * transitions['wrest'].unit
            # Logic
            cond = (wrest*(1+self.zcomp) >= wvlim[0]) & \
                   (wrest*(1+self.zcomp) <= wvlim[1])
            transitions = transitions[cond]

        # check outputs
        if len(transitions) == 0:
            warnings.warn(
                "No transitions satisfying the criteria found. Doing nothing.")
            return

        # loop over the transitions when more than one found
        for transition in transitions:
            iline = AbsLine(transition['name'], z=self.zcomp, linelist=llist)
            iline.limits.set(self.vlim)
            iline.attrib['coord'] = self.coord
            iline.attrib['logN'] = self.logN
            iline.attrib['sig_logN'] = self.sig_logN
            iline.attrib['flag_N'] = self.flag_N
            iline.attrib['N'] = 10**iline.attrib['logN'] / (u.cm * u.cm)
            iline.attrib['sig_N'] = 10**iline.attrib['sig_logN'] / (u.cm *
                                                                    u.cm)

            for key in self.attrib.keys():
                iline.attrib[key] = self.attrib[key]

            if min_Wr is not None:
                # check logN is defined
                logN = self.logN
                if logN == 0:
                    warnings.warn(
                        "AbsComponent does not have logN defined. Appending AbsLines "
                        "regardless of min_Wr.")
                else:
                    N = 10**logN / (u.cm * u.cm)
                    Wr_iline = iline.get_Wr_from_N(
                        N=N)  # valid for the tau0<<1 regime.
                    if Wr_iline < min_Wr:  # do not append
                        continue
            # add the absline
            self.add_absline(iline)
示例#7
0
文件: quasar.py 项目: yzhenggit/pyigm
def get_telfer_spec(zqso=0.,
                    igm=False,
                    fN_gamma=None,
                    LL_flatten=True,
                    nproc=6,
                    nskip=10):
    """Generate a Telfer QSO composite spectrum

    Parameters
    ----------
    zqso : float, optional
      Redshift of the QSO
    igm : bool, optional
      Include IGM opacity? [False]
    fN_gamma : float, optional
      Power-law evolution in f(N,X)
    LL_flatten : bool, optional
      Set Telfer to a constant below the LL?
    nproc : int, optional
      For multi-processing with IGM
    nskip : int, optional
      Evaluate IGM every nskip

    Returns
    -------
    telfer_spec : XSpectrum1D
      Spectrum
    """
    # Read
    telfer = ascii.read(pyigm_path + '/data/quasar/telfer_hst_comp01_rq.ascii',
                        comment='#')
    scale = telfer['flux'][(telfer['wrest'] == 1450.)]
    telfer_spec = XSpectrum1D.from_tuple(
        (np.array(telfer['wrest']) * (1 + zqso),
         np.array(telfer['flux']) / scale[0]))  # Observer frame

    # IGM?
    if igm is True:
        """The following concept is rather experimental.
        Use at your own risk.
        """
        import multiprocessing
        fN_model = FNModel.default_model()
        # Expanding range of zmnx (risky)
        fN_model.zmnx = (0., 5.5)
        if fN_gamma is not None:
            fN_model.gamma = fN_gamma
        # Setup inputs
        #EW_FIL = pyigm_path+'/data/fN/EW_SPLINE_b24.yml'
        #with open(EW_FIL, 'r') as infile:
        #    EW_spline = yaml.load(infile)  # dict from mk_ew_lyman_spline
        HI = LineList('HI')
        twrest = u.Quantity(HI._data['wrest'])
        # Parallel
        if LL_flatten:
            igm_wv = np.where((telfer['wrest'] > 900.)
                              & (telfer['wrest'] < 1220.))[0]
        else:
            igm_wv = np.where(telfer['wrest'] < 1220.)[0]
        adict = []
        sub_wv = igm_wv[0::nskip]
        if (len(igm_wv) % nskip) != 0:  # Make sure the last element is present
            sub_wv = np.concatenate([sub_wv, np.array([igm_wv[-1]])])
        for wrest in telfer_spec.wavelength[sub_wv].value:
            tdict = dict(ilambda=wrest,
                         zem=zqso,
                         fN_model=fN_model,
                         wrest=twrest.copy())
            adict.append(tdict)
        # Run
        if nproc > 1:
            pool = multiprocessing.Pool(
                nproc)  # initialize thread pool N threads
            ateff = pool.map(pyift.map_lymanew, adict)
        else:
            ateff = map(pyift.map_lymanew, adict)
        # Interpolate
        all_val = interp1d(telfer_spec.wavelength[sub_wv].value,
                           np.array(ateff))(telfer_spec.wavelength[igm_wv])
        # Apply
        new_flux = telfer_spec.flux.value
        new_flux[igm_wv] *= np.exp(-1. * np.array(all_val))
        # Flatten?
        if LL_flatten:
            wv_LL = np.where(
                np.abs(telfer_spec.wavelength /
                       (1 + zqso) - 914. * u.AA) < 3. * u.AA)[0]
            f_LL = np.median(new_flux[wv_LL])
            wv_low = np.where(telfer_spec.wavelength /
                              (1 + zqso) < 911.7 * u.AA)[0]
            new_flux[wv_low] = f_LL
        # Regenerate spectrum
        telfer_spec = XSpectrum1D.from_tuple(
            (np.array(telfer['wrest']) * (1 + zqso), new_flux))

    # Return
    return telfer_spec
示例#8
0
    def __init__(self,
                 ispec,
                 guessfile=None,
                 parent=None,
                 zsys=None,
                 norm=None,
                 exten=None,
                 rsp_kwargs={},
                 unit_test=False,
                 screen_scale=1.,
                 **kwargs):
        QMainWindow.__init__(self, parent)
        """
        ispec = str, XSpectrum1D or tuple of arrays
          Input spectrum or spectrum filename.  If tuple then (wave,
          fx), (wave, fx, sig) or (wave, fx, sig, co)
        guessfile : str, optional
          name of the .json file generated with igmguesses GUI in Pyigm (see https://github.com/pyigm/pyigm/blob/master/docs/igmguesses.rst)
          if not None - overplot fitted line profiles from igmguesses
        parent : Widget parent, optional
        zsys : float, optional
          intial redshift
        exten : int, optional
          extension for the spectrum in multi-extension FITS file
        norm : bool, optional
          True if the spectrum is normalized
        screen_scale : float, optional
          Scale the default sizes for the gui size
        """
        #reload(ltgl)
        #reload(ltgsp)
        # INIT
        #QtCore.pyqtRemoveInputHook()
        #xdb.set_trace()
        #QtCore.pyqtRestoreInputHook()

        self.scale = screen_scale

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

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

        # Status bar
        self.create_status_bar()

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

        ## Abs sys
        abs_sys = None
        voigtsfit = None
        if guessfile is not None:
            # Load
            ism = LineList('ISM')
            igm_guess = ltu.loadjson(guessfile)
            comps = []
            for key in igm_guess['cmps'].keys():
                comp = AbsComponent.from_dict(igm_guess['cmps'][key],
                                              chk_vel=False,
                                              linelist=ism)
                comps.append(comp)
            abs_sys = ltiu.build_systems_from_components(
                comps, vsys=500. * u.km /
                u.s)  # ,chk_z=False)  ### 100000.*u.km/u.s   ok

            ### voigt fit - added
            # Spectrum
            spec, spec_fil = ltgu.read_spec(ispec,
                                            exten=exten,
                                            norm=norm,
                                            rsp_kwargs=rsp_kwargs)

            voigtsfit = np.asarray([0] * len(spec.wavelength))
            alllines = []
            for iabs_sys in abs_sys:
                lines = iabs_sys.list_of_abslines()
                alllines = alllines + lines
            if len(alllines) > 0:
                voigtsfit = lav.voigt_from_abslines(spec.wavelength,
                                                    alllines,
                                                    fwhm=3.).flux.value

            if not norm:
                voigtsfit = voigtsfit * spec.co

        # Hook the spec widget to Plot Line
        self.spec_widg = ltgsp.ExamineSpecWidget(ispec,
                                                 guessfile=guessfile,
                                                 voigtsfit=voigtsfit,
                                                 status=self.statusBar,
                                                 parent=self,
                                                 llist=self.pltline_widg.llist,
                                                 zsys=zsys,
                                                 norm=norm,
                                                 exten=exten,
                                                 abs_sys=abs_sys,
                                                 screen_scale=self.scale,
                                                 rsp_kwargs=rsp_kwargs,
                                                 **kwargs)
        # Reset redshift from spec
        if zsys is None:
            if hasattr(self.spec_widg.spec, 'z'):
                self.pltline_widg.setz(
                    str(self.spec_widg.spec.z[self.spec_widg.select]))
        # 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)

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

        # Layout

        # 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.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()
示例#9
0
    def fill_data(self,
                  trans,
                  linelist=None,
                  closest=False,
                  verbose=True,
                  use_CACHE=False,
                  **kwargs):
        """ Fill atomic data and setup analy.

        Parameters
        ----------
        trans : Quantity or str
          Either a rest wavelength (e.g. 1215.6700*u.AA) or the name
          of a transition (e.g. 'CIV 1548'). For an unknown transition
          use string 'unknown'.
        linelist : str or LineList or list of LineList objects, optional
          Class of linelist or str setting LineList
          or list of LineList objects
        closest : bool, optional
          Take the closest line to input wavelength? [False]
        """
        global CACHE_LLIST  # Only cached if LineList is *not* input
        # Deal with LineList
        flg_list = False
        if linelist is None:
            if use_CACHE and (CACHE_LLIST is not None):
                llist = CACHE_LLIST
            else:
                if self.ltype == 'Abs':
                    llist = LineList('ISM')
                elif self.ltype == 'Em':
                    llist = LineList('Galaxy')
                else:
                    raise ValueError("Not ready for ltype = {:s}".format(
                        self.ltype))
        elif isinstance(linelist, basestring):
            llist = LineList(linelist)
        elif isinstance(linelist, LineList):
            llist = linelist
        elif isinstance(linelist, list):
            llist = linelist[0]
            flg_list = True
        else:
            raise ValueError('Bad input for linelist')

        # Cache
        CACHE_LLIST = llist
        # Closest?
        llist.closest = closest

        # Data
        if flg_list:  # Allow for a list of LineList
            for llist in linelist:
                llist.closest = closest
                newline = llist[trans]
                if newline is not None:
                    break
        else:
            newline = llist[trans]

        # Success?
        if newline is None:
            print("Transition {} not found in LineList {:s}".format(
                trans, llist.list))
            raise ValueError("You may need to set clear_CACHE_LLIST=True")
        try:
            self.data.update(newline)  # Expected to be a LineList dict object
        except TypeError:
            raise TypeError("Probably should not be here")

        # Update
        if isinstance(self.data, dict):
            self.wrest = self.data['wrest']
        else:
            self.wrest = self.data['wrest'] * self.data['wrest'].unit
        self.name = self.data['name']

        #
        self.update()  # is this used ?
示例#10
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 = urllib2.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_ion(ionc)
            except KeyError:
                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
示例#11
0
文件: tlk_qpq.py 项目: profxj/talks
def fig_molecules():
    """ H2, Lya, CII plots
    """
    # Spec files

    # Load QPQ7
    #if qpq7 is None:
    #    qpq7 = equ.load_qpq(7)

    # LineList
    H2 = LineList('H2')
    CO_waves = [1447.3521, 1477.5649, 1509.7480]
    CO_lbls = ['CO 2-0', 'CO 1-0', 'CO 0-0']

    outfil = 'fig_qpq_molecules.pdf'
    pp = PdfPages(outfil)

    fig = plt.figure(figsize=(8.5, 4))
    plt.clf()
    gs = gridspec.GridSpec(2, 5)
    xpsimp.dark_bkgd(plt)

    qpq8_sys = ['J114436.65+095904.9', 'J142758.73-012136.1']
    qpq8_yrng = [(0., 1.2), (0., 1.2)]
    wvobs = [(4160, 4240.), (4735, 4950)]  # Lyman-Werner, CO
    #qpq8_sys = ['J120416.68+022110.9']
    qpq8_zfg = [2.973, 2.27616]
    trans = [1215.6701, 1334.5323]
    tvmnx = [(-400, 400), (-200, 200)]
    lbls = ['HI Lya', 'CII 1334']

    for qq, qsys in enumerate(qpq8_sys):
        # Load spectrum
        sdict = eqs.spec_wvobs(qsys, wvobs[qq][0] * u.AA, high_res=2)
        spec = sdict['spec']
        spec.normalize(sdict['conti'])
        if qq == 1:  # Smooth for presentation
            tmpspec = XSpectrum1D.from_tuple((spec.wavelength, spec.flux))
            spec = tmpspec.box_smooth(3)

        # Loop on standard transitions
        for jj, itrans in enumerate(trans):

            ax = plt.subplot(gs[qq, jj])
            ax.set_xlim(tvmnx[jj])
            ax.xaxis.set_major_locator(plt.MultipleLocator(200.))
            ax.set_ylim(-0.05, 1.2)
            if jj == 0:
                ax.set_ylabel('Flux')
            ax.set_xlabel('Velocity (km/s)')

            # Plot
            velo = spec.relative_vel(itrans * u.AA * (1 + qpq8_zfg[qq]))
            ax.plot(velo, spec.flux, color='white', drawstyle='steps')
            ax.plot(tvmnx[jj], [1.] * 2, '--', color='lightgreen')
            # Label
            ax.text(0.50,
                    0.90,
                    lbls[jj],
                    transform=ax.transAxes,
                    size='large',
                    ha='center',
                    color='yellow')
        # Molecules
        ax = plt.subplot(gs[qq, len(trans):])
        ax.set_xlim(wvobs[qq])
        ax.set_ylim(qpq8_yrng[qq])
        ax.set_xlabel('Wavelength (Angstroms)')
        ax.plot(spec.wavelength, spec.flux, color='white', drawstyle='steps')
        if qq == 0:  # Lyman-Werner
            wrlim = [iwv * u.AA / (1 + qpq8_zfg[qq]) for iwv in wvobs[qq]]
            gdlin = np.where((H2._fulltable['Jk'] < 7)
                             & (H2._fulltable['wrest'] > wrlim[0])
                             & (H2._fulltable['wrest'] < wrlim[1]))[0]
            for igd in gdlin:
                if H2._fulltable['Jk'][igd] <= 2:
                    clr = 'cyan'
                    do_lbl = True
                else:
                    clr = 'gray'
                    do_lbl = False
                ax.plot(
                    [H2._fulltable['wrest'][igd].value *
                     (1 + qpq8_zfg[qq])] * 2,
                    qpq8_yrng[qq],
                    '--',
                    color=clr)
                if do_lbl:
                    ax.text(H2._fulltable['wrest'][igd].value *
                            (1 + qpq8_zfg[qq]),
                            0.4,
                            H2._fulltable['name'][igd],
                            rotation=90.,
                            color=clr,
                            size=12)
        else:  # CO
            for jj, CO_wave in enumerate(CO_waves):
                ax.plot([CO_wave * (1 + qpq8_zfg[qq])] * 2,
                        qpq8_yrng[qq],
                        '--',
                        color='cyan')
                ax.text(CO_wave * (1 + qpq8_zfg[qq]),
                        0.4,
                        CO_lbls[jj],
                        rotation=90,
                        color='cyan',
                        size=12)

    # Write
    plt.tight_layout(pad=0.2, h_pad=0., w_pad=0.1)
    pp.savefig()
    pp.close()
    plt.close()
    print('Genereated {:s}'.format(outfil))
示例#12
0
def set_llist(llist, in_dict=None, sort=True):
    ''' Method to set a line list dict for the Widgets
    sort: bool, optional [DEPRECATED CURRENTLY]
      Sort lines by rest wavelength [True]
    '''
    from linetools.lists.linelist import LineList
    from astropy.units.quantity import Quantity

    if in_dict is None:
        in_dict = {}

    if isinstance(llist, basestring):  # Set line list from a file
        in_dict['List'] = llist
        if llist == 'None':
            in_dict['Plot'] = False
        else:
            in_dict['Plot'] = True
            # Load?
            if not (llist in in_dict):
                # Homebrew
                if llist == 'OVI':
                    gdlines = u.AA * [
                        629.730, 702.332, 770.409, 780.324, 787.711, 832.927,
                        972.5367, 977.0201, 1025.7222, 1031.9261, 1037.6167,
                        1206.5, 1215.6700, 1260.4221
                    ]
                    llist_cls = LineList('Strong', subset=gdlines)
                    in_dict[llist] = llist_cls
                else:
                    llist_cls = LineList(llist)
                    # Sort
                    llist_cls._data.sort('wrest')
                    # Load
                    in_dict[llist] = llist_cls
    elif isinstance(llist, (Quantity, list)):  # Set from a list of wrest
        in_dict['List'] = 'input.lst'
        in_dict['Plot'] = True
        # Fill
        if sort:
            llist.sort()
        llist_cls = LineList('ISM', subset=llist)
        in_dict['input.lst'] = llist_cls
        '''
        line_file = xa_path+'/data/spec_lines/grb.lst'
        llist_cls = xspec.abs_line.Abs_Line_List(line_file)
        adict = llist_cls.data
        # Fill 
        names = []
        fval = []
        for wrest in llist:
            mt = np.where(np.abs(wrest-adict['wrest']) < 1e-3)[0]
            if len(mt) != 1:
                raise ValueError('Problem!')
            names.append(adict['name'][mt][0])
            fval.append(adict['fval'][mt][0])
        # Set
        #QtCore.pyqtRemoveInputHook()
        #xdb.set_trace()
        #QtCore.pyqtRestoreInputHook()
        # Generate a Table
        col0 = Column(np.array(llist), name='wrest', unit=u.AA) # Assumed Angstroms
        col1 = Column(np.array(names), name='name')
        col2 = Column(np.array(fval), name='fval')
        in_dict['input.lst'] = Table( (col0,col1,col2) )
        '''
    else:
        raise IOError('Not ready for this type of input')

    # Return
    return in_dict
示例#13
0
文件: galaxy.py 项目: yzhenggit/pyigm
    def load_coolgas(self):
        """ Load data on cool gas (CII, CIV, SiII, SiIII)
        Richter+17
        """
        llist = LineList('ISM')
        # Ricther+17
        print('Loading Richter+17 for CII, CIV, SiII, SiIII')
        r17_a1_file = resource_filename('pyigm',
                                        '/data/CGM/Galaxy/richter17_A1.fits')
        r17_a1 = Table.read(r17_a1_file)
        r17_a2_file = resource_filename('pyigm',
                                        '/data/CGM/Galaxy/richter17_A2.fits')
        r17_a2 = Table.read(r17_a2_file)
        # Coords
        coords = SkyCoord(ra=r17_a1['_RAJ2000'],
                          dec=r17_a1['_DEJ2000'],
                          unit='deg')
        gc = coords.transform_to('galactic')
        ra = np.zeros((len(r17_a2)))
        dec = np.zeros((len(r17_a2)))

        # Loop on Sightlines
        for kk, row in enumerate(r17_a1):
            if self.debug and (kk == 5):
                break
            a2_idx = np.where(r17_a2['Name'] == row['Name'])[0]
            if len(a2_idx) == 0:
                continue
            ra[a2_idx] = row['_RAJ2000']
            dec[a2_idx] = row['_DEJ2000']
            # Generate the components
            icoord = gc[kk]
            alines = []
            for jj, idx in enumerate(a2_idx):
                # Transition
                trans = '{:s} {:d}'.format(r17_a2['Ion'][idx].strip(),
                                           int(r17_a2['lambda0'][idx]))
                try:
                    aline = AbsLine(trans, linelist=llist)
                except ValueError:
                    pdb.set_trace()
                aline.attrib['coord'] = icoord

                # Skip EW=0 lines
                if r17_a2['e_W'][idx] == 0:
                    continue
                # Velocity
                z = 0.
                aline.setz(z)
                vlim = np.array([r17_a2['vmin'][idx], r17_a2['vmax'][idx]
                                 ]) * u.km / u.s

                aline.limits.set(vlim)  # These are v_LSR
                # EW
                aline.attrib['flag_EW'] = 1
                aline.attrib['EW'] = r17_a2['W'][idx] / 1e3 * u.AA
                aline.attrib['sig_EW'] = r17_a2['e_W'][idx] / 1e3 * u.AA
                # Column

                if np.isnan(
                        r17_a2['logN']
                    [idx]):  # Odd that some lines had an error but no value
                    aline.attrib['flag_N'] = 0
                elif r17_a2['l_logN'][idx] == '>':
                    aline.attrib['flag_N'] = 2
                    aline.attrib['sig_logN'] = 99.99
                else:
                    aline.attrib['flag_N'] = 1
                    aline.attrib['sig_logN'] = r17_a2['e_logN'][idx]
                aline.attrib['logN'] = r17_a2['logN'][idx]
                # Fill linear
                _, _ = linear_clm(aline.attrib)
                alines.append(aline)
            # Generate components from abslines
            comps = ltiu.build_components_from_abslines(alines,
                                                        chk_sep=False,
                                                        chk_vel=False)
            # Limits
            vmin = np.min([icomp.limits.vmin.value for icomp in comps])
            vmax = np.max([icomp.limits.vmax.value for icomp in comps])
            # Instantiate
            s_kwargs = dict(name=row['Name'] + '_z0')
            c_kwargs = dict(chk_sep=False, chk_z=False)
            abssys = IGMSystem.from_components(comps,
                                               vlim=[vmin, vmax] * u.km / u.s,
                                               s_kwargs=s_kwargs,
                                               c_kwargs=c_kwargs)
            # CGM Abs
            rho, ang_sep = calc_Galactic_rho(abssys.coord)
            cgmabs = CGMAbsSys(self.galaxy,
                               abssys,
                               rho=rho,
                               ang_sep=ang_sep,
                               cosmo=self.cosmo)
            # Add to cgm_abs
            self.abs.cgm_abs.append(cgmabs)
        # Finish
        r17_a2['RA'] = ra
        r17_a2['DEC'] = dec
        self.richter17 = r17_a2
        # Reference
        if len(self.refs) > 0:
            self.refs += ','
        self.refs += 'Richter+17'
示例#14
0
文件: galaxy.py 项目: yzhenggit/pyigm
    def load_hotgas(self):
        """ Load data on hot gas (e.g. OVII, OVIII)
        Fang+15
        """

        # Init
        llist = LineList('EUV')
        ovii = AbsLine('OVII 21', linelist=llist)
        scoord = self.abs.scoord  # Sightline coordiantes

        # Fang+15  Table 1  [OVII]
        fang15_file = resource_filename('pyigm',
                                        '/data/CGM/Galaxy/fang15_table1.dat')
        self.fang15 = Table.read(fang15_file, format='cds')
        print('Loading Fang+15 for OVII')
        # Reference
        if len(self.refs) > 0:
            self.refs += ','
        self.refs += 'Fang+15'
        # Generate the systems
        # # (should check to see if low-ion ones exist already)
        for row in self.fang15:
            # Coordinates
            gc = SkyCoord(l=row['GLON'] * u.degree,
                          b=row['GLAT'] * u.degree,
                          frame='galactic')
            # Limits
            # OVII line
            aline = ovii.copy()
            aline.attrib['coord'] = gc
            z = row['Vel'] / c_kms
            try:
                aline.setz(z)
            except IOError:
                z = 0.
                vlim = np.array([-300, 300]) * u.km / u.s
                aline.attrib['flag_EW'] = 3
                aline.attrib['EW'] = row['EW1'] / 1e3 * u.AA
                aline.attrib['sig_EW'] = 99. * u.AA
                #
                aline.attrib[
                    'flag_N'] = 0  # Might be able to set an upper limit
            else:
                aline.attrib['b'] = row['b'] * u.km / u.s
                aline.attrib['flag_EW'] = 1
                aline.attrib['EW'] = row['EW1'] / 1e3 * u.AA
                aline.attrib['sig_EW'] = row['e_EW1'] / 1e3 * u.AA
                vlim = np.array(
                    [-1, 1]) * (2 * row['b'] + 2 * row['E_b']) * u.km / u.s
                # N_OVII
                aline.attrib['flag_N'] = 1
                aline.attrib['logN'] = row['logNO']
                aline.attrib['sig_logN'] = np.array(
                    [row['e_logNO'], row['E_logNO']])
                # Fill linear
                _, _ = linear_clm(aline.attrib)
            # OVII
            aline.limits.set(vlim)
            # Generate component and add
            comp = AbsComponent.from_abslines([aline])
            if aline.attrib['flag_N'] == 0:  # Hack to merge later
                comp.attrib['sig_logN'] = np.array([0., 0.])
            else:
                pass
            # Check for existing system
            minsep = np.min(comp.coord.separation(scoord).to('arcsec'))
            if minsep < 30 * u.arcsec:  # Add component to existing system
                idx = np.argmin(comp.coord.separation(scoord).to('arcsec'))
                if self.verbose:
                    print("Adding OVII system to {}".format(
                        self.abs.cgm_abs[idx].igm_sys))
                self.abs.cgm_abs[idx].igm_sys.add_component(comp,
                                                            chk_sep=False,
                                                            debug=True)
            else:  # Instantiate
                abssys = IGMSystem(gc,
                                   z,
                                   vlim,
                                   name=row['Name'] + '_z0',
                                   zem=row['z'])
                abssys.add_component(comp, chk_sep=False)
                # CGM Abs
                rho, ang_sep = calc_Galactic_rho(abssys.coord)
                cgmabs = CGMAbsSys(self.galaxy,
                                   abssys,
                                   rho=rho,
                                   ang_sep=ang_sep,
                                   cosmo=self.cosmo)
                # Add to cgm_abs
                self.abs.cgm_abs.append(cgmabs)

        scoord = self.abs.scoord  # Sightline coordiantes
        # Savage+03  Table 2  [OVI] -- Thick disk/halo only??
        print('Loading Savage+03 for OVI')
        savage03_file = resource_filename(
            'pyigm', '/data/CGM/Galaxy/savage03_table2.fits')
        self.savage03 = Table.read(savage03_file)
        # Reference
        if len(self.refs) > 0:
            self.refs += ','
        self.refs += 'Savage+03'
        # Generate the systems
        # # (should check to see if low-ion ones exist already)
        for row in self.savage03:
            # Coordinates
            coord = SkyCoord(ra=row['_RA'] * u.deg,
                             dec=row['_DE'] * u.deg,
                             frame='icrs')
            gc = coord.transform_to('galactic')
            # Build the component
            vlim = np.array([row['V-'], row['V_']]) * u.km / u.s
            comp = AbsComponent(gc, (8, 6), 0., vlim)
            # Add attributes
            if row['b'] > 0.:
                comp.attrib['vcen'] = row['__v_obs'] * u.km / u.s
                comp.attrib['sig_vcen'] = row['e__v_obs'] * u.km / u.s
                comp.attrib['b'] = row['b'] * u.km / u.s
                comp.attrib['sig_b'] = row['e_b'] * u.km / u.s
                # Column
                comp.attrib['flag_N'] = 1
                comp.attrib['logN'] = row['logN_OVI_']
                comp.attrib['sig_logN'] = np.array(
                    [np.sqrt(row['e_sc']**2 + row['e_sys']**2)] * 2)
            else:  # Upper limit
                comp.attrib['flag_N'] = 3
                comp.attrib['logN'] = row['logN_OVI_']
                comp.attrib['sig_logN'] = np.array([99.] * 2)
            # Set linear quantities
            _, _ = linear_clm(comp.attrib)
            # Check for existing system
            minsep = np.min(comp.coord.separation(scoord).to('arcsec'))
            if minsep < 30 * u.arcsec:
                idx = np.argmin(comp.coord.separation(scoord).to('arcsec'))
                self.abs.cgm_abs[idx].igm_sys.add_component(comp,
                                                            chk_sep=False,
                                                            debug=True,
                                                            update_vlim=True)
            else:  # New
                if row['RV'] > 0:
                    zem = row['RV'] / c_kms
                else:
                    zem = row['z']
                abssys = IGMSystem(gc,
                                   comp.zcomp,
                                   vlim,
                                   name=row['Name'] + '_z0',
                                   zem=zem)
                abssys.add_component(comp, chk_sep=False, debug=True)
                # CGM Abs
                rho, ang_sep = calc_Galactic_rho(abssys.coord)
                cgmabs = CGMAbsSys(self.galaxy,
                                   abssys,
                                   rho=rho,
                                   ang_sep=ang_sep,
                                   cosmo=self.cosmo)
                # Add to cgm_abs
                self.abs.cgm_abs.append(cgmabs)
示例#15
0
def fig_lya_line(lw=1.5, csz=15.):
    """  Generate a DLA in optical depth and flux space
    Parameters
    ----------
    """
    llist = LineList('ISM')
    # Lya
    lya = AbsLine('HI 1215', z=0., llist=llist)

    # Wavelength
    wave = np.linspace(1100., 1310., 100000)*u.AA

    outfile = 'fig_lya_line.png'

    # Figure
    plt.figure(figsize=(8, 4))
    plt.clf()
    gs = gridspec.GridSpec(1, 2)


    # Tau plot
    ax1 = plt.subplot(gs[0])

    # Optical depth
    lya.attrib['N'] = 1e21 / u.cm**2
    lya.attrib['b'] = 20 * u.km/u.s
    tau = voigt_from_abslines(wave, lya, ret='tau')

    # Plot
    ax1.plot(wave, tau, 'g')

    # Axes
    ax1.set_xlim(1200., 1230.)
    ax1.set_ylim(1e-2, 5e7)
    ax1.set_yscale("log", nonposy='clip')
    ax1.set_ylabel(r'Optical Depth for $N_{\rm HI} = 10^{21} \, \rm cm^{-2}$')
    ax1.set_xlabel(r'Wavelength ($\AA$)')
    ax1.xaxis.set_major_locator(plt.MultipleLocator(10.))
    #
    set_spines(ax1, 2.)
    set_fontsize(ax1,csz)

    # Flux space
    ax2 = plt.subplot(gs[1])

    for logN in [19., 20., 21., 22.]:
        lya.attrib['N'] = 10**logN / u.cm**2
        spec = voigt_from_abslines(wave, lya)
        # Plot
        ax2.plot(spec.wavelength, spec.flux, label=r'$\log N_{\rm HI} = $'+'{:d}'.format(int(logN)))
    # Axes
    wvoff = 100.
    ax2.set_xlim(1215.-wvoff, 1215.+wvoff)
    ax2.set_ylim(-0.05, 1.1)
    #ax2.set_yscale("log", nonposy='clip')
    ax2.set_ylabel('Normalized Flux')
    ax2.set_xlabel(r'Wavelength ($\AA$)')
    ax2.xaxis.set_major_locator(plt.MultipleLocator(50.))
    #
    set_spines(ax2, 2.)
    set_fontsize(ax2,csz)
    legend = ax2.legend(loc='lower left', scatterpoints=1, borderpad=0.3,
                      handletextpad=0.3, fontsize='small', numpoints=1)

    # Write
    plt.tight_layout(pad=0.2,h_pad=0.,w_pad=0.1)
    plt.savefig(outfile, dpi=750)
    plt.close()
    print("Wrote {:s}".format(outfile))
示例#16
0
    def get_ions(self, use_Nfile=False, idict=None, update_zvlim=True,
                 linelist=None, verbose=True):
        """Parse the ions for each Subsystem

        And put them together for the full system
        Fills ._ionN with a QTable

        Parameters
        ----------
        idict : dict, optional
          dict containing the IonClms info
        use_Nfile : bool, optional
          Parse ions from a .clm file (JXP historical)
          NOTE: This ignores velocity constraints on components (i.e. chk_vel=False)
        update_zvlim : bool, optional
          Update zvlim from lines in .clm (as applicable)
        linelist : LineList
        """
        if idict is not None:
            table = dict_to_ions(idict)
            self._ionN = table
        elif use_Nfile:
            # Subsystems
            if self.nsub > 0:  # This speeds things up (but is rarely used)
                linelist = LineList('ISM')
            for lbl in self.subsys.keys():
                clm_fil = self.tree+self.subsys[lbl]._datdict['clm_file']
                # Parse .clm file
                self.subsys[lbl]._clmdict = igmau.read_clmfile(clm_fil, linelist=linelist)
                # Build components from lines
                components = ltiu.build_components_from_dict(self.subsys[lbl]._clmdict,
                                                             coord=self.coord, chk_vel=False)
                self.subsys[lbl]._components = components
                # Update z, vlim
                if update_zvlim:
                    self.update_vlim(sub_system=lbl)
                    self.subsys[lbl].zabs = self.subsys[lbl]._clmdict['zsys']
                # Read .ion file and fill in components
                ion_fil = self.tree+self.subsys[lbl]._clmdict['ion_fil']
                self.subsys[lbl]._indiv_ionclms = igmau.read_ion_file(ion_fil, components)
                # Parse .all file
                all_file = ion_fil.split('.ion')[0]+'.all'
                self.subsys[lbl].all_file=all_file #MF: useful to have
                _ = igmau.read_all_file(all_file, components=components)
                # Build table
                self.subsys[lbl]._ionN = ltiu.iontable_from_components(components,ztbl=self.subsys[lbl].zabs)
                # Add to IGMSystem
                for comp in components:
                    self.add_component(comp)

            # Combine
            if self.nsub == 1:
                self._ionN = self.subsys['A']._ionN
                self._clmdict = self.subsys['A']._clmdict
                #xdb.set_trace()
            elif self.nsub == 0:
                raise ValueError('lls_utils.get_ions: Cannot have 0 subsystems..')
            else:
                self._ionN = self.subsys['A']._ionN
                self._clmdict = self.subsys['A']._clmdict
                warnings.warn('lls_utils.get_ions: Need to update multiple subsystems!! Taking A.')
        else:
            raise ValueError("Need an option in get_ions")