Exemple #1
0
    def test_compare_specter(self):
        #- specter version
        psf = specter.psf.load_psf(self.psffile)

        for ispec in np.linspace(0, 499, 20).astype(int):
            spots, corners, psfparams = get_spots(ispec, 1, self.wavelengths,
                                                  self.psfdata)
            xc, yc = corners

            ny, nx = spots.shape[2:4]

            for iwave, w in enumerate(self.wavelengths):
                xslice, yslice, pix = psf.xypix(ispec, w)

                self.assertEqual(pix.shape, (ny, nx))
                self.assertEqual(xc[0, iwave], xslice.start)
                self.assertEqual(yc[0, iwave], yslice.start)
                self.assertTrue(np.allclose(spots[0, iwave], pix))
Exemple #2
0
def compute_fiber_bundle_trace_shifts_using_psf(fibers,
                                                line,
                                                psf,
                                                image,
                                                maxshift=2.):
    """
    Computes trace shifts along x and y from a preprocessed image, a PSF (with trace coords), and a given emission line,
    by doing a forward model of the image.

    Args:
        fibers : 1D array with list of fibers
        line : float, wavelength of an emission line (in Angstrom)
        psf  : specter psf object
        image : DESI preprocessed image object

    Optional:
        maxshift : float maximum shift in pixels for 2D chi2 scan

    Returns:
        x  : 1D array of x coordinates on CCD (axis=1 in numpy image array, AXIS=0 in FITS, cross-dispersion axis = fiber number direction)
        y  : 1D array of y coordinates on CCD (axis=0 in numpy image array, AXIS=1 in FITS, wavelength dispersion axis)
        dx : 1D array of shifts along x coordinates on CCD
        dy : 1D array of shifts along y coordinates on CCD
        sx : 1D array of uncertainties on dx
        sy : 1D array of uncertainties on dy
    """
    log = get_logger()
    #log.info("compute_fiber_bundle_offsets fibers={} line={}".format(fibers,line))

    # get central coordinates of bundle for interpolation of offsets on CCD
    x, y = psf.xy([
        int(np.median(fibers)),
    ], line)

    try:
        nfibers = len(fibers)

        # compute stamp coordinates
        xstart = None
        xstop = None
        ystart = None
        ystop = None
        xs = []
        ys = []
        pix = []
        xx = []
        yy = []

        for fiber in fibers:
            txs, tys, tpix = psf.xypix(fiber, line)
            xs.append(txs)
            ys.append(tys)
            pix.append(tpix)
            if xstart is None:
                xstart = txs.start
                xstop = txs.stop
                ystart = tys.start
                ystop = tys.stop
            else:
                xstart = min(xstart, txs.start)
                xstop = max(xstop, txs.stop)
                ystart = min(ystart, tys.start)
                ystop = max(ystop, tys.stop)

        # load stamp data, with margins to avoid problems with shifted psf
        margin = int(maxshift) + 1
        stamp = np.zeros(
            (ystop - ystart + 2 * margin, xstop - xstart + 2 * margin))
        stampivar = np.zeros(stamp.shape)
        stamp[margin:-margin, margin:-margin] = image.pix[ystart:ystop,
                                                          xstart:xstop]
        stampivar[margin:-margin, margin:-margin] = image.ivar[ystart:ystop,
                                                               xstart:xstop]

        # will use a fixed footprint despite changes of psf stamps
        # so that chi2 always based on same data set
        footprint = np.zeros(stamp.shape)
        for i in range(nfibers):
            footprint[margin - ystart + ys[i].start:margin - ystart +
                      ys[i].stop, margin - xstart + xs[i].start:margin -
                      xstart + xs[i].stop] = 1

        #plt.imshow(footprint) ; plt.show() ; sys.exit(12)

        # define grid of shifts to test
        res = 0.5
        nshift = int(maxshift / res)
        dx = res * np.tile(
            np.arange(2 * nshift + 1) - nshift, (2 * nshift + 1, 1))
        dy = dx.T
        original_shape = dx.shape
        dx = dx.ravel()
        dy = dy.ravel()
        chi2 = np.zeros(dx.shape)

        A = np.zeros((nfibers, nfibers))
        B = np.zeros((nfibers))
        mods = np.zeros(np.zeros(nfibers).shape + stamp.shape)

        debugging = False

        if debugging:  # FOR DEBUGGING KEEP MODELS
            models = []

        # loop on possible shifts
        # refit fluxes and compute chi2
        for d in range(len(dx)):
            # print(d,dx[d],dy[d])
            A *= 0
            B *= 0
            mods *= 0

            for i, fiber in enumerate(fibers):

                # apply the PSF shift
                psf._cache = {}  # reset cache !!
                psf.coeff['X']._coeff[fiber][0] += dx[d]
                psf.coeff['Y']._coeff[fiber][0] += dy[d]

                # compute pix and paste on stamp frame
                xx, yy, pix = psf.xypix(fiber, line)
                mods[i][margin - ystart + yy.start:margin - ystart + yy.stop,
                        margin - xstart + xx.start:margin - xstart +
                        xx.stop] = pix

                # undo the PSF shift
                psf.coeff['X']._coeff[fiber][0] -= dx[d]
                psf.coeff['Y']._coeff[fiber][0] -= dy[d]

                B[i] = np.sum(stampivar * stamp * mods[i])
                for j in range(i + 1):
                    A[i, j] = np.sum(stampivar * mods[i] * mods[j])
                    if j != i:
                        A[j, i] = A[i, j]
            Ai = np.linalg.inv(A)
            flux = Ai.dot(B)
            model = np.zeros(stamp.shape)
            for i in range(nfibers):
                model += flux[i] * mods[i]
            chi2[d] = np.sum(stampivar * (stamp - model)**2)
            if debugging:
                models.append(model)

        if debugging:
            schi2 = chi2.reshape(original_shape).copy()  # FOR DEBUGGING
            sdx = dx.copy()
            sdy = dy.copy()

        # find minimum chi2 grid point
        k = chi2.argmin()
        j, i = np.unravel_index(k, ((2 * nshift + 1), (2 * nshift + 1)))
        #print("node dx,dy=",dx.reshape(original_shape)[j,i],dy.reshape(original_shape)[j,i])

        # cut a region around minimum
        delta = 1
        istart = max(0, i - delta)
        istop = min(2 * nshift + 1, i + delta + 1)
        jstart = max(0, j - delta)
        jstop = min(2 * nshift + 1, j + delta + 1)
        chi2 = chi2.reshape(original_shape)[jstart:jstop, istart:istop].ravel()
        dx = dx.reshape(original_shape)[jstart:jstop, istart:istop].ravel()
        dy = dy.reshape(original_shape)[jstart:jstop, istart:istop].ravel()
        # fit 2D polynomial of deg2
        m = np.array([dx * 0 + 1, dx, dy, dx**2, dy**2, dx * dy]).T
        c, r, rank, s = np.linalg.lstsq(m, chi2)
        if c[3] > 0 and c[4] > 0:
            # get minimum
            # dchi2/dx=0 : c[1]+2*c[3]*dx+c[5]*dy = 0
            # dchi2/dy=0 : c[2]+2*c[4]*dy+c[5]*dx = 0
            a = np.array([[2 * c[3], c[5]], [c[5], 2 * c[4]]])
            b = np.array([c[1], c[2]])
            t = -np.linalg.inv(a).dot(b)
            dx = t[0]
            dy = t[1]
            sx = 1. / np.sqrt(c[3])
            sy = 1. / np.sqrt(c[4])
            #print("interp dx,dy=",dx,dy)

            if debugging:  # FOR DEBUGGING
                import matplotlib.pyplot as plt
                plt.figure()
                plt.subplot(2, 2, 1, title="chi2")
                plt.imshow(schi2,
                           extent=(-nshift * res, nshift * res, -nshift * res,
                                   nshift * res),
                           origin=0,
                           interpolation="nearest")
                plt.plot(dx, dy, "+", color="white", ms=20)
                plt.xlabel("x")
                plt.ylabel("y")
                plt.subplot(2, 2, 2, title="data")
                plt.imshow(stamp * footprint,
                           origin=0,
                           interpolation="nearest")
                plt.grid()
                k0 = np.argmin(sdx**2 + sdy**2)
                plt.subplot(2, 2, 3, title="original psf")
                plt.imshow(models[k0], origin=0, interpolation="nearest")
                plt.grid()
                plt.subplot(2, 2, 4, title="shifted psf")
                plt.imshow(models[k], origin=0, interpolation="nearest")
                plt.grid()
                plt.show()

        else:
            log.warning(
                "fit failed (bad chi2 surf.) for fibers [%d:%d] line=%dA" %
                (fibers[0], fibers[-1] + 1, int(line)))
            dx = 0.
            dy = 0.
            sx = 10.
            sy = 10.
    except LinAlgError:
        log.warning(
            "fit failed (masked or missing data) for fibers [%d:%d] line=%dA" %
            (fibers[0], fibers[-1] + 1, int(line)))
        dx = 0.
        dy = 0.
        sx = 10.
        sy = 10.

    return x, y, dx, dy, sx, sy
    elif cam == "z": camid = 2

    expnum = int(os.path.basename(filename).split("-")[2].replace(".fits", ""))

    for fiber in fibers:

        tx = psf.x(fiber, args.wave)
        ty = psf.y(fiber, args.wave)
        dtx = tx - reftx[fiber]
        dty = ty - refty[fiber]

        psf._cache = {}  # reset cache !!
        psf.coeff['X']._coeff[fiber][0] -= dtx
        psf.coeff['Y']._coeff[fiber][0] -= dty

        xx, yy, img = psf.xypix(fiber, args.wave)
        cx = np.sum(xpix * img) / np.sum(img)
        cy = np.sum(ypix * img) / np.sum(img)
        sx = np.sqrt(np.sum((xpix - cx)**2 * img) / np.sum(img))
        sy = np.sqrt(np.sum((ypix - cy)**2 * img) / np.sum(img))
        ebias = np.sum(refimage[fiber] * img) / np.sum(img**2) - 1.

        line = "%d %d %d %d" % (expnum, camid, fiber, args.wave)
        line += " %f %f %f %f %f %f %f" % (dtx, dty, cx, cy, sx, sy, ebias)

        #print(line)
        sys.stdout.flush()
        ofile.write("%s\n" % line)

    ofile.close()
