Exemple #1
0
def kepdeltapix(infile,
                nexp,
                columns,
                rows,
                fluxes,
                prfdir,
                interpolation,
                tolerance,
                fittype,
                imscale,
                colmap,
                verbose,
                logfile,
                status,
                cmdLine=False):

    # input arguments

    status = 0
    seterr(all="ignore")

    # log the call

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile, hashline, verbose)
    call = 'KEPDELTAPIX -- '
    call += 'infile=' + infile + ' '
    call += 'nexp=' + str(nexp) + ' '
    call += 'columns=' + columns + ' '
    call += 'rows=' + rows + ' '
    call += 'fluxes=' + fluxes + ' '
    call += 'prfdir=' + prfdir + ' '
    call += 'interpolation=' + interpolation + ' '
    call += 'tolerance=' + str(tolerance) + ' '
    call += 'fittype=' + str(fittype) + ' '
    call += 'imscale=' + imscale + ' '
    call += 'colmap=' + colmap + ' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose=' + chatter + ' '
    call += 'logfile=' + logfile
    kepmsg.log(logfile, call + '\n', verbose)

    # test log file

    logfile = kepmsg.test(logfile)

    # start time

    kepmsg.clock('KEPDELTAPIX started at', logfile, verbose)

    # reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPDELTAPIX: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile, message, verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID:  %s' % kepid
        print ' RA (J2000):  %s' % ra
        print 'Dec (J2000): %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:    %2s' % skygroup
        print '     Season:    %2s' % str(season)
        print '    Channel:    %2s' % channel
        print '     Module:    %2s' % module
        print '     Output:     %1s' % output
        print ''

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(
            output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPDELTAPIX: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile, message, verbose)

# read PRF images

    if status == 0:
        prfn = [0, 0, 0, 0, 0]
        crpix1p = numpy.zeros((5), dtype='float32')
        crpix2p = numpy.zeros((5), dtype='float32')
        crval1p = numpy.zeros((5), dtype='float32')
        crval2p = numpy.zeros((5), dtype='float32')
        cdelt1p = numpy.zeros((5), dtype='float32')
        cdelt2p = numpy.zeros((5), dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)

# choose rows in the TPF table at random

    if status == 0:
        i = 0
        rownum = []
        while i < nexp:
            work = int(random.random() * len(barytime))
            if numpy.isfinite(barytime[work]) and numpy.isfinite(
                    fluxpixels[work, ydim * xdim / 2]):
                rownum.append(work)
                i += 1

# construct input pixel image

    if status == 0:
        fscat = numpy.empty((len(fluxes), nexp), dtype='float32')
        xscat = numpy.empty((len(columns), nexp), dtype='float32')
        yscat = numpy.empty((len(rows), nexp), dtype='float32')
        for irow in range(nexp):
            flux = fluxpixels[rownum[irow], :]

            # image scale and intensity limits of pixel data

            if status == 0:
                flux_pl, zminfl, zmaxfl = kepplot.intScale1D(flux, imscale)
                n = 0
                imgflux_pl = empty((ydim, xdim))
                for i in range(ydim):
                    for j in range(xdim):
                        imgflux_pl[i, j] = flux_pl[n]
                        n += 1

# fit PRF model to pixel data

            if status == 0:
                start = time.time()
                f, y, x, prfMod, prfFit, prfRes = kepfit.fitMultiPRF(
                    flux, ydim, xdim, column, row, prfn, crval1p, crval2p,
                    cdelt1p, cdelt2p, interpolation, tolerance, fluxes,
                    columns, rows, fittype, verbose, logfile)
                if verbose:
                    print '\nConvergence time = %.1fs' % (time.time() - start)

# best fit parameters

            if status == 0:
                for i in range(len(f)):
                    fscat[i, irow] = f[i]
                    xscat[i, irow] = x[i]
                    yscat[i, irow] = y[i]

# replace starting guess with previous fit parameters

            if status == 0:
                fluxes = copy(f)
                columns = copy(x)
                rows = copy(y)

# mean and rms results

    if status == 0:
        fmean = []
        fsig = []
        xmean = []
        xsig = []
        ymean = []
        ysig = []
        for i in range(len(f)):
            fmean.append(numpy.mean(fscat[i, :]))
            xmean.append(numpy.mean(xscat[i, :]))
            ymean.append(numpy.mean(yscat[i, :]))
            fsig.append(numpy.std(fscat[i, :]))
            xsig.append(numpy.std(xscat[i, :]))
            ysig.append(numpy.std(yscat[i, :]))
            txt = 'Flux = %10.2f e-/s ' % fmean[-1]
            txt += 'X = %7.4f +/- %6.4f pix ' % (xmean[-1], xsig[i])
            txt += 'Y = %7.4f +/- %6.4f pix' % (ymean[-1], ysig[i])
            kepmsg.log(logfile, txt, True)

# output results for kepprfphot

    if status == 0:
        txt1 = 'columns=0.0'
        txt2 = '   rows=0.0'
        for i in range(1, len(f)):
            txt1 += ',%.4f' % (xmean[i] - xmean[0])
            txt2 += ',%.4f' % (ymean[i] - ymean[0])
        kepmsg.log(logfile, '\nkepprfphot input fields:', True)
        kepmsg.log(logfile, txt1, True)
        kepmsg.log(logfile, txt2, True)

# image scale and intensity limits for PRF model image

    if status == 0:
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(prfMod, imscale)

# image scale and intensity limits for PRF fit image

    if status == 0:
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(prfFit, imscale)

# image scale and intensity limits for data - fit residual

    if status == 0:
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(prfRes, imscale)

# plot style

    if status == 0:
        try:
            params = {
                'backend': 'png',
                'axes.linewidth': 2.5,
                'axes.labelsize': 24,
                'axes.font': 'sans-serif',
                'axes.fontweight': 'bold',
                'text.fontsize': 12,
                'legend.fontsize': 12,
                'xtick.labelsize': 10,
                'ytick.labelsize': 10
            }
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[10, 10])
        pylab.clf()
        plotimage(imgflux_pl, zminfl, zmaxfl, 1, row, column, xdim, ydim, 0.06,
                  0.52, 'flux', colmap)
        plotimage(imgfit_pl, zminfl, zmaxfl, 3, row, column, xdim, ydim, 0.06,
                  0.06, 'fit', colmap)
        plotimage(imgres_pl, zminfl, zmaxfl, 4, row, column, xdim, ydim, 0.52,
                  0.06, 'residual', colmap)
        plotimage(imgprf_pl, zminpr, zmaxpr * 0.9, 2, row, column, xdim, ydim,
                  0.52, 0.52, 'model', colmap)
        for i in range(len(f)):
            pylab.plot(xscat[i, :], yscat[i, :], 'o', color='k')

# Plot creep of target position over time, relative to the central source

#	barytime0 = float(int(barytime[0] / 100) * 100.0)
#	barytime -= barytime0
#        xlab = 'BJD $-$ %d' % barytime0
#	xmin = numpy.nanmin(barytime)
#	xmax = numpy.nanmax(barytime)
#	y1min = numpy.nanmin(data)
#	y1max = numpy.nanmax(data)
#	xr = xmax - xmin
#	yr = ymax - ymin
#        barytime = insert(barytime,[0],[barytime[0]])
#        barytime = append(barytime,[barytime[-1]])
#        data = insert(data,[0],[0.0])
#        data = append(data,0.0)
#
#        pylab.figure(2,figsize=[10,10])
#        pylab.clf()
#	ax = pylab.subplot(211)
#	pylab.subplots_adjust(0.1,0.5,0.88,0.42)
#        pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        labels = ax.get_yticklabels()
#        setp(labels, 'rotation', 90, fontsize=ticksize)
#        for i in range(1,len(f)):
#            pylab.plot(rownum,xscat[i,:]-xscat[0,:],'o')
#        pylab.ylabel('$\Delta$Columns', {'color' : 'k'})
#	ax = pylab.subplot(211)
#	pylab.subplots_adjust(0.1,0.1,0.88,0.42)
#        pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        labels = ax.get_yticklabels()
#        setp(labels, 'rotation', 90, fontsize=ticksize)
#        for i in range(1,len(f)):
#            pylab.plot(rownum,yscat[i,:]-yscat[0,:],'o')
#	pylab.xlim(xmin-xr*0.01,xmax+xr*0.01)
#	if ymin-yr*0.01 <= 0.0 or fullrange:
#            pylab.ylim(1.0e-10,ymax+yr*0.01)
#	else:
#            pylab.ylim(ymin-yr*0.01,ymax+yr*0.01)
#        pylab.ylabel('$\Delta$Rows', {'color' : 'k'})
#        pylab.xlabel(xlab, {'color' : 'k'})

# render plot

    if status == 0:
        if cmdLine:
            pylab.show(block=True)
        else:
            pylab.ion()
            pylab.plot([])
            pylab.ioff()

# stop time

    kepmsg.clock('\nKEPDELTAPIX ended at', logfile, verbose)

    return
Exemple #2
0
def kepprf(infile,plotfile,rownum,columns,rows,fluxes,border,background,focus,prfdir,xtol,ftol,
           imscale,colmap,labcol,apercol,plt,verbose,logfile,status,cmdLine=False): 

# input arguments

    status = 0
    seterr(all="ignore") 

# log the call 

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPPRF -- '
    call += 'infile='+infile+' '
    call += 'plotfile='+plotfile+' '
    call += 'rownum='+str(rownum)+' '
    call += 'columns='+columns+' '
    call += 'rows='+rows+' '
    call += 'fluxes='+fluxes+' '
    call += 'border='+str(border)+' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background='+bground+' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus='+focs+' '
    call += 'prfdir='+prfdir+' '
    call += 'xtol='+str(xtol)+' '
    call += 'ftol='+str(xtol)+' '
    call += 'imscale='+imscale+' '
    call += 'colmap='+colmap+' '
    call += 'labcol='+labcol+' '
    call += 'apercol='+apercol+' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot='+plotit+' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# start time

    kepmsg.clock('KEPPRF started at',logfile,verbose)

# reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# construct inital guess vector for fit 

    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in xrange(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in xrange(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border+1)*2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0); guess.append(1.0); guess.append(0.0)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRF: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile,message,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# read mask defintion data from TPF file

    if status == 0:
        maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(infile,logfile,verbose)
        npix = numpy.size(numpy.nonzero(maskimg)[0])

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID: %s' % kepid
        print '        BJD: %.2f' % (barytime[rownum-1] + 2454833.0)
        print ' RA (J2000): %s' % ra
        print 'Dec (J2000):  %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:   %2s' % skygroup
        print '     Season:   %2s' % str(season)
        print '    Channel:   %2s' % channel
        print '     Module:   %2s' % module
        print '     Output:    %1s' % output
        print ''

# is this a good row with finite timestamp and pixels?

    if status == 0:
        if not numpy.isfinite(barytime[rownum-1]) or numpy.nansum(fluxpixels[rownum-1,:]) == numpy.nan:
            message = 'ERROR -- KEPFIELD: Row ' + str(rownum) + ' is a bad quality timestamp'
            status = kepmsg.err(logfile,message,verbose)

# construct input pixel image

    if status == 0:
        flux = fluxpixels[rownum-1,:]
        ferr = errpixels[rownum-1,:]
        DATx = arange(column,column+xdim)
        DATy = arange(row,row+ydim)
#        if numpy.nanmin > 420000.0: flux -= 420000.0

# image scale and intensity limits of pixel data

    if status == 0:
        n = 0
        DATimg = empty((ydim,xdim))
        ERRimg = empty((ydim,xdim))
        for i in range(ydim):
            for j in range(xdim):
                DATimg[i,j] = flux[n]
                ERRimg[i,j] = ferr[n]
                n += 1

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose) 
        prfn = array(prfn)
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e-6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf) / cdelt1p[0] / cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

#    if status == 0:
#        prf = zeros(shape(prfn[0,:,:]),dtype='float32')
#        px = crval1p + len(PRFx) / 2 * cdelt1p[0]
#        py = crval2p + len(PRFy) / 2 * cdelt2p[0]
#        pp = [[px[0],py[0]],
#              [px[1],py[1]],
#              [px[2],py[2]],
#              [px[3],py[3]],
#              [px[4],py[4]]]
#        for index,value in ndenumerate(prf):
#            pz = prfn[:,index[0],index[1]]
#            prf[index] = griddata(pp, pz, ([column], [row]), method='linear')
#        print shape(prf)

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf)

# construct mesh for background model

    if status == 0 and background:
        bx = numpy.arange(1.,float(xdim+1))
        by = numpy.arange(1.,float(ydim+1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# fit PRF model to pixel data

    if status == 0:
        start = time.time()
        if focus and background:
            args = (DATx,DATy,DATimg,ERRimg,nsrc,border,xx,yy,splineInterpolation,float(x[0]),float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        elif focus and not background:
            args = (DATx,DATy,DATimg,ERRimg,nsrc,splineInterpolation,float(x[0]),float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocus,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)                    
        elif background and not focus:
            args = (DATx,DATy,DATimg,ERRimg,nsrc,border,xx,yy,splineInterpolation,float(x[0]),float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithBackground,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        else:
            args = (DATx,DATy,DATimg,ERRimg,nsrc,splineInterpolation,float(x[0]),float(y[0]))
            ans = fmin_powell(kepfunc.PRF,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        print 'Convergence time = %.2fs\n' % (time.time() - start)

# pad the PRF data if the PRF array is smaller than the data array 

    if status == 0:
        flux = []; OBJx = []; OBJy = []
        PRFmod = numpy.zeros((prfDimY,prfDimX))
        if PRFy0 < 0 or PRFx0 < 0.0:
            PRFmod = numpy.zeros((prfDimY,prfDimX))
            superPRF = zeros((prfDimY+1,prfDimX+1))
            superPRF[abs(PRFy0):abs(PRFy0)+shape(prf)[0],abs(PRFx0):abs(PRFx0)+shape(prf)[1]] = prf
            prf = superPRF * 1.0
            PRFy0 = 0
            PRFx0 = 0

# rotate the PRF model around its center

        if focus:
            angle = ans[-1]
            prf = rotate(prf,-angle,reshape=False,mode='nearest')

# iterate through the sources in the best fit PSF model

        for i in range(nsrc):
            flux.append(ans[i])
            OBJx.append(ans[nsrc+i])
            OBJy.append(ans[nsrc*2+i]) 

# calculate best-fit model

            y = (OBJy[i]-mean(DATy)) / cdelt1p[0]
            x = (OBJx[i]-mean(DATx)) / cdelt2p[0]
            prfTmp = shift(prf,[y,x],order=3,mode='constant')
            prfTmp = prfTmp[PRFy0:PRFy0+prfDimY,PRFx0:PRFx0+prfDimX]
            PRFmod = PRFmod + prfTmp * flux[i]
            wx = 1.0
            wy = 1.0
            angle = 0
            b = 0.0

# write out best fit parameters

            if verbose:
                txt = 'Flux = %10.2f e-/s ' % flux[i]
                txt += 'X = %9.4f pix ' % OBJx[i]
                txt += 'Y = %9.4f pix ' % OBJy[i]
                kepmsg.log(logfile,txt,True)
#
#        params = {'backend': 'png',
#                  'axes.linewidth': 2.5,
#                  'axes.labelsize': 24,
#                  'axes.font': 'sans-serif',
#                  'axes.fontweight' : 'bold',
#                  'text.fontsize': 12,
#                  'legend.fontsize': 12,
#                  'xtick.labelsize': 24,
#                  'ytick.labelsize': 24}
#        pylab.rcParams.update(params)
#
#        pylab.figure(figsize=[20,10])
#        ax = pylab.axes([0.05,0.08,0.46,0.9])
#        xxx = numpy.arange(397.5,402.5,0.02)
#        yyy = numpy.sum(PRFmod,axis=0) / numpy.max(numpy.sum(PRFmod,axis=0))
#        pylab.plot(xxx,yyy,color='b',linewidth=3.0) 
#        xxx = numpy.append(numpy.insert(xxx,[0],[xxx[0]]),xxx[-1])
#        yyy = numpy.append(numpy.insert(yyy,[0],[0.0]),yyy[-1]) 
#        pylab.fill(xxx,yyy,fc='y',linewidth=0.0,alpha=0.3) 
#        pylab.xlabel('Pixel Column Number')
#        pylab.xlim(397.5,402.5)
#        pylab.ylim(1.0e-30,1.02)
#        for xmaj in numpy.arange(397.5,402.5,1.0):
#            pylab.plot([xmaj,xmaj],[0.0,1.1],color='k',linewidth=0.5,linestyle=':') 
#        for xmaj in numpy.arange(0.2,1.2,0.2):
#            pylab.plot([0.0,2000.0],[xmaj,xmaj],color='k',linewidth=0.5,linestyle=':') 
#            
#
#        ax = pylab.axes([0.51,0.08,0.46,0.9])
#        xxx = numpy.arange(32.5,37.5,0.02)
#        yyy = numpy.sum(PRFmod,axis=1) / numpy.max(numpy.sum(PRFmod,axis=1))
#        pylab.plot(xxx,yyy,color='b',linewidth=3.0) 
#        xxx = numpy.append(numpy.insert(xxx,[0],[xxx[0]]),xxx[-1])
#        yyy = numpy.append(numpy.insert(yyy,[0],[0.0]),yyy[-1]) 
#        pylab.fill(xxx,yyy,fc='y',linewidth=0.0,alpha=0.3) 
#        pylab.setp(pylab.gca(),yticklabels=[])
#        pylab.xlabel('Pixel Row Number')
#        pylab.xlim(32.5,37.5)
#        pylab.ylim(1.0e-30,1.02)
#        for xmaj in numpy.arange(32.5,37.5,1.0):
#            pylab.plot([xmaj,xmaj],[0.0,1.1],color='k',linewidth=0.5,linestyle=':') 
#        for xmaj in numpy.arange(0.2,1.2,0.2):
#            pylab.plot([0.0,2000.0],[xmaj,xmaj],color='k',linewidth=0.5,linestyle=':') 
#        pylab.ion()
#        pylab.plot([])
#        pylab.ioff()

        if verbose and background:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc*3]
            else:
                bcoeff = array([ans[nsrc*3:nsrc*3+bterms],ans[nsrc*3+bterms:nsrc*3+bterms*2]]) 
                bkg = kepfunc.polyval2d(xx,yy,bcoeff)
                b = nanmean(bkg.reshape(bkg.size))
            txt = '\n   Mean background = %.2f e-/s' % b
            kepmsg.log(logfile,txt,True)
        if focus:
            wx = ans[-3]
            wy = ans[-2]
            angle = ans[-1]
        if verbose and focus:
            if not background: kepmsg.log(logfile,'',True)
            kepmsg.log(logfile,' X/Y focus factors = %.3f/%.3f' % (wx,wy),True)
            kepmsg.log(logfile,'PRF rotation angle = %.2f deg' % angle,True)

# measure flux fraction and contamination

    if status == 0:
        PRFall = kepfunc.PRF2DET(flux,OBJx,OBJy,DATx,DATy,wx,wy,angle,splineInterpolation)
        PRFone = kepfunc.PRF2DET([flux[0]],[OBJx[0]],[OBJy[0]],DATx,DATy,wx,wy,angle,splineInterpolation)
        FluxInMaskAll = numpy.nansum(PRFall)
        FluxInMaskOne = numpy.nansum(PRFone)
        FluxInAperAll = 0.0
        FluxInAperOne = 0.0
        for i in range(1,ydim):
            for j in range(1,xdim):
                if kepstat.bitInBitmap(maskimg[i,j],2):
                    FluxInAperAll += PRFall[i,j]
                    FluxInAperOne += PRFone[i,j]
        FluxFraction = FluxInAperOne / flux[0]
        try:
            Contamination = (FluxInAperAll - FluxInAperOne) / FluxInAperAll
        except:
            Contamination = 0.0

        kepmsg.log(logfile,'\n                Total flux in mask = %.2f e-/s' % FluxInMaskAll,True)
        kepmsg.log(logfile,'               Target flux in mask = %.2f e-/s' % FluxInMaskOne,True)
        kepmsg.log(logfile,'            Total flux in aperture = %.2f e-/s' % FluxInAperAll,True)
        kepmsg.log(logfile,'           Target flux in aperture = %.2f e-/s' % FluxInAperOne,True)
        kepmsg.log(logfile,'  Target flux fraction in aperture = %.2f%%' % (FluxFraction * 100.0),True)
        kepmsg.log(logfile,'Contamination fraction in aperture = %.2f%%' % (Contamination * 100.0),True)


# constuct model PRF in detector coordinates

    if status == 0:
        PRFfit = PRFall + 0.0
        if background and bterms == 1:
            PRFfit = PRFall + b
        if background and bterms > 1:
            PRFfit = PRFall + bkg

# calculate residual of DATA - FIT

    if status == 0:
        PRFres = DATimg - PRFfit
        FLUXres = numpy.nansum(PRFres) / npix
    
# calculate the sum squared difference between data and model

    if status == 0:
        Pearson = abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit))
        Chi2 = numpy.nansum(numpy.square(DATimg - PRFfit) / numpy.square(ERRimg))
        DegOfFreedom = npix - len(guess) - 1
        try:
            kepmsg.log(logfile,'\n       Residual flux = %.2f e-/s' % FLUXres,True)
            kepmsg.log(logfile,'Pearson\'s chi^2 test = %d for %d dof' % (Pearson,DegOfFreedom),True)
        except:
            pass
        kepmsg.log(logfile,'          Chi^2 test = %d for %d dof' % (Chi2,DegOfFreedom),True)

# image scale and intensity limits for plotting images

    if status == 0:
        imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg,imscale)
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod,imscale)
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit,imscale)
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres,'linear')
        if imscale == 'linear':
            zmaxpr *= 0.9
        elif imscale == 'logarithmic':
            zmaxpr = numpy.max(zmaxpr)
            zminpr = zmaxpr / 2
        
# plot style

    if status == 0:
        try:
            params = {'backend': 'png',
                      'axes.linewidth': 2.5,
                      'axes.labelsize': 28,
                      'axes.font': 'sans-serif',
                      'axes.fontweight' : 'bold',
                      'text.fontsize': 12,
                      'legend.fontsize': 12,
                      'xtick.labelsize': 20,
                      'ytick.labelsize': 20,
                      'xtick.major.pad': 6,
                      'ytick.major.pad': 6}
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[12,10])
        pylab.clf()
        plotimage(imgdat_pl,zminfl,zmaxfl,1,row,column,xdim,ydim,0.07,0.53,'observation',colmap,labcol)
#        pylab.text(830.0,242.1,'A',horizontalalignment='center',verticalalignment='center',
#                   fontsize=28,fontweight=500,color='white')
#        pylab.text(831.1,240.62,'B',horizontalalignment='center',verticalalignment='center',
#                   fontsize=28,fontweight=500,color='white')
#        plotimage(imgprf_pl,0.0,zmaxpr/0.5,2,row,column,xdim,ydim,0.52,0.52,'model',colmap)
        plotimage(imgprf_pl,zminpr,zmaxpr,2,row,column,xdim,ydim,0.44,0.53,'model',colmap,labcol)
        kepplot.borders(maskimg,xdim,ydim,pixcoord1,pixcoord2,1,apercol,'--',0.5)
        kepplot.borders(maskimg,xdim,ydim,pixcoord1,pixcoord2,2,apercol,'-',3.0)
        plotimage(imgfit_pl,zminfl,zmaxfl,3,row,column,xdim,ydim,0.07,0.08,'fit',colmap,labcol)
#        plotimage(imgres_pl,-zmaxre,zmaxre,4,row,column,xdim,ydim,0.44,0.08,'residual',colmap,'k')
        plotimage(imgres_pl,zminfl,zmaxfl,4,row,column,xdim,ydim,0.44,0.08,'residual',colmap,labcol)
            
# plot data color bar

#    barwin = pylab.axes([0.84,0.53,0.06,0.45])
    barwin = pylab.axes([0.84,0.08,0.06,0.9])
    if imscale == 'linear':
        brange = numpy.arange(zminfl,zmaxfl,(zmaxfl-zminfl)/1000)
    elif imscale == 'logarithmic':
        brange = numpy.arange(10.0**zminfl,10.0**zmaxfl,(10.0**zmaxfl-10.0**zminfl)/1000)
    elif imscale == 'squareroot':
        brange = numpy.arange(zminfl**2,zmaxfl**2,(zmaxfl**2-zminfl**2)/1000)
    if imscale == 'linear':
        barimg = numpy.resize(brange,(1000,1))
    elif imscale == 'logarithmic':
        barimg = numpy.log10(numpy.resize(brange,(1000,1)))        
    elif imscale == 'squareroot':
        barimg = numpy.sqrt(numpy.resize(brange,(1000,1)))        
    try:
        nrm = len(str(int(numpy.nanmax(brange))))-1
    except:
        nrm = 0
    brange = brange / 10**nrm
    pylab.imshow(barimg,aspect='auto',interpolation='nearest',origin='lower',
                 vmin=numpy.nanmin(barimg),vmax=numpy.nanmax(barimg),
                 extent=(0.0,1.0,brange[0],brange[-1]),cmap=colmap)
    barwin.yaxis.tick_right()
    barwin.yaxis.set_label_position('right')
    barwin.yaxis.set_major_locator(MaxNLocator(7))
    pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
    pylab.gca().set_autoscale_on(False)
    pylab.setp(pylab.gca(),xticklabels=[],xticks=[])
    pylab.ylabel('Flux (10$^%d$ e$^-$ s$^{-1}$)' % nrm)
    setp(barwin.get_yticklabels(), 'rotation', 90)
    barwin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))

# plot residual color bar

#    barwin = pylab.axes([0.84,0.08,0.06,0.45])
#    Brange = numpy.arange(-zmaxre,zmaxre,(zmaxre+zmaxre)/1000)
#    try:
#        nrm = len(str(int(numpy.nanmax(brange))))-1
#    except:
#        nrm = 0
#    brange = brange / 10**nrm
#    barimg = numpy.resize(brange,(1000,1))
#    pylab.imshow(barimg,aspect='auto',interpolation='nearest',origin='lower',
#           vmin=brange[0],vmax=brange[-1],extent=(0.0,1.0,brange[0],brange[-1]),cmap=colmap)
#    barwin.yaxis.tick_right()
#    barwin.yaxis.set_label_position('right')
#    barwin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
#    barwin.yaxis.set_major_locator(MaxNLocator(7))
#    pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#    pylab.gca().set_autoscale_on(False)
#    pylab.setp(pylab.gca(),xticklabels=[],xticks=[])
#    pylab.ylabel('Residual (10$^%d$ e$^-$ s$^{-1}$)' % nrm)
#    setp(barwin.get_yticklabels(), 'rotation', 90)

# render plot

    if status == 0 and len(plotfile) > 0 and plotfile.lower() != 'none':
        pylab.savefig(plotfile)
    if status == 0 and plt:
        if cmdLine: 
            pylab.show(block=True)
        else: 
            pylab.ion()
            pylab.plot([])
            pylab.ioff()
	
# stop time

    kepmsg.clock('\nKEPPRF ended at',logfile,verbose)

    return
