Esempio n. 1
0
    def __init__(self, xcoef, ycoef, wavemin, wavemax, npix_y, xsigcoef = None, ysigcoef = None) :
        """
        Lightweight wrapper for trace coordinates and wavelength solution
        

        Args:
            xcoef: 2D[ntrace, ncoef] Legendre coefficient of x as a function of wavelength
            ycoef: 2D[ntrace, ncoef] Legendre coefficient of y as a function of wavelength
            wavemin : float 
            wavemax : float. wavemin and wavemax are used to define a reduced variable legx(wave,wavemin,wavemax)=2*(wave-wavemin)/(wavemax-wavemin)-1
        used to compute the traces, xccd=legval(legx(wave,wavemin,wavemax),xtrace[fiber])
        """
        assert(xcoef.shape[0] == ycoef.shape[0])
        if xsigcoef is not None :
            assert(xcoef.shape[0] == xsigcoef.shape[0]) 
        if ysigcoef is not None :
            assert(xcoef.shape[0] == ysigcoef.shape[0]) 
            
        self.nspec   = xcoef.shape[0]
        self.wavemin = wavemin
        self.wavemax = wavemax
        self.npix_y = npix_y
        
        self.x_vs_wave_traceset = TraceSet(xcoef,[wavemin,wavemax])
        self.y_vs_wave_traceset = TraceSet(ycoef,[wavemin,wavemax])
        
        self.xsig_vs_wave_traceset = None
        self.ysig_vs_wave_traceset = None
        
        if xsigcoef is not None :
            self.xsig_vs_wave_traceset = TraceSet(xsigcoef,[wavemin,wavemax])
        if ysigcoef is not None :
            self.ysig_vs_wave_traceset = TraceSet(ysigcoef,[wavemin,wavemax])
        
        self.wave_vs_y_traceset = None
Esempio n. 2
0
def write_psffile(infile,
                  wcoeffs,
                  wcoeffs_wavemin,
                  wcoeffs_wavemax,
                  outfile,
                  wavestepsize=None):
    """
    extract psf file, add wcoeffs, and make a new psf file preserving the traces etc.
    psf module will load this
    """

    tset = read_xytraceset(infile)

    # convert wsigma to ysig ...
    nfiber = wcoeffs.shape[0]
    ncoef = wcoeffs.shape[1]
    nw = 100  # need a larger number than ncoef to get an accurate dydw from the gradients

    # wcoeffs and tset do not necessarily have the same wavelength range
    wave = np.linspace(tset.wavemin, tset.wavemax, nw)
    wsig_set = TraceSet(wcoeffs, [wcoeffs_wavemin, wcoeffs_wavemax])
    wsig_vals = np.zeros((nfiber, nw))
    for f in range(nfiber):
        y_vals = tset.y_vs_wave(f, wave)
        dydw = np.gradient(y_vals) / np.gradient(wave)
        wsig_vals[f] = wsig_set.eval(f, wave) * dydw
    tset.ysig_vs_wave_traceset = fit_traces(wave,
                                            wsig_vals,
                                            deg=ncoef - 1,
                                            domain=(tset.wavemin,
                                                    tset.wavemax))

    write_xytraceset(outfile, tset)
Esempio n. 3
0
def write_psffile(infile,wcoeffs,wcoeffs_wavemin,wcoeffs_wavemax,outfile,wavestepsize=None):
    """
    extract psf file, add wcoeffs, and make a new psf file preserving the traces etc.
    psf module will load this
    """

    tset = read_xytraceset(infile)
    
    # convert wsigma to ysig ...
    nfiber    = wcoeffs.shape[0]
    ncoef     = wcoeffs.shape[1]
    nw        = 100 # need a larger number than ncoef to get an accurate dydw from the gradients
    
    # wcoeffs and tset do not necessarily have the same wavelength range
    wave      = np.linspace(tset.wavemin,tset.wavemax,nw)
    wsig_set  = TraceSet(wcoeffs,[wcoeffs_wavemin,wcoeffs_wavemax]) 
    wsig_vals = np.zeros((nfiber,nw))
    for f in range(nfiber) :
        y_vals = tset.y_vs_wave(f,wave)
        dydw   = np.gradient(y_vals)/np.gradient(wave)
        wsig_vals[f]=wsig_set.eval(f,wave)*dydw
    tset.ysig_vs_wave_traceset = fit_traces(wave, wsig_vals, deg=ncoef-1, domain=(tset.wavemin,tset.wavemax))
        
    write_xytraceset(outfile,tset)
