Exemplo n.º 1
0
def Initial_PSF(FWHM, double=False):

    # NB. FWHM of PSF is given in pixels.

    if not double:
        # Single Gaussian default:
        w = np.array([1.0])  # amplitude at peak
        mu = np.array([[0.0, 0.0]])  # centroid position in pixels
        var = (FWHM / 2.35)**2.0
        cov = np.array([[[var, 0.0], [0.0,
                                      var]]])  # pixels^2, covariance matrix

    else:
        # Double Gaussian alternative:
        w = np.array([1.0, 1.0])
        mu = np.array([[0.0, 0.0], [0.0, 0.0]])
        var = (FWHM / 2.35)**2.0
        cov = np.array([[[1.0, 0.0], [0.0, 1.0]], [[var, 0.0], [0.0, var]]])

    return tractor.GaussianMixturePSF(w, mu, cov)
Exemplo n.º 2
0
    def fit_general_gaussian(self,
                             img,
                             sig1,
                             xi,
                             yi,
                             fluxi,
                             psf_r=15,
                             ps=None):
        import tractor
        H, W = img.shape
        ix = int(np.round(xi))
        iy = int(np.round(yi))
        xlo = max(0, ix - psf_r)
        xhi = min(W, ix + psf_r + 1)
        ylo = max(0, iy - psf_r)
        yhi = min(H, iy + psf_r + 1)
        xx, yy = np.meshgrid(np.arange(xlo, xhi), np.arange(ylo, yhi))
        r2 = (xx - xi)**2 + (yy - yi)**2
        keep = (r2 < psf_r**2)
        pix = img[ylo:yhi, xlo:xhi].copy()
        ie = np.zeros_like(pix)
        ie[keep] = 1. / sig1

        psf = tractor.NCircularGaussianPSF([4.], [1.])
        tim = tractor.Image(data=pix, inverr=ie, psf=psf)
        src = tractor.PointSource(tractor.PixPos(xi - xlo, yi - ylo),
                                  tractor.Flux(fluxi))
        tr = tractor.Tractor([tim], [src])

        src.pos.addGaussianPrior('x', 0., 1.)

        doplot = (ps is not None)
        if doplot:
            mod0 = tr.getModelImage(0)

        tim.freezeAllBut('psf')
        psf.freezeAllBut('sigmas')

        # print('Optimizing params:')
        # tr.printThawedParams()

        #print('Parameter step sizes:', tr.getStepSizes())
        optargs = dict(priors=False, shared_params=False)
        for step in range(50):
            dlnp, x, alpha = tr.optimize(**optargs)
            if dlnp == 0:
                break

        # Now fit only the PSF size
        tr.freezeParam('catalog')
        # print('Optimizing params:')
        # tr.printThawedParams()

        for step in range(50):
            dlnp, x, alpha = tr.optimize(**optargs)
            if dlnp == 0:
                break

        # fwhms.append(psf.sigmas[0] * 2.35 * self.pixscale)

        if doplot:
            mod1 = tr.getModelImage(0)
            chi1 = tr.getChiImage(0)

        # Now switch to a non-isotropic PSF
        s = psf.sigmas[0]
        #print('Isotropic fit sigma', s)
        s = np.clip(s, 1., 5.)
        tim.psf = tractor.GaussianMixturePSF(1., 0., 0., s**2, s**2, 0.)

        #print('Optimizing params:')
        #tr.printThawedParams()

        try:
            for step in range(50):
                dlnp, x, alpha = tr.optimize(**optargs)
                #print('PSF:', tim.psf)
                if dlnp == 0:
                    break
        except:
            import traceback
            print('Error during fitting PSF in a focus frame; not to worry')
            traceback.print_exc()
            print(
                '(The above was just an error during fitting one star in a focus frame; not to worry.)'
            )

        # Don't need to re-fit source params because PSF ampl and mean
        # can fit for flux and position.

        if doplot:
            mod2 = tr.getModelImage(0)
            chi2 = tr.getChiImage(0)
            kwa = dict(vmin=-3 * sig1, vmax=50 * sig1, cmap='gray')

            plt.clf()
            plt.subplot(2, 3, 1)
            plt.title('Image')
            dimshow(pix, ticks=False, **kwa)
            plt.subplot(2, 3, 2)
            plt.title('Initial model')
            dimshow(mod0, ticks=False, **kwa)
            plt.subplot(2, 3, 3)
            plt.title('Isotropic model')
            dimshow(mod1, ticks=False, **kwa)
            plt.subplot(2, 3, 4)
            plt.title('Final model')
            dimshow(mod2, ticks=False, **kwa)
            plt.subplot(2, 3, 5)
            plt.title('Isotropic chi')
            dimshow(chi1, vmin=-10, vmax=10, ticks=False)
            plt.subplot(2, 3, 6)
            plt.title('Final chi')
            dimshow(chi2, vmin=-10, vmax=10, ticks=False)
            plt.suptitle('PSF fit')
            ps.savefig()

        return tim.psf.getParams()[-3:]
