Exemplo n.º 1
0
def run_ptf(src, tag, opt):
    ps = PlotSequence('ptf-%s' % (tag))

    stari = src.srci
    fns = glob('ptf-%i/*.fits' % stari)
    print('Found files:', len(fns))
    stamps = []
    for fn in fns:
        print('  ', fn)
        wcs = Sip(fn, 0)
        x, y = wcs.radec2pixelxy(src.ra, src.dec)
        print('  source at', x, y)
        img = pyfits.open(fn)[0].data
        print('  image', img.shape)
        H, W = img.shape
        ix = int(np.round(x))
        iy = int(np.round(y))
        S = 20
        stamp = img[max(0, iy - S):min(H, iy + S),
                    max(0, ix - S):min(W, ix + S)]
        stamps.append(stamp)

    N = len(stamps)
    cols = int(np.ceil(np.sqrt(N)))
    rows = int(np.ceil(N / float(cols)))
    plt.clf()
    for i, stamp in enumerate(stamps):
        plt.subplot(rows, cols, i + 1)
        plt.imshow(stamp, interpolation='nearest', origin='lower')
    ps.savefig()
Exemplo n.º 2
0
def run_ptf(src, tag, opt):
	ps = PlotSequence('ptf-%s' % (tag))

	stari = src.srci
	fns = glob('ptf-%i/*.fits' % stari)
	print 'Found files:', len(fns)
	stamps = []
	for fn in fns:
		print '  ', fn
		wcs = Sip(fn, 0)
		x,y = wcs.radec2pixelxy(src.ra, src.dec)
		print '  source at', x, y
		img = pyfits.open(fn)[0].data
		print '  image', img.shape
		H,W = img.shape
		ix = int(np.round(x))
		iy = int(np.round(y))
		S = 20
		stamp = img[max(0, iy - S) : min(H, iy+S),
					max(0, ix - S) : min(W, ix+S)]
		stamps.append(stamp)

	N = len(stamps)
	cols = int(np.ceil(np.sqrt(N)))
	rows = int(np.ceil(N / float(cols)))
	plt.clf()
	for i,stamp in enumerate(stamps):
		plt.subplot(rows, cols, i+1)
		plt.imshow(stamp, interpolation='nearest', origin='lower')
	ps.savefig()
Exemplo n.º 3
0
    def read_pv_wcs(self):
        '''
        Reads the WCS header, returning an `astrometry.util.util.Sip` object.
        '''
        from astrometry.util.util import Sip

        print('Reading WCS from', self.pvwcsfn)
        wcs = Sip(self.pvwcsfn)
        dra, ddec = self.decals.get_astrometric_zeropoint_for(self)
        r, d = wcs.get_crval()
        print('Applying astrometric zeropoint:', (dra, ddec))
        wcs.set_crval((r + dra, d + ddec))
        hdr = fitsio.read_header(self.pvwcsfn)
        wcs.version = hdr.get('LEGPIPEV', '')
        if len(wcs.version) == 0:
            wcs.version = hdr.get('TRACTORV', '').strip()
            if len(wcs.version) == 0:
                wcs.version = str(os.stat(self.pvwcsfn).st_mtime)
        wcs.plver = hdr.get('PLVER', '').strip()
        return wcs
Exemplo n.º 4
0
    def read_pv_wcs(self):
        '''
        Reads the WCS header, returning an `astrometry.util.util.Sip` object.
        '''
        from astrometry.util.util import Sip

        print('Reading WCS from', self.pvwcsfn)
        wcs = Sip(self.pvwcsfn)
        dra,ddec = self.decals.get_astrometric_zeropoint_for(self)
        r,d = wcs.get_crval()
        print('Applying astrometric zeropoint:', (dra,ddec))
        wcs.set_crval((r + dra, d + ddec))
        hdr = fitsio.read_header(self.pvwcsfn)
        wcs.version = hdr.get('LEGPIPEV', '')
        if len(wcs.version) == 0:
            wcs.version = hdr.get('TRACTORV', '').strip()
            if len(wcs.version) == 0:
                wcs.version = str(os.stat(self.pvwcsfn).st_mtime)
        wcs.plver = hdr.get('PLVER', '').strip()
        return wcs
