예제 #1
0
def match_kdtree_catalog(wcs, catfn):
    from astrometry.libkd.spherematch import (
        tree_open,
        tree_close,
        tree_build_radec,
        tree_free,
        trees_match,
        tree_permute,
    )
    from astrometry.libkd import spherematch_c
    from astrometry.util.starutil_numpy import deg2dist, xyztoradec
    import numpy as np
    import sys

    rc, dc = wcs.get_center()
    rr = wcs.get_radius()
    kd = tree_open(catfn)
    kd2 = tree_build_radec(np.array([rc]), np.array([dc]))
    r = deg2dist(rr)
    I, J, nil = trees_match(kd, kd2, r, permuted=False)
    # HACK
    # I2,J,d = trees_match(kd, kd2, r)
    xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32))
    # print 'I', I
    I2 = tree_permute(kd, I)
    # print 'I2', I2
    tree_free(kd2)
    tree_close(kd)
    tra, tdec = xyztoradec(xyz)
    return tra, tdec, I2
예제 #2
0
    def __call__(self, ra, dec, spherematch=True, radius=0, contains=False):
        T = self.tab
        # HACK - magic 13x9 +1 arcmin.
        if radius == 0:
            radius = sqrt(14.**2 + 10.**2)/2.
        d2 = arcmin2distsq(radius)
        if self.sdssxyz is None:
            self.sdssxyz = radectoxyz(T.ra, T.dec)
        if not spherematch:
            rcfs = []
            for r,d in broadcast(ra,dec):
                xyz = radectoxyz(r,d)
                dist2s = sum((xyz - self.sdssxyz)**2, axis=1)
                I = flatnonzero(dist2s < d2)
                rcfs.append(zip(T[I].run, T[I].camcol,
                                T[I].field, T[I].ra, T[I].dec))
        else:
            from astrometry.libkd import spherematch
            if self.kd is None:
                self.kd = spherematch.tree_build(self.sdssxyz)
            rds = array([x for x in broadcast(ra,dec)])
            xyz = radectoxyz(rds[:,0], rds[:,1]).astype(double)
            kd2 = spherematch.tree_build(xyz)
            notself = False
            inds,D = spherematch.trees_match(self.kd, kd2, np.sqrt(d2),
                                             notself=notself, permuted=True)
            if len(inds) == 0:
                return []
            I = np.argsort(D[:,0])
            inds = inds[I]
            rcfs = [[] for i in range(len(rds))]
            cols = T.columns()
            gotem = False
            if contains:
                if ('ramin' in cols and 'ramax' in cols and
                    'decmin' in cols and 'decmax' in cols):
                    gotem = True
                    for j,i in inds:
                        (r,d) = rds[i]
                        if (r >= T.ramin[j] and r <= T.ramax[j]
                            and d >= T.decmin[j] and d <= T.decmax[j]):
                            rcfs[i].append((T.run[j], T.camcol[j],
                                            T.field[j], T.ra[j], T.dec[j]))
                        #print '%i fields contain the first query RA,Dec' % len(rcfs[0])
                else:
                    print('you requested fields *containing* the query RA,Dec,')
                    print('but the fields list file \"%s\" doesn\'t contain RAMIN,RAMAX,DECMIN, and DECMAX columns' % tablefn)
            if not gotem:
                for j,i in inds:
                    rcfs[i].append((T.run[j], T.camcol[j], T.field[j],
                                    T.ra[j], T.dec[j]))

        if isscalar(ra) and isscalar(dec):
            return rcfs[0]
        return rcfs
예제 #3
0
def _match_tile(X):
    tid, tile_ra, tile_dec, tile_obstime, tile_theta, tile_obsha, match_radius = X

    loc_ra, loc_dec = xy2radec(hw, tile_ra, tile_dec, tile_obstime, tile_theta,
                               tile_obsha, stuck_x, stuck_y, False, 0)
    kd = tree_build_radec(loc_ra, loc_dec)
    I, J, d = trees_match(starkd, kd, match_radius)
    print('Tile', tid, 'matched', len(I), 'stars')
    if len(I):
        res = tid, I, loc_ra[J], loc_dec[J], stuck_loc[J], np.rad2deg(
            d) * 3600.
    else:
        res = None
    return res