Esempio n. 4
0
    def __init__(self,
                 xcoef,
                 ycoef,
                 wavemin,
                 wavemax,
                 npix_y,
                 xsigcoef=None,
                 ysigcoef=None,
                 meta=None):
        """
        Lightweight wrapper for trace coordinates and wavelength solution
        

        Args:
            xcoef: 2D[ntrace, ncoef] Legendre coefficient of x as a function of wavelength
            ycoef: 2D[ntrace, ncoef] Legendre coefficient of y as a function of wavelength
            wavemin : float 
            wavemax : float. wavemin and wavemax are used to define a reduced variable legx(wave,wavemin,wavemax)=2*(wave-wavemin)/(wavemax-wavemin)-1
        used to compute the traces, xccd=legval(legx(wave,wavemin,wavemax),xtrace[fiber])
        """
        from specter.util.traceset import TraceSet

        assert (xcoef.shape[0] == ycoef.shape[0])
        if xsigcoef is not None:
            assert (xcoef.shape[0] == xsigcoef.shape[0])
        if ysigcoef is not None:
            assert (xcoef.shape[0] == ysigcoef.shape[0])

        self.nspec = xcoef.shape[0]
        self.wavemin = wavemin
        self.wavemax = wavemax
        self.npix_y = npix_y

        self.x_vs_wave_traceset = TraceSet(xcoef, [wavemin, wavemax])
        self.y_vs_wave_traceset = TraceSet(ycoef, [wavemin, wavemax])

        self.xsig_vs_wave_traceset = None
        self.ysig_vs_wave_traceset = None

        if xsigcoef is not None:
            self.xsig_vs_wave_traceset = TraceSet(xsigcoef, [wavemin, wavemax])
        if ysigcoef is not None:
            self.ysig_vs_wave_traceset = TraceSet(ysigcoef, [wavemin, wavemax])

        self.wave_vs_y_traceset = None
        self.meta = meta
