예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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()
예제 #6
0
 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
예제 #7
0
    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()
예제 #8
0
    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
예제 #9
0
    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)
예제 #10
0
    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()
예제 #11
0
    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
예제 #12
0
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
예제 #13
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()
예제 #14
0
    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)
예제 #15
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()
예제 #16
0
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