예제 #4
0
def match_kdtree_catalog(wcs, catfn):
    from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute
    from astrometry.libkd import spherematch_c
    from astrometry.util.starutil_numpy import deg2dist, xyztoradec
    import numpy as np
    import sys

    rc,dc = wcs.get_center()
    rr = wcs.get_radius()
    kd = tree_open(catfn)
    kd2 = tree_build_radec(np.array([rc]), np.array([dc]))
    r = deg2dist(rr)
    I,J,nil = trees_match(kd, kd2, r, permuted=False)
    del kd2
    xyz = kd.get_data(I.astype(np.uint32))
    I = kd.permute(I)
    del kd
    tra,tdec = xyztoradec(xyz)
    return tra, tdec, I
예제 #5
0
def match_kdtree_catalog(wcs, catfn):
    from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute
    from astrometry.libkd import spherematch_c
    from astrometry.util.starutil_numpy import deg2dist, xyztoradec
    import numpy as np
    import sys

    rc,dc = wcs.get_center()
    rr = wcs.get_radius()
    kd = tree_open(catfn)
    kd2 = tree_build_radec(np.array([rc]), np.array([dc]))
    r = deg2dist(rr)
    I,J,nil = trees_match(kd, kd2, r, permuted=False)
    del kd2
    xyz = kd.get_data(I.astype(np.uint32))
    I = kd.permute(I)
    del kd
    tra,tdec = xyztoradec(xyz)
    return tra, tdec, I
예제 #6
0
def match_kdtree_catalog(wcs, catfn):
    from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute
    from astrometry.libkd import spherematch_c
    from astrometry.util.starutil_numpy import deg2dist, xyztoradec
    import numpy as np
    import sys

    rc, dc = wcs.get_center()
    rr = wcs.get_radius()
    kd = tree_open(catfn)
    kd2 = tree_build_radec(np.array([rc]), np.array([dc]))
    r = deg2dist(rr)
    I, J, nil = trees_match(kd, kd2, r, permuted=False)
    # HACK
    #I2,J,d = trees_match(kd, kd2, r)
    xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32))
    #print 'I', I
    I2 = tree_permute(kd, I)
    #print 'I2', I2
    tree_free(kd2)
    tree_close(kd)
    tra, tdec = xyztoradec(xyz)
    return tra, tdec, I2
예제 #7
0
def plot_wcs_outline(wcsfn,
                     plotfn,
                     W=256,
                     H=256,
                     width=36,
                     zoom=True,
                     zoomwidth=3.6,
                     grid=10,
                     hd=False,
                     hd_labels=False,
                     tycho2=False):
    anutil.log_init(3)
    #anutil.log_set_level(3)

    wcs = anutil.Tan(wcsfn, 0)
    ra, dec = wcs.radec_center()

    plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra, dec, width))
    plot.linestep = 1.
    plot.color = 'verydarkblue'
    plot.plot('fill')

    plot.fontsize = 12
    #plot.color = 'gray'
    # dark gray
    plot.rgb = (0.3, 0.3, 0.3)
    if grid is not None:
        plot.plot_grid(*([grid] * 4))

    plot.rgb = (0.4, 0.6, 0.4)
    ann = plot.annotations
    ann.NGC = ann.bright = ann.HD = 0
    ann.constellations = 1
    ann.constellation_labels = 1
    ann.constellation_labels_long = 1
    plot.plot('annotations')
    plot.stroke()
    ann.constellation_labels = 0
    ann.constellation_labels_long = 0
    ann.constellation_lines = 0

    ann.constellation_markers = 1
    plot.markersize = 3
    plot.rgb = (0.4, 0.6, 0.4)
    plot.plot('annotations')
    plot.fill()
    ann.constellation_markers = 0

    ann.bright_labels = False
    ann.bright = True
    plot.markersize = 2
    if zoom >= 2:
        ann.bright_labels = True
    plot.plot('annotations')
    ann.bright = False
    ann.bright_labels = False
    plot.fill()

    if hd:
        ann.HD = True
        ann.HD_labels = hd_labels
        ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT)
        plot.plot('annotations')
        plot.stroke()
        ann.HD = False
        ann.HD_labels = False

    if tycho2 and settings.TYCHO2_KD:
        from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match
        from astrometry.libkd import spherematch_c
        from astrometry.util.starutil_numpy import deg2dist, xyztoradec
        import numpy as np
        import sys
        kd = tree_open(settings.TYCHO2_KD)
        # this is a bit silly: build a tree with a single point, then do match()
        kd2 = tree_build_radec(np.array([ra]), np.array([dec]))
        r = deg2dist(width * np.sqrt(2.) / 2.)
        #r = deg2dist(wcs.radius())
        I, nil, nil = trees_match(kd, kd2, r, permuted=False)
        del nil
        #print 'Matched', len(I)
        xyz = spherematch_c.kdtree_get_positions(kd, I)
        del I
        tree_free(kd2)
        tree_close(kd)
        #print >>sys.stderr, 'Got', xyz.shape, xyz
        tra, tdec = xyztoradec(xyz)
        #print >>sys.stderr, 'RA,Dec', ra,dec
        plot.apply_settings()
        for r, d in zip(tra, tdec):
            plot.marker_radec(r, d)
        plot.fill()

    ann.NGC = 1
    plot.plot('annotations')
    ann.NGC = 0

    plot.color = 'white'
    plot.lw = 3
    out = plot.outline
    out.wcs_file = wcsfn
    plot.plot('outline')

    if zoom:
        # MAGIC width, height are arbitrary
        zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000, 1000)
        out.wcs = zoomwcs
        plot.lw = 1
        plot.dashed(3)
        plot.plot('outline')

    plot.write(plotfn)