Exemple #4
0
def compute_fiber_bundle_trace_shifts_using_psf(fibers,line,psf,image,maxshift=2.) :
    """
    Computes trace shifts along x and y from a preprocessed image, a PSF (with trace coords), and a given emission line,
    by doing a forward model of the image.

    Args:
        fibers : 1D array with list of fibers
        line : float, wavelength of an emission line (in Angstrom)
        psf  : specter psf object
        image : DESI preprocessed image object

    Optional:
        maxshift : float maximum shift in pixels for 2D chi2 scan

    Returns:
        x  : 1D array of x coordinates on CCD (axis=1 in numpy image array, AXIS=0 in FITS, cross-dispersion axis = fiber number direction)
        y  : 1D array of y coordinates on CCD (axis=0 in numpy image array, AXIS=1 in FITS, wavelength dispersion axis)
        dx : 1D array of shifts along x coordinates on CCD
        dy : 1D array of shifts along y coordinates on CCD
        sx : 1D array of uncertainties on dx
        sy : 1D array of uncertainties on dy
    """
    log=get_logger()
    #log.info("compute_fiber_bundle_offsets fibers={} line={}".format(fibers,line))

    # get central coordinates of bundle for interpolation of offsets on CCD
    x,y = psf.xy([int(np.median(fibers)),],line)


    try :
        nfibers=len(fibers)

        # compute stamp coordinates
        xstart=None
        xstop=None
        ystart=None
        ystop=None
        xs=[]
        ys=[]
        pix=[]
        xx=[]
        yy=[]

        for fiber in fibers :
            txs,tys,tpix = psf.xypix(fiber,line)
            xs.append(txs)
            ys.append(tys)
            pix.append(tpix)
            if xstart is None :
                xstart =txs.start
                xstop  =txs.stop
                ystart =tys.start
                ystop  =tys.stop
            else :
                xstart =min(xstart,txs.start)
                xstop  =max(xstop,txs.stop)
                ystart =min(ystart,tys.start)
                ystop  =max(ystop,tys.stop)

        # load stamp data, with margins to avoid problems with shifted psf
        margin=int(maxshift)+1
        stamp=np.zeros((ystop-ystart+2*margin,xstop-xstart+2*margin))
        stampivar=np.zeros(stamp.shape)
        stamp[margin:-margin,margin:-margin]=image.pix[ystart:ystop,xstart:xstop]
        stampivar[margin:-margin,margin:-margin]=image.ivar[ystart:ystop,xstart:xstop]


        # will use a fixed footprint despite changes of psf stamps
        # so that chi2 always based on same data set
        footprint=np.zeros(stamp.shape)
        for i in range(nfibers) :
            footprint[margin-ystart+ys[i].start:margin-ystart+ys[i].stop,margin-xstart+xs[i].start:margin-xstart+xs[i].stop]=1

        #plt.imshow(footprint) ; plt.show() ; sys.exit(12)

        # define grid of shifts to test
        res=0.5
        nshift=int(maxshift/res)
        dx=res*np.tile(np.arange(2*nshift+1)-nshift,(2*nshift+1,1))
        dy=dx.T
        original_shape=dx.shape
        dx=dx.ravel()
        dy=dy.ravel()
        chi2=np.zeros(dx.shape)

        A=np.zeros((nfibers,nfibers))
        B=np.zeros((nfibers))
        mods=np.zeros(np.zeros(nfibers).shape+stamp.shape)

        debugging=False

        if debugging : # FOR DEBUGGING KEEP MODELS
            models=[]


        # loop on possible shifts
        # refit fluxes and compute chi2
        for d in range(len(dx)) :
            # print(d,dx[d],dy[d])
            A *= 0
            B *= 0
            mods *= 0

            for i,fiber in enumerate(fibers) :

                # apply the PSF shift
                psf._cache={} # reset cache !!
                psf.coeff['X']._coeff[fiber][0] += dx[d]
                psf.coeff['Y']._coeff[fiber][0] += dy[d]

                # compute pix and paste on stamp frame
                xx, yy, pix = psf.xypix(fiber,line)
                mods[i][margin-ystart+yy.start:margin-ystart+yy.stop,margin-xstart+xx.start:margin-xstart+xx.stop]=pix

                # undo the PSF shift
                psf.coeff['X']._coeff[fiber][0] -= dx[d]
                psf.coeff['Y']._coeff[fiber][0] -= dy[d]

                B[i] = np.sum(stampivar*stamp*mods[i])
                for j in range(i+1) :
                    A[i,j] = np.sum(stampivar*mods[i]*mods[j])
                    if j!=i :
                        A[j,i] = A[i,j]
            Ai=np.linalg.inv(A)
            flux=Ai.dot(B)
            model=np.zeros(stamp.shape)
            for i in range(nfibers) :
                model += flux[i]*mods[i]
            chi2[d]=np.sum(stampivar*(stamp-model)**2)
            if debugging :
                models.append(model)

        if debugging :
            schi2=chi2.reshape(original_shape).copy() # FOR DEBUGGING
            sdx=dx.copy()
            sdy=dy.copy()

        # find minimum chi2 grid point
        k   = chi2.argmin()
        j,i = np.unravel_index(k, ((2*nshift+1),(2*nshift+1)))
        #print("node dx,dy=",dx.reshape(original_shape)[j,i],dy.reshape(original_shape)[j,i])

        # cut a region around minimum
        delta=1
        istart=max(0,i-delta)
        istop=min(2*nshift+1,i+delta+1)
        jstart=max(0,j-delta)
        jstop=min(2*nshift+1,j+delta+1)
        chi2=chi2.reshape(original_shape)[jstart:jstop,istart:istop].ravel()
        dx=dx.reshape(original_shape)[jstart:jstop,istart:istop].ravel()
        dy=dy.reshape(original_shape)[jstart:jstop,istart:istop].ravel()
        # fit 2D polynomial of deg2
        m = np.array([dx*0+1, dx, dy, dx**2, dy**2, dx*dy ]).T
        c, r, rank, s = np.linalg.lstsq(m, chi2)
        if c[3]>0 and c[4]>0 :
            # get minimum
            # dchi2/dx=0 : c[1]+2*c[3]*dx+c[5]*dy = 0
            # dchi2/dy=0 : c[2]+2*c[4]*dy+c[5]*dx = 0
            a=np.array([[2*c[3],c[5]],[c[5],2*c[4]]])
            b=np.array([c[1],c[2]])
            t=-np.linalg.inv(a).dot(b)
            dx=t[0]
            dy=t[1]
            sx=1./np.sqrt(c[3])
            sy=1./np.sqrt(c[4])
            #print("interp dx,dy=",dx,dy)

            if debugging : # FOR DEBUGGING
                import matplotlib.pyplot as plt
                plt.figure()
                plt.subplot(2,2,1,title="chi2")
                plt.imshow(schi2,extent=(-nshift*res,nshift*res,-nshift*res,nshift*res),origin=0,interpolation="nearest")
                plt.plot(dx,dy,"+",color="white",ms=20)
                plt.xlabel("x")
                plt.ylabel("y")
                plt.subplot(2,2,2,title="data")
                plt.imshow(stamp*footprint,origin=0,interpolation="nearest")
                plt.grid()
                k0=np.argmin(sdx**2+sdy**2)
                plt.subplot(2,2,3,title="original psf")
                plt.imshow(models[k0],origin=0,interpolation="nearest")
                plt.grid()
                plt.subplot(2,2,4,title="shifted psf")
                plt.imshow(models[k],origin=0,interpolation="nearest")
                plt.grid()
                plt.show()

        else :
            log.warning("fit failed (bad chi2 surf.) for fibers [%d:%d] line=%dA"%(fibers[0],fibers[-1]+1,int(line)))
            dx=0.
            dy=0.
            sx=10.
            sy=10.
    except LinAlgError :
        log.warning("fit failed (masked or missing data) for fibers [%d:%d] line=%dA"%(fibers[0],fibers[-1]+1,int(line)))
        dx=0.
        dy=0.
        sx=10.
        sy=10.

    return x,y,dx,dy,sx,sy