Exemple #3
0
def kepprf(infile,
           plotfile,
           rownum,
           columns,
           rows,
           fluxes,
           border,
           background,
           focus,
           prfdir,
           xtol,
           ftol,
           imscale,
           colmap,
           labcol,
           apercol,
           plt,
           verbose,
           logfile,
           status,
           cmdLine=False):

    # input arguments

    status = 0
    seterr(all="ignore")

    # log the call

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile, hashline, verbose)
    call = 'KEPPRF -- '
    call += 'infile=' + infile + ' '
    call += 'plotfile=' + plotfile + ' '
    call += 'rownum=' + str(rownum) + ' '
    call += 'columns=' + columns + ' '
    call += 'rows=' + rows + ' '
    call += 'fluxes=' + fluxes + ' '
    call += 'border=' + str(border) + ' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background=' + bground + ' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus=' + focs + ' '
    call += 'prfdir=' + prfdir + ' '
    call += 'xtol=' + str(xtol) + ' '
    call += 'ftol=' + str(xtol) + ' '
    call += 'imscale=' + imscale + ' '
    call += 'colmap=' + colmap + ' '
    call += 'labcol=' + labcol + ' '
    call += 'apercol=' + apercol + ' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot=' + plotit + ' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose=' + chatter + ' '
    call += 'logfile=' + logfile
    kepmsg.log(logfile, call + '\n', verbose)

    # test log file

    logfile = kepmsg.test(logfile)

    # start time

    kepmsg.clock('KEPPRF started at', logfile, verbose)

    # reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# construct inital guess vector for fit

    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in range(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in range(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in range(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in range(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border + 1) * 2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0)
            guess.append(1.0)
            guess.append(0.0)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRF: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile, message, verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# read mask defintion data from TPF file

    if status == 0:
        maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(
            infile, logfile, verbose)
        npix = numpy.size(numpy.nonzero(maskimg)[0])

# print target data

    if status == 0 and verbose:
        print('')
        print('      KepID: %s' % kepid)
        print('        BJD: %.2f' % (barytime[rownum - 1] + 2454833.0))
        print(' RA (J2000): %s' % ra)
        print('Dec (J2000):  %s' % dec)
        print('     KepMag:  %s' % kepmag)
        print('   SkyGroup:   %2s' % skygroup)
        print('     Season:   %2s' % str(season))
        print('    Channel:   %2s' % channel)
        print('     Module:   %2s' % module)
        print('     Output:    %1s' % output)
        print('')

# is this a good row with finite timestamp and pixels?

    if status == 0:
        if not numpy.isfinite(barytime[rownum - 1]) or numpy.nansum(
                fluxpixels[rownum - 1, :]) == numpy.nan:
            message = 'ERROR -- KEPFIELD: Row ' + str(
                rownum) + ' is a bad quality timestamp'
            status = kepmsg.err(logfile, message, verbose)

# construct input pixel image

    if status == 0:
        flux = fluxpixels[rownum - 1, :]
        ferr = errpixels[rownum - 1, :]
        DATx = arange(column, column + xdim)
        DATy = arange(row, row + ydim)
#        if numpy.nanmin > 420000.0: flux -= 420000.0

# image scale and intensity limits of pixel data

    if status == 0:
        n = 0
        DATimg = empty((ydim, xdim))
        ERRimg = empty((ydim, xdim))
        for i in range(ydim):
            for j in range(xdim):
                DATimg[i, j] = flux[n]
                ERRimg[i, j] = ferr[n]
                n += 1

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(
            output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile, message, verbose)

# read PRF images

    if status == 0:
        prfn = [0, 0, 0, 0, 0]
        crpix1p = numpy.zeros((5), dtype='float32')
        crpix2p = numpy.zeros((5), dtype='float32')
        crval1p = numpy.zeros((5), dtype='float32')
        crval2p = numpy.zeros((5), dtype='float32')
        cdelt1p = numpy.zeros((5), dtype='float32')
        cdelt2p = numpy.zeros((5), dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)
        prfn = array(prfn)
        PRFx = arange(0.5, shape(prfn[0])[1] + 0.5)
        PRFy = arange(0.5, shape(prfn[0])[0] + 0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]), dtype='float32')
        prfWeight = zeros((5), dtype='float32')
        for i in range(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 +
                                (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e-6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf) / cdelt1p[0] / cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

#    if status == 0:
#        prf = zeros(shape(prfn[0,:,:]),dtype='float32')
#        px = crval1p + len(PRFx) / 2 * cdelt1p[0]
#        py = crval2p + len(PRFy) / 2 * cdelt2p[0]
#        pp = [[px[0],py[0]],
#              [px[1],py[1]],
#              [px[2],py[2]],
#              [px[3],py[3]],
#              [px[4],py[4]]]
#        for index,value in ndenumerate(prf):
#            pz = prfn[:,index[0],index[1]]
#            prf[index] = griddata(pp, pz, ([column], [row]), method='linear')
#        print shape(prf)

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(
            PRFx, PRFy, prf)

# construct mesh for background model

    if status == 0 and background:
        bx = numpy.arange(1., float(xdim + 1))
        by = numpy.arange(1., float(ydim + 1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# fit PRF model to pixel data

    if status == 0:
        start = time.time()
        if focus and background:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                    splineInterpolation, float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif focus and not background:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                    float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocus,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif background and not focus:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                    splineInterpolation, float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        else:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                    float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRF,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        print('Convergence time = %.2fs\n' % (time.time() - start))

# pad the PRF data if the PRF array is smaller than the data array

    if status == 0:
        flux = []
        OBJx = []
        OBJy = []
        PRFmod = numpy.zeros((prfDimY, prfDimX))
        if PRFy0 < 0 or PRFx0 < 0.0:
            PRFmod = numpy.zeros((prfDimY, prfDimX))
            superPRF = zeros((prfDimY + 1, prfDimX + 1))
            superPRF[abs(PRFy0):abs(PRFy0) + shape(prf)[0],
                     abs(PRFx0):abs(PRFx0) + shape(prf)[1]] = prf
            prf = superPRF * 1.0
            PRFy0 = 0
            PRFx0 = 0

# rotate the PRF model around its center

        if focus:
            angle = ans[-1]
            prf = rotate(prf, -angle, reshape=False, mode='nearest')

# iterate through the sources in the best fit PSF model

        for i in range(nsrc):
            flux.append(ans[i])
            OBJx.append(ans[nsrc + i])
            OBJy.append(ans[nsrc * 2 + i])

            # calculate best-fit model

            y = (OBJy[i] - mean(DATy)) / cdelt1p[0]
            x = (OBJx[i] - mean(DATx)) / cdelt2p[0]
            prfTmp = shift(prf, [y, x], order=3, mode='constant')
            prfTmp = prfTmp[PRFy0:PRFy0 + prfDimY, PRFx0:PRFx0 + prfDimX]
            PRFmod = PRFmod + prfTmp * flux[i]
            wx = 1.0
            wy = 1.0
            angle = 0
            b = 0.0

            # write out best fit parameters

            if verbose:
                txt = 'Flux = %10.2f e-/s ' % flux[i]
                txt += 'X = %9.4f pix ' % OBJx[i]
                txt += 'Y = %9.4f pix ' % OBJy[i]
                kepmsg.log(logfile, txt, True)
#
#        params = {'backend': 'png',
#                  'axes.linewidth': 2.5,
#                  'axes.labelsize': 24,
#                  'axes.font': 'sans-serif',
#                  'axes.fontweight' : 'bold',
#                  'text.fontsize': 12,
#                  'legend.fontsize': 12,
#                  'xtick.labelsize': 24,
#                  'ytick.labelsize': 24}
#        pylab.rcParams.update(params)
#
#        pylab.figure(figsize=[20,10])
#        ax = pylab.axes([0.05,0.08,0.46,0.9])
#        xxx = numpy.arange(397.5,402.5,0.02)
#        yyy = numpy.sum(PRFmod,axis=0) / numpy.max(numpy.sum(PRFmod,axis=0))
#        pylab.plot(xxx,yyy,color='b',linewidth=3.0)
#        xxx = numpy.append(numpy.insert(xxx,[0],[xxx[0]]),xxx[-1])
#        yyy = numpy.append(numpy.insert(yyy,[0],[0.0]),yyy[-1])
#        pylab.fill(xxx,yyy,fc='y',linewidth=0.0,alpha=0.3)
#        pylab.xlabel('Pixel Column Number')
#        pylab.xlim(397.5,402.5)
#        pylab.ylim(1.0e-30,1.02)
#        for xmaj in numpy.arange(397.5,402.5,1.0):
#            pylab.plot([xmaj,xmaj],[0.0,1.1],color='k',linewidth=0.5,linestyle=':')
#        for xmaj in numpy.arange(0.2,1.2,0.2):
#            pylab.plot([0.0,2000.0],[xmaj,xmaj],color='k',linewidth=0.5,linestyle=':')
#
#
#        ax = pylab.axes([0.51,0.08,0.46,0.9])
#        xxx = numpy.arange(32.5,37.5,0.02)
#        yyy = numpy.sum(PRFmod,axis=1) / numpy.max(numpy.sum(PRFmod,axis=1))
#        pylab.plot(xxx,yyy,color='b',linewidth=3.0)
#        xxx = numpy.append(numpy.insert(xxx,[0],[xxx[0]]),xxx[-1])
#        yyy = numpy.append(numpy.insert(yyy,[0],[0.0]),yyy[-1])
#        pylab.fill(xxx,yyy,fc='y',linewidth=0.0,alpha=0.3)
#        pylab.setp(pylab.gca(),yticklabels=[])
#        pylab.xlabel('Pixel Row Number')
#        pylab.xlim(32.5,37.5)
#        pylab.ylim(1.0e-30,1.02)
#        for xmaj in numpy.arange(32.5,37.5,1.0):
#            pylab.plot([xmaj,xmaj],[0.0,1.1],color='k',linewidth=0.5,linestyle=':')
#        for xmaj in numpy.arange(0.2,1.2,0.2):
#            pylab.plot([0.0,2000.0],[xmaj,xmaj],color='k',linewidth=0.5,linestyle=':')
#        pylab.ion()
#        pylab.plot([])
#        pylab.ioff()

        if verbose and background:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc * 3]
            else:
                bcoeff = array([
                    ans[nsrc * 3:nsrc * 3 + bterms],
                    ans[nsrc * 3 + bterms:nsrc * 3 + bterms * 2]
                ])
                bkg = kepfunc.polyval2d(xx, yy, bcoeff)
                b = nanmean(bkg.reshape(bkg.size))
            txt = '\n   Mean background = %.2f e-/s' % b
            kepmsg.log(logfile, txt, True)
        if focus:
            wx = ans[-3]
            wy = ans[-2]
            angle = ans[-1]
        if verbose and focus:
            if not background: kepmsg.log(logfile, '', True)
            kepmsg.log(logfile, ' X/Y focus factors = %.3f/%.3f' % (wx, wy),
                       True)
            kepmsg.log(logfile, 'PRF rotation angle = %.2f deg' % angle, True)

# measure flux fraction and contamination

# LUGER: This looks horribly bugged. ``PRFall`` is certainly NOT the sum of the all the sources.

    if status == 0:
        PRFall = kepfunc.PRF2DET(flux, OBJx, OBJy, DATx, DATy, wx, wy, angle,
                                 splineInterpolation)
        PRFone = kepfunc.PRF2DET([flux[0]], [OBJx[0]], [OBJy[0]], DATx, DATy,
                                 wx, wy, angle, splineInterpolation)

        # LUGER: Add up contaminant fluxes
        PRFcont = np.zeros_like(PRFone)
        for ncont in range(1, len(flux)):
            PRFcont += kepfunc.PRF2DET([flux[ncont]], [OBJx[ncont]],
                                       [OBJy[ncont]], DATx, DATy, wx, wy,
                                       angle, splineInterpolation)
        PRFcont[np.where(PRFcont < 0)] = 0

        FluxInMaskAll = numpy.nansum(PRFall)
        FluxInMaskOne = numpy.nansum(PRFone)
        FluxInAperAll = 0.0
        FluxInAperOne = 0.0
        FluxInAperAllTrue = 0.0

        for i in range(1, ydim):
            for j in range(1, xdim):
                if kepstat.bitInBitmap(maskimg[i, j], 2):
                    FluxInAperAll += PRFall[i, j]
                    FluxInAperOne += PRFone[i, j]
                    FluxInAperAllTrue += PRFone[i, j] + PRFcont[i, j]
        FluxFraction = FluxInAperOne / flux[0]
        try:
            Contamination = (FluxInAperAll - FluxInAperOne) / FluxInAperAll
        except:
            Contamination = 0.0

        # LUGER: Pixel crowding metrics
        Crowding = PRFone / (PRFone + PRFcont)

        # LUGER: Optimal aperture crowding metric
        CrowdAper = FluxInAperOne / FluxInAperAllTrue

        kepmsg.log(
            logfile,
            '\n                Total flux in mask = %.2f e-/s' % FluxInMaskAll,
            True)
        kepmsg.log(
            logfile,
            '               Target flux in mask = %.2f e-/s' % FluxInMaskOne,
            True)
        kepmsg.log(
            logfile,
            '            Total flux in aperture = %.2f e-/s' % FluxInAperAll,
            True)
        kepmsg.log(
            logfile,
            '           Target flux in aperture = %.2f e-/s' % FluxInAperOne,
            True)
        kepmsg.log(
            logfile, '  Target flux fraction in aperture = %.2f%%' %
            (FluxFraction * 100.0), True)
        kepmsg.log(
            logfile, 'Contamination fraction in aperture = %.2f%%' %
            (Contamination * 100.0), True)
        kepmsg.log(logfile,
                   '       Crowding metric in aperture = %.4f' % (CrowdAper),
                   True)

# constuct model PRF in detector coordinates

    if status == 0:
        PRFfit = PRFall + 0.0
        if background and bterms == 1:
            PRFfit = PRFall + b
        if background and bterms > 1:
            PRFfit = PRFall + bkg

# calculate residual of DATA - FIT

    if status == 0:
        PRFres = DATimg - PRFfit
        FLUXres = numpy.nansum(PRFres) / npix

# calculate the sum squared difference between data and model

    if status == 0:
        Pearson = abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit))
        Chi2 = numpy.nansum(
            numpy.square(DATimg - PRFfit) / numpy.square(ERRimg))
        DegOfFreedom = npix - len(guess) - 1
        try:
            kepmsg.log(logfile, '\n       Residual flux = %.2f e-/s' % FLUXres,
                       True)
            kepmsg.log(
                logfile, 'Pearson\'s chi^2 test = %d for %d dof' %
                (Pearson, DegOfFreedom), True)
        except:
            pass
        kepmsg.log(
            logfile,
            '          Chi^2 test = %d for %d dof' % (Chi2, DegOfFreedom),
            True)

# image scale and intensity limits for plotting images

    if status == 0:
        imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg, imscale)
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod, imscale)
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit, imscale)
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres, 'linear')
        if imscale == 'linear':
            zmaxpr *= 0.9
        elif imscale == 'logarithmic':
            zmaxpr = numpy.max(zmaxpr)
            zminpr = zmaxpr / 2

# plot style

    if status == 0:
        pylab.figure(figsize=[12, 10])
        pylab.clf()
        plotimage(imgdat_pl, zminfl, zmaxfl, 1, row, column, xdim, ydim, 0.07,
                  0.53, 'observation', colmap, labcol)
        #        pylab.text(830.0,242.1,'A',horizontalalignment='center',verticalalignment='center',
        #                   fontsize=28,fontweight=500,color='white')
        #        pylab.text(831.1,240.62,'B',horizontalalignment='center',verticalalignment='center',
        #                   fontsize=28,fontweight=500,color='white')
        #        plotimage(imgprf_pl,0.0,zmaxpr/0.5,2,row,column,xdim,ydim,0.52,0.52,'model',colmap)
        plotimage(imgprf_pl, zminpr, zmaxpr, 2, row, column, xdim, ydim, 0.44,
                  0.53, 'model', colmap, labcol)
        kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, apercol,
                        '--', 0.5)
        kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, apercol,
                        '-', 3.0)
        plotimage(imgfit_pl,
                  zminfl,
                  zmaxfl,
                  3,
                  row,
                  column,
                  xdim,
                  ydim,
                  0.07,
                  0.08,
                  'fit',
                  colmap,
                  labcol,
                  crowd=Crowding)
        #        plotimage(imgres_pl,-zmaxre,zmaxre,4,row,column,xdim,ydim,0.44,0.08,'residual',colmap,'k')
        plotimage(imgres_pl, zminfl, zmaxfl, 4, row, column, xdim, ydim, 0.44,
                  0.08, 'residual', colmap, labcol)

# plot data color bar

#    barwin = pylab.axes([0.84,0.53,0.06,0.45])
    barwin = pylab.axes([0.84, 0.08, 0.06, 0.9])
    if imscale == 'linear':
        brange = numpy.arange(zminfl, zmaxfl, (zmaxfl - zminfl) / 1000)
    elif imscale == 'logarithmic':
        brange = numpy.arange(10.0**zminfl, 10.0**zmaxfl,
                              (10.0**zmaxfl - 10.0**zminfl) / 1000)
    elif imscale == 'squareroot':
        brange = numpy.arange(zminfl**2, zmaxfl**2,
                              (zmaxfl**2 - zminfl**2) / 1000)
    if imscale == 'linear':
        barimg = numpy.resize(brange, (1000, 1))
    elif imscale == 'logarithmic':
        barimg = numpy.log10(numpy.resize(brange, (1000, 1)))
    elif imscale == 'squareroot':
        barimg = numpy.sqrt(numpy.resize(brange, (1000, 1)))
    try:
        nrm = len(str(int(numpy.nanmax(brange)))) - 1
    except:
        nrm = 0
    brange = brange / 10**nrm
    pylab.imshow(barimg,
                 aspect='auto',
                 interpolation='nearest',
                 origin='lower',
                 vmin=numpy.nanmin(barimg),
                 vmax=numpy.nanmax(barimg),
                 extent=(0.0, 1.0, brange[0], brange[-1]),
                 cmap=colmap)
    barwin.yaxis.tick_right()
    barwin.yaxis.set_label_position('right')
    barwin.yaxis.set_major_locator(MaxNLocator(7))
    pylab.gca().yaxis.set_major_formatter(
        pylab.ScalarFormatter(useOffset=False))
    pylab.gca().set_autoscale_on(False)
    pylab.setp(pylab.gca(), xticklabels=[], xticks=[])
    pylab.ylabel('Flux (10$^%d$ e$^-$ s$^{-1}$)' % nrm)
    setp(barwin.get_yticklabels(), 'rotation', 90)
    barwin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))

    # plot residual color bar

    #    barwin = pylab.axes([0.84,0.08,0.06,0.45])
    #    Brange = numpy.arange(-zmaxre,zmaxre,(zmaxre+zmaxre)/1000)
    #    try:
    #        nrm = len(str(int(numpy.nanmax(brange))))-1
    #    except:
    #        nrm = 0
    #    brange = brange / 10**nrm
    #    barimg = numpy.resize(brange,(1000,1))
    #    pylab.imshow(barimg,aspect='auto',interpolation='nearest',origin='lower',
    #           vmin=brange[0],vmax=brange[-1],extent=(0.0,1.0,brange[0],brange[-1]),cmap=colmap)
    #    barwin.yaxis.tick_right()
    #    barwin.yaxis.set_label_position('right')
    #    barwin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
    #    barwin.yaxis.set_major_locator(MaxNLocator(7))
    #    pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
    #    pylab.gca().set_autoscale_on(False)
    #    pylab.setp(pylab.gca(),xticklabels=[],xticks=[])
    #    pylab.ylabel('Residual (10$^%d$ e$^-$ s$^{-1}$)' % nrm)
    #    setp(barwin.get_yticklabels(), 'rotation', 90)

    # render plot

    if status == 0 and len(plotfile) > 0 and plotfile.lower() != 'none':
        pylab.savefig(plotfile)
    if status == 0 and plt:
        if cmdLine:
            pylab.show(block=True)
        else:
            pylab.ion()
            pylab.plot([])
            pylab.ioff()

# stop time

    kepmsg.clock('\nKEPPRF ended at', logfile, verbose)

    return
def kepprf(infile,
           plotfile,
           rownum,
           columns,
           rows,
           fluxes,
           border,
           background,
           focus,
           prfdir,
           xtol,
           ftol,
           imscale,
           colmap,
           plt,
           verbose,
           logfile,
           status,
           cmdLine=False):

    # input arguments
    print "... input arguments"
    status = 0
    seterr(all="ignore")

    # log the call
    print "... logging the call"
    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile, hashline, verbose)
    call = 'KEPPRF -- '
    call += 'infile=' + infile + ' '
    call += 'plotfile=' + plotfile + ' '
    call += 'rownum=' + str(rownum) + ' '
    call += 'columns=' + columns + ' '
    call += 'rows=' + rows + ' '
    call += 'fluxes=' + fluxes + ' '
    call += 'border=' + str(border) + ' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background=' + bground + ' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus=' + focs + ' '
    call += 'prfdir=' + prfdir + ' '
    call += 'xtol=' + str(xtol) + ' '
    call += 'ftol=' + str(xtol) + ' '
    call += 'imscale=' + imscale + ' '
    call += 'colmap=' + colmap + ' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot=' + plotit + ' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose=' + chatter + ' '
    call += 'logfile=' + logfile
    kepmsg.log(logfile, call + '\n', verbose)

    # test log file

    logfile = kepmsg.test(logfile)

    # start time
    print "... starting kepler time"
    kepmsg.clock('KEPPRF started at', logfile, verbose)

    # reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# construct inital guess vector for fit
    print " status = " + str(status)
    print "... initial guess"
    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in xrange(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in xrange(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border + 1) * 2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0)
            guess.append(1.0)
            guess.append(0.0)

# open TPF FITS file
    print "... open tpf file"
    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRF: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile, message, verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# read mask defintion data from TPF file
    print "... read mask definition"
    if status == 0:
        maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(
            infile, logfile, verbose)
        npix = numpy.size(numpy.nonzero(maskimg)[0])

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID:  %s' % kepid
        print ' RA (J2000):  %s' % ra
        print 'Dec (J2000): %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:    %2s' % skygroup
        print '     Season:    %2s' % str(season)
        print '    Channel:    %2s' % channel
        print '     Module:    %2s' % module
        print '     Output:     %1s' % output
        print ''

# is this a good row with finite timestamp and pixels?

    if status == 0:
        if not numpy.isfinite(barytime[rownum - 1]) or numpy.nansum(
                fluxpixels[rownum - 1, :]) == numpy.nan:
            message = 'ERROR -- KEPFIELD: Row ' + str(
                rownum) + ' is a bad quality timestamp'
            status = kepmsg.err(logfile, message, verbose)

# construct input pixel image

    if status == 0:
        flux = fluxpixels[rownum - 1, :]
        ferr = errpixels[rownum - 1, :]
        DATx = arange(column, column + xdim)
        DATy = arange(row, row + ydim)

# image scale and intensity limits of pixel data

    if status == 0:
        n = 0
        DATimg = empty((ydim, xdim))
        ERRimg = empty((ydim, xdim))
        for i in range(ydim):
            for j in range(xdim):
                DATimg[i, j] = flux[n]
                ERRimg[i, j] = ferr[n]
                n += 1

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(
            output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile, message, verbose)

# read PRF images

    if status == 0:
        prfn = [0, 0, 0, 0, 0]
        crpix1p = numpy.zeros((5), dtype='float32')
        crpix2p = numpy.zeros((5), dtype='float32')
        crval1p = numpy.zeros((5), dtype='float32')
        crval2p = numpy.zeros((5), dtype='float32')
        cdelt1p = numpy.zeros((5), dtype='float32')
        cdelt2p = numpy.zeros((5), dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)
        PRFx = arange(0.5, shape(prfn[0])[1] + 0.5)
        PRFy = arange(0.5, shape(prfn[0])[0] + 0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]), dtype='float32')
        prfWeight = zeros((5), dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 +
                                (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
            prf = prf / nansum(prf)
        prf = prf / cdelt1p[0] / cdelt2p[0]

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(
            PRFx, PRFy, prf)

# construct mesh for background model

    if status == 0 and background:
        bx = numpy.arange(1., float(xdim + 1))
        by = numpy.arange(1., float(ydim + 1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# fit PRF model to pixel data

    if status == 0:
        start = time.time()
        if focus and background:
            args = (DATx, DATy, DATimg, nsrc, border, xx, yy, PRFx, PRFy,
                    splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif focus and not background:
            args = (DATx, DATy, DATimg, nsrc, PRFx, PRFy, splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithFocus,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif background and not focus:
            args = (DATx, DATy, DATimg, nsrc, border, xx, yy,
                    splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        else:
            args = (DATx, DATy, DATimg, splineInterpolation)
            ans = fmin_powell(kepfunc.PRF,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        print 'Convergence time = %.2fs\n' % (time.time() - start)

# pad the PRF data if the PRF array is smaller than the data array

    if status == 0:
        flux = []
        OBJx = []
        OBJy = []
        PRFmod = numpy.zeros((prfDimY, prfDimX))
        if PRFy0 < 0 or PRFx0 < 0.0:
            PRFmod = numpy.zeros((prfDimY, prfDimX))
            superPRF = zeros((prfDimY + 1, prfDimX + 1))
            superPRF[abs(PRFy0):abs(PRFy0) + shape(prf)[0],
                     abs(PRFx0):abs(PRFx0) + shape(prf)[1]] = prf
            prf = superPRF * 1.0
            PRFy0 = 0
            PRFx0 = 0

# rotate the PRF model around its center

        if focus:
            angle = ans[-1]
            prf = rotate(prf, -angle, reshape=False, mode='nearest')

# iterate through the sources in the best fit PSF model

        for i in range(nsrc):
            flux.append(ans[i])
            OBJx.append(ans[nsrc + i])
            OBJy.append(ans[nsrc * 2 + i])

            # calculate best-fit model

            y = (OBJy[i] - mean(DATy)) / cdelt1p[0]
            x = (OBJx[i] - mean(DATx)) / cdelt2p[0]
            prfTmp = shift(prf, [y, x], order=1, mode='constant')
            prfTmp = prfTmp[PRFy0:PRFy0 + prfDimY, PRFx0:PRFx0 + prfDimX]
            PRFmod = PRFmod + prfTmp * flux[i]
            wx = 1.0
            wy = 1.0
            angle = 0
            b = 0.0

            # write out best fit parameters

            if verbose:
                txt = 'Flux = %10.2f e-/s ' % flux[i]
                txt += 'X = %9.4f pix ' % OBJx[i]
                txt += 'Y = %9.4f pix ' % OBJy[i]
                kepmsg.log(logfile, txt, True)
        if verbose and background:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc * 3]
            else:
                bcoeff = array([
                    ans[nsrc * 3:nsrc * 3 + bterms],
                    ans[nsrc * 3 + bterms:nsrc * 3 + bterms * 2]
                ])
                bkg = kepfunc.polyval2d(xx, yy, bcoeff)
                b = nanmean(bkg.reshape(bkg.size))
            txt = '\n   Mean background = %.2f e-/s' % b
            kepmsg.log(logfile, txt, True)
        if focus:
            wx = ans[-3]
            wy = ans[-2]
            angle = ans[-1]
        if verbose and focus:
            if not background: kepmsg.log(logfile, '', True)
            kepmsg.log(logfile, ' X/Y focus factors = %.3f/%.3f' % (wx, wy),
                       True)
            kepmsg.log(logfile, 'PRF rotation angle = %.2f deg' % angle, True)

# constuct model PRF in detector coordinates

    if status == 0:
        PRFfit = kepfunc.PRF2DET(flux, OBJx, OBJy, DATx, DATy, wx, wy, angle,
                                 splineInterpolation)
        if background and bterms == 1:
            PRFfit = PRFfit + b
        if background and bterms > 1:
            PRFfit = PRFfit + bkg

# calculate residual of DATA - FIT

    if status == 0:
        PRFres = DATimg - PRFfit
        FLUXres = numpy.nansum(PRFres)

# calculate the sum squared difference between data and model

    if status == 0:
        Pearson = abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit))
        Chi2 = numpy.nansum(
            numpy.square(DATimg - PRFfit) / numpy.square(ERRimg))
        DegOfFreedom = npix - len(guess)
        try:
            kepmsg.log(logfile, '\nResidual flux = %.6f e-/s' % FLUXres, True)
            kepmsg.log(
                logfile, 'Pearson\'s chi^2 test = %d for %d dof' %
                (Pearson, DegOfFreedom), True)
        except:
            pass
#        kepmsg.log(logfile,'Chi^2 test = %d for %d dof' % (Chi2,DegOfFreedom),True)

# image scale and intensity limits for plotting images

    if status == 0:
        imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg, imscale)
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod, imscale)
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit, imscale)
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres, imscale)
        if imscale == 'linear':
            zmaxpr *= 0.9
        elif imscale == 'logarithmic':
            print zminpr, zmaxpr, numpy.max(zmaxpr)
            zmaxpr = numpy.max(zmaxpr)
            zminpr = zmaxpr / 2

# plot style

    if status == 0:
        try:
            params = {
                'backend': 'png',
                'axes.linewidth': 2.5,
                'axes.labelsize': 24,
                'axes.font': 'sans-serif',
                'axes.fontweight': 'bold',
                'text.fontsize': 12,
                'legend.fontsize': 12,
                'xtick.labelsize': 10,
                'ytick.labelsize': 10
            }
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[10, 10])
        pylab.clf()
        plotimage(imgdat_pl, zminfl, zmaxfl, 1, row, column, xdim, ydim, 0.06,
                  0.52, 'flux', colmap)
        plotimage(imgprf_pl, zminpr, zmaxpr, 2, row, column, xdim, ydim, 0.52,
                  0.52, 'model', colmap)
        kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, 'b',
                        '--', 0.5)
        kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, 'b', '-',
                        3.0)
        plotimage(imgfit_pl, zminfl, zmaxfl, 3, row, column, xdim, ydim, 0.06,
                  0.06, 'fit', colmap)
        plotimage(imgres_pl, zminfl, zmaxfl, 4, row, column, xdim, ydim, 0.52,
                  0.06, 'residual', colmap)