예제 #8
0
def in_footprint(parent, nside=2048, dr='dr9'):
    """Find all galaxies in the DESI footprint.

    """
    import time
    import healpy as hp
    import legacyhalos.misc

    #tiles = SGA.io.read_desi_tiles(verbose=verbose)
    #indesi = SGA.misc.is_point_in_desi(tiles, parent['RA'], parent['DEC']).astype(bool)

    parentpix = legacyhalos.misc.radec2pix(nside, parent['RA'], parent['DEC'])
    #parentpix = np.hstack((parentpix, hp.pixelfunc.get_all_neighbours(nside, parentpix, nest=True).flatten()))

    drdir = os.path.join(sample_dir(), dr)

    bands = ('g', 'r', 'z')
    camera = ('90prime', 'mosaic', 'decam')

    indesi = dict()
    for cam in camera:
        for band in bands:
            indesi.update(
                {'{}_{}'.format(cam, band): np.zeros(len(parent), dtype=bool)})

    #indesi = np.zeros(len(parent), dtype=bool)
    t0 = time.time()
    for cam, radius in zip(camera, (0.44, 0.21, 0.17)):
        if False:
            from astrometry.libkd.spherematch import trees_match, tree_open
            kdccds = tree_open(
                os.path.join(drdir,
                             'survey-ccds-{}-{}.kd.fits'.format(cam, dr)))
            I, J, dd = trees_match(kdparent, kdccds,
                                   np.radians(radius))  #, nearest=True)
        else:
            ccdsfile = os.path.join(
                drdir, 'survey-ccds-{}-{}.kd.fits'.format(cam, dr))
            ccds = fitsio.read(ccdsfile)
            ccds = ccds[ccds['ccd_cuts'] == 0]
            print('Read {} CCDs from {}'.format(len(ccds), ccdsfile))

            for band in bands:
                ww = ccds['filter'] == band
                if np.sum(ww) > 0:
                    # add the neighboring healpixels to protect against edge effects
                    ccdpix = legacyhalos.misc.radec2pix(
                        nside, ccds['ra'][ww], ccds['dec'][ww])
                    ccdpix = np.hstack(
                        (ccdpix,
                         hp.pixelfunc.get_all_neighbours(nside,
                                                         ccdpix,
                                                         nest=True).flatten()))
                    if np.sum(
                            ccdpix == -1
                    ) > 0:  # remove the "no neighbors" healpixel, if it exists
                        ccdpix = np.delete(ccdpix, np.where(ccdpix == -1)[0])
                    I = np.isin(parentpix, ccdpix)
                    indesi['{}_{}'.format(cam, band)][I] = True
                else:
                    I = [False]
                #print('Found {} galaxies in {} {} footprint in {:.1f} sec'.format(np.sum(I), cam, time.time() - t0))
                print('  Found {} galaxies in {} {} footprint.'.format(
                    np.sum(I), cam, band))
    print('Total time to find galaxies in footprint = {:.1f} sec'.format(
        time.time() - t0))

    parent['IN_FOOTPRINT_NORTH'] = indesi['90prime_g'] | indesi[
        '90prime_r'] | indesi['mosaic_z']
    parent['IN_FOOTPRINT_NORTH_GRZ'] = indesi['90prime_g'] & indesi[
        '90prime_r'] & indesi['mosaic_z']

    parent['IN_FOOTPRINT_SOUTH'] = indesi['decam_g'] | indesi[
        'decam_r'] | indesi['decam_z']
    parent['IN_FOOTPRINT_SOUTH_GRZ'] = indesi['decam_g'] & indesi[
        'decam_r'] & indesi['decam_z']

    parent['IN_FOOTPRINT'] = parent['IN_FOOTPRINT_NORTH'] | parent[
        'IN_FOOTPRINT_SOUTH']
    parent['IN_FOOTPRINT_GRZ'] = parent['IN_FOOTPRINT_NORTH_GRZ'] | parent[
        'IN_FOOTPRINT_SOUTH_GRZ']

    #plt.scatter(parent['RA'], parent['DEC'], s=1)
    #plt.scatter(parent['RA'][indesi], parent['DEC'][indesi], s=1)
    #plt.xlim(360, 0)
    #plt.show()

    #bb = parent[parent['IN_FOOTPRINT_NORTH_GRZ'] & parent['IN_FOOTPRINT_SOUTH_GRZ']]
    #plt.scatter(bb['RA'], bb['DEC'], s=1)
    #plt.xlim(300, 90) ; plt.ylim(30, 36)
    #plt.axhline(y=32.375, color='k')
    #plt.xlabel('RA') ; plt.ylabel('Dec')
    #plt.show()

    print(
        '  Identified {}/{} ({:.2f}%) galaxies inside and {}/{} ({:.2f}%) galaxies outside the DESI footprint.'
        .format(np.sum(parent['IN_FOOTPRINT']), len(parent),
                100 * np.sum(parent['IN_FOOTPRINT']) / len(parent),
                np.sum(~parent['IN_FOOTPRINT']), len(parent),
                100 * np.sum(~parent['IN_FOOTPRINT']) / len(parent)))

    return parent
