Пример #1
0
def stage_rergb(coimgs=None,
                bands=None,
                basedir=None,
                brickid=None,
                ps=None,
                **kwargs):
    plt.figure(figsize=(10, 10))
    plt.subplots_adjust(left=0.002, right=0.998, bottom=0.002, top=0.998)

    rgb = get_rgb(coimgs, bands)

    plt.clf()
    dimshow(rgb)
    fn = os.path.join(basedir, 'coadd', 'image2-%06i.png' % brickid)
    plt.savefig(fn)
    print('Saved', fn)

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    fn = os.path.join(basedir, 'coadd', 'image2-%06i-full.jpg' % brickid)
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > %s' % (tmpfn, fn)
    os.system(cmd)
    os.unlink(tmpfn)
    print('Wrote', fn)
Пример #2
0
def stage_primage(coimgs=None, bands=None, ps=None, basedir=None, **kwargs):
    '''
    Nice PR image for NOAO.  Make a synthetic brick centered on a nice galaxy in 374451

    bricks.txt:
    # brickid ra dec ra1 ra2 dec1 dec2
    1 244.70 7.41 244.5739 244.8261 7.285 7.535
    2 244.70 7.41 244.5739 244.8261 7.285 7.535

    text2fits.py -f jdddddd PR/bricks.txt PR/decals-bricks.fits
    cp decals/decals-ccds.fits PR
    (cd PR; ln -s ~/cosmo/work/decam/versions/work/calib .)
    (cd PR; ln -s ~/cosmo/work/decam/versions/work/images .)
    export DECALS_DIR=$(pwd)/PR
    python -u projects/desi/tunebrick.py -b      1 -s primage -P "pickles/PR-%(brick)06i-%%(stage)s.pickle"
    python -u projects/desi/tunebrick.py -b 374441 -s primage -P "pickles/PR-%(brick)06i-%%(stage)s.pickle"

    '''

    print('kwargs:', kwargs.keys())

    rgb = get_rgb(coimgs, bands, mnmx=(0., 100.), arcsinh=1.)

    plt.clf()
    dimshow(rgb)
    ps.savefig()

    fn = ps.getnext()
    plt.imsave(fn, rgb, origin='lower')

    jpegfn = fn.replace('.png', '.jpg')
    cmd = 'pngtopnm %s | pnmtojpeg -quality 80 > %s' % (fn, jpegfn)
    print(cmd)
    os.system(cmd)
Пример #3
0
def stage_rergb(coimgs=None, bands=None, basedir=None, brickid=None,
                ps=None, **kwargs):
    plt.figure(figsize=(10,10))
    plt.subplots_adjust(left=0.002, right=0.998, bottom=0.002, top=0.998)

    rgb = get_rgb(coimgs, bands)

    plt.clf()
    dimshow(rgb)
    fn = os.path.join(basedir, 'coadd', 'image2-%06i.png' % brickid)
    plt.savefig(fn)
    print 'Saved', fn

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    fn = os.path.join(basedir, 'coadd', 'image2-%06i-full.jpg' % brickid)
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > %s' % (tmpfn, fn)
    os.system(cmd)
    os.unlink(tmpfn)
    print 'Wrote', fn
Пример #4
0
def stage_primage(coimgs=None, bands=None, ps=None, basedir=None,
                  **kwargs):

    '''
    Nice PR image for NOAO.  Make a synthetic brick centered on a nice galaxy in 374451

    bricks.txt:
    # brickid ra dec ra1 ra2 dec1 dec2
    1 244.70 7.41 244.5739 244.8261 7.285 7.535
    2 244.70 7.41 244.5739 244.8261 7.285 7.535

    text2fits.py -f jdddddd PR/bricks.txt PR/decals-bricks.fits
    cp decals/decals-ccds.fits PR
    (cd PR; ln -s ~/cosmo/work/decam/versions/work/calib .)
    (cd PR; ln -s ~/cosmo/work/decam/versions/work/images .)
    export DECALS_DIR=$(pwd)/PR
    python -u projects/desi/tunebrick.py -b      1 -s primage -P "pickles/PR-%(brick)06i-%%(stage)s.pickle"
    python -u projects/desi/tunebrick.py -b 374441 -s primage -P "pickles/PR-%(brick)06i-%%(stage)s.pickle"

    '''


    print 'kwargs:', kwargs.keys()

    rgb = get_rgb(coimgs, bands, mnmx=(0., 100.), arcsinh=1.)
    
    plt.clf()
    dimshow(rgb)
    ps.savefig()

    fn = ps.getnext()
    plt.imsave(fn, rgb, origin='lower')

    jpegfn = fn.replace('.png','.jpg')
    cmd = 'pngtopnm %s | pnmtojpeg -quality 80 > %s' % (fn, jpegfn)
    print cmd
    os.system(cmd)