# render plot

    if status == 0 and len(plotfile) > 0 and plotfile.lower() != 'none':
        pylab.savefig(plotfile)
    if status == 0 and plt:
        if cmdLine:
            pylab.show(block=True)
        else:
            pylab.ion()
            pylab.plot([])
            pylab.ioff()

# stop time

    kepmsg.clock('\nKEPPRF ended at', logfile, verbose)

    return
Exemple #5
0
def kepprfphot(infile,outroot,columns,rows,fluxes,border,background,focus,prfdir,ranges,
               tolerance,ftolerance,qualflags,plt,clobber,verbose,logfile,status,cmdLine=False):

# input arguments

    status = 0
    seterr(all="ignore")

# log the call

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPPRFPHOT -- '
    call += 'infile='+infile+' '
    call += 'outroot='+outroot+' '
    call += 'columns='+columns+' '
    call += 'rows='+rows+' '
    call += 'fluxes='+fluxes+' '
    call += 'border='+str(border)+' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background='+bground+' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus='+focs+' '
    call += 'prfdir='+prfdir+' '
    call += 'ranges='+ranges+' '
    call += 'xtol='+str(tolerance)+' '
    call += 'ftol='+str(ftolerance)+' '
    quality = 'n'
    if (qualflags): quality = 'y'
    call += 'qualflags='+quality+' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot='+plotit+' '
    overwrite = 'n'
    if (clobber): overwrite = 'y'
    call += 'clobber='+overwrite+ ' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# start time

    kepmsg.clock('KEPPRFPHOT started at',logfile,verbose)

# number of sources

    if status == 0:
        work = fluxes.strip()
        work = re.sub(' ',',',work)
        work = re.sub(';',',',work)
        nsrc = len(work.split(','))

# construct inital guess vector for fit

    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in xrange(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in xrange(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border+1)*2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0); guess.append(1.0); guess.append(0.0)

# clobber output file

    for i in range(nsrc):
        outfile = '%s_%d.fits' % (outroot, i)
        if clobber: status = kepio.clobber(outfile,logfile,verbose)
        if kepio.fileexists(outfile):
            message = 'ERROR -- KEPPRFPHOT: ' + outfile + ' exists. Use --clobber'
            status = kepmsg.err(logfile,message,verbose)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRFPHOT: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile,message,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, poscorr1, status = \
            kepio.readTPF(infile,'POS_CORR1',logfile,verbose)
        if status != 0:
            poscorr1 = numpy.zeros((len(barytime)),dtype='float32')
            poscorr1[:] = numpy.nan
            status = 0
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, poscorr2, status = \
            kepio.readTPF(infile,'POS_CORR2',logfile,verbose)
        if status != 0:
            poscorr2 = numpy.zeros((len(barytime)),dtype='float32')
            poscorr2[:] = numpy.nan
            status = 0
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)
    if status == 0:
        struct, status = kepio.openfits(infile,'readonly',logfile,verbose)
    if status == 0:
        tstart, tstop, bjdref, cadence, status = kepio.timekeys(struct,infile,logfile,verbose,status)

# input file keywords and mask map

    if status == 0:
        cards0 = struct[0].header.cards
        cards1 = struct[1].header.cards
        cards2 = struct[2].header.cards
        maskmap = copy(struct[2].data)
        npix = numpy.size(numpy.nonzero(maskmap)[0])

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID:  %s' % kepid
        print ' RA (J2000):  %s' % ra
        print 'Dec (J2000): %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:    %2s' % skygroup
        print '     Season:    %2s' % str(season)
        print '    Channel:    %2s' % channel
        print '     Module:    %2s' % module
        print '     Output:     %1s' % output
        print ''

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRFPHOT: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf)
        prf = prf / cdelt1p[0] / cdelt2p[0]

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = ydim / cdelt1p[0]
        prfDimX = xdim / cdelt2p[0]
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# construct input pixel image

    if status == 0:
        DATx = arange(column,column+xdim)
        DATy = arange(row,row+ydim)

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf,kx=3,ky=3)

# construct mesh for background model

    if status == 0:
        bx = numpy.arange(1.,float(xdim+1))
        by = numpy.arange(1.,float(ydim+1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# Get time ranges for new photometry, flag good data

    if status == 0:
        barytime += bjdref
        tstart,tstop,status = kepio.timeranges(ranges,logfile,verbose)
        incl = numpy.zeros((len(barytime)),dtype='int')
        for rownum in xrange(len(barytime)):
            for winnum in xrange(len(tstart)):
                if barytime[rownum] >= tstart[winnum] and \
                        barytime[rownum] <= tstop[winnum] and \
                        (qual[rownum] == 0 or qualflags) and \
                        numpy.isfinite(barytime[rownum]) and \
                        numpy.isfinite(numpy.nansum(fluxpixels[rownum,:])):
                    incl[rownum] = 1
        if not numpy.in1d(1,incl):
            message = 'ERROR -- KEPPRFPHOT: No legal data within the range ' + ranges
            status = kepmsg.err(logfile,message,verbose)

# filter out bad data

    if status == 0:
        n = 0
        nincl = (incl == 1).sum()
        tim = zeros((nincl),'float64')
        tco = zeros((nincl),'float32')
        cad = zeros((nincl),'float32')
        flu = zeros((nincl,len(fluxpixels[0])),'float32')
        fer = zeros((nincl,len(fluxpixels[0])),'float32')
        pc1 = zeros((nincl),'float32')
        pc2 = zeros((nincl),'float32')
        qua = zeros((nincl),'float32')
        for rownum in xrange(len(barytime)):
            if incl[rownum] == 1:
                tim[n] = barytime[rownum]
                tco[n] = tcorr[rownum]
                cad[n] = cadno[rownum]
                flu[n,:] = fluxpixels[rownum]
                fer[n,:] = errpixels[rownum]
                pc1[n] = poscorr1[rownum]
                pc2[n] = poscorr2[rownum]
                qua[n] = qual[rownum]
                n += 1
        barytime = tim * 1.0
        tcorr = tco * 1.0
        cadno = cad * 1.0
        fluxpixels = flu * 1.0
        errpixels = fer * 1.0
        poscorr1 = pc1 * 1.0
        poscorr2 = pc2 * 1.0
        qual = qua * 1.0

# initialize plot arrays

    if status == 0:
        t = numpy.array([],dtype='float64')
        fl = []; dx = []; dy = []; bg = []; fx = []; fy = []; fa = []; rs = []; ch = []
        for i in range(nsrc):
            fl.append(numpy.array([],dtype='float32'))
            dx.append(numpy.array([],dtype='float32'))
            dy.append(numpy.array([],dtype='float32'))

# Preparing fit data message

    if status == 0:
        progress = numpy.arange(nincl)
        if verbose:
            txt  = 'Preparing...'
            sys.stdout.write(txt)
            sys.stdout.flush()

# single processor version

    if status == 0:# and not cmdLine:
        oldtime = 0.0
        for rownum in xrange(numpy.min([80,len(barytime)])):
            try:
                if barytime[rownum] - oldtime > 0.5:
                    ftol = 1.0e-10; xtol = 1.0e-10
            except:
                pass
            args = (fluxpixels[rownum,:],errpixels[rownum,:],DATx,DATy,nsrc,border,xx,yy,PRFx,PRFy,splineInterpolation,
                    guess,ftol,xtol,focus,background,rownum,80,float(x[i]),float(y[i]),False)
            guess = PRFfits(args)
            ftol = ftolerance; xtol = tolerance; oldtime = barytime[rownum]

# Fit the time series: multi-processing

    if status == 0 and cmdLine:
        anslist = []
        cad1 = 0; cad2 = 50
        for i in range(int(nincl/50) + 1):
            try:
                fluxp = fluxpixels[cad1:cad2,:]
                errp = errpixels[cad1:cad2,:]
                progress = numpy.arange(cad1,cad2)
            except:
                fluxp = fluxpixels[cad1:nincl,:]
                errp = errpixels[cad1:nincl,:]
                progress = numpy.arange(cad1,nincl)
            try:
                args = itertools.izip(fluxp,errp,itertools.repeat(DATx),itertools.repeat(DATy),
                                      itertools.repeat(nsrc),itertools.repeat(border),itertools.repeat(xx),
                                      itertools.repeat(yy),itertools.repeat(PRFx),itertools.repeat(PRFy),
                                      itertools.repeat(splineInterpolation),itertools.repeat(guess),
                                      itertools.repeat(ftolerance),itertools.repeat(tolerance),
                                      itertools.repeat(focus),itertools.repeat(background),progress,
                                      itertools.repeat(numpy.arange(cad1,nincl)[-1]),
                                      itertools.repeat(float(x[0])),
                                      itertools.repeat(float(y[0])),itertools.repeat(True))
                p = multiprocessing.Pool()
                model = [0.0]
                model = p.imap(PRFfits,args,chunksize=1)
                p.close()
                p.join()
                cad1 += 50; cad2 += 50
                ans = array([array(item) for item in zip(*model)])
                try:
                    anslist = numpy.concatenate((anslist,ans.transpose()),axis=0)
                except:
                    anslist = ans.transpose()
                guess = anslist[-1]
                ans = anslist.transpose()
            except:
                pass

# single processor version

    if status == 0 and not cmdLine:
        oldtime = 0.0; ans = []
#        for rownum in xrange(1,10):
        for rownum in xrange(nincl):
            proctime = time.time()
            try:
                if barytime[rownum] - oldtime > 0.5:
                    ftol = 1.0e-10; xtol = 1.0e-10
            except:
                pass
            args = (fluxpixels[rownum,:],errpixels[rownum,:],DATx,DATy,nsrc,border,xx,yy,PRFx,PRFy,splineInterpolation,
                    guess,ftol,xtol,focus,background,rownum,nincl,float(x[0]),float(y[0]),True)
            guess = PRFfits(args)
            ans.append(guess)
            ftol = ftolerance; xtol = tolerance; oldtime = barytime[rownum]
        ans = array(ans).transpose()

# unpack the best fit parameters

    if status == 0:
        flux = []; OBJx = []; OBJy = []
        na = shape(ans)[1]
        for i in range(nsrc):
            flux.append(ans[i,:])
            OBJx.append(ans[nsrc+i,:])
            OBJy.append(ans[nsrc*2+i,:])
        try:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc*3,:]
            else:
                b = array([])
                bkg = []
                for i in range(na):
                    bcoeff = array([ans[nsrc*3:nsrc*3+bterms,i],ans[nsrc*3+bterms:nsrc*3+bterms*2,i]])
                    bkg.append(kepfunc.polyval2d(xx,yy,bcoeff))
                    b = numpy.append(b,nanmean(bkg[-1].reshape(bkg[-1].size)))
        except:
            b = zeros((na))
        if focus:
            wx = ans[-3,:]; wy = ans[-2,:]; angle = ans[-1,:]
        else:
            wx = ones((na)); wy = ones((na)); angle = zeros((na))

# constuct model PRF in detector coordinates

    if status == 0:
        residual = []; chi2 = []
        for i in range(na):
            f = empty((nsrc))
            x = empty((nsrc))
            y = empty((nsrc))
            for j in range(nsrc):
                f[j] = flux[j][i]
                x[j] = OBJx[j][i]
                y[j] = OBJy[j][i]
            PRFfit = kepfunc.PRF2DET(f,x,y,DATx,DATy,wx[i],wy[i],angle[i],splineInterpolation)
            if background and bterms == 1:
                PRFfit = PRFfit + b[i]
            if background and bterms > 1:
                PRFfit = PRFfit + bkg[i]

# calculate residual of DATA - FIT

            xdim = shape(xx)[1]
            ydim = shape(yy)[0]
            DATimg = numpy.empty((ydim,xdim))
            n = 0
            for k in range(ydim):
                for j in range(xdim):
                    DATimg[k,j] = fluxpixels[i,n]
                    n += 1
            PRFres = DATimg - PRFfit
            residual.append(numpy.nansum(PRFres) / npix)

# calculate the sum squared difference between data and model

            chi2.append(abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit)))

# load the output arrays

    if status == 0:
        otime = barytime - bjdref
        otimecorr = tcorr
        ocadenceno = cadno
        opos_corr1 = poscorr1
        opos_corr2 = poscorr2
        oquality = qual
        opsf_bkg = b
        opsf_focus1 = wx
        opsf_focus2 = wy
        opsf_rotation = angle
        opsf_residual = residual
        opsf_chi2 = chi2
        opsf_flux_err = numpy.empty((na)); opsf_flux_err.fill(numpy.nan)
        opsf_centr1_err = numpy.empty((na)); opsf_centr1_err.fill(numpy.nan)
        opsf_centr2_err = numpy.empty((na)); opsf_centr2_err.fill(numpy.nan)
        opsf_bkg_err = numpy.empty((na)); opsf_bkg_err.fill(numpy.nan)
        opsf_flux = []
        opsf_centr1 = []
        opsf_centr2 = []
        for i in range(nsrc):
            opsf_flux.append(flux[i])
            opsf_centr1.append(OBJx[i])
            opsf_centr2.append(OBJy[i])

# load the plot arrays

    if status == 0:
        t = barytime
        for i in range(nsrc):
            fl[i] = flux[i]
            dx[i] = OBJx[i]
            dy[i] = OBJy[i]
        bg = b
        fx = wx
        fy = wy
        fa = angle
        rs = residual
        ch = chi2

# construct output primary extension

    if status == 0:
        for j in range(nsrc):
            hdu0 = pyfits.PrimaryHDU()
            for i in range(len(cards0)):
                if cards0[i].key not in hdu0.header.keys():
                    hdu0.header.update(cards0[i].key, cards0[i].value, cards0[i].comment)
                else:
                    hdu0.header.cards[cards0[i].key].comment = cards0[i].comment
            status = kepkey.history(call,hdu0,outfile,logfile,verbose)
            outstr = HDUList(hdu0)

# construct output light curve extension

            col1 = Column(name='TIME',format='D',unit='BJD - 2454833',array=otime)
            col2 = Column(name='TIMECORR',format='E',unit='d',array=otimecorr)
            col3 = Column(name='CADENCENO',format='J',array=ocadenceno)
            col4 = Column(name='PSF_FLUX',format='E',unit='e-/s',array=opsf_flux[j])
            col5 = Column(name='PSF_FLUX_ERR',format='E',unit='e-/s',array=opsf_flux_err)
            col6 = Column(name='PSF_BKG',format='E',unit='e-/s/pix',array=opsf_bkg)
            col7 = Column(name='PSF_BKG_ERR',format='E',unit='e-/s',array=opsf_bkg_err)
            col8 = Column(name='PSF_CENTR1',format='E',unit='pixel',array=opsf_centr1[j])
            col9 = Column(name='PSF_CENTR1_ERR',format='E',unit='pixel',array=opsf_centr1_err)
            col10 = Column(name='PSF_CENTR2',format='E',unit='pixel',array=opsf_centr2[j])
            col11 = Column(name='PSF_CENTR2_ERR',format='E',unit='pixel',array=opsf_centr2_err)
            col12 = Column(name='PSF_FOCUS1',format='E',array=opsf_focus1)
            col13 = Column(name='PSF_FOCUS2',format='E',array=opsf_focus2)
            col14 = Column(name='PSF_ROTATION',format='E',unit='deg',array=opsf_rotation)
            col15 = Column(name='PSF_RESIDUAL',format='E',unit='e-/s',array=opsf_residual)
            col16 = Column(name='PSF_CHI2',format='E',array=opsf_chi2)
            col17 = Column(name='POS_CORR1',format='E',unit='pixel',array=opos_corr1)
            col18 = Column(name='POS_CORR2',format='E',unit='pixel',array=opos_corr2)
            col19 = Column(name='SAP_QUALITY',format='J',array=oquality)
            cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,
                            col12,col13,col14,col15,col16,col17,col18,col19])
            hdu1 = new_table(cols)
            for i in range(len(cards1)):
                if (cards1[i].key not in hdu1.header.keys() and
                    cards1[i].key[:4] not in ['TTYP','TFOR','TUNI','TDIS','TDIM','WCAX','1CTY',
                                              '2CTY','1CRP','2CRP','1CRV','2CRV','1CUN','2CUN',
                                              '1CDE','2CDE','1CTY','2CTY','1CDL','2CDL','11PC',
                                              '12PC','21PC','22PC']):
                    hdu1.header.update(cards1[i].key, cards1[i].value, cards1[i].comment)
            outstr.append(hdu1)

# construct output mask bitmap extension

            hdu2 = ImageHDU(maskmap)
            for i in range(len(cards2)):
                if cards2[i].key not in hdu2.header.keys():
                    hdu2.header.update(cards2[i].key, cards2[i].value, cards2[i].comment)
                else:
                    hdu2.header.cards[cards2[i].key].comment = cards2[i].comment
            outstr.append(hdu2)

# write output file

            outstr.writeto(outroot + '_' + str(j) + '.fits',checksum=True)

# close input structure

            status = kepio.closefits(struct,logfile,verbose)

# clean up x-axis unit

    if status == 0:
	barytime0 = float(int(t[0] / 100) * 100.0)
	t -= barytime0
        t = numpy.insert(t,[0],[t[0]])
        t = numpy.append(t,[t[-1]])
        xlab = 'BJD $-$ %d' % barytime0

# plot the light curves

    if status == 0:
        bg = numpy.insert(bg,[0],[-1.0e10])
        bg = numpy.append(bg,-1.0e10)
        fx = numpy.insert(fx,[0],[fx[0]])
        fx = numpy.append(fx,fx[-1])
        fy = numpy.insert(fy,[0],[fy[0]])
        fy = numpy.append(fy,fy[-1])
        fa = numpy.insert(fa,[0],[fa[0]])
        fa = numpy.append(fa,fa[-1])
        rs = numpy.insert(rs,[0],[-1.0e10])
        rs = numpy.append(rs,-1.0e10)
        ch = numpy.insert(ch,[0],[-1.0e10])
        ch = numpy.append(ch,-1.0e10)
        for i in range(nsrc):

# clean up y-axis units

            nrm = math.ceil(math.log10(numpy.nanmax(fl[i]))) - 1.0
            fl[i] /= 10**nrm
            if nrm == 0:
                ylab1 = 'e$^-$ s$^{-1}$'
            else:
                ylab1 = '10$^{%d}$ e$^-$ s$^{-1}$' % nrm
            xx = copy(dx[i])
            yy = copy(dy[i])
            ylab2 = 'offset (pixels)'

# data limits

            xmin = numpy.nanmin(t)
            xmax = numpy.nanmax(t)
            ymin1 = numpy.nanmin(fl[i])
            ymax1 = numpy.nanmax(fl[i])
            ymin2 = numpy.nanmin(xx)
            ymax2 = numpy.nanmax(xx)
            ymin3 = numpy.nanmin(yy)
            ymax3 = numpy.nanmax(yy)
            ymin4 = numpy.nanmin(bg[1:-1])
            ymax4 = numpy.nanmax(bg[1:-1])
            ymin5 = numpy.nanmin([numpy.nanmin(fx),numpy.nanmin(fy)])
            ymax5 = numpy.nanmax([numpy.nanmax(fx),numpy.nanmax(fy)])
            ymin6 = numpy.nanmin(fa[1:-1])
            ymax6 = numpy.nanmax(fa[1:-1])
            ymin7 = numpy.nanmin(rs[1:-1])
            ymax7 = numpy.nanmax(rs[1:-1])
            ymin8 = numpy.nanmin(ch[1:-1])
            ymax8 = numpy.nanmax(ch[1:-1])
            xr = xmax - xmin
            yr1 = ymax1 - ymin1
            yr2 = ymax2 - ymin2
            yr3 = ymax3 - ymin3
            yr4 = ymax4 - ymin4
            yr5 = ymax5 - ymin5
            yr6 = ymax6 - ymin6
            yr7 = ymax7 - ymin7
            yr8 = ymax8 - ymin8
            fl[i] = numpy.insert(fl[i],[0],[0.0])
            fl[i] = numpy.append(fl[i],0.0)

# plot style

            try:
                params = {'backend': 'png',
                          'axes.linewidth': 2.5,
                          'axes.labelsize': 24,
                          'axes.font': 'sans-serif',
                          'axes.fontweight' : 'bold',
                          'text.fontsize': 12,
                          'legend.fontsize': 12,
                          'xtick.labelsize': 12,
                          'ytick.labelsize': 12}
                pylab.rcParams.update(params)
            except:
                pass

# define size of plot on monitor screen

            pylab.figure(str(i+1) + ' ' + str(time.asctime(time.localtime())),figsize=[12,16])

# delete any fossil plots in the matplotlib window

            pylab.clf()

# position first axes inside the plotting window

            ax = pylab.axes([0.11,0.523,0.78,0.45])

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))

# no x-label

            pylab.setp(pylab.gca(),xticklabels=[])

# plot flux vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,fl[i][j])
                else:
                    pylab.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            pylab.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,fl[i],fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            if ymin1 - yr1 * 0.01 <= 0.0:
                pylab.ylim(1.0e-10, ymax1 + yr1 * 0.01)
            else:
                pylab.ylim(ymin1 - yr1 * 0.01, ymax1 + yr1 * 0.01)

# plot labels

#            pylab.xlabel(xlab, {'color' : 'k'})
            try:
                pylab.ylabel('Source (' + ylab1 + ')', {'color' : 'k'})
            except:
                ylab1 = '10**%d e-/s' % nrm
                pylab.ylabel('Source (' + ylab1 + ')', {'color' : 'k'})

# make grid on plot

            pylab.grid()

# plot centroid tracks - position second axes inside the plotting window

            if focus and background:
                axs = [0.11,0.433,0.78,0.09]
            elif background or focus:
                axs = [0.11,0.388,0.78,0.135]
            else:
                axs = [0.11,0.253,0.78,0.27]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot dx vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,xx[j-1])
                else:
                    ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin2 - yr2 * 0.03, ymax2 + yr2 * 0.03)

# plot labels

            ax1.set_ylabel('X-' + ylab2, color='k', fontsize=11)

# position second axes inside the plotting window

            ax2 = ax1.twinx()

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot dy vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,yy[j-1])
                else:
                    ax2.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax2.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)

# define plot y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin3 - yr3 * 0.03, ymax3 + yr3 * 0.03)

# plot labels

            ax2.set_ylabel('Y-' + ylab2, color='k',fontsize=11)

# background - position third axes inside the plotting window

            if background and focus:
                axs = [0.11,0.343,0.78,0.09]
            if background and not focus:
                axs = [0.11,0.253,0.78,0.135]
            if background:
                ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot background vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,bg[j])
                    else:
                        ax1.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

                pylab.fill(t,bg,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin4 - yr4 * 0.03, ymax4 + yr4 * 0.03)

# plot labels

                ax1.set_ylabel('Background \n(e$^-$ s$^{-1}$ pix$^{-1}$)',
                               multialignment='center', color='k',fontsize=11)

# make grid on plot

                pylab.grid()

# position focus axes inside the plotting window

            if focus and background:
                axs = [0.11,0.253,0.78,0.09]
            if focus and not background:
                axs = [0.11,0.253,0.78,0.135]
            if focus:
                ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot x-axis PSF width vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fx[j])
                    else:
                        ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)

# plot y-axis PSF width vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fy[j])
                    else:
                        ax1.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)

# define plot x and y limits

                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin5 - yr5 * 0.03, ymax5 + yr5 * 0.03)

# plot labels

                ax1.set_ylabel('Pixel Scale\nFactor',
                               multialignment='center', color='k',fontsize=11)

# Focus rotation - position second axes inside the plotting window

                ax2 = ax1.twinx()

# force tick labels to be absolute rather than relative

                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot dy vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fa[j])
                    else:
                        ax2.plot(ltime,ldata,color='#000080',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax2.plot(ltime,ldata,color='#000080',linestyle='-',linewidth=1.0)

# define plot y limits

                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin6 - yr6 * 0.03, ymax6 + yr6 * 0.03)

# plot labels

                ax2.set_ylabel('Rotation (deg)', color='k',fontsize=11)

# fit residuals - position fifth axes inside the plotting window

            axs = [0.11,0.163,0.78,0.09]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot residual vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,rs[j])
                else:
                    ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,rs,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin7 - yr7 * 0.03, ymax7 + yr7 * 0.03)

# plot labels

            ax1.set_ylabel('Residual \n(e$^-$ s$^{-1}$)',
                           multialignment='center', color='k',fontsize=11)

# make grid on plot

            pylab.grid()

# fit chi square - position sixth axes inside the plotting window

            axs = [0.11,0.073,0.78,0.09]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))

# plot background vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,ch[j])
                else:
                    ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,ch,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin8 - yr8 * 0.03, ymax8 + yr8 * 0.03)

# plot labels

            ax1.set_ylabel('$\chi^2$ (%d dof)' % (npix-len(guess)-1),color='k',fontsize=11)
            pylab.xlabel(xlab, {'color' : 'k'})

# make grid on plot

            pylab.grid()

# render plot

            if status == 0:
                pylab.savefig(outroot + '_' + str(i) + '.png')
            if status == 0 and plt:
                if cmdLine:
                    pylab.show(block=True)
                else:
                    pylab.ion()
                    pylab.plot([])
                    pylab.ioff()

# stop time

    kepmsg.clock('\n\nKEPPRFPHOT ended at',logfile,verbose)

    return
Exemple #6
0
def kepfake(outfile,prfdir,module,output,column,row,kepmag,background,xdim,ydim,
            clobber,verbose,logfile,status,cmdLine=False): 

# input arguments

    status = 0
    seterr(all="ignore") 

# log the call 

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPFAKE -- '
    call += 'outfile='+outfile+' '
    call += 'prfdir='+prfdir+' '
    call += 'module='+str(module)+' '
    call += 'output='+str(output)+' '
    call += 'column='+str(column)+' '
    call += 'row='+str(row)+' '
    call += 'kepmag='+str(kepmag)+' '
    call += 'background='+str(background)+' '
    call += 'xdim='+str(xdim)+' '
    call += 'ydim='+str(ydim)+' '
    clob = 'n'
    if (clobber): clob = 'y'
    call += 'clobber='+clob+' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# plot style

    if status == 0:
        try:
            params = {'backend': 'png',
                      'axes.linewidth': 2.5,
                      'axes.labelsize': 24,
                      'axes.font': 'sans-serif',
                      'axes.fontweight' : 'bold',
                      'text.fontsize': 12,
                      'legend.fontsize': 12,
                      'xtick.labelsize': 10,
                      'ytick.labelsize': 10}
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[12,12])
        pylab.clf()

# start time

    kepmsg.clock('KEPFAKE started at',logfile,verbose)

# clobber output file

    if status == 0:
        if clobber: status = kepio.clobber(outfile,logfile,verbose)
        if kepio.fileexists(outfile): 
            message = 'ERROR -- KEPPRFPHOT: ' + outfile + ' exists. Use --clobber'
            status = kepmsg.err(logfile,message,verbose)

# Create time-tagged arrays

    if status == 0:
        nobs = 192
        time = zeros((nobs))
        timecorr = zeros((nobs))
        cadenceno = zeros((nobs))
        raw_cnts = zeros((nobs,ydim,xdim))
        flux = zeros((nobs,ydim,xdim))
        flux_err = zeros((nobs,ydim,xdim))
        flux_bkg = zeros((nobs,ydim,xdim))
        flux_bkg_err = zeros((nobs,ydim,xdim))
        cosmic_rays = zeros((nobs,ydim,xdim))
        quality = zeros((nobs))
        pos_corr1 = zeros((nobs))
        pos_corr2 = zeros((nobs))

# Create aperture bit mqp

    if status == 0:
        aperture = ones((ydim,xdim)) * 3.0

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPFAKE: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)    
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in range(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0: prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf) / cdelt1p[0] / cdelt2p[0]

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf,kx=3,ky=3)

# flux from target

    if status == 0:
        zeropoint = 33.227
        kepflux = 10.0**((zeropoint - kepmag) / 2.5)

