Пример #1
0
def do_photometry(params,
                  extname='newflux',
                  star_file='star_positions',
                  psf_file='psf.fits',
                  star_positions=None,
                  reference_image='ref.fits'):

    #
    # Determine our list of files
    #
    all_files = os.listdir(params.loc_data)
    all_files.sort()
    files = []
    for f in all_files:
        if fnmatch.fnmatch(f, params.name_pattern):
            g = DS.Observation(params.loc_data + os.path.sep + f, params)
            if g.fw > 0.0:
                files.append(g)

    ref = DS.Observation(params.loc_output + os.path.sep + reference_image,
                         params)
    ref.register(ref, params)

    #
    # Detect stars and compute the PSF if necessary
    #

    psf_file = params.loc_output + os.path.sep + psf_file
    star_file = params.loc_output + os.path.sep + star_file

    print psf_file
    print os.path.exists(psf_file)
    print star_file
    print os.path.exists(star_file)

    if not (os.path.exists(psf_file)) or not (os.path.exists(star_file)):
        stars = PH.compute_psf_image(params, ref, psf_image=psf_file)

    if star_positions is None:

        if os.path.exists(star_file):
            star_positions = np.genfromtxt(star_file)[:, :2]
        else:
            star_positions = stars[:, 0:2]

    #
    # Group the stars by location
    #
    star_group_boundaries = None
    detector_mean_positions_x = None
    detector_mean_positions_y = None
    star_sort_index,star_group_boundaries,detector_mean_positions_x,detector_mean_positions_y = \
       PH.group_stars_ccd(params,star_positions,params.loc_output+os.path.sep+reference_image)
    star_positions = star_positions[star_sort_index]
    star_unsort_index = np.argsort(star_sort_index)

    #
    # Process the reference image
    #
    print 'Processing', reference_image
    ref = DS.Observation(params.loc_output + os.path.sep + reference_image,
                         params)
    #reg = Observation(params.loc_data+os.path.sep+
    #                  params.registration_image,params)
    mask, _ = IO.read_fits_file(params.loc_output + os.path.sep + 'mask_' +
                                reference_image)
    variance, _ = IO.read_fits_file(params.loc_output + os.path.sep + 'var_' +
                                    reference_image)
    ref.mask = mask
    ref.inv_variance = 1.0 / variance + (1 - mask)
    ref.register(ref, params)
    smask = IM.compute_saturated_pixel_mask(ref.image, params)
    ref.inv_variance += (1 - (smask * mask)) * 1.e-12
    ktable = params.loc_output + os.path.sep + 'k_' + os.path.basename(
        reference_image)
    kernelIndex, extendedBasis, c, params = IO.read_kernel_table(
        ktable, params)
    kernelRadius = np.max(kernelIndex[:, 0]) + 1
    if np.sum(extendedBasis) > 0:
        kernelRadius += 1
    print 'kernelIndex', kernelIndex
    print 'extendedBasis', extendedBasis
    print 'coeffs', c
    print 'kernelRadius', kernelRadius
    print 'star_positions', star_positions.shape
    phot_target, _ = IO.read_fits_file(params.loc_output + os.path.sep +
                                       'clean_' + reference_image)
    ref.flux, ref.dflux = CIF.photom_all_stars_simultaneous(
        phot_target, ref.inv_variance, star_positions, psf_file, c,
        kernelIndex, extendedBasis, kernelRadius, params,
        star_group_boundaries, detector_mean_positions_x,
        detector_mean_positions_y)

    if isinstance(ref.flux, np.ndarray):
        if not (params.use_GPU):
            print 'ungrouping fluxes'
            ref.flux = ref.flux[star_unsort_index].copy()
            ref.dflux = ref.dflux[star_unsort_index].copy()
            print ref.flux.shape, star_positions.shape
        np.savetxt(
            params.loc_output + os.path.sep + reference_image + '.' + extname,
            np.vstack((ref.flux, ref.dflux)))

    #
    # Process difference images
    #
    for f in files:

        if not (os.path.exists(params.loc_output + os.path.sep + f.name + '.' +
                               extname)):

            print 'Processing', f.name
            target = f.name
            dtarget = params.loc_output + os.path.sep + 'd_' + os.path.basename(
                target)
            ntarget = params.loc_output + os.path.sep + 'n_' + os.path.basename(
                target)
            ztarget = params.loc_output + os.path.sep + 'z_' + os.path.basename(
                target)
            ktable = params.loc_output + os.path.sep + 'k_' + os.path.basename(
                target)

            if os.path.exists(dtarget) and os.path.exists(
                    ntarget) and os.path.exists(ktable):

                norm, h = IO.read_fits_file(ntarget)
                diff, h = IO.read_fits_file(dtarget)
                mask, h = IO.read_fits_file(ztarget)
                inv_var = (norm / diff)**2 + (1 - mask)

                kernelIndex, extendedBasis, c, params = IO.read_kernel_table(
                    ktable, params)
                kernelRadius = np.max(kernelIndex[:, 0]) + 1
                if np.sum(extendedBasis) > 0:
                    kernelRadius += 1

                print 'kernelIndex', kernelIndex
                print 'extendedBasis', extendedBasis
                print 'coeffs', c
                print 'kernelRadius', kernelRadius

                IO.write_image(diff,
                               params.loc_output + os.path.sep + 'diff1.fits')
                diff = IM.undo_photometric_scale(diff, c, params.pdeg)
                IO.write_image(diff,
                               params.loc_output + os.path.sep + 'diff2.fits')
                IO.write_image(
                    inv_var, params.loc_output + os.path.sep + 'inv_var.fits')
                IO.write_kernel_table(
                    params.loc_output + os.path.sep + 'ktable.fits',
                    kernelIndex, extendedBasis, c, params)

                flux, dflux = CI.photom_all_stars(
                    diff, inv_var, star_positions, psf_file, c, kernelIndex,
                    extendedBasis, kernelRadius, params, star_group_boundaries,
                    detector_mean_positions_x, detector_mean_positions_y)

                print 'flux[100:110]:'
                print flux[100:110]
                if isinstance(flux, np.ndarray):
                    if not (params.use_GPU):
                        print 'ungrouping fluxes'
                        flux = flux[star_unsort_index].copy()
                        dflux = dflux[star_unsort_index].copy()
                        print 'unsort flux[100:110]:'
                        print flux[100:110]
                    np.savetxt(
                        params.loc_output + os.path.sep + f.name + '.' +
                        extname,
                        np.vstack((flux, dflux)).T)

                sys.exit(0)
