コード例 #1
0
def get_cfht_catalog(mags=['i'], maglim=27., returnTable=False):
    from astrometry.util.pyfits_utils import fits_table
    from tractor import Mags, RaDecPos, PointSource, Images, Catalog
    from tractor.galaxy import DevGalaxy, ExpGalaxy, CompositeGalaxy, GalaxyShape

    T = fits_table(
        '/project/projectdirs/bigboss/data/cs82/W4p1m1_i.V2.7A.swarp.cut.deVexp.fit',
        hdunum=2)
    print 'Read', len(T), 'sources'
    # Cut to ROI
    (ra0, ra1, dec0, dec1) = radecroi
    T.ra = T.alpha_j2000
    T.dec = T.delta_j2000
    T = T[(T.ra > ra0) * (T.ra < ra1) * (T.dec > dec0) * (T.dec < dec1)]
    print 'Cut to', len(T), 'objects in ROI.'

    srcs = Catalog()
    keepi = []
    for i, t in enumerate(T):
        if t.chi2_psf < t.chi2_model and t.mag_psf <= maglim:
            #print 'PSF'
            themag = t.mag_psf
            m = Mags(order=mags, **dict([(k, themag) for k in mags]))
            srcs.append(PointSource(RaDecPos(t.ra, t.dec), m))
            keepi.append(i)
            continue
        if t.mag_disk > maglim and t.mag_spheroid > maglim:
            #print 'Faint'
            continue
        keepi.append(i)
        themag = t.mag_spheroid
        m_exp = Mags(order=mags, **dict([(k, themag) for k in mags]))
        themag = t.mag_disk
        m_dev = Mags(order=mags, **dict([(k, themag) for k in mags]))

        # SPHEROID_REFF [for Sersic index n= 1] = 1.68 * DISK_SCALE
        shape_dev = GalaxyShape(t.disk_scale_world * 1.68 * 3600.,
                                t.disk_aspect_world, t.disk_theta_world + 90.)
        shape_exp = GalaxyShape(t.spheroid_reff_world * 3600.,
                                t.spheroid_aspect_world,
                                t.spheroid_theta_world + 90.)
        pos = RaDecPos(t.alphamodel_j2000, t.deltamodel_j2000)

        if t.mag_disk > maglim and t.mag_spheroid <= maglim:
            #print 'Exp'
            srcs.append(ExpGalaxy(pos, m_exp, shape_exp))
            continue
        if t.mag_disk <= maglim and t.mag_spheroid > maglim:
            #print 'deV'
            srcs.append(DevGalaxy(pos, m_dev, shape_dev))
            continue
        # exp + deV
        srcs.append(CompositeGalaxy(pos, m_exp, shape_exp, m_dev, shape_dev))

    if returnTable:
        import numpy as np
        T.cut(np.array(keepi))
        return srcs, T

    return srcs
コード例 #2
0
ファイル: tut.py プロジェクト: bpartridge/tractor
	def getModelPatch(self, img):
		# We start by rendering the visible lens galaxy.
		patch = self.light.getModelPatch(img)

		# We will use the lens model to predict the quasar's image positions.
		positions,mags = self.mass.getLensedImages(self.light.position, self.quasar)
		# 'positions' should be a list of RaDecPos objects
		# 'mags' should be a list of Mags objects

		for pos,mag,fudge in zip(positions, mags, self.magfudge):
			# For each image of the quasar, we will create a PointSource
			ps = PointSource(pos, mag + fudge)
			# ... and add it to the patch.
			patch += ps.getModelPatch(img)

		return patch
コード例 #3
0
ファイル: tut.py プロジェクト: charlotteaward/tractor-1
    def getModelPatch(self, img):
        # We start by rendering the visible lens galaxy.
        patch = self.light.getModelPatch(img)

        # We will use the lens model to predict the quasar's image positions.
        positions, mags = self.mass.getLensedImages(self.light.position,
                                                    self.quasar)
        # 'positions' should be a list of RaDecPos objects
        # 'mags' should be a list of Mags objects

        for pos, mag, fudge in zip(positions, mags, self.magfudge):
            # For each image of the quasar, we will create a PointSource
            ps = PointSource(pos, mag + fudge)
            # ... and add it to the patch.
            patch += ps.getModelPatch(img)

        return patch
コード例 #4
0
    #x0,y0 = s.ix - margin, s.iy - margin
    x0,y0 = s.x0, s.y0
    slc = (slice(y0, s.iy + margin+1),
           slice(x0, s.ix + margin+1))
    subpsf = tim.psf.constantPsfAt(s.ix, s.iy)
    
    subtim = Image(data=tim.data[slc],
                   inverr=tim.inverr[slc],
                   psf=subpsf, photocal=tim.photocal,
                   name=tim.name + '/star %i' % i)

    flux = NanoMaggies.magToNanomaggies(s.mag)
    print 'Flux:', flux
    flux = max(flux, 1.)
    src = PointSource(PixPos(s.xx - x0, s.yy - y0),
                      NanoMaggies(**{tim.band: flux}))

    tr = Tractor([subtim], [src])
    mod = tr.getModelImage(0)
    #mod = src.getModelImage(tsubtim)
    tractors.append(tr)
    
    resids.append((subtim.data - mod) * (subtim.inverr > 0))
    chis.append((subtim.data - mod) * subtim.inverr)
    
    plt.subplot(R, C, i+1)
    dimshow(mod, **ima)