Пример #5
0
def stage0(**kwargs):
    ps = PlotSequence('cfht')

    decals = CfhtDecals()
    B = decals.get_bricks()
    print('Bricks:')
    B.about()

    ra, dec = 190.0, 11.0

    #bands = 'ugri'
    bands = 'gri'

    B.cut(np.argsort(degrees_between(ra, dec, B.ra, B.dec)))
    print('Nearest bricks:', B.ra[:5], B.dec[:5], B.brickid[:5])

    brick = B[0]
    pixscale = 0.186
    #W,H = 1024,1024
    #W,H = 2048,2048
    #W,H = 3600,3600
    W, H = 4800, 4800

    targetwcs = wcs_for_brick(brick, pixscale=pixscale, W=W, H=H)
    ccdfn = 'cfht-ccds.fits'
    if os.path.exists(ccdfn):
        T = fits_table(ccdfn)
    else:
        T = get_ccd_list()
        T.writeto(ccdfn)
    print(len(T), 'CCDs')
    T.cut(ccds_touching_wcs(targetwcs, T))
    print(len(T), 'CCDs touching brick')

    T.cut(np.array([b in bands for b in T.filter]))
    print(len(T), 'in bands', bands)

    ims = []
    for t in T:
        im = CfhtImage(t)
        # magzp = hdr['PHOT_C'] + 2.5 * np.log10(hdr['EXPTIME'])
        # fwhm = t.seeing / (pixscale * 3600)
        # print '-> FWHM', fwhm, 'pix'
        im.seeing = t.seeing
        im.pixscale = t.pixscale
        print('seeing', t.seeing)
        print('pixscale', im.pixscale * 3600, 'arcsec/pix')
        im.run_calibs(t.ra, t.dec, im.pixscale, W=t.width, H=t.height)
        ims.append(im)

    # Read images, clip to ROI
    targetrd = np.array([
        targetwcs.pixelxy2radec(x, y)
        for x, y in [(1, 1), (W, 1), (W, H), (1, H), (1, 1)]
    ])
    keepims = []
    tims = []
    for im in ims:
        print()
        print('Reading expnum', im.expnum, 'name', im.extname, 'band', im.band,
              'exptime', im.exptime)
        band = im.band
        wcs = im.read_wcs()
        imh, imw = wcs.imageh, wcs.imagew
        imgpoly = [(1, 1), (1, imh), (imw, imh), (imw, 1)]
        ok, tx, ty = wcs.radec2pixelxy(targetrd[:-1, 0], targetrd[:-1, 1])
        tpoly = zip(tx, ty)
        clip = clip_polygon(imgpoly, tpoly)
        clip = np.array(clip)
        #print 'Clip', clip
        if len(clip) == 0:
            continue
        x0, y0 = np.floor(clip.min(axis=0)).astype(int)
        x1, y1 = np.ceil(clip.max(axis=0)).astype(int)
        slc = slice(y0, y1 + 1), slice(x0, x1 + 1)

        ## FIXME -- it seems I got lucky and the cross product is
        ## negative == clockwise, as required by clip_polygon. One
        ## could check this and reverse the polygon vertex order.
        # dx0,dy0 = tx[1]-tx[0], ty[1]-ty[0]
        # dx1,dy1 = tx[2]-tx[1], ty[2]-ty[1]
        # cross = dx0*dy1 - dx1*dy0
        # print 'Cross:', cross

        print('Image slice: x [%i,%i], y [%i,%i]' % (x0, x1, y0, y1))
        print('Reading image from', im.imgfn, 'HDU', im.hdu)
        img, imghdr = im.read_image(header=True, slice=slc)
        goodpix = (img != 0)
        print('Number of pixels == 0:', np.sum(img == 0))
        print('Number of pixels != 0:', np.sum(goodpix))
        if np.sum(goodpix) == 0:
            continue
        # print 'Image shape', img.shape
        print('Image range', img.min(), img.max())
        print('Goodpix image range:', (img[goodpix]).min(),
              (img[goodpix]).max())
        if img[goodpix].min() == img[goodpix].max():
            print('No dynamic range in image')
            continue
        # print 'Reading invvar from', im.wtfn, 'HDU', im.hdu
        # invvar = im.read_invvar(slice=slc)
        # # print 'Invvar shape', invvar.shape
        # # print 'Invvar range:', invvar.min(), invvar.max()
        # invvar[goodpix == 0] = 0.
        # if np.all(invvar == 0.):
        #     print 'Skipping zero-invvar image'
        #     continue
        # assert(np.all(np.isfinite(img)))
        # assert(np.all(np.isfinite(invvar)))
        # assert(not(np.all(invvar == 0.)))
        # # Estimate per-pixel noise via Blanton's 5-pixel MAD
        # slice1 = (slice(0,-5,10),slice(0,-5,10))
        # slice2 = (slice(5,None,10),slice(5,None,10))
        # # print 'sliced shapes:', img[slice1].shape, img[slice2].shape
        # # print 'good shape:', (goodpix[slice1] * goodpix[slice2]).shape
        # # print 'good values:', np.unique(goodpix[slice1] * goodpix[slice2])
        # # print 'sliced[good] shapes:', (img[slice1] -  img[slice2])[goodpix[slice1] * goodpix[slice2]].shape
        # mad = np.median(np.abs(img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].ravel())
        # sig1 = 1.4826 * mad / np.sqrt(2.)
        # print 'MAD sig1:', sig1
        # # invvar was 1 or 0
        # invvar *= (1./(sig1**2))
        # medsky = np.median(img[goodpix])

        # Read full image for sig1 and sky estimate
        fullimg = im.read_image()
        fullgood = (fullimg != 0)
        # Estimate per-pixel noise via Blanton's 5-pixel MAD
        slice1 = (slice(0, -5, 10), slice(0, -5, 10))
        slice2 = (slice(5, None, 10), slice(5, None, 10))
        mad = np.median(
            np.abs(fullimg[slice1] -
                   fullimg[slice2])[fullgood[slice1] *
                                    fullgood[slice2]].ravel())
        sig1 = 1.4826 * mad / np.sqrt(2.)
        print('MAD sig1:', sig1)
        medsky = np.median(fullimg[fullgood])
        invvar = np.zeros_like(img)
        invvar[goodpix] = 1. / sig1**2

        # Median-smooth sky subtraction
        plt.clf()
        dimshow(np.round((img - medsky) / sig1), vmin=-3, vmax=5)
        plt.title('Scalar median: %s' % im.name)
        ps.savefig()

        # medsky = np.zeros_like(img)
        # # astrometry.util.util
        # median_smooth(img, np.logical_not(goodpix), 256, medsky)
        fullmed = np.zeros_like(fullimg)
        median_smooth(fullimg - medsky, np.logical_not(fullgood), 256, fullmed)
        fullmed += medsky
        medimg = fullmed[slc]

        plt.clf()
        dimshow(np.round((img - medimg) / sig1), vmin=-3, vmax=5)
        plt.title('Median filtered: %s' % im.name)
        ps.savefig()

        #print 'Subtracting median:', medsky
        #img -= medsky
        img -= medimg

        primhdr = im.read_image_primary_header()

        magzp = decals.get_zeropoint_for(im)
        print('magzp', magzp)
        zpscale = NanoMaggies.zeropointToScale(magzp)
        print('zpscale', zpscale)

        # Scale images to Nanomaggies
        img /= zpscale
        sig1 /= zpscale
        invvar *= zpscale**2
        orig_zpscale = zpscale

        zpscale = 1.
        assert (np.sum(invvar > 0) > 0)
        print('After scaling:')
        print('sig1', sig1)
        print('invvar range', invvar.min(), invvar.max())
        print('image range', img.min(), img.max())

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

        plt.clf()
        lo, hi = -5 * sig1, 10 * sig1
        n, b, p = plt.hist(img[goodpix].ravel(),
                           100,
                           range=(lo, hi),
                           histtype='step',
                           color='k')
        xx = np.linspace(lo, hi, 200)
        plt.plot(xx, max(n) * np.exp(-xx**2 / (2. * sig1**2)), 'r-')
        plt.xlim(lo, hi)
        plt.title('Pixel histogram: %s' % im.name)
        ps.savefig()

        twcs = ConstantFitsWcs(wcs)
        if x0 or y0:
            twcs.setX0Y0(x0, y0)

        info = im.get_image_info()
        fullh, fullw = info['dims']

        # read fit PsfEx model
        psfex = PsfEx.fromFits(im.psffitfn)
        print('Read', psfex)

        # HACK -- highly approximate PSF here!
        #psf_fwhm = imghdr['FWHM']
        #psf_fwhm = im.seeing

        psf_fwhm = im.seeing / (im.pixscale * 3600)
        print('PSF FWHM', psf_fwhm, 'pixels')
        psf_sigma = psf_fwhm / 2.35
        psf = NCircularGaussianPSF([psf_sigma], [1.])

        print('img type', img.dtype)

        tim = Image(img,
                    invvar=invvar,
                    wcs=twcs,
                    psf=psf,
                    photocal=LinearPhotoCal(zpscale, band=band),
                    sky=ConstantSky(0.),
                    name=im.name + ' ' + band)
        tim.zr = [-3. * sig1, 10. * sig1]
        tim.sig1 = sig1
        tim.band = band
        tim.psf_fwhm = psf_fwhm
        tim.psf_sigma = psf_sigma
        tim.sip_wcs = wcs
        tim.x0, tim.y0 = int(x0), int(y0)
        tim.psfex = psfex
        tim.imobj = im
        mn, mx = tim.zr
        tim.ima = dict(interpolation='nearest',
                       origin='lower',
                       cmap='gray',
                       vmin=mn,
                       vmax=mx)
        tims.append(tim)
        keepims.append(im)

    ims = keepims

    print('Computing resampling...')
    # save resampling params
    for tim in tims:
        wcs = tim.sip_wcs
        subh, subw = tim.shape
        subwcs = wcs.get_subimage(tim.x0, tim.y0, subw, subh)
        tim.subwcs = subwcs
        try:
            Yo, Xo, Yi, Xi, rims = resample_with_wcs(targetwcs, subwcs, [], 2)
        except OverlapError:
            print('No overlap')
            continue
        if len(Yo) == 0:
            continue
        tim.resamp = (Yo, Xo, Yi, Xi)

    print('Creating coadds...')
    # Produce per-band coadds, for plots
    coimgs = []
    cons = []
    for ib, band in enumerate(bands):
        coimg = np.zeros((H, W), np.float32)
        con = np.zeros((H, W), np.uint8)
        for tim in tims:
            if tim.band != band:
                continue
            (Yo, Xo, Yi, Xi) = tim.resamp
            if len(Yo) == 0:
                continue
            nn = (tim.getInvvar()[Yi, Xi] > 0)
            coimg[Yo, Xo] += tim.getImage()[Yi, Xi] * nn
            con[Yo, Xo] += nn

            # print
            # print 'tim', tim.name
            # print 'number of resampled pix:', len(Yo)
            # reim = np.zeros_like(coimg)
            # ren  = np.zeros_like(coimg)
            # reim[Yo,Xo] = tim.getImage()[Yi,Xi] * nn
            # ren[Yo,Xo] = nn
            # print 'number of resampled pix with positive invvar:', ren.sum()
            # plt.clf()
            # plt.subplot(2,2,1)
            # mn,mx = [np.percentile(reim[ren>0], p) for p in [25,95]]
            # print 'Percentiles:', mn,mx
            # dimshow(reim, vmin=mn, vmax=mx)
            # plt.colorbar()
            # plt.subplot(2,2,2)
            # dimshow(con)
            # plt.colorbar()
            # plt.subplot(2,2,3)
            # dimshow(reim, vmin=tim.zr[0], vmax=tim.zr[1])
            # plt.colorbar()
            # plt.subplot(2,2,4)
            # plt.hist(reim.ravel(), 100, histtype='step', color='b')
            # plt.hist(tim.getImage().ravel(), 100, histtype='step', color='r')
            # plt.suptitle('%s: %s' % (band, tim.name))
            # ps.savefig()

        coimg /= np.maximum(con, 1)
        coimgs.append(coimg)
        cons.append(con)

    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ps.savefig()

    plt.clf()
    for i, b in enumerate(bands):
        plt.subplot(2, 2, i + 1)
        dimshow(cons[i], ticks=False)
        plt.title('%s band' % b)
        plt.colorbar()
    plt.suptitle('Number of exposures')
    ps.savefig()

    print('Grabbing SDSS sources...')
    bandlist = [b for b in bands]
    cat, T = get_sdss_sources(bandlist, targetwcs)
    # record coordinates in target brick image
    ok, T.tx, T.ty = targetwcs.radec2pixelxy(T.ra, T.dec)
    T.tx -= 1
    T.ty -= 1
    T.itx = np.clip(np.round(T.tx).astype(int), 0, W - 1)
    T.ity = np.clip(np.round(T.ty).astype(int), 0, H - 1)

    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ax = plt.axis()
    plt.plot(T.tx, T.ty, 'o', mec=green, mfc='none', ms=10, mew=1.5)
    plt.axis(ax)
    plt.title('SDSS sources')
    ps.savefig()

    print('Detmaps...')
    # Render the detection maps
    detmaps = dict([(b, np.zeros((H, W), np.float32)) for b in bands])
    detivs = dict([(b, np.zeros((H, W), np.float32)) for b in bands])
    for tim in tims:
        iv = tim.getInvvar()
        psfnorm = 1. / (2. * np.sqrt(np.pi) * tim.psf_sigma)
        detim = tim.getImage().copy()
        detim[iv == 0] = 0.
        detim = gaussian_filter(detim, tim.psf_sigma) / psfnorm**2
        detsig1 = tim.sig1 / psfnorm
        subh, subw = tim.shape
        detiv = np.zeros((subh, subw), np.float32) + (1. / detsig1**2)
        detiv[iv == 0] = 0.
        (Yo, Xo, Yi, Xi) = tim.resamp
        detmaps[tim.band][Yo, Xo] += detiv[Yi, Xi] * detim[Yi, Xi]
        detivs[tim.band][Yo, Xo] += detiv[Yi, Xi]

    rtn = dict()
    for k in [
            'T', 'coimgs', 'cons', 'detmaps', 'detivs', 'targetrd', 'pixscale',
            'targetwcs', 'W', 'H', 'bands', 'tims', 'ps', 'brick', 'cat'
    ]:
        rtn[k] = locals()[k]
    return rtn
