Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
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
Exemplo n.º 5
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