def mock_HIlines(HI_comps, wvmnx, tau0_min=5e-3): """Generate list of absorption lines for a sightline Parameters: ------------ HI_comps : QTable HI components ('z','lgNHI','bval') wvmnx : tuple (Quantity,Quantity) min/max wavelength tau0_min : float, optional Minimum optical depth to include Returns: -------- abs_lines: list List of HI Lyman lines """ # Linelist HIlines = lll.LineList('HI') wrest = HIlines._data['wrest'] # All wvobs grid_zp1 = np.outer(HI_comps['z']+1, np.ones(len(wrest))) grid_wr = np.outer(np.ones(len(HI_comps)), wrest) all_wvobs = grid_zp1 * grid_wr # All tau0 # Grids grid_NHI = np.outer(10.**HI_comps['lgNHI'], np.ones(len(wrest))) grid_b = np.outer(HI_comps['bval'].to('cm/s'), np.ones(len(wrest))) grid_f = np.outer(np.ones(len(HI_comps)), HIlines._data['f']) # tau0 (Spitzer 1979) grid_tau0 = 1.497e-2 * grid_wr * 1e-8 * grid_f * grid_NHI / grid_b # Good ones gdlin = np.where( (all_wvobs>wvmnx[0].value) & (all_wvobs<wvmnx[1].value) & (grid_tau0>tau0_min)) # Generate the line list for Lyman series grid_lgNHI = np.log10(grid_NHI) grid_z = grid_zp1 - 1. grid_bkms = grid_b / 1e5 * u.km/u.s # Parameters parm = [] for ii,jj in zip(gdlin[0],gdlin[1]): # lambda, z, N, b parm.append([grid_wr[ii,jj]*u.AA, grid_z[ii,jj], grid_lgNHI[ii,jj], grid_bkms[ii,jj]]) # Generate a large batch of AbsLines all_wrest = [iparm[0] for iparm in parm] abs_lines = spectralline.many_abslines(all_wrest, HIlines) # Fill in the rest for jj,iparm in enumerate(parm): abs_lines[jj].setz(iparm[1]) abs_lines[jj].attrib['logN'] = iparm[2] abs_lines[jj].attrib['N'] = 10**iparm[2] / u.cm**2 abs_lines[jj].attrib['b'] = iparm[3] # Retrun return abs_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 fill_lls_lines(self, bval=20. * u.km / u.s): """ Generate an HI line list for an LLS. Goes into self.lls_lines Parameters ---------- bval : float (20.) Doppler parameter in km/s """ from linetools.lists import linelist as lll from linetools.spectralline import AbsLine # May be replaced by component class (as NT desires) HIlines = lll.LineList('HI') self.lls_lines = [] for lline in HIlines._data: aline = AbsLine(lline['wrest'], linelist=HIlines) # Attributes aline.attrib['N'] = self.NHI aline.attrib['b'] = bval aline.attrib['z'] = self.zabs # Could set RA and DEC too aline.attrib['RA'] = self.coord.ra aline.attrib['DEC'] = self.coord.dec self.lls_lines.append(aline)
def calc_lum(neb_lines, line, z, cosmo, AV=None, curve='MW'): """ Calculate the line luminosity (and error) from input nebular line emission Error is -999.*erg/s if input line flux has negative error Args: neb_lines (dict): Observed line fluxes and errors line (str): Line to analyze z (float): Emission redshift -- for Luminosity distance cosmo (astropy.cosmology.FLRW): Cosmology AV (float, optional): Visual extinction, if supplied will apply curve (str): Name of the extinction curve. Only used if A_V is supplied Returns: Quantity, Quantity: Luminosity, sig(Luminosity) """ # Grab rest wavelength (vacuum) llist = linelist.LineList('Galaxy') wave = llist[line]['wrest'] # Dust correct? if AV is not None: alAV = load_extinction(curve) al = AV * alAV(wave.to('Angstrom').value) else: al = 0. # Cosmology DL = cosmo.luminosity_distance(z) # Luminosity flux = neb_lines[line] Lum = flux * units.erg/units.s/units.cm**2 * 10**(al/2.5) * (4*np.pi * DL**2) # Error if neb_lines[line+'_err'] > 0.: flux_err = neb_lines[line+'_err'] Lum_err = flux_err * units.erg/units.s/units.cm**2 * 10**(al/2.5) * (4*np.pi * DL**2) else: Lum_err = -999 * units.erg/units.s # Return return Lum.to('erg/s'), Lum_err.to('erg/s')
def fig_abs_gallery(wrest=None, lbl=None, outfil=None, cos_halos=None, passback=False, axes_flg=0): # import tlk_coshalos as tch # reload(tch) # cos_halos = tch.fig_abs_gallery(passback=True) '''Gallery of absorption lines Default is M* vs. sSFR But you can do rho vs. M* too axes_flg: int, optional 0: M* vs. sSFR 1: rho vs. M* ''' # Linelist llist = lll.LineList('Strong') if wrest is None: wrest = 1215.670 * u.AA Zion = (llist[wrest]['Z'], llist[wrest]['ion']) if lbl is None: lbl = r'HI Ly$\alpha$' if outfil is None: outfil = 'fig_HI_gallery.pdf' # Init COS-Halos (slow) if cos_halos is None: cos_halos = COSHalos() cos_halos.load_mega() #skip_ions=True) if passback: return cos_halos if axes_flg == 0: xmnx = (9.4, 11.7) ymnx = (-13., -9.) elif axes_flg == 1: ymnx = (9.4, 11.7) # log Msun xmnx = (15., 163) # kpc vmnx = (-600., 600.) # km/s wbox = {'facecolor': 'white', 'edgecolor': 'white'} lclr = 'blue' # To help with looping def sngl_abs(ax, field_gal, wbox=wbox, lclr=lclr, vmnx=vmnx, xmnx=xmnx, ymnx=ymnx, cos_halos=cos_halos, show_xylbl=True, srect=0.2, show_ewlbl=True, lw=1.3, axes_flg=axes_flg): # cgm_abs = cos_halos[field_gal] if axes_flg == 0: xplt = cgm_abs.galaxy.stellar_mass yplt = np.log10( cgm_abs.galaxy.sfr[1]) - cgm_abs.galaxy.stellar_mass elif axes_flg == 1: yplt = cgm_abs.galaxy.stellar_mass xplt = cgm_abs.rho.value # Spec spec = cos_halos.load_bg_cos_spec(field_gal, wrest) velo = spec.relative_vel(wrest * (cgm_abs.galaxy.z + 1)) # EW data = cgm_abs.abs_sys.ions[Zion] itrans = np.where(np.abs(data['LAMBDA'] - wrest.value) < 1e-3)[0] if len(itrans) == 0: print('No measurement of {:g} for {:s} {:s}'.format( wrest, field_gal[0], field_gal[1])) return EW = data['WREST'][itrans][0] * u.AA / 1e3 sigEW = data['SIGWREST'][itrans][0] * u.AA / 1e3 if sigEW <= 0.: # Something must be wrong return if EW > 3 * sigEW: sclr = 'k' else: sclr = 'r' # xrect = (xplt - xmnx[0]) / (xmnx[1] - xmnx[0]) yrect = (yplt - ymnx[0]) / (ymnx[1] - ymnx[0]) rect = [xrect, yrect, srect, srect] axsp = xpsimp.add_subplot_axes(ax, rect) #,axisbg=axisbg) axsp.set_xlim(vmnx) axsp.set_ylim(-0.1, 1.3) if show_xylbl: axsp.set_xlabel('Relative Velocity (km/s)', fontsize=9.) axsp.set_ylabel('Normalized Flux', fontsize=9.) # Plot axsp.plot(velo, spec.flux, sclr, drawstyle='steps', lw=lw) # Label #llbl = (r'$W_\lambda = $'+'{:0.2f} A \n'.format(EW.value)+ # '$z=${:.3f}\n'.format(cgm_abs.galaxy.z)+ # r'$\rho=$'+'{:d}kpc'.format(int(np.round(cgm_abs.rho.to('kpc').value)))) if show_ewlbl: llbl = r'$W_\lambda = $' + '{:0.2f} A'.format(EW.value) axsp.text(-300., 1.1, llbl, ha='left', fontsize=7., color=lclr, bbox=wbox) #multialignment='left') # Start the plot pp = PdfPages(outfil) if axes_flg == 0: loop = range(4) else: loop = range(3, 4) for ss in loop: plt.figure(figsize=(8, 5)) plt.clf() gs = gridspec.GridSpec(1, 1) # Axes ax = plt.subplot(gs[0, 0]) ax.set_xlim(xmnx) ax.set_ylim(ymnx) if axes_flg == 0: ax.set_ylabel('sSFR') ax.set_xlabel('log M*') ax.text(9.75, -12., lbl, color=lclr, fontsize=21.) elif axes_flg == 1: ax.set_ylabel('log M*') ax.set_xlabel('Impact Parameter (kpc)') ax.text(40., 11.5, lbl, color=lclr, fontsize=21.) #ax.xaxis.set_major_locator(plt.MultipleLocator(300.)) # if ss == 0: # Single system field_gal = ('J0950+4831', '177_27') sngl_abs(ax, field_gal) elif ss == 1: # Two systems cgm_list = [('J0950+4831', '177_27'), ('J1245+3356', '236_36')] for field_gal in cgm_list: sngl_abs(ax, field_gal) elif ss > 1: # Half systems if ss == 2: iend = 20 else: iend = -1 for cgm_abs in cos_halos.cgm_abs[0:iend]: field_gal = (cgm_abs.field, cgm_abs.gal_id) sngl_abs(ax, field_gal, show_xylbl=False, srect=0.1, show_ewlbl=False, lw=0.5) else: pass xputils.set_fontsize(ax, 17.) # Write plt.tight_layout(pad=0.2, h_pad=0., w_pad=0.1) pp.savefig() plt.close() # Finish print('tlk_coshalos: Wrote {:s}'.format(outfil)) pp.close()