Пример #6
0
def stage1(T=None,
           coimgs=None,
           cons=None,
           detmaps=None,
           detivs=None,
           targetrd=None,
           pixscale=None,
           targetwcs=None,
           W=None,
           H=None,
           bands=None,
           tims=None,
           ps=None,
           brick=None,
           cat=None):
    orig_wcsxy0 = [tim.wcs.getX0Y0() for tim in tims]
    hot = np.zeros((H, W), np.float32)

    for band in bands:
        detmap = detmaps[band] / np.maximum(1e-16, detivs[band])
        detsn = detmap * np.sqrt(detivs[band])
        hot = np.maximum(hot, detsn)
        detmaps[band] = detmap

    ### FIXME -- ugri
    for sedname, sed in [('Flat', (1., 1., 1.)), ('Red', (2.5, 1.0, 0.4))]:
        sedmap = np.zeros((H, W), np.float32)
        sediv = np.zeros((H, W), np.float32)
        for iband, band in enumerate(bands):
            # We convert the detmap to canonical band via
            #   detmap * w
            # And the corresponding change to sig1 is
            #   sig1 * w
            # So the invvar-weighted sum is
            #    (detmap * w) / (sig1**2 * w**2)
            #  = detmap / (sig1**2 * w)
            sedmap += detmaps[band] * detivs[band] / sed[iband]
            sediv += detivs[band] / sed[iband]**2
        sedmap /= np.maximum(1e-16, sediv)
        sedsn = sedmap * np.sqrt(sediv)
        hot = np.maximum(hot, sedsn)

        plt.clf()
        dimshow(np.round(sedsn), vmin=0, vmax=10, cmap='hot')
        plt.title('SED-matched detection filter: %s' % sedname)
        ps.savefig()

    peaks = (hot > 4)
    blobs, nblobs = label(peaks)
    print('N detected blobs:', nblobs)
    blobslices = find_objects(blobs)
    # Un-set catalog blobs
    for x, y in zip(T.itx, T.ity):
        # blob number
        bb = blobs[y, x]
        if bb == 0:
            continue
        # un-set 'peaks' within this blob
        slc = blobslices[bb - 1]
        peaks[slc][blobs[slc] == bb] = 0

    # Now, after having removed catalog sources, crank up the detection threshold
    peaks &= (hot > 5)

    # zero out the edges(?)
    peaks[0, :] = peaks[:, 0] = 0
    peaks[-1, :] = peaks[:, -1] = 0
    peaks[1:-1, 1:-1] &= (hot[1:-1, 1:-1] >= hot[0:-2, 1:-1])
    peaks[1:-1, 1:-1] &= (hot[1:-1, 1:-1] >= hot[2:, 1:-1])
    peaks[1:-1, 1:-1] &= (hot[1:-1, 1:-1] >= hot[1:-1, 0:-2])
    peaks[1:-1, 1:-1] &= (hot[1:-1, 1:-1] >= hot[1:-1, 2:])

    # These are our peaks
    pki = np.flatnonzero(peaks)
    peaky, peakx = np.unravel_index(pki, peaks.shape)
    print(len(peaky), 'peaks')

    crossa = dict(ms=10, mew=1.5)
    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ax = plt.axis()
    plt.plot(T.tx, T.ty, 'r+', **crossa)
    plt.plot(peakx, peaky, '+', color=green, **crossa)
    plt.axis(ax)
    plt.title('SDSS + SED-matched detections')
    ps.savefig()

    ### HACK -- high threshold again

    # Segment, and record which sources fall into each blob
    blobs, nblobs = label((hot > 20))
    print('N detected blobs:', nblobs)
    blobslices = find_objects(blobs)
    T.blob = blobs[T.ity, T.itx]
    blobsrcs = []
    blobflux = []
    fluximg = coimgs[1]
    for blob in range(1, nblobs + 1):
        blobsrcs.append(np.flatnonzero(T.blob == blob))
        bslc = blobslices[blob - 1]
        blobflux.append(np.sum(fluximg[bslc][blobs[bslc] == blob]))

    # Fit the SDSS sources

    for tim in tims:
        tim.psfex.fitSavedData(*tim.psfex.splinedata)
        tim.psf = tim.psfex

    # How far down to render model profiles
    minsigma = 0.1
    for tim in tims:
        tim.modelMinval = minsigma * tim.sig1
    srcvariances = [[] for src in cat]
    # Fit in order of flux
    for blobnumber, iblob in enumerate(np.argsort(-np.array(blobflux))):

        bslc = blobslices[iblob]
        Isrcs = blobsrcs[iblob]
        if len(Isrcs) == 0:
            continue

        print()
        print('Blob', blobnumber, 'of', len(blobflux), ':', len(Isrcs),
              'sources')
        print('Source indices:', Isrcs)
        print()

        # blob bbox in target coords
        sy, sx = bslc
        by0, by1 = sy.start, sy.stop
        bx0, bx1 = sx.start, sx.stop
        blobh, blobw = by1 - by0, bx1 - bx0

        rr, dd = targetwcs.pixelxy2radec([bx0, bx0, bx1, bx1],
                                         [by0, by1, by1, by0])
        alphas = [0.1, 0.3, 1.0]
        subtims = []
        for itim, tim in enumerate(tims):
            h, w = tim.shape
            ok, x, y = tim.subwcs.radec2pixelxy(rr, dd)
            sx0, sx1 = x.min(), x.max()
            sy0, sy1 = y.min(), y.max()
            if sx1 < 0 or sy1 < 0 or sx1 > w or sy1 > h:
                continue
            sx0 = np.clip(int(np.floor(sx0)), 0, w - 1)
            sx1 = np.clip(int(np.ceil(sx1)), 0, w - 1) + 1
            sy0 = np.clip(int(np.floor(sy0)), 0, h - 1)
            sy1 = np.clip(int(np.ceil(sy1)), 0, h - 1) + 1
            subslc = slice(sy0, sy1), slice(sx0, sx1)
            subimg = tim.getImage()[subslc]
            subie = tim.getInvError()[subslc]
            subwcs = tim.getWcs().copy()
            ox0, oy0 = orig_wcsxy0[itim]
            subwcs.setX0Y0(ox0 + sx0, oy0 + sy0)

            # Mask out inverr for pixels that are not within the blob.
            subtarget = targetwcs.get_subimage(bx0, by0, blobw, blobh)
            subsubwcs = tim.subwcs.get_subimage(int(sx0), int(sy0),
                                                int(sx1 - sx0), int(sy1 - sy0))
            try:
                Yo, Xo, Yi, Xi, rims = resample_with_wcs(
                    subsubwcs, subtarget, [], 2)
            except OverlapError:
                print('No overlap')
                continue
            if len(Yo) == 0:
                continue
            subie2 = np.zeros_like(subie)
            I = np.flatnonzero(blobs[bslc][Yi, Xi] == (iblob + 1))
            subie2[Yo[I], Xo[I]] = subie[Yo[I], Xo[I]]
            subie = subie2
            # If the subimage (blob) is small enough, instantiate a
            # constant PSF model in the center.
            if sy1 - sy0 < 100 and sx1 - sx0 < 100:
                subpsf = tim.psf.mogAt(ox0 + (sx0 + sx1) / 2.,
                                       oy0 + (sy0 + sy1) / 2.)
            else:
                # Otherwise, instantiate a (shifted) spatially-varying
                # PsfEx model.
                subpsf = ShiftedPsf(tim.psf, ox0 + sx0, oy0 + sy0)

            subtim = Image(data=subimg,
                           inverr=subie,
                           wcs=subwcs,
                           psf=subpsf,
                           photocal=tim.getPhotoCal(),
                           sky=tim.getSky(),
                           name=tim.name)
            subtim.band = tim.band
            subtim.sig1 = tim.sig1
            subtim.modelMinval = tim.modelMinval
            subtims.append(subtim)

        subcat = Catalog(*[cat[i] for i in Isrcs])
        subtr = Tractor(subtims, subcat)
        subtr.freezeParam('images')
        # Optimize individual sources in order of flux
        fluxes = []
        for src in subcat:
            # HACK -- here we just *sum* the nanomaggies in each band.  Bogus!
            br = src.getBrightness()
            flux = sum([br.getFlux(band) for band in bands])
            fluxes.append(flux)
        Ibright = np.argsort(-np.array(fluxes))

        if len(Ibright) >= 5:
            # -Remember the original subtim images
            # -Compute initial models for each source (in each tim)
            # -Subtract initial models from images
            # -During fitting, for each source:
            #   -add back in the source's initial model (to each tim)
            #   -fit, with Catalog([src])
            #   -subtract final model (from each tim)
            # -Replace original subtim images
            #
            # --Might want to omit newly-added detection-filter sources, since their
            # fluxes are bogus.

            # Remember original tim images
            orig_timages = [tim.getImage().copy() for tim in subtims]
            initial_models = []
            # Create initial models for each tim x each source
            for tim in subtims:
                mods = []
                for src in subcat:
                    mod = src.getModelPatch(tim)
                    mods.append(mod)
                    if mod is not None:
                        if not np.all(np.isfinite(mod.patch)):
                            print('Non-finite mod patch')
                            print('source:', src)
                            print('tim:', tim)
                            print('PSF:', tim.getPsf())
                        assert (np.all(np.isfinite(mod.patch)))
                        mod.addTo(tim.getImage(), scale=-1)
                initial_models.append(mods)
            # For sources in decreasing order of brightness
            for numi, i in enumerate(Ibright):
                tsrc = Time()
                print('Fitting source', i,
                      '(%i of %i in blob)' % (numi, len(Ibright)))
                src = subcat[i]
                print(src)

                srctractor = Tractor(subtims, [src])
                srctractor.freezeParams('images')

                # Add this source's initial model back in.
                for tim, mods in zip(subtims, initial_models):
                    mod = mods[i]
                    if mod is not None:
                        mod.addTo(tim.getImage())

                print('Optimizing:', srctractor)
                srctractor.printThawedParams()
                for step in range(50):
                    dlnp, X, alpha = srctractor.optimize(priors=False,
                                                         shared_params=False,
                                                         alphas=alphas)
                    print('dlnp:', dlnp, 'src', src)
                    if dlnp < 0.1:
                        break

                for tim in subtims:
                    mod = src.getModelPatch(tim)
                    if mod is not None:
                        mod.addTo(tim.getImage(), scale=-1)

            for tim, img in zip(subtims, orig_timages):
                tim.data = img

            del orig_timages
            del initial_models
        else:
            # Fit sources one at a time, but don't subtract other models
            subcat.freezeAllParams()
            for numi, i in enumerate(Ibright):
                tsrc = Time()
                print('Fitting source', i,
                      '(%i of %i in blob)' % (numi, len(Ibright)))
                print(subcat[i])
                subcat.freezeAllBut(i)
                print('Optimizing:', subtr)
                subtr.printThawedParams()
                for step in range(10):
                    dlnp, X, alpha = subtr.optimize(priors=False,
                                                    shared_params=False,
                                                    alphas=alphas)
                    print('dlnp:', dlnp)
                    if dlnp < 0.1:
                        break
                print('Fitting source took', Time() - tsrc)
                print(subcat[i])
        if len(Isrcs) > 1 and len(Isrcs) <= 10:
            tfit = Time()
            # Optimize all at once?
            subcat.thawAllParams()
            print('Optimizing:', subtr)
            subtr.printThawedParams()
            for step in range(20):
                dlnp, X, alpha = subtr.optimize(priors=False,
                                                shared_params=False,
                                                alphas=alphas)
                print('dlnp:', dlnp)
                if dlnp < 0.1:
                    break

        # Variances
        subcat.thawAllRecursive()
        subcat.freezeAllParams()
        for isub, srci in enumerate(Isrcs):
            print('Variances for source', srci)
            subcat.thawParam(isub)

            src = subcat[isub]
            print('Source', src)
            print('Params:', src.getParamNames())

            if isinstance(src, (DevGalaxy, ExpGalaxy)):
                src.shape = EllipseE.fromEllipseESoft(src.shape)
            elif isinstance(src, FixedCompositeGalaxy):
                src.shapeExp = EllipseE.fromEllipseESoft(src.shapeExp)
                src.shapeDev = EllipseE.fromEllipseESoft(src.shapeDev)

            print('Converted ellipse:', src)

            allderivs = subtr.getDerivs()
            for iparam, derivs in enumerate(allderivs):
                dchisq = 0
                for deriv, tim in derivs:
                    h, w = tim.shape
                    deriv.clipTo(w, h)
                    ie = tim.getInvError()
                    slc = deriv.getSlice(ie)
                    chi = deriv.patch * ie[slc]
                    dchisq += (chi**2).sum()
                if dchisq == 0.:
                    v = np.nan
                else:
                    v = 1. / dchisq
                srcvariances[srci].append(v)
            assert (len(srcvariances[srci]) == subcat[isub].numberOfParams())
            subcat.freezeParam(isub)

    cat.thawAllRecursive()

    for i, src in enumerate(cat):
        print('Source', i, src)
        print('variances:', srcvariances[i])
        print(len(srcvariances[i]), 'vs', src.numberOfParams())
        if len(srcvariances[i]) != src.numberOfParams():
            # This can happen for sources outside the brick bounds: they never get optimized?
            print('Warning: zeroing variances for source', src)
            srcvariances[i] = [0] * src.numberOfParams()
            if isinstance(src, (DevGalaxy, ExpGalaxy)):
                src.shape = EllipseE.fromEllipseESoft(src.shape)
            elif isinstance(src, FixedCompositeGalaxy):
                src.shapeExp = EllipseE.fromEllipseESoft(src.shapeExp)
                src.shapeDev = EllipseE.fromEllipseESoft(src.shapeDev)
        assert (len(srcvariances[i]) == src.numberOfParams())

    variances = np.hstack(srcvariances)
    assert (len(variances) == cat.numberOfParams())

    return dict(cat=cat, variances=variances)