res_fiber=[]
res_wave=[]
res_x_rms=[]
res_y_rms=[]

use_trace = True

for fiber in fibers :
    for wave in waves :
        images = []
        i0 = []
        i1 = []
        xc = []
        yc = []
        for psf in psfs :
            xx, yy, ccdpix = psf.xypix(fiber,wave)
            xc.append(psf.x(fiber,wave))
            yc.append(psf.y(fiber,wave))
            #print("fiber,wave",fiber,wave)
            #print("xx",xx)
            #print("yy",yy)
            
            #plt.imshow(ccdpix)
            #plt.show()


            
            images.append(ccdpix)
            i1.append(xx.start)
            i0.append(yy.start)
        
                    default=None,
                    required=False,
                    help='path to output image (png) file')

args = parser.parse_args()

psf = specter.psf.GaussHermitePSF(args.psf)
wave = np.linspace(psf.wmin + 200, psf.wmax - 200, 15)

zoom = 18
image = np.zeros((psf.npix_y / zoom, psf.npix_x / zoom))
for fiber in range(psf.nspec):
    for wavelength in wave:
        print(fiber, wavelength)
        x, y = psf.xy(fiber, wavelength)
        xslice, yslice, pix = psf.xypix(fiber, wavelength)

        xslice = slice(xslice.start + int(x / zoom - x),
                       xslice.stop + int(x / zoom - x))
        yslice = slice(yslice.start + int(y / zoom - y),
                       yslice.stop + int(y / zoom - y))
        try:
            image[yslice, xslice] += pix
        except ValueError:
            print("failed for fiber wave=", fiber, wavelength)
            pass

