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_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_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_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_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_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_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 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 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 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 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 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 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 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 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_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_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 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 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 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 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 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 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 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 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 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 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_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 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_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_DLA_from_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 lya.attrib['N'] = 3e20 / u.cm**2 lyb = AbsLine(1025.7222*u.AA) lyb.analy['vlim'] = [-300.,300.]*u.km/u.s lyb.attrib['z'] = lya.attrib['z'] lyb.attrib['N'] = 3e20 / 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 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.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) # 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 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 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)
# Calculate the EW of 1st sodium line S1 = AbsLine(transitions['wrest'][0] * u.AA, z=float(data['z'])) S1.analy['spec'] = XSpectrum1D.from_file('n_' + name[42:-5] + '.fits') S1.analy['vlim'] = [-150., 150.] * u.km / u.s S1.attrib['coord'] = radec x = float(input("Enter a lower lim: ")) y = float(input("Enter a higher lim: ")) S1.limits.set([x, y] * u.AA) S1.measure_aodm() S1.measure_ew() # Observer frame S1.measure_kin() N, sigN, flgN = [S1.attrib[key] for key in ['N', 'sig_N', 'flag_N']] print(S1.attrib) abscomp = AbsComponent.from_abslines([S1]) abscomp.stack_plot() # Calculate the EW of 2nd sodium line S2 = AbsLine(transitions['wrest'][1] * u.AA, z=float(data['z'])) S2.attrib['coord'] = radec S2.analy['vlim'] = [-150., 150.] * u.km / u.s S2.analy['spec'] = XSpectrum1D.from_file('n_' + name[42:-5] + '.fits') x = float(input("Enter a lower lim: ")) y = float(input("Enter a higher lim: ")) S2.limits.set([x, y] * u.AA) S2.measure_ew() # Observer frame N, sigN, flgN = [S2.attrib[key] for key in ['N', 'sig_N', 'flag_N']] print('DONE') #adict = specline.to_dict()
def build_components_from_abslines(iabslines, clmdict=None, coord=None, **kwargs): """ 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: raise DeprecationWarning("Gone") abslines = [] # 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 if lines[0].data['Ej'].value > 0.: # Grab stars from transition name nstars = lines[0].name.count('*') if nstars == 0: raise ValueError("Should have at least one *") stars = '*'*nstars else: stars = None component = AbsComponent.from_abslines(lines, stars=stars, **kwargs) # Reset vmin, vmax vmin,vmax = 9999., -9999. for iline in lines: vmin = min(vmin, iline.analy['vlim'][0].value) vmax = max(vmax, iline.analy['vlim'][1].value) component.vlim = [vmin,vmax]*u.km/u.s # Append components.append(component) # Return return components
def load_single_fits(self, inp, skip_ions=False, verbose=True, **kwargs): """ Load a single COS-Halos sightline Appends to cgm_abs list Parameters ---------- inp : tuple or str if tuple -- (field,gal_id) field: str Name of field (e.g. 'J0226+0015') gal_id: str Name of galaxy (e.g. '268_22') skip_ions : bool, optional Avoid loading the ions (not recommended) verbose : bool, optional """ # Parse input if isinstance(inp, basestring): fil = inp elif isinstance(inp, tuple): field, gal_id = inp tmp = self.fits_path + '/' + field + '.' + gal_id + '.fits.gz' fils = glob.glob(tmp) if len(fils) != 1: raise IOError('Bad field, gal_id: {:s}'.format(tmp)) fil = fils[0] else: raise IOError('Bad input to load_single') # Read COS-Halos file if verbose: print('cos_halos: Reading {:s}'.format(fil)) hdu = fits.open(fil) summ = Table(hdu[1].data) galx = Table(hdu[2].data) # Instantiate the galaxy gal = Galaxy((galx['RA'][0], galx['DEC'][0]), z=summ['ZFINAL'][0]) gal.field = galx['FIELD'][0] gal.gal_id = galx['GALID'][0] # Galaxy properties gal.halo_mass = summ['LOGMHALO'][0] gal.stellar_mass = summ['LOGMFINAL'][0] gal.rvir = galx['RVIR'][0] gal.MH = galx['ABUN'][0] gal.flag_MH = galx['ABUN_FLAG'][0] gal.sdss_phot = [ galx[key][0] for key in ['SDSSU', 'SDSSG', 'SDSSR', 'SDSSI', 'SDSSZ'] ] gal.sdss_phot_sig = [ galx[key][0] for key in ['SDSSU_ERR', 'SDSSG_ERR', 'SDSSR_ERR', 'SDSSI_ERR', 'SDSSZ_ERR'] ] gal.sfr = (galx['SFR_UPLIM'][0], galx['SFR'][0], galx['SFR_FLAG'][0] ) # FLAG actually gives method used gal.ssfr = galx['SSFR'][0] # Instantiate the IGM System igm_sys = IGMSystem((galx['QSORA'][0], galx['QSODEC'][0]), summ['ZFINAL'][0], [-600, 600.] * u.km / u.s, abs_type='CGM') igm_sys.zqso = galx['ZQSO'][0] # Instantiate cgabs = CGMAbsSys(gal, igm_sys, name=gal.field + '_' + gal.gal_id, **kwargs) # EBV cgabs.ebv = galx['EBV'][0] # Ions if skip_ions is True: # NHI dat_tab = Table(hdu[3].data) #if dat_tab['Z'] != 1: # raise ValueError("Uh oh") cgabs.igm_sys.NHI = dat_tab['CLM'][0] cgabs.igm_sys.sig_NHI = dat_tab['SIG_CLM'][0] cgabs.igm_sys.flag_NHI = dat_tab['FLG_CLM'][0] self.cgm_abs.append(cgabs) return all_Z = [] all_ion = [] for jj in range(summ['NION'][0]): iont = hdu[3 + jj].data if jj == 0: # Generate new Table dat_tab = Table(iont) else: try: dat_tab.add_row(Table(iont)[0]) except: pdb.set_trace() all_Z.append(iont['ZION'][0][0]) all_ion.append(iont['ZION'][0][1]) # AbsLines abslines = [] ntrans = len(np.where(iont['LAMBDA'][0] > 1.)[0]) for kk in range(ntrans): flg = iont['FLG'][0][kk] # Fill in aline = AbsLine(iont['LAMBDA'][0][kk] * u.AA, closest=True) aline.attrib['flag_origCH'] = int(flg) aline.attrib[ 'EW'] = iont['WOBS'][0][kk] * u.AA / 1e3 # Observed aline.attrib['sig_EW'] = iont['SIGWOBS'][0][kk] * u.AA / 1e3 if aline.attrib['EW'] > 3. * aline.attrib['sig_EW']: aline.attrib['flag_EW'] = 1 else: aline.attrib['flag_EW'] = 3 # Force an upper limit (i.e. from a blend) if (flg == 2) or (flg == 4) or (flg == 6): aline.attrib['flag_EW'] = 3 # aline.analy['vlim'] = [ iont['VMIN'][0][kk], iont['VMAX'][0][kk] ] * u.km / u.s aline.attrib['z'] = igm_sys.zabs aline.attrib['coord'] = igm_sys.coord # Check f if (np.abs(aline.data['f'] - iont['FVAL'][0][kk]) / aline.data['f']) > 0.001: Nscl = iont['FVAL'][0][kk] / aline.data['f'] flag_f = True else: Nscl = 1. flag_f = False # Colm if ((flg % 2) == 0) or (flg == 15) or (flg == 13): flgN = 0 print( 'Skipping column contribution from {:g} as NG for a line; flg={:d}' .format(iont['LAMBDA'][0][kk], flg)) elif (flg == 1) or (flg == 3): flgN = 1 elif (flg == 5) or (flg == 7): flgN = 3 elif (flg == 9) or (flg == 11): flgN = 2 else: pdb.set_trace() raise ValueError("Bad flag!") if flgN == 3: aline.attrib['logN'] = iont['LOGN2SIG'][0][kk] + np.log10( Nscl) aline.attrib['sig_logN'] = 9. elif flgN == 0: # Not for N measurement pass else: aline.attrib['logN'] = iont['LOGN'][0][kk] + np.log10(Nscl) aline.attrib['sig_logN'] = iont['SIGLOGN'][0][kk] aline.attrib['flag_N'] = int(flgN) #pdb.set_trace() if flgN != 0: _, _ = ltaa.linear_clm(aline.attrib) # Append abslines.append(aline) # Component if len(abslines) == 0: comp = AbsComponent(cgabs.igm_sys.coord, (iont['ZION'][0][0], iont['ZION'][0][1]), igm_sys.zabs, igm_sys.vlim) else: comp = AbsComponent.from_abslines(abslines, chk_vel=False) if comp.Zion != (1, 1): comp.synthesize_colm() # Combine the abs lines if np.abs(comp.logN - float(iont['CLM'][0])) > 0.15: print( "New colm for ({:d},{:d}) and sys {:s} is {:g} different from old" .format(comp.Zion[0], comp.Zion[1], cgabs.name, comp.logN - float(iont['CLM'][0]))) if comp.flag_N != iont['FLG_CLM'][0]: if comp.flag_N == 0: pass else: print( "New flag for ({:d},{:d}) and sys {:s} is different from old" .format(comp.Zion[0], comp.Zion[1], cgabs.name)) pdb.set_trace() #_,_ = ltaa.linear_clm(comp) cgabs.igm_sys.add_component(comp) self.cgm_abs.append(cgabs) # Add Z,ion dat_tab.add_column(Column(all_Z, name='Z')) dat_tab.add_column(Column(all_ion, name='ion')) # Rename dat_tab.rename_column('LOGN', 'indiv_logN') dat_tab.rename_column('SIGLOGN', 'indiv_sig_logN') dat_tab.rename_column('CLM', 'logN') dat_tab.rename_column('SIG_CLM', 'sig_logN') dat_tab.rename_column('FLG_CLM', 'flag_N') # Set self.cgm_abs[-1].igm_sys._ionN = dat_tab # NHI HI = (dat_tab['Z'] == 1) & (dat_tab['ion'] == 1) if np.sum(HI) > 0: self.cgm_abs[-1].igm_sys.NHI = dat_tab[HI]['logN'][0] self.cgm_abs[-1].igm_sys.sig_NHI = dat_tab[HI]['sig_logN'][0] self.cgm_abs[-1].igm_sys.flag_NHI = dat_tab[HI]['flag_N'][0] else: warnings.warn("No HI measurement for {}".format(self.cgm_abs[-1])) self.cgm_abs[-1].igm_sys.flag_NHI = 0
def load_data(self, **kwargs): # q6file = self.data_file if self.from_dict: qpq6dict = CGMAbsSurvey.from_json(q6file) ism = LineList('ISM') qpq6dict.build_systems_from_dict(llist=ism) self.survey_data = qpq6dict #self.cgm_abs = qpq6dict.cgm_abs else: qpqdata = Table.read(q6file) if self.nmax is not None: nmax = self.nmax else: nmax = len(qpqdata) for i in range(nmax): # Instantiate the galaxy gal = Galaxy((qpqdata['RAD'][i], qpqdata['DECD'][i]), z=qpqdata['Z_FG'][i]) gal.L_BOL = qpqdata['L_BOL'][i] gal.L_912 = qpqdata['L_912'][i] gal.G_UV = qpqdata['G_UV'][i] gal.flg_BOSS = qpqdata['FLG_BOSS'][i] gal.zsig = qpqdata['Z_FSIG'][i] * u.km / u.s # Instantiate the IGM System igm_sys = IGMSystem( (qpqdata['RAD_BG'][i], qpqdata['DECD_BG'][i]), qpqdata['Z_FG'][i], [-5500, 5500.] * u.km / u.s, abs_type='CGM' ) ## if velocity range lower - does not load all abslines igm_sys.zem = qpqdata['Z_BG'][i] igm_sys.NHI = qpqdata['NHI'][i] igm_sys.sig_NHI = qpqdata['SIG_NHI'][i] igm_sys.flag_NHI = qpqdata['FLG_NHI'][i] igm_sys.s2n_lya = qpqdata['S2N_LYA'][i] igm_sys.flg_othick = qpqdata['FLG_OTHICK'][i] igm_sys.z_lya = qpqdata['Z_LYA'][i] iname = qpqdata['QSO'][i] # Instantiate rho = qpqdata['R_PHYS'][i] * u.kpc cgabs = CGMAbsSys(gal, igm_sys, name=iname, rho=rho, **kwargs) aline = AbsLine(1215.67 * u.AA, closest=True, z=igm_sys.zabs) aline.attrib['EW'] = qpqdata['EWLYA'][i] * u.AA # Rest EW aline.attrib['sig_EW'] = qpqdata['SIG_EWLYA'][i] * u.AA if aline.attrib['EW'] > 3. * aline.attrib['sig_EW']: aline.attrib['flag_EW'] = 1 else: aline.attrib['flag_EW'] = 3 aline.attrib['coord'] = igm_sys.coord aline.limits._wvlim = qpqdata['WVMNX'][i] * u.AA dv = ltu.rel_vel(aline.limits._wvlim, aline.wrest * (1 + qpqdata['Z_FG'][i])) aline.limits._vlim = dv abslines = [] abslines.append(aline) ### comp = AbsComponent.from_abslines(abslines, chk_vel=False) # add ang_sep qsocoord = SkyCoord(ra=qpqdata['RAD'][i], dec=qpqdata['DECD'][i], unit='deg') bgcoord = SkyCoord(ra=qpqdata['RAD_BG'][i], dec=qpqdata['DECD_BG'][i], unit='deg') cgabs.ang_sep = qsocoord.separation(bgcoord).to('arcsec') cgabs.igm_sys.add_component(comp) self.cgm_abs.append(cgabs)
def load_data(self, **kwargs): # if self.from_dict: q5file = self.data_file qpq5dict = CGMAbsSurvey.from_json(q5file) ism = LineList('ISM') qpq5dict.build_systems_from_dict(llist=ism) self.survey_data = qpq5dict #self.cgm_abs = qpq5dict.cgm_abs else: qpqdata = load_qpq(5) nmax = len(qpqdata) # max number of QSOs for i in range(nmax): # Instantiate the galaxy gal = Galaxy((qpqdata['RAD'][i], qpqdata['DECD'][i]), z=qpqdata['Z_FG'][i]) gal.L_BOL = qpqdata['L_BOL'][i] gal.L_912 = qpqdata['L_912'][i] gal.G_UV = qpqdata['G_UV'][i] gal.flg_BOSS = qpqdata['FLG_BOSS'][i] gal.zsig = qpqdata['Z_FSIG'][i] * u.km / u.s # Instantiate the IGM System igm_sys = IGMSystem( (qpqdata['RAD_BG'][i], qpqdata['DECD_BG'][i]), qpqdata['Z_FG'][i], [-5500, 5500.] * u.km / u.s, abs_type='CGM') igm_sys.zem = qpqdata['Z_BG'][i] igm_sys.NHI = qpqdata['NHI'][i] igm_sys.sig_NHI = qpqdata['SIG_NHI'][i] igm_sys.flag_NHI = qpqdata['FLG_NHI'][i] igm_sys.s2n_lya = qpqdata['S2N_LYA'][i] igm_sys.flg_othick = qpqdata['FLG_OTHICK'][i] igm_sys.z_lya = qpqdata['Z_LYA'][i] iname = qpqdata['QSO'][i] # Instantiate rho = qpqdata['R_PHYS'][i] * u.kpc cgabs = CGMAbsSys(gal, igm_sys, name=iname, rho=rho, **kwargs) aline = AbsLine(1215.67 * u.AA, closest=True, z=igm_sys.zabs, linelist=ism) aline.attrib['EW'] = qpqdata['EWLYA'][i] * u.AA # Rest EW aline.attrib['sig_EW'] = qpqdata['SIG_EWLYA'][i] * u.AA if aline.attrib['EW'] > 3. * aline.attrib['sig_EW']: aline.attrib['flag_EW'] = 1 else: aline.attrib['flag_EW'] = 3 aline.attrib['coord'] = igm_sys.coord #aline.limits._wvlim = qpqdata['WVMNX'][i]*u.AA ## (no data in QPQ7 file) #dv = ltu.rel_vel(aline.limits._wvlim, aline.wrest * (1 + qpqdata['Z_FG'][i])) #aline.limits._vlim = dv abslines = [] abslines.append(aline) comp = AbsComponent.from_abslines(abslines, chk_vel=False) cgabs.igm_sys.add_component(comp) # add metal lines for j in range(100): if qpqdata[i]['FLG_METAL_EW'][j] > 0: wave0 = qpqdata[i]['METAL_WREST'][j] iline = AbsLine(wave0 * u.AA, closest=True, z=igm_sys.zabs, linelist=ism) iline.attrib[ 'EW'] = qpqdata['METAL_EW'][i][j] * u.AA # Rest EW iline.attrib[ 'sig_EW'] = qpqdata['METAL_SIGEW'][i][j] * u.AA iline.attrib['flag_EW'] = qpqdata['FLG_METAL_EW'][i][j] iline.analy['flg_eye'] = qpqdata['FLG_METAL_EYE'][i][j] iline.attrib['coord'] = igm_sys.coord abslines = [] abslines.append(iline) comp = AbsComponent.from_abslines(abslines, chk_vel=False) cgabs.igm_sys.add_component(comp) # add ang_sep qsocoord = SkyCoord(ra=qpqdata['RAD'][i], dec=qpqdata['DECD'][i], unit='deg') bgcoord = SkyCoord(ra=qpqdata['RAD_BG'][i], dec=qpqdata['DECD_BG'][i], unit='deg') cgabs.ang_sep = qsocoord.separation(bgcoord).to('arcsec') self.cgm_abs.append(cgabs)
def build_components_from_abslines(iabslines, clmdict=None, coord=None, **kwargs): """ 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: raise DeprecationWarning("Gone") abslines = [] # 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 if lines[0].data['Ej'].value > 0.: # Grab stars from transition name nstars = lines[0].name.count('*') if nstars == 0: raise ValueError("Should have at least one *") stars = '*'*nstars else: stars = None component = AbsComponent.from_abslines(lines, stars=stars, **kwargs) # Reset vmin, vmax vmin,vmax = 9999., -9999. for iline in lines: vmin = min(vmin, iline.limits.vlim[0].value) vmax = max(vmax, iline.limits.vlim[1].value) component.limits.set([vmin,vmax]*u.km/u.s) # Append components.append(component) # Return return components
def load_data(self, **kwargs): # #q8file = resource_filename('pyigm', 'data/CGM/QPQ/qpq8_all_measured.dat') q8file = self.data_file if self.from_dict: q8file = self.data_file qpq8dict = CGMAbsSurvey.from_json(q8file) ism = LineList('ISM') qpq8dict.build_systems_from_dict(llist=ism) self.survey_data = qpq8dict #self.cgm_abs = qpq8dict.cgm_abs else: qpqdata = Table.read(q8file, format='ascii') #nmax = len(qpqdata) # max number of QSOs q8filecoord = resource_filename('pyigm', 'data/CGM/QPQ/qpq8_pairs.fits') qpqdatacoord = Table.read(q8filecoord) if self.nmax is not None: nmax = self.nmax else: nmax = len(qpqdatacoord) #(qpqdata) # match names with qpqdatacoord qnames = [] for i in range(len(qpqdatacoord)): qname = qpqdatacoord['QSO'][i].strip() qnames.append(qname[-10:]) qnames2 = [] for i in range(len(qpqdata)): qname = qpqdata['Pair'][i] qnames2.append(qname) for j in range(nmax): # i,j # match names with qpqdatacoord i = np.where(np.asarray(qnames2) == qnames[j])[0] # Instantiate the galaxy gal = Galaxy((qpqdatacoord['RAD'][j], qpqdatacoord['DECD'][j]), z=qpqdatacoord['Z_FG'][j]) gal.L_BOL = qpqdatacoord['L_BOL'][j] gal.L_912 = qpqdatacoord['L_912'][j] gal.G_UV = qpqdatacoord['G_UV'][j] gal.zsig = qpqdatacoord['Z_FSIG'][j] * u.km / u.s # Instantiate the IGM System igm_sys = IGMSystem( (qpqdatacoord['RAD_BG'][j], qpqdatacoord['DECD_BG'][j]), qpqdatacoord['Z_FG'][j], [-5500, 5500.] * u.km / u.s, abs_type='CGM') # Redshifts: QSO emission redshifts igm_sys.zem = qpqdatacoord['Z_BG'][j] igm_sys.NHI = qpqdata['HIcol'][i] igm_sys.sig_NHI = [ qpqdata['HIcolhierr'][i], qpqdata['HIcolloerr'][i] ] igm_sys.s2n_lya = qpqdatacoord['S2N_LYA'][j] iname = qpqdata['Pair'][i][0] #+'_'+qpqdata['subsys'][i] # Instantiate rho = qpqdatacoord['R_PHYS'][j] * u.kpc cgabs = CGMAbsSys(gal, igm_sys, name=iname, rho=rho, **kwargs) ### add metal lines ### not included CII*, SiII* lines = [ ['CII 1334'], ## ['CII* 1335'], ['CIV 1548', 'CIV 1550'], ['NI 1134', 'NI 1199'], ['NII 1083'], ['NV 1238', 'NV 1242'], ['OI 1302'], ['OVI 1037'], ['MgI 2852'], ['MgII 2796', 'MgII 2803'], ['AlII 1670'], ['AlIII 1854', 'AlIII 1862'], [ 'SiII 1190', 'SiII 1193', 'SiII 1304', 'SiII 1260', 'SiII 1526', 'SiII 1808' ], ## ['SiII* 1264'], ['SiIII 1206'], ['SiIV 1393', 'SiIV 1402'], [ 'FeII 1608', 'FeII 2344', 'FeII 2374', 'FeII 2382', 'FeII 2586', 'FeII 2600' ], ['FeIII 1122'] ] for kk in i: for icmp in range(len(lines)): abslines = [] for ii in range(len(lines[icmp])): wave0 = float(lines[icmp][ii].split(' ')[1]) ewstr = str(lines[icmp][ii].split(' ')[1]) + 'EW' ewerrstr = str( lines[icmp][ii].split(' ')[1]) + 'EWerr' if ewstr == '1808EW': ewstr = '1808E' if ewerrstr == '1122EWerr': ewerrstr = '122EWerr' if qpqdata[ewstr][kk] != '/': # find z v0 = 0.5 * ( qpqdata['v_lobound'][kk] + qpqdata['v_upbound'][kk]) * u.km / u.s dv = v0 zref = igm_sys.zabs z_cmp = ltu.z_from_dv(dv, zref) ## vlim v1 = qpqdata['v_lobound'][kk] * u.km / u.s z1 = ltu.z_from_dv(v1, zref) v1_cmp = ltu.dv_from_z(z1, z_cmp) v2 = qpqdata['v_upbound'][kk] * u.km / u.s z2 = ltu.z_from_dv(v2, zref) v2_cmp = ltu.dv_from_z(z2, z_cmp) # iline iline = AbsLine(wave0 * u.AA, closest=True, z=z_cmp) iline.attrib['coord'] = igm_sys.coord ## EW iline.attrib['EW'] = float( qpqdata[ewstr][kk]) * u.AA # Rest EW iline.attrib['sig_EW'] = float( qpqdata[ewerrstr][kk]) * u.AA flgew = 1 if iline.attrib[ 'EW'] < 3. * iline.attrib['sig_EW']: flgew = 3 iline.attrib['flag_EW'] = flgew ## column densities colstr = str( lines[icmp][ii].split(' ')[0]) + 'col' colerrstr = str( lines[icmp][ii].split(' ')[0]) + 'colerr' iline.attrib['logN'] = qpqdata[colstr][kk] iline.attrib['sig_logN'] = qpqdata[colerrstr][ kk] abslines.append(iline) if len(abslines) > 0: comp = AbsComponent.from_abslines(abslines, chk_vel=False) comp.limits._vlim = [v1_cmp.value, v2_cmp.value ] * u.km / u.s cgabs.igm_sys.add_component(comp) # add ang_sep qsocoord = SkyCoord(ra=qpqdatacoord['RAD'][j], dec=qpqdatacoord['DECD'][j], unit='deg') bgcoord = SkyCoord(ra=qpqdatacoord['RAD_BG'][j], dec=qpqdatacoord['DECD_BG'][j], unit='deg') cgabs.ang_sep = qsocoord.separation(bgcoord).to('arcsec') self.cgm_abs.append(cgabs)
def load_hotgas(self): """ Load data on hot gas (e.g. OVII, OVIII) Fang+15 """ from linetools.lists.linelist import LineList from linetools.analysis.absline import linear_clm llist = LineList('EUV',use_ISM_table=False) ovii = AbsLine('OVII 21', linelist=llist) # Fang+15 Table 1 [OVII] self.fang15 = Table.read(pyigm.__path__[0]+'/data/CGM/Galaxy/fang15_table1.dat', 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['flag_N'] = 0 # Might be able to set an upper limit aline.attrib['EW'] = row['EW1'] / 1e3 * u.AA aline.attrib['sig_EW'] = 99. * u.AA 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]) comp.synthesize_colm() # Instantiate abssys = IGMSystem(gc, z, vlim, name=row['Name']+'_z0', zem=row['z']) abssys.add_component(comp, chk_sep=False) # CGM Abs cgmabs = CGMAbsSys(self.galaxy, abssys, Galactic=True) # 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') self.savage03 = Table.read(pyigm.__path__[0] + '/data/CGM/Galaxy/savage03_table2.fits') # 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='fk5') 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.flag_N = 1 comp.logN = row['logN_OVI_'] comp.sig_logN = np.sqrt(row['e_sc']**2 + row['e_sys']**2) else: # Upper limit comp.flag_N = 3 comp.logN = row['logN_OVI_'] comp.sig_logN = 99. # 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) 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 cgmabs = CGMAbsSys(self.galaxy, abssys, Galactic=True) # Add to cgm_abs self.abs.cgm_abs.append(cgmabs)
def read_joebvp_to_components(filename, coord, llist=None, specfile=None, chk_vel=False): """ Generate a list of AbsComponent objects from a JoeB VP output file Parameters ---------- filename : str joeB VP filename coord : SkyCoord QSO sightline llist : LineList, optional Used to construct AbsLine objects specfile : str, optional chk_vel : bool, optional Demand that the velocities of a given ion all be the same Returns ------- comps : list list of AbsComponent objects """ # init if llist is None: llist = LineList('ISM') comps = [] # Read vp_data = Table.read(filename, format='ascii') # Subset by zsys + trans lbls = [] for izsys, itrans in zip(vp_data['zsys'], vp_data['trans']): lbls.append('{:.6f}_{:s}'.format(izsys, itrans)) lbls = np.array(lbls) ulbls = np.unique(lbls) # Subset by nflag; Build components for lbl in ulbls: mt_lines = np.where(lbls == lbl)[0] if chk_vel: if len(np.unique(vp_data['vel'][mt_lines])) != 1: pdb.set_trace() z_fit = ltu.z_from_dv(vp_data['vel'][mt_lines[0]] * u.km / u.s, vp_data['zsys'][mt_lines[0]]) # Loop on abs lines alines = [] for idx in mt_lines: zlim = [ vp_data['zsys'][idx] + vp_data[vkey][idx] * (1 + vp_data['zsys'][idx]) / ckms for vkey in ['vlim1', 'vlim2'] ] absline = AbsLine(vp_data['restwave'][idx] * u.AA, z=z_fit, zlim=zlim, linelist=llist) # Add measurements [JB -- Want to capture anything else??] absline.attrib['coord'] = coord absline.attrib['flag_N'] = 1 absline.attrib['logN'] = vp_data['col'][idx] absline.attrib['sig_logN'] = vp_data['sigcol'][idx] absline.attrib['b'] = vp_data['bval'][idx] absline.attrib['sig_b'] = vp_data['sigbval'][idx] absline.attrib['z'] = z_fit absline.attrib['sig_z'] = ltu.dz_from_dv( vp_data['sigvel'][idx] * u.km / u.s, vp_data['z_comp'][idx]) if specfile is None: absline.attrib['specfile'] = vp_data['specfile'][idx] else: absline.attrib['specfile'] = specfile # Fill N, sig_N _, _, = linear_clm(absline.attrib) alines.append(absline) # AbsComponent stars = '*' * alines[0].ion_name.count('*') if 'comment' in vp_data.keys(): comment = vp_data['comment'][mt_lines[0]] else: comment = '' if 'rely' in vp_data.keys(): reliability = vp_data['rely'][mt_lines[0]] else: reliability = 'none' abscomp = AbsComponent.from_abslines(alines, stars=stars, comment=comment, reliability=reliability) # Add measurements [JB -- Want to capture anything else??] abscomp.attrib = alines[0].attrib.copy() # Remove undesired keys for key in ['EW', 'sig_EW', 'flag_EW', 'N', 'sig_N']: abscomp.attrib.pop(key) # And more required for key in ['flag_N', 'logN', 'sig_logN']: setattr(abscomp, key, abscomp.attrib[key]) # Errors must be in first line! assert abscomp.sig_logN > 0. comps.append(abscomp) # Finish return comps
def load_single_fits(self, inp, skip_ions=False, verbose=True, **kwargs): """ Load a single COS-Halos sightline Appends to cgm_abs list Parameters ---------- inp : tuple or str if tuple -- (field,gal_id) field: str Name of field (e.g. 'J0226+0015') gal_id: str Name of galaxy (e.g. '268_22') skip_ions : bool, optional Avoid loading the ions (not recommended) verbose : bool, optional """ # Parse input if isinstance(inp, basestring): fil = inp elif isinstance(inp, tuple): field, gal_id = inp tmp = self.fits_path+'/'+field+'.'+gal_id+'.fits.gz' fils = glob.glob(tmp) if len(fils) != 1: raise IOError('Bad field, gal_id: {:s}'.format(tmp)) fil = fils[0] else: raise IOError('Bad input to load_single') # Read COS-Halos file if verbose: print('cos_halos: Reading {:s}'.format(fil)) hdu = fits.open(fil) summ = Table(hdu[1].data) galx = Table(hdu[2].data) # Instantiate the galaxy gal = Galaxy((galx['RA'][0], galx['DEC'][0]), z=summ['ZFINAL'][0]) gal.field = galx['FIELD'][0] gal.gal_id = galx['GALID'][0] # Galaxy properties gal.halo_mass = summ['LOGMHALO'][0] gal.stellar_mass = summ['LOGMFINAL'][0] gal.rvir = galx['RVIR'][0] gal.MH = galx['ABUN'][0] gal.flag_MH = galx['ABUN_FLAG'][0] gal.sdss_phot = [galx[key][0] for key in ['SDSSU','SDSSG','SDSSR','SDSSI','SDSSZ']] gal.sdss_phot_sig = [galx[key][0] for key in ['SDSSU_ERR','SDSSG_ERR','SDSSR_ERR','SDSSI_ERR','SDSSZ_ERR']] gal.sfr = (galx['SFR_UPLIM'][0], galx['SFR'][0], galx['SFR_FLAG'][0]) # FLAG actually gives method used gal.ssfr = galx['SSFR'][0] # Instantiate the IGM System igm_sys = IGMSystem((galx['QSORA'][0], galx['QSODEC'][0]), summ['ZFINAL'][0], [-600, 600.]*u.km/u.s, abs_type='CGM') igm_sys.zqso = galx['ZQSO'][0] # Instantiate cgabs = CGMAbsSys(gal, igm_sys, name=gal.field+'_'+gal.gal_id, **kwargs) # EBV cgabs.ebv = galx['EBV'][0] # Ions if skip_ions is True: # NHI dat_tab = Table(hdu[3].data) #if dat_tab['Z'] != 1: # raise ValueError("Uh oh") cgabs.igm_sys.NHI = dat_tab['CLM'][0] cgabs.igm_sys.sig_NHI = dat_tab['SIG_CLM'][0] cgabs.igm_sys.flag_NHI = dat_tab['FLG_CLM'][0] self.cgm_abs.append(cgabs) return all_Z = [] all_ion = [] for jj in range(summ['NION'][0]): iont = hdu[3+jj].data if jj == 0: # Generate new Table dat_tab = Table(iont) else: try: dat_tab.add_row(Table(iont)[0]) except: pdb.set_trace() all_Z.append(iont['ZION'][0][0]) all_ion.append(iont['ZION'][0][1]) # AbsLines abslines = [] ntrans = len(np.where(iont['LAMBDA'][0] > 1.)[0]) for kk in range(ntrans): flg = iont['FLG'][0][kk] # Fill in aline = AbsLine(iont['LAMBDA'][0][kk]*u.AA, closest=True) aline.attrib['flag_origCH'] = int(flg) aline.attrib['EW'] = iont['WOBS'][0][kk]*u.AA/1e3 # Observed aline.attrib['sig_EW'] = iont['SIGWOBS'][0][kk]*u.AA/1e3 if aline.attrib['EW'] > 3.*aline.attrib['sig_EW']: aline.attrib['flag_EW'] = 1 else: aline.attrib['flag_EW'] = 3 # Force an upper limit (i.e. from a blend) if (flg == 2) or (flg == 4) or (flg == 6): aline.attrib['flag_EW'] = 3 # aline.analy['vlim'] = [iont['VMIN'][0][kk],iont['VMAX'][0][kk]]*u.km/u.s aline.attrib['z'] = igm_sys.zabs aline.attrib['coord'] = igm_sys.coord # Check f if (np.abs(aline.data['f']-iont['FVAL'][0][kk])/aline.data['f']) > 0.001: Nscl = iont['FVAL'][0][kk] / aline.data['f'] flag_f = True else: Nscl = 1. flag_f = False # Colm if ((flg % 2) == 0) or (flg == 15) or (flg == 13): flgN = 0 print('Skipping column contribution from {:g} as NG for a line; flg={:d}'.format(iont['LAMBDA'][0][kk],flg)) elif (flg == 1) or (flg == 3): flgN = 1 elif (flg == 5) or (flg == 7): flgN = 3 elif (flg == 9) or (flg == 11): flgN = 2 else: pdb.set_trace() raise ValueError("Bad flag!") if flgN == 3: aline.attrib['logN'] = iont['LOGN2SIG'][0][kk] + np.log10(Nscl) aline.attrib['sig_logN'] = 9. elif flgN == 0: # Not for N measurement pass else: aline.attrib['logN'] = iont['LOGN'][0][kk] + np.log10(Nscl) aline.attrib['sig_logN'] = iont['SIGLOGN'][0][kk] aline.attrib['flag_N'] = int(flgN) #pdb.set_trace() if flgN != 0: _,_ = ltaa.linear_clm(aline.attrib) # Append abslines.append(aline) # Component if len(abslines) == 0: comp = AbsComponent(cgabs.igm_sys.coord, (iont['ZION'][0][0],iont['ZION'][0][1]), igm_sys.zabs, igm_sys.vlim) else: comp = AbsComponent.from_abslines(abslines, chk_vel=False) if comp.Zion != (1,1): comp.synthesize_colm() # Combine the abs lines if np.abs(comp.logN - float(iont['CLM'][0])) > 0.15: print("New colm for ({:d},{:d}) and sys {:s} is {:g} different from old".format( comp.Zion[0], comp.Zion[1], cgabs.name, comp.logN - float(iont['CLM'][0]))) if comp.flag_N != iont['FLG_CLM'][0]: if comp.flag_N == 0: pass else: print("New flag for ({:d},{:d}) and sys {:s} is different from old".format( comp.Zion[0], comp.Zion[1], cgabs.name)) pdb.set_trace() #_,_ = ltaa.linear_clm(comp) cgabs.igm_sys.add_component(comp) self.cgm_abs.append(cgabs) # Add Z,ion dat_tab.add_column(Column(all_Z,name='Z')) dat_tab.add_column(Column(all_ion,name='ion')) # Rename dat_tab.rename_column('LOGN','indiv_logN') dat_tab.rename_column('SIGLOGN','indiv_sig_logN') dat_tab.rename_column('CLM','logN') dat_tab.rename_column('SIG_CLM','sig_logN') dat_tab.rename_column('FLG_CLM','flag_N') # Set self.cgm_abs[-1].igm_sys._ionN = dat_tab # NHI HI = (dat_tab['Z'] == 1) & (dat_tab['ion'] == 1) if np.sum(HI) > 0: self.cgm_abs[-1].igm_sys.NHI = dat_tab[HI]['logN'][0] self.cgm_abs[-1].igm_sys.sig_NHI = dat_tab[HI]['sig_logN'][0] self.cgm_abs[-1].igm_sys.flag_NHI = dat_tab[HI]['flag_N'][0] else: warnings.warn("No HI measurement for {}".format(self.cgm_abs[-1])) self.cgm_abs[-1].igm_sys.flag_NHI = 0
def abscomponents_from_abslines(abslinelist, **kwargs): ''' Organizes list of AbsLines into components based on the following order: redshift, velocity, and species Parameters ---------- abslinelist : list List of AbsLine objects Returns ------- complist : list List AbsComponent objects ''' ### Import machine learning clustering algorithm for velocity grouping from sklearn.cluster import MeanShift, estimate_bandwidth from linetools.isgm.abscomponent import AbsComponent ### Populate arrays with line redshifts, velocity centroids, and name of species zarr=np.zeros(len(abslinelist)) varr=np.zeros(len(abslinelist)) sparr=np.chararray(len(abslinelist),itemsize=6) for i,absline in enumerate(abslinelist): zarr[i]=absline.z # import pdb; pdb.set_trace() varr[i]=absline.attrib['vel'].value sparr[i]=atomicdata.lam2ion(absline.wrest.value) abslinelist=np.array(abslinelist) # Convert to array for the indexing used below ### Group lines with the same redshifts and similar velocities complines=[] uqzs=np.unique(zarr) for uqz in uqzs: ### Identify velocity groups thesez = np.where(zarr==uqz)[0] X = np.array(zip(varr[thesez],np.zeros(len(varr[thesez]))), dtype=float) ms = MeanShift(bandwidth=7.) ms.fit(X) vidxs = ms.labels_ vs = ms.cluster_centers_ uqvidxs=np.unique(vidxs) ### Make lists of lines that will belong to each component for idx in uqvidxs: theseuqvs=thesez[np.where(vidxs==idx)[0]] # isolate velocity-grouped lines with this redshift uqsp=np.unique(sparr[theseuqvs]) # identify the unique species with lines in this group ### Get lines belonging to each species and add them to become components for sp in uqsp: spidx=theseuqvs[np.where(sparr[theseuqvs]==sp)] complines.append(abslinelist[spidx]) ### Instantiate the AbsComponents comps=[] for lst in complines: if '*' in lst[0].name: linename=lst[0].name starct=linename.count('*') stars='*'*starct else: stars = None thiscomp=AbsComponent.from_abslines(lst.tolist(), stars=stars, chk_vel=False, **kwargs) comps.append(thiscomp) return comps
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)
def abscomponents_from_abslines(abslinelist, **kwargs): ''' Organizes list of AbsLines into components based on the following order: redshift, velocity, and species Parameters ---------- abslinelist : list List of AbsLine objects Returns ------- complist : list List AbsComponent objects ''' ### Import machine learning clustering algorithm for velocity grouping from sklearn.cluster import MeanShift, estimate_bandwidth from linetools.isgm.abscomponent import AbsComponent ### Populate arrays with line redshifts, velocity centroids, and name of species zarr = np.zeros(len(abslinelist)) varr = np.zeros(len(abslinelist)) sparr = np.chararray(len(abslinelist), itemsize=6) for i, absline in enumerate(abslinelist): zarr[i] = absline.z # import pdb; pdb.set_trace() varr[i] = absline.attrib['vel'].value sparr[i] = atomicdata.lam2ion(absline.wrest.value) abslinelist = np.array( abslinelist) # Convert to array for the indexing used below ### Group lines with the same redshifts and similar velocities complines = [] uqzs = np.unique(zarr) for uqz in uqzs: ### Identify velocity groups thesez = np.where(zarr == uqz)[0] X = np.array(list(zip(varr[thesez], np.zeros(len(varr[thesez])))), dtype=float) ms = MeanShift(bandwidth=7.) ms.fit(X) vidxs = ms.labels_ vs = ms.cluster_centers_ uqvidxs = np.unique(vidxs) ### Make lists of lines that will belong to each component for idx in uqvidxs: theseuqvs = thesez[np.where( vidxs == idx)[0]] # isolate velocity-grouped lines with this redshift uqsp = np.unique( sparr[theseuqvs] ) # identify the unique species with lines in this group ### Get lines belonging to each species and add them to become components for sp in uqsp: spidx = theseuqvs[np.where(sparr[theseuqvs] == sp)] complines.append(abslinelist[spidx]) ### Instantiate the AbsComponents comps = [] for lst in complines: if '*' in lst[0].name: linename = lst[0].name starct = linename.count('*') stars = '*' * starct else: stars = None thiscomp = AbsComponent.from_abslines(lst.tolist(), stars=stars, chk_vel=False, adopt_median=True, **kwargs) comps.append(thiscomp) return comps