plt.suptitle('Models for Pan-STARRS stars: ' + tim.name)
ps.savefig()

resa = dict(vmin=-5.*tim.sig1, vmax=5.*tim.sig1, ticks=False)
コード例 #5
0
def run_forced_phot(cat,
                    tim,
                    ceres=True,
                    derivs=False,
                    agn=False,
                    do_forced=True,
                    do_apphot=True,
                    get_model=False,
                    ps=None,
                    timing=False,
                    fixed_also=False,
                    ceres_threads=1):
    '''
    fixed_also: if derivs=True, also run without derivatives and report
    that flux too?
    '''
    if timing:
        tlast = Time()
    if ps is not None:
        import pylab as plt
    opti = None
    forced_kwargs = {}
    if ceres:
        from tractor.ceres_optimizer import CeresOptimizer
        B = 8

        try:
            opti = CeresOptimizer(BW=B, BH=B, threads=ceres_threads)
        except:
            if ceres_threads > 1:
                raise RuntimeError(
                    'ceres_threads requested but not supported by tractor.ceres version'
                )
            opti = CeresOptimizer(BW=B, BH=B)
        #forced_kwargs.update(verbose=True)

    # nsize = 0
    for src in cat:
        # Limit sizes of huge models
        # from tractor.galaxy import ProfileGalaxy
        # if isinstance(src, ProfileGalaxy):
        #     px,py = tim.wcs.positionToPixel(src.getPosition())
        #     h = src._getUnitFluxPatchSize(tim, px, py, tim.modelMinval)
        #     MAXHALF = 128
        #     if h > MAXHALF:
        #         #print('halfsize', h,'for',src,'-> setting to',MAXHALF)
        #         nsize += 1
        #         src.halfsize = MAXHALF

        src.freezeAllBut('brightness')
        src.getBrightness().freezeAllBut(tim.band)
    #print('Limited the size of', nsize, 'large galaxy models')

    if derivs:
        realsrcs = []
        derivsrcs = []
        Iderivs = []
        for i, src in enumerate(cat):
            from tractor import PointSource
            realsrcs.append(src)

            if not isinstance(src, PointSource):
                continue
            Iderivs.append(i)

            brightness_dra = src.getBrightness().copy()
            brightness_ddec = src.getBrightness().copy()
            brightness_dra.setParams(np.zeros(brightness_dra.numberOfParams()))
            brightness_ddec.setParams(
                np.zeros(brightness_ddec.numberOfParams()))
            brightness_dra.freezeAllBut(tim.band)
            brightness_ddec.freezeAllBut(tim.band)

            dsrc = SourceDerivatives(src, [brightness_dra, brightness_ddec],
                                     tim, ps)
            derivsrcs.append(dsrc)
        Iderivs = np.array(Iderivs)

        if fixed_also:
            pass
        else:
            # For convenience, put all the real sources at the front of
            # the list, so we can pull the IVs off the front of the list.
            cat = realsrcs + derivsrcs

    if agn:
        from tractor.galaxy import ExpGalaxy, DevGalaxy, FixedCompositeGalaxy
        from tractor import PointSource
        from legacypipe.survey import SimpleGalaxy, RexGalaxy

        realsrcs = []
        agnsrcs = []
        iagn = []
        for i, src in enumerate(cat):
            realsrcs.append(src)
            ## ??
            if isinstance(src, (SimpleGalaxy, RexGalaxy)):
                #print('Skipping SIMP or REX:', src)
                continue
            if isinstance(src, (ExpGalaxy, DevGalaxy, FixedCompositeGalaxy)):
                iagn.append(i)
                bright = src.getBrightness().copy()
                bright.setParams(np.zeros(bright.numberOfParams()))
                bright.freezeAllBut(tim.band)
                agn = PointSource(src.pos, bright)
                agn.freezeAllBut('brightness')
                #print('Adding "agn"', agn, 'to', src)
                #print('agn params:', agn.getParamNames())
                agnsrcs.append(src)
        iagn = np.array(iagn)
        cat = realsrcs + agnsrcs
        print('Added AGN to', len(iagn), 'galaxies')

    tr = Tractor([tim], cat, optimizer=opti)
    tr.freezeParam('images')
    disable_galaxy_cache()

    F = fits_table()

    if do_forced:

        if timing and (derivs or agn):
            t = Time()
            print('Setting up:', t - tlast)
            tlast = t

        if derivs:
            if fixed_also:
                print('Forced photom with fixed positions:')
                R = tr.optimize_forced_photometry(variance=True,
                                                  fitstats=False,
                                                  shared_params=False,
                                                  priors=False,
                                                  **forced_kwargs)
                F.flux_fixed = np.array([
                    src.getBrightness().getFlux(tim.band) for src in cat
                ]).astype(np.float32)
                N = len(cat)
                F.flux_fixed_ivar = R.IV[:N].astype(np.float32)

                if timing:
                    t = Time()
                    print('Forced photom with fixed positions finished:',
                          t - tlast)
                    tlast = t

                cat = realsrcs + derivsrcs
                tr.setCatalog(Catalog(*cat))
            print('Forced photom with position derivatives:')

        if ps is None and not get_model:
            forced_kwargs.update(wantims=False)

        R = tr.optimize_forced_photometry(variance=True,
                                          fitstats=True,
                                          shared_params=False,
                                          priors=False,
                                          **forced_kwargs)

        if ps is not None or get_model:
            (data, mod, ie, chi, roi) = R.ims1[0]

        if ps is not None:
            ima = dict(vmin=-2. * tim.sig1,
                       vmax=5. * tim.sig1,
                       interpolation='nearest',
                       origin='lower',
                       cmap='gray')
            imchi = dict(interpolation='nearest',
                         origin='lower',
                         vmin=-5,
                         vmax=5,
                         cmap='RdBu')
            plt.clf()
            plt.imshow(data, **ima)
            plt.title('Data: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(mod, **ima)
            plt.title('Model: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(chi, **imchi)
            plt.title('Chi: %s' % tim.name)
            ps.savefig()

            if derivs:
                trx = Tractor([tim], realsrcs)
                trx.freezeParam('images')

                modx = trx.getModelImage(0)
                chix = (data - modx) * tim.getInvError()

                plt.clf()
                plt.imshow(modx, **ima)
                plt.title('Model without derivatives: %s' % tim.name)
                ps.savefig()

                plt.clf()
                plt.imshow(chix, **imchi)
                plt.title('Chi without derivatives: %s' % tim.name)
                ps.savefig()

        if derivs or agn:
            cat = realsrcs
        N = len(cat)

        F.flux = np.array([
            src.getBrightness().getFlux(tim.band) for src in cat
        ]).astype(np.float32)
        F.flux_ivar = R.IV[:N].astype(np.float32)

        F.fracflux = R.fitstats.profracflux[:N].astype(np.float32)
        F.rchisq = R.fitstats.prochi2[:N].astype(np.float32)
        try:
            F.fracmasked = R.fitstats.promasked[:N].astype(np.float32)
        except:
            print(
                'No "fracmasked" available (only in recent Tractor versions)')

        if derivs:
            F.flux_dra = np.zeros(len(F), np.float32)
            F.flux_ddec = np.zeros(len(F), np.float32)
            F.flux_dra[Iderivs] = np.array(
                [src.getParams()[0] for src in derivsrcs]).astype(np.float32)
            F.flux_ddec[Iderivs] = np.array(
                [src.getParams()[1] for src in derivsrcs]).astype(np.float32)
            F.flux_dra_ivar = np.zeros(len(F), np.float32)
            F.flux_ddec_ivar = np.zeros(len(F), np.float32)
            F.flux_dra_ivar[Iderivs] = R.IV[N::2].astype(np.float32)
            F.flux_ddec_ivar[Iderivs] = R.IV[N + 1::2].astype(np.float32)

        if agn:
            F.flux_agn = np.zeros(len(F), np.float32)
            F.flux_agn_ivar = np.zeros(len(F), np.float32)
            F.flux_agn[iagn] = np.array(
                [src.getParams()[0] for src in agnsrcs])
            F.flux_agn_ivar[iagn] = R.IV[N:].astype(np.float32)

        if timing:
            t = Time()
            print('Forced photom:', t - tlast)
            tlast = t

    if do_apphot:
        import photutils

        img = tim.getImage()
        ie = tim.getInvError()
        with np.errstate(divide='ignore'):
            imsigma = 1. / ie
        imsigma[ie == 0] = 0.

        apimg = []
        apimgerr = []

        # Aperture photometry locations
        xxyy = np.vstack(
            [tim.wcs.positionToPixel(src.getPosition()) for src in cat]).T
        apxy = xxyy - 1.

        apertures = apertures_arcsec / tim.wcs.pixel_scale()
        #print('Apertures:', apertures, 'pixels')

        #print('apxy shape', apxy.shape)  # --> (2,N)

        # The aperture photometry routine doesn't like pixel positions outside the image
        H, W = img.shape
        Iap = np.flatnonzero((apxy[0, :] >= 0) * (apxy[1, :] >= 0) *
                             (apxy[0, :] <= W - 1) * (apxy[1, :] <= H - 1))
        print('Aperture photometry for', len(Iap), 'of', len(apxy[0, :]),
              'sources within image bounds')

        for rad in apertures:
            aper = photutils.CircularAperture(apxy[:, Iap], rad)
            p = photutils.aperture_photometry(img, aper, error=imsigma)
            apimg.append(p.field('aperture_sum'))
            apimgerr.append(p.field('aperture_sum_err'))
        ap = np.vstack(apimg).T
        ap[np.logical_not(np.isfinite(ap))] = 0.
        F.apflux = np.zeros((len(F), len(apertures)), np.float32)
        F.apflux[Iap, :] = ap.astype(np.float32)

        apimgerr = np.vstack(apimgerr).T
        apiv = np.zeros(apimgerr.shape, np.float32)
        apiv[apimgerr != 0] = 1. / apimgerr[apimgerr != 0]**2

        F.apflux_ivar = np.zeros((len(F), len(apertures)), np.float32)
        F.apflux_ivar[Iap, :] = apiv
        if timing:
            print('Aperture photom:', Time() - tlast)

    if get_model:
        return F, mod
    return F
コード例 #6
0
def main():
    # Where are the data?
    datadir = os.path.join(os.path.dirname(__file__), 'data-decam')
    name = 'decam-520206-S16'
    imagefn = os.path.join(datadir, '%s-image-sub.fits' % name)
    invvarfn = os.path.join(datadir, '%s-invvar-sub.fits' % name)
    psfexfn = os.path.join(datadir, '%s-psfex.fits' % name)
    catfn = os.path.join(datadir, 'tractor-1816p325-sub.fits')

    # Read the image and inverse-variance maps.
    image = fitsio.read(imagefn)
    invvar = fitsio.read(invvarfn)
    # The DECam inverse-variance maps are unfortunately corrupted
    # by fpack, causing zeros to become negative.  Fix those.
    invvar[invvar < np.median(invvar) * 0.1] = 0.
    H, W = image.shape
    print('Subimage size:', image.shape)

    # For the PSF model, we need to know what subimage region this is:
    subimage_offset = (35, 1465)
    # We also need the calibrated zeropoint.
    zeropoint = 24.7787

    # What filter was this image taken in?  (z)
    prim_header = fitsio.read_header(imagefn)
    band = prim_header['FILTER'].strip()[0]
    print('Band:', band)
    # These DECam images were calibrated so that the zeropoints need
    # an exposure-time factor, so add that in.
    exptime = prim_header['EXPTIME']
    zeropoint += 2.5 * np.log10(exptime)

    # Read the PsfEx model file
    psf = PixelizedPsfEx(psfexfn)
    # Instantiate a constant pixelized PSF at the image center
    # (of the subimage)
    x0, y0 = subimage_offset
    psf = psf.constantPsfAt(x0 + W / 2., y0 + H / 2.)

    # Load the WCS model from the header
    # We convert from the RA---TPV type to RA---SIP
    header = fitsio.read_header(imagefn, ext=1)
    wcsobj = wcs_pv2sip_hdr(header, stepsize=10)

    # We'll just use a rough sky estimate...
    skyval = np.median(image)

    # Create the Tractor Image (tim).
    tim = Image(data=image,
                invvar=invvar,
                psf=psf,
                wcs=ConstantFitsWcs(wcsobj),
                sky=ConstantSky(skyval),
                photocal=LinearPhotoCal(
                    NanoMaggies.zeropointToScale(zeropoint), band=band))

    # Read the official DECaLS DR3 catalog -- it has only two sources in this subimage.
    catalog = fits_table(catfn)
    print('Read', len(catalog), 'sources')
    print('Source types:', catalog.type)

    # Create Tractor sources corresponding to these two catalog
    # entries.

    # In DECaLS, the "SIMP" type is a round Exponential galaxy with a
    # fixed 0.45" radius, but we'll treat it as a general Exp galaxy.

    sources = []
    for c in catalog:
        # Create a "position" object given the catalog RA,Dec
        position = RaDecPos(c.ra, c.dec)
        # Create a "brightness" object; in the catalog, the fluxes are
        # stored in a [ugrizY] array, so pull out the right index
        band_index = 'ugrizY'.index(band)
        flux = c.decam_flux[band_index]
        brightness = NanoMaggies(**{band: flux})

        # Depending on the source classification in the catalog, pull
        # out different fields for the galaxy shape, and for the
        # galaxy type.  The DECaLS catalogs, conveniently, store
        # galaxy shapes as (radius, e1, e2) ellipses.
        if c.type.strip() == 'DEV':
            shape = EllipseE(c.shapedev_r, c.shapedev_e1, c.shapedev_e2)
            galclass = DevGalaxy
        elif c.type.strip() == 'SIMP':
            shape = EllipseE(c.shapeexp_r, c.shapeexp_e1, c.shapeexp_e2)
            galclass = ExpGalaxy
        else:
            assert (False)
        # Create the tractor galaxy object
        source = galclass(position, brightness, shape)
        print('Created', source)
        sources.append(source)

    # Create the Tractor object -- a list of tractor Images and a list of tractor sources.
    tractor = Tractor([tim], sources)

    # Render the initial model image.
    print('Getting initial model...')
    mod = tractor.getModelImage(0)
    make_plot(tim, mod, 'Initial Scene', 'mod0.png')

    # Instantiate a new source at the location of the unmodelled peak.
    print('Adding new source...')
    # Find the peak very naively...
    ipeak = np.argmax((image - mod) * tim.inverr)
    iy, ix = np.unravel_index(ipeak, tim.shape)
    print('Residual peak at', ix, iy)
    # Compute the RA,Dec location of the peak...
    radec = tim.getWcs().pixelToPosition(ix, iy)
    print('RA,Dec', radec)

    # Try modelling it as a point source.
    # We'll initialize the brightness arbitrarily to 1 nanomaggy (= mag 22.5)
    brightness = NanoMaggies(**{band: 1.})
    source = PointSource(radec, brightness)

    # Add it to the catalog!
    tractor.catalog.append(source)

    # Render the new model image with this source added.
    mod = tractor.getModelImage(0)
    make_plot(tim, mod, 'New Source (Before Fit)', 'mod1.png')

    print('Fitting new source...')
    # Now we're going to fit for the properties of the new source we
    # added.
    # We don't want to fit for any of the image calibration properties:
    tractor.freezeParam('images')
    # And we don't (yet) want to fit the existing sources.  The new
    # source is index number 2, so freeze everything else in the catalog.
    tractor.catalog.freezeAllBut(2)

    print('Fitting parameters:')
    tractor.printThawedParams()

    # Do the actual optimization:
    tractor.optimize_loop()

    mod = tractor.getModelImage(0)
    make_plot(tim, mod, 'New Source Fit', 'mod2.png')

    print('Fitting sources simultaneously...')
    # Now let's unfreeze all the sources and fit them simultaneously.
    tractor.catalog.thawAllParams()
    tractor.printThawedParams()

    tractor.optimize_loop()

    mod = tractor.getModelImage(0)
    make_plot(tim, mod, 'Simultaneous Fit', 'mod3.png')
コード例 #7
0
ファイル: forcedphot.py プロジェクト: dmuniesa/tractor
def main():
    import optparse
    from astrometry.util.plotutils import PlotSequence
    from astrometry.util.util import Tan

    parser = optparse.OptionParser(usage='%prog [options] incat.fits out.fits')
    parser.add_option('-r', '--ralo',  dest='ralo',  type=float,
                      help='Minimum RA')
    parser.add_option('-R', '--rahi',  dest='rahi',  type=float,
                      help='Maximum RA')
    parser.add_option('-d', '--declo', dest='declo', type=float,
                      help='Minimum Dec')
    parser.add_option('-D', '--dechi', dest='dechi', type=float,
                      help='Maximum Dec')

    parser.add_option('-b', '--band', dest='bands', action='append', type=int,
                      default=[], help='WISE band to photometer (default: 1,2)')

    parser.add_option('-u', '--unwise', dest='unwise_dir',
                      default='unwise-coadds',
                      help='Directory containing unWISE coadds')

    parser.add_option('--no-ceres', dest='ceres', action='store_false',
                      default=True,
                      help='Use scipy lsqr rather than Ceres Solver?')

    parser.add_option('--ceres-block', '-B', dest='ceresblock', type=int,
                      default=8,
                      help='Ceres image block size (default: %default)')

    parser.add_option('--plots', dest='plots',
                      default=False, action='store_true')
    parser.add_option('--save-fits', dest='save_fits',
                      default=False, action='store_true')

    # parser.add_option('--ellipses', action='store_true',
    #                  help='Assume catalog shapes are ellipse descriptions (not r,ab,phi)')

    # parser.add_option('--ra', help='Center RA')
    # parser.add_option('--dec', help='Center Dec')
    # parser.add_option('--width', help='Degrees width (in RA*cos(Dec))')
    # parser.add_option('--height', help='Degrees height (Dec)')
    opt, args = parser.parse_args()
    if len(args) != 2:
        parser.print_help()
        sys.exit(-1)

    if len(opt.bands) == 0:
        opt.bands = [1, 2]
    # Allow specifying bands like "123"
    bb = []
    for band in opt.bands:
        for s in str(band):
            bb.append(int(s))
    opt.bands = bb
    print('Bands', opt.bands)

    ps = None
    if opt.plots:
        ps = PlotSequence('unwise')

    infn, outfn = args

    T = fits_table(infn)
    print('Read', len(T), 'sources from', infn)
    if opt.declo is not None:
        T.cut(T.dec >= opt.declo)
    if opt.dechi is not None:
        T.cut(T.dec <= opt.dechi)

    # Let's be a bit smart about RA wrap-around.  Compute the 'center'
    # of the RA points, use the cross product against that to define
    # inequality (clockwise-of).
    r = np.deg2rad(T.ra)
    x = np.mean(np.cos(r))
    y = np.mean(np.sin(r))
    rr = np.hypot(x, y)
    x /= rr
    y /= rr
    midra = np.rad2deg(np.arctan2(y, x))
    midra += 360. * (midra < 0)
    xx = np.cos(r)
    yy = np.sin(r)
    T.cross = x * yy - y * xx
    minra = T.ra[np.argmin(T.cross)]
    maxra = T.ra[np.argmax(T.cross)]

    if opt.ralo is not None:
        r = np.deg2rad(opt.ralo)
        xx = np.cos(r)
        yy = np.sin(r)
        crosscut = x * yy - y * xx
        T.cut(T.cross >= crosscut)
        print('Cut to', len(T), 'with RA >', opt.ralo)

    if opt.rahi is not None:
        r = np.deg2rad(opt.rahi)
        xx = np.cos(r)
        yy = np.sin(r)
        crosscut = x * yy - y * xx
        T.cut(T.cross <= crosscut)
        print('Cut to', len(T), 'with RA <', opt.rahi)
    if opt.declo is None:
        opt.declo = T.dec.min()
    if opt.dechi is None:
        opt.dechi = T.dec.max()
    if opt.ralo is None:
        opt.ralo = T.ra[np.argmin(T.cross)]
    if opt.rahi is None:
        opt.rahi = T.ra[np.argmax(T.cross)]
    T.delete_column('cross')

    print('RA range:', opt.ralo, opt.rahi)
    print('Dec range:', opt.declo, opt.dechi)

    x = np.mean([np.cos(np.deg2rad(r)) for r in (opt.ralo, opt.rahi)])
    y = np.mean([np.sin(np.deg2rad(r)) for r in (opt.ralo, opt.rahi)])
    midra = np.rad2deg(np.arctan2(y, x))
    midra += 360. * (midra < 0)
    middec = (opt.declo + opt.dechi) / 2.

    print('RA,Dec center:', midra, middec)

    pixscale = 2.75 / 3600.
    H = (opt.dechi - opt.declo) / pixscale
    dra = 2. * min(np.abs(midra - opt.ralo), np.abs(midra - opt.rahi))
    W = dra * np.cos(np.deg2rad(middec)) / pixscale

    margin = 5
    W = int(W) + margin * 2
    H = int(H) + margin * 2
    print('W,H', W, H)
    targetwcs = Tan(midra, middec, (W + 1) / 2., (H + 1) / 2.,
                    -pixscale, 0., 0., pixscale, float(W), float(H))
    #print('Target WCS:', targetwcs)

    ra0, dec0 = targetwcs.pixelxy2radec(0.5, 0.5)
    ra1, dec1 = targetwcs.pixelxy2radec(W + 0.5, H + 0.5)
    roiradecbox = [ra0, ra1, dec0, dec1]
    #print('ROI RA,Dec box', roiradecbox)

    tiles = unwise_tiles_touching_wcs(targetwcs)
    print('Cut to', len(tiles), 'unWISE tiles')

    disable_galaxy_cache()

    cols = T.get_columns()
    all_ptsrcs = not('type' in cols)
    if not all_ptsrcs:
        assert('shapeexp' in cols)
        assert('shapedev' in cols)
        assert('fracdev' in cols)

    wanyband = 'w'

    print('Creating Tractor catalog...')
    cat = []
    for i, t in enumerate(T):
        pos = RaDecPos(t.ra, t.dec)
        flux = NanoMaggies(**{wanyband: 1.})
        if all_ptsrcs:
            cat.append(PointSource(pos, flux))
            continue

        tt = t.type.strip()
        if tt in ['PTSRC', 'STAR', 'S']:
            cat.append(PointSource(pos, flux))
        elif tt in ['EXP', 'E']:
            shape = EllipseE(*t.shapeexp)
            cat.append(ExpGalaxy(pos, flux, shape))
        elif tt in ['DEV', 'D']:
            shape = EllipseE(*t.shapedev)
            cat.append(DevGalaxy(pos, flux, shape))
        elif tt in ['COMP', 'C']:
            eshape = EllipseE(*t.shapeexp)
            dshape = EllipseE(*t.shapedev)
            cat.append(FixedCompositeGalaxy(pos, flux, t.fracdev,
                                            eshape, dshape))
        else:
            print('Did not understand row', i, 'of input catalog:')
            t.about()
            assert(False)

    W = unwise_forcedphot(cat, tiles, roiradecbox=roiradecbox,
                          bands=opt.bands, unwise_dir=opt.unwise_dir,
                          use_ceres=opt.ceres, ceres_block=opt.ceresblock,
                          save_fits=opt.save_fits, ps=ps)
    W.writeto(outfn)
コード例 #8
0
def scan_dchisq(seeing, target_dchisq, ps, e1=0.):
    pixscale = 0.262
    psfsigma = seeing / pixscale / 2.35
    print('PSF sigma:', psfsigma, 'pixels')
    psf = GaussianMixturePSF(1., 0., 0., psfsigma**2, psfsigma**2, 0.)

    sig1 = 0.01
    psfnorm = 1./(2. * np.sqrt(np.pi) * psfsigma)
    detsig1 = sig1 / psfnorm

    sz = 50
    cd = pixscale / 3600.
    wcs = Tan(0., 0., float(sz/2), float(sz/2), -cd, 0., 0., cd,
              float(sz), float(sz))
    band = 'r'

    tim = Image(data=np.zeros((sz,sz)), inverr=np.ones((sz,sz)) / sig1,
                psf=psf,
                wcs = ConstantFitsWcs(wcs),
                photocal = LinearPhotoCal(1., band=band))
    
    re_vals = np.logspace(-1., 0., 50)
    
    all_runs = []

    mods = []
    
    for i,re in enumerate(re_vals):
        true_src = ExpGalaxy(RaDecPos(0., 0.),
                             NanoMaggies(**{band: 1.}),
                             EllipseE(re, e1, 0.))
        print('True source:', true_src)
        tr = Tractor([tim], [true_src])
        tr.freezeParams('images')
        true_mod = tr.getModelImage(0)

        dchisq_none = np.sum((true_mod * tim.inverr)**2)
        scale = np.sqrt(target_dchisq / dchisq_none)

        true_src.brightness.setParams([scale])

        true_mod = tr.getModelImage(0)
        dchisq_none = np.sum((true_mod * tim.inverr)**2)

        mods.append(true_mod)
        
        tim.data = true_mod
        
        exp_src = true_src.copy()
        psf_src = PointSource(true_src.pos.copy(), true_src.brightness.copy())
        simp_src = SimpleGalaxy(true_src.pos.copy(), true_src.brightness.copy())

        dchisqs = []
        #for src in [psf_src, simp_src, exp_src]:
        for src in [psf_src, simp_src]:
            src.freezeParam('pos')
            #print('Fitting source:', src)
            #src.printThawedParams()
            tr.catalog[0] = src
            tr.optimize_loop()
            #print('Fitted:', src)
            mod = tr.getModelImage(0)
            dchisqs.append(dchisq_none - np.sum(((true_mod - mod) * tim.inverr)**2))
            #print('dchisq:', dchisqs[-1])
        dchisqs.append(dchisq_none)
        
        all_runs.append([re,] + dchisqs)

    all_runs = np.array(all_runs)

    re = all_runs[:,0]
    dchi_psf  = all_runs[:,1]
    dchi_simp = all_runs[:,2]
    dchi_exp  = all_runs[:,3]

    dchi_ps = np.maximum(dchi_psf, dchi_simp)
    dchi_cut1 = dchi_ps + 3+9
    dchi_cut2 = dchi_ps + dchi_psf * 0.02
    dchi_cut3 = dchi_ps + dchi_psf * 0.008
    
    plt.clf()
    plt.plot(re, dchi_psf, 'k-', label='PSF')
    plt.plot(re, dchi_simp, 'b-', label='SIMP')
    plt.plot(re, dchi_exp, 'r-', label='EXP')

    plt.plot(re, dchi_cut2, 'm--', alpha=0.5, lw=2, label='Cut: 2%')
    plt.plot(re, dchi_cut3, 'm:',  alpha=0.5, lw=2, label='Cut: 0.08%')
    plt.plot(re, dchi_cut1, 'm-',  alpha=0.5, lw=2, label='Cut: 12')

    plt.xlabel('True r_e (arcsec)')
    plt.ylabel('dchisq')
    #plt.legend(loc='lower left')
    plt.legend(loc='upper right')
    tt = 'Seeing = %g arcsec, S/N ~ %i' % (seeing, int(np.round(np.sqrt(target_dchisq))))
    if e1 != 0.:
        tt += ', Ellipticity %g' % e1
    plt.title(tt)
    plt.ylim(0.90 * target_dchisq, 1.05 * target_dchisq)

    # aspect = 1.2
    # ax = plt.axis()
    # dre  = (ax[1]-ax[0]) / 20 / aspect
    # dchi = (ax[3]-ax[2]) / 20
    # I = np.linspace(0, len(re_vals)-1, 8).astype(int)
    # for mod,re in [(mods[i], re_vals[i]) for i in I]:
    #     print('extent:', [re-dre, re+dre, ax[2], ax[2]+dchi])
    #     plt.imshow(mod, interpolation='nearest', origin='lower', aspect='auto',
    #                extent=[re-dre, re+dre, ax[2], ax[2]+dchi], cmap='gray')
    # plt.axis(ax)
        
    ps.savefig()
コード例 #9
0
            for k in range(Nper):
                noise = np.random.normal(scale=sig1, size=true_mod.shape)

                tim.data = true_mod + noise

                if k == 0 and False:
                    plt.clf()
                    plt.subplot(1,2,1)
                    plt.imshow(true_mod, **ima)
                    plt.subplot(1,2,2)
                    plt.imshow(tim.data, **ima)
                    plt.title('S/N %f, r_e %f' % (sn, re))
                    ps.savefig()
                
                ## run one_blob code?  Or shortcut?
                src = PointSource(RaDecPos(0., 0.),
                                  NanoMaggies(**{band: flux}))

                nblob,iblob,Isrcs = 0, 1, np.array([0])
                brickwcs = wcs
                bx0, by0, blobw, blobh = 0, 0, sz, sz
                blobmask = np.ones((sz,sz), bool)
                timargs = [(tim.data, tim.getInvError(), tim.wcs, tim.wcs.wcs,
                            tim.getPhotoCal(), tim.getSky(), tim.psf,
                            'tim', 0, sz, 0, sz, band, sig1,
                            tim.modelMinval, None)]
                srcs = [src]
                bands = band
                plots,psx = False, None
                simul_opt, use_ceres, hastycho = False, False, False
                
                X = (nblob, iblob, Isrcs, brickwcs, bx0, by0, blobw, blobh,
コード例 #10
0
ファイル: detection.py プロジェクト: mehdirezaie/legacypipe
def run_sed_matched_filters(SEDs,
                            bands,
                            detmaps,
                            detivs,
                            omit_xy,
                            targetwcs,
                            nsigma=5,
                            saddle_fraction=0.1,
                            saddle_min=2.,
                            saturated_pix=None,
                            exclusion_radius=4.,
                            veto_map=None,
                            mp=None,
                            plots=False,
                            ps=None,
                            rgbimg=None):
    '''
    Runs a given set of SED-matched filters.

    Parameters
    ----------
    SEDs : list of (name, sed) tuples
        The SEDs to run.  The `sed` values are lists the same length
        as `bands`.
    bands : list of string
        The band names of `detmaps` and `detivs`.
    detmaps : numpy array, float
        Detection maps for each of the listed `bands`.
    detivs : numpy array, float
        Inverse-variances of the `detmaps`.
    omit_xy : None, or (xx,yy,rr) tuple
        Existing sources to avoid: x, y, radius.
    targetwcs : WCS object
        WCS object to use to convert pixel values into RA,Decs for the
        returned Tractor PointSource objects.
    nsigma : float, optional
        Detection threshold
    saturated_pix : None or list of numpy arrays, booleans
        Passed through to sed_matched_detection.
        A map of pixels that are always considered "hot" when
        determining whether a new source touches hot pixels of an
        existing source.
    exclusion_radius: int
        How many pixels around an existing source to veto
    plots : boolean, optional
        Create plots?
    ps : PlotSequence object
        Create plots?
    mp : multiproc object
        Multiprocessing

    Returns
    -------
    Tnew : fits_table
        Table of new sources detected
    newcat : list of PointSource objects
        Newly detected objects, with positions and fluxes, as Tractor
        PointSource objects.
    hot : numpy array of bool
        "Hot pixels" containing sources.

    See also
    --------
    sed_matched_detection : run a single SED-matched filter.

    '''
    from astrometry.util.fits import fits_table
    from tractor import PointSource, RaDecPos, NanoMaggies

    if omit_xy is not None:
        xx, yy, rr = omit_xy
        n0 = len(xx)
    else:
        xx, yy, rr = [], [], []
        n0 = 0

    H, W = detmaps[0].shape
    hot = np.zeros((H, W), bool)

    peaksn = []
    apsn = []

    for sedname, sed in SEDs:
        if plots:
            pps = ps
        else:
            pps = None
        sedhot, px, py, peakval, apval = sed_matched_detection(
            sedname,
            sed,
            detmaps,
            detivs,
            bands,
            xx,
            yy,
            rr,
            nsigma=nsigma,
            saddle_fraction=saddle_fraction,
            saddle_min=saddle_min,
            saturated_pix=saturated_pix,
            veto_map=veto_map,
            ps=pps,
            rgbimg=rgbimg)
        if sedhot is None:
            continue
        info('SED', sedname, ':', len(px), 'new peaks')
        hot |= sedhot
        # With an empty xx, np.append turns it into a double!
        xx = np.append(xx, px).astype(int)
        yy = np.append(yy, py).astype(int)
        rr = np.append(rr, np.zeros_like(px) + exclusion_radius).astype(int)
        peaksn.extend(peakval)
        apsn.extend(apval)

    # New peaks:
    peakx = xx[n0:]
    peaky = yy[n0:]

    Tnew = None
    newcat = []
    if len(peakx):
        # Add sources for the new peaks we found
        pr, pd = targetwcs.pixelxy2radec(peakx + 1, peaky + 1)
        info('Adding', len(pr), 'new sources')
        # Also create FITS table for new sources
        Tnew = fits_table()
        Tnew.ra = pr
        Tnew.dec = pd
        Tnew.ibx = peakx
        Tnew.iby = peaky
        assert (len(peaksn) == len(Tnew))
        assert (len(apsn) == len(Tnew))
        Tnew.peaksn = np.array(peaksn)
        Tnew.apsn = np.array(apsn)
        for r, d, x, y in zip(pr, pd, peakx, peaky):
            fluxes = dict([(band, detmap[y, x])
                           for band, detmap in zip(bands, detmaps)])
            newcat.append(
                PointSource(RaDecPos(r, d), NanoMaggies(order=bands,
                                                        **fluxes)))
    return Tnew, newcat, hot
コード例 #11
0
ファイル: morphology.py プロジェクト: legacysurvey/legacypipe
            for k in range(Nper):
                noise = np.random.normal(scale=sig1, size=true_mod.shape)

                tim.data = true_mod + noise

                if k == 0 and False:
                    plt.clf()
                    plt.subplot(1,2,1)
                    plt.imshow(true_mod, **ima)
                    plt.subplot(1,2,2)
                    plt.imshow(tim.data, **ima)
                    plt.title('S/N %f, r_e %f' % (sn, re))
                    ps.savefig()
                
                ## run one_blob code?  Or shortcut?
                src = PointSource(RaDecPos(0., 0.),
                                  NanoMaggies(**{band: flux}))

                nblob,iblob,Isrcs = 0, 1, np.array([0])
                brickwcs = wcs
                bx0, by0, blobw, blobh = 0, 0, sz, sz
                blobmask = np.ones((sz,sz), bool)
                timargs = [(tim.data, tim.getInvError(), tim.wcs, tim.wcs.wcs,
                            tim.getPhotoCal(), tim.getSky(), tim.psf,
                            'tim', 0, sz, 0, sz, band, sig1,
                            tim.modelMinval, None)]
                srcs = [src]
                bands = band
                plots,psx = False, None
                simul_opt, use_ceres, hastycho = False, False, False
                
                X = (nblob, iblob, Isrcs, brickwcs, bx0, by0, blobw, blobh,
コード例 #12
0
ファイル: mini.py プロジェクト: charlotteaward/tractor-1
    # (but in SDSS we'll be using multi-band NanoMaggies)
    band = 'r'
    # image sensitivity:
    photocal = LinearPhotoCal(10., band=band)

    # flat sky
    sky = ConstantSky(0.)

    # Create tractor.Image object
    tim = Image(data, iv, psf=psf, wcs=wcs, sky=sky, photocal=photocal)

    def brightness(x):
        return NanoMaggies(**{band: x})

    # Create some sources
    ptsrc = PointSource(RaDecPos(ra, dec), brightness(10.))

    gal1 = ExpGalaxy(RaDecPos(ra - 10 * pscale, dec), brightness(50.),
                     GalaxyShape(5., 0.5, 45.))

    gal2 = DevGalaxy(RaDecPos(ra + 10 * pscale, dec), brightness(50.),
                     GalaxyShape(5., 0.25, 135.))

    gal3 = FixedCompositeGalaxy(
        RaDecPos(ra, dec + 10 * pscale),
        brightness(50.),
        0.6,  # fraction of light in deV component
        GalaxyShape(5., 0.6, 30.),
        GalaxyShape(5., 0.3, 45.))

    cat = Catalog(ptsrc, gal1, gal2, gal3)