fig = pylab.figure()
pylab.imshow(image,
             origin=0,
             interpolation="nearest",
Exemple #7
0
psf=specter.psf.GaussHermitePSF(args.psf)
wmin=max(3650,psf.wmin+500)
wmax=min(10200,psf.wmax-500)


wave=np.linspace(wmin,wmax,15)

zoom_out=32

image=np.zeros((psf.npix_y//zoom_out,psf.npix_x//zoom_out))
fibers=10+20*np.arange(25)
for fiber in fibers :
    for wavelength in wave :
        print(fiber,wavelength)
        x,y = psf.xy(fiber,wavelength)
        xslice,yslice,pix = psf.xypix(fiber,wavelength)
        #dx=xslice.stop-xslice.start
        #dy=yslice.stop-yslice.start
        dx=(x/zoom_out-x)
        dy=(y/zoom_out-y)
        idx=int(dx+0.5)
        idy=int(dy+0.5)
        
        ipix=np.zeros(pix.shape)
        x=np.arange(xslice.start,xslice.stop)+idx
        y=np.arange(yslice.start,yslice.stop)+idy
        f=scipy.interpolate.interp2d(x,y,pix) 
        ipix = f(x+(idx-dx), y+(idy-dy))
        xslice = slice(xslice.start+idx,xslice.stop+idx)
        yslice = slice(yslice.start+idy,yslice.stop+idy)   
        
Exemple #8
0
res_fiber = []
res_wave = []
res_x_rms = []
res_y_rms = []

use_trace = True

for fiber in fibers:
    for wave in waves:
        images = []
        i0 = []
        i1 = []
        xc = []
        yc = []
        for psf in psfs:
            xx, yy, ccdpix = psf.xypix(fiber, wave)
            xc.append(psf.x(fiber, wave))
            yc.append(psf.y(fiber, wave))
            #print("fiber,wave",fiber,wave)
            #print("xx",xx)
            #print("yy",yy)

            #plt.imshow(ccdpix)
            #plt.show()

            images.append(ccdpix)
            i1.append(xx.start)
            i0.append(yy.start)

        mi0 = int(np.min(i0))
        mi1 = int(np.min(i1))