# range of the output image in detector coordinates
        
    if status == 0:
        if xdim % 2  == 0: xdim += 1
        if ydim % 2  == 0: ydim += 1
        DATx = arange(round(column) - floor(xdim/2),round(column) + floor(xdim/2) + 1.0)
        DATy = arange(round(row) - floor(ydim/2),round(row) + floor(ydim/2) + 1.0)
    ax = pylab.axes([0.05,0.5,0.45,0.45])
    pylab.imshow(log10(prf+0.001),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(PRFx),max(PRFx),min(PRFy),max(PRFy)))
    pylab.plot([-100.,100.],[0.0,0.0],'k',ls='--')
    pylab.plot([0.0,0.0],[-100.,100.],'k',ls='--')
    pylab.xlim(min(PRFx),max(PRFx))
    pylab.ylim(min(PRFy),max(PRFy))
    ax = pylab.axes([0.5,0.5,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx),0.1) + floor(column)
    TMPy = arange(min(PRFy),max(PRFy),0.1) + floor(row)
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx),max(TMPx),min(TMPy),max(TMPy)))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    ax = pylab.axes([0.05,0.05,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx),0.5) + floor(column)
    TMPy = arange(min(PRFy),max(PRFy),0.5) + floor(row)
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx),max(TMPx),min(TMPy),max(TMPy)))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    ax = pylab.axes([0.5,0.05,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx+1.0),1.0) + floor(column) - 0.5
    TMPy = arange(min(PRFy),max(PRFy+1.0),1.0) + floor(row) - 0.5
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx)-0.5,max(TMPx)-0.5,min(TMPy)-0.5,max(TMPy)-0.5))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    pylab.ion()
    pylab.plot([])
    pylab.ioff()
#    sys.exit()

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# iterate over each exposure

    if status == 0:
        for i in range(nobs):
#        for i in range(1):

# constuct model PRF in detector coordinates

            if status == 0:
                PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],DATx,DATy,1.0,1.0,0.0,splineInterpolation)
                PRFfit = PRFfit + background

# add noise to image

            if status == 0:
                for index,value in ndenumerate(PRFfit):
                    PRFfit[index] += sqrt(value) * kepfunc.inv_normal_cummulative_function(random.random())

# populate output array

            if status == 0:
                time[i] = 1500.2 + float(i) * 0.020416667
                cadenceno[i] = 10000 + i
                flux[i,:,:] = PRFfit
                flux_err[i,:,:] = sqrt(PRFfit)

    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(DATx),max(DATx),min(DATy),max(DATy)))
    pylab.ion()
    pylab.plot([])
    pylab.ioff()
            
# Create the outfile primary extension

    if status == 0:
        hdu0 = PrimaryHDU()
        hdu0.header.update('EXTNAME','PRIMARY','name of extension')
        hdu0.header.update('EXTEND',True,'file may contain standard extensions')
        hdu0.header.update('EXTVER',1.0,'extension version number')
        hdu0.header.update('ORIGIN','NASA/Ames','organization that generated this file')
        hdu0.header.update('DATE','2014-04-08','file creation date')
        hdu0.header.update('CREATOR','FluxExporter-91415','SW version used to create this file')
        hdu0.header.update('PROCVER',11.0,'processing script version')
        hdu0.header.update('FILEVER','COA','file format version')
        hdu0.header.update('TIMVERSN','OGIP/93-003','OGIP memo number for file format')
        hdu0.header.update('TELESCOP','Kepler','telescope')
        hdu0.header.update('INSTRUME','Kepler photometer','detector type')
        hdu0.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu0.header.update('KEPLERID',1234567,'unique Kepler target identifier')
        hdu0.header.update('CHANNEL',58,'CCD channel')
        hdu0.header.update('SKYGROUP',32,'roll-independent location of channel')
        hdu0.header.update('MODULE',17,'CCD module')
        hdu0.header.update('OUTPUT',2,'CCD output')
        hdu0.header.update('QUARTER',4,'mission quarter during which data was collected')
        hdu0.header.update('SEASON',2,'mission season during which data was collected')
        hdu0.header.update('DATA_REL',25,'version of data release notes describing data')
        hdu0.header.update('OBSMODE','long cadence','observing mode')
        hdu0.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu0.header.update('RA_OBJ',0.0,'[deg] right ascension from KIC')
        hdu0.header.update('DEC_OBJ',0.0,'[deg] declination from KIC')
        hdu0.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu0.header.update('PMRA',0.0,'[arcsec/yr] RA proper motion')
        hdu0.header.update('PMDEC',0.0,'[arcsec/yr] Dec proper motion')
        hdu0.header.update('PMTOTAL',0.0,'[arcsec/yr] total proper motion')
        hdu0.header.update('PARALLAX',0.0,'[arcsec] parallax')
        hdu0.header.update('GLON',0.0,'[deg] galactic longitude')
        hdu0.header.update('GLAT',0.0,'[deg] galactic latitude')
        hdu0.header.update('GMAG',kepmag,'[mag] SDSS g band magnitude from KIC')
        hdu0.header.update('RMAG',kepmag,'[mag] SDSS r band magnitude from KIC')
        hdu0.header.update('IMAG',kepmag,'[mag] SDSS i band magnitude from KIC')
        hdu0.header.update('ZMAG',kepmag,'[mag] SDSS z band magnitude from KIC')
        hdu0.header.update('D51MAG',kepmag,'[mag] D51 magnitude, from KIC')
        hdu0.header.update('JMAG',kepmag,'[mag] J band magnitude from 2MASS')
        hdu0.header.update('HMAG',kepmag,'[mag] H band magnitude from 2MASS')
        hdu0.header.update('KMAG',kepmag,'[mag] K band magnitude from 2MASS')
        hdu0.header.update('KEPMAG',kepmag,'[mag] Kepler magnitude (Kp) from KIC')
        hdu0.header.update('GRCOLOR',0.0,'[mag] (g-r) color, SDSS bands')
        hdu0.header.update('JKCOLOR',0.0,'[mag] (J-K) color, 2MASS bands')
        hdu0.header.update('GKCOLOR',0.0,'[mag] (g-K) color, SDSS g - 2MASS K')
        hdu0.header.update('TEFF',5000.0,'[K] effective temperature from KIC')
        hdu0.header.update('LOGG',4.5,'[cm/s2] log10 surface gravity from KIC')
        hdu0.header.update('FEH',0.0,'[log10([Fe/H])] metallicity from KIC')
        hdu0.header.update('EBMINUSV',0.0,'[mag] E(B-V) redenning from KIC')
        hdu0.header.update('AV',0.0,'[mag] A_v extinction from KIC')
        hdu0.header.update('RADIUS',1.0,'[solar radii] stellar radius from KIC')
        hdu0.header.update('TMINDEX',1117146912,'unique 2MASS catalog ID from KIC')
        hdu0.header.update('SCPID',1117146912,'unique SCP processing ID from KIC') 
        hdulist = HDUList(hdu0)

# create the outfile table extension

    if status == 0:
        eformat = str(ydim*xdim) + 'E'
        jformat = str(ydim*xdim) + 'J'
        kformat = str(ydim*xdim) + 'K'
        coldim = '(' + str(ydim) + ',' + str(ydim) + ')'
        col1 = Column(name='TIME',format='D',unit='BJD - 2454833',array=time)
        col2 = Column(name='TIMECORR',format='E',unit='d',array=timecorr)
        col3 = Column(name='CADENCENO',format='J',array=cadenceno)
        col4 = Column(name='RAW_CNTS',format=jformat,unit='count',dim=coldim,array=raw_cnts)
        col5 = Column(name='FLUX',format=eformat,unit='e-/s',dim=coldim,array=flux)
        col6 = Column(name='FLUX_ERR',format=eformat,unit='e-/s',dim=coldim,array=flux_err)
        col7 = Column(name='FLUX_BKG',format=eformat,unit='e-/s',dim=coldim,array=flux_bkg)
        col8 = Column(name='FLUX_BKG_ERR',format=eformat,unit='e-/s',dim=coldim,array=flux_bkg_err)
        col9 = Column(name='COSMIC_RAYS',format=eformat,unit='e-/s',dim=coldim,array=cosmic_rays)
        col10 = Column(name='QUALITY',format='J',array=quality)
        col11 = Column(name='POS_CORR1',format='E',unit='pixel',array=pos_corr1)
        col12 = Column(name='POS_CORR2',format='E',unit='pixel',array=pos_corr2)
        cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12])
        hdu1 = new_table(cols)
        hdu1.header.update('TTYPE1','TIME','column title: data time stamps')
        hdu1.header.update('TFORM1','D','data type: float64')
        hdu1.header.update('TUNIT1','BJD - 2454833','column units: barycenter corrected JD')
        hdu1.header.update('TDISP1','D13.7','column display format')
        hdu1.header.update('TTYPE2','TIMECORR','column title: barycentric correction')
        hdu1.header.update('TFORM2','E','column format: float32')
        hdu1.header.update('TUNIT2','d','column units: days')
        hdu1.header.update('TDISP2','D12.7','column display format')
        hdu1.header.update('TTYPE3','CADENCENO','column title: unique cadence number')
        hdu1.header.update('TFORM3','J','column format: signed integer32')
        hdu1.header.update('TTYPE4','RAW_CNTS','column title: raw pixel count')
        hdu1.header.update('TFORM4',jformat,'column format: signed integer32')
        hdu1.header.update('TDIM4',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT4','count','column units: count')
        hdu1.header.update('TTYPE5','FLUX','column title: calibrated pixel flux')
        hdu1.header.update('TFORM5',eformat,'column format: float32')
        hdu1.header.update('TDIM5',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT5','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE6','FLUX_ERR','column title: 1-sigma calibrated uncertainty')
        hdu1.header.update('TFORM6',eformat,'column format: float32')
        hdu1.header.update('TDIM6',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT6','e-/s','column units: electrons per second (1-sigma)')
        hdu1.header.update('TTYPE7','FLUX_BKG','column title: calibrated background flux')
        hdu1.header.update('TFORM7',eformat,'column format: float32')
        hdu1.header.update('TDIM7',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT7','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE8','FLUX_BKG_ERR','column title: 1-sigma cal. backgrnd uncertainty')
        hdu1.header.update('TFORM8',eformat,'column format: float32')
        hdu1.header.update('TDIM8',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT8','e-/s','column units: electrons per second (1-sigma)')
        hdu1.header.update('TTYPE9','COSMIC_RAYS','column title: cosmic ray detections')
        hdu1.header.update('TFORM9',eformat,'column format: float32')
        hdu1.header.update('TDIM9',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT9','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE10','QUALITY','column title: pixel quality flags')
        hdu1.header.update('TFORM10','J','column format: signed integer32')
        hdu1.header.update('TTYPE11','POS_CORR1','column title: col correction for vel. abbern')
        hdu1.header.update('TFORM11','E','column format: float32')
        hdu1.header.update('TUNIT11','pixel','column units: pixel')
        hdu1.header.update('TTYPE12','POS_CORR2','column title: row correction for vel. abbern')
        hdu1.header.update('TFORM12','E','column format: float32')
        hdu1.header.update('TUNIT12','pixel','column units: pixel')
        hdu1.header.update('WCAX4',2,'number of WCS axes')
        hdu1.header.update('1CTY4P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY4P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP4P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP4P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV4P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV4P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN4P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN4P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE4P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE4P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP4','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP4','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX4',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX4',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL4',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL4',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI4','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI4','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT4',-0.001106815552144,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT4',0.001106815552144,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC4',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC4',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC4',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC4',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX5',2,'number of WCS axes')
        hdu1.header.update('1CTY5P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY5P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP5P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP5P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV5P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV5P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN5P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN5P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE5P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE5P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP5','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP5','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX5',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX5',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL5',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL5',43.80033,'[deg] declination at reference pixel [deg]')
        hdu1.header.update('1CUNI5','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI5','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT5',-0.001106815552144,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT5',0.001106815552144,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC5',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC5',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC5',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC5',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX6',2,'number of WCS axes')
        hdu1.header.update('1CTY6P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY6P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP6P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP6P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV6P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV6P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN6P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN6P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE6P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE6P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP6','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP6','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX6',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX6',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL6',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL6',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI6','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI6','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT6',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT6',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC6',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC6',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC6',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC6',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX7',2,'number of WCS axes')
        hdu1.header.update('1CTY7P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY7P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP7P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP7P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV7P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV7P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN7P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN7P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE7P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE7P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP7','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP7','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX7',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX7',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL7',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL7',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI7','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI7','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT7',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT7',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC7',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC7',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC7',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC7',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX8',2,'number of WCS axes')
        hdu1.header.update('1CTY8P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY8P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP8P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP8P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV8P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV8P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN8P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN8P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE8P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE8P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP8','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP8','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX8',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX8',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL8',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL8',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI8','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI8','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT8',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT8',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC8',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC8',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC8',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC8',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX9',2,'number of WCS axes')
        hdu1.header.update('1CTY9P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY9P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP9P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP9P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV9P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV9P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN9P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN9P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE9P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE9P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP9','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP9','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX9',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX9',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL9',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL9',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI9','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI9','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT9',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT9',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC9',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC9',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC9',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC9',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX10',2,'number of WCS axes')
        hdu1.header.update('1CTY10P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY10P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP10P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP10P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV10P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV10P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN10P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN10P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE10P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE10P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP10','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP10','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX10',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX10',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL10',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL10',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI10','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI10','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT10',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT10',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC10',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC10',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC10',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC10',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('INHERIT',True,'inherit primary keywords')
        hdu1.header.update('EXTNAME','TARGETTABLES','name of extension')
        hdu1.header.update('EXTVER',1,'extension version number')
        hdu1.header.update('TELESCOP','Kepler','telescope')
        hdu1.header.update('INSTRUME','Kepler photometer','detector type')
        hdu1.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu1.header.update('KEPLERID',12345678,'unique Kepler target identifier')
        hdu1.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu1.header.update('RA_OBJ',0.0,'[deg] right ascension from KIC')
        hdu1.header.update('DEC_OBJ',0.0,'[deg] declination from KIC')
        hdu1.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu1.header.update('TIMEREF','SOLARSYSTEM','barycentric correction applied to times')
        hdu1.header.update('TASSIGN','SPACECRAFT','where time is assigned')
        hdu1.header.update('TIMESYS','TDB','time system is barycentric JD')
        hdu1.header.update('BJDREFI',2454833,'integer part of BJD reference date')
        hdu1.header.update('BJDREFF',0.0,'fraction of day in BJD reference date')
        hdu1.header.update('TIMEUNIT','d','time unit for TIME, TSTART and TSTOP')
        hdu1.header.update('TSTART',1500.0,'observation start time in JD - BJDREF')
        hdu1.header.update('TSTOP',1504.0,'observation stop time in JD - BJDREF')
        hdu1.header.update('LC_START',1500.0+54833.5,'observation start time in MJD')
        hdu1.header.update('LC_END',1504.0+54833.5,'observation stop time in MJD')
        hdu1.header.update('TELAPSE',93.0,'[d] TSTOP - TSTART')
        hdu1.header.update('LIVETIME',82.7273,'[d] TELAPSE multiplied by DEADC')
        hdu1.header.update('EXPOSURE',82.7273,'[d] time on source')
        hdu1.header.update('DEADC',0.909091,'deadtime correction')
        hdu1.header.update('TIMEPIXR',0.5,'bin time beginning=0 middle=0.5 end=1')
        hdu1.header.update('TIERRELA',5.78e-7,'[d] relative time error')
        hdu1.header.update('TIERABSO',5.78e-6,'[d] absolute time error')
        hdu1.header.update('INT_TIME',6.0198,'[s] photon accumulation time per frame')
        hdu1.header.update('READTIME',0.518948526144,'[s] readout time per frame')
        hdu1.header.update('FRAMETIM',6.53875,'[s] frame time (INT_TIME + READTIME)')
        hdu1.header.update('NUM_FRM',270,'number of frames per time stamp')
        hdu1.header.update('TIMEDEL',30.0/1440,'[d] time resolution of data')
        hdu1.header.update('DATE-OBS','2014-09-30T12:28:48.0','TSTART as UT calendar date')
        hdu1.header.update('DATE-END','2014-10-02T11:02:24.0','TSTOP as UT calendar date')
        hdu1.header.update('BACKAPP',True,'background is subtracted')
        hdu1.header.update('DEADAPP',False,'deadtime applied')
        hdu1.header.update('VIGNAPP',False,'vignetting or collimator correction applied')
        hdu1.header.update('GAIN',104.88,'[electrons/count] channel gain')
        hdu1.header.update('READNOIS',0.7845*104.88,'[electrons] read noise')
        hdu1.header.update('NREADOUT',276,'number of reads per cadence')
        hdu1.header.update('TIMSLICE',3,'time-slice readout sequence section')
        hdu1.header.update('MEANBLCK',738,'[count] FSW mean black level')
        hdulist.append(hdu1)
        
# create the outfile image extension

    if status == 0:
        hdu2 = ImageHDU(aperture)
        hdu2.header.update('INHERIT',True,'inherit primary keywords')
        hdu2.header.update('EXTNAME','APERTURE','extension name')
        hdu2.header.update('EXTVER',1,'extension version number')
        hdu2.header.update('TELESCOP','Kepler','telescope')
        hdu2.header.update('INSTRUME','Kepler photometer','detector type')
        hdu2.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu2.header.update('KEPLERID',1234567,'unique Kepler target identifier')
        hdu2.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu2.header.update('RA_OBJ',294.94017,'[deg] right ascension from KIC')
        hdu2.header.update('DEC_OBJ',43.80033,'[deg] declination from KIC')
        hdu2.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu2.header.update('WCSAXES',2,'number of WCS axes')
        hdu2.header.update('CTYPE1P','RAWX','pixel coordinate type')
        hdu2.header.update('CTYPE2P','RAWY','pixel coordinate type')
        hdu2.header.update('CRPIX1P',1,'[pixel] reference pixel along image axis 1')
        hdu2.header.update('CRPIX2P',1,'[pixel] reference pixel along image axis 2')
        hdu2.header.update('CRVAL1P',DATx[0],'[pixel] column number at reference pixel')
        hdu2.header.update('CRVAL2P',DATy[0],'[pixel] row number at reference pixel')
        hdu2.header.update('CUNIT1P','pixel','physical unit in column dimension')
        hdu2.header.update('CUNIT2P','pixel','physical unit in row dimension')
        hdu2.header.update('CDELT1P',1.0,'[pixel] pixel scale along columns')
        hdu2.header.update('CDELT2P',1.0,'[pixel] pixel scale along rows')
        hdu2.header.update('CTYPE1','RA---TAN','right ascension coordinate type')
        hdu2.header.update('CTYPE2','DEC--TAN','declination coordinate type')
        hdu2.header.update('CRPIX1',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu2.header.update('CRPIX2',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu2.header.update('CRVAL1',294.94017,'right ascension at reference pixel [deg]')
        hdu2.header.update('CRVAL2',43.80033,'declination at reference pixel [deg]')
        hdu2.header.update('CUNIT1','deg','physical unit in column dimension')
        hdu2.header.update('CUNIT2','deg','physical unit in row dimension')
        hdu2.header.update('CDELT1',-0.001106815552144,'pixel scale in RA dimension')
        hdu2.header.update('CDELT2',0.001106815552144,'pixel scale in Dec dimension')
        hdu2.header.update('PC1_1',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu2.header.update('PC1_2',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu2.header.update('PC2_1',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu2.header.update('PC2_2',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdulist.append(hdu2)

# write output file
        
    if status == 0:
        hdulist.writeto(outfile,checksum=True)

# stop time

    kepmsg.clock('\nKEPFAKE ended at',logfile,verbose)

    return
Exemple #7
0
def kepprf_AMC(infile, rownum, columns, rows, fluxes, border, background,
               focus, prfdir, xtol, ftol, verbose, logfile):

    # input arguments

    status = 0
    seterr(all="ignore")

    # open FITS file and get header info + data

    instr = fits.open(infile, mode='readonly', memmap=True)

    crval1p = instr[0].header['CRVAL1P']
    crval2p = instr[0].header['CRVAL2P']

    # construct inital guess vector for fit

    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in xrange(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in xrange(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(x[i]) + crval1p)
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(y[i]) + crval2p)
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile, message, verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border + 1) * 2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0)
            guess.append(1.0)
            guess.append(0.0)

# Get data from image; then close it

    fluxpixels = instr[0].data[:]
    errpixels = np.array([sqrt(val) for val in fluxpixels])

    module = instr[0].header['MODULE']
    output = instr[0].header['OUTPUT']

    instr.close()

    x[0] = str(int(x[0]) + crval1p)
    y[0] = str(int(y[0]) + crval2p)
    column = int(x[0]) - 3
    row = int(y[0]) - 3

    ##    xdim = 11
    ##    ydim = 11
    ##    npix = 121

    xdim = 7
    ydim = 7
    npix = 49

    # construct input pixel image

    if status == 0:
        flux = fluxpixels[row - crval2p:row - crval2p + ydim,
                          column - crval1p:column - crval1p + xdim]
        ferr = errpixels[row - crval2p:row - crval2p + ydim,
                         column - crval1p:column - crval1p + xdim]

        isize = numpy.shape(flux)[0]
        jsize = numpy.shape(flux)[1]
        flux = numpy.reshape(flux, (isize * jsize))
        ferr = numpy.reshape(ferr, (isize * jsize))

        DATx = arange(column, column + xdim)
        DATy = arange(row, row + ydim)
#        if numpy.nanmin > 420000.0: flux -= 420000.0

# image scale and intensity limits of pixel data

    if status == 0:
        n = 0
        DATimg = empty((ydim, xdim))
        ERRimg = empty((ydim, xdim))
        for i in range(ydim):
            for j in range(xdim):
                DATimg[i, j] = flux[n]
                ERRimg[i, j] = ferr[n]
                n += 1

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(
            output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile, message, verbose)

# read PRF images

    if status == 0:
        prfn = [0, 0, 0, 0, 0]
        crpix1p = numpy.zeros((5), dtype='float32')
        crpix2p = numpy.zeros((5), dtype='float32')
        crval1p = numpy.zeros((5), dtype='float32')
        crval2p = numpy.zeros((5), dtype='float32')
        cdelt1p = numpy.zeros((5), dtype='float32')
        cdelt2p = numpy.zeros((5), dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)
        prfn = array(prfn)
        PRFx = arange(0.5, shape(prfn[0])[1] + 0.5)
        PRFy = arange(0.5, shape(prfn[0])[0] + 0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]), dtype='float32')
        prfWeight = zeros((5), dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 +
                                (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e-6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf) / cdelt1p[0] / cdelt2p[0]

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(
            PRFx, PRFy, prf)

# construct mesh for background model

    if status == 0 and background:
        bx = numpy.arange(1., float(xdim + 1))
        by = numpy.arange(1., float(ydim + 1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# fit PRF model to pixel data

    if status == 0:
        if focus and background:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                    splineInterpolation, float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif focus and not background:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                    float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithFocus,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        elif background and not focus:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                    splineInterpolation, float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRFwithBackground,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)
        else:
            args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                    float(x[0]), float(y[0]))
            ans = fmin_powell(kepfunc.PRF,
                              guess,
                              args=args,
                              xtol=xtol,
                              ftol=ftol,
                              disp=False)

# pad the PRF data if the PRF array is smaller than the data array

    if status == 0:
        flux = []
        OBJx = []
        OBJy = []
        PRFmod = numpy.zeros((prfDimY, prfDimX))
        if PRFy0 < 0 or PRFx0 < 0.0:
            PRFmod = numpy.zeros((prfDimY, prfDimX))
            superPRF = zeros((prfDimY + 1, prfDimX + 1))
            superPRF[abs(PRFy0):abs(PRFy0) + shape(prf)[0],
                     abs(PRFx0):abs(PRFx0) + shape(prf)[1]] = prf
            prf = superPRF * 1.0
            PRFy0 = 0
            PRFx0 = 0

# rotate the PRF model around its center

        if focus:
            angle = ans[-1]
            prf = rotate(prf, -angle, reshape=False, mode='nearest')

# iterate through the sources in the best fit PSF model

        for i in range(nsrc):
            flux.append(ans[i])
            OBJx.append(ans[nsrc + i])
            OBJy.append(ans[nsrc * 2 + i])

            # calculate best-fit model

            y = (OBJy[i] - mean(DATy)) / cdelt1p[0]
            x = (OBJx[i] - mean(DATx)) / cdelt2p[0]
            prfTmp = shift(prf, [y, x], order=3, mode='constant')
            prfTmp = prfTmp[PRFy0:PRFy0 + prfDimY, PRFx0:PRFx0 + prfDimX]
            PRFmod = PRFmod + prfTmp * flux[i]
            wx = 1.0
            wy = 1.0
            angle = 0
            b = 0.0

            # write out best fit parameters

            if verbose:
                txt = 'Flux = %10.2f e-/s ' % flux[i]
                txt += 'X = %9.4f pix ' % OBJx[i]
                txt += 'Y = %9.4f pix ' % OBJy[i]
                kepmsg.log(logfile, txt, True)

        if background:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc * 3]
            else:
                bcoeff = array([
                    ans[nsrc * 3:nsrc * 3 + bterms],
                    ans[nsrc * 3 + bterms:nsrc * 3 + bterms * 2]
                ])
                bkg = kepfunc.polyval2d(xx, yy, bcoeff)
                b = nanmean(bkg.reshape(bkg.size))
            txt = '\n   Mean background = %.2f e-/s' % b
        if verbose and background:
            kepmsg.log(logfile, txt, True)
        if focus:
            wx = ans[-3]
            wy = ans[-2]
            angle = ans[-1]
        if verbose and focus:
            if not background: kepmsg.log(logfile, '', True)
            kepmsg.log(logfile, ' X/Y focus factors = %.3f/%.3f' % (wx, wy),
                       True)
            kepmsg.log(logfile, 'PRF rotation angle = %.2f deg' % angle, True)

# measure flux fraction and contamination

    if status == 0:
        PRFall = kepfunc.PRF2DET(flux, OBJx, OBJy, DATx, DATy, wx, wy, angle,
                                 splineInterpolation)
        PRFone = kepfunc.PRF2DET([flux[0]], [OBJx[0]], [OBJy[0]], DATx, DATy,
                                 wx, wy, angle, splineInterpolation)

# constuct model PRF in detector coordinates

    if status == 0:
        PRFfit = PRFall + 0.0
        if background and bterms == 1:
            PRFfit = PRFall + b
        if background and bterms > 1:
            PRFfit = PRFall + bkg

# calculate residual of DATA - FIT

    if status == 0:
        PRFres = DATimg - PRFfit
        FLUXres = numpy.nansum(PRFres) / npix

# calculate the sum squared difference between data and model

    if status == 0:
        Pearson = abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit))
        Chi2 = numpy.nansum(
            numpy.square(DATimg - PRFfit) / numpy.square(ERRimg))
        DegOfFreedom = npix - len(guess) - 1
        if verbose:
            try:
                kepmsg.log(logfile,
                           '\n       Residual flux = %.2f e-/s' % FLUXres,
                           True)
                kepmsg.log(
                    logfile, 'Pearson\'s chi^2 test = %d for %d dof' %
                    (Pearson, DegOfFreedom), True)
            except:
                pass
            kepmsg.log(
                logfile,
                '          Chi^2 test = %d for %d dof' % (Chi2, DegOfFreedom),
                True)

    result = np.array([flux[0], OBJx[0], OBJy[0]])

    return result
Exemple #8
0
def kepprf(infile,plotfile,rownum,columns,rows,fluxes,border,background,focus,prfdir,xtol,ftol,
           imscale,colmap,plt,verbose,logfile,status,cmdLine=False): 

# input arguments
    print "... input arguments"
    status = 0
    seterr(all="ignore") 

# log the call 
    print "... logging the call"
    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPPRF -- '
    call += 'infile='+infile+' '
    call += 'plotfile='+plotfile+' '
    call += 'rownum='+str(rownum)+' '
    call += 'columns='+columns+' '
    call += 'rows='+rows+' '
    call += 'fluxes='+fluxes+' '
    call += 'border='+str(border)+' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background='+bground+' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus='+focs+' '
    call += 'prfdir='+prfdir+' '
    call += 'xtol='+str(xtol)+' '
    call += 'ftol='+str(xtol)+' '
    call += 'imscale='+imscale+' '
    call += 'colmap='+colmap+' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot='+plotit+' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# start time
    print "... starting kepler time"
    kepmsg.clock('KEPPRF started at',logfile,verbose)

# reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# construct inital guess vector for fit 
    print " status = "+str(status)
    print "... initial guess"        
    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in xrange(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in xrange(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in xrange(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border+1)*2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0); guess.append(1.0); guess.append(0.0)

# open TPF FITS file
    print "... open tpf file"        
    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRF: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile,message,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# read mask defintion data from TPF file
    print "... read mask definition"        
    if status == 0:
        maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(infile,logfile,verbose)
        npix = numpy.size(numpy.nonzero(maskimg)[0])

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID:  %s' % kepid
        print ' RA (J2000):  %s' % ra
        print 'Dec (J2000): %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:    %2s' % skygroup
        print '     Season:    %2s' % str(season)
        print '    Channel:    %2s' % channel
        print '     Module:    %2s' % module
        print '     Output:     %1s' % output
        print ''

# is this a good row with finite timestamp and pixels?

    if status == 0:
        if not numpy.isfinite(barytime[rownum-1]) or numpy.nansum(fluxpixels[rownum-1,:]) == numpy.nan:
            message = 'ERROR -- KEPFIELD: Row ' + str(rownum) + ' is a bad quality timestamp'
            status = kepmsg.err(logfile,message,verbose)

# construct input pixel image

    if status == 0:
        flux = fluxpixels[rownum-1,:]
        ferr = errpixels[rownum-1,:]
        DATx = arange(column,column+xdim)
        DATy = arange(row,row+ydim)

# image scale and intensity limits of pixel data

    if status == 0:
        n = 0
        DATimg = empty((ydim,xdim))
        ERRimg = empty((ydim,xdim))
        for i in range(ydim):
            for j in range(xdim):
                DATimg[i,j] = flux[n]
                ERRimg[i,j] = ferr[n]
                n += 1
        
# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)    
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
            prf = prf / nansum(prf)
        prf = prf / cdelt1p[0] / cdelt2p[0]

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf)

# construct mesh for background model

    if status == 0 and background:
        bx = numpy.arange(1.,float(xdim+1))
        by = numpy.arange(1.,float(ydim+1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# fit PRF model to pixel data

    if status == 0:
        start = time.time()
        if focus and background:
            args = (DATx,DATy,DATimg,nsrc,border,xx,yy,PRFx,PRFy,splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        elif focus and not background:
            args = (DATx,DATy,DATimg,nsrc,PRFx,PRFy,splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithFocus,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)                    
        elif background and not focus:
            args = (DATx,DATy,DATimg,nsrc,border,xx,yy,splineInterpolation)
            ans = fmin_powell(kepfunc.PRFwithBackground,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        else:
            args = (DATx,DATy,DATimg,splineInterpolation)
            ans = fmin_powell(kepfunc.PRF,guess,args=args,xtol=xtol,
                              ftol=ftol,disp=False)
        print 'Convergence time = %.2fs\n' % (time.time() - start)

# pad the PRF data if the PRF array is smaller than the data array 

    if status == 0:
        flux = []; OBJx = []; OBJy = []
        PRFmod = numpy.zeros((prfDimY,prfDimX))
        if PRFy0 < 0 or PRFx0 < 0.0:
            PRFmod = numpy.zeros((prfDimY,prfDimX))
            superPRF = zeros((prfDimY+1,prfDimX+1))
            superPRF[abs(PRFy0):abs(PRFy0)+shape(prf)[0],abs(PRFx0):abs(PRFx0)+shape(prf)[1]] = prf
            prf = superPRF * 1.0
            PRFy0 = 0
            PRFx0 = 0

# rotate the PRF model around its center

        if focus:
            angle = ans[-1]
            prf = rotate(prf,-angle,reshape=False,mode='nearest')

# iterate through the sources in the best fit PSF model

        for i in range(nsrc):
            flux.append(ans[i])
            OBJx.append(ans[nsrc+i])
            OBJy.append(ans[nsrc*2+i]) 

# calculate best-fit model

            y = (OBJy[i]-mean(DATy)) / cdelt1p[0]
            x = (OBJx[i]-mean(DATx)) / cdelt2p[0]
            prfTmp = shift(prf,[y,x],order=1,mode='constant')
            prfTmp = prfTmp[PRFy0:PRFy0+prfDimY,PRFx0:PRFx0+prfDimX]
            PRFmod = PRFmod + prfTmp * flux[i]
            wx = 1.0
            wy = 1.0
            angle = 0
            b = 0.0

# write out best fit parameters

            if verbose:
                txt = 'Flux = %10.2f e-/s ' % flux[i]
                txt += 'X = %9.4f pix ' % OBJx[i]
                txt += 'Y = %9.4f pix ' % OBJy[i]
                kepmsg.log(logfile,txt,True)
        if verbose and background:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc*3]
            else:
                bcoeff = array([ans[nsrc*3:nsrc*3+bterms],ans[nsrc*3+bterms:nsrc*3+bterms*2]]) 
                bkg = kepfunc.polyval2d(xx,yy,bcoeff)
                b = nanmean(bkg.reshape(bkg.size))
            txt = '\n   Mean background = %.2f e-/s' % b
            kepmsg.log(logfile,txt,True)
        if focus:
            wx = ans[-3]
            wy = ans[-2]
            angle = ans[-1]
        if verbose and focus:
            if not background: kepmsg.log(logfile,'',True)
            kepmsg.log(logfile,' X/Y focus factors = %.3f/%.3f' % (wx,wy),True)
            kepmsg.log(logfile,'PRF rotation angle = %.2f deg' % angle,True)

# constuct model PRF in detector coordinates

    if status == 0:
        PRFfit = kepfunc.PRF2DET(flux,OBJx,OBJy,DATx,DATy,wx,wy,angle,splineInterpolation)
        if background and bterms == 1:
            PRFfit = PRFfit + b
        if background and bterms > 1:
            PRFfit = PRFfit + bkg

# calculate residual of DATA - FIT

    if status == 0:
        PRFres = DATimg - PRFfit
        FLUXres = numpy.nansum(PRFres)
    
# calculate the sum squared difference between data and model

    if status == 0:
        Pearson = abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit))
        Chi2 = numpy.nansum(numpy.square(DATimg - PRFfit) / numpy.square(ERRimg))
        DegOfFreedom = npix - len(guess)
        try:
            kepmsg.log(logfile,'\nResidual flux = %.6f e-/s' % FLUXres,True)
            kepmsg.log(logfile,'Pearson\'s chi^2 test = %d for %d dof' % (Pearson,DegOfFreedom),True)
        except:
            pass
#        kepmsg.log(logfile,'Chi^2 test = %d for %d dof' % (Chi2,DegOfFreedom),True)

# image scale and intensity limits for plotting images

    if status == 0:
        imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg,imscale)
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod,imscale)
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit,imscale)
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres,imscale)
        if imscale == 'linear':
            zmaxpr *= 0.9
        elif imscale == 'logarithmic':
            print zminpr,zmaxpr,numpy.max(zmaxpr)
            zmaxpr = numpy.max(zmaxpr)
            zminpr = zmaxpr / 2
        
# plot style

    if status == 0:
        try:
            params = {'backend': 'png',
                      'axes.linewidth': 2.5,
                      'axes.labelsize': 24,
                      'axes.font': 'sans-serif',
                      'axes.fontweight' : 'bold',
                      'text.fontsize': 12,
                      'legend.fontsize': 12,
                      'xtick.labelsize': 10,
                      'ytick.labelsize': 10}
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[10,10])
        pylab.clf()
        plotimage(imgdat_pl,zminfl,zmaxfl,1,row,column,xdim,ydim,0.06,0.52,'flux',colmap)
        plotimage(imgprf_pl,zminpr,zmaxpr,2,row,column,xdim,ydim,0.52,0.52,'model',colmap)
        kepplot.borders(maskimg,xdim,ydim,pixcoord1,pixcoord2,1,'b','--',0.5)
        kepplot.borders(maskimg,xdim,ydim,pixcoord1,pixcoord2,2,'b','-',3.0)
        plotimage(imgfit_pl,zminfl,zmaxfl,3,row,column,xdim,ydim,0.06,0.06,'fit',colmap)
        plotimage(imgres_pl,zminfl,zmaxfl,4,row,column,xdim,ydim,0.52,0.06,'residual',colmap)
            
# render plot

    if status == 0 and len(plotfile) > 0 and plotfile.lower() != 'none':
        pylab.savefig(plotfile)
    if status == 0 and plt:
        if cmdLine: 
            pylab.show(block=True)
        else: 
            pylab.ion()
            pylab.plot([])
            pylab.ioff()
	
# stop time

    kepmsg.clock('\nKEPPRF ended at',logfile,verbose)

    return
Exemple #9
0
def kepdeltapix(infile,nexp,columns,rows,fluxes,prfdir,interpolation,tolerance,fittype,imscale,
           colmap,verbose,logfile,status,cmdLine=False): 

# input arguments

    status = 0
    seterr(all="ignore") 

# log the call 

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPDELTAPIX -- '
    call += 'infile='+infile+' '
    call += 'nexp='+str(nexp)+' '
    call += 'columns='+columns+' '
    call += 'rows='+rows+' '
    call += 'fluxes='+fluxes+' '
    call += 'prfdir='+prfdir+' '
    call += 'interpolation='+interpolation+' '
    call += 'tolerance='+str(tolerance)+' '
    call += 'fittype='+str(fittype)+' '
    call += 'imscale='+imscale+' '
    call += 'colmap='+colmap+' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# start time

    kepmsg.clock('KEPDELTAPIX started at',logfile,verbose)

# reference color map

    if colmap == 'browse':
        status = cmap_plot(cmdLine)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPDELTAPIX: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile,message,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)

# print target data

    if status == 0 and verbose:
        print ''
        print '      KepID:  %s' % kepid
        print ' RA (J2000):  %s' % ra
        print 'Dec (J2000): %s' % dec
        print '     KepMag:  %s' % kepmag
        print '   SkyGroup:    %2s' % skygroup
        print '     Season:    %2s' % str(season)
        print '    Channel:    %2s' % channel
        print '     Module:    %2s' % module
        print '     Output:     %1s' % output
        print ''

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPDELTAPIX: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)    

# choose rows in the TPF table at random

    if status == 0:
        i = 0
        rownum = []
        while i < nexp:
            work = int(random.random() * len(barytime))
            if numpy.isfinite(barytime[work]) and numpy.isfinite(fluxpixels[work,ydim*xdim/2]):
                rownum.append(work)
                i += 1

# construct input pixel image

    if status == 0:
        fscat = numpy.empty((len(fluxes),nexp),dtype='float32')
        xscat = numpy.empty((len(columns),nexp),dtype='float32')
        yscat = numpy.empty((len(rows),nexp),dtype='float32')
        for irow in range(nexp):
            flux = fluxpixels[rownum[irow],:]

# image scale and intensity limits of pixel data

            if status == 0:
                flux_pl, zminfl, zmaxfl = kepplot.intScale1D(flux,imscale)
                n = 0
                imgflux_pl = empty((ydim,xdim))
                for i in range(ydim):
                    for j in range(xdim):
                        imgflux_pl[i,j] = flux_pl[n]
                        n += 1
        
# fit PRF model to pixel data

            if status == 0:
                start = time.time()
                f,y,x,prfMod,prfFit,prfRes = kepfit.fitMultiPRF(flux,ydim,xdim,column,row,prfn,crval1p,
                     crval2p,cdelt1p,cdelt2p,interpolation,tolerance,fluxes,columns,rows,fittype,
                     verbose,logfile)
                if verbose:
                    print '\nConvergence time = %.1fs' % (time.time() - start)

# best fit parameters

            if status == 0:
                for i in range(len(f)):
                    fscat[i,irow] = f[i]
                    xscat[i,irow] = x[i]
                    yscat[i,irow] = y[i]

# replace starting guess with previous fit parameters

            if status == 0:
                fluxes = copy(f)
                columns = copy(x)
                rows = copy(y)

# mean and rms results

    if status == 0:
        fmean = []; fsig = []
        xmean = []; xsig = []
        ymean = []; ysig = []
        for i in range(len(f)):
            fmean.append(numpy.mean(fscat[i,:]))
            xmean.append(numpy.mean(xscat[i,:]))
            ymean.append(numpy.mean(yscat[i,:]))
            fsig.append(numpy.std(fscat[i,:]))
            xsig.append(numpy.std(xscat[i,:]))
            ysig.append(numpy.std(yscat[i,:]))
            txt = 'Flux = %10.2f e-/s ' % fmean[-1]
            txt += 'X = %7.4f +/- %6.4f pix ' % (xmean[-1], xsig[i])
            txt += 'Y = %7.4f +/- %6.4f pix' % (ymean[-1], ysig[i])
            kepmsg.log(logfile,txt,True)

# output results for kepprfphot

    if status == 0:
        txt1 = 'columns=0.0'
        txt2 = '   rows=0.0'
        for i in range(1,len(f)):
            txt1 += ',%.4f' % (xmean[i] - xmean[0])
            txt2 += ',%.4f' % (ymean[i] - ymean[0])
        kepmsg.log(logfile,'\nkepprfphot input fields:',True)
        kepmsg.log(logfile,txt1,True)
        kepmsg.log(logfile,txt2,True)
        
# image scale and intensity limits for PRF model image

    if status == 0:
        imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(prfMod,imscale)
        
# image scale and intensity limits for PRF fit image

    if status == 0:
        imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(prfFit,imscale)
        
# image scale and intensity limits for data - fit residual

    if status == 0:
        imgres_pl, zminre, zmaxre = kepplot.intScale2D(prfRes,imscale)
        
# plot style

    if status == 0:
        try:
            params = {'backend': 'png',
                      'axes.linewidth': 2.5,
                      'axes.labelsize': 24,
                      'axes.font': 'sans-serif',
                      'axes.fontweight' : 'bold',
                      'text.fontsize': 12,
                      'legend.fontsize': 12,
                      'xtick.labelsize': 10,
                      'ytick.labelsize': 10}
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[10,10])
        pylab.clf()
        plotimage(imgflux_pl,zminfl,zmaxfl,1,row,column,xdim,ydim,0.06,0.52,'flux',colmap)
        plotimage(imgfit_pl,zminfl,zmaxfl,3,row,column,xdim,ydim,0.06,0.06,'fit',colmap)
        plotimage(imgres_pl,zminfl,zmaxfl,4,row,column,xdim,ydim,0.52,0.06,'residual',colmap)
        plotimage(imgprf_pl,zminpr,zmaxpr*0.9,2,row,column,xdim,ydim,0.52,0.52,'model',colmap)
        for i in range(len(f)):        
            pylab.plot(xscat[i,:],yscat[i,:],'o',color='k')            
            
# Plot creep of target position over time, relative to the central source

#	barytime0 = float(int(barytime[0] / 100) * 100.0)
#	barytime -= barytime0
#        xlab = 'BJD $-$ %d' % barytime0
#	xmin = numpy.nanmin(barytime)
#	xmax = numpy.nanmax(barytime)
#	y1min = numpy.nanmin(data)
#	y1max = numpy.nanmax(data)
#	xr = xmax - xmin
#	yr = ymax - ymin
#        barytime = insert(barytime,[0],[barytime[0]]) 
#        barytime = append(barytime,[barytime[-1]])
#        data = insert(data,[0],[0.0]) 
#        data = append(data,0.0)
#
#        pylab.figure(2,figsize=[10,10])
#        pylab.clf()
#	ax = pylab.subplot(211)
#	pylab.subplots_adjust(0.1,0.5,0.88,0.42)
#        pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        labels = ax.get_yticklabels()
#        setp(labels, 'rotation', 90, fontsize=ticksize)
#        for i in range(1,len(f)):
#            pylab.plot(rownum,xscat[i,:]-xscat[0,:],'o')
#        pylab.ylabel('$\Delta$Columns', {'color' : 'k'})
#	ax = pylab.subplot(211)
#	pylab.subplots_adjust(0.1,0.1,0.88,0.42)
#        pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
#        labels = ax.get_yticklabels()
#        setp(labels, 'rotation', 90, fontsize=ticksize)
#        for i in range(1,len(f)):
#            pylab.plot(rownum,yscat[i,:]-yscat[0,:],'o')
#	pylab.xlim(xmin-xr*0.01,xmax+xr*0.01)
#	if ymin-yr*0.01 <= 0.0 or fullrange:
#            pylab.ylim(1.0e-10,ymax+yr*0.01)
#	else:
#            pylab.ylim(ymin-yr*0.01,ymax+yr*0.01)
#        pylab.ylabel('$\Delta$Rows', {'color' : 'k'})
#        pylab.xlabel(xlab, {'color' : 'k'})

# render plot

    if status == 0:
        if cmdLine: 
            pylab.show(block=True)
        else: 
            pylab.ion()
            pylab.plot([])
            pylab.ioff()
	
# stop time

    kepmsg.clock('\nKEPDELTAPIX ended at',logfile,verbose)

    return
def kepfake(outfile,prfdir,module,output,column,row,kepmag,background,xdim,ydim,
            clobber,verbose,logfile,status,cmdLine=False): 

# input arguments

    status = 0
    seterr(all="ignore") 

# log the call 

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPFAKE -- '
    call += 'outfile='+outfile+' '
    call += 'prfdir='+prfdir+' '
    call += 'module='+str(module)+' '
    call += 'output='+str(output)+' '
    call += 'column='+str(column)+' '
    call += 'row='+str(row)+' '
    call += 'kepmag='+str(kepmag)+' '
    call += 'background='+str(background)+' '
    call += 'xdim='+str(xdim)+' '
    call += 'ydim='+str(ydim)+' '
    clob = 'n'
    if (clobber): clob = 'y'
    call += 'clobber='+clob+' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# plot style

    if status == 0:
        try:
            params = {'backend': 'png',
                      'axes.linewidth': 2.5,
                      'axes.labelsize': 24,
                      'axes.font': 'sans-serif',
                      'axes.fontweight' : 'bold',
                      'text.fontsize': 12,
                      'legend.fontsize': 12,
                      'xtick.labelsize': 10,
                      'ytick.labelsize': 10}
            pylab.rcParams.update(params)
        except:
            pass
        pylab.figure(figsize=[12,12])
        pylab.clf()

# start time

    kepmsg.clock('KEPFAKE started at',logfile,verbose)

# clobber output file

    if status == 0:
        if clobber: status = kepio.clobber(outfile,logfile,verbose)
        if kepio.fileexists(outfile): 
            message = 'ERROR -- KEPPRFPHOT: ' + outfile + ' exists. Use --clobber'
            status = kepmsg.err(logfile,message,verbose)

# Create time-tagged arrays

    if status == 0:
        nobs = 192
        time = zeros((nobs))
        timecorr = zeros((nobs))
        cadenceno = zeros((nobs))
        raw_cnts = zeros((nobs,ydim,xdim))
        flux = zeros((nobs,ydim,xdim))
        flux_err = zeros((nobs,ydim,xdim))
        flux_bkg = zeros((nobs,ydim,xdim))
        flux_bkg_err = zeros((nobs,ydim,xdim))
        cosmic_rays = zeros((nobs,ydim,xdim))
        quality = zeros((nobs))
        pos_corr1 = zeros((nobs))
        pos_corr2 = zeros((nobs))

# Create aperture bit mqp

    if status == 0:
        aperture = ones((ydim,xdim)) * 3.0

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPFAKE: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)    
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in xrange(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0: prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf) / cdelt1p[0] / cdelt2p[0]

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf,kx=3,ky=3)

