Example #1
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
Example #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
Example #3
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
Example #4
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
Example #5
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
Example #6
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
Example #7
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
Example #8
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
Example #9
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