def test_multi_components(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans) iline.attrib['z'] = 2.92939 iline.analy['vlim'] = [-250.,80.]*u.km/u.s abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) SiII_comp.coord = radec # Instantiate LLSsys = GenericAbsSystem.from_components([abscomp,SiII_comp]) # Test assert len(LLSsys._components) == 2
def test_add_component(): radec = SkyCoord(ra=123.1143 * u.deg, dec=-12.4321 * u.deg) # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA) lya.analy['vlim'] = [-300., 300.] * u.km / u.s lya.attrib['z'] = 2.92939 lya.attrib['N'] = 1e17 / u.cm**2 lyb = AbsLine(1025.7222 * u.AA) lyb.analy['vlim'] = [-300., 300.] * u.km / u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya, lyb]) abscomp.coord = radec # Instantiate abssys = GenericAbsSystem.from_components([abscomp]) # New component oi = AbsLine('OI 1302') oi.analy['vlim'] = [-300., 300.] * u.km / u.s oi.attrib['z'] = lya.attrib['z'] abscomp2 = AbsComponent.from_abslines([oi]) abscomp2.coord = radec # Standard assert abssys.add_component(abscomp2) # Fail abssys = GenericAbsSystem.from_components([abscomp]) abscomp2.vlim = [-400., 300.] * u.km / u.s assert not abssys.add_component(abscomp2) # Overlap assert abssys.add_component(abscomp2, overlap_only=True)
def __init__(self, z, wrest, vlim=[-300.,300]*u.km/u.s, linelist=None): # Init self.init_wrest = wrest self.linelist = linelist self.lines = [] self.init_lines() # Generate with type radec = (0*u.deg,0*u.deg) Zion = (self.lines[0].data['Z'],self.lines[0].data['ion']) Ej = self.lines[0].data['Ej'] AbsComponent.__init__(self,radec, Zion, z, vlim, Ej, comment='None') # Init cont. self.attrib = {'N': 0./u.cm**2, 'Nsig': 0./u.cm**2, 'flagN': 0, # Column 'logN': 0., 'sig_logN': 0., 'b': 0.*u.km/u.s, 'bsig': 0.*u.km/u.s, # Doppler 'z': self.zcomp, 'zsig': 0., 'Quality': 'None'} # Sync self.sync_lines() # Use different naming convention here self.name = 'z{:.5f}_{:s}'.format( self.zcomp,self.lines[0].data['name'].split(' ')[0])
def test_add_component(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lya.attrib['N'] = 1e17 / u.cm**2 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # Instantiate abssys = GenericAbsSystem.from_components([abscomp]) # New component oi = AbsLine('OI 1302') oi.analy['vlim'] = [-300.,300.]*u.km/u.s oi.attrib['z'] = lya.attrib['z'] abscomp2 = AbsComponent.from_abslines([oi]) abscomp2.coord = radec # Standard assert abssys.add_component(abscomp2) # Fail abssys = GenericAbsSystem.from_components([abscomp]) abscomp2.vlim = [-400.,300.]*u.km/u.s assert not abssys.add_component(abscomp2) # Overlap assert abssys.add_component(abscomp2, overlap_only=True)
def test_init_multi_absline(): # AbsLine(s) lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) lyb = AbsLine(1025.7222 * u.AA) lyb.setz(lya.z) lyb.limits.set([-300., 300.] * u.km / u.s) # Instantiate abscomp = AbsComponent.from_abslines([lya, lyb]) # Test assert len(abscomp._abslines) == 2 np.testing.assert_allclose(abscomp.zcomp, 2.92939) # With column densities lya.attrib['N'] = 1e12 / u.cm**2 lya.attrib['sig_N'] = [1e11] * 2 / u.cm**2 lya.attrib['flag_N'] = 1 lya.attrib['b'] = 30 * u.km / u.s lyb.attrib['N'] = 3e12 / u.cm**2 lyb.attrib['sig_N'] = [2e11] * 2 / u.cm**2 lyb.attrib['flag_N'] = 1 lyb.attrib['b'] = 30 * u.km / u.s abscomp = AbsComponent.from_abslines([lya, lyb]) # Test assert abscomp.flag_N == 1 assert abscomp.attrib['sig_logN'].size == 2 assert np.isclose(abscomp.logN, 12.146128035678238)
def test_list_of_abslines(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans) iline.attrib['z'] = 2.92939 iline.analy['vlim'] = [-250.,80.]*u.km/u.s abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) SiII_comp.coord = radec # Instantiate gensys = GenericAbsSystem.from_components([abscomp,SiII_comp]) # Now the list abslines = gensys.list_of_abslines() # Test assert len(abslines) == 6 # Grab one line lyb = gensys.get_absline('HI 1025') np.testing.assert_allclose(lyb.wrest.value, 1025.7222) lyb = gensys.get_absline(1025.72*u.AA) np.testing.assert_allclose(lyb.wrest.value, 1025.7222)
def test_abscomp_H2(): Zion = (-1, -1) # temporary code for molecules Ntuple = (1, 17, -1) # initial guess for Ntuple (needs to be given for adding lines from linelist) coord = SkyCoord(0,0, unit='deg') z = 0.212 vlim = [-100., 100.] * u.km/u.s comp = AbsComponent(coord, Zion, z, vlim, Ntup=Ntuple) comp.add_abslines_from_linelist(llist='H2', init_name="B19-0P(1)", wvlim=[1100, 5000]*u.AA) assert len(comp._abslines) == 7
def test_fromtodict(): SiIIcomp1,_ = mk_comp('SiII',vlim=[-300.,50.]*u.km/u.s, add_spec=True) cdict = SiIIcomp1.to_dict() # assert isinstance(cdict, dict) assert cdict['Zion'] == (14, 2) # And instantiate newcomp = AbsComponent.from_dict(cdict) assert isinstance(newcomp, AbsComponent) newcomp = AbsComponent.from_dict(cdict, coord=SkyCoord(0,0, unit='deg'))
def test_fromtodict(): SiIIcomp1, _ = mk_comp('SiII', vlim=[-300., 50.] * u.km / u.s, add_spec=True) cdict = SiIIcomp1.to_dict() # assert isinstance(cdict, dict) assert cdict['Zion'] == (14, 2) # And instantiate newcomp = AbsComponent.from_dict(cdict) assert isinstance(newcomp, AbsComponent) newcomp = AbsComponent.from_dict(cdict, coord=SkyCoord(0, 0, unit='deg'))
def test_init(): # Simple properties abscomp = AbsComponent((10.0 * u.deg, 45 * u.deg), (14, 2), 1.0, [-300, 300] * u.km / u.s) # Test assert abscomp.Zion[0] == 14 np.testing.assert_allclose(abscomp.zcomp, 1.0) print(abscomp) # Fine structure comp = AbsComponent((10.0 * u.deg, 45 * u.deg), (14, 2), 1.0, [-300, 300] * u.km / u.s, Ej=0.1 / u.cm) # need stars! assert comp.name.count('*') == 1
def test_abscomp_H2(): Zion = (-1, -1) # temporary code for molecules Ntuple = ( 1, 17, -1 ) # initial guess for Ntuple (needs to be given for adding lines from linelist) coord = SkyCoord(0, 0, unit='deg') z = 0.212 vlim = [-100., 100.] * u.km / u.s comp = AbsComponent(coord, Zion, z, vlim, Ntup=Ntuple) comp.add_abslines_from_linelist(llist='H2', init_name="B19-0P(1)", wvlim=[1100, 5000] * u.AA) assert len(comp._abslines) == 7
def fill_lls_lines(self, bval=20. * u.km / u.s, do_analysis=1): """ Generate an HI line list for an LLS. Goes into self.lls_lines Now generates a component too. Should have it check for an existing HI component.. Parameters ---------- bval : float, optional Doppler parameter in km/s do_analysis : int, optional flag for analysis """ from linetools.lists import linelist as lll # May be replaced by component class (as NT desires) HIlines = lll.LineList('HI') self.lls_lines = [] Nval = 10**self.NHI / u.cm**2 for wrest in u.Quantity(HIlines._data['wrest']): aline = AbsLine(wrest, linelist=HIlines) # Attributes aline.attrib['N'] = Nval aline.attrib['b'] = bval aline.setz(self.zabs) aline.limits.set(self.vlim) aline.analy['do_analysis'] = do_analysis aline.attrib['coord'] = self.coord self.lls_lines.append(aline) # Generate a component (should remove any previous HI) self.add_component(AbsComponent.from_abslines(self.lls_lines))
def test_todict_withjson(): radec = SkyCoord(ra=123.1143 * u.deg, dec=-12.4321 * u.deg) # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA) lya.limits.set([-300., 300.] * u.km / u.s) lya.attrib['z'] = 2.92939 lya.attrib['coord'] = radec lyb = AbsLine(1025.7222 * u.AA) lyb.limits.set([-300., 300.] * u.km / u.s) lyb.attrib['z'] = lya.attrib['z'] lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya, lyb]) # Instantiate HIsys = LymanAbsSystem.from_components([abscomp]) # Dict adict = HIsys.to_dict() assert isinstance(adict, dict) # Verify it is JSON compatible (failing in Python 3) import io, json with io.open('tmp.json', 'w', encoding='utf-8') as f: f.write( unicode( json.dumps(adict, sort_keys=True, indent=4, separators=(',', ': '))))
def mk_comp(ctype,vlim=[-300.,300]*u.km/u.s,add_spec=False, use_rand=True, add_trans=False, zcomp=2.92939, b=20*u.km/u.s): # Read a spectrum Spec if add_spec: xspec = lsio.readspec(lt_path+'/spectra/tests/files/UM184_nF.fits') else: xspec = None # AbsLines if ctype == 'HI': all_trans = ['HI 1215', 'HI 1025'] elif ctype == 'SiII': all_trans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] if add_trans: all_trans += ['SiII 1193'] abslines = [] for trans in all_trans: iline = AbsLine(trans, z=zcomp) if use_rand: rnd = np.random.rand() else: rnd = 0. iline.attrib['logN'] = 13.3 + rnd iline.attrib['sig_logN'] = 0.15 iline.attrib['flag_N'] = 1 iline.attrib['b'] = b iline.analy['spec'] = xspec iline.limits.set(vlim) _,_ = ltaa.linear_clm(iline.attrib) # Loads N, sig_N abslines.append(iline) # Component abscomp = AbsComponent.from_abslines(abslines) return abscomp, abslines
def fill_lls_lines(self, bval=20.*u.km/u.s, do_analysis=1): """ Generate an HI line list for an LLS. Goes into self.lls_lines Now generates a component too. Should have it check for an existing HI component.. Parameters ---------- bval : float, optional Doppler parameter in km/s do_analysis : int, optional flag for analysis """ from linetools.lists import linelist as lll # May be replaced by component class (as NT desires) HIlines = lll.LineList('HI') self.lls_lines = [] Nval = 10**self.NHI / u.cm**2 for lline in HIlines._data: aline = AbsLine(lline['wrest'], linelist=HIlines) # Attributes aline.attrib['N'] = Nval aline.attrib['b'] = bval aline.attrib['z'] = self.zabs aline.analy['vlim'] = self.vlim aline.analy['do_analysis'] = do_analysis aline.attrib['coord'] = self.coord self.lls_lines.append(aline) # Generate a component (should remove any previous HI) self.add_component(AbsComponent.from_abslines(self.lls_lines))
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_init(): # Simple properties abscomp = AbsComponent((10.0 * u.deg, 45 * u.deg), (14, 2), 1.0, [-300, 300] * u.km / u.s) # Test assert abscomp.Zion[0] == 14 np.testing.assert_allclose(abscomp.zcomp, 1.0) print(abscomp)
def complist_from_igmgjson(igmguesses_json): """Creates a list of AbsComponenbts from a igmguesses_json file Parameters ---------- igmguesses_json : str Name of the json file genereted by IGMGUESSES Returns ------- comp_list : list of AbsComponents A list of AbsComponents """ return ltiio.read_igmg_to_components(igmguesses_json, linelist='ISM') # Read the JSON file with open(igmguesses_json) as data_file: igmg_dict = json.load(data_file) # Components comp_list = [] for ii, key in enumerate(igmg_dict['cmps'].keys()): comp_dict = igmg_dict['cmps'][key] comp_dict['flag_N'] = 1 comp_dict['logN'] = comp_dict['Nfit'] comp_dict['sig_logN'] = -1 # import pdb; pdb.set_trace() try: comp = AbsComponent.from_dict(comp_dict, chk_sep=False, chk_data=False, chk_vel=False, linelist="ISM") except: comp = AbsComponent.from_dict(comp_dict, chk_sep=False, chk_data=False, chk_vel=False, linelist='H2') # add extra attributes manually comp.attrib['b'] = comp_dict['bfit'] comp.attrib['sig_b'] = -1 comp.attrib['reliability'] = comp_dict['Reliability'] comp_list += [comp] return comp_list
def test_init_single_absline(): # Single AbsLine lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 abscomp = AbsComponent.from_abslines([lya]) # Test assert abscomp.Zion[0] == 1 np.testing.assert_allclose(abscomp.zcomp,2.92939)
def test_init_single_absline(): # Single AbsLine lya = AbsLine(1215.670*u.AA,z=2.92939) lya.limits.set([-300.,300.]*u.km/u.s) abscomp = AbsComponent.from_abslines([lya]) # Test assert abscomp.Zion[0] == 1 np.testing.assert_allclose(abscomp.zcomp,2.92939) print(abscomp)
def test_init_single_absline(): # Single AbsLine lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) abscomp = AbsComponent.from_abslines([lya]) # Test assert abscomp.Zion[0] == 1 np.testing.assert_allclose(abscomp.zcomp, 2.92939) print(abscomp)
def json_eqw(json_file, fits_file, outfile, overwrite=False): ion_name = [] restwave = [] col = [] col_err = [] flag = [] zcomp = [] if not os.path.isfile(json_file): return np.array(ion_name), np.array(restwave), np.array(col), \ np.array(col_err), np.array(flag), np.array(zcomp) if not os.path.isfile(outfile) or overwrite == True: out = open(outfile, 'w') out.write('#ion_name, restwave, logN, logN_err, flag_N, zcomp\n') with open(json_file) as data_file: igmg_dict = json.load(data_file) comp_list = [] for ii, key in enumerate(igmg_dict['cmps'].keys()): comp = AbsComponent.from_dict(igmg_dict['cmps'][key], chk_sep=False, chk_data=False, chk_vel=False) comp_list += [comp] spec = readspec(fits_file) for i, cc in enumerate(comp_list): for j, al in enumerate(cc._abslines): al.analy['spec'] = spec al.measure_ew() al.measure_aodm() ion_name.append(al.ion_name) restwave.append(al.wrest.value) col.append(al.attrib['logN']) sig_logN = al.attrib['sig_logN'] if np.isnan(sig_logN): sig_logN = 0.0 col_err.append(sig_logN) flag.append(al.attrib['flag_N']) zcomp.append(al.z) out.write('%s\t%f\t%e\t%e\t%d\t%0.6f\n'%(al.ion_name, al.wrest.value, \ al.attrib['logN'], sig_logN, al.attrib['flag_N'], al.z)) out.close() if os.path.isfile(outfile) and len(open(outfile).readlines()) > 1: ion_name = np.loadtxt(outfile, unpack=True, skiprows=1, usecols=0, dtype='str') restwave, col, col_err, flag, zcomp = \ np.loadtxt(outfile, unpack = True, skiprows = 1, usecols = (1, 2, 3, 4, 5)) return np.array(ion_name), np.array(restwave), np.array(col), np.array( col_err), np.array(flag), np.array(zcomp)
def lyman_comp(radec): # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lya.attrib['N'] = 1e17 / u.cm**2 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec return abscomp
def build_components_from_abslines(iabslines, clmdict=None, coord=None): """ Generate a list of AbsComponent from a list of abslines Groups lines with like Zion, Ej, (and A; future) Parameters ---------- abslines : list List of AbsLine objects May be ignored if clmdict is passed in clmdict : dict, optional If present, build the abslines list from this dict coord : SkyCoord, optional Required if clmdict is used Returns ------- components : list of AbsComponent objects """ if clmdict is None: abslines = iabslines else: abslines = [] vmin, vmax = 9999.0, -9999.0 for wrest in clmdict["lines"].keys(): vmin = min(vmin, clmdict["lines"][wrest].analy["vlim"][0].value) vmax = max(vmax, clmdict["lines"][wrest].analy["vlim"][1].value) clmdict["lines"][wrest].attrib["coord"] = coord abslines.append(clmdict["lines"][wrest]) # Test if not isinstance(abslines, list): raise IOError("Need a list of AbsLine objects") # Identify unique Zion, Ej combinations in the lines uZiE = np.array( [ iline.data["Z"] * 1000000 + iline.data["ion"] * 10000 + iline.data["Ej"].to("1/cm").value for iline in abslines ] ) uniZi, auidx = np.unique(uZiE, return_index=True) # Loop to build components components = [] for uidx in auidx: # Synthesize lines with like Zion, Ej mtZiE = np.where(uZiE == uZiE[uidx])[0] lines = [abslines[ii] for ii in mtZiE] # Need a list # Generate component components.append(AbsComponent.from_abslines(lines)) return components
def test_init_multi_absline(): # AbsLine(s) lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) lyb = AbsLine(1025.7222 * u.AA) lyb.setz(lya.z) lyb.limits.set([-300., 300.] * u.km / u.s) # Instantiate abscomp = AbsComponent.from_abslines([lya, lyb]) # Test assert len(abscomp._abslines) == 2 np.testing.assert_allclose(abscomp.zcomp, 2.92939)
def test_init_multi_absline(): # AbsLine(s) lya = AbsLine(1215.670*u.AA, z=2.92939) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.setz(lya.z) # Instantiate abscomp = AbsComponent.from_abslines([lya,lyb]) # Test assert len(abscomp._abslines) == 2 np.testing.assert_allclose(abscomp.zcomp,2.92939)
def test_init_failures(): with pytest.raises(IOError): AbsComponent.from_abslines('blah') with pytest.raises(IOError): AbsComponent.from_abslines(['blah']) with pytest.raises(IOError): AbsComponent.from_component('blah')
def test_copy(): # Single AbsLine lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) abscomp = AbsComponent.from_abslines([lya]) # Copy abscomp2 = abscomp.copy() # Checks attrs = vars(abscomp).keys() attrs2 = vars(abscomp2).keys() for attr in attrs: assert attr in attrs2 np.testing.assert_allclose(abscomp._abslines[0].z, abscomp2._abslines[0].z)
def test_build_table(): # AbsLine(s) lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] # Instantiate abscomp = AbsComponent.from_abslines([lya,lyb]) comp_tbl = abscomp.build_table() # Test assert isinstance(comp_tbl,QTable)
def test_init_failures(): with pytest.raises(IOError): AbsComponent.from_abslines('blah') with pytest.raises(IOError): AbsComponent.from_abslines(['blah']) with pytest.raises(IOError): AbsComponent.from_component('blah') with pytest.raises(IOError): AbsComponent((10.0 * u.deg, 45 * u.deg), (14, 2), 1.0, [-300, 300] * u.km / u.s, Ej=0.1 / u.cm) # need stars!
def lyman_comp(radec, z=2.92939): # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA, z=z) lya.limits.set([-300., 300.] * u.km / u.s) lya.attrib['flag_N'] = 1 lya.attrib['N'] = 1e17 / u.cm**2 lya.attrib['coord'] = radec lyb = AbsLine(1025.7222 * u.AA, z=z) lyb.limits.set([-300., 300.] * u.km / u.s) lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya, lyb]) abscomp.synthesize_colm() return abscomp
def lyman_comp(radec): # HI Lya, Lyb lya = AbsLine(1215.670*u.AA, z=2.92939) lya.limits.set([-300.,300.]*u.km/u.s) lya.attrib['flag_N'] = 1 lya.attrib['N'] = 1e17 / u.cm**2 lya.attrib['coord'] = radec lyb = AbsLine(1025.7222*u.AA, z=2.92939) lyb.limits.set([-300.,300.]*u.km/u.s) lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.synthesize_colm() return abscomp
def test_init_single_absline(): # Single AbsLine lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) lya.attrib['N'] = 1e12 / u.cm**2 lya.attrib['sig_N'] = [1e11] * 2 / u.cm**2 lya.attrib['flag_N'] = 1 abscomp = AbsComponent.from_abslines([lya]) # Test assert abscomp.Zion[0] == 1 assert len(abscomp.sig_N) == 2 assert np.isclose(abscomp.sig_logN[0], 0.04342945) assert isinstance(abscomp.sig_logN, np.ndarray) np.testing.assert_allclose(abscomp.zcomp, 2.92939)
def init_system(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA, z=2.92939) lya.limits.set([-300.,300.]*u.km/u.s) lya.attrib['coord'] = radec lyb = AbsLine(1025.7222*u.AA, z=lya.z) lyb.limits.set([-300.,300.]*u.km/u.s) lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya,lyb]) # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans, z=2.92939) iline.attrib['coord'] = radec iline.limits.set([-250.,80.]*u.km/u.s) abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) # Instantiate gensys = GenericAbsSystem.from_components([abscomp,SiII_comp]) return gensys
def test_copy(): # Single AbsLine lya = AbsLine(1215.670*u.AA, z=2.92939) lya.analy['vlim'] = [-300.,300.]*u.km/u.s abscomp = AbsComponent.from_abslines([lya]) # Copy abscomp2 = abscomp.copy() # Checks attrs = vars(abscomp).keys() attrs2 = vars(abscomp2).keys() for attr in attrs: assert attr in attrs2 np.testing.assert_allclose(abscomp._abslines[0].z, abscomp2._abslines[0].z)
def init_system(): radec = SkyCoord(ra=123.1143 * u.deg, dec=-12.4321 * u.deg) # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.limits.set([-300., 300.] * u.km / u.s) lya.attrib['coord'] = radec lyb = AbsLine(1025.7222 * u.AA, z=lya.z) lyb.limits.set([-300., 300.] * u.km / u.s) lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya, lyb]) # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans, z=2.92939) iline.attrib['coord'] = radec iline.limits.set([-250., 80.] * u.km / u.s) abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) # Instantiate gensys = GenericAbsSystem.from_components([abscomp, SiII_comp]) return gensys
def si2_comp(radec): # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans) iline.attrib['z'] = 2.92939 iline.analy['vlim'] = [-250.,80.]*u.km/u.s abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) SiII_comp.coord = radec # return SiII_comp
def test_init_failures(): with pytest.raises(IOError): AbsComponent.from_abslines('blah') with pytest.raises(IOError): AbsComponent.from_abslines(['blah']) with pytest.raises(IOError): AbsComponent.from_component('blah') with pytest.raises(IOError): AbsComponent((10.0*u.deg, 45*u.deg), (14,2), 1.0, [-300,300]*u.km/u.s, Ej=0.1/u.cm) # need stars!
def si2_comp(radec): # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans, z=2.92939) iline.attrib['coord'] = radec iline.limits.set([-250.,80.]*u.km/u.s) abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) SiII_comp.logN = 15. SiII_comp.flag_N = 1 # return SiII_comp
def oi_comp(radec, vlim=[-250.,80.]*u.km/u.s, z=2.92939): # SiII OItrans = ['OI 1302'] abslines = [] for trans in OItrans: iline = AbsLine(trans, z=z, linelist=ism) iline.attrib['coord'] = radec iline.limits.set(vlim) abslines.append(iline) # OI_comp = AbsComponent.from_abslines(abslines, skip_synth=True) OI_comp.logN = 15. OI_comp.flag_N = 1 # return OI_comp
def si2_comp(radec): # SiII SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans, z=2.92939) iline.attrib['coord'] = radec iline.limits.set([-250., 80.] * u.km / u.s) abslines.append(iline) # SiII_comp = AbsComponent.from_abslines(abslines) SiII_comp.logN = 15. SiII_comp.flag_N = 1 # return SiII_comp
def oi_comp(radec, vlim=[-250., 80.] * u.km / u.s, z=2.92939): # SiII OItrans = ['OI 1302'] abslines = [] for trans in OItrans: iline = AbsLine(trans, z=z, linelist=ism) iline.attrib['coord'] = radec iline.limits.set(vlim) abslines.append(iline) # OI_comp = AbsComponent.from_abslines(abslines, skip_synth=True) OI_comp.logN = 15. OI_comp.flag_N = 1 # return OI_comp
def build_components_from_dict(idict, coord=None, **kwargs): """ Generate a list of components from an input dict Parameters ---------- idict : dict Must contain either components or lines as a key coord : SkyCoord, optional Returns ------- components : list of AbsComponent objects Sorted by zcomp """ from linetools.spectralline import AbsLine components = [] if 'components' in idict.keys(): # Components for key in idict['components']: components.append( AbsComponent.from_dict(idict['components'][key], coord=coord, **kwargs)) elif 'lines' in idict.keys(): # to be deprecated lines = [] for key in idict['lines']: if isinstance(idict['lines'][key], AbsLine): line = idict['lines'][key] elif isinstance(idict['lines'][key], dict): line = AbsLine.from_dict(idict['lines'][key], coord=coord, **kwargs) else: raise IOError("Need those lines") if coord is not None: line.attrib['coord'] = coord lines.append(line) components = build_components_from_abslines(lines, **kwargs) else: warnings.warn("No components in this dict") # Sort by z -- Deals with dict keys being random z = [comp.zcomp for comp in components] isrt = np.argsort(np.array(z)) srt_comps = list(np.array(components)[isrt]) # Return return srt_comps
def test_rest_limits(): SiIItrans = ['SiII 1260', 'SiII 1304'] radec = SkyCoord(ra=1., dec=1., unit='deg') abslines = [] for kk, trans in enumerate(SiIItrans): iline = AbsLine(trans, z=1., linelist=ism) iline.attrib['coord'] = radec if kk == 0: iline.limits.set([-250., 80.] * u.km / u.s) else: iline.limits.set([-50., 180.] * u.km / u.s) abslines.append(iline) # comp = AbsComponent.from_abslines(abslines, chk_vel=False) comp.reset_limits_from_abslines() assert np.isclose(comp.vlim[1].value, 180.)
def test_rest_limits(): SiIItrans = ['SiII 1260', 'SiII 1304'] radec = SkyCoord(ra=1., dec=1., unit='deg') abslines = [] for kk,trans in enumerate(SiIItrans): iline = AbsLine(trans, z=1., linelist=ism) iline.attrib['coord'] = radec if kk == 0: iline.limits.set([-250.,80.]*u.km/u.s) else: iline.limits.set([-50.,180.]*u.km/u.s) abslines.append(iline) # comp = AbsComponent.from_abslines(abslines, chk_vel=False) comp.reset_limits_from_abslines() assert np.isclose(comp.vlim[1].value, 180.)
def build_components_from_dict(idict, coord=None, **kwargs): """ Generate a list of components from an input dict Parameters ---------- idict : dict Must contain either components or lines as a key coord : SkyCoord, optional Returns ------- components : list of AbsComponent objects Sorted by zcomp """ from linetools.spectralline import AbsLine components = [] if 'components' in idict.keys(): # Components for key in idict['components']: components.append(AbsComponent.from_dict(idict['components'][key], coord=coord, **kwargs)) elif 'lines' in idict.keys(): # to be deprecated lines = [] for key in idict['lines']: if isinstance(idict['lines'][key], AbsLine): line = idict['lines'][key] elif isinstance(idict['lines'][key], dict): line = AbsLine.from_dict(idict['lines'][key], coord=coord) else: raise IOError("Need those lines") if coord is not None: line.attrib['coord'] = coord lines.append(line) components = build_components_from_abslines(lines, **kwargs) else: warnings.warn("No components in this dict") # Sort by z -- Deals with dict keys being random z = [comp.zcomp for comp in components] isrt = np.argsort(np.array(z)) srt_comps = [] for idx in isrt: srt_comps.append(components[idx]) # Return return srt_comps
def test_synthesize_colm(): # Read a spectrum Spec xspec = lsio.readspec(lt_path+'/spectra/tests/files/UM184_nF.fits') # AbsLines SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans) iline.attrib['z'] = 2.92939 iline.analy['vlim'] = [-250.,80.]*u.km/u.s iline.analy['spec'] = xspec abslines.append(iline) # Component abscomp = AbsComponent.from_abslines(abslines) # Column abscomp.synthesize_colm(redo_aodm=True) # Test np.testing.assert_allclose(abscomp.logN,13.594447075294818)
def test_one_component(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # Instantiate HIsys = LymanAbsSystem.from_components([abscomp]) # Test assert HIsys.abs_type == 'HILyman' assert len(HIsys._components) == 1 assert HIsys._components[0].Zion[0] == 1 assert HIsys._components[0].Zion[1] == 1
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
def mk_comp(ctype, vlim=[-300., 300] * u.km / u.s, add_spec=False, use_rand=True, add_trans=False, zcomp=2.92939, b=20 * u.km / u.s, **kwargs): # Read a spectrum Spec if add_spec: spec_file = resource_filename('linetools', '/spectra/tests/files/UM184_nF.fits') xspec = lsio.readspec(spec_file) else: xspec = None # AbsLines if ctype == 'HI': all_trans = ['HI 1215', 'HI 1025'] elif ctype == 'SiII': all_trans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] if add_trans: all_trans += ['SiII 1193'] elif ctype == 'SiII*': all_trans = ['SiII* 1264', 'SiII* 1533'] elif ctype == 'SiIII': all_trans = ['SiIII 1206'] abslines = [] for trans in all_trans: iline = AbsLine(trans, z=zcomp, linelist=ism) if use_rand: rnd = np.random.rand() else: rnd = 0. iline.attrib['logN'] = 13.3 + rnd iline.attrib['sig_logN'] = 0.15 iline.attrib['flag_N'] = 1 iline.attrib['b'] = b iline.analy['spec'] = xspec iline.limits.set(vlim) _, _ = ltaa.linear_clm(iline.attrib) # Loads N, sig_N abslines.append(iline) # Component abscomp = AbsComponent.from_abslines(abslines, **kwargs) return abscomp, abslines
def test_one_component(): radec = SkyCoord(ra=123.1143 * u.deg, dec=-12.4321 * u.deg) # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA) lya.analy['vlim'] = [-300., 300.] * u.km / u.s lya.attrib['z'] = 2.92939 lya.attrib['N'] = 1e17 / u.cm**2 lyb = AbsLine(1025.7222 * u.AA) lyb.analy['vlim'] = [-300., 300.] * u.km / u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya, lyb]) abscomp.coord = radec # Instantiate HIsys = LymanAbsSystem.from_components([abscomp]) # Test assert HIsys.abs_type == 'HILyman' assert len(HIsys._components) == 1 assert HIsys._components[0].Zion[0] == 1 assert HIsys._components[0].Zion[1] == 1
def test_cog(): # Read a spectrum Spec xspec = lsio.readspec(lt_path+'/spectra/tests/files/UM184_nF.fits') # AbsLines SiIItrans = ['SiII 1260', 'SiII 1304', 'SiII 1526', 'SiII 1808'] abslines = [] for trans in SiIItrans: iline = AbsLine(trans) iline.attrib['z'] = 2.92939 iline.analy['vlim'] = [-250.,80.]*u.km/u.s iline.analy['spec'] = xspec abslines.append(iline) # Component abscomp = AbsComponent.from_abslines(abslines) # COG COG_dict = abscomp.cog(redo_EW=True) # Test np.testing.assert_allclose(COG_dict['logN'],13.693355878125537) np.testing.assert_allclose(COG_dict['sig_logN'],0.054323725737309987)
def test_init_failures(): with pytest.raises(IOError): AbsComponent.from_abslines('blah') with pytest.raises(IOError): AbsComponent.from_abslines(['blah']) with pytest.raises(IOError): AbsComponent.from_component('blah') # Inconsistent abslines with median lya = AbsLine(1215.670 * u.AA, z=2.92939) lya.attrib['N'] = 1e12 / u.cm**2 lya.attrib['sig_N'] = [1e11] * 2 / u.cm**2 lya.attrib['b'] = 30 * u.km / u.s lyb = AbsLine('HI 1025', z=2.92939) lyb.attrib['N'] = 3e12 / u.cm**2 lyb.attrib['sig_N'] = [3e11] * 2 / u.cm**2 lyb.attrib['b'] = 30 * u.km / u.s with pytest.raises(ValueError): AbsComponent.from_abslines([lya, lyb], adopt_median=True, chk_meas=True)
def test_todict(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['z'] = 2.92939 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # Instantiate HIsys = LymanAbsSystem.from_components([abscomp]) # Dict adict = HIsys.to_dict() assert isinstance(adict, dict) # Instantiate newsys = AbsSystem.from_dict(adict) assert isinstance(newsys, AbsSystem)
def from_igmguesses_to_complist(infile): """Reads .json file generated by IGMGuesses and return a list of AbsComponent objects Parameters ---------- infile : str Name of the .json file from IGMGuesses Returns: complist : list of AbsComponent """ import json # Read the JSON file with open(infile) as data_file: igmg_dict = json.load(data_file) # Components comp_list = [] for ii, key in enumerate(igmg_dict['cmps'].keys()): # QtCore.pyqtRemoveInputHook() # pdb.set_trace() # QtCore.pyqtRestoreInputHook() # import pdb; pdb.set_trace() idict = igmg_dict['cmps'][key] idict['logN'] = idict['attrib']['logN'] try: idict['flag_N'] = idict['attrib']['flag_N'] except: idict['flag_N'] = 0. try: idict['sig_logN'] = idict['attrib']['sig_logN'] except: idict['sig_logN'] = 0. comp = AbsComponent.from_dict(idict, skip_abslines=False, chk_sep=False, chk_data=False, chk_vel=False) comp_list += [comp] return comp_list
def test_todict(): radec = SkyCoord(ra=123.1143 * u.deg, dec=-12.4321 * u.deg) # HI Lya, Lyb lya = AbsLine(1215.670 * u.AA) lya.analy['vlim'] = [-300., 300.] * u.km / u.s lya.attrib['z'] = 2.92939 lya.attrib['coord'] = radec lyb = AbsLine(1025.7222 * u.AA) lyb.analy['vlim'] = [-300., 300.] * u.km / u.s lyb.attrib['z'] = lya.attrib['z'] lyb.attrib['coord'] = radec abscomp = AbsComponent.from_abslines([lya, lyb]) # Instantiate HIsys = LymanAbsSystem.from_components([abscomp]) # Dict adict = HIsys.to_dict() assert isinstance(adict, dict) # Instantiate #pdb.set_trace() newsys = AbsSystem.from_dict(adict) assert isinstance(newsys, AbsSystem)
def test_DLA_from_components(): radec = SkyCoord(ra=123.1143*u.deg, dec=-12.4321*u.deg) # HI Lya, Lyb lya = AbsLine(1215.670*u.AA, z=2.92939) lya.analy['vlim'] = [-300.,300.]*u.km/u.s lya.attrib['flag_N'] = 1 lya.attrib['N'] = 3e20 / u.cm**2 lya.attrib['sig_N'] = [1]*2 / u.cm**2 lyb = AbsLine(1025.7222*u.AA, z=lya.z) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['N'] = 3e20 / u.cm**2 lyb.attrib['flag_N'] = 1 lyb.attrib['sig_N'] = [1]*2 / u.cm**2 abscomp = AbsComponent.from_abslines([lya,lyb]) abscomp.coord = radec # Instantiate HIsys = DLASystem.from_components([abscomp]) # Test np.testing.assert_allclose(HIsys.NHI, 20.477121254719663) assert len(HIsys._components) == 1 assert HIsys._components[0].Zion[0] == 1 assert HIsys._components[0].Zion[1] == 1
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