# flux from target

    if status == 0:
        zeropoint = 33.227
        kepflux = 10.0**((zeropoint - kepmag) / 2.5)

# range of the output image in detector coordinates
        
    if status == 0:
        if xdim % 2  == 0: xdim += 1
        if ydim % 2  == 0: ydim += 1
        DATx = arange(round(column) - floor(xdim/2),round(column) + floor(xdim/2) + 1.0)
        DATy = arange(round(row) - floor(ydim/2),round(row) + floor(ydim/2) + 1.0)
    ax = pylab.axes([0.05,0.5,0.45,0.45])
    pylab.imshow(log10(prf+0.001),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(PRFx),max(PRFx),min(PRFy),max(PRFy)))
    pylab.plot([-100.,100.],[0.0,0.0],'k',ls='--')
    pylab.plot([0.0,0.0],[-100.,100.],'k',ls='--')
    pylab.xlim(min(PRFx),max(PRFx))
    pylab.ylim(min(PRFy),max(PRFy))
    ax = pylab.axes([0.5,0.5,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx),0.1) + floor(column)
    TMPy = arange(min(PRFy),max(PRFy),0.1) + floor(row)
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx),max(TMPx),min(TMPy),max(TMPy)))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    ax = pylab.axes([0.05,0.05,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx),0.5) + floor(column)
    TMPy = arange(min(PRFy),max(PRFy),0.5) + floor(row)
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx),max(TMPx),min(TMPy),max(TMPy)))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    ax = pylab.axes([0.5,0.05,0.45,0.45])
    TMPx = arange(min(PRFx),max(PRFx+1.0),1.0) + floor(column) - 0.5
    TMPy = arange(min(PRFy),max(PRFy+1.0),1.0) + floor(row) - 0.5
    PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],TMPx,TMPy,1.0,1.0,0.0,splineInterpolation)
    PRFfit = PRFfit + background
    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(TMPx)-0.5,max(TMPx)-0.5,min(TMPy)-0.5,max(TMPy)-0.5))
    pylab.plot([column,column],[-100.,2000.],'k',ls='--')
    pylab.plot([-100.,2000.],[row,row],'k',ls='--')
    pylab.xlim(min(TMPx),max(TMPx))
    pylab.ylim(min(TMPy),max(TMPy))
    pylab.ion()
    pylab.plot([])
    pylab.ioff()
#    sys.exit()

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = int(ydim / cdelt1p[0])
        prfDimX = int(xdim / cdelt2p[0])
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# iterate over each exposure

    if status == 0:
        for i in range(nobs):
#        for i in range(1):

# constuct model PRF in detector coordinates

            if status == 0:
                PRFfit = kepfunc.PRF2DET([kepflux],[column],[row],DATx,DATy,1.0,1.0,0.0,splineInterpolation)
                PRFfit = PRFfit + background

# add noise to image

            if status == 0:
                for index,value in ndenumerate(PRFfit):
                    PRFfit[index] += sqrt(value) * kepfunc.inv_normal_cummulative_function(random.random())

# populate output array

            if status == 0:
                time[i] = 1500.2 + float(i) * 0.020416667
                cadenceno[i] = 10000 + i
                flux[i,:,:] = PRFfit
                flux_err[i,:,:] = sqrt(PRFfit)

    pylab.imshow(log10(PRFfit),aspect='auto',interpolation='nearest',origin='lower',cmap='jet',
                 extent=(min(DATx),max(DATx),min(DATy),max(DATy)))
    pylab.ion()
    pylab.plot([])
    pylab.ioff()
            
# Create the outfile primary extension

    if status == 0:
        hdu0 = PrimaryHDU()
        hdu0.header.update('EXTNAME','PRIMARY','name of extension')
        hdu0.header.update('EXTEND',True,'file may contain standard extensions')
        hdu0.header.update('EXTVER',1.0,'extension version number')
        hdu0.header.update('ORIGIN','NASA/Ames','organization that generated this file')
        hdu0.header.update('DATE','2014-04-08','file creation date')
        hdu0.header.update('CREATOR','FluxExporter-91415','SW version used to create this file')
        hdu0.header.update('PROCVER',11.0,'processing script version')
        hdu0.header.update('FILEVER','COA','file format version')
        hdu0.header.update('TIMVERSN','OGIP/93-003','OGIP memo number for file format')
        hdu0.header.update('TELESCOP','Kepler','telescope')
        hdu0.header.update('INSTRUME','Kepler photometer','detector type')
        hdu0.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu0.header.update('KEPLERID',1234567,'unique Kepler target identifier')
        hdu0.header.update('CHANNEL',58,'CCD channel')
        hdu0.header.update('SKYGROUP',32,'roll-independent location of channel')
        hdu0.header.update('MODULE',17,'CCD module')
        hdu0.header.update('OUTPUT',2,'CCD output')
        hdu0.header.update('QUARTER',4,'mission quarter during which data was collected')
        hdu0.header.update('SEASON',2,'mission season during which data was collected')
        hdu0.header.update('DATA_REL',25,'version of data release notes describing data')
        hdu0.header.update('OBSMODE','long cadence','observing mode')
        hdu0.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu0.header.update('RA_OBJ',0.0,'[deg] right ascension from KIC')
        hdu0.header.update('DEC_OBJ',0.0,'[deg] declination from KIC')
        hdu0.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu0.header.update('PMRA',0.0,'[arcsec/yr] RA proper motion')
        hdu0.header.update('PMDEC',0.0,'[arcsec/yr] Dec proper motion')
        hdu0.header.update('PMTOTAL',0.0,'[arcsec/yr] total proper motion')
        hdu0.header.update('PARALLAX',0.0,'[arcsec] parallax')
        hdu0.header.update('GLON',0.0,'[deg] galactic longitude')
        hdu0.header.update('GLAT',0.0,'[deg] galactic latitude')
        hdu0.header.update('GMAG',kepmag,'[mag] SDSS g band magnitude from KIC')
        hdu0.header.update('RMAG',kepmag,'[mag] SDSS r band magnitude from KIC')
        hdu0.header.update('IMAG',kepmag,'[mag] SDSS i band magnitude from KIC')
        hdu0.header.update('ZMAG',kepmag,'[mag] SDSS z band magnitude from KIC')
        hdu0.header.update('D51MAG',kepmag,'[mag] D51 magnitude, from KIC')
        hdu0.header.update('JMAG',kepmag,'[mag] J band magnitude from 2MASS')
        hdu0.header.update('HMAG',kepmag,'[mag] H band magnitude from 2MASS')
        hdu0.header.update('KMAG',kepmag,'[mag] K band magnitude from 2MASS')
        hdu0.header.update('KEPMAG',kepmag,'[mag] Kepler magnitude (Kp) from KIC')
        hdu0.header.update('GRCOLOR',0.0,'[mag] (g-r) color, SDSS bands')
        hdu0.header.update('JKCOLOR',0.0,'[mag] (J-K) color, 2MASS bands')
        hdu0.header.update('GKCOLOR',0.0,'[mag] (g-K) color, SDSS g - 2MASS K')
        hdu0.header.update('TEFF',5000.0,'[K] effective temperature from KIC')
        hdu0.header.update('LOGG',4.5,'[cm/s2] log10 surface gravity from KIC')
        hdu0.header.update('FEH',0.0,'[log10([Fe/H])] metallicity from KIC')
        hdu0.header.update('EBMINUSV',0.0,'[mag] E(B-V) redenning from KIC')
        hdu0.header.update('AV',0.0,'[mag] A_v extinction from KIC')
        hdu0.header.update('RADIUS',1.0,'[solar radii] stellar radius from KIC')
        hdu0.header.update('TMINDEX',1117146912,'unique 2MASS catalog ID from KIC')
        hdu0.header.update('SCPID',1117146912,'unique SCP processing ID from KIC') 
        hdulist = HDUList(hdu0)