예제 #9
0
				continue
			ann.add_target(T.ra[i], T.dec[i], 'Abell %i' % T.aco[i])

	if opt.t2cat:
		from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match
		from astrometry.libkd import spherematch_c
		from astrometry.util.starutil_numpy import deg2dist, xyztoradec
		import numpy as np
		import sys
		wcs = plot.wcs
		rc,dc = wcs.get_center()
		rr = wcs.get_radius()
		kd = tree_open(opt.t2cat)
		kd2 = tree_build_radec(np.array([rc]), np.array([dc]))
		r = deg2dist(rr)
		I,J,d = trees_match(kd, kd2, r, permuted=False)
		# HACK
		I2,J,d = trees_match(kd, kd2, r)
		xyz = spherematch_c.kdtree_get_positions(kd, I)
		tree_free(kd2)
		tree_close(kd)
		tra,tdec = xyztoradec(xyz)
		T = fits_table(opt.t2cat, hdu=6)
		for r,d,t1,t2,t3 in zip(tra,tdec, T.tyc1[I2], T.tyc2[I2], T.tyc3[I2]):
			if not plot.wcs.is_inside(r, d):
				continue
			ann.add_target(r, d, 'Tycho-2 %i-%i-%i' % (t1,t2,t3))

			
	plot.color = opt.textcolor
	plot.fontsize = opt.textsize
예제 #10
0
t0 = time()
(inds,dists) = spherematch.nearest(x1, x2, r)
dt = time() - t0

t0 = time()
inds = spherematch.match(x1, x2, r, indexlist=True)
dt = time() - t0

kd = spherematch.tree_build(x1)
kd.print()
R = spherematch.tree_search(kd, x2[0,:], 1.)
print('tree_search:', len(R), 'results')
spherematch.tree_close(kd)

kd2 = spherematch.tree_build(x2)
I,J,d = spherematch.trees_match(kd, kd2, 1.)
print('trees_match:', len(I), 'matches')

I,J,d = spherematch.trees_match(kd, kd2, 1., nearest=True)
print('trees_match:', len(I), 'matches (nearest)')

print('Kd bounding-box:', spherematch.tree_bbox(kd))