Пример #7
0
def stage_tune(tims=None,
               cat=None,
               targetwcs=None,
               coimgs=None,
               cons=None,
               bands=None,
               invvars=None,
               brickid=None,
               Tcat=None,
               version_header=None,
               ps=None,
               **kwargs):
    tstage = t0 = Time()
    print('kwargs:', kwargs.keys())

    #print 'invvars:', invvars

    # How far down to render model profiles
    minsigma = 0.1
    for tim in tims:
        tim.modelMinval = minsigma * tim.sig1

    # Caching PSF
    for tim in tims:
        from tractor.psfex import CachingPsfEx
        tim.psfex.radius = 20
        tim.psfex.fitSavedData(*tim.psfex.splinedata)
        tim.psf = CachingPsfEx.fromPsfEx(tim.psfex)

    orig_wcsxy0 = [tim.wcs.getX0Y0() for tim in tims]
    set_source_radii(bands, orig_wcsxy0, tims, cat, minsigma)

    plt.figure(figsize=(10, 10))
    plt.subplots_adjust(left=0.002, right=0.998, bottom=0.002, top=0.998)

    plt.clf()
    rgb = get_rgb(coimgs, bands)
    dimshow(rgb)
    #plt.title('Image')
    ps.savefig()

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > tunebrick/coadd/image-%06i-full.jpg' % (
        tmpfn, brickid)
    os.system(cmd)
    os.unlink(tmpfn)

    pla = dict(ms=5, mew=1)

    ax = plt.axis()
    for i, src in enumerate(cat):
        rd = src.getPosition()
        ok, x, y = targetwcs.radec2pixelxy(rd.ra, rd.dec)
        cc = (0, 1, 0)
        if isinstance(src, PointSource):
            plt.plot(x - 1, y - 1, '+', color=cc, **pla)
        else:
            plt.plot(x - 1, y - 1, 'o', mec=cc, mfc='none', **pla)
        # plt.text(x, y, '%i' % i, color=cc, ha='center', va='bottom')
    plt.axis(ax)
    ps.savefig()

    print('Plots:', Time() - t0)

    # print 'Catalog:'
    # for src in cat:
    #     print '  ', src
    # switch_to_soft_ellipses(cat)

    assert (Catalog(*cat).numberOfParams() == len(invvars))

    keepcat = []
    keepinvvars = []
    iterinvvars = invvars
    ikeep = []
    for i, src in enumerate(cat):
        N = src.numberOfParams()
        iv = iterinvvars[:N]
        iterinvvars = iterinvvars[N:]
        if not np.all(np.isfinite(src.getParams())):
            print('Dropping source:', src)
            continue
        keepcat.append(src)
        keepinvvars.extend(iv)
        #print 'Keep:', src
        #print 'iv:', iv
        #print 'sigma', 1./np.sqrt(np.array(iv))
        ikeep.append(i)
    cat = keepcat
    Tcat.cut(np.array(ikeep))
    invvars = keepinvvars
    print(len(cat), 'sources with finite params')
    assert (Catalog(*cat).numberOfParams() == len(invvars))
    assert (len(iterinvvars) == 0)

    print('Rendering model images...')
    t0 = Time()
    mods = _map(_get_mod, [(tim, cat) for tim in tims])
    print('Getting model images:', Time() - t0)

    wcsW = targetwcs.get_width()
    wcsH = targetwcs.get_height()

    t0 = Time()
    comods = []
    for iband, band in enumerate(bands):
        comod = np.zeros((wcsH, wcsW), np.float32)
        for itim, (tim, mod) in enumerate(zip(tims, mods)):
            if tim.band != band:
                continue
            R = tim_get_resamp(tim, targetwcs)
            if R is None:
                continue
            (Yo, Xo, Yi, Xi) = R
            comod[Yo, Xo] += mod[Yi, Xi]
        comod /= np.maximum(cons[iband], 1)
        comods.append(comod)
    print('Creating model coadd:', Time() - t0)

    plt.clf()
    dimshow(get_rgb(comods, bands))
    plt.title('Model')
    ps.savefig()
    del comods

    t0 = Time()
    keepinvvars = []
    keepcat = []
    iterinvvars = invvars
    ikeep = []
    for isrc, src in enumerate(cat):
        newiv = None
        N = src.numberOfParams()

        gc = get_galaxy_cache()
        print('Galaxy cache:', gc)
        if gc is not None:
            gc.clear()

        print('Checking source', isrc, 'of', len(cat), ':', src)
        #print 'N params:', N
        #print 'iterinvvars:', len(iterinvvars)

        oldiv = iterinvvars[:N]
        iterinvvars = iterinvvars[N:]
        recompute_iv = False

        if isinstance(src, FixedCompositeGalaxy):
            # Obvious simplification: for composite galaxies with fracdev
            # out of bounds, convert to exp or dev.
            f = src.fracDev.getClippedValue()
            if f == 0.:
                oldsrc = src
                src = ExpGalaxy(oldsrc.pos, oldsrc.brightness, oldsrc.shapeExp)
                print('Converted comp to exp')
                #print '   ', oldsrc
                #print ' ->', src
                # pull out the invvar elements!
                pp = src.getParams()
                oldsrc.setParams(oldiv)
                newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams(
                ) + oldsrc.shapeExp.getParams()
                src.setParams(pp)
            elif f == 1.:
                oldsrc = src
                src = DevGalaxy(oldsrc.pos, oldsrc.brightness, oldsrc.shapeDev)
                print('Converted comp to dev')
                ##print '   ', oldsrc
                print(' ->', src)
                pp = src.getParams()
                oldsrc.setParams(oldiv)
                newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams(
                ) + oldsrc.shapeDev.getParams()
                src.setParams(pp)

        # treated_as_pointsource: do the bright-star check at least!
        if not isinstance(src, PointSource):
            # This is the check we use in unWISE
            if src.getBrightness().getMag('r') < 12.5:
                oldsrc = src
                src = PointSource(oldsrc.pos, oldsrc.brightness)
                print('Bright star: replacing', oldsrc)
                print('With', src)
                # Not QUITE right.
                #oldsrc.setParams(oldiv)
                #newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams()
                recompute_iv = True

        #print 'Try removing source:', src
        tsrc = Time()

        srcmodlist = []
        for itim, tim in enumerate(tims):
            patch = src.getModelPatch(tim)
            if patch is None:
                continue
            if patch.patch is None:
                continue

            # HACK -- this shouldn't be necessary, but seems to be!
            # FIXME -- track down why patches are being made with extent outside
            # that of the parent!
            H, W = tim.shape
            if patch.x0 < 0 or patch.y0 < 0 or patch.x1 > W or patch.y1 > H:
                print('Warning: Patch extends outside tim bounds:')
                print('patch extent:', patch.getExtent())
                print('image size:', W, 'x', H)
            patch.clipTo(W, H)
            ph, pw = patch.shape
            if pw * ph == 0:
                continue
            srcmodlist.append((itim, patch))

        # Try removing the source from the model;
        # check chi-squared change in the patches.
        sdlnp = 0.
        for itim, patch in srcmodlist:
            tim = tims[itim]
            mod = mods[itim]
            slc = patch.getSlice(tim)
            simg = tim.getImage()[slc]
            sie = tim.getInvError()[slc]
            chisq0 = np.sum(((simg - mod[slc]) * sie)**2)
            chisq1 = np.sum(((simg - (mod[slc] - patch.patch)) * sie)**2)
            sdlnp += -0.5 * (chisq1 - chisq0)
        print('Removing source: dlnp =', sdlnp)
        print('Testing source removal:', Time() - tsrc)

        if sdlnp > 0:
            #print 'Removing source!'
            for itim, patch in srcmodlist:
                patch.addTo(mods[itim], scale=-1)
            continue

        # Try some model changes...
        newsrcs = []
        if isinstance(src, FixedCompositeGalaxy):
            newsrcs.append(ExpGalaxy(src.pos, src.brightness, src.shapeExp))
            newsrcs.append(DevGalaxy(src.pos, src.brightness, src.shapeDev))
            newsrcs.append(PointSource(src.pos, src.brightness))
        elif isinstance(src, (DevGalaxy, ExpGalaxy)):
            newsrcs.append(PointSource(src.pos, src.brightness))

        bestnew = None
        bestdlnp = 0.
        bestdpatches = None

        srcmodlist2 = [None for tim in tims]
        for itim, patch in srcmodlist:
            srcmodlist2[itim] = patch

        for newsrc in newsrcs:

            dpatches = []
            dlnp = 0.
            for itim, tim in enumerate(tims):
                patch = newsrc.getModelPatch(tim)
                if patch is not None:
                    if patch.patch is None:
                        patch = None
                if patch is not None:
                    # HACK -- this shouldn't be necessary, but seems to be!
                    # FIXME -- track down why patches are being made with extent outside
                    # that of the parent!
                    H, W = tim.shape
                    patch.clipTo(W, H)
                    ph, pw = patch.shape
                    if pw * ph == 0:
                        patch = None

                oldpatch = srcmodlist2[itim]
                if oldpatch is None and patch is None:
                    continue

                # Find difference in models
                if oldpatch is None:
                    dpatch = patch
                elif patch is None:
                    dpatch = oldpatch * -1.
                else:
                    dpatch = patch - oldpatch
                dpatches.append((itim, dpatch))

                mod = mods[itim]
                slc = dpatch.getSlice(tim)
                simg = tim.getImage()[slc]
                sie = tim.getInvError()[slc]
                chisq0 = np.sum(((simg - mod[slc]) * sie)**2)
                chisq1 = np.sum(((simg - (mod[slc] + dpatch.patch)) * sie)**2)
                dlnp += -0.5 * (chisq1 - chisq0)

            #print 'Trying source change:'
            #print 'from', src
            #print '  to', newsrc
            print('Trying source change to',
                  type(newsrc).__name__, ': dlnp =', dlnp)

            if dlnp >= bestdlnp:
                bestnew = newsrc
                bestdlnp = dlnp
                bestdpatches = dpatches

        if bestnew is not None:
            print('Found model improvement!  Switching to', end=' ')
            print(bestnew)
            for itim, dpatch in bestdpatches:
                dpatch.addTo(mods[itim])
            src = bestnew
            recompute_iv = True

        del srcmodlist
        del srcmodlist2

        if recompute_iv:
            dchisqs = np.zeros(src.numberOfParams())
            for tim in tims:
                derivs = src.getParamDerivatives(tim)
                h, w = tim.shape
                ie = tim.getInvError()
                for i, deriv in enumerate(derivs):
                    if deriv is None:
                        continue
                    deriv.clipTo(w, h)
                    slc = deriv.getSlice(ie)
                    chi = deriv.patch * ie[slc]
                    dchisqs[i] += (chi**2).sum()
            newiv = dchisqs

        if newiv is None:
            keepinvvars.append(oldiv)
        else:
            keepinvvars.append(newiv)

        keepcat.append(src)
        ikeep.append(isrc)
    cat = keepcat
    Tcat.cut(np.array(ikeep))

    gc = get_galaxy_cache()
    print('Galaxy cache:', gc)
    if gc is not None:
        gc.clear()

    assert (len(iterinvvars) == 0)
    keepinvvars = np.hstack(keepinvvars)
    assert (Catalog(*keepcat).numberOfParams() == len(keepinvvars))
    invvars = keepinvvars
    assert (len(cat) == len(Tcat))
    print('Model selection:', Time() - t0)

    t0 = Time()
    # WCS header for these images
    hdr = fitsio.FITSHDR()
    targetwcs.add_to_header(hdr)
    fwa = dict(clobber=True, header=hdr)

    comods = []
    for iband, band in enumerate(bands):
        comod = np.zeros((wcsH, wcsW), np.float32)
        cochi2 = np.zeros((wcsH, wcsW), np.float32)
        coiv = np.zeros((wcsH, wcsW), np.float32)
        detiv = np.zeros((wcsH, wcsW), np.float32)
        for itim, (tim, mod) in enumerate(zip(tims, mods)):
            if tim.band != band:
                continue
            R = tim_get_resamp(tim, targetwcs)
            if R is None:
                continue
            (Yo, Xo, Yi, Xi) = R
            comod[Yo, Xo] += mod[Yi, Xi]
            ie = tim.getInvError()
            cochi2[Yo, Xo] += ((tim.getImage()[Yi, Xi] - mod[Yi, Xi]) *
                               ie[Yi, Xi])**2
            coiv[Yo, Xo] += ie[Yi, Xi]**2

            psfnorm = 1. / (2. * np.sqrt(np.pi) * tim.psf_sigma)
            detsig1 = tim.sig1 / psfnorm
            detiv[Yo, Xo] += (ie[Yi, Xi] > 0) * (1. / detsig1**2)

        comod /= np.maximum(cons[iband], 1)
        comods.append(comod)
        del comod

        fn = 'tunebrick/coadd/chi2-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, cochi2, **fwa)
        del cochi2
        print('Wrote', fn)

        fn = 'tunebrick/coadd/image-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, coimgs[iband], **fwa)
        print('Wrote', fn)
        fitsio.write(fn, coiv, clobber=False)
        print('Appended ivar to', fn)
        del coiv

        fn = 'tunebrick/coadd/depth-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, detiv, **fwa)
        print('Wrote', fn)
        del detiv

        fn = 'tunebrick/coadd/model-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, comods[iband], **fwa)
        print('Wrote', fn)

        fn = 'tunebrick/coadd/nexp-b%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, cons[iband], **fwa)
        print('Wrote', fn)

    plt.clf()
    rgb = get_rgb(comods, bands)
    dimshow(rgb)
    plt.title('Model')
    ps.savefig()
    del comods

    # Plot sources over top
    ax = plt.axis()
    for i, src in enumerate(cat):
        rd = src.getPosition()
        ok, x, y = targetwcs.radec2pixelxy(rd.ra, rd.dec)
        cc = (0, 1, 0)
        if isinstance(src, PointSource):
            plt.plot(x - 1, y - 1, '+', color=cc, **pla)
        else:
            plt.plot(x - 1, y - 1, 'o', mec=cc, mfc='none', **pla)
        # plt.text(x, y, '%i' % i, color=cc, ha='center', va='bottom')
    plt.axis(ax)
    ps.savefig()

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > tunebrick/coadd/model-%06i-full.jpg' % (
        tmpfn, brickid)
    os.system(cmd)
    os.unlink(tmpfn)

    assert (len(cat) == len(Tcat))
    print('Coadd FITS files and plots:', Time() - t0)

    print('Whole stage:', Time() - tstage)

    return dict(cat=cat, Tcat=Tcat, invvars=invvars)
