def test_doublet(): o = type(str('Dummy'), (object,), {}) o.xdata = 5000. i = type(str('Dummy2'), (object,), {}) for key in ['C','M','4','X','8','B']: o.key = key _ = ltgu.set_doublet(i, o)
def test_doublet(): o = type(str('Dummy'), (object, ), {}) o.xdata = 5000. i = type(str('Dummy2'), (object, ), {}) for key in ['C', 'M', '4', 'X', '8', 'B']: o.key = key _ = ltgu.set_doublet(i, o)
def test_doublet(): o = type(str("Dummy"), (object,), {}) o.xdata = 5000.0 i = type(str("Dummy2"), (object,), {}) for key in ["C", "M", "4", "X", "8", "B"]: o.key = key _ = ltgu.set_doublet(i, o)
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): """ 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