def test_navigate(): # Init nav_dict = dict(nav=ltgu.navigate(0,0,init=True)) assert isinstance(nav_dict['nav'], list) nav_dict['x_minmax'] = [0., 1] nav_dict['y_minmax'] = [0., 1] nav_dict['sv_xy_minmax'] = [[0,1], [0,1]] nav_dict['tmp_xy'] = None # Usage o = type(str('Dummy'), (object,), {}) o.xdata = 22. o.ydata = 1. for key in nav_dict['nav']: o.key = key ltgu.navigate(nav_dict, o)
def test_navigate(): # Init nav_dict = dict(nav=ltgu.navigate(0, 0, init=True)) assert isinstance(nav_dict["nav"], list) nav_dict["x_minmax"] = [0.0, 1] nav_dict["y_minmax"] = [0.0, 1] nav_dict["sv_xy_minmax"] = [[0, 1], [0, 1]] nav_dict["tmp_xy"] = None # Usage o = type(str("Dummy"), (object,), {}) o.xdata = 22.0 o.ydata = 1.0 for key in nav_dict["nav"]: o.key = key ltgu.navigate(nav_dict, o)
def on_key(self,event): # Init rescale = True flg = 0 ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict,event) if event.key in ['b','t','W','Z','Y','l','r']: rescale = False self.on_draw(rescale=rescale)
def on_key(self, event): # Init rescale = True flg = 0 ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event) if event.key in ['b', 't', 'W', 'Z', 'Y', 'l', 'r']: rescale = False self.on_draw(rescale=rescale)
def __init__(self, spec, z, wrest, parent=None, vmnx=[-300., 300.] * u.km / u.s, norm=True, linelist=None): ''' spec = Spectrum1D ''' super(AODMWidget, self).__init__(parent) # Initialize self.spec = spec self.norm = norm self.z = z self.vmnx = vmnx self.wrest = wrest # Expecting (requires) units self.lines = [] if linelist is None: self.linelist = LineList('ISM') for iwrest in self.wrest: self.lines.append(AbsLine(iwrest, linelist=self.linelist)) self.psdict = {} # Dict for spectra plotting self.psdict[ 'x_minmax'] = self.vmnx.value # Too painful to use units here self.psdict['y_minmax'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Create the mpl Figure and FigCanvas objects. # self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw()
def init_spec(self): """ Initialize parameters for plotting the spectrum """ #xy min/max xmin = np.min(self.spec.dispersion.value) xmax = np.max(self.spec.dispersion.value) from linetools.spectra.plotting import get_flux_plotrange ymin, ymax = get_flux_plotrange(self.spec.flux.value) #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict['x_minmax'] = np.array([xmin, xmax]) self.psdict['y_minmax'] = [ymin, ymax] self.psdict['sv_xy_minmax'] = [[xmin, xmax], [ymin, ymax]] self.psdict['tmp_xy'] = None self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Analysis dict self.adict['flg'] = 0 # Column density flag
def __init__(self, spec, z, wrest, parent=None, vmnx=[-300., 300.]*u.km/u.s, norm=True, linelist=None): ''' spec = Spectrum1D ''' super(AODMWidget, self).__init__(parent) # Initialize self.spec = spec self.norm = norm self.z = z self.vmnx = vmnx self.wrest = wrest # Expecting (requires) units self.lines = [] if linelist is None: self.linelist = LineList('ISM') for iwrest in self.wrest: self.lines.append(AbsLine(iwrest,linelist=self.linelist)) self.psdict = {} # Dict for spectra plotting self.psdict['xmnx'] = self.vmnx.value # Too painful to use units here self.psdict['ymnx'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0,0,init=True) # Create the mpl Figure and FigCanvas objects. # self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw()
def on_key(self, event): """ Deals with key events Parameters ---------- event : event object """ # Flag to control re-draw flg = -1 # NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event) # DOUBLETS if event.key in ['C', 'M', 'X', '4', '8', 'B']: wave = ltgu.set_doublet(self, event) #print('wave = {:g},{:g}'.format(wave[0], wave[1])) self.ax.plot([wave[0], wave[0]], self.psdict['y_minmax'], '--', color='red') self.ax.plot([wave[1], wave[1]], self.psdict['y_minmax'], '--', color='red') flg = 2 # Layer ## SMOOTH if event.key == 'S': self.spec = self.spec.box_smooth(2) flg = 1 if event.key == 'U': self.spec = self.orig_spec flg = 1 ## Lya Profiles if event.key in ['D', 'R']: # Set NHI if event.key == 'D': NHI = 10**20.3 * u.cm**-2 elif event.key == 'R': NHI = 10**19.0 * u.cm**-2 zlya = event.xdata/1215.6701 - 1. self.llist['z'] = zlya # Generate Lya profile lya_line = AbsLine(1215.6701*u.AA) lya_line.attrib['z'] = zlya lya_line.attrib['N'] = NHI lya_line.attrib['b'] = 30. * u.km/u.s self.lya_line = ltv.voigt_from_abslines(self.spec.dispersion, lya_line, fwhm=3.) self.adict['flg'] = 4 # QtCore.pyqtRemoveInputHook() # import pdb; pdb.set_trace() # QtCore.pyqtRestoreInputHook() flg = 1 # ANALYSIS: AODM, EW, Stats, Gaussian if event.key in ['N', 'E', '$', 'G']: # If column check for line list #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if (event.key in ['N', 'E']) & (self.llist['List'] == 'None'): print('xspec: Choose a Line list first!') try: self.statusBar().showMessage('Choose a Line list first!') except AttributeError: pass self.adict['flg'] = 0 return flg = 1 if self.adict['flg'] == 0: self.adict['wv_1'] = event.xdata # wavelength self.adict['C_1'] = event.ydata # continuum self.adict['flg'] = 1 # Plot dot else: self.adict['wv_2'] = event.xdata # wavelength self.adict['C_2'] = event.ydata # continuum self.adict['flg'] = 2 # Ready to plot + print # Sort em + make arrays iwv = np.array(sorted([self.adict['wv_1'], self.adict['wv_2']])) * self.spec.wcs.unit ic = np.array(sorted([self.adict['C_1'], self.adict['C_2']])) # Calculate the continuum (linear fit) param = np.polyfit(iwv, ic, 1) cfunc = np.poly1d(param) self.spec.conti = cfunc(self.spec.dispersion) if event.key == '$': # Simple stats pix = self.spec.pix_minmax(iwv)[0] mean = np.mean(self.spec.flux[pix]) median = np.median(self.spec.flux[pix]) stdv = np.std(self.spec.flux[pix]-self.spec.conti[pix]) S2N = median / stdv mssg = 'Mean={:g}, Median={:g}, S/N={:g}'.format( mean,median,S2N) elif event.key == 'G': # Fit a Gaussian # Good pixels pix = self.spec.pix_minmax(iwv)[0] # EW EW = np.sum(self.spec.conti[pix]-self.spec.flux[pix]) if EW > 0.: # Absorption line sign=-1 else: # Emission sign=1 # Amplitude Aguess = np.max(self.spec.flux[pix]-self.spec.conti[pix]) Cguess = np.mean(self.spec.dispersion[pix]) sguess = 0.1*np.abs(self.adict['wv_1']-self.adict['wv_2']) #QtCore.pyqtRemoveInputHook() #pdb.set_trace() #QtCore.pyqtRestoreInputHook() g_init = models.Gaussian1D(amplitude=Aguess, mean=Cguess, stddev=sguess) fitter = fitting.LevMarLSQFitter() parm = fitter(g_init, self.spec.wavelength[pix].value, sign*(self.spec.flux[pix]-self.spec.conti[pix])) g_final = models.Gaussian1D(amplitude=parm.amplitude.value, mean=parm.mean.value, stddev=parm.stddev.value) # Plot model_Gauss = g_final(self.spec.dispersion.value) self.model = XSpectrum1D.from_tuple((self.spec.wavelength, self.spec.conti + sign*model_Gauss)) # Message mssg = 'Gaussian Fit: ' mssg = mssg+' :: Mean={:g}, Amplitude={:g}, sigma={:g}, flux={:g}'.format( parm.mean.value, parm.amplitude.value, parm.stddev.value, parm.stddev.value*(parm.amplitude.value-np.median(self.spec.conti[pix]))*np.sqrt(2*np.pi)) else: # Find the spectral line (or request it!) rng_wrest = iwv / (self.llist['z']+1) gdl = np.where( (self.llist[self.llist['List']].wrest-rng_wrest[0]) * (self.llist[self.llist['List']].wrest-rng_wrest[1]) < 0.)[0] if len(gdl) == 1: wrest = self.llist[self.llist['List']].wrest[gdl[0]] else: if len(gdl) == 0: # Search through them all gdl = np.arange(len(self.llist[self.llist['List']])) sel_widg = ltgl.SelectLineWidget(self.llist[self.llist['List']]._data[gdl]) sel_widg.exec_() line = sel_widg.line #wrest = float(line.split('::')[1].lstrip()) quant = line.split('::')[1].lstrip() spltw = quant.split(' ') wrest = Quantity(float(spltw[0]), unit=spltw[1]) # Units if not hasattr(wrest,'unit'): # Assume Ang wrest = wrest * u.AA # Generate the Spectral Line aline = AbsLine(wrest,linelist=self.llist[self.llist['List']]) aline.attrib['z'] = self.llist['z'] aline.analy['spec'] = self.spec # AODM if event.key == 'N': # Calculate the velocity limits and load-up aline.analy['vlim'] = const.c.to('km/s') * ( ( iwv/(1+self.llist['z']) - wrest) / wrest ) # AODM #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() aline.measure_aodm() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: logN = {:g} +/- {:g}'.format( aline.attrib['logN'], aline.attrib['sig_logN']) elif event.key == 'E': #EW aline.analy['wvlim'] = iwv aline.measure_restew() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: Rest EW = {:g} +/- {:g}'.format( aline.attrib['EW'].to(mAA), aline.attrib['sig_EW'].to(mAA)) # Display values try: self.statusBar().showMessage(mssg) except AttributeError: pass print(mssg) #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() """ ## Velocity plot if event.key == 'v': z=self.llist['z'] # Check for a match in existing list and use it if so if len(self.abs_sys) > 0: zabs = np.array([abs_sys.zabs for abs_sys in self.abs_sys]) mt = np.where( np.abs(zabs-z) < 1e-4)[0] else: mt = [] if len(mt) == 1: ini_abs_sys = self.abs_sys[mt[0]] outfil = ini_abs_sys.absid_file self.vplt_flg = 0 # Old one print('Using existing ID file {:s}'.format(outfil)) else: ini_abs_sys = None outfil = None if self.llist['List'] == 'None': print('Need to set a line list first!!') self.vplt_flg = -1 # Nothing to do here return self.vplt_flg = 1 # New one # Outfil if outfil is None: i0 = self.spec.filename.rfind('/') i1 = self.spec.filename.rfind('.') if i0 < 0: path = './ID_LINES/' else: path = self.spec.filename[0:i0]+'/ID_LINES/' outfil = path + self.spec.filename[i0+1:i1]+'_z'+'{:.4f}'.format(z)+'_id.fits' d = os.path.dirname(outfil) if not os.path.exists(d): os.mkdir(d) self.outfil = outfil #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() # Launch #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() gui = xsgui.XVelPltGui(self.spec, z=z, outfil=outfil, llist=self.llist, abs_sys=ini_abs_sys, norm=self.norm, sel_wv=self.xval*self.spec.wcs.unit) gui.exec_() if gui.flg_quit == 0: # Quit without saving (i.e. discarded) self.vplt_flg = 0 else: # Push to Abs_Sys if len(mt) == 1: self.abs_sys[mt[0]] = gui.abs_sys else: self.abs_sys.append(gui.abs_sys) print('Adding new abs system') # Redraw flg=1 """ # Dummy keys if event.key in ['shift', 'control', 'shift+super', 'super+shift']: flg = 0 # Draw if flg==1: # Default is not to redraw self.on_draw() elif flg==2: # Layer (no clear) self.on_draw(replot=False) elif flg==-1: # Layer (no clear) try: self.statusBar().showMessage('Not a valid key! {:s}'.format(event.key)) except AttributeError: pass
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 __init__(self, ispec, z, abs_lines=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.]*u.km/u.s): ''' spec : XSpectrum1D z : float abs_lines: list, optional List of AbsLines llist : LineList, optional Input line list. Defaults to 'Strong' norm : bool, optional Normalized spectrum? vmnx : Quantity array, optional Starting velocity range for the widget ''' super(VelPlotWidget, self).__init__(parent) self.help_message = """ Click on any white region within the velocity plots for the following keystroke commands to work: i,o : zoom in/out x limits I,O : zoom in/out x limits (larger re-scale) y : zoom out y limits t,b : set y top/bottom limit l,r : set left/right x limit [,] : pan left/right C,c : add/remove column K,k : add/remove row =,- : move to next/previous page 1,2 : Modify velocity region of the single line (left, right sides) !,@ : Modify velocity region of all lines (left, right) A,x : Add/remove select line from analysis list X : Remove all lines from analysis list ^,& : Flag line to be analyzed for low/high-ion kinematics B : Toggle as blend/no-blend (orange color = blend) N : Toggle as do/do-not include for analysis (red color = exclude) V : Indicate as a normal value L : Indicate as a lower limit U : Indicate as a upper limit ? : Print this """ # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs Lines if abs_lines is None: self.abs_lines = [] else: self.abs_lines = abs_lines #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict['x_minmax'] = self.vmnx.value # Too much pain to use units with this self.psdict['y_minmax'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0,0,init=True) # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots (Initial) self.sub_xy = [3,4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) # Layout vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Print help message print(self.help_message) # Draw on init self.on_draw()
def on_key(self, event): """ Deals with key events Parameters ---------- event : event object """ # Flag to control re-draw flg = -1 # Quit if event.key == 'q': self.parent.quit() return # NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event, flux=self.spec.flux.value, wave=self.spec.wavelength.value) # DOUBLETS if event.key in ['C', 'M', 'X', '4', '8', 'B']: wave, name = ltgu.set_doublet(self, event) # Lines self.ax.plot([wave[0]]*2, self.psdict['y_minmax'], '--', color='red') self.ax.plot([wave[1]]*2, self.psdict['y_minmax'], '--', color='red') # Name for wv in wave: self.ax.text(wv, self.psdict['y_minmax'][0]+0.8*( self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]), name, color='red') flg = 2 # Layer ## SMOOTH if event.key == 'S': self.spec = self.spec.box_smooth(2) flg = 1 if event.key == 'U': self.spec = self.orig_spec flg = 1 ## Lya Profiles if event.key in ['D', 'R']: # Set NHI if event.key == 'D': NHI = 10**20.3 * u.cm**-2 elif event.key == 'R': NHI = 10**19.0 * u.cm**-2 zlya = event.xdata/1215.6701 - 1. self.llist['z'] = zlya # Generate Lya profile lya_line = AbsLine(1215.6701*u.AA) lya_line.attrib['z'] = zlya lya_line.attrib['N'] = NHI lya_line.attrib['b'] = 30. * u.km/u.s lya_spec = ltv.voigt_from_abslines(self.spec.wavelength, lya_line, fwhm=3.) lconti = event.ydata self.lya_line = XSpectrum1D.from_tuple((lya_spec.wavelength, lya_spec.flux*lconti)) self.adict['flg'] = 4 # QtCore.pyqtRemoveInputHook() # import pdb; pdb.set_trace() # QtCore.pyqtRestoreInputHook() flg = 1 # ANALYSIS: AODM, EW, Stats, Gaussian if event.key in ['N', 'E', '$', 'G']: # If column check for line list #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if (event.key in ['N', 'E']) & (self.llist['List'] == 'None'): print('xspec: Choose a Line list first!') try: self.statusBar().showMessage('Choose a Line list first!') except AttributeError: pass self.adict['flg'] = 0 return flg = 1 if (self.adict['flg'] == 0) or (self.adict['flg'] > 2): self.adict['wv_1'] = event.xdata # wavelength self.adict['C_1'] = event.ydata # local continuum self.adict['flg'] = 1 # Plot dot print("Dot at x={:g}, y={:g}".format(event.xdata, event.ydata)) else: self.adict['wv_2'] = event.xdata # wavelength self.adict['C_2'] = event.ydata # local continuum self.adict['flg'] = 2 # Ready to plot + print print("Dot at x={:g}, y={:g}".format(event.xdata, event.ydata)) # Sort em + make arrays iwv = np.array(sorted([self.adict['wv_1'], self.adict['wv_2']])) * self.spec.units['wave'] ic = np.array(sorted([self.adict['C_1'], self.adict['C_2']])) # Calculate the continuum (linear fit) param = np.polyfit(iwv, ic, 1) cfunc = np.poly1d(param) lconti = cfunc(self.spec.wavelength.value) # Local continuum if event.key == '$': # Simple stats pix = self.spec.pix_minmax(iwv)[0] mean = np.mean(self.spec.flux[pix]) median = np.median(self.spec.flux[pix]) stdv = np.std(self.spec.flux[pix]-lconti[pix]) S2N = median / stdv mssg = 'Mean={:g}, Median={:g}, S/N={:g}'.format( mean,median,S2N) elif event.key == 'G': # Fit a Gaussian # Good pixels pix = self.spec.pix_minmax(iwv)[0] # EW EW = np.sum(lconti[pix]-self.spec.flux[pix]) if EW > 0.: # Absorption line sign=-1 else: # Emission sign=1 # Amplitude Aguess = np.max(self.spec.flux[pix]-lconti[pix]) Cguess = np.mean(self.spec.wavelength[pix]) sguess = 0.1*np.abs(self.adict['wv_1']-self.adict['wv_2']) # Fit g_init = models.Gaussian1D(amplitude=Aguess, mean=Cguess, stddev=sguess) fitter = fitting.LevMarLSQFitter() parm = fitter(g_init, self.spec.wavelength[pix].value, sign*(self.spec.flux[pix]-lconti[pix])) # Error var = [fitter.fit_info['param_cov'][ii,ii] for ii in range(3)] sig = np.sqrt(var) # amplitude, mean, stddev sig_dict = {g_init.param_names[0]:sig[0], g_init.param_names[1]:sig[1], g_init.param_names[2]:sig[2], } # Plot g_final = models.Gaussian1D(amplitude=parm.amplitude.value, mean=parm.mean.value, stddev=parm.stddev.value) model_Gauss = g_final(self.spec.wavelength.value) self.model = XSpectrum1D.from_tuple((self.spec.wavelength, lconti + sign*model_Gauss)) # Flux flux = parm.stddev.value*parm.amplitude.value*np.sqrt(2*np.pi) #flux = parm.stddev.value*(parm.amplitude.value-np.median(lconti[pix]))*np.sqrt(2*np.pi) sig_flux1 = np.sqrt( (sig_dict['stddev']*parm.amplitude.value*np.sqrt(2*np.pi))**2 + (parm.stddev.value*sig_dict['amplitude']*np.sqrt(2*np.pi))**2) if self.spec.sig_is_set: sig_flux2 = np.sqrt(np.sum(self.spec.sig[pix].value**2)) else: sig_flux2 = 9e9 #QtCore.pyqtRemoveInputHook() #pdb.set_trace() #QtCore.pyqtRestoreInputHook() # Message mssg = 'Gaussian Fit: ' mssg = mssg+' :: Mean={:g}, Amplitude={:g}, sigma={:g}, flux={:g}'.format( parm.mean.value, parm.amplitude.value, parm.stddev.value, flux) mssg = mssg+' :: sig(Mean)={:g}, sig(Amplitude)={:g}, sig(sigma)={:g}, sig(flux)={:g}'.format( sig_dict['mean'], sig_dict['amplitude'], sig_dict['stddev'], min(sig_flux1,sig_flux2)) else: # Find the spectral line (or request it!) rng_wrest = iwv / (self.llist['z']+1) gdl = np.where( (self.llist[self.llist['List']].wrest-rng_wrest[0]) * (self.llist[self.llist['List']].wrest-rng_wrest[1]) < 0.)[0] if len(gdl) == 1: wrest = self.llist[self.llist['List']].wrest[gdl[0]] closest = False else: if len(gdl) == 0: # Search through them all gdl = np.arange(len(self.llist[self.llist['List']])) sel_widg = ltgl.SelectLineWidget(self.llist[self.llist['List']]._data[gdl]) sel_widg.exec_() line = sel_widg.line #wrest = float(line.split('::')[1].lstrip()) quant = line.split('::')[1].lstrip() spltw = quant.split(' ') wrest = Quantity(float(spltw[0]), unit=spltw[1]) closest = True # Units if not hasattr(wrest,'unit'): # Assume Ang wrest = wrest * u.AA # Generate the Spectral Line aline = AbsLine(wrest,linelist=self.llist[self.llist['List']], z=self.llist['z'], closest=closest) # Generate a temporary spectrum for analysis and apply the local continuum tspec = XSpectrum1D.from_tuple((self.spec.wavelength, self.spec.flux, self.spec.sig)) tspec.normalize(lconti) aline.analy['spec'] = tspec # AODM if event.key == 'N': # Calculate the velocity limits and load-up aline.limits.set(const.c.to('km/s') * ( (iwv/(1+self.llist['z']) - wrest) / wrest )) # AODM #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() aline.measure_aodm() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: logN = {:g} +/- {:g}'.format( aline.attrib['logN'], aline.attrib['sig_logN']) elif event.key == 'E': #EW aline.limits.set(iwv) aline.measure_restew() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: Rest EW = {:g} +/- {:g}'.format( aline.attrib['EW'].to(mAA), aline.attrib['sig_EW'].to(mAA)) # Display values try: self.statusBar().showMessage(mssg) except AttributeError: pass print(mssg) ## Velocity plot if event.key == 'v': z=self.llist['z'] # Launch #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() abs_sys = GenericAbsSystem((0.,0.), z, (-300,300)*u.km/u.s) gui = XAbsSysGui(self.spec, abs_sys, norm=self.norm, llist=self.llist) gui.exec_() # Redraw flg=1 # Dummy keys if event.key in ['shift', 'control', 'shift+super', 'super+shift']: flg = 0 if event.key == '?': # open the XSpecGUI help page import webbrowser webbrowser.open("http://linetools.readthedocs.org/en/latest/xspecgui.html#navigating-these-key-strokes-help-you-explore-the-spectrum-be-sure-to-click-in-the-spectrum-panel-first") # Draw if flg==1: # Default is not to redraw self.on_draw() elif flg==2: # Layer (no clear) self.on_draw(replot=False) elif flg==-1: # Layer (no clear) try: self.statusBar().showMessage('Not a valid key! {:s}'.format(event.key)) except AttributeError: pass
def test_navigate(): # Init nav_dict = dict(nav=ltgu.navigate(0, 0, init=True)) assert isinstance(nav_dict['nav'], list) nav_dict['x_minmax'] = [0., 1] nav_dict['y_minmax'] = [0., 1] nav_dict['sv_xy_minmax'] = [[0, 1], [0, 1]] nav_dict['tmp_xy'] = None # Usage o = type(str('Dummy'), (object, ), {}) o.xdata = 22. o.ydata = 1. for key in nav_dict['nav']: o.key = key if key == 's': # test two options nav_dict['tmp_xy'] = [0, 0.5] # is not None ltgu.navigate(nav_dict, o) nav_dict['tmp_xy'] = None # is None again ltgu.navigate(nav_dict, o) elif key == 'y': # test two options ltgu.navigate(nav_dict, o, wave=np.linspace(0, 1, 100), flux=np.ones(100)) ltgu.navigate(nav_dict, o) else: ltgu.navigate(nav_dict, o) # test wrong key event o.xdata = 'this_is_not_float' out = ltgu.navigate(nav_dict, o) assert out == 0
def __init__(self, ispec, z=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.]*u.km/u.s, abs_sys=None): ''' spec = Spectrum1D Norm: Bool (False) Normalized spectrum? abs_sys: AbsSystem Absorption system class ''' super(VelPlotWidget, self).__init__(parent) # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs_System self.abs_sys = abs_sys if self.abs_sys is None: self.abs_sys = GenericAbsSystem((0.*u.deg,0.*u.deg), self.z, self.vmnx) self.abs_lines = [] else: self.z = self.abs_sys.zabs # Line list if llist is None: self.abs_lines = self.abs_sys.list_of_abslines() if len(self.abs_lines)>0: lwrest = [iline.wrest for iline in self.abs_lines] else: lwrest = None if lwrest is not None: llist = ltgu.set_llist(lwrest) # Not sure this is working.. #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict['xmnx'] = self.vmnx.value # Too much pain to use units with this self.psdict['ymnx'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0,0,init=True) # Status Bar? #if not status is None: # self.statusBar = status # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. # self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots self.sub_xy = [3,4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw()
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 __init__(self, ispec, z=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.] * u.km / u.s, abs_sys=None): ''' spec = Spectrum1D Norm: Bool (False) Normalized spectrum? abs_sys: AbsSystem Absorption system class ''' super(VelPlotWidget, self).__init__(parent) # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs_System self.abs_sys = abs_sys if self.abs_sys is None: self.abs_sys = GenericAbsSystem((0. * u.deg, 0. * u.deg), self.z, self.vmnx) self.abs_lines = [] else: self.z = self.abs_sys.zabs # Line list if llist is None: self.abs_lines = self.abs_sys.list_of_abslines() if len(self.abs_lines) > 0: lwrest = [iline.wrest for iline in self.abs_lines] else: lwrest = None if lwrest is not None: llist = ltgu.set_llist( lwrest) # Not sure this is working.. #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict[ 'xmnx'] = self.vmnx.value # Too much pain to use units with this self.psdict['ymnx'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Status Bar? #if not status is None: # self.statusBar = status # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. # self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots self.sub_xy = [3, 4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw()
def test_navigate(): # Init nav_dict = dict(nav=ltgu.navigate(0,0,init=True)) assert isinstance(nav_dict['nav'], list) nav_dict['x_minmax'] = [0., 1] nav_dict['y_minmax'] = [0., 1] nav_dict['sv_xy_minmax'] = [[0,1], [0,1]] nav_dict['tmp_xy'] = None # Usage o = type(str('Dummy'), (object,), {}) o.xdata = 22. o.ydata = 1. for key in nav_dict['nav']: o.key = key if key == 's': # test two options nav_dict['tmp_xy'] = [0, 0.5] # is not None ltgu.navigate(nav_dict, o) nav_dict['tmp_xy'] = None # is None again ltgu.navigate(nav_dict, o) elif key == 'y': # test two options ltgu.navigate(nav_dict, o, wave = np.linspace(0,1,100), flux = np.ones(100)) ltgu.navigate(nav_dict, o) else: ltgu.navigate(nav_dict, o) # test wrong key event o.xdata = 'this_is_not_float' out = ltgu.navigate(nav_dict, o) assert out == 0