Esempio n. 5
0
def read_xytraceset(filename) :
    """
    Reads traces in PSF fits file
    
    Args:
        filename : Path to input fits file which has to contain XTRACE and YTRACE HDUs
    Returns:
         XYTraceSet object
    
    """

    log=get_logger()

    
    xcoef=None
    ycoef=None
    xsigcoef=None
    ysigcoef=None
    wsigmacoef=None
    wavemin=None
    wavemax=None
     
    log.info("reading traces in '%s'"%filename)
    
    fits_file = fits.open(filename)
    
    
    # npix_y, needed for boxcar extractions
    npix_y=0
    for hdu in [0,"XTRACE","PSF"] :
        if npix_y > 0 : break
        if hdu in fits_file : 
            head = fits_file[hdu].header
            if "NPIX_Y" in head :
                npix_y=int(head["NPIX_Y"])
    if npix_y == 0 :
        raise KeyError("Didn't find head entry NPIX_Y in hdu 0, XTRACE or PSF")
    log.info("npix_y={}".format(npix_y))
    
    try :
        psftype=fits_file[0].header["PSFTYPE"]
    except KeyError :
        psftype=""
    
    # now read trace coefficients
    log.info("psf is a '%s'"%psftype)
    if psftype == "bootcalib" :
        xcoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[0],"xcoef")
        ycoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[1],"ycoef")
    else :
        for k in ["XTRACE","XCOEF","XCOEFF"] :
            if k in fits_file :
                xcoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[k],"xcoef")
        for k in ["YTRACE","YCOEF","YCOEFF"] :
            if k in fits_file :
                ycoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[k],"ycoef")
        for k in ["XSIG"] :
            if k in fits_file :
                xsigcoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[k],"xsigcoef")
        for k in ["YSIG"] :
            if k in fits_file :
                ysigcoef,wavemin,wavemax =_traceset_from_image(wavemin,wavemax,fits_file[k],"ysigcoef")
        if "WSIGMA" in fits_file :
            wsigmacoef = fits_file["WSIGMA"].data
                
    if psftype == "GAUSS-HERMITE" : # older version where XTRACE and YTRACE are not saved in separate HDUs
        hdu=fits_file["PSF"]
        if xcoef is None    : xcoef,wavemin,wavemax =_traceset_from_table(wavemin,wavemax,hdu,"X")
        if ycoef is None    : ycoef,wavemin,wavemax =_traceset_from_table(wavemin,wavemax,hdu,"Y")
        if xsigcoef is None : xsigcoef,wavemin,wavemax =_traceset_from_table(wavemin,wavemax,hdu,"GHSIGX")
        if ysigcoef is None : ysigcoef,wavemin,wavemax =_traceset_from_table(wavemin,wavemax,hdu,"GHSIGY")
    
    log.info("wavemin={} wavemax={}".format(wavemin,wavemax))
    
    if xcoef is None or ycoef is None :
        raise ValueError("could not find xcoef and ycoef in psf file %s"%filename)
    
    if xcoef.shape[0] != ycoef.shape[0] :
        raise ValueError("XCOEF and YCOEF don't have same number of fibers %d %d"%(xcoef.shape[0],ycoef.shape[0]))
    
    fits_file.close()
    
    if wsigmacoef is not None :
        log.warning("Converting deprecated WSIGMA coefficents (in Ang.) into YSIG (in CCD pixels)")
        nfiber    = wsigmacoef.shape[0]
        ncoef     = wsigmacoef.shape[1]
        nw = 100 # to get accurate dydw
        wave      = np.linspace(wavemin,wavemax,nw)
        wsig_set  = TraceSet(wsigmacoef,[wavemin,wavemax])
        y_set  = TraceSet(ycoef,[wavemin,wavemax])
        wsig_vals = np.zeros((nfiber,nw))
        for f in range(nfiber) :
            y_vals = y_set.eval(f,wave)
            dydw   = np.gradient(y_vals)/np.gradient(wave)
            wsig_vals[f]=wsig_set.eval(f,wave)*dydw
        tset = fit_traces(wave, wsig_vals, deg=ncoef-1, domain=(wavemin,wavemax))
        ysigcoef = tset._coeff
        
    return XYTraceSet(xcoef,ycoef,wavemin,wavemax,npix_y,xsigcoef=xsigcoef,ysigcoef=ysigcoef)
Esempio n. 6
0
def process_arc(qframe, xytraceset, linelist=None, npoly=2, nbins=2):
    """
    qframe: desispec.qframe.QFrame object
    xytraceset : desispec.xytraceset.XYTraceSet object
    linelist: line list to fit
    npoly: polynomial order for sigma expansion
    nbins: no of bins for the half of the fitting window
    return: xytraceset (with ysig vs wave)
    """

    log = get_logger()

    if linelist is None:

        if qframe.meta is None or "CAMERA" not in qframe.meta:
            log.error(
                "no information about camera in qframe so I don't know which lines to use"
            )
            raise RuntimeError(
                "no information about camera in qframe so I don't know which lines to use"
            )

        camera = qframe.meta["CAMERA"]
        #- load arc lines
        from desispec.bootcalib import load_arcline_list, load_gdarc_lines, find_arc_lines
        llist = load_arcline_list(camera)
        dlamb, gd_lines = load_gdarc_lines(camera, llist)
        linelist = gd_lines
        log.info(
            "No line list configured. Fitting for lines {}".format(linelist))

    tset = xytraceset

    assert (qframe.nspec == tset.nspec)

    tset.ysig_vs_wave_traceset = TraceSet(np.zeros((tset.nspec, npoly + 1)),
                                          [tset.wavemin, tset.wavemax])

    for spec in range(tset.nspec):
        spec_wave = qframe.wave[spec]
        spec_linelist = linelist[(linelist > spec_wave[0])
                                 & (linelist < spec_wave[-1])]
        meanwaves, emeanwaves, sigmas, esigmas = sigmas_from_arc(
            spec_wave,
            qframe.flux[spec],
            qframe.ivar[spec],
            spec_linelist,
            n=nbins)

        # convert from wavelength A unit to CCD pixel for consistency with specex PSF
        y = tset.y_vs_wave(spec, spec_wave)
        dydw = np.interp(meanwaves, spec_wave,
                         np.gradient(y) / np.gradient(spec_wave))
        sigmas *= dydw  # A -> pixels
        esigmas *= dydw  # A -> pixels

        ok = (sigmas > 0) & (esigmas > 0)

        try:
            thislegfit = Legendre.fit(meanwaves[ok],
                                      sigmas[ok],
                                      npoly,
                                      domain=[tset.wavemin, tset.wavemax],
                                      w=1. / esigmas[ok]**2)
            tset.ysig_vs_wave_traceset._coeff[spec] = thislegfit.coef
        except:
            log.error("legfit of psf width failed for spec {}".format(spec))

        wave = np.linspace(tset.wavemin, tset.wavemax, 20)
        #plt.plot(wave,tset.ysig_vs_wave(spec,wave))

    #plt.show()
    return xytraceset