# create the outfile table extension

    if status == 0:
        eformat = str(ydim*xdim) + 'E'
        jformat = str(ydim*xdim) + 'J'
        kformat = str(ydim*xdim) + 'K'
        coldim = '(' + str(ydim) + ',' + str(ydim) + ')'
        col1 = Column(name='TIME',format='D',unit='BJD - 2454833',array=time)
        col2 = Column(name='TIMECORR',format='E',unit='d',array=timecorr)
        col3 = Column(name='CADENCENO',format='J',array=cadenceno)
        col4 = Column(name='RAW_CNTS',format=jformat,unit='count',dim=coldim,array=raw_cnts)
        col5 = Column(name='FLUX',format=eformat,unit='e-/s',dim=coldim,array=flux)
        col6 = Column(name='FLUX_ERR',format=eformat,unit='e-/s',dim=coldim,array=flux_err)
        col7 = Column(name='FLUX_BKG',format=eformat,unit='e-/s',dim=coldim,array=flux_bkg)
        col8 = Column(name='FLUX_BKG_ERR',format=eformat,unit='e-/s',dim=coldim,array=flux_bkg_err)
        col9 = Column(name='COSMIC_RAYS',format=eformat,unit='e-/s',dim=coldim,array=cosmic_rays)
        col10 = Column(name='QUALITY',format='J',array=quality)
        col11 = Column(name='POS_CORR1',format='E',unit='pixel',array=pos_corr1)
        col12 = Column(name='POS_CORR2',format='E',unit='pixel',array=pos_corr2)
        cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12])
        hdu1 = new_table(cols)
        hdu1.header.update('TTYPE1','TIME','column title: data time stamps')
        hdu1.header.update('TFORM1','D','data type: float64')
        hdu1.header.update('TUNIT1','BJD - 2454833','column units: barycenter corrected JD')
        hdu1.header.update('TDISP1','D13.7','column display format')
        hdu1.header.update('TTYPE2','TIMECORR','column title: barycentric correction')
        hdu1.header.update('TFORM2','E','column format: float32')
        hdu1.header.update('TUNIT2','d','column units: days')
        hdu1.header.update('TDISP2','D12.7','column display format')
        hdu1.header.update('TTYPE3','CADENCENO','column title: unique cadence number')
        hdu1.header.update('TFORM3','J','column format: signed integer32')
        hdu1.header.update('TTYPE4','RAW_CNTS','column title: raw pixel count')
        hdu1.header.update('TFORM4',jformat,'column format: signed integer32')
        hdu1.header.update('TDIM4',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT4','count','column units: count')
        hdu1.header.update('TTYPE5','FLUX','column title: calibrated pixel flux')
        hdu1.header.update('TFORM5',eformat,'column format: float32')
        hdu1.header.update('TDIM5',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT5','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE6','FLUX_ERR','column title: 1-sigma calibrated uncertainty')
        hdu1.header.update('TFORM6',eformat,'column format: float32')
        hdu1.header.update('TDIM6',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT6','e-/s','column units: electrons per second (1-sigma)')
        hdu1.header.update('TTYPE7','FLUX_BKG','column title: calibrated background flux')
        hdu1.header.update('TFORM7',eformat,'column format: float32')
        hdu1.header.update('TDIM7',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT7','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE8','FLUX_BKG_ERR','column title: 1-sigma cal. backgrnd uncertainty')
        hdu1.header.update('TFORM8',eformat,'column format: float32')
        hdu1.header.update('TDIM8',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT8','e-/s','column units: electrons per second (1-sigma)')
        hdu1.header.update('TTYPE9','COSMIC_RAYS','column title: cosmic ray detections')
        hdu1.header.update('TFORM9',eformat,'column format: float32')
        hdu1.header.update('TDIM9',coldim,'column dimensions: pixel apeture array')
        hdu1.header.update('TUNIT9','e-/s','column units: electrons per second')
        hdu1.header.update('TTYPE10','QUALITY','column title: pixel quality flags')
        hdu1.header.update('TFORM10','J','column format: signed integer32')
        hdu1.header.update('TTYPE11','POS_CORR1','column title: col correction for vel. abbern')
        hdu1.header.update('TFORM11','E','column format: float32')
        hdu1.header.update('TUNIT11','pixel','column units: pixel')
        hdu1.header.update('TTYPE12','POS_CORR2','column title: row correction for vel. abbern')
        hdu1.header.update('TFORM12','E','column format: float32')
        hdu1.header.update('TUNIT12','pixel','column units: pixel')
        hdu1.header.update('WCAX4',2,'number of WCS axes')
        hdu1.header.update('1CTY4P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY4P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP4P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP4P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV4P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV4P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN4P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN4P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE4P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE4P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP4','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP4','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX4',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX4',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL4',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL4',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI4','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI4','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT4',-0.001106815552144,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT4',0.001106815552144,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC4',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC4',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC4',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC4',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX5',2,'number of WCS axes')
        hdu1.header.update('1CTY5P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY5P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP5P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP5P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV5P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV5P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN5P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN5P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE5P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE5P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP5','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP5','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX5',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX5',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL5',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL5',43.80033,'[deg] declination at reference pixel [deg]')
        hdu1.header.update('1CUNI5','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI5','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT5',-0.001106815552144,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT5',0.001106815552144,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC5',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC5',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC5',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC5',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX6',2,'number of WCS axes')
        hdu1.header.update('1CTY6P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY6P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP6P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP6P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV6P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV6P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN6P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN6P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE6P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE6P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP6','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP6','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX6',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX6',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL6',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL6',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI6','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI6','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT6',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT6',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC6',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC6',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC6',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC6',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX7',2,'number of WCS axes')
        hdu1.header.update('1CTY7P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY7P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP7P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP7P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV7P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV7P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN7P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN7P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE7P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE7P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP7','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP7','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX7',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX7',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL7',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL7',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI7','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI7','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT7',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT7',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC7',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC7',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC7',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC7',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX8',2,'number of WCS axes')
        hdu1.header.update('1CTY8P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY8P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP8P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP8P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV8P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV8P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN8P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN8P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE8P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE8P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP8','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP8','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX8',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX8',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL8',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL8',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI8','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI8','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT8',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT8',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC8',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC8',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC8',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC8',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX9',2,'number of WCS axes')
        hdu1.header.update('1CTY9P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY9P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP9P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP9P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV9P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV9P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN9P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN9P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE9P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE9P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP9','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP9','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX9',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX9',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL9',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL9',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI9','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI9','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT9',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT9',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC9',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC9',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC9',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC9',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('WCAX10',2,'number of WCS axes')
        hdu1.header.update('1CTY10P','RAWX','right ascension coordinate type')
        hdu1.header.update('2CTY10P','RAWY','declination coordinate type')
        hdu1.header.update('1CRP10P',1,'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRP10P',1,'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRV10P',DATx[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('2CRV10P',DATy[0],'[pixel] detector coordinate at reference pixel')
        hdu1.header.update('1CUN10P','pixel','physical unit in column dimension')
        hdu1.header.update('2CUN10P','pixel','physical unit in row dimension')
        hdu1.header.update('1CDE10P',1.0,'[pixel] pixel scale in column dimension')
        hdu1.header.update('2CDE10P',1.0,'[pixel] pixel scale in row dimension')
        hdu1.header.update('1CTYP10','RA---TAN','right ascension coordinate type')
        hdu1.header.update('2CTYP10','DEC--TAN','declination coordinate type')
        hdu1.header.update('1CRPX10',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu1.header.update('2CRPX10',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu1.header.update('1CRVL10',294.94017,'[deg] right ascension at reference pixel')
        hdu1.header.update('2CRVL10',43.80033,'[deg] declination at reference pixel')
        hdu1.header.update('1CUNI10','deg','physical unit in column dimension')
        hdu1.header.update('2CUNI10','deg','physical unit in row dimension')
        hdu1.header.update('1CDLT10',-0.00110558987335788,'[deg] pixel scale in RA dimension')
        hdu1.header.update('2CDLT10',0.00110558987335788,'[deg] pixel scale in Dec dimension')
        hdu1.header.update('11PC10',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu1.header.update('12PC10',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu1.header.update('21PC10',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu1.header.update('22PC10',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdu1.header.update('INHERIT',True,'inherit primary keywords')
        hdu1.header.update('EXTNAME','TARGETTABLES','name of extension')
        hdu1.header.update('EXTVER',1,'extension version number')
        hdu1.header.update('TELESCOP','Kepler','telescope')
        hdu1.header.update('INSTRUME','Kepler photometer','detector type')
        hdu1.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu1.header.update('KEPLERID',12345678,'unique Kepler target identifier')
        hdu1.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu1.header.update('RA_OBJ',0.0,'[deg] right ascension from KIC')
        hdu1.header.update('DEC_OBJ',0.0,'[deg] declination from KIC')
        hdu1.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu1.header.update('TIMEREF','SOLARSYSTEM','barycentric correction applied to times')
        hdu1.header.update('TASSIGN','SPACECRAFT','where time is assigned')
        hdu1.header.update('TIMESYS','TDB','time system is barycentric JD')
        hdu1.header.update('BJDREFI',2454833,'integer part of BJD reference date')
        hdu1.header.update('BJDREFF',0.0,'fraction of day in BJD reference date')
        hdu1.header.update('TIMEUNIT','d','time unit for TIME, TSTART and TSTOP')
        hdu1.header.update('TSTART',1500.0,'observation start time in JD - BJDREF')
        hdu1.header.update('TSTOP',1504.0,'observation stop time in JD - BJDREF')
        hdu1.header.update('LC_START',1500.0+54833.5,'observation start time in MJD')
        hdu1.header.update('LC_END',1504.0+54833.5,'observation stop time in MJD')
        hdu1.header.update('TELAPSE',93.0,'[d] TSTOP - TSTART')
        hdu1.header.update('LIVETIME',82.7273,'[d] TELAPSE multiplied by DEADC')
        hdu1.header.update('EXPOSURE',82.7273,'[d] time on source')
        hdu1.header.update('DEADC',0.909091,'deadtime correction')
        hdu1.header.update('TIMEPIXR',0.5,'bin time beginning=0 middle=0.5 end=1')
        hdu1.header.update('TIERRELA',5.78e-7,'[d] relative time error')
        hdu1.header.update('TIERABSO',5.78e-6,'[d] absolute time error')
        hdu1.header.update('INT_TIME',6.0198,'[s] photon accumulation time per frame')
        hdu1.header.update('READTIME',0.518948526144,'[s] readout time per frame')
        hdu1.header.update('FRAMETIM',6.53875,'[s] frame time (INT_TIME + READTIME)')
        hdu1.header.update('NUM_FRM',270,'number of frames per time stamp')
        hdu1.header.update('TIMEDEL',30.0/1440,'[d] time resolution of data')
        hdu1.header.update('DATE-OBS','2014-09-30T12:28:48.0','TSTART as UT calendar date')
        hdu1.header.update('DATE-END','2014-10-02T11:02:24.0','TSTOP as UT calendar date')
        hdu1.header.update('BACKAPP',True,'background is subtracted')
        hdu1.header.update('DEADAPP',False,'deadtime applied')
        hdu1.header.update('VIGNAPP',False,'vignetting or collimator correction applied')
        hdu1.header.update('GAIN',104.88,'[electrons/count] channel gain')
        hdu1.header.update('READNOIS',0.7845*104.88,'[electrons] read noise')
        hdu1.header.update('NREADOUT',276,'number of reads per cadence')
        hdu1.header.update('TIMSLICE',3,'time-slice readout sequence section')
        hdu1.header.update('MEANBLCK',738,'[count] FSW mean black level')
        hdulist.append(hdu1)
        
# create the outfile image extension

    if status == 0:
        hdu2 = ImageHDU(aperture)
        hdu2.header.update('INHERIT',True,'inherit primary keywords')
        hdu2.header.update('EXTNAME','APERTURE','extension name')
        hdu2.header.update('EXTVER',1,'extension version number')
        hdu2.header.update('TELESCOP','Kepler','telescope')
        hdu2.header.update('INSTRUME','Kepler photometer','detector type')
        hdu2.header.update('OBJECT','KIC 12345678','string version of kepID')
        hdu2.header.update('KEPLERID',1234567,'unique Kepler target identifier')
        hdu2.header.update('RADESYS','ICRS','reference frame of celestial coordinates')
        hdu2.header.update('RA_OBJ',294.94017,'[deg] right ascension from KIC')
        hdu2.header.update('DEC_OBJ',43.80033,'[deg] declination from KIC')
        hdu2.header.update('EQUINOX',2000.0,'equinox of celestial coordinate system')
        hdu2.header.update('WCSAXES',2,'number of WCS axes')
        hdu2.header.update('CTYPE1P','RAWX','pixel coordinate type')
        hdu2.header.update('CTYPE2P','RAWY','pixel coordinate type')
        hdu2.header.update('CRPIX1P',1,'[pixel] reference pixel along image axis 1')
        hdu2.header.update('CRPIX2P',1,'[pixel] reference pixel along image axis 2')
        hdu2.header.update('CRVAL1P',DATx[0],'[pixel] column number at reference pixel')
        hdu2.header.update('CRVAL2P',DATy[0],'[pixel] row number at reference pixel')
        hdu2.header.update('CUNIT1P','pixel','physical unit in column dimension')
        hdu2.header.update('CUNIT2P','pixel','physical unit in row dimension')
        hdu2.header.update('CDELT1P',1.0,'[pixel] pixel scale along columns')
        hdu2.header.update('CDELT2P',1.0,'[pixel] pixel scale along rows')
        hdu2.header.update('CTYPE1','RA---TAN','right ascension coordinate type')
        hdu2.header.update('CTYPE2','DEC--TAN','declination coordinate type')
        hdu2.header.update('CRPIX1',int(xdim/2),'[pixel] reference pixel along image axis 1')
        hdu2.header.update('CRPIX2',int(ydim/2),'[pixel] reference pixel along image axis 2')
        hdu2.header.update('CRVAL1',294.94017,'right ascension at reference pixel [deg]')
        hdu2.header.update('CRVAL2',43.80033,'declination at reference pixel [deg]')
        hdu2.header.update('CUNIT1','deg','physical unit in column dimension')
        hdu2.header.update('CUNIT2','deg','physical unit in row dimension')
        hdu2.header.update('CDELT1',-0.001106815552144,'pixel scale in RA dimension')
        hdu2.header.update('CDELT2',0.001106815552144,'pixel scale in Dec dimension')
        hdu2.header.update('PC1_1',0.46086006096337634,'linear transformation matrix element cos(th)')
        hdu2.header.update('PC1_2',-0.8897046441865888,'linear transformation matrix element -sin(th)')
        hdu2.header.update('PC2_1',0.8864170184391076,'linear transformation matrix element sin(th)')
        hdu2.header.update('PC2_2',0.45860051653617395,'linear transformation matrix element cos(th)')
        hdulist.append(hdu2)

# write output file
        
    if status == 0:
        hdulist.writeto(outfile,checksum=True)

# stop time

    kepmsg.clock('\nKEPFAKE ended at',logfile,verbose)

    return
Exemple #11
0
def kepprf(infile,
           columns,
           rows,
           fluxes,
           rownum=0,
           border=0,
           background=0,
           focus=0,
           prfdir='../KeplerPRF',
           xtol=1.e-6,
           ftol=1.e-6,
           imscale='linear',
           cmap='YlOrBr',
           lcolor='k',
           acolor='b',
           logfile='kepcrowd.log',
           CrowdTPF=np.nan,
           srcinfo=None,
           **kwargs):

    # log the call
    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile, hashline, True)
    call = 'KEPPRF -- '
    call += 'infile=' + infile + ' '
    call += 'rownum=' + str(rownum) + ' '
    call += 'columns=' + columns + ' '
    call += 'rows=' + rows + ' '
    call += 'fluxes=' + fluxes + ' '
    call += 'border=' + str(border) + ' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background=' + bground + ' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus=' + focs + ' '
    call += 'prfdir=' + prfdir + ' '
    call += 'xtol=' + str(xtol) + ' '
    call += 'ftol=' + str(xtol) + ' '
    call += 'logfile=' + logfile
    kepmsg.log(logfile, call + '\n', True)

    guess = []
    try:
        f = fluxes.strip().split(',')
        x = columns.strip().split(',')
        y = rows.strip().split(',')
        for i in range(len(f)):
            f[i] = float(f[i])
    except:
        f = fluxes
        x = columns
        y = rows

    nsrc = len(f)
    for i in range(nsrc):
        try:
            guess.append(float(f[i]))
        except:
            message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
            kepmsg.err(logfile, message, True)
            return None

    if len(x) != nsrc or len(y) != nsrc:
        message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
        message += 'fluxes must have the same number of sources'
        kepmsg.err(logfile, message, True)
        return None

    for i in range(nsrc):
        try:
            guess.append(float(x[i]))
        except:
            message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
            kepmsg.err(logfile, message, True)
            return None

    for i in range(nsrc):
        try:
            guess.append(float(y[i]))
        except:
            message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
            kepmsg.err(logfile, message, True)
            return None

    if background:
        if border == 0:
            guess.append(0.0)
        else:
            for i in range((border + 1) * 2):
                guess.append(0.0)

    if focus:
        guess.append(1.0)
        guess.append(1.0)
        guess.append(0.0)

    # open TPF FITS file
    try:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
            kepio.readTPF(infile,'TIME',logfile,True)
    except:
        message = 'ERROR -- KEPPRF: is %s a Target Pixel File? ' % infile
        kepmsg.err(logfile, message, True)
        return None

    kepid, channel, skygroup, module, output, quarter, season, \
        ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
        kepio.readTPF(infile,'TIMECORR',logfile,True)

    kepid, channel, skygroup, module, output, quarter, season, \
        ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
        kepio.readTPF(infile,'CADENCENO',logfile,True)

    kepid, channel, skygroup, module, output, quarter, season, \
        ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
        kepio.readTPF(infile,'FLUX',logfile,True)

    kepid, channel, skygroup, module, output, quarter, season, \
        ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
        kepio.readTPF(infile,'FLUX_ERR',logfile,True)

    kepid, channel, skygroup, module, output, quarter, season, \
        ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
        kepio.readTPF(infile,'QUALITY',logfile,True)

    # read mask defintion data from TPF file
    maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(
        infile, logfile, True)
    npix = np.size(np.nonzero(maskimg)[0])

    print('')
    print('      KepID: %s' % kepid)
    print('        BJD: %.2f' % (barytime[rownum - 1] + 2454833.0))
    print(' RA (J2000): %s' % ra)
    print('Dec (J2000):  %s' % dec)
    print('     KepMag:  %s' % kepmag)
    print('   SkyGroup:   %2s' % skygroup)
    print('     Season:   %2s' % str(season))
    print('    Channel:   %2s' % channel)
    print('     Module:   %2s' % module)
    print('     Output:    %1s' % output)
    print('')

    # is this a good row with finite timestamp and pixels?
    if not np.isfinite(barytime[rownum - 1]) or np.nansum(
            fluxpixels[rownum - 1, :]) == np.nan:
        message = 'ERROR -- KEPFIELD: Row ' + str(
            rownum) + ' is a bad quality timestamp'
        status = kepmsg.err(logfile, message, True)

    # construct input pixel image
    flux = fluxpixels[rownum - 1, :]
    ferr = errpixels[rownum - 1, :]
    DATx = np.arange(column, column + xdim)
    DATy = np.arange(row, row + ydim)

    # image scale and intensity limits of pixel data
    n = 0
    DATimg = np.empty((ydim, xdim))
    ERRimg = np.empty((ydim, xdim))
    for i in range(ydim):
        for j in range(xdim):
            DATimg[i, j] = flux[n]
            ERRimg[i, j] = ferr[n]
            n += 1

    # determine suitable PRF calibration file
    if int(module) < 10:
        prefix = 'kplr0'
    else:
        prefix = 'kplr'
    prfglob = prfdir + '/' + prefix + str(module) + '.' + str(
        output) + '*' + '_prf.fits'
    try:
        prffile = glob.glob(prfglob)[0]
    except:
        message = 'ERROR -- KEPPRF: No PRF file found in ' + prfdir
        kepmsg.err(logfile, message, True)
        return None

    # read PRF images
    prfn = [0, 0, 0, 0, 0]
    crpix1p = np.zeros((5), dtype='float32')
    crpix2p = np.zeros((5), dtype='float32')
    crval1p = np.zeros((5), dtype='float32')
    crval2p = np.zeros((5), dtype='float32')
    cdelt1p = np.zeros((5), dtype='float32')
    cdelt2p = np.zeros((5), dtype='float32')
    for i in range(5):
        prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
            = kepio.readPRFimage(prffile,i+1,logfile,True)
    prfn = np.array(prfn)
    PRFx = np.arange(0.5, np.shape(prfn[0])[1] + 0.5)
    PRFy = np.arange(0.5, np.shape(prfn[0])[0] + 0.5)
    PRFx = (PRFx - np.size(PRFx) / 2) * cdelt1p[0]
    PRFy = (PRFy - np.size(PRFy) / 2) * cdelt2p[0]

    # interpolate the calibrated PRF shape to the target position
    prf = np.zeros(np.shape(prfn[0]), dtype='float32')
    prfWeight = np.zeros((5), dtype='float32')
    for i in range(5):
        prfWeight[i] = np.sqrt((column - crval1p[i])**2 +
                               (row - crval2p[i])**2)
        if prfWeight[i] == 0.0:
            prfWeight[i] = 1.0e-6
        prf = prf + prfn[i] / prfWeight[i]
    prf = prf / np.nansum(prf) / cdelt1p[0] / cdelt2p[0]

    # location of the data image centered on the PRF image (in PRF pixel units)
    prfDimY = int(ydim / cdelt1p[0])
    prfDimX = int(xdim / cdelt2p[0])
    PRFy0 = (np.shape(prf)[0] - prfDimY) / 2
    PRFx0 = (np.shape(prf)[1] - prfDimX) / 2

    # interpolation function over the PRF
    splineInterpolation = scipy.interpolate.RectBivariateSpline(
        PRFx, PRFy, prf)

    # construct mesh for background model
    if background:
        bx = np.arange(1., float(xdim + 1))
        by = np.arange(1., float(ydim + 1))
        xx, yy = np.meshgrid(np.linspace(bx.min(), bx.max(), xdim),
                             np.linspace(by.min(), by.max(), ydim))

    # fit PRF model to pixel data
    start = time.time()
    if focus and background:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithFocusAndBackground,
                          guess,
                          args=args,
                          xtol=xtol,
                          ftol=ftol,
                          disp=False)
    elif focus and not background:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithFocus,
                          guess,
                          args=args,
                          xtol=xtol,
                          ftol=ftol,
                          disp=False)
    elif background and not focus:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy,
                splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithBackground,
                          guess,
                          args=args,
                          xtol=xtol,
                          ftol=ftol,
                          disp=False)
    else:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation,
                float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRF,
                          guess,
                          args=args,
                          xtol=xtol,
                          ftol=ftol,
                          disp=False)
    kepmsg.log(logfile, 'Convergence time = %.2fs\n' % (time.time() - start),
               True)

    # pad the PRF data if the PRF array is smaller than the data array
    flux = []
    OBJx = []
    OBJy = []
    PRFmod = np.zeros((prfDimY, prfDimX))
    if PRFy0 < 0 or PRFx0 < 0.0:
        PRFmod = np.zeros((prfDimY, prfDimX))
        superPRF = np.zeros((prfDimY + 1, prfDimX + 1))
        superPRF[np.abs(PRFy0):np.abs(PRFy0) + np.shape(prf)[0],
                 np.abs(PRFx0):np.abs(PRFx0) + np.shape(prf)[1]] = prf
        prf = superPRF * 1.0
        PRFy0 = 0
        PRFx0 = 0

    # rotate the PRF model around its center
    if focus:
        angle = ans[-1]
        prf = rotate(prf, -angle, reshape=False, mode='nearest')

    # iterate through the sources in the best fit PSF model
    for i in range(nsrc):
        flux.append(ans[i])
        OBJx.append(ans[nsrc + i])
        OBJy.append(ans[nsrc * 2 + i])

        # calculate best-fit model
        y = (OBJy[i] - np.mean(DATy)) / cdelt1p[0]
        x = (OBJx[i] - np.mean(DATx)) / cdelt2p[0]
        prfTmp = shift(prf, [y, x], order=3, mode='constant')
        prfTmp = prfTmp[PRFy0:PRFy0 + prfDimY, PRFx0:PRFx0 + prfDimX]
        PRFmod = PRFmod + prfTmp * flux[i]
        wx = 1.0
        wy = 1.0
        angle = 0
        b = 0.0

        # write out best fit parameters
        txt = 'Flux = %10.2f e-/s ' % flux[i]
        txt += 'X = %9.4f pix ' % OBJx[i]
        txt += 'Y = %9.4f pix ' % OBJy[i]
        kepmsg.log(logfile, txt, True)

    if background:
        bterms = border + 1
        if bterms == 1:
            b = ans[nsrc * 3]
        else:
            bcoeff = np.array([
                ans[nsrc * 3:nsrc * 3 + bterms],
                ans[nsrc * 3 + bterms:nsrc * 3 + bterms * 2]
            ])
            bkg = kepfunc.polyval2d(xx, yy, bcoeff)
            b = nanmean(bkg.reshape(bkg.size))
        txt = '\n   Mean background = %.2f e-/s' % b
        kepmsg.log(logfile, txt, True)
    if focus:
        wx = ans[-3]
        wy = ans[-2]
        angle = ans[-1]
        if not background: kepmsg.log(logfile, '', True)
        kepmsg.log(logfile, ' X/Y focus factors = %.3f/%.3f' % (wx, wy), True)
        kepmsg.log(logfile, 'PRF rotation angle = %.2f deg' % angle, True)

    # measure flux fraction and contamination

    # LUGER: This looks horribly bugged. ``PRFall`` is certainly NOT the sum of the all the sources.
    # Check out my comments in ``kepfunc.py``.

    PRFall = kepfunc.PRF2DET(flux, OBJx, OBJy, DATx, DATy, wx, wy, angle,
                             splineInterpolation)
    PRFone = kepfunc.PRF2DET([flux[0]], [OBJx[0]], [OBJy[0]], DATx, DATy, wx,
                             wy, angle, splineInterpolation)

    # LUGER: Add up contaminant fluxes
    PRFcont = np.zeros_like(PRFone)
    for ncont in range(1, len(flux)):
        PRFcont += kepfunc.PRF2DET([flux[ncont]], [OBJx[ncont]], [OBJy[ncont]],
                                   DATx, DATy, wx, wy, angle,
                                   splineInterpolation)
    PRFcont[np.where(PRFcont < 0)] = 0

    FluxInMaskAll = np.nansum(PRFall)
    FluxInMaskOne = np.nansum(PRFone)
    FluxInAperAll = 0.0
    FluxInAperOne = 0.0
    FluxInAperAllTrue = 0.0

    for i in range(1, ydim):
        for j in range(1, xdim):
            if kepstat.bitInBitmap(maskimg[i, j], 2):
                FluxInAperAll += PRFall[i, j]
                FluxInAperOne += PRFone[i, j]
                FluxInAperAllTrue += PRFone[i, j] + PRFcont[i, j]
    FluxFraction = FluxInAperOne / flux[0]
    try:
        Contamination = (FluxInAperAll - FluxInAperOne) / FluxInAperAll
    except:
        Contamination = 0.0

    # LUGER: Pixel crowding metrics
    Crowding = PRFone / (PRFone + PRFcont)
    Crowding[np.where(Crowding < 0)] = np.nan

    # LUGER: Optimal aperture crowding metric
    CrowdAper = FluxInAperOne / FluxInAperAllTrue

    kepmsg.log(
        logfile,
        '\n                Total flux in mask = %.2f e-/s' % FluxInMaskAll,
        True)
    kepmsg.log(
        logfile,
        '               Target flux in mask = %.2f e-/s' % FluxInMaskOne, True)
    kepmsg.log(
        logfile,
        '            Total flux in aperture = %.2f e-/s' % FluxInAperAll, True)
    kepmsg.log(
        logfile,
        '           Target flux in aperture = %.2f e-/s' % FluxInAperOne, True)
    kepmsg.log(
        logfile,
        '  Target flux fraction in aperture = %.2f%%' % (FluxFraction * 100.0),
        True)
    kepmsg.log(
        logfile, 'Contamination fraction in aperture = %.2f%%' %
        (Contamination * 100.0), True)
    kepmsg.log(logfile,
               '       Crowding metric in aperture = %.4f' % (CrowdAper), True)
    kepmsg.log(logfile,
               '          Crowding metric from TPF = %.4f' % (CrowdTPF), True)

    # constuct model PRF in detector coordinates
    PRFfit = PRFall + 0.0
    if background and bterms == 1:
        PRFfit = PRFall + b
    if background and bterms > 1:
        PRFfit = PRFall + bkg

    # calculate residual of DATA - FIT
    PRFres = DATimg - PRFfit
    FLUXres = np.nansum(PRFres) / npix

    # calculate the sum squared difference between data and model
    Pearson = np.abs(np.nansum(np.square(DATimg - PRFfit) / PRFfit))
    Chi2 = np.nansum(np.square(DATimg - PRFfit) / np.square(ERRimg))
    DegOfFreedom = npix - len(guess) - 1
    try:
        kepmsg.log(logfile, '\n       Residual flux = %.2f e-/s' % FLUXres,
                   True)
        kepmsg.log(
            logfile,
            'Pearson\'s chi^2 test = %d for %d dof' % (Pearson, DegOfFreedom),
            True)
    except:
        pass
    kepmsg.log(logfile,
               '          Chi^2 test = %d for %d dof' % (Chi2, DegOfFreedom),
               True)

    # image scale and intensity limits for plotting images
    imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg, imscale)
    imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod, imscale)
    imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit, imscale)
    imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres, 'linear')
    if imscale == 'linear':
        zmaxpr *= 0.9
    elif imscale == 'logarithmic':
        zmaxpr = np.max(zmaxpr)
        zminpr = zmaxpr / 2

    # plot
    pl.figure(figsize=[12, 10])
    pl.clf()

    # data
    plotimage(imgdat_pl, zminfl, zmaxfl, 1, row, column, xdim, ydim, 0.07,
              0.58, 'observation', cmap, lcolor)
    pl.text(0.05,
            0.05,
            'CROWDSAP: %.4f' % CrowdTPF,
            horizontalalignment='left',
            verticalalignment='center',
            fontsize=18,
            fontweight=500,
            color=lcolor,
            transform=pl.gca().transAxes)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, '--',
                    0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, '-',
                    3.0)

    # model
    plotimage(imgprf_pl, zminpr, zmaxpr, 2, row, column, xdim, ydim, 0.445,
              0.58, 'model', cmap, lcolor)
    pl.text(0.05,
            0.05,
            'Crowding: %.4f' % CrowdAper,
            horizontalalignment='left',
            verticalalignment='center',
            fontsize=18,
            fontweight=500,
            color=lcolor,
            transform=pl.gca().transAxes)
    for x, y in zip(OBJx, OBJy):
        pl.scatter(x, y, marker='x', color='w')
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, '--',
                    0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, '-',
                    3.0)

    if srcinfo is not None:
        kepid, sx, sy, kepmag = srcinfo
        for i in range(len(sx) - 1, -1, -1):
            if kepid[i] != 0 and kepmag[i] != 0.0:
                size = max(
                    np.array([
                        80.0, 80.0 +
                        (2.5**(18.0 - max(12.0, float(kepmag[i])))) * 250.0
                    ]))
                pl.scatter(sx[i],
                           sy[i],
                           s=size,
                           facecolors='g',
                           edgecolors='k',
                           alpha=0.1)
            else:
                pl.scatter(sx[i],
                           sy[i],
                           s=80,
                           facecolors='r',
                           edgecolors='k',
                           alpha=0.1)

    # binned model
    plotimage(imgfit_pl,
              zminfl,
              zmaxfl,
              3,
              row,
              column,
              xdim,
              ydim,
              0.07,
              0.18,
              'fit',
              cmap,
              lcolor,
              crowd=Crowding)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, '--',
                    0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, '-',
                    3.0)

    # residuals
    reslim = max(np.abs(zminre), np.abs(zmaxre))
    plotimage(imgres_pl, -reslim, reslim, 4, row, column, xdim, ydim, 0.445,
              0.18, 'residual', 'coolwarm', lcolor)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, '--',
                    0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, '-',
                    3.0)

    # plot data color bar
    barwin = pl.axes([0.84, 0.18, 0.03, 0.8])
    if imscale == 'linear':
        brange = np.arange(zminfl, zmaxfl, (zmaxfl - zminfl) / 1000)
    elif imscale == 'logarithmic':
        brange = np.arange(10.0**zminfl, 10.0**zmaxfl,
                           (10.0**zmaxfl - 10.0**zminfl) / 1000)
    elif imscale == 'squareroot':
        brange = np.arange(zminfl**2, zmaxfl**2,
                           (zmaxfl**2 - zminfl**2) / 1000)
    if imscale == 'linear':
        barimg = np.resize(brange, (1000, 1))
    elif imscale == 'logarithmic':
        barimg = np.log10(np.resize(brange, (1000, 1)))
    elif imscale == 'squareroot':
        barimg = np.sqrt(np.resize(brange, (1000, 1)))
    try:
        nrm = len(str(int(np.nanmax(brange)))) - 1
    except:
        nrm = 0
    brange = brange / 10**nrm
    pl.imshow(barimg,
              aspect='auto',
              interpolation='nearest',
              origin='lower',
              vmin=np.nanmin(barimg),
              vmax=np.nanmax(barimg),
              extent=(0.0, 1.0, brange[0], brange[-1]),
              cmap=cmap)
    barwin.yaxis.tick_right()
    barwin.yaxis.set_label_position('right')
    barwin.yaxis.set_major_locator(MaxNLocator(7))
    pl.gca().yaxis.set_major_formatter(pl.ScalarFormatter(useOffset=False))
    pl.gca().set_autoscale_on(False)
    pl.setp(pl.gca(), xticklabels=[], xticks=[])
    pl.ylabel('Flux (10$^%d$ e$^-$ s$^{-1}$)' % nrm)
    pl.setp(barwin.get_yticklabels(), 'rotation', 90)
    barwin.yaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    # plot residual color bar
    barwin = pl.axes([0.07, 0.08, 0.75, 0.03])
    brange = np.arange(-reslim, reslim, reslim / 500)
    barimg = np.resize(brange, (1, 1000))
    pl.imshow(barimg,
              aspect='auto',
              interpolation='nearest',
              origin='lower',
              vmin=np.nanmin(barimg),
              vmax=np.nanmax(barimg),
              extent=(brange[0], brange[-1], 0.0, 1.0),
              cmap='coolwarm')
    barwin.xaxis.set_major_locator(MaxNLocator(7))
    pl.gca().xaxis.set_major_formatter(pl.ScalarFormatter(useOffset=False))
    pl.gca().set_autoscale_on(False)
    pl.setp(pl.gca(), yticklabels=[], yticks=[])
    pl.xlabel('Residuals (e$^-$ s$^{-1}$)')
    barwin.xaxis.set_major_formatter(FormatStrFormatter('%.1f'))

    # render plot
    pl.show(block=True)
    pl.close()

    # stop time
    kepmsg.clock('\nKEPPRF ended at', logfile, True)

    return Crowding
Exemple #12
0
def kepprfphot(infile,outroot,columns,rows,fluxes,border,background,focus,prfdir,ranges,
               tolerance,ftolerance,qualflags,plt,clobber,verbose,logfile,status,cmdLine=False): 

# input arguments

    status = 0
    seterr(all="ignore") 

# log the call 

    hashline = '----------------------------------------------------------------------------'
    kepmsg.log(logfile,hashline,verbose)
    call = 'KEPPRFPHOT -- '
    call += 'infile='+infile+' '
    call += 'outroot='+outroot+' '
    call += 'columns='+columns+' '
    call += 'rows='+rows+' '
    call += 'fluxes='+fluxes+' '
    call += 'border='+str(border)+' '
    bground = 'n'
    if (background): bground = 'y'
    call += 'background='+bground+' '
    focs = 'n'
    if (focus): focs = 'y'
    call += 'focus='+focs+' '
    call += 'prfdir='+prfdir+' '
    call += 'ranges='+ranges+' '
    call += 'xtol='+str(tolerance)+' '
    call += 'ftol='+str(ftolerance)+' '
    quality = 'n'
    if (qualflags): quality = 'y'
    call += 'qualflags='+quality+' '
    plotit = 'n'
    if (plt): plotit = 'y'
    call += 'plot='+plotit+' '
    overwrite = 'n'
    if (clobber): overwrite = 'y'
    call += 'clobber='+overwrite+ ' '
    chatter = 'n'
    if (verbose): chatter = 'y'
    call += 'verbose='+chatter+' '
    call += 'logfile='+logfile
    kepmsg.log(logfile,call+'\n',verbose)

# test log file

    logfile = kepmsg.test(logfile)

# start time

    kepmsg.clock('KEPPRFPHOT started at',logfile,verbose)

# number of sources

    if status == 0:
        work = fluxes.strip()
        work = re.sub(' ',',',work)
        work = re.sub(';',',',work)
        nsrc = len(work.split(','))

# construct inital guess vector for fit 

    if status == 0:
        guess = []
        try:
            f = fluxes.strip().split(',')
            x = columns.strip().split(',')
            y = rows.strip().split(',')
            for i in range(len(f)):
                f[i] = float(f[i])
        except:
            f = fluxes
            x = columns
            y = rows
        nsrc = len(f)
        for i in range(nsrc):
            try:
                guess.append(float(f[i]))
            except:
                message = 'ERROR -- KEPPRF: Fluxes must be floating point numbers'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            if len(x) != nsrc or len(y) != nsrc:
                message = 'ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and '
                message += 'fluxes must have the same number of sources'
                status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in range(nsrc):
                try:
                    guess.append(float(x[i]))
                except:
                    message = 'ERROR -- KEPPRF: Columns must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0:
            for i in range(nsrc):
                try:
                    guess.append(float(y[i]))
                except:
                    message = 'ERROR -- KEPPRF: Rows must be floating point numbers'
                    status = kepmsg.err(logfile,message,verbose)
        if status == 0 and background:
            if border == 0:
                guess.append(0.0)
            else:
                for i in range((border+1)*2):
                    guess.append(0.0)
        if status == 0 and focus:
            guess.append(1.0); guess.append(1.0); guess.append(0.0)

# clobber output file

    for i in range(nsrc):
        outfile = '%s_%d.fits' % (outroot, i)
        if clobber: status = kepio.clobber(outfile,logfile,verbose)
        if kepio.fileexists(outfile): 
            message = 'ERROR -- KEPPRFPHOT: ' + outfile + ' exists. Use --clobber'
            status = kepmsg.err(logfile,message,verbose)

# open TPF FITS file

    if status == 0:
        try:
            kepid, channel, skygroup, module, output, quarter, season, \
                ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \
                kepio.readTPF(infile,'TIME',logfile,verbose)
        except:
            message = 'ERROR -- KEPPRFPHOT: is %s a Target Pixel File? ' % infile
            status = kepmsg.err(logfile,message,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \
            kepio.readTPF(infile,'TIMECORR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \
            kepio.readTPF(infile,'CADENCENO',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \
            kepio.readTPF(infile,'FLUX',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \
            kepio.readTPF(infile,'FLUX_ERR',logfile,verbose)
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, poscorr1, status = \
            kepio.readTPF(infile,'POS_CORR1',logfile,verbose)
        if status != 0:
            poscorr1 = numpy.zeros((len(barytime)),dtype='float32')
            poscorr1[:] = numpy.nan
            status = 0
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, poscorr2, status = \
            kepio.readTPF(infile,'POS_CORR2',logfile,verbose)
        if status != 0:
            poscorr2 = numpy.zeros((len(barytime)),dtype='float32')
            poscorr2[:] = numpy.nan
            status = 0
    if status == 0:
        kepid, channel, skygroup, module, output, quarter, season, \
            ra, dec, column, row, kepmag, xdim, ydim, qual, status = \
            kepio.readTPF(infile,'QUALITY',logfile,verbose)
    if status == 0:
        struct, status = kepio.openfits(infile,'readonly',logfile,verbose)
    if status == 0:
        tstart, tstop, bjdref, cadence, status = kepio.timekeys(struct,infile,logfile,verbose,status)

# input file keywords and mask map

    if status == 0:
        cards0 = struct[0].header.cards
        cards1 = struct[1].header.cards
        cards2 = struct[2].header.cards
        maskmap = copy(struct[2].data)
        npix = numpy.size(numpy.nonzero(maskmap)[0])

# print target data

    if status == 0 and verbose:
        print('')
        print(('      KepID:  %s' % kepid))
        print((' RA (J2000):  %s' % ra))
        print(('Dec (J2000): %s' % dec))
        print(('     KepMag:  %s' % kepmag))
        print(('   SkyGroup:    %2s' % skygroup))
        print(('     Season:    %2s' % str(season)))
        print(('    Channel:    %2s' % channel))
        print(('     Module:    %2s' % module))
        print(('     Output:     %1s' % output))
        print('')

# determine suitable PRF calibration file

    if status == 0:
        if int(module) < 10:
            prefix = 'kplr0'
        else:
            prefix = 'kplr'
        prfglob = prfdir + '/' + prefix + str(module) + '.' + str(output) + '*' + '_prf.fits'
        try:
            prffile = glob.glob(prfglob)[0]
        except:
            message = 'ERROR -- KEPPRFPHOT: No PRF file found in ' + prfdir
            status = kepmsg.err(logfile,message,verbose)

# read PRF images

    if status == 0:
        prfn = [0,0,0,0,0]
        crpix1p = numpy.zeros((5),dtype='float32')
        crpix2p = numpy.zeros((5),dtype='float32')
        crval1p = numpy.zeros((5),dtype='float32')
        crval2p = numpy.zeros((5),dtype='float32')
        cdelt1p = numpy.zeros((5),dtype='float32')
        cdelt2p = numpy.zeros((5),dtype='float32')
        for i in range(5):
            prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status \
                = kepio.readPRFimage(prffile,i+1,logfile,verbose)    
        PRFx = arange(0.5,shape(prfn[0])[1]+0.5)
        PRFy = arange(0.5,shape(prfn[0])[0]+0.5)
        PRFx = (PRFx - size(PRFx) / 2) * cdelt1p[0]
        PRFy = (PRFy - size(PRFy) / 2) * cdelt2p[0]

# interpolate the calibrated PRF shape to the target position

    if status == 0:
        prf = zeros(shape(prfn[0]),dtype='float32')
        prfWeight = zeros((5),dtype='float32')
        for i in range(5):
            prfWeight[i] = sqrt((column - crval1p[i])**2 + (row - crval2p[i])**2)
            if prfWeight[i] == 0.0:
                prfWeight[i] = 1.0e6
            prf = prf + prfn[i] / prfWeight[i]
        prf = prf / nansum(prf)
        prf = prf / cdelt1p[0] / cdelt2p[0]

# location of the data image centered on the PRF image (in PRF pixel units)

    if status == 0:
        prfDimY = ydim / cdelt1p[0]
        prfDimX = xdim / cdelt2p[0]
        PRFy0 = (shape(prf)[0] - prfDimY) / 2
        PRFx0 = (shape(prf)[1] - prfDimX) / 2

# construct input pixel image

    if status == 0:
        DATx = arange(column,column+xdim)
        DATy = arange(row,row+ydim)

# interpolation function over the PRF

    if status == 0:
        splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx,PRFy,prf,kx=3,ky=3)

# construct mesh for background model

    if status == 0:
        bx = numpy.arange(1.,float(xdim+1))
        by = numpy.arange(1.,float(ydim+1))
        xx, yy = numpy.meshgrid(numpy.linspace(bx.min(), bx.max(), xdim),
                                numpy.linspace(by.min(), by.max(), ydim))

# Get time ranges for new photometry, flag good data

    if status == 0:
        barytime += bjdref
        tstart,tstop,status = kepio.timeranges(ranges,logfile,verbose)
        incl = numpy.zeros((len(barytime)),dtype='int')
        for rownum in range(len(barytime)):
            for winnum in range(len(tstart)):
                if barytime[rownum] >= tstart[winnum] and \
                        barytime[rownum] <= tstop[winnum] and \
                        (qual[rownum] == 0 or qualflags) and \
                        numpy.isfinite(barytime[rownum]) and \
                        numpy.isfinite(numpy.nansum(fluxpixels[rownum,:])):
                    incl[rownum] = 1
        if not numpy.in1d(1,incl):
            message = 'ERROR -- KEPPRFPHOT: No legal data within the range ' + ranges
            status = kepmsg.err(logfile,message,verbose)

# filter out bad data

    if status == 0:
        n = 0
        nincl = (incl == 1).sum()
        tim = zeros((nincl),'float64')
        tco = zeros((nincl),'float32')
        cad = zeros((nincl),'float32')
        flu = zeros((nincl,len(fluxpixels[0])),'float32')
        fer = zeros((nincl,len(fluxpixels[0])),'float32')
        pc1 = zeros((nincl),'float32')
        pc2 = zeros((nincl),'float32')
        qua = zeros((nincl),'float32')
        for rownum in range(len(barytime)):
            if incl[rownum] == 1:
                tim[n] = barytime[rownum]
                tco[n] = tcorr[rownum]
                cad[n] = cadno[rownum]
                flu[n,:] = fluxpixels[rownum]
                fer[n,:] = errpixels[rownum]
                pc1[n] = poscorr1[rownum]
                pc2[n] = poscorr2[rownum]
                qua[n] = qual[rownum]
                n += 1
        barytime = tim * 1.0
        tcorr = tco * 1.0
        cadno = cad * 1.0
        fluxpixels = flu * 1.0
        errpixels = fer * 1.0
        poscorr1 = pc1 * 1.0
        poscorr2 = pc2 * 1.0
        qual = qua * 1.0

# initialize plot arrays

    if status == 0:
        t = numpy.array([],dtype='float64')
        fl = []; dx = []; dy = []; bg = []; fx = []; fy = []; fa = []; rs = []; ch = []
        for i in range(nsrc):
            fl.append(numpy.array([],dtype='float32'))
            dx.append(numpy.array([],dtype='float32'))
            dy.append(numpy.array([],dtype='float32'))

# Preparing fit data message

    if status == 0:
        progress = numpy.arange(nincl)
        if verbose:
            txt  = 'Preparing...'
            sys.stdout.write(txt)
            sys.stdout.flush()

# single processor version

    if status == 0:# and not cmdLine:
        oldtime = 0.0
        for rownum in range(numpy.min([80,len(barytime)])):
            try:
                if barytime[rownum] - oldtime > 0.5:
                    ftol = 1.0e-10; xtol = 1.0e-10
            except:
                pass
            args = (fluxpixels[rownum,:],errpixels[rownum,:],DATx,DATy,nsrc,border,xx,yy,PRFx,PRFy,splineInterpolation,
                    guess,ftol,xtol,focus,background,rownum,80,float(x[i]),float(y[i]),False)
            guess = PRFfits(args)
            ftol = ftolerance; xtol = tolerance; oldtime = barytime[rownum]

# Fit the time series: multi-processing

    if status == 0 and cmdLine:
        anslist = []
        cad1 = 0; cad2 = 50
        for i in range(int(nincl/50) + 1):
            try:
                fluxp = fluxpixels[cad1:cad2,:]
                errp = errpixels[cad1:cad2,:]
                progress = numpy.arange(cad1,cad2)
            except:
                fluxp = fluxpixels[cad1:nincl,:]
                errp = errpixels[cad1:nincl,:]
                progress = numpy.arange(cad1,nincl)
            try:
                args = zip(fluxp,errp,itertools.repeat(DATx),itertools.repeat(DATy),
                                      itertools.repeat(nsrc),itertools.repeat(border),itertools.repeat(xx),
                                      itertools.repeat(yy),itertools.repeat(PRFx),itertools.repeat(PRFy),
                                      itertools.repeat(splineInterpolation),itertools.repeat(guess),
                                      itertools.repeat(ftolerance),itertools.repeat(tolerance),
                                      itertools.repeat(focus),itertools.repeat(background),progress,
                                      itertools.repeat(numpy.arange(cad1,nincl)[-1]),
                                      itertools.repeat(float(x[0])),
                                      itertools.repeat(float(y[0])),itertools.repeat(True))
                p = multiprocessing.Pool()
                model = [0.0]
                model = p.imap(PRFfits,args,chunksize=1)
                p.close()
                p.join()
                cad1 += 50; cad2 += 50
                ans = array([array(item) for item in zip(*model)])
                try:
                    anslist = numpy.concatenate((anslist,ans.transpose()),axis=0)
                except:
                    anslist = ans.transpose()
                guess = anslist[-1]
                ans = anslist.transpose()
            except:
                pass
            
# single processor version

    if status == 0 and not cmdLine:
        oldtime = 0.0; ans = []
#        for rownum in xrange(1,10):
        for rownum in range(nincl):
            proctime = time.time()
            try:
                if barytime[rownum] - oldtime > 0.5:
                    ftol = 1.0e-10; xtol = 1.0e-10
            except:
                pass
            args = (fluxpixels[rownum,:],errpixels[rownum,:],DATx,DATy,nsrc,border,xx,yy,PRFx,PRFy,splineInterpolation,
                    guess,ftol,xtol,focus,background,rownum,nincl,float(x[0]),float(y[0]),True)
            guess = PRFfits(args)
            ans.append(guess)
            ftol = ftolerance; xtol = tolerance; oldtime = barytime[rownum]
        ans = array(ans).transpose()

# unpack the best fit parameters

    if status == 0:
        flux = []; OBJx = []; OBJy = []
        na = shape(ans)[1]
        for i in range(nsrc):
            flux.append(ans[i,:])
            OBJx.append(ans[nsrc+i,:])
            OBJy.append(ans[nsrc*2+i,:])
        try:
            bterms = border + 1
            if bterms == 1:
                b = ans[nsrc*3,:]
            else:
                b = array([])
                bkg = []
                for i in range(na):
                    bcoeff = array([ans[nsrc*3:nsrc*3+bterms,i],ans[nsrc*3+bterms:nsrc*3+bterms*2,i]])
                    bkg.append(kepfunc.polyval2d(xx,yy,bcoeff))
                    b = numpy.append(b,nanmean(bkg[-1].reshape(bkg[-1].size)))
        except:
            b = zeros((na))
        if focus:
            wx = ans[-3,:]; wy = ans[-2,:]; angle = ans[-1,:]
        else:
            wx = ones((na)); wy = ones((na)); angle = zeros((na))
        
# constuct model PRF in detector coordinates

    if status == 0:
        residual = []; chi2 = []
        for i in range(na):
            f = empty((nsrc))
            x = empty((nsrc))
            y = empty((nsrc))
            for j in range(nsrc):
                f[j] = flux[j][i]
                x[j] = OBJx[j][i]
                y[j] = OBJy[j][i]
            PRFfit = kepfunc.PRF2DET(f,x,y,DATx,DATy,wx[i],wy[i],angle[i],splineInterpolation)
            if background and bterms == 1:
                PRFfit = PRFfit + b[i]
            if background and bterms > 1:
                PRFfit = PRFfit + bkg[i]

# calculate residual of DATA - FIT

            xdim = shape(xx)[1]
            ydim = shape(yy)[0]
            DATimg = numpy.empty((ydim,xdim))
            n = 0
            for k in range(ydim):
                for j in range(xdim):
                    DATimg[k,j] = fluxpixels[i,n]
                    n += 1
            PRFres = DATimg - PRFfit
            residual.append(numpy.nansum(PRFres) / npix)
    
# calculate the sum squared difference between data and model

            chi2.append(abs(numpy.nansum(numpy.square(DATimg - PRFfit) / PRFfit)))

# load the output arrays

    if status == 0:
        otime = barytime - bjdref
        otimecorr = tcorr
        ocadenceno = cadno
        opos_corr1 = poscorr1
        opos_corr2 = poscorr2
        oquality = qual
        opsf_bkg = b
        opsf_focus1 = wx
        opsf_focus2 = wy
        opsf_rotation = angle
        opsf_residual = residual
        opsf_chi2 = chi2
        opsf_flux_err = numpy.empty((na)); opsf_flux_err.fill(numpy.nan)
        opsf_centr1_err = numpy.empty((na)); opsf_centr1_err.fill(numpy.nan)
        opsf_centr2_err = numpy.empty((na)); opsf_centr2_err.fill(numpy.nan)
        opsf_bkg_err = numpy.empty((na)); opsf_bkg_err.fill(numpy.nan)
        opsf_flux = []
        opsf_centr1 = []
        opsf_centr2 = []
        for i in range(nsrc):
            opsf_flux.append(flux[i])
            opsf_centr1.append(OBJx[i])
            opsf_centr2.append(OBJy[i])

# load the plot arrays

    if status == 0:
        t = barytime
        for i in range(nsrc):
            fl[i] = flux[i]
            dx[i] = OBJx[i]
            dy[i] = OBJy[i]
        bg = b
        fx = wx
        fy = wy
        fa = angle
        rs = residual
        ch = chi2
                
# construct output primary extension

    if status == 0:
        for j in range(nsrc):
            hdu0 = pyfits.PrimaryHDU()
            for i in range(len(cards0)):
                if cards0[i].key not in list(hdu0.header.keys()):
                    hdu0.header.update(cards0[i].key, cards0[i].value, cards0[i].comment)
                else:
                    hdu0.header.cards[cards0[i].key].comment = cards0[i].comment
            status = kepkey.history(call,hdu0,outfile,logfile,verbose)
            outstr = HDUList(hdu0)

# construct output light curve extension

            col1 = Column(name='TIME',format='D',unit='BJD - 2454833',array=otime)
            col2 = Column(name='TIMECORR',format='E',unit='d',array=otimecorr)
            col3 = Column(name='CADENCENO',format='J',array=ocadenceno)
            col4 = Column(name='PSF_FLUX',format='E',unit='e-/s',array=opsf_flux[j])
            col5 = Column(name='PSF_FLUX_ERR',format='E',unit='e-/s',array=opsf_flux_err)
            col6 = Column(name='PSF_BKG',format='E',unit='e-/s/pix',array=opsf_bkg)
            col7 = Column(name='PSF_BKG_ERR',format='E',unit='e-/s',array=opsf_bkg_err)
            col8 = Column(name='PSF_CENTR1',format='E',unit='pixel',array=opsf_centr1[j])
            col9 = Column(name='PSF_CENTR1_ERR',format='E',unit='pixel',array=opsf_centr1_err)
            col10 = Column(name='PSF_CENTR2',format='E',unit='pixel',array=opsf_centr2[j])
            col11 = Column(name='PSF_CENTR2_ERR',format='E',unit='pixel',array=opsf_centr2_err)
            col12 = Column(name='PSF_FOCUS1',format='E',array=opsf_focus1)
            col13 = Column(name='PSF_FOCUS2',format='E',array=opsf_focus2)
            col14 = Column(name='PSF_ROTATION',format='E',unit='deg',array=opsf_rotation)
            col15 = Column(name='PSF_RESIDUAL',format='E',unit='e-/s',array=opsf_residual)
            col16 = Column(name='PSF_CHI2',format='E',array=opsf_chi2)
            col17 = Column(name='POS_CORR1',format='E',unit='pixel',array=opos_corr1)
            col18 = Column(name='POS_CORR2',format='E',unit='pixel',array=opos_corr2)
            col19 = Column(name='SAP_QUALITY',format='J',array=oquality)
            cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,
                            col12,col13,col14,col15,col16,col17,col18,col19])
            hdu1 = new_table(cols)
            for i in range(len(cards1)):
                if (cards1[i].key not in list(hdu1.header.keys()) and
                    cards1[i].key[:4] not in ['TTYP','TFOR','TUNI','TDIS','TDIM','WCAX','1CTY',
                                              '2CTY','1CRP','2CRP','1CRV','2CRV','1CUN','2CUN',
                                              '1CDE','2CDE','1CTY','2CTY','1CDL','2CDL','11PC',
                                              '12PC','21PC','22PC']):
                    hdu1.header.update(cards1[i].key, cards1[i].value, cards1[i].comment)
            outstr.append(hdu1)

# construct output mask bitmap extension

            hdu2 = ImageHDU(maskmap)
            for i in range(len(cards2)):
                if cards2[i].key not in list(hdu2.header.keys()):
                    hdu2.header.update(cards2[i].key, cards2[i].value, cards2[i].comment)
                else:
                    hdu2.header.cards[cards2[i].key].comment = cards2[i].comment
            outstr.append(hdu2)

# write output file

            outstr.writeto(outroot + '_' + str(j) + '.fits',checksum=True)

# close input structure

            status = kepio.closefits(struct,logfile,verbose)            

# clean up x-axis unit

    if status == 0:
        barytime0 = float(int(t[0] / 100) * 100.0)
        t -= barytime0
        t = numpy.insert(t,[0],[t[0]]) 
        t = numpy.append(t,[t[-1]])
        xlab = 'BJD $-$ %d' % barytime0

# plot the light curves

    if status == 0:
        bg = numpy.insert(bg,[0],[-1.0e10]) 
        bg = numpy.append(bg,-1.0e10)
        fx = numpy.insert(fx,[0],[fx[0]]) 
        fx = numpy.append(fx,fx[-1])
        fy = numpy.insert(fy,[0],[fy[0]]) 
        fy = numpy.append(fy,fy[-1])
        fa = numpy.insert(fa,[0],[fa[0]]) 
        fa = numpy.append(fa,fa[-1])
        rs = numpy.insert(rs,[0],[-1.0e10]) 
        rs = numpy.append(rs,-1.0e10)
        ch = numpy.insert(ch,[0],[-1.0e10]) 
        ch = numpy.append(ch,-1.0e10)
        for i in range(nsrc):

# clean up y-axis units

            nrm = math.ceil(math.log10(numpy.nanmax(fl[i]))) - 1.0
            fl[i] /= 10**nrm
            if nrm == 0:
                ylab1 = 'e$^-$ s$^{-1}$'
            else:
                ylab1 = '10$^{%d}$ e$^-$ s$^{-1}$' % nrm
            xx = copy(dx[i])
            yy = copy(dy[i])
            ylab2 = 'offset (pixels)'
            
# data limits

            xmin = numpy.nanmin(t)
            xmax = numpy.nanmax(t)
            ymin1 = numpy.nanmin(fl[i])
            ymax1 = numpy.nanmax(fl[i])
            ymin2 = numpy.nanmin(xx)
            ymax2 = numpy.nanmax(xx)
            ymin3 = numpy.nanmin(yy)
            ymax3 = numpy.nanmax(yy)
            ymin4 = numpy.nanmin(bg[1:-1])
            ymax4 = numpy.nanmax(bg[1:-1])
            ymin5 = numpy.nanmin([numpy.nanmin(fx),numpy.nanmin(fy)])
            ymax5 = numpy.nanmax([numpy.nanmax(fx),numpy.nanmax(fy)])
            ymin6 = numpy.nanmin(fa[1:-1])
            ymax6 = numpy.nanmax(fa[1:-1])
            ymin7 = numpy.nanmin(rs[1:-1])
            ymax7 = numpy.nanmax(rs[1:-1])
            ymin8 = numpy.nanmin(ch[1:-1])
            ymax8 = numpy.nanmax(ch[1:-1])
            xr = xmax - xmin
            yr1 = ymax1 - ymin1
            yr2 = ymax2 - ymin2
            yr3 = ymax3 - ymin3
            yr4 = ymax4 - ymin4
            yr5 = ymax5 - ymin5
            yr6 = ymax6 - ymin6
            yr7 = ymax7 - ymin7
            yr8 = ymax8 - ymin8
            fl[i] = numpy.insert(fl[i],[0],[0.0]) 
            fl[i] = numpy.append(fl[i],0.0)

# plot style

            try:
                params = {'backend': 'png',
                          'axes.linewidth': 2.5,
                          'axes.labelsize': 24,
                          'axes.font': 'sans-serif',
                          'axes.fontweight' : 'bold',
                          'text.fontsize': 12,
                          'legend.fontsize': 12,
                          'xtick.labelsize': 12,
                          'ytick.labelsize': 12}
                pylab.rcParams.update(params)
            except:
                pass

# define size of plot on monitor screen

            pylab.figure(str(i+1) + ' ' + str(time.asctime(time.localtime())),figsize=[12,16])

# delete any fossil plots in the matplotlib window

            pylab.clf()

# position first axes inside the plotting window

            ax = pylab.axes([0.11,0.523,0.78,0.45])

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))

