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 cgm_from_galaxy_igmsystems(galaxy, igmsystems, rho_max=300 * u.kpc, dv_max=400 * u.km / u.s, cosmo=None, dummysys=False, dummyspec=None, verbose=True, **kwargs): """ Generate a list of CGMAbsSys objects given an input galaxy and a list of IGMSystems Parameters ---------- galaxy : Galaxy igmsystems : list list of IGMSystems rho_max : Quantity Maximum projected separation from sightline to galaxy dv_max Maximum velocity offset between system and galaxy dummysys: bool, optional If True, instantiate CGMAbsSys even if no match is found in igmsystems dummyspec : XSpectrum1D, optional Spectrum object to attach to dummy AbsLine/AbsComponent objects when adding IGMSystems if dummysys is True. Returns ------- cgm_list : list list of CGM objects generated """ from pyigm.cgm.cgm import CGMAbsSys # Cosmology if cosmo is None: cosmo = cosmology.Planck15 if dummysys is True: if dummyspec is None: dummyspec = igmsystems[0]._components[0]._abslines[0].analy['spec'] dummycoords = igmsystems[0].coord # R -- speed things up rho, angles = calc_cgm_rho(galaxy, igmsystems, cosmo, **kwargs) if len(igmsystems) == 1: # Kludge rho = u.Quantity([rho]) angles = u.Quantity([angles]) # dv igm_z = np.array([igmsystem.zabs for igmsystem in igmsystems]) dv = ltu.dv_from_z(igm_z, galaxy.z) # Rules match = np.where((rho < rho_max) & (np.abs(dv) < dv_max))[0] ### If none, see if some system has a component that's actually within dv_max if (len(match) == 0) & (rho[0] < rho_max): zcomps = [] sysidxs = [] for i, csys in enumerate(igmsystems): thesezs = [comp.zcomp for comp in csys._components] sysidxs.extend([i] * len(thesezs)) zcomps.extend(thesezs) zcomps = np.array(zcomps) sysidxs = np.array(sysidxs) dv_comps = ltu.dv_from_z(zcomps, galaxy.z) match = np.unique(sysidxs[np.where(np.abs(dv_comps) < dv_max)[0]]) if len(match) == 0: if dummysys is False: print( "No IGMSystem paired to this galaxy. CGM object not created.") return [] else: if verbose: print("No IGMSystem match found. Attaching dummy IGMSystem.") dummysystem = IGMSystem(dummycoords, galaxy.z, vlim=None) dummycomp = AbsComponent(dummycoords, (1, 1), galaxy.z, [-100., 100.] * u.km / u.s) dummycomp.flag_N = 3 dummyline = AbsLine( 'HI 1215', **kwargs) # Need an actual transition for comp check dummyline.analy['spec'] = dummyspec dummyline.attrib['coord'] = dummycoords dummycomp.add_absline(dummyline, chk_vel=False, chk_sep=False) dummysystem.add_component(dummycomp, chk_vel=False, chk_sep=False) cgm = CGMAbsSys(galaxy, dummysystem, cosmo=cosmo, **kwargs) cgm_list = [cgm] else: # Loop to generate cgm_list = [] for imatch in match: # Instantiate new IGMSystem # Otherwise, updates to the IGMSystem cross-pollinate other CGMs sysmatch = igmsystems[imatch] newisys = sysmatch.copy() # Handle z limits zlim = ltu.z_from_dv((-dv_max.value, dv_max.value) * u.km / u.s, galaxy.z) newlims = zLimits(galaxy.z, zlim.tolist()) newisys.limits = newlims # Allow for components extending beyond dv_max newisys.update_vlim() newisys.update_component_vel() # Finish cgm = CGMAbsSys(galaxy, newisys, cosmo=cosmo, rho=rho[imatch], ang_sep=angles[imatch], **kwargs) cgm_list.append(cgm) # Return return cgm_list
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)