Пример #2
0
def do_photometry(params,
                  extname='newflux',
                  star_file='star_positions',
                  psf_file='psf.fits',
                  star_positions=None,
                  reference_image='ref.fits'):
    #
    # Determine our list of files
    #
    all_files = os.listdir(params.loc_data)
    all_files.sort()
    files = []
    for f in all_files:
        if fnmatch.fnmatch(f, params.name_pattern):
            g = DS.Observation(params.loc_data + os.path.sep + f, params)
            if g.fw > 0.0:
                files.append(g)

    ref = DS.Observation(params.loc_output + os.path.sep + reference_image,
                         params)
    ref.register(ref, params)

    #
    # Detect stars and compute the PSF if necessary
    #
    if params.do_photometry:
        psf_file = params.loc_output + os.path.sep + psf_file
        if os.path.exists(params.star_file):
            star_pos = np.genfromtxt(params.star_file)[:, 1:3]
            if not (os.path.exists(psf_file)):
                stars = PH.compute_psf_image(params, ref, psf_image=psf_file)
        else:
            if not (os.path.exists(star_file)):
                stars = PH.compute_psf_image(params, ref, psf_image=psf_file)
                star_pos = stars[:, 0:2]
                np.savetxt(star_file, star_pos)
            else:
                star_pos = np.genfromtxt(star_file)
                if not (os.path.exists(psf_file)):
                    stars = PH.compute_psf_image(params,
                                                 ref,
                                                 psf_image=psf_file)

    #
    # Have we been passed an array of star positions?
    #
    if star_positions == None:
        star_positions = star_pos

    #
    # If we are using a CPU, group the stars by location
    #
    star_group_boundaries = None
    detector_mean_positions_x = None
    detector_mean_positions_y = None
    if not (params.use_GPU):
        star_sort_index, star_group_boundaries, detector_mean_positions_x, detector_mean_positions_y = PH.group_stars_ccd(
            params, star_positions,
            params.loc_output + os.path.sep + reference_image)
        star_positions = star_positions[star_sort_index]
        star_unsort_index = np.argsort(star_sort_index)

    #
    # Process the reference image
    #
    print('Processing', reference_image)
    ref = DS.Observation(params.loc_output + os.path.sep + reference_image,
                         params)
    # reg = Observation(params.loc_data+os.path.sep+
    #                  params.registration_image,params)
    ref.register(ref, params)
    smask = IM.compute_saturated_pixel_mask(ref.image, 6, params)
    ref.inv_variance += 1 - smask
    ktable = params.loc_output + os.path.sep + 'k_' + os.path.basename(
        reference_image)
    kernelIndex, extendedBasis, c, params = IO.read_kernel_table(
        ktable, params)
    kernelRadius = np.max(kernelIndex[:, 0]) + 1
    if np.sum(extendedBasis) > 0:
        kernelRadius += 1
    print('kernelIndex', kernelIndex)
    print('extendedBasis', extendedBasis)
    print('coeffs', c)
    print('kernelRadius', kernelRadius)
    phot_target = ref.image
    ref.flux, ref.dflux = CI.photom_all_stars(
        phot_target, ref.inv_variance, star_positions, psf_file, c,
        kernelIndex, extendedBasis, kernelRadius, params,
        star_group_boundaries, detector_mean_positions_x,
        detector_mean_positions_y)

    if isinstance(ref.flux, np.ndarray):
        if not (params.use_GPU):
            print('ungrouping fluxes')
            ref.flux = ref.flux[star_unsort_index].copy()
            ref.dflux = ref.dflux[star_unsort_index].copy()
        np.savetxt(
            params.loc_output + os.path.sep + reference_image + '.' + extname,
            np.vstack((ref.flux, ref.dflux)).T)

    #
    # Process difference images
    #
    for f in files:

        if not (os.path.exists(params.loc_output + os.path.sep + f.name + '.' +
                               extname)):

            print('Processing', f.name)
            target = f.name
            dtarget = params.loc_output + os.path.sep + 'd_' + os.path.basename(
                target)
            ntarget = params.loc_output + os.path.sep + 'n_' + os.path.basename(
                target)
            ztarget = params.loc_output + os.path.sep + 'z_' + os.path.basename(
                target)
            ktable = params.loc_output + os.path.sep + 'k_' + os.path.basename(
                target)

            if os.path.exists(dtarget) and os.path.exists(
                    ntarget) and os.path.exists(ktable):

                norm, h = IO.read_fits_file(ntarget)
                diff, h = IO.read_fits_file(dtarget)
                mask, h = IO.read_fits_file(ztarget)
                inv_var = (norm / diff)**2 + (1 - mask)

                kernelIndex, extendedBasis, c, params = IO.read_kernel_table(
                    ktable, params)
                kernelRadius = np.max(kernelIndex[:, 0]) + 1
                if np.sum(extendedBasis) > 0:
                    kernelRadius += 1

                print('kernelIndex', kernelIndex)
                print('extendedBasis', extendedBasis)
                print('coeffs', c)
                print('kernelRadius', kernelRadius)

                diff = IM.undo_photometric_scale(diff, c, params.pdeg)

                flux, dflux = PH.photom_all_stars(
                    diff, inv_var, star_positions, psf_file, c, kernelIndex,
                    extendedBasis, kernelRadius, params, star_group_boundaries,
                    detector_mean_positions_x, detector_mean_positions_y)

                if isinstance(flux, np.ndarray):
                    if not (params.use_GPU):
                        print('ungrouping fluxes')
                        flux = flux[star_unsort_index].copy()
                        dflux = dflux[star_unsort_index].copy()
                    np.savetxt(
                        params.loc_output + os.path.sep + f.name + '.' +
                        extname,
                        np.vstack((flux, dflux)).T)