Exemplo n.º 3
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.º 4
0
'''
if __name__ == '__main__':
    H, W = 100, 100

    pixscale = 0.262
    ra, dec = 40., 10.
    psf_sigma = 1.4  # pixels
    v = psf_sigma**2

    ps = pixscale / 3600.
    wcs = Tan(ra, dec, W / 2. + 0.5, H / 2. + 0.5, -ps, 0., 0., ps, float(W),
              float(H))

    tim = tractor.Image(data=np.zeros((H, W), np.float32),
                        inverr=np.ones((H, W), np.float32),
                        psf=tractor.GaussianMixturePSF(1., 0., 0., v, v, 0.),
                        wcs=tractor.ConstantFitsWcs(wcs))
    src = RexGalaxy(tractor.RaDecPos(ra, dec), tractor.Flux(100.),
                    LogRadius(0.))

    tr = tractor.Tractor([tim], [src])
    mod = tr.getModelImage(0)

    plt.clf()
    plt.imshow(mod, interpolation='nearest', origin='lower')
    plt.savefig('rex.png')

    # add noise with std 1.
    noisy = mod + np.random.normal(size=mod.shape)
    # make that the tim's data
    tim.data = noisy
Exemplo n.º 5
0
def read_cfht_coadd(imgfn, weightfn, roi=None, radecroi=None, filtermap=None):
    '''
    Given filenames for CFHT coadd image and weight files, produce
    a tractor.Image object.

    *roi*: (x0,x1, y0,y1): a region-of-interest in pixel space;
           returns the subimage [x0,x1), [y0,y1).
    *radecroi*: (ra0, ra1, dec0, dec1): a region-of-interest in RA,Dec space;
           returns the subimage bounding the given RA,Dec box [ra0,ra1], [dec0,dec1].
    *filtermap*: dict, eg,  { 'i.MP9701': 'i' }, to map from the FILTER header keyword to
           a standard filter name.
    '''

    P = pyfits.open(imgfn)
    print 'Read', P[0].data.shape, 'image'
    img = P[0].data
    imgheader = P[0].header

    # WCS: the image file has a WCS header
    # we should be able to do:
    #twcs = tractor.FitsWcs(imgfn)
    # ARGH!  Memory issues reading the file; HACK: copy header...
    f, tempfn = tempfile.mkstemp()
    os.close(f)
    pyfits.writeto(tempfn, None, header=imgheader, clobber=True)
    twcs = tractor.FitsWcs(tempfn)

    # Cut down to the region-of-interest, if given.
    if roi is not None:
        x0, x1, y0, y1 = roi
    elif 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

        # Clip to image size...
        H, W = data.shape
        x0 = max(0, min(x0, W - 1))
        x1 = max(0, min(x1, W))
        y0 = max(0, min(y0, H - 1))
        y1 = max(0, min(y1, H))
        print ' clipped to', x0, x1, y0, y1

    else:
        H, W = img.shape
        x0, x1, y0, y1 = 0, W, 0, H

    if roi is not None or radecroi is not None:
        # Actually cut the pixels
        img = img[y0:y1, x0:x1].copy()
        # Also tell the WCS to apply an offset.
        twcs.setX0Y0(x0, y0)

    print 'Image:', img.shape

    # HACK, tell the WCS how big the image is...
    # (needed because of the previous HACK, copying the header)
    twcs.wcs.set_imagesize(x1 - x0, y1 - y0)
    print twcs

    # Argh, this doesn't work: the files are .fz compressed
    #P = pyfits.open(weightfn)
    #weight = P[1].data[y0:y1, x0:x1]
    # HACK: use "imcopy" to uncompress to a temp file!
    #print 'Writing to temp file', tempfn
    cmd = "imcopy '%s[%i:%i,%i:%i]' '!%s'" % (weightfn, x0 + 1, x1, y0 + 1, y1,
                                              tempfn)
    print 'running', cmd
    os.system(cmd)
    P = pyfits.open(tempfn)
    weight = P[0].data
    print 'Read', weight.shape, 'weight image'

    # PSF model: FAKE IT for now
    tpsf = tractor.GaussianMixturePSF(np.array([0.9, 0.1]), np.zeros((2, 2)),
                                      np.array([1, 2]))

    # SKY level: assume zero
    #sky = np.median(img)
    #print 'Image median value:', sky
    sky = 0.
    tsky = tractor.ConstantSky(sky)

    # Photometric calibration: the FITS header says:
    '''
    FILTER  = 'r.MP9601'           / Filter
    PHOTZP  =               30.000 / photometric zeropoint
    COMMENT AB magnitude = -2.5 * log10(flux) + PHOTZP
    COMMENT r.MP9601=r_SDSS-0.024*(g_SDSS-r_SDSS)
    '''
    # Grab the filter name, and apply the filtermap (if given)
    filter = imgheader['FILTER']
    if filtermap:
        filter = filtermap.get(filter, filter)
    zp = imgheader['PHOTZP']
    # Simple photocal object
    photocal = tractor.MagsPhotoCal(filter, zp)

    # For plotting: find the approximate standard deviation
    #print 'Median weight:', np.median(weight)
    sigma1 = 1. / np.sqrt(np.median(weight))
    zr = np.array([-3, 10]) * sigma1 + sky

    name = 'CFHT ' + imgheader.get('OBJECT', '')

    tim = tractor.Image(data=img,
                        invvar=weight,
                        psf=tpsf,
                        wcs=twcs,
                        sky=tsky,
                        photocal=photocal,
                        name=name,
                        zr=zr)
    tim.extent = [x0, x1, y0, y1]
    return tim
Exemplo n.º 6
0
    brick = B[0]

    tims = []

    for band in bands:
        sky_level_sig, psf_fwhm, zpt, psf_theta, psf_ell = unpack_ccds(
            band=band, index=0)

        ##  Gaussian approx.
        psf_sigma = psf_fwhm / (2. * np.sqrt(2. * np.log(2.)))
        psf_sigma2 = psf_sigma**2.

        psfnorm = 1. / (2. * np.sqrt(np.pi) * psf_sigma)

        psf = tractor.GaussianMixturePSF(1., 0., 0., psf_sigma2, psf_sigma2,
                                         0.)
        ##  psf                                            = gen_psf(psf_fwhm, psf_ell, psf_theta, pixscale, H, W)

        ##
        photcal = tractor.MagsPhotoCal(band, zpt)

        sky_level_sig = tractor.NanoMaggies(**{band: sky_level_sig})
        sky_level_sig = photcal.brightnessToCounts(sky_level_sig)

        noise = np.random.normal(loc=sky_level_sig,
                                 scale=np.sqrt(sky_level_sig),
                                 size=(H, W))

        ##
        tim = tractor.Image(data=np.zeros((H, W), np.float32),
                            inverr=np.ones((H, W), np.float32),