print('Kd bounding-box:', kd.bbox)

print('Kd data:', spherematch.tree_data(kd, np.array([0,3,5]).astype(np.uint32)))

print('Kd data:', kd.get_data(np.array([0,3,5]).astype(np.uint32)))

print('Permute:', spherematch.tree_permute(kd, np.array([3,5,7]).astype(np.int32)))
예제 #11
0
        ra = np.append(ra, ra[0])
        dec = T.dec[hull.vertices]
        dec = np.append(dec, dec[0])
        hulls.append((ra, dec))

    aligns = {}

    #for i in []:
    for i in range(len(kds)):
        for j in range(i + 1, len(kds)):
            print('Matching trees', i, 'and', j)

            r_arcsec = 0.2
            radius = np.deg2rad(r_arcsec / 3600)

            I, J, d2 = trees_match(kds[i], kds[j], radius)
            print(len(I), 'matches')
            if len(I) == 0:
                continue

            Ti = TT[i]
            Tj = TT[j]
            dec = Ti[I].dec
            cosdec = np.cos(np.deg2rad(dec))
            dr = (Ti[I].ra - Tj[J].ra) * cosdec * 3600.
            dd = (Ti[I].dec - Tj[J].dec) * 3600.

            if False:
                al = Alignment(Ti, Tj, searchradius=r_arcsec)
                print('Aligning...')
                if not al.shift():
예제 #12
0
def plot_wcs_outline(wcsfn, plotfn, W=256, H=256, width=36, zoom=True,
                     zoomwidth=3.6, grid=10, hd=False, hd_labels=False,
                     tycho2=False):
    anutil.log_init(3)
    #anutil.log_set_level(3)

    wcs = anutil.Tan(wcsfn, 0)
    ra,dec = wcs.radec_center()

    plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra,dec,width))
    plot.linestep = 1.
    plot.color = 'verydarkblue'
    plot.plot('fill')

    plot.fontsize = 12
    #plot.color = 'gray'
    # dark gray
    plot.rgb = (0.3,0.3,0.3)
    if grid is not None:
        plot.plot_grid(*([grid]*4))

    plot.rgb = (0.4, 0.6, 0.4)
    ann = plot.annotations
    ann.NGC = ann.bright = ann.HD = 0
    ann.constellations = 1
    ann.constellation_labels = 1
    ann.constellation_labels_long = 1
    plot.plot('annotations')
    plot.stroke()
    ann.constellation_labels = 0
    ann.constellation_labels_long = 0
    ann.constellation_lines = 0

    ann.constellation_markers = 1
    plot.markersize = 3
    plot.rgb = (0.4, 0.6, 0.4)
    plot.plot('annotations')
    plot.fill()
    ann.constellation_markers = 0

    ann.bright_labels = False
    ann.bright = True
    plot.markersize = 2
    if zoom >= 2:
        ann.bright_labels = True
    plot.plot('annotations')
    ann.bright = False
    ann.bright_labels = False
    plot.fill()

    if hd:
        ann.HD = True
        ann.HD_labels = hd_labels
        ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT)
        plot.plot('annotations')
        plot.stroke()
        ann.HD = False
        ann.HD_labels = False

    if tycho2:
        from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match
        from astrometry.libkd import spherematch_c
        from astrometry.util.starutil_numpy import deg2dist, xyztoradec
        import numpy as np
        import sys
        kd = tree_open(settings.TYCHO2_KD)
        # this is a bit silly: build a tree with a single point, then do match()
        kd2 = tree_build_radec(np.array([ra]), np.array([dec]))
        r = deg2dist(width * np.sqrt(2.) / 2.)
        #r = deg2dist(wcs.radius())
        I,J,d = trees_match(kd, kd2, r, permuted=False)
        del J
        del d
        #print 'Matched', len(I)
        xyz = spherematch_c.kdtree_get_positions(kd, I)
        del I
        tree_free(kd2)
        tree_close(kd)
        #print >>sys.stderr, 'Got', xyz.shape, xyz
        tra,tdec = xyztoradec(xyz)
        #print >>sys.stderr, 'RA,Dec', ra,dec
        plot.apply_settings()
        for r,d in zip(tra,tdec):
            plot.marker_radec(r,d)
        plot.fill()

    ann.NGC = 1
    plot.plot('annotations')
    ann.NGC = 0

    plot.color = 'white'
    plot.lw = 3
    out = plot.outline
    out.wcs_file = wcsfn
    plot.plot('outline')

    if zoom:
        # MAGIC width, height are arbitrary
        zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000,1000)
        out.wcs = zoomwcs
        plot.lw = 1
        plot.dashed(3)
        plot.plot('outline')

    plot.write(plotfn)
