def test_sumlogn_limit(): obj1 = dict(flag_N=3, logN=15., sig_logN=99.) obj2 = dict(flag_N=1, logN=14., sig_logN=0.3) flag_N, logN, sig_logN = sum_logN(obj1, obj2) # Test assert flag_N == 1 np.testing.assert_allclose((logN, sig_logN), (obj2['logN'], obj2['sig_logN']))
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_sumlogn_limit(): obj1 = dict(flag_N=3, logN=15., sig_logN=99.) obj2 = dict(flag_N=1, logN=14., sig_logN=0.3) flag_N, logN, sig_logN = sum_logN(obj1, obj2) # Test assert flag_N == 1 np.testing.assert_allclose((logN, sig_logN), (obj2['logN'], obj2['sig_logN']))
def sum_ionN(tbl1, tbl2): """ Sum two ion column density tables Parameters ---------- tbl1 : Table tbl2 : Table Returns ------- sum_tbl : Table """ # Instantiate and use data form original as starting point sum_tbl = tbl1.copy() # Loop through other for row2 in tbl2: # New? Zion = (row2['Z'], row2['ion']) try: row1 = sum_tbl[(sum_tbl['Z'] == Zion[0]) & (sum_tbl['ion'] == Zion[1])] except KeyError: # Add in the new row sum_tbl.add_row(row2) else: idx = np.where((sum_tbl['Z'] == Zion[0]) & (sum_tbl['ion'] == Zion[1]))[0][0] # Clm flagN, logN, siglogN = ltaa.sum_logN(row1, row2) sum_tbl['logN'][idx] = logN # Error sum_tbl['sig_logN'][idx] = siglogN # Flag flags = [row1['flag_N'], row2['flag_N']] if 2 in flags: # At least one saturated flag = 2 elif 1 in flags: # None saturated; at least one detection flag = 1 else: # Both upper limits flag = 3 sum_tbl['flag_N'][idx] = flag # Instrument (assuming binary flag) if 'flg_inst' in row1.keys(): binflg = [0] * 10 for jj in range(10): if (row2['flg_inst'] % 2**(jj + 1)) >= 2**jj: binflg[jj] = 1 if (row1['flg_inst'] % 2**(jj + 1)) >= 2**jj: binflg[jj] = 1 sum_tbl['flg_inst'][idx] = int( np.sum([ 2**kk for kk, ibinf in enumerate(binflg) if ibinf == 1 ])) # Return return sum_tbl
def add_ion_to_data(self, inp_ion): """ Add columns for ion info (column density) to the Table Parameters ---------- inp_ion Returns ------- """ from linetools.analysis import absline as ltaa ion = inp_ion.replace(' ', '') # Check for previous if 'flag_N_{:s}'.format(ion) in self._data.keys(): print("Ion data is already in the _data table") return # Loop on the systems flagNs, Ns, sigNs = [], [], [] for key in self._dict.keys(): igm_comp = self._dict[key]['igm_sys']['components'] comps = [] # Allow for more than one for comp in igm_comp.keys(): sion = comp.split('_')[0] if sion == ion: if 'attrib' in igm_comp[comp].keys(): attrib = igm_comp[comp]['attrib'] attrib['sig_logN'] = np.array(attrib['sig_logN']) comps.append(attrib.copy()) else: # Deprecated comps.append( dict(logN=igm_comp[comp]['logN'], flag_N=igm_comp[comp]['flag_N'], sig_logN=np.array( [igm_comp[comp]['sig_logN']] * 2))) # Now sum em up if len(comps) == 0: flagNs.append(0) Ns.append(0.) sigNs.append(np.array([0.] * 2)) continue obj = dict(flag_N=comps[0]['flag_N'], logN=comps[0]['logN'], sig_logN=comps[0]['sig_logN']) for comp in comps[1:]: if comp['flag_N'] != 0: obj['flag_N'], obj['logN'], obj[ 'sig_logN'] = ltaa.sum_logN(obj, comp) # Save flagNs.append(obj['flag_N']) Ns.append(obj['logN']) sigNs.append(obj['sig_logN']) # Add to Table self._data.add_column(Column(flagNs, name='flag_N_{:s}'.format(ion))) self._data.add_column(Column(Ns, name='logN_{:s}'.format(ion))) self._data.add_column(Column(sigNs, name='sig_logN_{:s}'.format(ion)))
def sum(self,other): '''Sum two IonClms classes Parameters: ---------- other: IonClms Class Another one Returns: -------- A new instance of IonClms with the column densities summed ''' # Instantiate and use data form original as starting point newIC = IonClms() newIC._data = copy.deepcopy(self._data) # Loop through other for row in other._data: # New? Zion = (row['Z'], row['ion']) try: sdict = newIC[Zion] except KeyError: # Add in the new row newIC._data.add_row(row) else: idx = np.where((newIC.Z==Zion[0]) & (newIC.ion==Zion[1]))[0][0] # Clm logN, siglogN = ltaa.sum_logN(sdict,row) newIC._data['logN'][idx] = logN # Error newIC._data['sig_logN'][idx] = siglogN ''' np.sqrt( np.sum([(sdict['sig_clm']*(10.**sdict['clm']))**2, (row['sig_clm']*(10.**row['clm']))**2]))/(10.**newIC._data['clm'][idx]) ''' # Flag flags = [sdict['flg_clm'], row['flg_clm']] if 2 in flags: # At least one saturated flag = 2 elif 1 in flags: # None saturated; at least one detection flag = 1 else: # Both upper limits flag = 3 newIC._data['flg_clm'][idx] = flag # Instrument (assuming binary flag) if 'flg_inst' in sdict.keys(): binflg = [0]*10 for jj in range(10): if (row['flg_inst'] % 2**(jj+1)) >= 2**jj: binflg[jj] = 1 if (sdict['flg_inst'] % 2**(jj+1)) >= 2**jj: binflg[jj] = 1 newIC._data['flg_inst'][idx] = int(np.sum( [2**kk for kk,ibinf in enumerate(binflg) if ibinf==1])) # Return return newIC
def sum_ionN(tbl1, tbl2): """ Sum two ion column density tables Parameters ---------- tbl1 : Table tbl2 : Table Returns ------- sum_tbl : Table """ # Instantiate and use data form original as starting point sum_tbl = tbl1.copy() # Loop through other for row2 in tbl2: # New? Zion = (row2['Z'], row2['ion']) try: row1 = sum_tbl[(sum_tbl['Z'] == Zion[0])&(sum_tbl['ion'] == Zion[1])] except KeyError: # Add in the new row sum_tbl.add_row(row2) else: idx = np.where((sum_tbl['Z'] == Zion[0]) & (sum_tbl['ion'] == Zion[1]))[0][0] # Clm flagN, logN, siglogN = ltaa.sum_logN(row1, row2) sum_tbl['logN'][idx] = logN # Error sum_tbl['sig_logN'][idx] = siglogN # Flag flags = [row1['flag_N'], row2['flag_N']] if 2 in flags: # At least one saturated flag = 2 elif 1 in flags: # None saturated; at least one detection flag = 1 else: # Both upper limits flag = 3 sum_tbl['flag_N'][idx] = flag # Instrument (assuming binary flag) if 'flg_inst' in row1.keys(): binflg = [0]*10 for jj in range(10): if (row2['flg_inst'] % 2**(jj+1)) >= 2**jj: binflg[jj] = 1 if (row1['flg_inst'] % 2**(jj+1)) >= 2**jj: binflg[jj] = 1 sum_tbl['flg_inst'][idx] = int(np.sum( [2**kk for kk, ibinf in enumerate(binflg) if ibinf==1])) # Return return sum_tbl
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 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 tumlinson11(): """Tumlinson, J. et al. 2011, ApJ, 733, 111 J1009+0713 HST/COS Metal columns parsed from Table 1 NHI from LL+Lyman series (uncertain) """ # Grab ASCII file from ApJ tab_fil = pyigm_path + "/data/LLS/Literature/tumlinson11.tb1.ascii" url = 'http://iopscience.iop.org/0004-637X/733/2/111/suppdata/apj388927t1_ascii.txt' chk_fil = glob.glob(tab_fil) if len(chk_fil) > 0: tab_fil = chk_fil[0] else: print('LLSSurvey: Grabbing table file from {:s}'.format(url)) f = urlopen(url) with open(tab_fil, "wb") as code: code.write(f.read()) # Setup radec = '100902.06+071343.8' # From paper lls = LLSSystem(name='J1009+0713_z0.356', radec=radec, zem=0.456, zabs=0.3558, vlim=[-200., 250.] * u.km / u.s, NHI=18.4, sig_NHI=np.array([0.41, 0.41])) # Columns # Start with Table 3 (VPFIT) with open(tab_fil, 'r') as f: flines1 = f.readlines() # Trim flines1 = flines1[18:] # ion_dict = {} line_dict = dict(OI='1302', OVI='1038', MgII='2803^b', SiII='1190', CaII='3934', FeII='2586') ion = None for iline in flines1: isplit = iline.split('\t') if ion == 'FeIII': # Last line break # Ion is2 = isplit[0].split(' ') ion = is2[0] + is2[1] try: gdl = line_dict[ion] except: pass #print('Taking {:s}'.format(isplit[0])) else: if is2[2] != gdl: continue Zion = ltai.name_ion(ion) ion_dict[ion] = dict(logN=0., sig_logN=0., flag_N=0, Z=Zion[0], ion=Zion[1]) # Combine components [could replace with SubSystems some day] for iis in isplit[1:-1]: # Upper limit if (iis.strip()[0] == '<') & (ion_dict[ion]['flag_N'] == 0): ion_dict[ion]['flag_N'] = 3 ion_dict[ion]['logN'] = float(iis[1:]) elif (iis.strip()[0] == '>'): # Saturated ion_dict[ion]['flag_N'] = 2 ion_dict[ion]['logN'] = log_sum( [ion_dict[ion]['logN'], float(iis[1:5])]) elif iis.strip()[0] in ['.', '<']: pass else: if ion_dict[ion]['flag_N'] == 2: # Add to saturated ion_dict[ion]['logN'] = log_sum( [ion_dict[ion]['logN'], float(iis[0:4])]) else: ion_dict[ion]['flag_N'] = 1 obj = dict(logN=float(iis[0:4]), sig_logN=float(iis[-4:]), flag_N=1) # Add flag, N, sig = ltaa.sum_logN(ion_dict[ion], obj) ion_dict[ion]['logN'] = N ion_dict[ion]['sig_logN'] = sig # Finish lls._ionN = pyiau.dict_to_ions(ion_dict) lls.Refs.append('Tum11') return lls
def tripp2005(): '''Tripp, T. et al. 2005, ApJ, 2005, 619, 714 PG 1216+069 (LLS in Virgo) HST/STIS, FUSE Metal columns parsed from Tables 2 and 3 Total NHI from damping wings M/H from O/H ''' # Grab ASCII files from ApJ tab_fils = [ pyigm_path + "/data/LLS/tripp2005.tb3.ascii", pyigm_path + "/data/LLS/tripp2005.tb2.ascii" ] urls = [ 'http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb3.txt', 'http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb2.txt' ] for jj, tab_fil in enumerate(tab_fils): chk_fil = glob.glob(tab_fil) if len(chk_fil) > 0: tab_fil = chk_fil[0] else: url = urls[jj] print('LLSSurvey: Grabbing table file from {:s}'.format(url)) f = urlopen(url) with open(tab_fil, "wb") as code: code.write(f.read()) # Setup radec = '121920.9320+063838.476' # SIMBAD lls = LLSSystem(name='PG1216+069_z0.006', radec=radec, zem=0.3313, zabs=0.00632, vlim=[-100., 100.] * u.km / u.s, NHI=19.32, ZH=-1.6, sig_NHI=np.array([0.03, 0.03])) # Columns # Start with Table 3 (VPFIT) with open(tab_fils[0], 'r') as f: flines3 = f.readlines() ion_dict = {} for iline in flines3: if (len(iline.strip()) == 0): continue isplit = iline.split('\t') # Ion flg = 2 if (len(isplit[0].strip()) > 0): # & (isplit[0][0] not in ['1','2']): ipos = isplit[0].find('1') ionc = isplit[0][0:ipos - 1].strip() try: Zion = ltai.name_ion(ionc) except KeyError: pdb.set_trace() flg = 1 # Column csplit = isplit[3].split(' ') clm = float(csplit[0]) sig = float(csplit[2]) if flg == 1: ion_dict[ionc] = dict(logN=clm, sig_logN=sig, flag_N=1, Z=Zion[0], ion=Zion[1]) else: # Add it in tmp_dict = dict(logN=clm, sig_logN=sig, flag_N=1, Z=Zion[0], ion=Zion[1]) flagN, logN, siglogN = ltaa.sum_logN(ion_dict[ionc], tmp_dict) ion_dict[ionc]['logN'] = logN ion_dict[ionc]['sig_logN'] = siglogN ions = ion_dict.keys() # Now Table 2 for the extras with open(tab_fils[1], 'r') as f: flines2 = f.readlines() # Trim the first 10 lines flines2 = flines2[10:] # Loop for iline in flines2: isplit = iline.split('\t') # ionc = isplit[0].strip() if (len(ionc) == 0) or (ionc in ions): continue # Zion = ltai.name_ion(ionc) ion_dict[ionc] = dict(Z=Zion[0], ion=Zion[1], sig_logN=0.) if isplit[4][0] == '<': ion_dict[ionc]['logN'] = float(isplit[4][1:]) ion_dict[ionc]['flag_N'] = 3 else: raise ValueError('Should not get here') # Finish lls._ionN = pyiau.dict_to_ions(ion_dict) lls.Refs.append('Tri05') return lls
def tumlinson11(): """Tumlinson, J. et al. 2011, ApJ, 733, 111 J1009+0713 HST/COS Metal columns parsed from Table 1 NHI from LL+Lyman series (uncertain) """ # Grab ASCII file from ApJ tab_fil = pyigm_path+"/data/LLS/Literature/tumlinson11.tb1.ascii" url = 'http://iopscience.iop.org/0004-637X/733/2/111/suppdata/apj388927t1_ascii.txt' chk_fil = glob.glob(tab_fil) if len(chk_fil) > 0: tab_fil = chk_fil[0] else: print('LLSSurvey: Grabbing table file from {:s}'.format(url)) f = urllib2.urlopen(url) with open(tab_fil, "wb") as code: code.write(f.read()) # Setup radec = '100902.06+071343.8' # From paper lls = LLSSystem(name='J1009+0713_z0.356', radec=radec, zem=0.456, zabs=0.3558, vlim=[-200., 250.]*u.km/u.s, NHI=18.4, sig_NHI=np.array([0.41,0.41])) # Columns # Start with Table 3 (VPFIT) with open(tab_fil,'r') as f: flines1 = f.readlines() # Trim flines1 = flines1[18:] # ion_dict = {} line_dict = dict(OI='1302',OVI='1038',MgII='2803^b',SiII='1190', CaII='3934',FeII='2586') ion = None for iline in flines1: isplit = iline.split('\t') if ion=='FeIII': # Last line break # Ion is2 = isplit[0].split(' ') ion = is2[0]+is2[1] try: gdl = line_dict[ion] except: pass #print('Taking {:s}'.format(isplit[0])) else: if is2[2] != gdl: continue Zion = ltai.name_ion(ion) ion_dict[ion] = dict(logN=0., sig_logN=0., flag_N=0, Z=Zion[0],ion=Zion[1]) # Combine components [could replace with SubSystems some day] for iis in isplit[1:-1]: # Upper limit if (iis.strip()[0] == '<') & (ion_dict[ion]['flag_N']==0): ion_dict[ion]['flag_N']=3 ion_dict[ion]['logN']=float(iis[1:]) elif (iis.strip()[0] == '>'): # Saturated ion_dict[ion]['flag_N']=2 ion_dict[ion]['logN']=log_sum([ion_dict[ion]['logN'],float(iis[1:5])]) elif iis.strip()[0] in ['.','<']: pass else: if ion_dict[ion]['flag_N']==2: # Add to saturated ion_dict[ion]['logN']=log_sum([ion_dict[ion]['logN'],float(iis[0:4])]) else: ion_dict[ion]['flag_N']=1 obj = dict(logN=float(iis[0:4]),sig_logN=float(iis[-4:]), flag_N=1) # Add flag,N,sig = ltaa.sum_logN(ion_dict[ion],obj) ion_dict[ion]['logN']=N ion_dict[ion]['sig_logN']=sig # Finish lls._ionN = pyiau.dict_to_ions(ion_dict) lls.Refs.append('Tum11') return lls
def tripp2005(): '''Tripp, T. et al. 2005, ApJ, 2005, 619, 714 PG 1216+069 (LLS in Virgo) HST/STIS, FUSE Metal columns parsed from Tables 2 and 3 Total NHI from damping wings M/H from O/H ''' # Grab ASCII files from ApJ tab_fils = [pyigm_path+"/data/LLS/tripp2005.tb3.ascii", pyigm_path+"/data/LLS/tripp2005.tb2.ascii"] urls = ['http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb3.txt', 'http://iopscience.iop.org/0004-637X/619/2/714/fulltext/60797.tb2.txt'] for jj,tab_fil in enumerate(tab_fils): chk_fil = glob.glob(tab_fil) if len(chk_fil) > 0: tab_fil = chk_fil[0] else: url = urls[jj] print('LLSSurvey: Grabbing table file from {:s}'.format(url)) f = urllib2.urlopen(url) with open(tab_fil, "wb") as code: code.write(f.read()) # Setup radec = '121920.9320+063838.476' # SIMBAD lls = LLSSystem(name='PG1216+069_z0.006', radec=radec, zem=0.3313, zabs=0.00632, vlim=[-100., 100.]*u.km/u.s, NHI=19.32, ZH=-1.6, sig_NHI=np.array([0.03, 0.03])) # Columns # Start with Table 3 (VPFIT) with open(tab_fils[0],'r') as f: flines3 = f.readlines() ion_dict = {} for iline in flines3: if (len(iline.strip()) == 0): continue isplit = iline.split('\t') # Ion flg = 2 if (len(isplit[0].strip()) > 0):# & (isplit[0][0] not in ['1','2']): ipos = isplit[0].find('1') ionc = isplit[0][0:ipos-1].strip() try: Zion = ltai.name_ion(ionc) except KeyError: pdb.set_trace() flg = 1 # Column csplit = isplit[3].split(' ') clm = float(csplit[0]) sig = float(csplit[2]) if flg == 1: ion_dict[ionc] = dict(logN=clm, sig_logN=sig, flag_N=1, Z=Zion[0], ion=Zion[1]) else: # Add it in tmp_dict = dict(logN=clm, sig_logN=sig, flag_N=1, Z=Zion[0], ion=Zion[1]) flagN, logN, siglogN = ltaa.sum_logN(ion_dict[ionc], tmp_dict) ion_dict[ionc]['logN'] = logN ion_dict[ionc]['sig_logN'] = siglogN ions = ion_dict.keys() # Now Table 2 for the extras with open(tab_fils[1],'r') as f: flines2 = f.readlines() # Trim the first 10 lines flines2 = flines2[10:] # Loop for iline in flines2: isplit = iline.split('\t') # ionc = isplit[0].strip() if (len(ionc) == 0) or (ionc in ions): continue # Zion = ltai.name_ion(ionc) ion_dict[ionc] = dict(Z=Zion[0], ion=Zion[1], sig_logN=0.) if isplit[4][0] == '<': ion_dict[ionc]['logN'] = float(isplit[4][1:]) ion_dict[ionc]['flag_N'] = 3 else: raise ValueError('Should not get here') # Finish lls._ionN = pyiau.dict_to_ions(ion_dict) lls.Refs.append('Tri05') return lls