# no x-label

            pylab.setp(pylab.gca(),xticklabels=[])

# plot flux vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,fl[i][j])
                else:
                    pylab.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            pylab.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,fl[i],fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            if ymin1 - yr1 * 0.01 <= 0.0:
                pylab.ylim(1.0e-10, ymax1 + yr1 * 0.01)
            else:
                pylab.ylim(ymin1 - yr1 * 0.01, ymax1 + yr1 * 0.01)
           
# plot labels

#            pylab.xlabel(xlab, {'color' : 'k'})
            try:
                pylab.ylabel('Source (' + ylab1 + ')', {'color' : 'k'})
            except:
                ylab1 = '10**%d e-/s' % nrm
                pylab.ylabel('Source (' + ylab1 + ')', {'color' : 'k'})

# make grid on plot

            pylab.grid()

# plot centroid tracks - position second axes inside the plotting window

            if focus and background:
                axs = [0.11,0.433,0.78,0.09]
            elif background or focus:
                axs = [0.11,0.388,0.78,0.135]
            else:
                axs = [0.11,0.253,0.78,0.27]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot dx vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,xx[j-1])
                else:
                    ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin2 - yr2 * 0.03, ymax2 + yr2 * 0.03)
           
# plot labels

            ax1.set_ylabel('X-' + ylab2, color='k', fontsize=11)