Exemplo n.º 5
0
            plt.savefig('p2-%02i.png' % i)
        sys.exit(0)

    ra, dec = 219.577111, 54.52
    pixscale = 2.75 / 3600.
    #W,H = 2048, 2048
    W, H = 512, 512
    #W,H = 100,100
    cowcs = Tan(ra, dec, (W + 1) / 2., (H + 1) / 2., -pixscale, 0., 0.,
                pixscale, W, H)
    cowcs.write_to('co.wcs')

    if True:
        #intfn = '05579a167-w1-int-1b.fits'
        intfn = 'wise-frames/9a/05579a/167/05579a167-w1-int-1b.fits'
        wcs = Sip(intfn)
        pix = fitsio.read(intfn)
        pix[np.logical_not(np.isfinite(pix))] = 0.
        print('pix', pix.shape, pix.dtype)

    for i in range(5):
        t0 = time.clock()
        Yo, Xo, Yi, Xi, ims = resample_with_wcs(cowcs, wcs, [pix], 3)
        t1 = time.clock() - t0
        print('C resampling took', t1)

    t0 = time.clock()
    Yo2, Xo2, Yi2, Xi2, ims2 = resample_with_wcs(cowcs,
                                                 wcs, [pix],
                                                 3,
                                                 cinterp=False,
Exemplo n.º 6
0
def plotDistortionFile(sipfn, ext, ncells, **kwargs):
    wcs = Sip(sipfn, ext)
    if wcs is None:
        raise RuntimeError('Failed to open WCS file %s' % sipfn)
    plotDistortion(wcs, wcs.get_width(), wcs.get_height(), ncells, **kwargs)
Exemplo n.º 7
0
    flt1 = gst1.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')
    flt2 = gst2.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')
    fltout = gstout.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')

    print('Reading', gst1)
    T1 = fits_table(gst1)
    print('Read', len(T1))
    T1.about()
    print('Reading', gst2)
    T2 = fits_table(gst2)
    print('Read', len(T2))
    T2.about()

    print('Reading WCS from', flt1)
    wcs1 = Sip(flt1, 0)
    wcs1.ensure_inverse_polynomials()
    # print('Reading WCS from', flt2)
    # wcs2 = Sip(flt2, 0)
    # wcs2.ensure_inverse_polynomials()

    print('T1 X,Y ranges', T1.x.min(), T1.x.max(), T1.y.min(), T1.y.max())
    print('T2 X,Y ranges', T2.x.min(), T2.x.max(), T2.y.min(), T2.y.max())

    # ~ 1e-6, 0.0006
    # ok,x,y = wcs2.radec2pixelxy(T2.ra, T2.dec)
    # print('Scatter wcs x vs catalog x:', np.mean(x - T2.x), np.std(x - T2.x))
    # print('Scatter wcs y vs catalog y:', np.mean(y - T2.y), np.std(y - T2.y))

    ok, x, y = wcs1.radec2pixelxy(T2.ra, T2.dec)
    print('Converted X,Y ranges:', x.min(), x.max(), y.min(), y.max())
Exemplo n.º 8
0
def plotDistortionFile(sipfn, ext, ncells, **kwargs):
    wcs = Sip(sipfn, ext)
    if wcs is None:
        raise RuntimeError('Failed to open WCS file %s' % sipfn)
    plotDistortion(wcs, wcs.get_width(), wcs.get_height(), ncells, **kwargs)
Exemplo n.º 9
0
def main():

    # In LSST meas-deblend (on lsst6):
    # python examples/suprimePlot.py --data ~dstn/lsst/ACT-data -v 126969 -c 5 --data-range -100 300 --roi 0 500 0 500 --psf psf.fits --image img.fits --sources srcs.fits

    from optparse import OptionParser
    import sys

    parser = OptionParser(usage=('%prog <img> <psf> <srcs>'))
    parser.add_option('-v',
                      '--verbose',
                      dest='verbose',
                      action='count',
                      default=0,
                      help='Make more verbose')
    opt, args = parser.parse_args()

    if len(args) != 3:
        parser.print_help()
        sys.exit(-1)

    if opt.verbose == 0:
        lvl = logging.INFO
    else:
        lvl = logging.DEBUG
    logging.basicConfig(level=lvl, format='%(message)s', stream=sys.stdout)

    imgfn, psffn, srcfn = args

    pimg = pyfits.open(imgfn)
    if len(pimg) != 4:
        print('Image must have 3 extensions')
        sys.exit(-1)
    img = pimg[1].data
    mask = pimg[2].data
    maskhdr = pimg[2].header
    var = pimg[3].data
    del pimg

    print('var', var.shape)
    #print var
    print('mask', mask.shape)
    #print mask
    print('img', img.shape)
    #print img

    mask = mask.astype(np.int16)
    for bit in range(16):
        on = ((mask & (1 << bit)) != 0)
        print('Bit', bit, 'has', np.sum(on), 'pixels set')
    '''
	MP_BAD  =                    0
	Bit 0 has 2500 pixels set
	MP_SAT  =                    1
	Bit 1 has 5771 pixels set
	MP_INTRP=                    2
	Bit 2 has 11269 pixels set
	MP_CR   =                    3
	Bit 3 has 136 pixels set
	MP_EDGE =                    4
	Bit 4 has 11856 pixels set
	HIERARCH MP_DETECTED =       5
	Bit 5 has 37032 pixels set
	'''

    print('Mask header:', maskhdr)
    maskplanes = {}
    print('Mask planes:')
    for card in maskhdr.ascardlist():
        if not card.key.startswith('MP_'):
            continue
        print(card.value, card.key)
        maskplanes[card.key[3:]] = card.value

    print('Variance range:', var.min(), var.max())

    print('Image median:', np.median(img.ravel()))

    invvar = 1. / var
    invvar[var == 0] = 0.
    invvar[var < 0] = 0.

    sig = np.sqrt(np.median(var))
    H, W = img.shape
    for k, v in maskplanes.items():
        plt.clf()

        I = ((mask & (1 << v)) != 0)
        rgb = np.zeros((H, W, 3))
        clipimg = np.clip((img - (-3. * sig)) / (13. * sig), 0, 1)
        cimg = clipimg.copy()
        cimg[I] = 1
        rgb[:, :, 0] = cimg
        cimg = clipimg.copy()
        cimg[I] = 0
        rgb[:, :, 1] = cimg
        rgb[:, :, 2] = cimg
        plt.imshow(rgb, interpolation='nearest', origin='lower')
        plt.title(k)
        plt.savefig('mask-%s.png' % k.lower())

    badmask = sum([(1 << maskplanes[k])
                   for k in ['BAD', 'SAT', 'INTRP', 'CR']])
    # HACK -- left EDGE sucks
    badmask += (1 << maskplanes['EDGE'])
    #badmask = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)
    #badmask |= (1 << 4)
    print('Masking out: 0x%x' % badmask)
    invvar[(mask & badmask) != 0] = 0.

    assert (all(np.isfinite(img.ravel())))
    assert (all(np.isfinite(invvar.ravel())))

    psf = pyfits.open(psffn)[0].data
    print('psf', psf.shape)
    psf /= psf.sum()

    from tractor.emfit import em_fit_2d
    from tractor.fitpsf import em_init_params

    # Create Gaussian mixture model PSF approximation.
    S = psf.shape[0]
    # number of Gaussian components
    K = 3
    w, mu, sig = em_init_params(K, None, None, None)
    II = psf.copy()
    II /= II.sum()
    # HIDEOUS HACK
    II = np.maximum(II, 0)
    print('Multi-Gaussian PSF fit...')
    xm, ym = -(S / 2), -(S / 2)
    em_fit_2d(II, xm, ym, w, mu, sig)
    print('w,mu,sig', w, mu, sig)
    mypsf = tractor.GaussianMixturePSF(w, mu, sig)

    P = mypsf.getPointSourcePatch(S / 2, S / 2)
    mn, mx = psf.min(), psf.max()
    ima = dict(interpolation='nearest', origin='lower', vmin=mn, vmax=mx)
    plt.clf()
    plt.subplot(1, 2, 1)
    plt.imshow(psf, **ima)
    plt.subplot(1, 2, 2)
    pimg = np.zeros_like(psf)
    P.addTo(pimg)
    plt.imshow(pimg, **ima)
    plt.savefig('psf.png')

    sig = np.sqrt(np.median(var))

    plt.clf()
    plt.hist(img.ravel(), 100, range=(-3. * sig, 3. * sig))
    plt.savefig('imghist.png')

    srcs = fits_table(srcfn)
    print('Initial:', len(srcs), 'sources')
    # Trim sources with x=0 or y=0
    srcs = srcs[(srcs.x != 0) * (srcs.y != 0)]
    print('Trim on x,y:', len(srcs), 'sources left')
    # Zero out nans & infs
    for c in ['theta', 'a', 'b']:
        I = np.logical_not(np.isfinite(srcs.get(c)))
        srcs.get(c)[I] = 0.
    # Set sources with flux=NaN to something more sensible...
    I = np.logical_not(np.isfinite(srcs.flux))
    srcs.flux[I] = 1.
    # Sort sources by flux.
    srcs = srcs[np.argsort(-srcs.flux)]

    # Trim sources that are way outside the image.
    margin = 8. * np.maximum(srcs.a, srcs.b)
    H, W = img.shape
    srcs = srcs[(srcs.x > -margin) * (srcs.y > -margin) *
                (srcs.x < (W + margin) * (srcs.y < (H + margin)))]
    print('Trim out-of-bounds:', len(srcs), 'sources left')

    wcs = tractor.FitsWcs(Sip(imgfn, 1))
    #wcs = tractor.NullWCS()

    timg = tractor.Image(data=img,
                         invvar=invvar,
                         psf=mypsf,
                         wcs=wcs,
                         sky=tractor.ConstantSky(0.),
                         photocal=tractor.NullPhotoCal(),
                         name='image')

    inverr = timg.getInvError()
    assert (all(np.isfinite(inverr.ravel())))

    tsrcs = []
    for s in srcs:
        #pos = tractor.PixPos(s.x, s.y)
        pos = tractor.RaDecPos(s.ra, s.dec)
        if s.a > 0 and s.b > 0:
            eflux = tractor.Flux(s.flux / 2.)
            dflux = tractor.Flux(s.flux / 2.)
            re, ab, phi = s.a, s.b / s.a, 90. - s.theta
            eshape = gal.GalaxyShape(re, ab, phi)
            dshape = gal.GalaxyShape(re, ab, phi)
            print('Fluxes', eflux, dflux)
            tsrc = gal.CompositeGalaxy(pos, eflux, eshape, dflux, dshape)
        else:
            flux = tractor.Flux(s.flux)
            print('Flux', flux)
            tsrc = tractor.PointSource(pos, flux)
        tsrcs.append(tsrc)

    chug = tractor.Tractor([timg])
    for src in tsrcs:
        if chug.getModelPatch(timg, src) is None:
            print('Dropping non-overlapping source:', src)
            continue
        chug.addSource(src)
    print('Kept a total of', len(chug.catalog), 'sources')

    ima = dict(interpolation='nearest',
               origin='lower',
               vmin=-3. * sig,
               vmax=10. * sig)
    chia = dict(interpolation='nearest', origin='lower', vmin=-5., vmax=5.)

    plt.clf()
    plt.imshow(img, **ima)
    plt.colorbar()
    plt.savefig('img.png')

    plt.clf()
    plt.imshow(invvar, interpolation='nearest', origin='lower')
    plt.colorbar()
    plt.savefig('invvar.png')

    mod = chug.getModelImages()[0]
    plt.clf()
    plt.imshow(mod, **ima)
    plt.colorbar()
    plt.savefig('mod-0.png')

    chi = chug.getChiImage(0)
    plt.clf()
    plt.imshow(chi, **chia)
    plt.colorbar()
    plt.savefig('chi-0.png')

    for step in range(5):
        cat = chug.getCatalog()
        for src in cat:
            if chug.getModelPatch(timg, src) is None:
                print('Dropping non-overlapping source:', src)
                chug.removeSource(src)
        print('Kept a total of', len(chug.catalog), 'sources')

        #cat = chug.getCatalog()
        #for i,src in enumerate([]):
        #for i,src in enumerate(chug.getCatalog()):
        #for i in range(len(cat)):
        i = 0
        while i < len(cat):
            src = cat[i]

            #print 'Step', i
            #for j,s in enumerate(cat):
            #	x,y = timg.getWcs().positionToPixel(s, s.getPosition())
            #	print '  ',
            #	if j == i:
            #		print '*',
            #	print '(%6.1f, %6.1f)'%(x,y), s

            print('Optimizing source', i, 'of', len(cat))

            x, y = timg.getWcs().positionToPixel(src.getPosition(), src)
            print('(%6.1f, %6.1f)' % (x, y), src)
            # pre = src.getModelPatch(timg)

            s1 = str(src)
            print('src1 ', s1)
            dlnp1, X, a = chug.optimizeCatalogFluxes(srcs=[src])
            s2 = str(src)
            dlnp2, X, a = chug.optimizeCatalogAtFixedComplexityStep(srcs=[src],
                                                                    sky=False)
            s3 = str(src)

            #post = src.getModelPatch(timg)

            print('src1 ', s1)
            print('src2 ', s2)
            print('src3 ', s3)
            print('dlnp', dlnp1, dlnp2)

            if chug.getModelPatch(timg, src) is None:
                print('After optimizing, no overlap!')
                print('Removing source', src)
                chug.removeSource(src)
                i -= 1
            i += 1

            # plt.clf()
            # plt.subplot(2,2,1)
            # img = timg.getImage()
            # (x0,x1,y0,y1) = pre.getExtent()
            # plt.imshow(img, **ima)
            # ax = plt.axis()
            # plt.plot([x0,x0,x1,x1,x0], [y0,y1,y1,y0,y0], 'k-', lw=2)
            # plt.axis(ax)
            # plt.subplot(2,2,3)
            # plt.imshow(pre.getImage(), **ima)
            # plt.subplot(2,2,4)
            # plt.imshow(post.getImage(), **ima)
            # plt.savefig('prepost-s%i-s%03i.png' % (step, i))
            #
            # mod = chug.getModelImages()[0]
            # plt.clf()
            # plt.imshow(mod, **ima)
            # plt.colorbar()
            # plt.savefig('mod-s%i-s%03i.png' % (step, i))
            # chi = chug.getChiImage(0)
            # plt.clf()
            # plt.imshow(chi, **chia)
            # plt.colorbar()
            # plt.savefig('chi-s%i-s%03i.png' % (step, i))

        #dlnp,x,a = chug.optimizeCatalogFluxes()
        #print 'fluxes: dlnp', dlnp
        #dlnp,x,a = chug.optimizeCatalogAtFixedComplexityStep()
        #print 'opt: dlnp', dlnp

        mod = chug.getModelImages()[0]
        plt.clf()
        plt.imshow(mod, **ima)
        plt.colorbar()
        plt.savefig('mod-%i.png' % (step + 1))

        chi = chug.getChiImage(0)
        plt.clf()
        plt.imshow(chi, **chia)
        plt.colorbar()
        plt.savefig('chi-%i.png' % (step + 1))

    return

    for step in range(5):
        chug.optimizeCatalogFluxes()
        mod = chug.getModelImages()[0]
        plt.clf()
        plt.imshow(mod, **ima)
        plt.colorbar()
        plt.savefig('mod-s%i.png' % step)

        chi = chug.getChiImage(0)
        plt.clf()
        plt.imshow(chi, **chia)
        plt.colorbar()
        plt.savefig('chi-s%i.png' % step)
Exemplo n.º 10
0
def main():
    decals = Decals()

    catpattern = 'pipebrick-cats/tractor-phot-b%06i.fits'
    ra,dec = 242, 7

    # Region-of-interest, in pixels: x0, x1, y0, y1
    #roi = None
    roi = [500, 1000, 500, 1000]

    if roi is not None:
        x0,x1,y0,y1 = roi

    #expnum = 346623
    #ccdname = 'N12'
    #chips = decals.find_ccds(expnum=expnum, extname=ccdname)
    #print 'Found', len(chips), 'chips for expnum', expnum, 'extname', ccdname
    #if len(chips) != 1:
    #return False

    chips = decals.get_ccds()
    D = np.argsort(np.hypot(chips.ra - ra, chips.dec - dec))
    print('Closest chip:', chips[D[0]])
    chips = [chips[D[0]]]

    im = DecamImage(decals, chips[0])
    print('Image:', im)

    targetwcs = Sip(im.wcsfn)
    if roi is not None:
        targetwcs = targetwcs.get_subimage(x0, y0, x1-x0, y1-y0)

    r0,r1,d0,d1 = targetwcs.radec_bounds()
    # ~ 30-pixel margin
    margin = 2e-3
    if r0 > r1:
        # RA wrap-around
        TT = [brick_catalog_for_radec_box(ra,rb, d0-margin,d1+margin,
                                          decals, catpattern)
                for (ra,rb) in [(0, r1+margin), (r0-margin, 360.)]]
        T = merge_tables(TT)
        T._header = TT[0]._header
    else:
        T = brick_catalog_for_radec_box(r0-margin,r1+margin,d0-margin,
                                        d1+margin, decals, catpattern)

    print('Got', len(T), 'catalog entries within range')
    cat = read_fits_catalog(T, T._header)
    print('Got', len(cat), 'catalog objects')

    print('Switching ellipse parameterizations')
    switch_to_soft_ellipses(cat)
    keepcat = []
    for src in cat:
        if not np.all(np.isfinite(src.getParams())):
            print('Src has infinite params:', src)
            continue
        if isinstance(src, FixedCompositeGalaxy):
            f = src.fracDev.getClippedValue()
            if f == 0.:
                src = ExpGalaxy(src.pos, src.brightness, src.shapeExp)
            elif f == 1.:
                src = DevGalaxy(src.pos, src.brightness, src.shapeDev)
        keepcat.append(src)
    cat = keepcat

    slc = None
    if roi is not None:
        slc = slice(y0,y1), slice(x0,x1)
    tim = im.get_tractor_image(slc=slc)
    print('Got', tim)
    tim.psfex.fitSavedData(*tim.psfex.splinedata)
    tim.psfex.radius = 20
    tim.psf = CachingPsfEx.fromPsfEx(tim.psfex)
    
    tractor = Tractor([tim], cat)
    print('Created', tractor)

    mod = tractor.getModelImage(0)

    plt.clf()
    dimshow(tim.getImage(), **tim.ima)
    plt.title('Image')
    plt.savefig('1.png')

    plt.clf()
    dimshow(mod, **tim.ima)
    plt.title('Model')
    plt.savefig('2.png')

    
    ok,x,y = targetwcs.radec2pixelxy([src.getPosition().ra  for src in cat],
                                  [src.getPosition().dec for src in cat])
    ax = plt.axis()
    plt.plot(x, y, 'rx')
    #plt.savefig('3.png')
    plt.axis(ax)
    plt.title('Sources')
    plt.savefig('3.png')
    
    bands = [im.band]
    import runbrick
    runbrick.photoobjdir = '.'
    scat,T = get_sdss_sources(bands, targetwcs, local=False)
    print('Got', len(scat), 'SDSS sources in bounds')
    
    stractor = Tractor([tim], scat)
    print('Created', stractor)
    smod = stractor.getModelImage(0)

    plt.clf()
    dimshow(smod, **tim.ima)
    plt.title('SDSS model')
    plt.savefig('4.png')
Exemplo n.º 11
0
def map_sdss(req,
             ver,
             zoom,
             x,
             y,
             savecache=None,
             tag='sdss',
             get_images=False,
             ignoreCached=False,
             wcs=None,
             forcecache=False,
             forcescale=None,
             bestOnly=False,
             bands='gri',
             **kwargs):
    from decals import settings

    if savecache is None:
        savecache = settings.SAVE_CACHE
    zoom = int(zoom)
    zoomscale = 2.**zoom
    x = int(x)
    y = int(y)
    if zoom < 0 or x < 0 or y < 0 or x >= zoomscale or y >= zoomscale:
        raise RuntimeError('Invalid zoom,x,y %i,%i,%i' % (zoom, x, y))
    ver = int(ver)

    if not ver in tileversions[tag]:
        raise RuntimeError('Invalid version %i for tag %s' % (ver, tag))

    basedir = settings.DATA_DIR
    tilefn = os.path.join(basedir, 'tiles', tag,
                          '%i/%i/%i/%i.jpg' % (ver, zoom, x, y))
    if os.path.exists(tilefn) and not ignoreCached:
        if get_images:
            return None
        return send_file(tilefn,
                         'image/jpeg',
                         expires=oneyear,
                         modsince=req.META.get('HTTP_IF_MODIFIED_SINCE'))

    if not savecache:
        import tempfile
        f, tilefn = tempfile.mkstemp(suffix='.jpg')
        os.close(f)

    if wcs is None:
        try:
            wcs, W, H, zoomscale, zoom, x, y = get_tile_wcs(zoom, x, y)
        except RuntimeError as e:
            if get_images:
                return None
            return HttpResponse(e.strerror)
    else:
        W = wcs.get_width()
        H = wcs.get_height()

    from astrometry.util.fits import fits_table
    import numpy as np
    from astrometry.libkd.spherematch import tree_build_radec, tree_search_radec
    from astrometry.util.starutil_numpy import degrees_between, arcsec_between
    from astrometry.util.resample import resample_with_wcs, OverlapError
    from astrometry.util.util import Tan, Sip
    import fitsio

    print('Tile wcs: center', wcs.radec_center(), 'pixel scale',
          wcs.pixel_scale())

    global w_flist
    global w_flist_tree
    if w_flist is None:
        w_flist = fits_table(
            os.path.join(settings.DATA_DIR, 'sdss', 'window_flist.fits'),
            columns=['run', 'rerun', 'camcol', 'field', 'ra', 'dec', 'score'])
        print('Read', len(w_flist), 'window_flist entries')
        w_flist.cut(w_flist.rerun == '301')
        print('Cut to', len(w_flist), 'in rerun 301')
        w_flist_tree = tree_build_radec(w_flist.ra, w_flist.dec)

    # SDSS field size
    radius = 1.01 * np.hypot(10., 14.) / 2. / 60.

    # leaflet tile size
    ra, dec = wcs.pixelxy2radec(W / 2., H / 2.)[-2:]
    r0, d0 = wcs.pixelxy2radec(1, 1)[-2:]
    r1, d1 = wcs.pixelxy2radec(W, H)[-2:]
    radius = radius + max(degrees_between(ra, dec, r0, d0),
                          degrees_between(ra, dec, r1, d1))

    J = tree_search_radec(w_flist_tree, ra, dec, radius)

    print(len(J), 'overlapping SDSS fields found')
    if len(J) == 0:
        if get_images:
            return None
        if forcecache:
            # create symlink to blank.jpg!
            trymakedirs(tilefn)
            src = os.path.join(settings.STATIC_ROOT, 'blank.jpg')
            if os.path.exists(tilefn):
                os.unlink(tilefn)
            os.symlink(src, tilefn)
            print('Symlinked', tilefn, '->', src)
        from django.http import HttpResponseRedirect
        return HttpResponseRedirect(settings.STATIC_URL + 'blank.jpg')

    ww = [1, W * 0.25, W * 0.5, W * 0.75, W]
    hh = [1, H * 0.25, H * 0.5, H * 0.75, H]

    r, d = wcs.pixelxy2radec(
        [1] * len(hh) + ww + [W] * len(hh) + list(reversed(ww)),
        hh + [1] * len(ww) + list(reversed(hh)) + [H] * len(ww))[-2:]

    scaled = 0
    scalepat = None
    scaledir = 'sdss'

    if zoom <= 13 and forcescale is None:
        # Get *actual* pixel scales at the top & bottom
        r1, d1 = wcs.pixelxy2radec(W / 2., H)[-2:]
        r2, d2 = wcs.pixelxy2radec(W / 2., H - 1.)[-2:]
        r3, d3 = wcs.pixelxy2radec(W / 2., 1.)[-2:]
        r4, d4 = wcs.pixelxy2radec(W / 2., 2.)[-2:]
        # Take the min = most zoomed-in
        scale = min(arcsec_between(r1, d1, r2, d2),
                    arcsec_between(r3, d3, r4, d4))

        native_scale = 0.396
        scaled = int(np.floor(np.log2(scale / native_scale)))
        print('Zoom:', zoom, 'x,y', x, y, 'Tile pixel scale:', scale,
              'Scale step:', scaled)
        scaled = np.clip(scaled, 1, 7)
        dirnm = os.path.join(basedir, 'scaled', scaledir)
        scalepat = os.path.join(
            dirnm, '%(scale)i%(band)s', '%(rerun)s', '%(run)i', '%(camcol)i',
            'sdss-%(run)i-%(camcol)i-%(field)i-%(band)s.fits')

    if forcescale is not None:
        scaled = forcescale

    rimgs = [np.zeros((H, W), np.float32) for band in bands]
    rns = [np.zeros((H, W), np.float32) for band in bands]

    from astrometry.sdss import AsTransWrapper, DR9
    sdss = DR9(basedir=settings.SDSS_DIR)
    sdss.saveUnzippedFiles(settings.SDSS_DIR)
    #sdss.setFitsioReadBZ2()
    if settings.SDSS_PHOTOOBJS:
        sdss.useLocalTree(photoObjs=settings.SDSS_PHOTOOBJS,
                          resolve=settings.SDSS_RESOLVE)

    for jnum, j in enumerate(J):
        print('SDSS field', jnum, 'of', len(J), 'for zoom', zoom, 'x', x, 'y',
              y)
        im = w_flist[j]

        if im.score >= 0.5:
            weight = 1.
        else:
            weight = 0.001

        for band, rimg, rn in zip(bands, rimgs, rns):
            if im.rerun != '301':
                continue
            tmpsuff = '.tmp%08i' % np.random.randint(100000000)
            basefn = sdss.retrieve('frame',
                                   im.run,
                                   im.camcol,
                                   field=im.field,
                                   band=band,
                                   rerun=im.rerun,
                                   tempsuffix=tmpsuff)
            if scaled > 0:
                fnargs = dict(band=band,
                              rerun=im.rerun,
                              run=im.run,
                              camcol=im.camcol,
                              field=im.field)
                fn = get_scaled(scalepat,
                                fnargs,
                                scaled,
                                basefn,
                                read_base_wcs=read_astrans,
                                read_wcs=read_sip_wcs)
                print('get_scaled:', fn)
            else:
                fn = basefn
            frame = None
            if fn == basefn:
                frame = sdss.readFrame(im.run,
                                       im.camcol,
                                       im.field,
                                       band,
                                       filename=fn)
                h, w = frame.getImageShape()
                # Trim off the overlapping top of the image
                # Wimp out and instead of trimming 128 pix, trim 124!
                trim = 124
                subh = h - trim
                astrans = frame.getAsTrans()
                fwcs = AsTransWrapper(astrans, w, subh)
                fullimg = frame.getImage()
                fullimg = fullimg[:-trim, :]
            else:
                fwcs = Sip(fn)
                fitsimg = fitsio.FITS(fn)[0]
                h, w = fitsimg.get_info()['dims']
                fullimg = fitsimg.read()

            try:
                #Yo,Xo,Yi,Xi,nil = resample_with_wcs(wcs, fwcs, [], 3)
                Yo, Xo, Yi, Xi, [resamp
                                 ] = resample_with_wcs(wcs, fwcs, [fullimg], 2)
            except OverlapError:
                continue
            if len(Xi) == 0:
                #print 'No overlap'
                continue

            if sdssps is not None:
                x0 = Xi.min()
                x1 = Xi.max()
                y0 = Yi.min()
                y1 = Yi.max()
                slc = (slice(y0, y1 + 1), slice(x0, x1 + 1))
                if frame is not None:
                    img = frame.getImageSlice(slc)
                else:
                    img = fitsimg[slc]
            #rimg[Yo,Xo] += img[Yi-y0, Xi-x0]

            if bestOnly:
                K = np.flatnonzero(weight > rn[Yo, Xo])
                print('Updating', len(K), 'of', len(Yo), 'pixels')
                if len(K):
                    rimg[Yo[K], Xo[K]] = resamp[K] * weight
                    rn[Yo[K], Xo[K]] = weight
            else:
                rimg[Yo, Xo] += resamp * weight
                rn[Yo, Xo] += weight

            if sdssps is not None:
                # goodpix = np.ones(img.shape, bool)
                # fpM = sdss.readFpM(im.run, im.camcol, im.field, band)
                # for plane in [ 'INTERP', 'SATUR', 'CR', 'GHOST' ]:
                #     fpM.setMaskedPixels(plane, goodpix, False, roi=[x0,x1,y0,y1])
                plt.clf()
                #ima = dict(vmin=-0.05, vmax=0.5)
                #ima = dict(vmin=-0.5, vmax=2.)
                ima = dict(vmax=np.percentile(img, 99))
                plt.subplot(2, 3, 1)
                dimshow(img, ticks=False, **ima)
                plt.title('image')
                rthis = np.zeros_like(rimg)
                #rthis[Yo,Xo] += img[Yi-y0, Xi-x0]
                rthis[Yo, Xo] += resamp
                plt.subplot(2, 3, 2)
                dimshow(rthis, ticks=False, **ima)
                plt.title('resampled')
                # plt.subplot(2,3,3)
                # dimshow(goodpix, ticks=False, vmin=0, vmax=1)
                # plt.title('good pix')
                plt.subplot(2, 3, 4)
                dimshow(rimg / np.maximum(rn, 1), ticks=False, **ima)
                plt.title('coadd')
                plt.subplot(2, 3, 5)
                dimshow(rn, vmin=0, ticks=False)
                plt.title('coverage: max %i' % rn.max())
                plt.subplot(2, 3, 6)
                rgb = sdss_rgb(
                    [rimg / np.maximum(rn, 1) for rimg, rn in zip(rimgs, rns)],
                    bands)
                dimshow(rgb)
                plt.suptitle('SDSS %s, R/C/F %i/%i/%i' %
                             (band, im.run, im.camcol, im.field))
                sdssps.savefig()

    for rimg, rn in zip(rimgs, rns):
        rimg /= np.maximum(rn, 1e-3)
    del rns

    if get_images:
        return rimgs

    rgb = sdss_rgb(rimgs, bands)
    trymakedirs(tilefn)
    save_jpeg(tilefn, rgb)
    print('Wrote', tilefn)

    return send_file(tilefn, 'image/jpeg', unlink=(not savecache))
Exemplo n.º 12
0
    I = np.flatnonzero(T.flt == fltmerged)
    if len(I) != 1:
        print('Found %i match to merged FLT filename "%s"; expected 1' % (len(I), fltmerged))
        sys.exit(-1)
    i = I[0]
    #aff = T[i]

    affs = Affine.fromTable(T[I])
    aff = affs[0]

    print('Will write to', scriptout)
    fscript = open(scriptout, 'w')

    print('Reading WCS from', flt2)
    wcsext = 0
    wcs2 = Sip(flt2, wcsext)
    wcs2.ensure_inverse_polynomials()

    tan = wcs2.wcstan
    aff.applyToWcsObject(tan)
    tt = NamedTemporaryFile()
    outfn = tt.name
    wcs2.write_to(outfn)

    info = parse_flt_filename(flt2)
    name = info['name']
    chip = info['chip']

    extmap = {1:1, 2:4, 0:1}
    scriptfn = '%s_flt.fits[%i]' % (name, extmap[chip])
    write_update_script(flt2, outfn, scriptfn, fscript, inext=wcsext)
Exemplo n.º 13
0
def main():
    decals = Decals()

    catpattern = 'pipebrick-cats/tractor-phot-b%06i.fits'
    ra, dec = 242, 7

    # Region-of-interest, in pixels: x0, x1, y0, y1
    #roi = None
    roi = [500, 1000, 500, 1000]

    if roi is not None:
        x0, x1, y0, y1 = roi

    #expnum = 346623
    #ccdname = 'N12'
    #chips = decals.find_ccds(expnum=expnum, extname=ccdname)
    #print 'Found', len(chips), 'chips for expnum', expnum, 'extname', ccdname
    #if len(chips) != 1:
    #return False

    chips = decals.get_ccds()
    D = np.argsort(np.hypot(chips.ra - ra, chips.dec - dec))
    print('Closest chip:', chips[D[0]])
    chips = [chips[D[0]]]

    im = DecamImage(decals, chips[0])
    print('Image:', im)

    targetwcs = Sip(im.wcsfn)
    if roi is not None:
        targetwcs = targetwcs.get_subimage(x0, y0, x1 - x0, y1 - y0)

    r0, r1, d0, d1 = targetwcs.radec_bounds()
    # ~ 30-pixel margin
    margin = 2e-3
    if r0 > r1:
        # RA wrap-around
        TT = [
            brick_catalog_for_radec_box(ra, rb, d0 - margin, d1 + margin,
                                        decals, catpattern)
            for (ra, rb) in [(0, r1 + margin), (r0 - margin, 360.)]
        ]
        T = merge_tables(TT)
        T._header = TT[0]._header
    else:
        T = brick_catalog_for_radec_box(r0 - margin, r1 + margin, d0 - margin,
                                        d1 + margin, decals, catpattern)

    print('Got', len(T), 'catalog entries within range')
    cat = read_fits_catalog(T, T._header)
    print('Got', len(cat), 'catalog objects')

    print('Switching ellipse parameterizations')
    switch_to_soft_ellipses(cat)
    keepcat = []
    for src in cat:
        if not np.all(np.isfinite(src.getParams())):
            print('Src has infinite params:', src)
            continue
        if isinstance(src, FixedCompositeGalaxy):
            f = src.fracDev.getClippedValue()
            if f == 0.:
                src = ExpGalaxy(src.pos, src.brightness, src.shapeExp)
            elif f == 1.:
                src = DevGalaxy(src.pos, src.brightness, src.shapeDev)
        keepcat.append(src)
    cat = keepcat

    slc = None
    if roi is not None:
        slc = slice(y0, y1), slice(x0, x1)
    tim = im.get_tractor_image(slc=slc)
    print('Got', tim)
    tim.psfex.fitSavedData(*tim.psfex.splinedata)
    tim.psfex.radius = 20
    tim.psf = CachingPsfEx.fromPsfEx(tim.psfex)

    tractor = Tractor([tim], cat)
    print('Created', tractor)

    mod = tractor.getModelImage(0)

    plt.clf()
    dimshow(tim.getImage(), **tim.ima)
    plt.title('Image')
    plt.savefig('1.png')

    plt.clf()
    dimshow(mod, **tim.ima)
    plt.title('Model')
    plt.savefig('2.png')

    ok, x, y = targetwcs.radec2pixelxy([src.getPosition().ra for src in cat],
                                       [src.getPosition().dec for src in cat])
    ax = plt.axis()
    plt.plot(x, y, 'rx')
    #plt.savefig('3.png')
    plt.axis(ax)
    plt.title('Sources')
    plt.savefig('3.png')

    bands = [im.band]
    import runbrick
    runbrick.photoobjdir = '.'
    scat, T = get_sdss_sources(bands, targetwcs, local=False)
    print('Got', len(scat), 'SDSS sources in bounds')

    stractor = Tractor([tim], scat)
    print('Created', stractor)
    smod = stractor.getModelImage(0)

    plt.clf()
    dimshow(smod, **tim.ima)
    plt.title('SDSS model')
    plt.savefig('4.png')
Exemplo n.º 14
0
def read_wise_level1b(basefn, radecroi=None, radecrad=None, filtermap=None,
                      nanomaggies=False, mask_gz=False, unc_gz=False,
                      sipwcs=False, constantInvvar=False,
                      roi=None,
                      zrsigs=[-3, 10],
                      ):
    if filtermap is None:
        filtermap = {}

    intfn = basefn + '-int-1b.fits'
    maskfn = basefn + '-msk-1b.fits'

    if mask_gz:
        maskfn = maskfn + '.gz'
    uncfn = basefn + '-unc-1b.fits'
    if unc_gz:
        uncfn = uncfn + '.gz'

    logger.debug('intensity image   %s' % intfn)
    logger.debug('mask image        %s' % maskfn)
    logger.debug('uncertainty image %s' % uncfn)

    if sipwcs:
        wcs = Sip(intfn, 0)
        twcs = tractor.ConstantFitsWcs(wcs)
    else:
        twcs = tractor.ConstantFitsWcs(intfn)

    # Read enough of the image to get its size
    Fint = fitsio.FITS(intfn)
    H, W = Fint[0].get_info()['dims']

    if radecrad is not None:
        r, d, rad = radecrad
        x, y = twcs.positionToPixel(tractor.RaDecPos(r, d))
        pixrad = rad / (twcs.pixel_scale() / 3600.)
        print('Tractor WCS:', twcs)
        print('RA,Dec,rad', r, d, rad, 'becomes x,y,pixrad', x, y, pixrad)
        roi = (x - pixrad, x + pixrad + 1, y - pixrad, y + pixrad + 1)

    if radecroi is not None:
        ralo, rahi, declo, dechi = radecroi
        xy = [twcs.positionToPixel(tractor.RaDecPos(r, d))
              for r, d in [(ralo, declo), (ralo, dechi), (rahi, declo), (rahi, dechi)]]
        xy = np.array(xy)
        x0, x1 = xy[:, 0].min(), xy[:, 0].max()
        y0, y1 = xy[:, 1].min(), xy[:, 1].max()
        print('RA,Dec ROI', ralo, rahi, declo, dechi,
              'becomes x,y ROI', x0, x1, y0, y1)
        roi = (x0, x1 + 1, y0, y1 + 1)

    if roi is not None:
        x0, x1, y0, y1 = roi
        x0 = int(np.floor(x0))
        x1 = int(np.ceil(x1))
        y0 = int(np.floor(y0))
        y1 = int(np.ceil(y1))
        roi = (x0, x1, y0, y1)
        # Clip to image size...
        x0 = np.clip(x0, 0, W)
        x1 = np.clip(x1, 0, W)
        y0 = np.clip(y0, 0, H)
        y1 = np.clip(y1, 0, H)
        if x0 == x1 or y0 == y1:
            print('ROI is empty')
            return None
        assert(x0 < x1)
        assert(y0 < y1)
        #roi = (x0,x1,y0,y1)
        twcs.setX0Y0(x0, y0)

    else:
        x0, x1, y0, y1 = 0, W, 0, H
        roi = (x0, x1, y0, y1)

    ihdr = Fint[0].read_header()
    data = Fint[0][y0:y1, x0:x1]
    logger.debug('Read %s intensity' % (str(data.shape)))
    band = ihdr['BAND']

    F = fitsio.FITS(uncfn)
    assert(F[0].get_info()['dims'] == [H, W])
    unc = F[0][y0:y1, x0:x1]

    F = fitsio.FITS(maskfn)
    assert(F[0].get_info()['dims'] == [H, W])
    mask = F[0][y0:y1, x0:x1]

    # HACK -- circular Gaussian PSF of fixed size...
    # in arcsec
    fwhms = {1: 6.1, 2: 6.4, 3: 6.5, 4: 12.0}
    # -> sigma in pixels
    sig = fwhms[band] / 2.35 / twcs.pixel_scale()
    # print 'PSF sigma', sig, 'pixels'
    tpsf = tractor.NCircularGaussianPSF([sig], [1.])

    filter = 'w%i' % band
    if filtermap:
        filter = filtermap.get(filter, filter)
    zp = ihdr['MAGZP']
    if nanomaggies:
        photocal = tractor.LinearPhotoCal(tractor.NanoMaggies.zeropointToScale(zp),
                                          band=filter)
    else:
        photocal = tractor.MagsPhotoCal(filter, zp)

    # print 'Image median:', np.median(data)
    # print 'unc median:', np.median(unc)

    sky = np.median(data)
    tsky = tractor.ConstantSky(sky)

    name = 'WISE ' + ihdr['FRSETID'] + ' W%i' % band

    # Mask bits, from
    # http://wise2.ipac.caltech.edu/docs/release/allsky/expsup/sec4_4a.html#maskdef
    # 0 from static mask: excessively noisy due to high dark current alone
    # 1 from static mask: generally noisy [includes bit 0]
    # 2 from static mask: dead or very low responsivity
    # 3 from static mask: low responsivity or low dark current
    # 4 from static mask: high responsivity or high dark current
    # 5 from static mask: saturated anywhere in ramp
    # 6 from static mask: high, uncertain, or unreliable non-linearity
    # 7 from static mask: known broken hardware pixel or excessively noisy responsivity estimate [may include bit 1]
    # 8 reserved
    # 9 broken pixel or negative slope fit value (downlink value = 32767)
    # 10 saturated in sample read 1 (down-link value = 32753)
    # 11 saturated in sample read 2 (down-link value = 32754)
    # 12 saturated in sample read 3 (down-link value = 32755)
    # 13 saturated in sample read 4 (down-link value = 32756)
    # 14 saturated in sample read 5 (down-link value = 32757)
    # 15 saturated in sample read 6 (down-link value = 32758)
    # 16 saturated in sample read 7 (down-link value = 32759)
    # 17 saturated in sample read 8 (down-link value = 32760)
    # 18 saturated in sample read 9 (down-link value = 32761)
    # 19 reserved
    # 20 reserved
    # 21 new/transient bad pixel from dynamic masking
    # 22 reserved
    # 23 reserved
    # 24 reserved
    # 25 reserved
    # 26 non-linearity correction unreliable
    # 27 contains cosmic-ray or outlier that cannot be classified (from temporal outlier rejection in multi-frame pipeline)
    # 28 contains positive or negative spike-outlier
    # 29 reserved
    # 30 reserved
    # 31 not used: sign bit

    goodmask = ((mask & sum([1 << bit for bit in [0, 1, 2, 3, 4, 5, 6, 7, 9,
                                                  10, 11, 12, 13, 14, 15, 16, 17, 18,
                                                  21, 26, 27, 28]])) == 0)
    sigma1 = np.median(unc[goodmask])
    zr = np.array(zrsigs) * sigma1 + sky

    # constant
    cinvvar = np.zeros_like(data)
    cinvvar[goodmask] = 1. / (sigma1**2)
    # varying
    vinvvar = np.zeros_like(data)
    vinvvar[goodmask] = 1. / (unc[goodmask])**2

    bad = np.flatnonzero(np.logical_not(np.isfinite(vinvvar)))
    if len(bad):
        vinvvar.flat[bad] = 0.
        cinvvar.flat[bad] = 0.
        data.flat[bad] = sky

    if constantInvvar:
        invvar = cinvvar
    else:
        invvar = vinvvar

    # avoid NaNs
    data[np.logical_not(goodmask)] = sky

    mjd = ihdr['MJD_OBS']
    time = TAITime(None, mjd=mjd)

    tim = tractor.Image(data=data, invvar=invvar, psf=tpsf, wcs=twcs,
                        sky=tsky, photocal=photocal, time=time, name=name, zr=zr,
                        domask=False)
    tim.extent = [x0, x1, y0, y1]
    tim.sigma1 = sigma1
    #tim.roi = roi

    # FIXME
    tim.maskplane = mask
    tim.uncplane = unc
    tim.goodmask = goodmask

    # carry both around for retrofitting
    tim.vinvvar = vinvvar
    tim.cinvvar = cinvvar

    return tim
Exemplo n.º 15
0
        chipnames = []
        corrs = []
        for im in ims:
            if not os.path.exists(im.corrfn):
                print 'NO SUCH FILE:', im.corrfn
                continue

            sdss = fits_table(im.sdssfn)

            #sefn = im.morphfn
            sefn = im.sefn
            print 'Looking for', sefn

            morph = fits_table(sefn, hdu=2)

            wcs = Sip(im.wcsfn)
            if len(sdss) == 0:
                print 'EMPTY:', im.sdssfn
                continue
            if len(morph) == 0:
                print 'EMPTY:', im.morphfn
                continue
            print len(sdss), 'SDSS sources from', im.sdssfn
            print len(morph), 'SE sources from', sefn
            morph.ra, morph.dec = wcs.pixelxy2radec(morph.x_image,
                                                    morph.y_image)

            I, J, d = match_radec(morph.ra, morph.dec, sdss.ra, sdss.dec,
                                  0.5 / 3600.)
            corr = sdss[J]
            corr.add_columns_from(morph[I])
Exemplo n.º 16
0
        chipnames = []
        corrs = []
        for im in ims:
            if not os.path.exists(im.corrfn):
                print 'NO SUCH FILE:', im.corrfn
                continue

            sdss = fits_table(im.sdssfn)

            #sefn = im.morphfn
            sefn = im.sefn
            print 'Looking for', sefn

            morph = fits_table(sefn, hdu=2)

            wcs = Sip(im.wcsfn)
            if len(sdss) == 0:
                print 'EMPTY:', im.sdssfn
                continue
            if len(morph) == 0:
                print 'EMPTY:', im.morphfn
                continue
            print len(sdss), 'SDSS sources from', im.sdssfn
            print len(morph), 'SE sources from', sefn
            morph.ra,morph.dec = wcs.pixelxy2radec(morph.x_image, morph.y_image)

            I,J,d = match_radec(morph.ra, morph.dec, sdss.ra, sdss.dec, 0.5/3600.)
            corr = sdss[J]
            corr.add_columns_from(morph[I])

            chipnames.append(im.extname)
Exemplo n.º 17
0
    flt1 = gst1.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')
    flt2 = gst2.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')
    fltout = gstout.replace('.gst.fits', '.fits').replace('.st.fits', '.fits')

    print('Reading', gst1)
    T1 = fits_table(gst1)
    print('Read', len(T1))
    T1.about()
    print('Reading', gst2)
    T2 = fits_table(gst2)
    print('Read', len(T2))
    T2.about()

    print('Reading WCS from', flt1)
    wcs1 = Sip(flt1, 0)
    wcs1.ensure_inverse_polynomials()
    # print('Reading WCS from', flt2)
    # wcs2 = Sip(flt2, 0)
    # wcs2.ensure_inverse_polynomials()

    print('T1 X,Y ranges', T1.x.min(), T1.x.max(), T1.y.min(), T1.y.max())
    print('T2 X,Y ranges', T2.x.min(), T2.x.max(), T2.y.min(), T2.y.max())

    # ~ 1e-6, 0.0006
    # ok,x,y = wcs2.radec2pixelxy(T2.ra, T2.dec)
    # print('Scatter wcs x vs catalog x:', np.mean(x - T2.x), np.std(x - T2.x))
    # print('Scatter wcs y vs catalog y:', np.mean(y - T2.y), np.std(y - T2.y))
    
    ok,x,y = wcs1.radec2pixelxy(T2.ra, T2.dec)
    print('Converted X,Y ranges:', x.min(), x.max(), y.min(), y.max())