Пример #8
0
def stage_tune(tims=None, cat=None, targetwcs=None, coimgs=None, cons=None,
               bands=None, invvars=None, brickid=None,
               Tcat=None, version_header=None, ps=None, **kwargs):
    tstage = t0 = Time()
    print 'kwargs:', kwargs.keys()

    #print 'invvars:', invvars

    # How far down to render model profiles
    minsigma = 0.1
    for tim in tims:
        tim.modelMinval = minsigma * tim.sig1

    # Caching PSF
    for tim in tims:
        from tractor.psfex import CachingPsfEx
        tim.psfex.radius = 20
        tim.psfex.fitSavedData(*tim.psfex.splinedata)
        tim.psf = CachingPsfEx.fromPsfEx(tim.psfex)

    orig_wcsxy0 = [tim.wcs.getX0Y0() for tim in tims]
    set_source_radii(bands, orig_wcsxy0, tims, cat, minsigma)

    plt.figure(figsize=(10,10))
    plt.subplots_adjust(left=0.002, right=0.998, bottom=0.002, top=0.998)

    plt.clf()
    rgb = get_rgb(coimgs, bands)
    dimshow(rgb)
    #plt.title('Image')
    ps.savefig()

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > tunebrick/coadd/image-%06i-full.jpg' % (tmpfn, brickid)
    os.system(cmd)
    os.unlink(tmpfn)

    pla = dict(ms=5, mew=1)

    ax = plt.axis()
    for i,src in enumerate(cat):
        rd = src.getPosition()
        ok,x,y = targetwcs.radec2pixelxy(rd.ra, rd.dec)
        cc = (0,1,0)
        if isinstance(src, PointSource):
            plt.plot(x-1, y-1, '+', color=cc, **pla)
        else:
            plt.plot(x-1, y-1, 'o', mec=cc, mfc='none', **pla)
        # plt.text(x, y, '%i' % i, color=cc, ha='center', va='bottom')
    plt.axis(ax)
    ps.savefig()

    print 'Plots:', Time()-t0

    # print 'Catalog:'
    # for src in cat:
    #     print '  ', src
    # switch_to_soft_ellipses(cat)

    assert(Catalog(*cat).numberOfParams() == len(invvars))

    keepcat = []
    keepinvvars = []
    iterinvvars = invvars
    ikeep = []
    for i,src in enumerate(cat):
        N = src.numberOfParams()
        iv = iterinvvars[:N]
        iterinvvars = iterinvvars[N:]
        if not np.all(np.isfinite(src.getParams())):
            print 'Dropping source:', src
            continue
        keepcat.append(src)
        keepinvvars.extend(iv)
        #print 'Keep:', src
        #print 'iv:', iv
        #print 'sigma', 1./np.sqrt(np.array(iv))
        ikeep.append(i)
    cat = keepcat
    Tcat.cut(np.array(ikeep))
    invvars = keepinvvars
    print len(cat), 'sources with finite params'
    assert(Catalog(*cat).numberOfParams() == len(invvars))
    assert(len(iterinvvars) == 0)

    print 'Rendering model images...'
    t0 = Time()
    mods = _map(_get_mod, [(tim, cat) for tim in tims])
    print 'Getting model images:', Time()-t0

    wcsW = targetwcs.get_width()
    wcsH = targetwcs.get_height()

    t0 = Time()
    comods = []
    for iband,band in enumerate(bands):
        comod  = np.zeros((wcsH,wcsW), np.float32)
        for itim, (tim,mod) in enumerate(zip(tims, mods)):
            if tim.band != band:
                continue
            R = tim_get_resamp(tim, targetwcs)
            if R is None:
                continue
            (Yo,Xo,Yi,Xi) = R
            comod[Yo,Xo] += mod[Yi,Xi]
        comod  /= np.maximum(cons[iband], 1)
        comods.append(comod)
    print 'Creating model coadd:', Time()-t0

    plt.clf()
    dimshow(get_rgb(comods, bands))
    plt.title('Model')
    ps.savefig()
    del comods

    t0 = Time()
    keepinvvars = []
    keepcat = []
    iterinvvars = invvars
    ikeep = []
    for isrc,src in enumerate(cat):
        newiv = None
        N = src.numberOfParams()

        gc = get_galaxy_cache()
        print 'Galaxy cache:', gc
        if gc is not None:
            gc.clear()

        print 'Checking source', isrc, 'of', len(cat), ':', src
        #print 'N params:', N
        #print 'iterinvvars:', len(iterinvvars)

        oldiv = iterinvvars[:N]
        iterinvvars = iterinvvars[N:]
        recompute_iv = False

        if isinstance(src, FixedCompositeGalaxy):
            # Obvious simplification: for composite galaxies with fracdev
            # out of bounds, convert to exp or dev.
            f = src.fracDev.getClippedValue()
            if f == 0.:
                oldsrc = src
                src = ExpGalaxy(oldsrc.pos, oldsrc.brightness, oldsrc.shapeExp)
                print 'Converted comp to exp'
                #print '   ', oldsrc
                #print ' ->', src
                # pull out the invvar elements!
                pp = src.getParams()
                oldsrc.setParams(oldiv)
                newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams() + oldsrc.shapeExp.getParams()
                src.setParams(pp)
            elif f == 1.:
                oldsrc = src
                src = DevGalaxy(oldsrc.pos, oldsrc.brightness, oldsrc.shapeDev)
                print 'Converted comp to dev'
                ##print '   ', oldsrc
                print ' ->', src
                pp = src.getParams()
                oldsrc.setParams(oldiv)
                newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams() + oldsrc.shapeDev.getParams()
                src.setParams(pp)

        # treated_as_pointsource: do the bright-star check at least!
        if not isinstance(src, PointSource):
            # This is the check we use in unWISE
            if src.getBrightness().getMag('r') < 12.5:
                oldsrc = src
                src = PointSource(oldsrc.pos, oldsrc.brightness)
                print 'Bright star: replacing', oldsrc
                print 'With', src
                # Not QUITE right.
                #oldsrc.setParams(oldiv)
                #newiv = oldsrc.pos.getParams() + oldsrc.brightness.getParams()
                recompute_iv = True

        #print 'Try removing source:', src
        tsrc = Time()

        srcmodlist = []
        for itim,tim in enumerate(tims):
            patch = src.getModelPatch(tim)
            if patch is None:
                continue
            if patch.patch is None:
                continue

            # HACK -- this shouldn't be necessary, but seems to be!
            # FIXME -- track down why patches are being made with extent outside
            # that of the parent!
            H,W = tim.shape
            if patch.x0 < 0 or patch.y0 < 0 or patch.x1 > W or patch.y1 > H:
                print 'Warning: Patch extends outside tim bounds:'
                print 'patch extent:', patch.getExtent()
                print 'image size:', W, 'x', H
            patch.clipTo(W,H)
            ph,pw = patch.shape
            if pw*ph == 0:
                continue
            srcmodlist.append((itim, patch))
    
        # Try removing the source from the model;
        # check chi-squared change in the patches.
        sdlnp = 0.
        for itim,patch in srcmodlist:
            tim = tims[itim]
            mod = mods[itim]
            slc = patch.getSlice(tim)
            simg = tim.getImage()[slc]
            sie  = tim.getInvError()[slc]
            chisq0 = np.sum(((simg - mod[slc]) * sie)**2)
            chisq1 = np.sum(((simg - (mod[slc] - patch.patch)) * sie)**2)
            sdlnp += -0.5 * (chisq1 - chisq0)
        print 'Removing source: dlnp =', sdlnp
        print 'Testing source removal:', Time()-tsrc
    
        if sdlnp > 0:
            #print 'Removing source!'
            for itim,patch in srcmodlist:
                patch.addTo(mods[itim], scale=-1)
            continue

        # Try some model changes...
        newsrcs = []
        if isinstance(src, FixedCompositeGalaxy):
            newsrcs.append(ExpGalaxy(src.pos, src.brightness, src.shapeExp))
            newsrcs.append(DevGalaxy(src.pos, src.brightness, src.shapeDev))
            newsrcs.append(PointSource(src.pos, src.brightness))
        elif isinstance(src, (DevGalaxy, ExpGalaxy)):
            newsrcs.append(PointSource(src.pos, src.brightness))

        bestnew = None
        bestdlnp = 0.
        bestdpatches = None

        srcmodlist2 = [None for tim in tims]
        for itim,patch in srcmodlist:
            srcmodlist2[itim] = patch

        for newsrc in newsrcs:

            dpatches = []
            dlnp = 0.
            for itim,tim in enumerate(tims):
                patch = newsrc.getModelPatch(tim)
                if patch is not None:
                    if patch.patch is None:
                        patch = None
                if patch is not None:
                    # HACK -- this shouldn't be necessary, but seems to be!
                    # FIXME -- track down why patches are being made with extent outside
                    # that of the parent!
                    H,W = tim.shape
                    patch.clipTo(W,H)
                    ph,pw = patch.shape
                    if pw*ph == 0:
                        patch = None

                oldpatch = srcmodlist2[itim]
                if oldpatch is None and patch is None:
                    continue

                # Find difference in models
                if oldpatch is None:
                    dpatch = patch
                elif patch is None:
                    dpatch = oldpatch * -1.
                else:
                    dpatch = patch - oldpatch
                dpatches.append((itim, dpatch))
                
                mod = mods[itim]
                slc = dpatch.getSlice(tim)
                simg = tim.getImage()[slc]
                sie  = tim.getInvError()[slc]
                chisq0 = np.sum(((simg - mod[slc]) * sie)**2)
                chisq1 = np.sum(((simg - (mod[slc] + dpatch.patch)) * sie)**2)
                dlnp += -0.5 * (chisq1 - chisq0)

            #print 'Trying source change:'
            #print 'from', src
            #print '  to', newsrc
            print 'Trying source change to', type(newsrc).__name__, ': dlnp =', dlnp

            if dlnp >= bestdlnp:
                bestnew = newsrc
                bestdlnp = dlnp
                bestdpatches = dpatches

        if bestnew is not None:
            print 'Found model improvement!  Switching to',
            print bestnew
            for itim,dpatch in bestdpatches:
                dpatch.addTo(mods[itim])
            src = bestnew
            recompute_iv = True

        del srcmodlist
        del srcmodlist2

        if recompute_iv:
            dchisqs = np.zeros(src.numberOfParams())
            for tim in tims:
                derivs = src.getParamDerivatives(tim)
                h,w = tim.shape
                ie = tim.getInvError()
                for i,deriv in enumerate(derivs):
                    if deriv is None:
                        continue
                    deriv.clipTo(w,h)
                    slc = deriv.getSlice(ie)
                    chi = deriv.patch * ie[slc]
                    dchisqs[i] += (chi**2).sum()
            newiv = dchisqs

        if newiv is None:
            keepinvvars.append(oldiv)
        else:
            keepinvvars.append(newiv)
    
        keepcat.append(src)
        ikeep.append(isrc)
    cat = keepcat
    Tcat.cut(np.array(ikeep))

    gc = get_galaxy_cache()
    print 'Galaxy cache:', gc
    if gc is not None:
        gc.clear()

    assert(len(iterinvvars) == 0)
    keepinvvars = np.hstack(keepinvvars)
    assert(Catalog(*keepcat).numberOfParams() == len(keepinvvars))
    invvars = keepinvvars
    assert(len(cat) == len(Tcat))
    print 'Model selection:', Time()-t0

    t0 = Time()
    # WCS header for these images
    hdr = fitsio.FITSHDR()
    targetwcs.add_to_header(hdr)
    fwa = dict(clobber=True, header=hdr)

    comods = []
    for iband,band in enumerate(bands):
        comod  = np.zeros((wcsH,wcsW), np.float32)
        cochi2 = np.zeros((wcsH,wcsW), np.float32)
        coiv   = np.zeros((wcsH,wcsW), np.float32)
        detiv   = np.zeros((wcsH,wcsW), np.float32)
        for itim, (tim,mod) in enumerate(zip(tims, mods)):
            if tim.band != band:
                continue
            R = tim_get_resamp(tim, targetwcs)
            if R is None:
                continue
            (Yo,Xo,Yi,Xi) = R
            comod[Yo,Xo] += mod[Yi,Xi]
            ie = tim.getInvError()
            cochi2[Yo,Xo] += ((tim.getImage()[Yi,Xi] - mod[Yi,Xi]) * ie[Yi,Xi])**2
            coiv[Yo,Xo] += ie[Yi,Xi]**2

            psfnorm = 1./(2. * np.sqrt(np.pi) * tim.psf_sigma)
            detsig1 = tim.sig1 / psfnorm
            detiv[Yo,Xo] += (ie[Yi,Xi] > 0) * (1. / detsig1**2)

        comod  /= np.maximum(cons[iband], 1)
        comods.append(comod)
        del comod

        fn = 'tunebrick/coadd/chi2-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, cochi2, **fwa)
        del cochi2
        print 'Wrote', fn

        fn = 'tunebrick/coadd/image-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, coimgs[iband], **fwa)
        print 'Wrote', fn
        fitsio.write(fn, coiv, clobber=False)
        print 'Appended ivar to', fn
        del coiv

        fn = 'tunebrick/coadd/depth-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, detiv, **fwa)
        print 'Wrote', fn
        del detiv

        fn = 'tunebrick/coadd/model-%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, comods[iband], **fwa)
        print 'Wrote', fn

        fn = 'tunebrick/coadd/nexp-b%06i-%s.fits' % (brickid, band)
        fitsio.write(fn, cons[iband], **fwa)
        print 'Wrote', fn

    plt.clf()
    rgb = get_rgb(comods, bands)
    dimshow(rgb)
    plt.title('Model')
    ps.savefig()
    del comods
    
    # Plot sources over top
    ax = plt.axis()
    for i,src in enumerate(cat):
        rd = src.getPosition()
        ok,x,y = targetwcs.radec2pixelxy(rd.ra, rd.dec)
        cc = (0,1,0)
        if isinstance(src, PointSource):
            plt.plot(x-1, y-1, '+', color=cc, **pla)
        else:
            plt.plot(x-1, y-1, 'o', mec=cc, mfc='none', **pla)
        # plt.text(x, y, '%i' % i, color=cc, ha='center', va='bottom')
    plt.axis(ax)
    ps.savefig()

    tmpfn = create_temp(suffix='.png')
    plt.imsave(tmpfn, rgb)
    del rgb
    cmd = 'pngtopnm %s | pnmtojpeg -quality 90 > tunebrick/coadd/model-%06i-full.jpg' % (tmpfn, brickid)
    os.system(cmd)
    os.unlink(tmpfn)

    assert(len(cat) == len(Tcat))
    print 'Coadd FITS files and plots:', Time()-t0

    print 'Whole stage:', Time()-tstage

    return dict(cat=cat, Tcat=Tcat, invvars=invvars)