# position second axes inside the plotting window

            ax2 = ax1.twinx()

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot dy vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,yy[j-1])
                else:
                    ax2.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax2.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)

# define plot y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin3 - yr3 * 0.03, ymax3 + yr3 * 0.03)
           
# plot labels

            ax2.set_ylabel('Y-' + ylab2, color='k',fontsize=11)

# background - position third axes inside the plotting window

            if background and focus:
                axs = [0.11,0.343,0.78,0.09]
            if background and not focus:
                axs = [0.11,0.253,0.78,0.135]
            if background:
                ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot background vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,bg[j])
                    else:
                        ax1.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='#0000ff',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

                pylab.fill(t,bg,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin4 - yr4 * 0.03, ymax4 + yr4 * 0.03)
           
# plot labels

                ax1.set_ylabel('Background \n(e$^-$ s$^{-1}$ pix$^{-1}$)', 
                               multialignment='center', color='k',fontsize=11)

# make grid on plot

                pylab.grid()

# position focus axes inside the plotting window

            if focus and background:
                axs = [0.11,0.253,0.78,0.09]
            if focus and not background:
                axs = [0.11,0.253,0.78,0.135]
            if focus:
                ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative
                
                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot x-axis PSF width vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fx[j])
                    else:
                        ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='r',linestyle='-',linewidth=1.0)

# plot y-axis PSF width vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fy[j])
                    else:
                        ax1.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax1.plot(ltime,ldata,color='g',linestyle='-',linewidth=1.0)

# define plot x and y limits

                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin5 - yr5 * 0.03, ymax5 + yr5 * 0.03)
           
# plot labels

                ax1.set_ylabel('Pixel Scale\nFactor', 
                               multialignment='center', color='k',fontsize=11)

# Focus rotation - position second axes inside the plotting window

                ax2 = ax1.twinx()

# force tick labels to be absolute rather than relative

                pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
                pylab.setp(pylab.gca(),xticklabels=[])

# plot dy vs time

                ltime = numpy.array([],dtype='float64')
                ldata = numpy.array([],dtype='float32')
                dt = 0
                work1 = 2.0 * cadence / 86400
                for j in range(1,len(t)-1):
                    dt = t[j] - t[j-1]
                    if dt < work1:
                        ltime = numpy.append(ltime,t[j])
                        ldata = numpy.append(ldata,fa[j])
                    else:
                        ax2.plot(ltime,ldata,color='#000080',linestyle='-',linewidth=1.0)
                        ltime = numpy.array([],dtype='float64')
                        ldata = numpy.array([],dtype='float32')
                ax2.plot(ltime,ldata,color='#000080',linestyle='-',linewidth=1.0)

# define plot y limits
                
                pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
                pylab.ylim(ymin6 - yr6 * 0.03, ymax6 + yr6 * 0.03)
           
# plot labels

                ax2.set_ylabel('Rotation (deg)', color='k',fontsize=11)

# fit residuals - position fifth axes inside the plotting window

            axs = [0.11,0.163,0.78,0.09]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.setp(pylab.gca(),xticklabels=[])

# plot residual vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,rs[j])
                else:
                    ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,rs,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin7 - yr7 * 0.03, ymax7 + yr7 * 0.03)
           
# plot labels

            ax1.set_ylabel('Residual \n(e$^-$ s$^{-1}$)', 
                           multialignment='center', color='k',fontsize=11)

# make grid on plot

            pylab.grid()

# fit chi square - position sixth axes inside the plotting window

            axs = [0.11,0.073,0.78,0.09]
            ax1 = pylab.axes(axs)

# force tick labels to be absolute rather than relative

            pylab.gca().xaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))
            pylab.gca().yaxis.set_major_formatter(pylab.ScalarFormatter(useOffset=False))

# plot background vs time

            ltime = numpy.array([],dtype='float64')
            ldata = numpy.array([],dtype='float32')
            dt = 0
            work1 = 2.0 * cadence / 86400
            for j in range(1,len(t)-1):
                dt = t[j] - t[j-1]
                if dt < work1:
                    ltime = numpy.append(ltime,t[j])
                    ldata = numpy.append(ldata,ch[j])
                else:
                    ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)
                    ltime = numpy.array([],dtype='float64')
                    ldata = numpy.array([],dtype='float32')
            ax1.plot(ltime,ldata,color='b',linestyle='-',linewidth=1.0)

# plot the fill color below data time series, with no data gaps

            pylab.fill(t,ch,fc='#ffff00',linewidth=0.0,alpha=0.2)

# define plot x and y limits

            pylab.xlim(xmin - xr * 0.01, xmax + xr * 0.01)
            pylab.ylim(ymin8 - yr8 * 0.03, ymax8 + yr8 * 0.03)
           
# plot labels

            ax1.set_ylabel('$\chi^2$ (%d dof)' % (npix-len(guess)-1),color='k',fontsize=11)
            pylab.xlabel(xlab, {'color' : 'k'})

# make grid on plot

            pylab.grid()

# render plot

            if status == 0:
                pylab.savefig(outroot + '_' + str(i) + '.png')
            if status == 0 and plt:
                if cmdLine: 
                    pylab.show(block=True)
                else: 
                    pylab.ion()
                    pylab.plot([])
                    pylab.ioff()
        
# stop time

    kepmsg.clock('\n\nKEPPRFPHOT ended at',logfile,verbose)

    return
Exemple #13
0
def kepprf(
    infile,
    columns,
    rows,
    fluxes,
    rownum=0,
    border=0,
    background=0,
    focus=0,
    prfdir="../KeplerPRF",
    xtol=1.0e-6,
    ftol=1.0e-6,
    imscale="linear",
    cmap="YlOrBr",
    lcolor="k",
    acolor="b",
    logfile="kepcrowd.log",
    CrowdTPF=np.nan,
    srcinfo=None,
    **kwargs
):

    # log the call
    hashline = "----------------------------------------------------------------------------"
    kepmsg.log(logfile, hashline, True)
    call = "KEPPRF -- "
    call += "infile=" + infile + " "
    call += "rownum=" + str(rownum) + " "
    call += "columns=" + columns + " "
    call += "rows=" + rows + " "
    call += "fluxes=" + fluxes + " "
    call += "border=" + str(border) + " "
    bground = "n"
    if background:
        bground = "y"
    call += "background=" + bground + " "
    focs = "n"
    if focus:
        focs = "y"
    call += "focus=" + focs + " "
    call += "prfdir=" + prfdir + " "
    call += "xtol=" + str(xtol) + " "
    call += "ftol=" + str(xtol) + " "
    call += "logfile=" + logfile
    kepmsg.log(logfile, call + "\n", True)

    guess = []
    try:
        f = fluxes.strip().split(",")
        x = columns.strip().split(",")
        y = rows.strip().split(",")
        for i in range(len(f)):
            f[i] = float(f[i])
    except:
        f = fluxes
        x = columns
        y = rows

    nsrc = len(f)
    for i in range(nsrc):
        try:
            guess.append(float(f[i]))
        except:
            message = "ERROR -- KEPPRF: Fluxes must be floating point numbers"
            kepmsg.err(logfile, message, True)
            return None

    if len(x) != nsrc or len(y) != nsrc:
        message = "ERROR -- KEPFIT:FITMULTIPRF: Guesses for rows, columns and "
        message += "fluxes must have the same number of sources"
        kepmsg.err(logfile, message, True)
        return None

    for i in range(nsrc):
        try:
            guess.append(float(x[i]))
        except:
            message = "ERROR -- KEPPRF: Columns must be floating point numbers"
            kepmsg.err(logfile, message, True)
            return None

    for i in range(nsrc):
        try:
            guess.append(float(y[i]))
        except:
            message = "ERROR -- KEPPRF: Rows must be floating point numbers"
            kepmsg.err(logfile, message, True)
            return None

    if background:
        if border == 0:
            guess.append(0.0)
        else:
            for i in range((border + 1) * 2):
                guess.append(0.0)

    if focus:
        guess.append(1.0)
        guess.append(1.0)
        guess.append(0.0)

    # open TPF FITS file
    try:
        kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, barytime, status = kepio.readTPF(
            infile, "TIME", logfile, True
        )
    except:
        message = "ERROR -- KEPPRF: is %s a Target Pixel File? " % infile
        kepmsg.err(logfile, message, True)
        return None

    kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = kepio.readTPF(
        infile, "TIMECORR", logfile, True
    )

    kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, cadno, status = kepio.readTPF(
        infile, "CADENCENO", logfile, True
    )

    kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = kepio.readTPF(
        infile, "FLUX", logfile, True
    )

    kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = kepio.readTPF(
        infile, "FLUX_ERR", logfile, True
    )

    kepid, channel, skygroup, module, output, quarter, season, ra, dec, column, row, kepmag, xdim, ydim, qual, status = kepio.readTPF(
        infile, "QUALITY", logfile, True
    )

    # read mask defintion data from TPF file
    maskimg, pixcoord1, pixcoord2, status = kepio.readMaskDefinition(infile, logfile, True)
    npix = np.size(np.nonzero(maskimg)[0])

    print("")
    print("      KepID: %s" % kepid)
    print("        BJD: %.2f" % (barytime[rownum - 1] + 2454833.0))
    print(" RA (J2000): %s" % ra)
    print("Dec (J2000):  %s" % dec)
    print("     KepMag:  %s" % kepmag)
    print("   SkyGroup:   %2s" % skygroup)
    print("     Season:   %2s" % str(season))
    print("    Channel:   %2s" % channel)
    print("     Module:   %2s" % module)
    print("     Output:    %1s" % output)
    print("")

    # is this a good row with finite timestamp and pixels?
    if not np.isfinite(barytime[rownum - 1]) or np.nansum(fluxpixels[rownum - 1, :]) == np.nan:
        message = "ERROR -- KEPFIELD: Row " + str(rownum) + " is a bad quality timestamp"
        status = kepmsg.err(logfile, message, True)

    # construct input pixel image
    flux = fluxpixels[rownum - 1, :]
    ferr = errpixels[rownum - 1, :]
    DATx = np.arange(column, column + xdim)
    DATy = np.arange(row, row + ydim)

    # image scale and intensity limits of pixel data
    n = 0
    DATimg = np.empty((ydim, xdim))
    ERRimg = np.empty((ydim, xdim))
    for i in range(ydim):
        for j in range(xdim):
            DATimg[i, j] = flux[n]
            ERRimg[i, j] = ferr[n]
            n += 1

    # determine suitable PRF calibration file
    if int(module) < 10:
        prefix = "kplr0"
    else:
        prefix = "kplr"
    prfglob = prfdir + "/" + prefix + str(module) + "." + str(output) + "*" + "_prf.fits"
    try:
        prffile = glob.glob(prfglob)[0]
    except:
        message = "ERROR -- KEPPRF: No PRF file found in " + prfdir
        kepmsg.err(logfile, message, True)
        return None

    # read PRF images
    prfn = [0, 0, 0, 0, 0]
    crpix1p = np.zeros((5), dtype="float32")
    crpix2p = np.zeros((5), dtype="float32")
    crval1p = np.zeros((5), dtype="float32")
    crval2p = np.zeros((5), dtype="float32")
    cdelt1p = np.zeros((5), dtype="float32")
    cdelt2p = np.zeros((5), dtype="float32")
    for i in range(5):
        prfn[i], crpix1p[i], crpix2p[i], crval1p[i], crval2p[i], cdelt1p[i], cdelt2p[i], status = kepio.readPRFimage(
            prffile, i + 1, logfile, True
        )
    prfn = np.array(prfn)
    PRFx = np.arange(0.5, np.shape(prfn[0])[1] + 0.5)
    PRFy = np.arange(0.5, np.shape(prfn[0])[0] + 0.5)
    PRFx = (PRFx - np.size(PRFx) / 2) * cdelt1p[0]
    PRFy = (PRFy - np.size(PRFy) / 2) * cdelt2p[0]

    # interpolate the calibrated PRF shape to the target position
    prf = np.zeros(np.shape(prfn[0]), dtype="float32")
    prfWeight = np.zeros((5), dtype="float32")
    for i in range(5):
        prfWeight[i] = np.sqrt((column - crval1p[i]) ** 2 + (row - crval2p[i]) ** 2)
        if prfWeight[i] == 0.0:
            prfWeight[i] = 1.0e-6
        prf = prf + prfn[i] / prfWeight[i]
    prf = prf / np.nansum(prf) / cdelt1p[0] / cdelt2p[0]

    # location of the data image centered on the PRF image (in PRF pixel units)
    prfDimY = int(ydim / cdelt1p[0])
    prfDimX = int(xdim / cdelt2p[0])
    PRFy0 = (np.shape(prf)[0] - prfDimY) / 2
    PRFx0 = (np.shape(prf)[1] - prfDimX) / 2

    # interpolation function over the PRF
    splineInterpolation = scipy.interpolate.RectBivariateSpline(PRFx, PRFy, prf)

    # construct mesh for background model
    if background:
        bx = np.arange(1.0, float(xdim + 1))
        by = np.arange(1.0, float(ydim + 1))
        xx, yy = np.meshgrid(np.linspace(bx.min(), bx.max(), xdim), np.linspace(by.min(), by.max(), ydim))

    # fit PRF model to pixel data
    start = time.time()
    if focus and background:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy, splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithFocusAndBackground, guess, args=args, xtol=xtol, ftol=ftol, disp=False)
    elif focus and not background:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithFocus, guess, args=args, xtol=xtol, ftol=ftol, disp=False)
    elif background and not focus:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, border, xx, yy, splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRFwithBackground, guess, args=args, xtol=xtol, ftol=ftol, disp=False)
    else:
        args = (DATx, DATy, DATimg, ERRimg, nsrc, splineInterpolation, float(x[0]), float(y[0]))
        ans = fmin_powell(kepfunc.PRF, guess, args=args, xtol=xtol, ftol=ftol, disp=False)
    kepmsg.log(logfile, "Convergence time = %.2fs\n" % (time.time() - start), True)

    # pad the PRF data if the PRF array is smaller than the data array
    flux = []
    OBJx = []
    OBJy = []
    PRFmod = np.zeros((prfDimY, prfDimX))
    if PRFy0 < 0 or PRFx0 < 0.0:
        PRFmod = np.zeros((prfDimY, prfDimX))
        superPRF = np.zeros((prfDimY + 1, prfDimX + 1))
        superPRF[
            np.abs(PRFy0) : np.abs(PRFy0) + np.shape(prf)[0], np.abs(PRFx0) : np.abs(PRFx0) + np.shape(prf)[1]
        ] = prf
        prf = superPRF * 1.0
        PRFy0 = 0
        PRFx0 = 0

    # rotate the PRF model around its center
    if focus:
        angle = ans[-1]
        prf = rotate(prf, -angle, reshape=False, mode="nearest")

    # iterate through the sources in the best fit PSF model
    for i in range(nsrc):
        flux.append(ans[i])
        OBJx.append(ans[nsrc + i])
        OBJy.append(ans[nsrc * 2 + i])

        # calculate best-fit model
        y = (OBJy[i] - np.mean(DATy)) / cdelt1p[0]
        x = (OBJx[i] - np.mean(DATx)) / cdelt2p[0]
        prfTmp = shift(prf, [y, x], order=3, mode="constant")
        prfTmp = prfTmp[PRFy0 : PRFy0 + prfDimY, PRFx0 : PRFx0 + prfDimX]
        PRFmod = PRFmod + prfTmp * flux[i]
        wx = 1.0
        wy = 1.0
        angle = 0
        b = 0.0

        # write out best fit parameters
        txt = "Flux = %10.2f e-/s " % flux[i]
        txt += "X = %9.4f pix " % OBJx[i]
        txt += "Y = %9.4f pix " % OBJy[i]
        kepmsg.log(logfile, txt, True)

    if background:
        bterms = border + 1
        if bterms == 1:
            b = ans[nsrc * 3]
        else:
            bcoeff = np.array([ans[nsrc * 3 : nsrc * 3 + bterms], ans[nsrc * 3 + bterms : nsrc * 3 + bterms * 2]])
            bkg = kepfunc.polyval2d(xx, yy, bcoeff)
            b = nanmean(bkg.reshape(bkg.size))
        txt = "\n   Mean background = %.2f e-/s" % b
        kepmsg.log(logfile, txt, True)
    if focus:
        wx = ans[-3]
        wy = ans[-2]
        angle = ans[-1]
        if not background:
            kepmsg.log(logfile, "", True)
        kepmsg.log(logfile, " X/Y focus factors = %.3f/%.3f" % (wx, wy), True)
        kepmsg.log(logfile, "PRF rotation angle = %.2f deg" % angle, True)

    # measure flux fraction and contamination

    # LUGER: This looks horribly bugged. ``PRFall`` is certainly NOT the sum of the all the sources.
    # Check out my comments in ``kepfunc.py``.

    PRFall = kepfunc.PRF2DET(flux, OBJx, OBJy, DATx, DATy, wx, wy, angle, splineInterpolation)
    PRFone = kepfunc.PRF2DET([flux[0]], [OBJx[0]], [OBJy[0]], DATx, DATy, wx, wy, angle, splineInterpolation)

    # LUGER: Add up contaminant fluxes
    PRFcont = np.zeros_like(PRFone)
    for ncont in range(1, len(flux)):
        PRFcont += kepfunc.PRF2DET(
            [flux[ncont]], [OBJx[ncont]], [OBJy[ncont]], DATx, DATy, wx, wy, angle, splineInterpolation
        )
    PRFcont[np.where(PRFcont < 0)] = 0

    FluxInMaskAll = np.nansum(PRFall)
    FluxInMaskOne = np.nansum(PRFone)
    FluxInAperAll = 0.0
    FluxInAperOne = 0.0
    FluxInAperAllTrue = 0.0

    for i in range(1, ydim):
        for j in range(1, xdim):
            if kepstat.bitInBitmap(maskimg[i, j], 2):
                FluxInAperAll += PRFall[i, j]
                FluxInAperOne += PRFone[i, j]
                FluxInAperAllTrue += PRFone[i, j] + PRFcont[i, j]
    FluxFraction = FluxInAperOne / flux[0]
    try:
        Contamination = (FluxInAperAll - FluxInAperOne) / FluxInAperAll
    except:
        Contamination = 0.0

    # LUGER: Pixel crowding metrics
    Crowding = PRFone / (PRFone + PRFcont)
    Crowding[np.where(Crowding < 0)] = np.nan

    # LUGER: Optimal aperture crowding metric
    CrowdAper = FluxInAperOne / FluxInAperAllTrue

    kepmsg.log(logfile, "\n                Total flux in mask = %.2f e-/s" % FluxInMaskAll, True)
    kepmsg.log(logfile, "               Target flux in mask = %.2f e-/s" % FluxInMaskOne, True)
    kepmsg.log(logfile, "            Total flux in aperture = %.2f e-/s" % FluxInAperAll, True)
    kepmsg.log(logfile, "           Target flux in aperture = %.2f e-/s" % FluxInAperOne, True)
    kepmsg.log(logfile, "  Target flux fraction in aperture = %.2f%%" % (FluxFraction * 100.0), True)
    kepmsg.log(logfile, "Contamination fraction in aperture = %.2f%%" % (Contamination * 100.0), True)
    kepmsg.log(logfile, "       Crowding metric in aperture = %.4f" % (CrowdAper), True)
    kepmsg.log(logfile, "          Crowding metric from TPF = %.4f" % (CrowdTPF), True)

    # constuct model PRF in detector coordinates
    PRFfit = PRFall + 0.0
    if background and bterms == 1:
        PRFfit = PRFall + b
    if background and bterms > 1:
        PRFfit = PRFall + bkg

    # calculate residual of DATA - FIT
    PRFres = DATimg - PRFfit
    FLUXres = np.nansum(PRFres) / npix

    # calculate the sum squared difference between data and model
    Pearson = np.abs(np.nansum(np.square(DATimg - PRFfit) / PRFfit))
    Chi2 = np.nansum(np.square(DATimg - PRFfit) / np.square(ERRimg))
    DegOfFreedom = npix - len(guess) - 1
    try:
        kepmsg.log(logfile, "\n       Residual flux = %.2f e-/s" % FLUXres, True)
        kepmsg.log(logfile, "Pearson's chi^2 test = %d for %d dof" % (Pearson, DegOfFreedom), True)
    except:
        pass
    kepmsg.log(logfile, "          Chi^2 test = %d for %d dof" % (Chi2, DegOfFreedom), True)

    # image scale and intensity limits for plotting images
    imgdat_pl, zminfl, zmaxfl = kepplot.intScale2D(DATimg, imscale)
    imgprf_pl, zminpr, zmaxpr = kepplot.intScale2D(PRFmod, imscale)
    imgfit_pl, zminfi, zmaxfi = kepplot.intScale2D(PRFfit, imscale)
    imgres_pl, zminre, zmaxre = kepplot.intScale2D(PRFres, "linear")
    if imscale == "linear":
        zmaxpr *= 0.9
    elif imscale == "logarithmic":
        zmaxpr = np.max(zmaxpr)
        zminpr = zmaxpr / 2

    # plot
    pl.figure(figsize=[12, 10])
    pl.clf()

    # data
    plotimage(imgdat_pl, zminfl, zmaxfl, 1, row, column, xdim, ydim, 0.07, 0.58, "observation", cmap, lcolor)
    pl.text(
        0.05,
        0.05,
        "CROWDSAP: %.4f" % CrowdTPF,
        horizontalalignment="left",
        verticalalignment="center",
        fontsize=18,
        fontweight=500,
        color=lcolor,
        transform=pl.gca().transAxes,
    )
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, "--", 0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, "-", 3.0)

    # model
    plotimage(imgprf_pl, zminpr, zmaxpr, 2, row, column, xdim, ydim, 0.445, 0.58, "model", cmap, lcolor)
    pl.text(
        0.05,
        0.05,
        "Crowding: %.4f" % CrowdAper,
        horizontalalignment="left",
        verticalalignment="center",
        fontsize=18,
        fontweight=500,
        color=lcolor,
        transform=pl.gca().transAxes,
    )
    for x, y in zip(OBJx, OBJy):
        pl.scatter(x, y, marker="x", color="w")
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, "--", 0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, "-", 3.0)

    if srcinfo is not None:
        kepid, sx, sy, kepmag = srcinfo
        for i in range(len(sx) - 1, -1, -1):
            if kepid[i] != 0 and kepmag[i] != 0.0:
                size = max(np.array([80.0, 80.0 + (2.5 ** (18.0 - max(12.0, float(kepmag[i])))) * 250.0]))
                pl.scatter(sx[i], sy[i], s=size, facecolors="g", edgecolors="k", alpha=0.1)
            else:
                pl.scatter(sx[i], sy[i], s=80, facecolors="r", edgecolors="k", alpha=0.1)

    # binned model
    plotimage(imgfit_pl, zminfl, zmaxfl, 3, row, column, xdim, ydim, 0.07, 0.18, "fit", cmap, lcolor, crowd=Crowding)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, "--", 0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, "-", 3.0)

    # residuals
    reslim = max(np.abs(zminre), np.abs(zmaxre))
    plotimage(imgres_pl, -reslim, reslim, 4, row, column, xdim, ydim, 0.445, 0.18, "residual", "coolwarm", lcolor)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 1, acolor, "--", 0.5)
    kepplot.borders(maskimg, xdim, ydim, pixcoord1, pixcoord2, 2, acolor, "-", 3.0)

    # plot data color bar
    barwin = pl.axes([0.84, 0.18, 0.03, 0.8])
    if imscale == "linear":
        brange = np.arange(zminfl, zmaxfl, (zmaxfl - zminfl) / 1000)
    elif imscale == "logarithmic":
        brange = np.arange(10.0 ** zminfl, 10.0 ** zmaxfl, (10.0 ** zmaxfl - 10.0 ** zminfl) / 1000)
    elif imscale == "squareroot":
        brange = np.arange(zminfl ** 2, zmaxfl ** 2, (zmaxfl ** 2 - zminfl ** 2) / 1000)
    if imscale == "linear":
        barimg = np.resize(brange, (1000, 1))
    elif imscale == "logarithmic":
        barimg = np.log10(np.resize(brange, (1000, 1)))
    elif imscale == "squareroot":
        barimg = np.sqrt(np.resize(brange, (1000, 1)))
    try:
        nrm = len(str(int(np.nanmax(brange)))) - 1
    except:
        nrm = 0
    brange = brange / 10 ** nrm
    pl.imshow(
        barimg,
        aspect="auto",
        interpolation="nearest",
        origin="lower",
        vmin=np.nanmin(barimg),
        vmax=np.nanmax(barimg),
        extent=(0.0, 1.0, brange[0], brange[-1]),
        cmap=cmap,
    )
    barwin.yaxis.tick_right()
    barwin.yaxis.set_label_position("right")
    barwin.yaxis.set_major_locator(MaxNLocator(7))
    pl.gca().yaxis.set_major_formatter(pl.ScalarFormatter(useOffset=False))
    pl.gca().set_autoscale_on(False)
    pl.setp(pl.gca(), xticklabels=[], xticks=[])
    pl.ylabel("Flux (10$^%d$ e$^-$ s$^{-1}$)" % nrm)
    pl.setp(barwin.get_yticklabels(), "rotation", 90)
    barwin.yaxis.set_major_formatter(FormatStrFormatter("%.1f"))

    # plot residual color bar
    barwin = pl.axes([0.07, 0.08, 0.75, 0.03])
    brange = np.arange(-reslim, reslim, reslim / 500)
    barimg = np.resize(brange, (1, 1000))
    pl.imshow(
        barimg,
        aspect="auto",
        interpolation="nearest",
        origin="lower",
        vmin=np.nanmin(barimg),
        vmax=np.nanmax(barimg),
        extent=(brange[0], brange[-1], 0.0, 1.0),
        cmap="coolwarm",
    )
    barwin.xaxis.set_major_locator(MaxNLocator(7))
    pl.gca().xaxis.set_major_formatter(pl.ScalarFormatter(useOffset=False))
    pl.gca().set_autoscale_on(False)
    pl.setp(pl.gca(), yticklabels=[], yticks=[])
    pl.xlabel("Residuals (e$^-$ s$^{-1}$)")
    barwin.xaxis.set_major_formatter(FormatStrFormatter("%.1f"))

    # render plot
    pl.show(block=True)
    pl.close()

    # stop time
    kepmsg.clock("\nKEPPRF ended at", logfile, True)

    return Crowding