Esempio n. 7
0
def read_xytraceset(filename):
    """
    Reads traces in PSF fits file
    
    Args:
        filename : Path to input fits file which has to contain XTRACE and YTRACE HDUs
    Returns:
         XYTraceSet object
    
    """
    #- specter import isolated within function so specter only loaded if
    #- really needed
    from specter.util.traceset import TraceSet, fit_traces

    log = get_logger()

    xcoef = None
    ycoef = None
    xsigcoef = None
    ysigcoef = None
    wsigmacoef = None
    wavemin = None
    wavemax = None

    log.info("reading traces in '%s'" % filename)

    fits_file = fits.open(filename)

    # npix_y, needed for boxcar extractions
    npix_y = 0
    for hdu in [0, "XTRACE", "PSF"]:
        if npix_y > 0: break
        if hdu in fits_file:
            head = fits_file[hdu].header
            if "NPIX_Y" in head:
                npix_y = int(head["NPIX_Y"])
    if npix_y == 0:
        raise KeyError("Didn't find head entry NPIX_Y in hdu 0, XTRACE or PSF")
    log.debug("npix_y={}".format(npix_y))

    try:
        psftype = fits_file[0].header["PSFTYPE"]
    except KeyError:
        psftype = ""

    # now read trace coefficients
    log.debug("psf is a '%s'" % psftype)
    if psftype == "bootcalib":
        xcoef, wavemin, wavemax = _traceset_from_image(wavemin, wavemax,
                                                       fits_file[0], "xcoef")
        ycoef, wavemin, wavemax = _traceset_from_image(wavemin, wavemax,
                                                       fits_file[1], "ycoef")
    else:
        for k in ["XTRACE", "XCOEF", "XCOEFF"]:
            if k in fits_file:
                xcoef, wavemin, wavemax = _traceset_from_image(
                    wavemin, wavemax, fits_file[k], "xcoef")
        for k in ["YTRACE", "YCOEF", "YCOEFF"]:
            if k in fits_file:
                ycoef, wavemin, wavemax = _traceset_from_image(
                    wavemin, wavemax, fits_file[k], "ycoef")
        for k in ["XSIG"]:
            if k in fits_file:
                xsigcoef, wavemin, wavemax = _traceset_from_image(
                    wavemin, wavemax, fits_file[k], "xsigcoef")
        for k in ["YSIG"]:
            if k in fits_file:
                ysigcoef, wavemin, wavemax = _traceset_from_image(
                    wavemin, wavemax, fits_file[k], "ysigcoef")
        if "WSIGMA" in fits_file:
            wsigmacoef = fits_file["WSIGMA"].data

    if psftype == "GAUSS-HERMITE":  # older version where XTRACE and YTRACE are not saved in separate HDUs
        hdu = fits_file["PSF"]
        if xcoef is None:
            xcoef, wavemin, wavemax = _traceset_from_table(
                wavemin, wavemax, hdu, "X")
        if ycoef is None:
            ycoef, wavemin, wavemax = _traceset_from_table(
                wavemin, wavemax, hdu, "Y")
        if xsigcoef is None:
            xsigcoef, wavemin, wavemax = _traceset_from_table(
                wavemin, wavemax, hdu, "GHSIGX")
        if ysigcoef is None:
            ysigcoef, wavemin, wavemax = _traceset_from_table(
                wavemin, wavemax, hdu, "GHSIGY")

    log.debug("wavemin={} wavemax={}".format(wavemin, wavemax))

    if xcoef is None or ycoef is None:
        raise ValueError("could not find xcoef and ycoef in psf file %s" %
                         filename)

    if xcoef.shape[0] != ycoef.shape[0]:
        raise ValueError(
            "XCOEF and YCOEF don't have same number of fibers %d %d" %
            (xcoef.shape[0], ycoef.shape[0]))

    fits_file.close()

    if wsigmacoef is not None:
        log.warning(
            "Converting deprecated WSIGMA coefficents (in Ang.) into YSIG (in CCD pixels)"
        )
        nfiber = wsigmacoef.shape[0]
        ncoef = wsigmacoef.shape[1]
        nw = 100  # to get accurate dydw
        wave = np.linspace(wavemin, wavemax, nw)
        wsig_set = TraceSet(wsigmacoef, [wavemin, wavemax])
        y_set = TraceSet(ycoef, [wavemin, wavemax])
        wsig_vals = np.zeros((nfiber, nw))
        for f in range(nfiber):
            y_vals = y_set.eval(f, wave)
            dydw = np.gradient(y_vals) / np.gradient(wave)
            wsig_vals[f] = wsig_set.eval(f, wave) * dydw
        tset = fit_traces(wave,
                          wsig_vals,
                          deg=ncoef - 1,
                          domain=(wavemin, wavemax))
        ysigcoef = tset._coeff

    return XYTraceSet(xcoef,
                      ycoef,
                      wavemin,
                      wavemax,
                      npix_y,
                      xsigcoef=xsigcoef,
                      ysigcoef=ysigcoef)