Пример #9
0
def stage0(**kwargs):
    ps = PlotSequence('cfht')

    decals = CfhtDecals()
    B = decals.get_bricks()
    print 'Bricks:'
    B.about()

    ra,dec = 190.0, 11.0

    #bands = 'ugri'
    bands = 'gri'
    
    B.cut(np.argsort(degrees_between(ra, dec, B.ra, B.dec)))
    print 'Nearest bricks:', B.ra[:5], B.dec[:5], B.brickid[:5]

    brick = B[0]
    pixscale = 0.186
    #W,H = 1024,1024
    #W,H = 2048,2048
    #W,H = 3600,3600
    W,H = 4800,4800

    targetwcs = wcs_for_brick(brick, pixscale=pixscale, W=W, H=H)
    ccdfn = 'cfht-ccds.fits'
    if os.path.exists(ccdfn):
        T = fits_table(ccdfn)
    else:
        T = get_ccd_list()
        T.writeto(ccdfn)
    print len(T), 'CCDs'
    T.cut(ccds_touching_wcs(targetwcs, T))
    print len(T), 'CCDs touching brick'

    T.cut(np.array([b in bands for b in T.filter]))
    print len(T), 'in bands', bands

    ims = []
    for t in T:
        im = CfhtImage(t)
        # magzp = hdr['PHOT_C'] + 2.5 * np.log10(hdr['EXPTIME'])
        # fwhm = t.seeing / (pixscale * 3600)
        # print '-> FWHM', fwhm, 'pix'
        im.seeing = t.seeing
        im.pixscale = t.pixscale
        print 'seeing', t.seeing
        print 'pixscale', im.pixscale*3600, 'arcsec/pix'
        im.run_calibs(t.ra, t.dec, im.pixscale, W=t.width, H=t.height)
        ims.append(im)


    # Read images, clip to ROI
    targetrd = np.array([targetwcs.pixelxy2radec(x,y) for x,y in
                         [(1,1),(W,1),(W,H),(1,H),(1,1)]])
    keepims = []
    tims = []
    for im in ims:
        print
        print 'Reading expnum', im.expnum, 'name', im.extname, 'band', im.band, 'exptime', im.exptime
        band = im.band
        wcs = im.read_wcs()
        imh,imw = wcs.imageh,wcs.imagew
        imgpoly = [(1,1),(1,imh),(imw,imh),(imw,1)]
        ok,tx,ty = wcs.radec2pixelxy(targetrd[:-1,0], targetrd[:-1,1])
        tpoly = zip(tx,ty)
        clip = clip_polygon(imgpoly, tpoly)
        clip = np.array(clip)
        #print 'Clip', clip
        if len(clip) == 0:
            continue
        x0,y0 = np.floor(clip.min(axis=0)).astype(int)
        x1,y1 = np.ceil (clip.max(axis=0)).astype(int)
        slc = slice(y0,y1+1), slice(x0,x1+1)

        ## FIXME -- it seems I got lucky and the cross product is
        ## negative == clockwise, as required by clip_polygon. One
        ## could check this and reverse the polygon vertex order.
        # dx0,dy0 = tx[1]-tx[0], ty[1]-ty[0]
        # dx1,dy1 = tx[2]-tx[1], ty[2]-ty[1]
        # cross = dx0*dy1 - dx1*dy0
        # print 'Cross:', cross

        print 'Image slice: x [%i,%i], y [%i,%i]' % (x0,x1, y0,y1)
        print 'Reading image from', im.imgfn, 'HDU', im.hdu
        img,imghdr = im.read_image(header=True, slice=slc)
        goodpix = (img != 0)
        print 'Number of pixels == 0:', np.sum(img == 0)
        print 'Number of pixels != 0:', np.sum(goodpix)
        if np.sum(goodpix) == 0:
            continue
        # print 'Image shape', img.shape
        print 'Image range', img.min(), img.max()
        print 'Goodpix image range:', (img[goodpix]).min(), (img[goodpix]).max()
        if img[goodpix].min() == img[goodpix].max():
            print 'No dynamic range in image'
            continue
        # print 'Reading invvar from', im.wtfn, 'HDU', im.hdu
        # invvar = im.read_invvar(slice=slc)
        # # print 'Invvar shape', invvar.shape
        # # print 'Invvar range:', invvar.min(), invvar.max()
        # invvar[goodpix == 0] = 0.
        # if np.all(invvar == 0.):
        #     print 'Skipping zero-invvar image'
        #     continue
        # assert(np.all(np.isfinite(img)))
        # assert(np.all(np.isfinite(invvar)))
        # assert(not(np.all(invvar == 0.)))
        # # Estimate per-pixel noise via Blanton's 5-pixel MAD
        # slice1 = (slice(0,-5,10),slice(0,-5,10))
        # slice2 = (slice(5,None,10),slice(5,None,10))
        # # print 'sliced shapes:', img[slice1].shape, img[slice2].shape
        # # print 'good shape:', (goodpix[slice1] * goodpix[slice2]).shape
        # # print 'good values:', np.unique(goodpix[slice1] * goodpix[slice2])
        # # print 'sliced[good] shapes:', (img[slice1] -  img[slice2])[goodpix[slice1] * goodpix[slice2]].shape
        # mad = np.median(np.abs(img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].ravel())
        # sig1 = 1.4826 * mad / np.sqrt(2.)
        # print 'MAD sig1:', sig1
        # # invvar was 1 or 0
        # invvar *= (1./(sig1**2))
        # medsky = np.median(img[goodpix])

        # Read full image for sig1 and sky estimate
        fullimg = im.read_image()
        fullgood = (fullimg != 0)
        # Estimate per-pixel noise via Blanton's 5-pixel MAD
        slice1 = (slice(0,-5,10),slice(0,-5,10))
        slice2 = (slice(5,None,10),slice(5,None,10))
        mad = np.median(np.abs(fullimg[slice1] - fullimg[slice2])[fullgood[slice1] * fullgood[slice2]].ravel())
        sig1 = 1.4826 * mad / np.sqrt(2.)
        print 'MAD sig1:', sig1
        medsky = np.median(fullimg[fullgood])
        invvar = np.zeros_like(img)
        invvar[goodpix] = 1./sig1**2

        # Median-smooth sky subtraction
        plt.clf()
        dimshow(np.round((img-medsky) / sig1), vmin=-3, vmax=5)
        plt.title('Scalar median: %s' % im.name)
        ps.savefig()

        # medsky = np.zeros_like(img)
        # # astrometry.util.util
        # median_smooth(img, np.logical_not(goodpix), 256, medsky)
        fullmed = np.zeros_like(fullimg)
        median_smooth(fullimg - medsky, np.logical_not(fullgood), 256, fullmed)
        fullmed += medsky
        medimg = fullmed[slc]
        
        plt.clf()
        dimshow(np.round((img - medimg) / sig1), vmin=-3, vmax=5)
        plt.title('Median filtered: %s' % im.name)
        ps.savefig()
        
        #print 'Subtracting median:', medsky
        #img -= medsky
        img -= medimg
        
        primhdr = im.read_image_primary_header()

        magzp = decals.get_zeropoint_for(im)
        print 'magzp', magzp
        zpscale = NanoMaggies.zeropointToScale(magzp)
        print 'zpscale', zpscale

        # Scale images to Nanomaggies
        img /= zpscale
        sig1 /= zpscale
        invvar *= zpscale**2
        orig_zpscale = zpscale

        zpscale = 1.
        assert(np.sum(invvar > 0) > 0)
        print 'After scaling:'
        print 'sig1', sig1
        print 'invvar range', invvar.min(), invvar.max()
        print 'image range', img.min(), img.max()

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

        plt.clf()
        lo,hi = -5*sig1, 10*sig1
        n,b,p = plt.hist(img[goodpix].ravel(), 100, range=(lo,hi), histtype='step', color='k')
        xx = np.linspace(lo, hi, 200)
        plt.plot(xx, max(n)*np.exp(-xx**2 / (2.*sig1**2)), 'r-')
        plt.xlim(lo,hi)
        plt.title('Pixel histogram: %s' % im.name)
        ps.savefig()

        twcs = ConstantFitsWcs(wcs)
        if x0 or y0:
            twcs.setX0Y0(x0,y0)

        info = im.get_image_info()
        fullh,fullw = info['dims']

        # read fit PsfEx model
        psfex = PsfEx.fromFits(im.psffitfn)
        print 'Read', psfex

        # HACK -- highly approximate PSF here!
        #psf_fwhm = imghdr['FWHM']
        #psf_fwhm = im.seeing

        psf_fwhm = im.seeing / (im.pixscale * 3600)
        print 'PSF FWHM', psf_fwhm, 'pixels'
        psf_sigma = psf_fwhm / 2.35
        psf = NCircularGaussianPSF([psf_sigma],[1.])

        print 'img type', img.dtype
        
        tim = Image(img, invvar=invvar, wcs=twcs, psf=psf,
                    photocal=LinearPhotoCal(zpscale, band=band),
                    sky=ConstantSky(0.), name=im.name + ' ' + band)
        tim.zr = [-3. * sig1, 10. * sig1]
        tim.sig1 = sig1
        tim.band = band
        tim.psf_fwhm = psf_fwhm
        tim.psf_sigma = psf_sigma
        tim.sip_wcs = wcs
        tim.x0,tim.y0 = int(x0),int(y0)
        tim.psfex = psfex
        tim.imobj = im
        mn,mx = tim.zr
        tim.ima = dict(interpolation='nearest', origin='lower', cmap='gray',
                       vmin=mn, vmax=mx)
        tims.append(tim)
        keepims.append(im)

    ims = keepims

    print 'Computing resampling...'
    # save resampling params
    for tim in tims:
        wcs = tim.sip_wcs
        subh,subw = tim.shape
        subwcs = wcs.get_subimage(tim.x0, tim.y0, subw, subh)
        tim.subwcs = subwcs
        try:
            Yo,Xo,Yi,Xi,rims = resample_with_wcs(targetwcs, subwcs, [], 2)
        except OverlapError:
            print 'No overlap'
            continue
        if len(Yo) == 0:
            continue
        tim.resamp = (Yo,Xo,Yi,Xi)

    print 'Creating coadds...'
    # Produce per-band coadds, for plots
    coimgs = []
    cons = []
    for ib,band in enumerate(bands):
        coimg = np.zeros((H,W), np.float32)
        con   = np.zeros((H,W), np.uint8)
        for tim in tims:
            if tim.band != band:
                continue
            (Yo,Xo,Yi,Xi) = tim.resamp
            if len(Yo) == 0:
                continue
            nn = (tim.getInvvar()[Yi,Xi] > 0)
            coimg[Yo,Xo] += tim.getImage ()[Yi,Xi] * nn
            con  [Yo,Xo] += nn

            # print
            # print 'tim', tim.name
            # print 'number of resampled pix:', len(Yo)
            # reim = np.zeros_like(coimg)
            # ren  = np.zeros_like(coimg)
            # reim[Yo,Xo] = tim.getImage()[Yi,Xi] * nn
            # ren[Yo,Xo] = nn
            # print 'number of resampled pix with positive invvar:', ren.sum()
            # plt.clf()
            # plt.subplot(2,2,1)
            # mn,mx = [np.percentile(reim[ren>0], p) for p in [25,95]]
            # print 'Percentiles:', mn,mx
            # dimshow(reim, vmin=mn, vmax=mx)
            # plt.colorbar()
            # plt.subplot(2,2,2)
            # dimshow(con)
            # plt.colorbar()
            # plt.subplot(2,2,3)
            # dimshow(reim, vmin=tim.zr[0], vmax=tim.zr[1])
            # plt.colorbar()
            # plt.subplot(2,2,4)
            # plt.hist(reim.ravel(), 100, histtype='step', color='b')
            # plt.hist(tim.getImage().ravel(), 100, histtype='step', color='r')
            # plt.suptitle('%s: %s' % (band, tim.name))
            # ps.savefig()

        coimg /= np.maximum(con,1)
        coimgs.append(coimg)
        cons  .append(con)

    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ps.savefig()

    plt.clf()
    for i,b in enumerate(bands):
        plt.subplot(2,2,i+1)
        dimshow(cons[i], ticks=False)
        plt.title('%s band' % b)
        plt.colorbar()
    plt.suptitle('Number of exposures')
    ps.savefig()

    print 'Grabbing SDSS sources...'
    bandlist = [b for b in bands]
    cat,T = get_sdss_sources(bandlist, targetwcs)
    # record coordinates in target brick image
    ok,T.tx,T.ty = targetwcs.radec2pixelxy(T.ra, T.dec)
    T.tx -= 1
    T.ty -= 1
    T.itx = np.clip(np.round(T.tx).astype(int), 0, W-1)
    T.ity = np.clip(np.round(T.ty).astype(int), 0, H-1)

    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ax = plt.axis()
    plt.plot(T.tx, T.ty, 'o', mec=green, mfc='none', ms=10, mew=1.5)
    plt.axis(ax)
    plt.title('SDSS sources')
    ps.savefig()

    print 'Detmaps...'
    # Render the detection maps
    detmaps = dict([(b, np.zeros((H,W), np.float32)) for b in bands])
    detivs  = dict([(b, np.zeros((H,W), np.float32)) for b in bands])
    for tim in tims:
        iv = tim.getInvvar()
        psfnorm = 1./(2. * np.sqrt(np.pi) * tim.psf_sigma)
        detim = tim.getImage().copy()
        detim[iv == 0] = 0.
        detim = gaussian_filter(detim, tim.psf_sigma) / psfnorm**2
        detsig1 = tim.sig1 / psfnorm
        subh,subw = tim.shape
        detiv = np.zeros((subh,subw), np.float32) + (1. / detsig1**2)
        detiv[iv == 0] = 0.
        (Yo,Xo,Yi,Xi) = tim.resamp
        detmaps[tim.band][Yo,Xo] += detiv[Yi,Xi] * detim[Yi,Xi]
        detivs [tim.band][Yo,Xo] += detiv[Yi,Xi]

    rtn = dict()
    for k in ['T', 'coimgs', 'cons', 'detmaps', 'detivs',
              'targetrd', 'pixscale', 'targetwcs', 'W','H',
              'bands', 'tims', 'ps', 'brick', 'cat']:
        rtn[k] = locals()[k]
    return rtn
