def dla_stat(DLAs, qsos, vprox=None, buff=3000.*u.km/u.s, zem_min=0., flg_zsrch=0, vmin=0.*u.km/u.s, LLS_CUT=None, partial=False, prox=False): """ Identify the statistical DLA in a survey Parameters ---------- vmin : Quantity vprox maxdz zem_min buff : Quantity Buffer velocity in Proximate analysis [not ready for this] NHI_cut flg_zsrch dz_toler partial : bool, optional Analyze partial LLS? [pLLS] prox : bool, optional Proximate LLS? [PLLS] Returns ------- msk_smpl : bool array True = statistical """ from linetools.utils import z_from_v from astropy.coordinates import SkyCoord # DLA msk_smpl = DLAs.zem != DLAs.zem #zmax = z_from_v(qsos['ZEM'], vprox) zmin = z_from_v(qsos['Z_START'], vmin) # Make some lists qsos_coord = SkyCoord(ra=qsos['RA'], dec=qsos['DEC']) for qq, idla in enumerate(DLAs._abs_sys): # In stat? small_sep = idla.coord.separation(qsos_coord) < 3.6*u.arcsec close_zem = np.abs(idla.zem-qsos['ZEM']) < 0.03 idx = np.where(small_sep & close_zem)[0] if len(idx) == 0: continue elif len(idx) == 1: #pdb.set_trace() if ((idla.zabs >= zmin[idx]) & (idla.zabs <= qsos[idx]['Z_END']) & (qsos[idx]['FLG_BAL'] != 2)): msk_smpl[qq] = True else: pdb.set_trace() raise ValueError("Should not be here") # Return return msk_smpl
def on_key(self,event): # Init rescale = True fig_clear = False wrest = None flg = 0 sv_idx = self.idx_line ## Change rows/columns if event.key == 'k': self.sub_xy[0] = max(0, self.sub_xy[0]-1) if event.key == 'K': self.sub_xy[0] = self.sub_xy[0]+1 if event.key == 'c': self.sub_xy[1] = max(0, self.sub_xy[1]-1) if event.key == 'C': self.sub_xy[1] = max(0, self.sub_xy[1]+1) ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict,event) if event.key == '-': self.idx_line = max(0, self.idx_line-self.sub_xy[0]*self.sub_xy[1]) # Min=0 if self.idx_line == sv_idx: print('Edge of list') if event.key == '=': self.idx_line = min(len(self.llist['show_line'])-self.sub_xy[0]*self.sub_xy[1], self.idx_line + self.sub_xy[0]*self.sub_xy[1]) if self.idx_line == sv_idx: print('Edge of list') ## Reset z if event.key == 'z': newz = ltu.z_from_v(self.z, event.xdata) self.z = newz # Drawing self.psdict['x_minmax'] = self.vmnx.value # Single line command if event.key in ['1','2','B','U','L','N','V','A', 'x', 'X', '^', '&']: try: wrest = event.inaxes.get_gid() except AttributeError: return else: absline = self.grab_line(wrest) ## Velocity limits unit = u.km/u.s if event.key == '1': absline.limits.set((event.xdata, absline.limits.vlim[1].value)*unit) if event.key == '2': absline.limits.set((absline.limits.vlim[0].value, event.xdata)*unit) if event.key == '!': # Set all lines to this value for iline in self.abs_lines: iline.limits.set((event.xdata, iline.limits.vlim[1].value)*unit) if event.key == '@': for iline in self.abs_lines: iline.limits.set((iline.limits.vlim[0].value, event.xdata)*unit) ## Line type if event.key == 'A': # Add to lines self.generate_line((self.z,wrest)) if event.key == 'x': # Remove line if self.remove_line(wrest): print('VelPlot: Removed line {:g}'.format(wrest)) if event.key == 'X': # Remove all lines # Double check gui = simple_widgets.WarningWidg('About to remove all lines. \n Continue??') gui.exec_() if gui.ans is False: return # self.abs_lines = [] # Flush?? # Kinematics if event.key == '^': # Low-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**1 >= 2**0) * 2**0 absline.analy['flag_kin'] = fkin if event.key == '&': # High-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**2 >= 2**1) * 2**1 absline.analy['flag_kin'] = fkin # Toggle blend if event.key == 'B': try: feye = absline.analy['flg_eye'] except KeyError: feye = 0 feye = (feye + 1) % 2 absline.analy['flg_eye'] = feye # Toggle NG if event.key == 'N': try: fanly = absline.analy['do_analysis'] except KeyError: fanly = 1 if fanly == 0: fanly = 1 else: fanly = 0 absline.analy['do_analysis'] = fanly if event.key == 'V': # Normal absline.analy['flg_limit'] = 1 if event.key == 'L': # Lower limit absline.analy['flg_limit'] = 2 if event.key == 'U': # Upper limit absline.analy['flg_limit'] = 3 ''' # AODM plot if event.key == ':': # # Grab good lines from xastropy.xguis import spec_guis as xsgui gdl = [iline.wrest for iline in self.abs_sys.lines if iline.analy['do_analysis'] > 0] # Launch AODM if len(gdl) > 0: gui = xsgui.XAODMGui(self.spec, self.z, gdl, vmnx=self.vmnx, norm=self.norm) gui.exec_() else: print('VelPlot.AODM: No good lines to plot') ''' if wrest is not None: # Single window flg = 3 if event.key in ['c','C','k','K','W','!', '@', '=', '-', 'X', 'z','R']: # Redraw all flg = 1 if event.key in ['Y']: rescale = False if event.key in ['k','c','C','K', 'R']: fig_clear = True # Print help message if event.key == '?': print(self.help_message) if flg == 1: # Default is not to redraw self.on_draw(rescale=rescale, fig_clear=fig_clear) elif flg == 2: # Layer (no clear) self.on_draw(replot=False, rescale=rescale) elif flg == 3: # Layer (no clear) self.on_draw(in_wrest=wrest, rescale=rescale)
def get_zpeak(self): """ Measure zpeak from an ionic transition """ if self.ions is None: print('get_zpeak: Need to fill ions with get_ions first.') return # Ions for analysis low_ions = [ (14,2), (6,2), (13,2), (26,2), (13,3)] # SiII,CII,AlII,FeII,AlIII high_ions= [(14,4), (6,4)] # SiIV, CIV for tt in range(4): if tt == 0: ions = low_ions iflg = 1 # Standard elif tt == 1: ions = low_ions iflg = 2 # Saturated elif tt == 2: ions = high_ions iflg = 1 # Standard elif tt == 3: ions = high_ions iflg = 2 # Standard else: raise ValueError('Bad value') # Search for ion in ions: try: t = self.ions[ion] except KeyError: continue # Measurement? if t['flag_N'] == iflg: # Identify the transition gdi = np.where( (self.ions.trans['Z'] == ion[0]) & (self.ions.trans['ion'] == ion[1]) & (self.ions.trans['flag_N'] <= iflg) )[0] # Take the first one gdt = self.ions.trans[gdi[0]] wrest = gdt['wrest'] flgs = self.clm_analy.clm_lines[wrest].analy['FLAGS'] spec_file = self.clm_analy.fits_files[flgs[1] % 64] # Generate an Abs_Line with spectrum line = AbsLine(wrest, z=self.clm_analy.zsys, spec_file=spec_file) # vpeak from linetools import utils as ltu vpeak = line.vpeak() self.zpeak = ltu.z_from_v(self.clm_analy.zsys, vpeak) if tt == 3: print('zpeak WARNING: Using saturated high-ions!!') break else: continue break # Error catching if self.zpeak is None: # Skip primordial LLS print('lls.zpeak: No transition in {:s}'.format(self.clm_analy.clm_fil)) return (0,0), 0. # Return return ion, vpeak
def on_key(self, event): # Init rescale = True fig_clear = False wrest = None flg = 0 sv_idx = self.idx_line ## Change rows/columns if event.key == 'k': self.sub_xy[0] = max(0, self.sub_xy[0] - 1) if event.key == 'K': self.sub_xy[0] = self.sub_xy[0] + 1 if event.key == 'c': self.sub_xy[1] = max(0, self.sub_xy[1] - 1) if event.key == 'C': self.sub_xy[1] = max(0, self.sub_xy[1] + 1) ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event) if event.key == '-': self.idx_line = max(0, self.idx_line - self.sub_xy[0] * self.sub_xy[1]) # Min=0 if self.idx_line == sv_idx: print('Edge of list') if event.key == '=': self.idx_line = min( len(self.llist['show_line']) - self.sub_xy[0] * self.sub_xy[1], self.idx_line + self.sub_xy[0] * self.sub_xy[1]) #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if self.idx_line == sv_idx: print('Edge of list') ## Reset z if event.key == 'z': newz = ltu.z_from_v(self.z, event.xdata) self.z = newz self.abs_sys.zabs = newz # Drawing self.psdict['xmnx'] = self.vmnx.value # Single line command if event.key in [ '1', '2', 'B', 'U', 'L', 'N', 'V', 'A', 'x', 'X', '^', '&' ]: try: wrest = event.inaxes.get_gid() except AttributeError: return else: absline = self.grab_line(wrest) kwrest = wrest.value ## Velocity limits unit = u.km / u.s if event.key == '1': absline.analy['vlim'][0] = event.xdata * unit if event.key == '2': #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() absline.analy['vlim'][1] = event.xdata * unit if event.key == '!': for iline in self.abs_sys.lines: iline.analy['vlim'][0] = event.xdata * unit if event.key == '@': for iline in self.abs_sys.lines: iline.analy['vlim'][1] = event.xdata * unit ## Line type if event.key == 'A': # Add to lines self.generate_line((self.z, wrest)) if event.key == 'x': # Remove line if self.remove_line(wrest): print('VelPlot: Removed line {:g}'.format(wrest)) if event.key == 'X': # Remove all lines # Double check gui = xguiu.WarningWidg( 'About to remove all lines. \n Continue??') gui.exec_() if gui.ans is False: return # self.abs_lines = [] # Flush?? # Kinematics if event.key == '^': # Low-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**1 >= 2**0) * 2**0 absline.analy['flag_kin'] = fkin if event.key == '&': # High-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**2 >= 2**1) * 2**1 absline.analy['flag_kin'] = fkin # Toggle blend if event.key == 'B': try: feye = absline.analy['flg_eye'] except KeyError: feye = 0 feye = (feye + 1) % 2 absline.analy['flg_eye'] = feye # Toggle NG if event.key == 'N': try: fanly = absline.analy['do_analysis'] except KeyError: fanly = 1 if fanly == 0: fanly = 1 else: fanly = 0 absline.analy['do_analysis'] = fanly if event.key == 'V': # Normal absline.analy['flg_limit'] = 1 if event.key == 'L': # Lower limit absline.analy['flg_limit'] = 2 if event.key == 'U': # Upper limit absline.analy['flg_limit'] = 3 # AODM plot if event.key == ':': # # Grab good lines from xastropy.xguis import spec_guis as xsgui gdl = [ iline.wrest for iline in self.abs_sys.lines if iline.analy['do_analysis'] > 0 ] # Launch AODM if len(gdl) > 0: gui = xsgui.XAODMGui(self.spec, self.z, gdl, vmnx=self.vmnx, norm=self.norm) gui.exec_() else: print('VelPlot.AODM: No good lines to plot') #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if not wrest is None: # Single window flg = 3 if event.key in [ 'c', 'C', 'k', 'K', 'W', '!', '@', '=', '-', 'X', 'z', 'R' ]: # Redraw all flg = 1 if event.key in ['Y']: rescale = False if event.key in ['k', 'c', 'C', 'K', 'R']: fig_clear = True if flg == 1: # Default is not to redraw self.on_draw(rescale=rescale, fig_clear=fig_clear) elif flg == 2: # Layer (no clear) self.on_draw(replot=False, rescale=rescale) elif flg == 3: # Layer (no clear) self.on_draw(in_wrest=wrest, rescale=rescale)
def lls_stat(LLSs, qsos, vprox=3000.*u.km/u.s, maxdz=99.99, zem_min=0., NHI_cut=17.5, flg_zsrch=0, dz_toler=0.04, LLS_CUT=None, partial=False, prox=False): """ Identify the statistical LLS in a survey Parameters ---------- vprox maxdz zem_min NHI_cut flg_zsrch dz_toler partial : bool, optional Analyze partial LLS? [pLLS] prox : bool, optional Proximate LLS? [PLLS] Returns ------- msk_smpl : bool array True = statistical """ from linetools.utils import z_from_v # Search redshift if flg_zsrch == 0: zsrch = qsos['ZT2'] elif flg_zsrch == 1: zsrch = qsos['ZT1'] elif flg_zsrch == 2: zsrch = qsos['ZT0'] # Modify by LLS along QSO sightline as required if LLS_CUT is not None: pdb.set_trace() #zsrch = zsrch > qsos.zlls[LLS_CUT] # LLS msk_smpl = LLSs.zem != LLSs.zem zmax = z_from_v(qsos['ZEM'], vprox) # Make some lists lls_coord = LLSs.coord lls_zem = LLSs.zem lls_zabs = LLSs.zabs qsos_coord = SkyCoord(ra=qsos['RA']*u.deg, dec=qsos['DEC']*u.deg) for qq, ills in enumerate(LLSs._abs_sys): # Two LLS on one sightline? small_sep = ills.coord.separation(lls_coord) < 3.6*u.arcsec close_zem = np.abs(ills.zem-lls_zem) < 0.03 close_zabs = np.abs(ills.zabs-lls_zabs) < dz_toler if np.sum(small_sep & close_zem & close_zabs) != 1: raise ValueError("LLS are probably too close in z") # Cut on NHI if partial & (ills.NHI > NHI_cut): continue if ~partial & (ills.NHI <= NHI_cut): continue # Match to QSO RA, DEC idx = np.where( (ills.coord.separation(qsos_coord) < 3.6*u.arcsec) & (np.abs(qsos['ZEM']-ills.zem) < 0.03))[0] if len(idx) != 1: raise ValueError("Problem with matches") # Query redshift if ((zsrch[idx] > 0.) & (ills.zabs > max(zsrch[idx], qsos['ZEM'][idx] - maxdz) - 1e-4) & (qsos['ZEM'][idx] > zem_min)): if (~prox) & (ills.zabs < zmax[idx]): # Intervening msk_smpl[qq] = True if prox & (ills.zabs >= zmax[idx]): # Proximate msk_smpl[qq] = True # Return return msk_smpl
def get_zpeak(self): """ Measure zpeak from an ionic transition """ if self.ions is None: print('get_zpeak: Need to fill ions with get_ions first.') return # Ions for analysis low_ions = [(14, 2), (6, 2), (13, 2), (26, 2), (13, 3)] # SiII,CII,AlII,FeII,AlIII high_ions = [(14, 4), (6, 4)] # SiIV, CIV for tt in range(4): if tt == 0: ions = low_ions iflg = 1 # Standard elif tt == 1: ions = low_ions iflg = 2 # Saturated elif tt == 2: ions = high_ions iflg = 1 # Standard elif tt == 3: ions = high_ions iflg = 2 # Standard else: raise ValueError('Bad value') # Search for ion in ions: try: t = self.ions[ion] except KeyError: continue # Measurement? if t['flag_N'] == iflg: # Identify the transition gdi = np.where((self.ions.trans['Z'] == ion[0]) & (self.ions.trans['ion'] == ion[1]) & (self.ions.trans['flag_N'] <= iflg))[0] # Take the first one gdt = self.ions.trans[gdi[0]] wrest = gdt['wrest'] flgs = self.clm_analy.clm_lines[wrest].analy['FLAGS'] spec_file = self.clm_analy.fits_files[flgs[1] % 64] # Generate an Abs_Line with spectrum line = AbsLine(wrest, z=self.clm_analy.zsys, spec_file=spec_file) # vpeak from linetools import utils as ltu vpeak = line.vpeak() self.zpeak = ltu.z_from_v(self.clm_analy.zsys, vpeak) if tt == 3: print('zpeak WARNING: Using saturated high-ions!!') break else: continue break # Error catching if self.zpeak is None: # Skip primordial LLS print('lls.zpeak: No transition in {:s}'.format( self.clm_analy.clm_fil)) return (0, 0), 0. # Return return ion, vpeak