Esempio n. 8
0
class XYTraceSet(object):
    def __init__(self, xcoef, ycoef, wavemin, wavemax, npix_y, xsigcoef = None, ysigcoef = None) :
        """
        Lightweight wrapper for trace coordinates and wavelength solution
        

        Args:
            xcoef: 2D[ntrace, ncoef] Legendre coefficient of x as a function of wavelength
            ycoef: 2D[ntrace, ncoef] Legendre coefficient of y as a function of wavelength
            wavemin : float 
            wavemax : float. wavemin and wavemax are used to define a reduced variable legx(wave,wavemin,wavemax)=2*(wave-wavemin)/(wavemax-wavemin)-1
        used to compute the traces, xccd=legval(legx(wave,wavemin,wavemax),xtrace[fiber])
        """
        assert(xcoef.shape[0] == ycoef.shape[0])
        if xsigcoef is not None :
            assert(xcoef.shape[0] == xsigcoef.shape[0]) 
        if ysigcoef is not None :
            assert(xcoef.shape[0] == ysigcoef.shape[0]) 
            
        self.nspec   = xcoef.shape[0]
        self.wavemin = wavemin
        self.wavemax = wavemax
        self.npix_y = npix_y
        
        self.x_vs_wave_traceset = TraceSet(xcoef,[wavemin,wavemax])
        self.y_vs_wave_traceset = TraceSet(ycoef,[wavemin,wavemax])
        
        self.xsig_vs_wave_traceset = None
        self.ysig_vs_wave_traceset = None
        
        if xsigcoef is not None :
            self.xsig_vs_wave_traceset = TraceSet(xsigcoef,[wavemin,wavemax])
        if ysigcoef is not None :
            self.ysig_vs_wave_traceset = TraceSet(ysigcoef,[wavemin,wavemax])
        
        self.wave_vs_y_traceset = None
            
    def x_vs_wave(self,fiber,wavelength) :
        return self.x_vs_wave_traceset.eval(fiber,wavelength)
    
    def y_vs_wave(self,fiber,wavelength) :
        return self.y_vs_wave_traceset.eval(fiber,wavelength)
    
    def xsig_vs_wave(self,fiber,wavelength) :
        if self.xsig_vs_wave_traceset is None :
            raise RuntimeError("no xsig coefficents were read in the PSF")
        
        return self.xsig_vs_wave_traceset.eval(fiber,wavelength)
    
    def ysig_vs_wave(self,fiber,wavelength) :
        if self.ysig_vs_wave_traceset is None :
            raise RuntimeError("no ysig coefficents were read in the PSF")
            
        return self.ysig_vs_wave_traceset.eval(fiber,wavelength)
    
    def wave_vs_y(self,fiber,y) :
        if self.wave_vs_y_traceset is None :
            self.wave_vs_y_traceset = self.y_vs_wave_traceset.invert()
        return self.wave_vs_y_traceset.eval(fiber,y)
    
    def x_vs_y(self,fiber,y) :
        return self.x_vs_wave(fiber,self.wave_vs_y(fiber,y))

    def xsig_vs_y(self,fiber,y) :
        return self.xsig_vs_wave(fiber,self.wave_vs_y(fiber,y))
    
    def ysig_vs_y(self,fiber,y) :
        return self.ysig_vs_wave(fiber,self.wave_vs_y(fiber,y))
    
    """
Esempio n. 9
0
class XYTraceSet(object):
    def __init__(self, xcoef, ycoef, wavemin, wavemax, npix_y, xsigcoef = None, ysigcoef = None, meta = None) :
        """
        Lightweight wrapper for trace coordinates and wavelength solution
        

        Args:
            xcoef: 2D[ntrace, ncoef] Legendre coefficient of x as a function of wavelength
            ycoef: 2D[ntrace, ncoef] Legendre coefficient of y as a function of wavelength
            wavemin : float 
            wavemax : float. wavemin and wavemax are used to define a reduced variable legx(wave,wavemin,wavemax)=2*(wave-wavemin)/(wavemax-wavemin)-1
        used to compute the traces, xccd=legval(legx(wave,wavemin,wavemax),xtrace[fiber])
        """
        assert(xcoef.shape[0] == ycoef.shape[0])
        if xsigcoef is not None :
            assert(xcoef.shape[0] == xsigcoef.shape[0]) 
        if ysigcoef is not None :
            assert(xcoef.shape[0] == ysigcoef.shape[0]) 
            
        self.nspec   = xcoef.shape[0]
        self.wavemin = wavemin
        self.wavemax = wavemax
        self.npix_y = npix_y
        
        self.x_vs_wave_traceset = TraceSet(xcoef,[wavemin,wavemax])
        self.y_vs_wave_traceset = TraceSet(ycoef,[wavemin,wavemax])
        
        self.xsig_vs_wave_traceset = None
        self.ysig_vs_wave_traceset = None
        
        if xsigcoef is not None :
            self.xsig_vs_wave_traceset = TraceSet(xsigcoef,[wavemin,wavemax])
        if ysigcoef is not None :
            self.ysig_vs_wave_traceset = TraceSet(ysigcoef,[wavemin,wavemax])
        
        self.wave_vs_y_traceset = None
        self.meta = meta

    def x_vs_wave(self,fiber,wavelength) :
        return self.x_vs_wave_traceset.eval(fiber,wavelength)
    
    def y_vs_wave(self,fiber,wavelength) :
        return self.y_vs_wave_traceset.eval(fiber,wavelength)
    
    def xsig_vs_wave(self,fiber,wavelength) :
        if self.xsig_vs_wave_traceset is None :
            raise RuntimeError("no xsig coefficents were read in the PSF")
        
        return self.xsig_vs_wave_traceset.eval(fiber,wavelength)
    
    def ysig_vs_wave(self,fiber,wavelength) :
        if self.ysig_vs_wave_traceset is None :
            raise RuntimeError("no ysig coefficents were read in the PSF")
            
        return self.ysig_vs_wave_traceset.eval(fiber,wavelength)
    
    def wave_vs_y(self,fiber,y) :
        if self.wave_vs_y_traceset is None :
            self.wave_vs_y_traceset = self.y_vs_wave_traceset.invert()
        return self.wave_vs_y_traceset.eval(fiber,y)
    
    def x_vs_y(self,fiber,y) :
        return self.x_vs_wave(fiber,self.wave_vs_y(fiber,y))

    def xsig_vs_y(self,fiber,y) :
        return self.xsig_vs_wave(fiber,self.wave_vs_y(fiber,y))
    
    def ysig_vs_y(self,fiber,y) :
        return self.ysig_vs_wave(fiber,self.wave_vs_y(fiber,y))
    
    """