Пример #10
0
def stage1(T=None, coimgs=None, cons=None, detmaps=None, detivs=None,
           targetrd=None, pixscale=None, targetwcs=None, W=None,H=None,
           bands=None, tims=None, ps=None, brick=None, cat=None):
    orig_wcsxy0 = [tim.wcs.getX0Y0() for tim in tims]
    hot = np.zeros((H,W), np.float32)

    for band in bands:
        detmap = detmaps[band] / np.maximum(1e-16, detivs[band])
        detsn = detmap * np.sqrt(detivs[band])
        hot = np.maximum(hot, detsn)
        detmaps[band] = detmap

    ### FIXME -- ugri
    for sedname,sed in [('Flat', (1.,1.,1.)), ('Red', (2.5, 1.0, 0.4))]:
        sedmap = np.zeros((H,W), np.float32)
        sediv  = np.zeros((H,W), np.float32)
        for iband,band in enumerate(bands):
            # We convert the detmap to canonical band via
            #   detmap * w
            # And the corresponding change to sig1 is
            #   sig1 * w
            # So the invvar-weighted sum is
            #    (detmap * w) / (sig1**2 * w**2)
            #  = detmap / (sig1**2 * w)
            sedmap += detmaps[band] * detivs[band] / sed[iband]
            sediv  += detivs [band] / sed[iband]**2
        sedmap /= np.maximum(1e-16, sediv)
        sedsn   = sedmap * np.sqrt(sediv)
        hot = np.maximum(hot, sedsn)

        plt.clf()
        dimshow(np.round(sedsn), vmin=0, vmax=10, cmap='hot')
        plt.title('SED-matched detection filter: %s' % sedname)
        ps.savefig()

    peaks = (hot > 4)
    blobs,nblobs = label(peaks)
    print 'N detected blobs:', nblobs
    blobslices = find_objects(blobs)
    # Un-set catalog blobs
    for x,y in zip(T.itx, T.ity):
        # blob number
        bb = blobs[y,x]
        if bb == 0:
            continue
        # un-set 'peaks' within this blob
        slc = blobslices[bb-1]
        peaks[slc][blobs[slc] == bb] = 0

    # Now, after having removed catalog sources, crank up the detection threshold
    peaks &= (hot > 5)
        
    # zero out the edges(?)
    peaks[0 ,:] = peaks[:, 0] = 0
    peaks[-1,:] = peaks[:,-1] = 0
    peaks[1:-1, 1:-1] &= (hot[1:-1,1:-1] >= hot[0:-2,1:-1])
    peaks[1:-1, 1:-1] &= (hot[1:-1,1:-1] >= hot[2:  ,1:-1])
    peaks[1:-1, 1:-1] &= (hot[1:-1,1:-1] >= hot[1:-1,0:-2])
    peaks[1:-1, 1:-1] &= (hot[1:-1,1:-1] >= hot[1:-1,2:  ])

    # These are our peaks
    pki = np.flatnonzero(peaks)
    peaky,peakx = np.unravel_index(pki, peaks.shape)
    print len(peaky), 'peaks'

    crossa = dict(ms=10, mew=1.5)
    plt.clf()
    dimshow(get_rgb(coimgs, bands))
    ax = plt.axis()
    plt.plot(T.tx, T.ty, 'r+', **crossa)
    plt.plot(peakx, peaky, '+', color=green, **crossa)
    plt.axis(ax)
    plt.title('SDSS + SED-matched detections')
    ps.savefig()


    ### HACK -- high threshold again

    # Segment, and record which sources fall into each blob
    blobs,nblobs = label((hot > 20))
    print 'N detected blobs:', nblobs
    blobslices = find_objects(blobs)
    T.blob = blobs[T.ity, T.itx]
    blobsrcs = []
    blobflux = []
    fluximg = coimgs[1]
    for blob in range(1, nblobs+1):
        blobsrcs.append(np.flatnonzero(T.blob == blob))
        bslc = blobslices[blob-1]
        blobflux.append(np.sum(fluximg[bslc][blobs[bslc] == blob]))

    # Fit the SDSS sources
    
    for tim in tims:
        tim.psfex.fitSavedData(*tim.psfex.splinedata)
        tim.psf = tim.psfex
        
    # How far down to render model profiles
    minsigma = 0.1
    for tim in tims:
        tim.modelMinval = minsigma * tim.sig1
    srcvariances = [[] for src in cat]
    # Fit in order of flux
    for blobnumber,iblob in enumerate(np.argsort(-np.array(blobflux))):

        bslc  = blobslices[iblob]
        Isrcs = blobsrcs  [iblob]
        if len(Isrcs) == 0:
            continue

        print
        print 'Blob', blobnumber, 'of', len(blobflux), ':', len(Isrcs), 'sources'
        print 'Source indices:', Isrcs
        print

        # blob bbox in target coords
        sy,sx = bslc
        by0,by1 = sy.start, sy.stop
        bx0,bx1 = sx.start, sx.stop
        blobh,blobw = by1 - by0, bx1 - bx0

        rr,dd = targetwcs.pixelxy2radec([bx0,bx0,bx1,bx1],[by0,by1,by1,by0])
        alphas = [0.1, 0.3, 1.0]
        subtims = []
        for itim,tim in enumerate(tims):
            h,w = tim.shape
            ok,x,y = tim.subwcs.radec2pixelxy(rr,dd)
            sx0,sx1 = x.min(), x.max()
            sy0,sy1 = y.min(), y.max()
            if sx1 < 0 or sy1 < 0 or sx1 > w or sy1 > h:
                continue
            sx0 = np.clip(int(np.floor(sx0)), 0, w-1)
            sx1 = np.clip(int(np.ceil (sx1)), 0, w-1) + 1
            sy0 = np.clip(int(np.floor(sy0)), 0, h-1)
            sy1 = np.clip(int(np.ceil (sy1)), 0, h-1) + 1
            subslc = slice(sy0,sy1),slice(sx0,sx1)
            subimg = tim.getImage ()[subslc]
            subie  = tim.getInvError()[subslc]
            subwcs = tim.getWcs().copy()
            ox0,oy0 = orig_wcsxy0[itim]
            subwcs.setX0Y0(ox0 + sx0, oy0 + sy0)

            # Mask out inverr for pixels that are not within the blob.
            subtarget = targetwcs.get_subimage(bx0, by0, blobw, blobh)
            subsubwcs = tim.subwcs.get_subimage(int(sx0), int(sy0), int(sx1-sx0), int(sy1-sy0))
            try:
                Yo,Xo,Yi,Xi,rims = resample_with_wcs(subsubwcs, subtarget, [], 2)
            except OverlapError:
                print 'No overlap'
                continue
            if len(Yo) == 0:
                continue
            subie2 = np.zeros_like(subie)
            I = np.flatnonzero(blobs[bslc][Yi, Xi] == (iblob+1))
            subie2[Yo[I],Xo[I]] = subie[Yo[I],Xo[I]]
            subie = subie2
            # If the subimage (blob) is small enough, instantiate a
            # constant PSF model in the center.
            if sy1-sy0 < 100 and sx1-sx0 < 100:
                subpsf = tim.psf.mogAt(ox0 + (sx0+sx1)/2., oy0 + (sy0+sy1)/2.)
            else:
                # Otherwise, instantiate a (shifted) spatially-varying
                # PsfEx model.
                subpsf = ShiftedPsf(tim.psf, ox0+sx0, oy0+sy0)

            subtim = Image(data=subimg, inverr=subie, wcs=subwcs,
                           psf=subpsf, photocal=tim.getPhotoCal(),
                           sky=tim.getSky(), name=tim.name)
            subtim.band = tim.band
            subtim.sig1 = tim.sig1
            subtim.modelMinval = tim.modelMinval
            subtims.append(subtim)

        subcat = Catalog(*[cat[i] for i in Isrcs])
        subtr = Tractor(subtims, subcat)
        subtr.freezeParam('images')
        # Optimize individual sources in order of flux
        fluxes = []
        for src in subcat:
            # HACK -- here we just *sum* the nanomaggies in each band.  Bogus!
            br = src.getBrightness()
            flux = sum([br.getFlux(band) for band in bands])
            fluxes.append(flux)
        Ibright = np.argsort(-np.array(fluxes))

        if len(Ibright) >= 5:
            # -Remember the original subtim images
            # -Compute initial models for each source (in each tim)
            # -Subtract initial models from images
            # -During fitting, for each source:
            #   -add back in the source's initial model (to each tim)
            #   -fit, with Catalog([src])
            #   -subtract final model (from each tim)
            # -Replace original subtim images
            #
            # --Might want to omit newly-added detection-filter sources, since their
            # fluxes are bogus.

            # Remember original tim images
            orig_timages = [tim.getImage().copy() for tim in subtims]
            initial_models = []
            # Create initial models for each tim x each source
            for tim in subtims:
                mods = []
                for src in subcat:
                    mod = src.getModelPatch(tim)
                    mods.append(mod)
                    if mod is not None:
                        if not np.all(np.isfinite(mod.patch)):
                            print 'Non-finite mod patch'
                            print 'source:', src
                            print 'tim:', tim
                            print 'PSF:', tim.getPsf()
                        assert(np.all(np.isfinite(mod.patch)))
                        mod.addTo(tim.getImage(), scale=-1)
                initial_models.append(mods)
            # For sources in decreasing order of brightness
            for numi,i in enumerate(Ibright):
                tsrc = Time()
                print 'Fitting source', i, '(%i of %i in blob)' % (numi, len(Ibright))
                src = subcat[i]
                print src

                srctractor = Tractor(subtims, [src])
                srctractor.freezeParams('images')
                
                # Add this source's initial model back in.
                for tim,mods in zip(subtims, initial_models):
                    mod = mods[i]
                    if mod is not None:
                        mod.addTo(tim.getImage())

                print 'Optimizing:', srctractor
                srctractor.printThawedParams()
                for step in range(50):
                    dlnp,X,alpha = srctractor.optimize(priors=False, shared_params=False,
                                                  alphas=alphas)
                    print 'dlnp:', dlnp, 'src', src
                    if dlnp < 0.1:
                        break

                for tim in subtims:
                    mod = src.getModelPatch(tim)
                    if mod is not None:
                        mod.addTo(tim.getImage(), scale=-1)
    
            for tim,img in zip(subtims, orig_timages):
                tim.data = img

            del orig_timages
            del initial_models
        else:
            # Fit sources one at a time, but don't subtract other models
            subcat.freezeAllParams()
            for numi,i in enumerate(Ibright):
                tsrc = Time()
                print 'Fitting source', i, '(%i of %i in blob)' % (numi, len(Ibright))
                print subcat[i]
                subcat.freezeAllBut(i)
                print 'Optimizing:', subtr
                subtr.printThawedParams()
                for step in range(10):
                    dlnp,X,alpha = subtr.optimize(priors=False, shared_params=False,
                                                  alphas=alphas)
                    print 'dlnp:', dlnp
                    if dlnp < 0.1:
                        break
                print 'Fitting source took', Time()-tsrc
                print subcat[i]
        if len(Isrcs) > 1 and len(Isrcs) <= 10:
            tfit = Time()
            # Optimize all at once?
            subcat.thawAllParams()
            print 'Optimizing:', subtr
            subtr.printThawedParams()
            for step in range(20):
                dlnp,X,alpha = subtr.optimize(priors=False, shared_params=False,
                                              alphas=alphas)
                print 'dlnp:', dlnp
                if dlnp < 0.1:
                    break

        # Variances
        subcat.thawAllRecursive()
        subcat.freezeAllParams()
        for isub,srci in enumerate(Isrcs):
            print 'Variances for source', srci
            subcat.thawParam(isub)

            src = subcat[isub]
            print 'Source', src
            print 'Params:', src.getParamNames()
            
            if isinstance(src, (DevGalaxy, ExpGalaxy)):
                src.shape = EllipseE.fromEllipseESoft(src.shape)
            elif isinstance(src, FixedCompositeGalaxy):
                src.shapeExp = EllipseE.fromEllipseESoft(src.shapeExp)
                src.shapeDev = EllipseE.fromEllipseESoft(src.shapeDev)

            print 'Converted ellipse:', src

            allderivs = subtr.getDerivs()
            for iparam,derivs in enumerate(allderivs):
                dchisq = 0
                for deriv,tim in derivs:
                    h,w = tim.shape
                    deriv.clipTo(w,h)
                    ie = tim.getInvError()
                    slc = deriv.getSlice(ie)
                    chi = deriv.patch * ie[slc]
                    dchisq += (chi**2).sum()
                if dchisq == 0.:
                    v = np.nan
                else:
                    v = 1./dchisq
                srcvariances[srci].append(v)
            assert(len(srcvariances[srci]) == subcat[isub].numberOfParams())
            subcat.freezeParam(isub)

    cat.thawAllRecursive()

    for i,src in enumerate(cat):
        print 'Source', i, src
        print 'variances:', srcvariances[i]
        print len(srcvariances[i]), 'vs', src.numberOfParams()
        if len(srcvariances[i]) != src.numberOfParams():
            # This can happen for sources outside the brick bounds: they never get optimized?
            print 'Warning: zeroing variances for source', src
            srcvariances[i] = [0]*src.numberOfParams()
            if isinstance(src, (DevGalaxy, ExpGalaxy)):
                src.shape = EllipseE.fromEllipseESoft(src.shape)
            elif isinstance(src, FixedCompositeGalaxy):
                src.shapeExp = EllipseE.fromEllipseESoft(src.shapeExp)
                src.shapeDev = EllipseE.fromEllipseESoft(src.shapeDev)
        assert(len(srcvariances[i]) == src.numberOfParams())

    variances = np.hstack(srcvariances)
    assert(len(variances) == cat.numberOfParams())

    return dict(cat=cat, variances=variances)