예제 #13
0
(inds,dists) = spherematch.nearest(x1, x2, r)
dt = time() - t0

t0 = time()
inds = spherematch.match(x1, x2, r, indexlist=True)
dt = time() - t0

kd = spherematch.tree_build(x1)
spherematch.tree_print(kd)
kd.print()
R = spherematch.tree_search(kd, x2[0,:], 1.)
print('tree_search:', len(R), 'results')
spherematch.tree_close(kd)

kd2 = spherematch.tree_build(x2)
I,J,d = spherematch.trees_match(kd, kd2, 1.)
print('trees_match:', len(I), 'matches')

I,J,d = spherematch.trees_match(kd, kd2, 1., nearest=True)
print('trees_match:', len(I), 'matches (nearest)')

print('Kd bounding-box:', spherematch.tree_bbox(kd))

print('Kd bounding-box:', kd.bbox)

print('Kd data:', spherematch.tree_data(kd, np.array([0,3,5]).astype(np.uint32)))

print('Kd data:', kd.get_data(np.array([0,3,5]).astype(np.uint32)))

print('Permute:', spherematch.tree_permute(kd, np.array([3,5,7]).astype(np.int32)))
예제 #14
0
def find_alignments(fns, wcsfns, gaia_fn, aff_fn, aligned_fn):
    from astrometry.libkd.spherematch import tree_build_radec, trees_match
    from astrometry.libkd.spherematch import match_radec
    from astrometry.util.plotutils import plothist
    from astrometry.util.util import Tan
    import fitsio

    from astrom_common import getwcsoutline
    from singles import find_overlaps

    if True:
        WCS = []
        for fn in wcsfns:
            wcs = Tan(fn)
            WCS.append(wcs)

    names = [fn.replace('-bright.fits', '') for fn in fns]

    outlines = [getwcsoutline(wcs) for wcs in WCS]

    overlaps, areas = find_overlaps(outlines)

    print('Reading tables...')
    TT = [fits_table(fn) for fn in fns]
    print('Building trees...')
    kds = [tree_build_radec(T.ra, T.dec) for T in TT]

    for T, name in zip(TT, names):
        T.name = np.array([name] * len(T))

    allra = np.hstack([T.ra for T in TT])
    alldec = np.hstack([T.dec for T in TT])
    minra = np.min(allra)
    maxra = np.max(allra)
    mindec = np.min(alldec)
    maxdec = np.max(alldec)

    print('RA,Dec range:', minra, maxra, mindec, maxdec)

    plothist(allra, alldec)
    plt.axis([maxra, minra, mindec, maxdec])
    plt.xlabel('RA (deg)')
    plt.ylabel('Dec (deg)')
    plt.savefig('match-all.png')

    Tref = fits_table(gaia_fn)
    r_arcsec = 0.2
    I, J, d = match_radec(Tref.ra, Tref.dec, allra, alldec, r_arcsec / 3600.)
    dec = alldec[J]
    cosdec = np.cos(np.deg2rad(dec))
    dr = (Tref.ra[I] - allra[J]) * cosdec * 3600.
    dd = (Tref.dec[I] - alldec[J]) * 3600.
    plt.clf()
    rr = (-r_arcsec * 1000, +r_arcsec * 1000)
    plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr))
    plt.xlabel('dRA (milli-arcsec)')
    plt.ylabel('dDec (milli-arcsec)')
    plt.savefig('match-all-ref-before.png')

    # Initial matching of all stars
    r_arcsec = 0.2
    I, J, d = match_radec(allra,
                          alldec,
                          allra,
                          alldec,
                          r_arcsec / 3600.,
                          notself=True)
    dec = alldec[I]
    cosdec = np.cos(np.deg2rad(dec))
    dr = (allra[I] - allra[J]) * cosdec * 3600.
    dd = (alldec[I] - alldec[J]) * 3600.

    plt.clf()
    rr = (-r_arcsec * 1000, +r_arcsec * 1000)
    plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr))
    plt.xlabel('dRA (milli-arcsec)')
    plt.ylabel('dDec (milli-arcsec)')
    plt.savefig('match-all-before.png')

    hulls = []
    from scipy.spatial import ConvexHull
    for T in TT:
        hull = ConvexHull(np.vstack((T.ra, T.dec)).T)
        ra = T.ra[hull.vertices]
        ra = np.append(ra, ra[0])
        dec = T.dec[hull.vertices]
        dec = np.append(dec, dec[0])
        hulls.append((ra, dec))

    aligns = {}

    #for i in []:
    for i in range(len(kds)):
        for j in range(i + 1, len(kds)):
            print('Matching trees', i, 'and', j)

            r_arcsec = 0.2
            radius = np.deg2rad(r_arcsec / 3600)

            I, J, d2 = trees_match(kds[i], kds[j], radius)
            print(len(I), 'matches')
            if len(I) == 0:
                continue

            Ti = TT[i]
            Tj = TT[j]
            dec = Ti[I].dec
            cosdec = np.cos(np.deg2rad(dec))
            dr = (Ti[I].ra - Tj[J].ra) * cosdec * 3600.
            dd = (Ti[I].dec - Tj[J].dec) * 3600.

            if False:
                al = Alignment(Ti, Tj, searchradius=r_arcsec)
                print('Aligning...')
                if not al.shift():
                    print('Failed to find Alignment between fields')
                    continue
                aligns[(i, j)] = al

                plt.clf()
                plotalignment(al)
                plt.savefig('match-align-%02i-%02i.png' % (i, j))

            plt.clf()
            #plothist(np.append(Ti.ra, Tj.ra), np.append(Ti.dec, Tj.dec), docolorbar=False, doclf=False, dohot=False,
            #         imshowargs=dict(cmap=antigray))
            plothist(Ti.ra[I], Ti.dec[I], docolorbar=False, doclf=False)
            r, d = hulls[i]
            plt.plot(r, d, 'r-')
            r, d = hulls[j]
            plt.plot(r, d, 'b-')
            mra = Ti.ra[I]
            mdec = Ti.dec[I]
            mnra = np.min(mra)
            mxra = np.max(mra)
            mndec = np.min(mdec)
            mxdec = np.max(mdec)
            plt.plot([mnra, mnra, mxra, mxra, mnra],
                     [mndec, mxdec, mxdec, mndec, mndec], 'g-')

            plt.axis([maxra, minra, mindec, maxdec])
            plt.xlabel('RA (deg)')
            plt.ylabel('Dec (deg)')
            plt.savefig('match-radec-%02i-%02i.png' % (i, j))

            plt.clf()
            rr = (-r_arcsec, +r_arcsec)
            plothist(dr, dd, nbins=100, range=(rr, rr))
            plt.xlabel('dRA (arcsec)')
            plt.ylabel('dDec (arcsec)')
            plt.savefig('match-dradec-%02i-%02i.png' % (i, j))

    #for roundi,(Nk,R) in enumerate(NkeepRads):

    refrad = 0.15
    targetrad = 0.005

    ps = PlotSequence('shift')

    from astrom_intra import intrabrickshift
    from singles import plot_all_alignments

    #Rads = [0.25, 0.1]
    Rads = [0.2, 0.050, 0.020]
    #Rads = [0.1]
    affs = None
    # this is the reference point around which rotations take place, NOT reference catalog stars.
    refrd = None
    for roundi, R in enumerate(Rads):

        if roundi > 0:
            refrad = 0.050

        TT1 = TT

        nb = int(np.ceil(R / targetrad))
        nb = max(nb, 5)
        if nb % 2 == 0:
            nb += 1
        print('Round', roundi + 1, ': matching with radius', R)
        print('Nbins:', nb)

        # kwargs to pass to intrabrickshift
        ikwargs = {}
        minoverlap = 0.01
        tryoverlaps = (overlaps > minoverlap)
        ikwargs.update(
            do_affine=True,  #mp=mp,
            #alignplotargs=dict(bins=25),
            alignplotargs=dict(bins=50),
            overlaps=tryoverlaps)

        ikwargs.update(ref=Tref, refrad=refrad)

        # kwargs to pass to Alignment
        akwargs = {}

        i1 = intrabrickshift(TT1,
                             matchradius=R,
                             refradecs=refrd,
                             align_kwargs=dict(histbins=nb, **akwargs),
                             **ikwargs)

        refrd = i1.get_reference_radecs()

        filts = ['' for n in names]
        ap = i1.alplotgrid
        Nk = 100000
        plot_all_alignments(ap, R * 1000, refrad * 1000, roundi + 1, names,
                            filts, ps, overlaps, outlines, Nk)
        for T, aff in zip(TT, i1.affines):
            T.ra, T.dec = aff.apply(T.ra, T.dec)

        if affs is None:
            affs = i1.affines
        else:
            for a, a2 in zip(affs, i1.affines):
                a.add(a2)

    from astrom_common import Affine
    T = Affine.toTable(affs)
    T.filenames = fns
    #T.flt = fltfns
    #T.gst = gstfns
    #T.chip = chips

    # FAKE -- used as a name in alignment_plots
    T.gst = np.array([n + '.gst.fits' for n in names])

    T.writeto(aff_fn)

    # Final matching of all stars
    allra = np.hstack([T.ra for T in TT])
    alldec = np.hstack([T.dec for T in TT])

    r_arcsec = 0.2
    I, J, d = match_radec(allra,
                          alldec,
                          allra,
                          alldec,
                          r_arcsec / 3600.,
                          notself=True)
    dec = alldec[I]
    cosdec = np.cos(np.deg2rad(dec))
    dr = (allra[I] - allra[J]) * cosdec * 3600.
    dd = (alldec[I] - alldec[J]) * 3600.

    plt.clf()
    rr = (-r_arcsec * 1000, +r_arcsec * 1000)
    plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr))
    plt.xlabel('dRA (milli-arcsec)')
    plt.ylabel('dDec (milli-arcsec)')
    plt.savefig('match-all-after.png')

    I, J, d = match_radec(Tref.ra, Tref.dec, allra, alldec, r_arcsec / 3600.)
    dec = alldec[J]
    cosdec = np.cos(np.deg2rad(dec))
    dr = (Tref.ra[I] - allra[J]) * cosdec * 3600.
    dd = (Tref.dec[I] - alldec[J]) * 3600.
    plt.clf()
    rr = (-r_arcsec * 1000, +r_arcsec * 1000)
    plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr))
    plt.xlabel('dRA (milli-arcsec)')
    plt.ylabel('dDec (milli-arcsec)')
    plt.savefig('match-all-ref-after.png')

    r_arcsec = 0.02
    I, J, d = match_radec(allra,
                          alldec,
                          allra,
                          alldec,
                          r_arcsec / 3600.,
                          notself=True)
    dec = alldec[I]
    cosdec = np.cos(np.deg2rad(dec))
    dr = (allra[I] - allra[J]) * cosdec * 3600.
    dd = (alldec[I] - alldec[J]) * 3600.
    plt.clf()
    rr = (-r_arcsec * 1000, +r_arcsec * 1000)
    plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr))
    plt.xlabel('dRA (milli-arcsec)')
    plt.ylabel('dDec (milli-arcsec)')
    plt.savefig('match-all-after2.png')

    T = fits_table()
    T.ra = allra
    T.dec = alldec
    for col in [
            'f814w_vega', 'f475w_vega', 'f336w_vega', 'f275w_vega',
            'f110w_vega', 'f160w_vega', 'name'
    ]:
        T.set(col, np.hstack([t.get(col) for t in TT]))
    T.writeto(aligned_fn)

    if False:
        from singles import alignment_plots

        dataset = 'M31'
        Nkeep = 100000
        R = 0.1
        minoverlap = 0.01
        perfield = False
        nocache = True

        from astrometry.util.multiproc import multiproc
        mp = multiproc()

        filts = ['F475W' for n in names]
        chips = [-1] * len(names)
        exptimes = [1] * len(names)
        Nall = [0] * len(names)
        rd = (minra, maxra, mindec, maxdec)
        cnames = names
        meta = (chips, names, cnames, filts, exptimes, Nall, rd)

        alignment_plots(afffn,
                        dataset,
                        Nkeep,
                        0,
                        R,
                        minoverlap,
                        perfield,
                        nocache,
                        mp,
                        0,
                        tables=(TT, outlines, meta),
                        lexsort=False)