Пример #3
0
def photom_variable_star(x0,
                         y0,
                         params,
                         patch_half_width=15,
                         converge=True,
                         save_stamps=False,
                         stamp_prefix='mosaic',
                         locate=True,
                         locate_iterations=2,
                         locate_half_width=14,
                         q_sigma_threshold=1.0,
                         locate_date_range=None):

    from astropy.io import fits

    def save_mosaic(stack, nfiles, patch_size, name, diff_std, threshold):
        stamps_per_row = int(np.sqrt(nfiles))
        nrows = (nfiles - 1) / stamps_per_row + 1
        mx = stamps_per_row * (patch_size + 1) + 1
        my = nrows * (patch_size + 1) + 1
        mosaic = np.ones((my, mx)) * 1000.0
        for i in range(nfiles):
            mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
                    (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] \
                    = stack[i,:,:]
            if diff_std[i] > threshold:
                mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
                      (i%stamps_per_row)*(patch_size+1)+1] = -1000.0
                mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
                      (i%stamps_per_row+1)*(patch_size+1)-1] = -1000.0
                mosaic[(i/stamps_per_row)*(patch_size+1)+1, \
                      (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] = -1000.0
                mosaic[(i/stamps_per_row+1)*(patch_size+1)-1, \
                      (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] = -1000.0
        IO.write_image(mosaic, name)

    # Obtain a list of files

    all_files = os.listdir(params.loc_data)
    all_files.sort()
    filenames = []
    nfiles = 0

    print 'Searching in', params.loc_output, 'for', params.name_pattern

    for f in all_files:

        if fnmatch.fnmatch(f, params.name_pattern):

            basename = os.path.basename(f)
            dfile = params.loc_output + os.path.sep + 'd_' + basename
            ktable = params.loc_output + os.path.sep + 'k_' + basename

            if os.path.exists(dfile) and os.path.exists(ktable):

                nfiles += 1
                filenames.append(f)

    # Load the kernel tables
    # Load the difference images into a data cube

    print len(filenames), 'files found'

    dates = np.zeros(nfiles)
    seeing = np.zeros(nfiles)
    roundness = np.zeros(nfiles)
    bgnd = np.zeros(nfiles)
    signal = np.zeros(nfiles)
    norm_std = np.zeros(nfiles, dtype=np.float64)
    diff_std = np.zeros(nfiles, dtype=np.float64)
    n_kernel = np.zeros(nfiles, dtype=np.int32)
    n_coeffs = np.zeros(nfiles, dtype=np.int32)
    kindex_x = np.arange(0, dtype=np.int32)
    kindex_y = np.arange(0, dtype=np.int32)
    kindex_ext = np.arange(0, dtype=np.int32)
    coeffs = np.arange(0, dtype=np.float64)

    filenames.sort()

    if not converge:
        locate_iterations = 1

    threshold = -10
    for iteration in range(np.max([1, locate_iterations])):

        ix0 = np.int32(x0 + 0.5)
        iy0 = np.int32(y0 + 0.5)

        x_patch = x0 - ix0 + patch_half_width
        y_patch = y0 - iy0 + patch_half_width

        patch_size = 2 * patch_half_width + 1
        patch_slice = (ix0 - patch_half_width, ix0 + patch_half_width + 1,
                       iy0 - patch_half_width, iy0 + patch_half_width + 1)

        d_image_stack = np.zeros((nfiles, patch_size, patch_size),
                                 dtype=np.float64)
        inv_var_image_stack = np.zeros((nfiles, patch_size, patch_size),
                                       dtype=np.float64)

        for i, f in enumerate(filenames):

            basename = os.path.basename(f)
            ktable = params.loc_output + os.path.sep + 'k_' + basename
            kernelIndex, extendedBasis, c, params = IO.read_kernel_table(
                ktable, params)
            coeffs = np.hstack((coeffs, c))
            kindex_x = np.hstack((kindex_x, kernelIndex[:, 0].T))
            kindex_y = np.hstack((kindex_y, kernelIndex[:, 1].T))
            kindex_ext = np.hstack((kindex_ext, extendedBasis))
            n_kernel[i] = kernelIndex.shape[0]
            n_coeffs[i] = c.shape[0]
            dates[i] = IO.get_date(params.loc_data + os.path.sep + basename,
                                   key=params.datekey) - 2450000
            seeing[i], roundness[i], bgnd[i], signal[i] = IM.compute_fwhm(
                f, params, width=20, image_name=True)

            dfile = params.loc_output + os.path.sep + 'd_' + basename
            nfile = params.loc_output + os.path.sep + 'n_' + basename
            zfile = params.loc_output + os.path.sep + 'z_' + basename
            diff, _ = IO.read_fits_file(dfile)
            mask, _ = IO.read_fits_file(zfile)
            diff_sc = IM.undo_photometric_scale(diff, c, params.pdeg)
            diff_sc *= mask
            d_image_stack[i, :, :] = diff_sc[patch_slice[2]:patch_slice[3],
                                             patch_slice[0]:patch_slice[1]]
            norm, _ = IO.read_fits_file(nfile, slice=patch_slice)
            inv_var_image_stack[i, :, :] = (norm / d_image_stack[i, :, :])**2
            diff_std[i] = np.std(diff)
            d_image_stack[i, :, :] -= np.median(d_image_stack[i, :, :])

        if save_stamps:
            save_mosaic(
                d_image_stack, nfiles, patch_size,
                params.loc_output + os.path.sep + stamp_prefix + '.fits',
                diff_std, threshold)

        print 'kappa-clipping'
        qd1 = np.arange(len(filenames))
        #qd = np.where(diff_std[qd1]<10)
        #qd1 = qd1[qd]
        for iter in range(10):
            qd = np.where(diff_std[qd1] < np.mean(diff_std[qd1]) +
                          (4.0 - 1.5 * (iter / 9.0)) * np.std(diff_std[qd1]))
            qd1 = qd1[qd]
            print iter, np.mean(diff_std[qd1]), np.std(diff_std[qd1]), np.mean(
                diff_std[qd1]) + (4.0 - 3 *
                                  (iter / 9.0)) * np.std(diff_std[qd1])

        print 'mean(diff) :', np.mean(diff_std[qd1])
        print 'std(diff) :', np.std(diff_std[qd1])
        print '1-sig threshold:', np.mean(
            diff_std[qd1]) + 1 * np.std(diff_std[qd1])
        print '2-sig threshold:', np.mean(
            diff_std[qd1]) + 2 * np.std(diff_std[qd1])
        print '3-sig threshold:', np.mean(
            diff_std[qd1]) + 3 * np.std(diff_std[qd1])

        print '1-sig diff reject:', np.where(
            diff_std > np.mean(diff_std[qd1]) + 1 * np.std(diff_std[qd1]))
        print '2-sig diff reject:', np.where(
            diff_std > np.mean(diff_std[qd1]) + 2 * np.std(diff_std[qd1]))
        print '3-sig diff reject:', np.where(
            diff_std > np.mean(diff_std[qd1]) + 3 * np.std(diff_std[qd1]))

        threshold = np.mean(
            diff_std[qd1]) + q_sigma_threshold * np.std(diff_std[qd1])
        threshold2 = np.mean(diff_std[qd1]) + 2 * np.std(diff_std[qd1])
        threshold3 = np.mean(diff_std[qd1]) + 3 * np.std(diff_std[qd1])

        if locate_date_range is not None:
            diff_std_copy = diff_std.copy()
            diff_std = diff_std * 0.0 + 2 * threshold
            pp = np.where((dates > locate_date_range[0])
                          & (dates < locate_date_range[1]))[0]
            if pp.any():
                diff_std[pp] = diff_std_copy[pp]
            else:
                print 'Error: No images found in date range', locate_date_range
                print 'Reverting to all dates.'
                diff_std = diff_std_copy

        dsum = np.zeros((patch_size, patch_size), dtype=np.float64)
        for i in range(nfiles):
            if diff_std[i] < threshold3:
                dsum += d_image_stack[i, :, :]
        IO.write_image(
            dsum, params.loc_output + os.path.sep + 'dsum%d.fits' % iteration)
        dr = patch_half_width - int(locate_half_width)
        dsum[:dr, :] = 0.0
        dsum[-dr:, :] = 0.0
        dsum[:, :dr] = 0.0
        dsum[:, -dr:] = 0.0
        ind_dsum_max = np.unravel_index(dsum.argmax(), dsum.shape)
        print 'Iteration', iteration, ': dsum maximum located at ', ind_dsum_max

        if locate and converge:
            y0 += ind_dsum_max[0] - patch_half_width
            x0 += ind_dsum_max[1] - patch_half_width

    # Read the PSF

    psf_image = params.loc_output + os.path.sep + 'psf.fits'
    psf, psf_hdr = fits.getdata(psf_image, 0, header='true')
    psf_height = psf_hdr['PSFHEIGH']
    psf_sigma_x = psf_hdr['PAR1'] * 0.8493218
    psf_sigma_y = psf_hdr['PAR2'] * 0.8493218
    psf_x = psf_hdr['PSFX']
    psf_y = psf_hdr['PSFY']
    psf_size = psf.shape[1]
    psf_fit_rad = params.psf_fit_radius
    psf_parameters = np.array([
        psf_size, psf_height, psf_sigma_x, psf_sigma_y, psf_x, psf_y,
        psf_fit_rad, params.gain
    ]).astype(np.float64)

    if params.psf_profile_type == 'gaussian':
        psf_sigma_x = psf_hdr['PAR1'] * 0.8493218
        psf_sigma_y = psf_hdr['PAR2'] * 0.8493218
        psf_parameters = np.array([
            psf_size, psf_height, psf_sigma_x, psf_sigma_y, psf_x, psf_y,
            psf_fit_rad, params.gain
        ]).astype(np.float64)
        profile_type = 0
    elif params.psf_profile_type == 'moffat25':
        print 'params.psf_profile_type moffat25 not working yet. Exiting.'
        sys.exit(0)
        psf_sigma_x = psf_hdr['PAR1']
        psf_sigma_y = psf_hdr['PAR2']
        psf_sigma_xy = psf_hdr['PAR3']
        psf_parameters = np.array([
            psf_size, psf_height, psf_sigma_x, psf_sigma_y, psf_x, psf_y,
            psf_fit_rad, params.gain, psf_sigma_xy
        ]).astype(np.float64)
        profile_type = 1
    else:
        print 'params.psf_profile_type undefined'
        sys.exit(0)

    psf_0 = psf.astype(np.float64).copy()
    psf_xd = psf.astype(np.float64).copy() * 0.0
    psf_yd = psf.astype(np.float64).copy() * 0.0
    flux = np.zeros(nfiles, dtype=np.float64)
    dflux = np.zeros(nfiles, dtype=np.float64)

    x0_arr = np.atleast_1d(np.array([x0], dtype=np.float64))
    y0_arr = np.atleast_1d(np.array([y0], dtype=np.float64))

    cu_photom_converge(
        profile_type, patch_half_width, params.pdeg, params.sdeg, nfiles,
        n_kernel, kindex_x, kindex_y, kindex_ext, n_coeffs,
        coeffs.astype(np.float64), psf_parameters, psf_0, psf_xd, psf_yd,
        np.float64(d_image_stack.ravel()), inv_var_image_stack, diff_std,
        np.float64(threshold), x0_arr, y0_arr, x_patch, y_patch, diff.shape[1],
        diff.shape[0], 16, 16, flux, dflux, np.float64(params.gain),
        np.int32(converge), np.float64(2.5))

    if save_stamps:
        save_mosaic(
            d_image_stack, nfiles, patch_size,
            params.loc_output + os.path.sep + 'p' + stamp_prefix + '.fits',
            diff_std, threshold)

    if locate_date_range is not None:
        diff_std = diff_std_copy

    return dates, seeing, roundness, bgnd, signal, flux, dflux, diff_std / threshold, x0_arr[
        0], y0_arr[0]
Пример #4
0
def photom_variable_star(x0,y0,params,patch_half_width=15,converge=True,save_stamps=False,stamp_prefix='mosaic',locate=True,locate_iterations=2,
						  locate_half_width=14,q_sigma_threshold=1.0,locate_date_range=None):

	from astropy.io import fits
	from scipy.ndimage.filters import median_filter

	outer_radius = 15
	inner_radius = 12
	diameter = 2*outer_radius + 1
	x = np.arange(diameter)-outer_radius
	xx,yy = np.meshgrid(x,x)
	filter_kernel = np.zeros((diameter,diameter))
	filter_kernel[xx**2+yy**2<=outer_radius**2] = 1
	filter_kernel[xx**2+yy**2<=inner_radius**2] = 0


	def save_mosaic(stack,nfiles,patch_size,name,diff_std,threshold):
		stamps_per_row = int(np.sqrt(nfiles))
		nrows = (nfiles-1)/stamps_per_row+1;
		mx = stamps_per_row*(patch_size+1)+1
		my = nrows*(patch_size+1)+1
		mosaic = np.ones((my,mx))*1000.0
		for i in range(nfiles):
		  mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
				  (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] \
				  = stack[i,:,:]
		  if diff_std[i] > threshold:
			mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
				  (i%stamps_per_row)*(patch_size+1)+1] = -1000.0
			mosaic[(i/stamps_per_row)*(patch_size+1)+1:(i/stamps_per_row+1)*(patch_size+1), \
				  (i%stamps_per_row+1)*(patch_size+1)-1] = -1000.0
			mosaic[(i/stamps_per_row)*(patch_size+1)+1, \
				  (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] = -1000.0                  
			mosaic[(i/stamps_per_row+1)*(patch_size+1)-1, \
				  (i%stamps_per_row)*(patch_size+1)+1:(i%stamps_per_row+1)*(patch_size+1)] = -1000.0                  
		IO.write_image(mosaic,name)

	# Obtain a list of files

	all_files = os.listdir(params.loc_data)
	all_files.sort()
	filenames = []
	nfiles = 0

	print 'Searching in', params.loc_output, 'for', params.name_pattern

	for f in all_files:

		if fnmatch.fnmatch(f,params.name_pattern):

			basename = os.path.basename(f)
			dfile = params.loc_output+os.path.sep+'d_'+basename
			ktable = params.loc_output+os.path.sep+'k_'+basename

			if os.path.exists(dfile) and os.path.exists(ktable):

				nfiles += 1
				filenames.append(f)

	# Load the kernel tables
	# Load the difference images into a data cube

	print len(filenames), 'files found'


	dates = np.zeros(nfiles)
	seeing = np.zeros(nfiles)
	roundness = np.zeros(nfiles)
	bgnd = np.zeros(nfiles)
	signal = np.zeros(nfiles)
	norm_std = np.zeros(nfiles,dtype=np.float64)
	diff_std = np.zeros(nfiles,dtype=np.float64)
	n_kernel = np.zeros(nfiles,dtype=np.int32)
	n_coeffs = np.zeros(nfiles,dtype=np.int32)
	kindex_x = np.arange(0,dtype=np.int32)
	kindex_y = np.arange(0,dtype=np.int32)
	kindex_ext = np.arange(0,dtype=np.int32)
	coeffs = np.arange(0,dtype=np.float64)

	filenames.sort()

	if not converge:
	 	locate_iterations = 1

	threshold = -10
	for iteration in range(np.max([1,locate_iterations])):

	 	#ix0 = np.int32(x0+0.5)
	 	#iy0 = np.int32(y0+0.5)
		ix0 = np.int32(x0)
		iy0 = np.int32(y0)

		x_patch = x0 - ix0 + patch_half_width
		y_patch = y0 - iy0 + patch_half_width

		patch_size = 2*patch_half_width+1
		patch_slice = np.array([ix0-patch_half_width, ix0+patch_half_width+1, iy0-patch_half_width, iy0+patch_half_width+1])
		print 'patch_slice:', patch_slice

		# check that patch doesn't overlap the edge of the image
		f = filenames[0]
		diff, _ = IO.read_fits_file(params.loc_output+os.path.sep+'d_'+os.path.basename(f))
		nx = diff.shape[1]
		ny = diff.shape[0]
		delta_patch_x = 0
		delta_patch_y = 0
		if patch_slice[0] < 0:
			delta_patch_x = -patch_slice[0]
		elif patch_slice[1] >= nx:
			delta_patch_x = nx - patch_slice[1] - 1
		if patch_slice[2] < 0:
			delta_patch_y = -patch_slice[2]
		elif patch_slice[3] >= ny:
			delta_patch_y = ny - patch_slice[3] - 1

		print 'delta_patch_x, delta_patch_y:', delta_patch_x, delta_patch_y

		patch_slice += np.array([delta_patch_x,delta_patch_x,delta_patch_y,delta_patch_y])
		print 'patch_slice:', patch_slice

		x_patch -= delta_patch_x
		y_patch -= delta_patch_y

		d_image_stack = np.zeros((nfiles,patch_size,patch_size),dtype=np.float64)
		inv_var_image_stack = np.zeros((nfiles,patch_size,patch_size),dtype=np.float64)

		dmask = np.ones([patch_size,patch_size],dtype=np.bool)
		dmask_rad = 8.0
		dmix = np.linspace(-patch_half_width,patch_half_width,patch_size) - delta_patch_x
		dmiy = np.linspace(-patch_half_width,patch_half_width,patch_size) - delta_patch_y
		dmx, dmy = np.meshgrid(dmix,dmiy,indexing='ij')
		dmask[dmx**2 + dmy**2 < dmask_rad**2] = False

		for i, f in enumerate(filenames):

			basename = os.path.basename(f)
			ktable = params.loc_output+os.path.sep+'k_'+basename
			kernelIndex, extendedBasis, c, params = IO.read_kernel_table(ktable,params)
			coeffs = np.hstack((coeffs,c))
			kindex_x = np.hstack((kindex_x,kernelIndex[:,0].T))
			kindex_y = np.hstack((kindex_y,kernelIndex[:,1].T))
			kindex_ext = np.hstack((kindex_ext,extendedBasis))
			n_kernel[i] = kernelIndex.shape[0]
			n_coeffs[i] = c.shape[0]
			dates[i] = IO.get_date(params.loc_data+os.path.sep+basename,key=params.datekey)
			if dates[i] > 2450000:
				dates[i] -= 2450000
			seeing[i], roundness[i], bgnd[i], signal[i] = IM.compute_fwhm(f,params,width=20,image_name=True)

			dfile = params.loc_output+os.path.sep+'d_'+basename
			nfile = params.loc_output+os.path.sep+'n_'+basename
			zfile = params.loc_output+os.path.sep+'sm_'+basename
			ivfile = params.loc_output+os.path.sep+'iv_'+basename
			diff, _ = IO.read_fits_file(dfile)
			mask, _ = IO.read_fits_file(zfile)
			iv, _ = IO.read_fits_file(ivfile)
			diff_sc = IM.undo_photometric_scale(diff,c,params.pdeg)
			#diff_sc = diff
			#diff_sc -= median_filter(diff_sc,footprint=filter_kernel)
			diff_sc *= mask
			d_image_stack[i,:,:] = diff_sc[patch_slice[2]:patch_slice[3],patch_slice[0]:patch_slice[1]]
			inv_var_image_stack[i,:,:], _ = IO.read_fits_file(ivfile,slice=patch_slice)
			#inv_var_image_stack[i,:,:] = (norm / d_image_stack[i,:,:])**2
			#diff_std[i] = np.std(diff)
			diff_std[i] = np.std(d_image_stack[i,:,:][dmask])
			d_image_stack[i,:,:] -= np.median(d_image_stack[i,:,:])

		print 'kappa-clipping'
		qd = np.arange(len(filenames))
		qd1 = np.where(np.isfinite(diff_std))[0]
		for iter in range(10):
			qd = np.where(diff_std[qd1]<np.mean(diff_std[qd1])+(4.0-1.5*(iter/9.0))*np.std(diff_std[qd1]))[0]
			qd1 = qd1[qd]
			print iter, np.mean(diff_std[qd1]), np.std(diff_std[qd1]), np.mean(diff_std[qd1])+(4.0-3*(iter/9.0))*np.std(diff_std[qd1])

		print 'mean(diff) :',np.mean(diff_std[qd1])
		print 'std(diff) :',np.std(diff_std[qd1])
		print '1-sig threshold:', np.mean(diff_std[qd1])+1*np.std(diff_std[qd1])
		print '2-sig threshold:', np.mean(diff_std[qd1])+2*np.std(diff_std[qd1])
		print '3-sig threshold:', np.mean(diff_std[qd1])+3*np.std(diff_std[qd1])

		print '1-sig diff reject:',np.where(diff_std>np.mean(diff_std[qd1])+1*np.std(diff_std[qd1]))
		print '2-sig diff reject:',np.where(diff_std>np.mean(diff_std[qd1])+2*np.std(diff_std[qd1]))
		print '3-sig diff reject:',np.where(diff_std>np.mean(diff_std[qd1])+3*np.std(diff_std[qd1]))

		threshold = np.mean(diff_std[qd1])+q_sigma_threshold*np.std(diff_std[qd1])
		threshold2 = np.mean(diff_std[qd1])+2*np.std(diff_std[qd1])
		threshold3 = np.mean(diff_std[qd1])+3*np.std(diff_std[qd1])

		if locate_date_range is not None:
			diff_std_copy = diff_std.copy()
			diff_std = diff_std*0.0 + 100.0*threshold
			pp = np.where((dates>locate_date_range[0]) & (dates<locate_date_range[1]))[0]
			if pp.any():
				print 'Using images ',pp
				diff_std[pp] = diff_std_copy[pp]
			else:
				print 'Error: No images found in date range',locate_date_range
				print 'Reverting to all dates.'
				diff_std = diff_std_copy

		print 'zeros:'
		for i in range(nfiles):
			print i, np.sum(np.abs(d_image_stack[i,:,:]) < 1.e-6)
			if np.isnan(inv_var_image_stack[i,:,:]).any() or np.sum(np.abs(d_image_stack[i,:,:]) < 1.e-6) > 5:
				diff_std[i] = 100.0*threshold
				inv_var_image_stack[i,:,:] = inv_var_image_stack[i,:,:]*0.0


		if save_stamps:
			save_mosaic(d_image_stack,nfiles,patch_size,params.loc_output+os.path.sep+stamp_prefix+'.fits',diff_std,threshold)

		dsum = np.zeros((patch_size,patch_size),dtype=np.float64)
		for i in range(nfiles):
			if diff_std[i] < threshold3:
				dsum += d_image_stack[i,:,:]
		IO.write_image(dsum,params.loc_output+os.path.sep+'dsum%d.fits'%iteration)
		dr = patch_half_width-int(locate_half_width)
		print 'dr:', dr
		dsum[:dr-delta_patch_y,:] = 0.0
		dsum[-dr-delta_patch_y:,:] = 0.0
		dsum[:,:dr-delta_patch_x] = 0.0
		dsum[:,-dr-delta_patch_x:] = 0.0
		IO.write_image(dsum,params.loc_output+os.path.sep+'dsum_m%d.fits'%iteration)
		ind_dsum_max = np.unravel_index(dsum.argmax(),dsum.shape)
		print 'Iteration',iteration,': dsum maximum located at ',ind_dsum_max

		if locate and converge:
			y0 += ind_dsum_max[0] - patch_half_width + delta_patch_y
			x0 += ind_dsum_max[1] - patch_half_width + delta_patch_x


	# Read the PSF

	psf_image = params.loc_output+os.path.sep+'psf.fits'
	psf,psf_hdr = fits.getdata(psf_image,0,header='true')
	psf_height = psf_hdr['PSFHEIGH']
	psf_sigma_x = psf_hdr['PAR1']*0.8493218
	psf_sigma_y = psf_hdr['PAR2']*0.8493218
	psf_x = psf_hdr['PSFX']
	psf_y = psf_hdr['PSFY']
	psf_size = psf.shape[1]
	psf_fit_rad = params.psf_fit_radius
	psf_parameters = np.array([psf_size,psf_height,psf_sigma_x,psf_sigma_y,psf_x,
							   psf_y,psf_fit_rad,params.gain]).astype(np.float64)

	if params.psf_profile_type == 'gaussian':
		psf_sigma_x = psf_hdr['PAR1']*0.8493218
		psf_sigma_y = psf_hdr['PAR2']*0.8493218
		psf_parameters = np.array([psf_size,psf_height,psf_sigma_x,psf_sigma_y,psf_x,
								   psf_y,psf_fit_rad,params.gain]).astype(np.float64)
		profile_type = 0
	elif params.psf_profile_type == 'moffat25':
		print 'params.psf_profile_type moffat25 not working yet. Exiting.'
		sys.exit(0)
		psf_sigma_x = psf_hdr['PAR1']
		psf_sigma_y = psf_hdr['PAR2']
		psf_sigma_xy = psf_hdr['PAR3']
		psf_parameters = np.array([psf_size,psf_height,psf_sigma_x,psf_sigma_y,psf_x,
								   psf_y,
								   psf_fit_rad,params.gain,psf_sigma_xy]).astype(np.float64)
		profile_type = 1
	else:
		print 'params.psf_profile_type undefined'
		sys.exit(0)

	psf_0 = psf.astype(np.float64).copy()
	psf_xd = psf.astype(np.float64).copy()*0.0
	psf_yd = psf.astype(np.float64).copy()*0.0
	flux = np.zeros(nfiles,dtype=np.float64)
	dflux = np.zeros(nfiles,dtype=np.float64)

	x0_arr = np.atleast_1d(np.array([x0],dtype=np.float64))
	y0_arr = np.atleast_1d(np.array([y0],dtype=np.float64))

	print 'Converging photometry'
	print 'x0, y0:', x0, y0
	print 'x_patch, y_patch:', x_patch, y_patch
	good_images = np.where(diff_std < threshold)[0]
	print 'using images', good_images
	print 'threshold', threshold
	for i, f in enumerate(filenames):
		if i in good_images:
			print i, 'd_'+f, diff_std[i] 

	cu_photom_converge(profile_type, patch_half_width, params.pdeg, params.sdeg, nfiles, 
						n_kernel, kindex_x, kindex_y, kindex_ext, n_coeffs, coeffs.astype(np.float64),
						psf_parameters, psf_0, psf_xd, psf_yd,
						np.float64(d_image_stack.ravel()), np.float64(inv_var_image_stack.ravel()), diff_std, np.float64(threshold),
						x0_arr, y0_arr, x_patch, y_patch, diff.shape[1], diff.shape[0], 16, 16, flux, dflux, 
						np.float64(params.gain),np.int32(converge),np.float64(2.5))

	if save_stamps:
		save_mosaic(d_image_stack,nfiles,patch_size,params.loc_output+os.path.sep+'p'+stamp_prefix+'.fits',diff_std,threshold)

	if locate_date_range is not None:
	  diff_std = diff_std_copy

	return dates, seeing, roundness, bgnd, signal, flux, dflux, diff_std/threshold, x0_arr[0], y0_arr[0]