Ejemplo n.º 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
Ejemplo n.º 2
0
 def galaxy_norm(self, tim, x=None, y=None):
     # Galaxy-detection norm
     from tractor.galaxy import ExpGalaxy
     from tractor.ellipses import EllipseE
     from tractor.patch import Patch
     h,w = tim.shape
     band = tim.band
     if x is None:
         x = w/2.
     if y is None:
         y = h/2.
     pos = tim.wcs.pixelToPosition(x, y)
     gal = ExpGalaxy(pos, NanoMaggies(**{band:1.}), EllipseE(0.45, 0., 0.))
     S = 32
     mm = Patch(int(x-S), int(y-S), np.ones((2*S+1, 2*S+1), bool))
     galmod = gal.getModelPatch(tim, modelMask=mm).patch
     galmod = np.maximum(0, galmod)
     galmod /= galmod.sum()
     galnorm = np.sqrt(np.sum(galmod**2))
     return galnorm
Ejemplo n.º 3
0
 def galaxy_norm(self, tim, x=None, y=None):
     # Galaxy-detection norm
     from tractor.galaxy import ExpGalaxy
     from tractor.ellipses import EllipseE
     from tractor.patch import Patch
     h, w = tim.shape
     band = tim.band
     if x is None:
         x = w / 2.
     if y is None:
         y = h / 2.
     pos = tim.wcs.pixelToPosition(x, y)
     gal = ExpGalaxy(pos, NanoMaggies(**{band: 1.}), EllipseE(0.45, 0., 0.))
     S = 32
     mm = Patch(int(x - S), int(y - S), np.ones((2 * S + 1, 2 * S + 1),
                                                bool))
     galmod = gal.getModelPatch(tim, modelMask=mm).patch
     galmod = np.maximum(0, galmod)
     galmod /= galmod.sum()
     galnorm = np.sqrt(np.sum(galmod**2))
     return galnorm
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
def gim2d_catalog(cat, band):
    '''
    http://irsa.ipac.caltech.edu/data/COSMOS/tables/morphology/cosmos_morph_zurich_colDescriptions.html
    '''
    '''
    ACS_MU_CLASS 	float 	  	Type of object.
    1 = galaxy
    2 = star
    3 = spurious
    '''
    '''
    ACS_CLEAN 	float 	  	Object useable flag.
    0 = do not use this object
    1 = use this object
    '''
    '''
    FLUX_GIM2D 	float 	counts 	GIM2D total flux
    R_GIM2D 	float 	arcseconds 	GIM2D psf-convolved half-light radius of object
    ELL_GIM2D 	float 	  	GIM2D ellipticity = 1-b/a of object
    PA_GIM2D 	float 	degrees 	GIM2D position angle of object - cw from +y-axis
    DX_GIM2D 	float 	arcseconds 	x-offset of GIM2D-model center from ACS-coordinate center
    DY_GIM2D 	float 	arcseconds 	y-offset of GIM2D-model center from ACS-coordinate center
    SERSIC_N_GIM2D 	float 	  	GIM2D Sersic index
    R_0P5_GIM2D 	float 	arcseconds 	GIM2D half-light radius of object without PSF convolution

    TYPE 	float 	  	ZEST Type CLASS
    1 = Early type
    2 = Disk
    3 = Irregular Galaxy
    9 = no classification
    '''
    '''
    BULG 	float 	  	ZEST "Bulgeness" CLASS - only for Type 2 (disk) galaxies.
    0 = bulge dominated galaxy
    1,2 = intermediate-bulge galaxies
    3 = pure disk galaxy
    9 = no classification
    '''
    '''
    STELLARITY 	float 	  	Visual Stellarity flag.

    0 if ACS_CLASS_STAR<0.6 (object is ASSUMED to be a galaxy; no visual inspection)
    0 if ACS_CLASS_STAR>=0.6 AND object visually identified as a galaxy.
    1 if ACS_CLASS_STAR>=0.6 AND visually identified as a star.
    2 if ACS_CLASS_STAR>=0.8 (object is assumed to be a star and was not visually inspected)
    3 if ACS_CLASS_STAR<0.6 but object is visually identified as a star (e.g. saturated star, etc)

    JUNKFLAG 	float 	  	
    0 = good object
    1 = spurious
    '''

    print('Classifications:', Counter(cat.type).most_common())

    cat.is_galaxy = (cat.stellarity == 0)
    srcs = []
    for t in cat:
        pos = RaDecPos(t.ra, t.dec)
        bright = NanoMaggies(
            **{band: NanoMaggies.magToNanomaggies(t.acs_mag_auto)})
        shape = GalaxyShape(t.r_0p5_gim2d, 1. - t.ell_gim2d, 90. + t.pa_gim2d)

        is_galaxy = (t.is_galaxy * (shape.re >= 0) * (shape.ab <= 1.) *
                     (shape.phi > -999))

        if is_galaxy and t.type == 1:
            # deV
            src = DevGalaxy(pos, bright, shape)
        elif is_galaxy and t.type == 2:
            # exp
            src = ExpGalaxy(pos, bright, shape)
        else:
            src = PointSource(pos, bright)
        srcs.append(src)
    return srcs
Ejemplo n.º 6
0
def get_reference_sources(survey,
                          targetwcs,
                          pixscale,
                          bands,
                          tycho_stars=True,
                          gaia_stars=True,
                          large_galaxies=True,
                          star_clusters=True):

    from legacypipe.survey import GaiaSource
    from legacypipe.survey import LegacyEllipseWithPriors
    from tractor import NanoMaggies, RaDecPos
    from tractor.galaxy import ExpGalaxy
    from tractor.ellipses import EllipseESoft

    H, W = targetwcs.shape
    H, W = int(H), int(W)

    # How big of a margin to search for bright stars and star clusters --
    # this should be based on the maximum radius they are considered to
    # affect.
    ref_margin = 0.125
    mpix = int(np.ceil(ref_margin * 3600. / pixscale))
    marginwcs = targetwcs.get_subimage(-mpix, -mpix, W + 2 * mpix,
                                       H + 2 * mpix)

    refs = []

    # Tycho-2 stars
    if tycho_stars:
        tycho = read_tycho2(survey, marginwcs)
        if len(tycho):
            refs.append(tycho)

    # Add Gaia stars
    gaia = None
    if gaia_stars:
        from astrometry.libkd.spherematch import match_radec
        gaia = read_gaia(marginwcs)
    if gaia is not None:
        gaia.isbright = (gaia.phot_g_mean_mag < 13.)
        gaia.ismedium = (gaia.phot_g_mean_mag < 16.)
        gaia.donotfit = np.zeros(len(gaia), bool)
        # Handle sources that appear in both Gaia and Tycho-2 by
        # dropping the entry from Tycho-2.
        if len(gaia) and len(tycho):
            # Before matching, apply proper motions to bring them to
            # the same epoch.  We want to use the more-accurate Gaia
            # proper motions, so rewind Gaia positions to the
            # approximate epoch of Tycho-2: 1991.5.
            cosdec = np.cos(np.deg2rad(gaia.dec))
            gra = gaia.ra + (1991.5 - gaia.ref_epoch) * gaia.pmra / (
                3600. * 1000.) / cosdec
            gdec = gaia.dec + (1991.5 - gaia.ref_epoch) * gaia.pmdec / (3600. *
                                                                        1000.)
            I, J, _ = match_radec(tycho.ra,
                                  tycho.dec,
                                  gra,
                                  gdec,
                                  1. / 3600.,
                                  nearest=True)
            debug('Matched', len(I), 'Tycho-2 stars to Gaia stars.')
            if len(I):
                keep = np.ones(len(tycho), bool)
                keep[I] = False
                tycho.cut(keep)
                gaia.isbright[J] = True
        if gaia is not None and len(gaia) > 0:
            refs.append(gaia)

    # Read the catalog of star (open and globular) clusters and add them to the
    # set of reference stars (with the isbright bit set).
    if star_clusters:
        clusters = read_star_clusters(marginwcs)
        if clusters is not None:
            debug('Found', len(clusters), 'star clusters nearby')
            clusters.iscluster = np.ones(len(clusters), bool)
            refs.append(clusters)

    # Read large galaxies nearby.
    if large_galaxies:
        galaxies = read_large_galaxies(survey, targetwcs)
        if galaxies is not None:
            # Resolve possible Gaia-large-galaxy duplicates
            if gaia and len(gaia):
                I, J, _ = match_radec(galaxies.ra,
                                      galaxies.dec,
                                      gaia.ra,
                                      gaia.dec,
                                      2. / 3600.,
                                      nearest=True)
                print('Matched', len(I), 'large galaxies to Gaia stars.')
                if len(I):
                    gaia.donotfit[J] = True
            refs.append(galaxies)

    refcat = None
    if len(refs):
        refs = merge_tables([r for r in refs if r is not None],
                            columns='fillzero')
    if len(refs) == 0:
        return None, None

    refs.radius_pix = np.ceil(refs.radius * 3600. / pixscale).astype(int)

    ok, xx, yy = targetwcs.radec2pixelxy(refs.ra, refs.dec)
    # ibx = integer brick coords
    refs.ibx = np.round(xx - 1.).astype(int)
    refs.iby = np.round(yy - 1.).astype(int)

    # cut ones whose position + radius are outside the brick bounds.
    refs.cut((xx > -refs.radius_pix) * (xx < W + refs.radius_pix) *
             (yy > -refs.radius_pix) * (yy < H + refs.radius_pix))
    # mark ones that are actually inside the brick area.
    refs.in_bounds = ((refs.ibx >= 0) * (refs.ibx < W) * (refs.iby >= 0) *
                      (refs.iby < H))

    for col in [
            'isbright', 'ismedium', 'islargegalaxy', 'iscluster', 'donotfit'
    ]:
        if not col in refs.get_columns():
            refs.set(col, np.zeros(len(refs), bool))

    ## Create Tractor sources from reference stars
    refcat = []
    for g in refs:
        if g.donotfit or g.iscluster:
            refcat.append(None)

        elif g.islargegalaxy:
            fluxes = dict([(band, NanoMaggies.magToNanomaggies(g.mag))
                           for band in bands])
            assert (np.all(np.isfinite(list(fluxes.values()))))
            rr = g.radius * 3600. / 0.5  # factor of two accounts for R(25)-->reff
            pa = 180 - g.pa
            if not np.isfinite(pa):
                pa = 0.
            logr, ee1, ee2 = EllipseESoft.rAbPhiToESoft(rr, g.ba, pa)
            gal = ExpGalaxy(RaDecPos(g.ra, g.dec),
                            NanoMaggies(order=bands, **fluxes),
                            LegacyEllipseWithPriors(logr, ee1, ee2))
            refcat.append(gal)

        else:
            # Gaia star -- which we want to create a source for, regardless of
            # whether it is marked medium | bright (or neither).
            refcat.append(GaiaSource.from_catalog(g, bands))

    for src in refcat:
        if src:
            src.is_reference_source = True

    return refs, refcat
Ejemplo n.º 7
0
def get_galaxy_sources(galaxies, bands):
    from legacypipe.catalog import fits_reverse_typemap
    from legacypipe.survey import (LegacySersicIndex, LegacyEllipseWithPriors,
                                   LogRadius, RexGalaxy)
    from tractor import NanoMaggies, RaDecPos, PointSource
    from tractor.ellipses import EllipseE, EllipseESoft
    from tractor.galaxy import DevGalaxy, ExpGalaxy
    from tractor.sersic import SersicGalaxy

    # Factor of HyperLEDA to set the galaxy max radius
    radius_max_factor = 2.

    srcs = [None for g in galaxies]

    # If we have pre-burned galaxies, re-create the Tractor sources for them.
    I, = np.nonzero(galaxies.preburned)
    for ii, g in zip(I, galaxies[I]):
        typ = fits_reverse_typemap[g.type.strip()]
        pos = RaDecPos(g.ra, g.dec)
        fluxes = dict([(band, g.get('flux_%s' % band)) for band in bands])
        bright = NanoMaggies(order=bands, **fluxes)
        shape = None
        # put the Rex branch first, because Rex is a subclass of ExpGalaxy!
        if issubclass(typ, RexGalaxy):
            assert (np.isfinite(g.shape_r))
            logre = np.log(g.shape_r)
            shape = LogRadius(logre)
            # set prior max at 2x SGA radius
            shape.setMaxLogRadius(logre + np.log(radius_max_factor))
        elif issubclass(typ, (DevGalaxy, ExpGalaxy, SersicGalaxy)):
            assert (np.isfinite(g.shape_r))
            assert (np.isfinite(g.shape_e1))
            assert (np.isfinite(g.shape_e2))
            shape = EllipseE(g.shape_r, g.shape_e1, g.shape_e2)
            # switch to softened ellipse (better fitting behavior)
            shape = EllipseESoft.fromEllipseE(shape)
            # and then to our custom ellipse class
            logre = shape.logre
            shape = LegacyEllipseWithPriors(logre, shape.ee1, shape.ee2)
            assert (np.all(np.isfinite(shape.getParams())))
            # set prior max at 2x SGA radius
            shape.setMaxLogRadius(logre + np.log(radius_max_factor))

        if issubclass(typ, PointSource):
            src = typ(pos, bright)
        # this catches Rex too
        elif issubclass(typ, (DevGalaxy, ExpGalaxy)):
            src = typ(pos, bright, shape)
        elif issubclass(typ, (SersicGalaxy)):
            assert (np.isfinite(g.sersic))
            sersic = LegacySersicIndex(g.sersic)
            src = typ(pos, bright, shape, sersic)
        else:
            raise RuntimeError('Unknown preburned SGA source type "%s"' % typ)
        debug('Created', src)
        assert (np.isfinite(src.getLogPrior()))
        srcs[ii] = src

    # SGA parent catalog: 'preburned' is not set
    # This also can happen in the preburned/ellipse catalog when fitting
    # fails, or no-grz, etc.
    I, = np.nonzero(np.logical_not(galaxies.preburned))
    for ii, g in zip(I, galaxies[I]):
        # Initialize each source with an exponential disk--
        fluxes = dict([(band, NanoMaggies.magToNanomaggies(g.mag))
                       for band in bands])
        assert (np.all(np.isfinite(list(fluxes.values()))))
        rr = g.radius * 3600. / 2  # factor of two accounts for R(25)-->reff [arcsec]
        assert (np.isfinite(rr))
        assert (np.isfinite(g.ba))
        assert (np.isfinite(g.pa))
        ba = g.ba
        if ba <= 0.0 or ba > 1.0:
            # Make round!
            ba = 1.0
        logr, ee1, ee2 = EllipseESoft.rAbPhiToESoft(
            rr, ba, 180 - g.pa)  # note the 180 rotation
        assert (np.isfinite(logr))
        assert (np.isfinite(ee1))
        assert (np.isfinite(ee2))
        shape = LegacyEllipseWithPriors(logr, ee1, ee2)
        shape.setMaxLogRadius(logr + np.log(radius_max_factor))
        src = ExpGalaxy(RaDecPos(g.ra, g.dec),
                        NanoMaggies(order=bands, **fluxes), shape)
        assert (np.isfinite(src.getLogPrior()))
        src.needs_initial_flux = True
        srcs[ii] = src

    return srcs
Ejemplo n.º 8
0
    def test_psfex(self):

        if ps is not None:
            from astrometry.util.plotutils import dimshow
            import pylab as plt

        H, W = 100, 100
        cx, cy = W / 2., H / 2.

        pixpsf = self.psf.constantPsfAt(cx, cy)

        ph, pw = pixpsf.shape
        xx, yy = np.meshgrid(np.arange(pw), np.arange(ph))
        im = pixpsf.img.copy()
        im /= np.sum(im)
        cenx, ceny = np.sum(im * xx), np.sum(im * yy)
        print('Pixpsf centroid:', cenx, ceny)
        print('shape:', ph, pw)

        dx, dy = cenx - pw // 2, ceny - ph // 2
        print('dx,dy', dx, dy)

        # gpsf = GaussianMixturePSF.fromStamp(im, N=1)
        # print('Fit gpsf:', gpsf)
        # self.assertTrue(np.abs(gpsf.mog.mean[0,0] - dx) < 0.1)
        # self.assertTrue(np.abs(gpsf.mog.mean[0,1] - dy) < 0.1)
        # self.assertTrue(np.abs(gpsf.mog.var[0,0,0] - 15.5) < 1.)
        # self.assertTrue(np.abs(gpsf.mog.var[0,1,1] - 13.5) < 1.)
        # self.assertTrue(np.abs(gpsf.mog.var[0,1,0] -   -1) < 1.)

        gpsf = GaussianMixturePSF.fromStamp(im, N=2)
        print('Fit gpsf:', gpsf)
        print('Params:', ', '.join(['%.1f' % p for p in gpsf.getParams()]))

        pp = np.array(
            [0.8, 0.2, 0.1, -0.0, 1.2, 0.2, 7.6, 6.0, -1.0, 51.6, 49.1, -1.3])
        self.assertTrue(np.all(np.abs(np.array(gpsf.getParams()) - pp) < 0.1))

        tim = Image(data=np.zeros((H, W)),
                    invvar=np.ones((H, W)),
                    psf=self.psf)

        xx, yy = np.meshgrid(np.arange(W), np.arange(H))

        star = PointSource(PixPos(cx, cy), Flux(100.))
        gal = ExpGalaxy(PixPos(cx, cy), Flux(100.), EllipseE(1., 0., 0.))

        tr1 = Tractor([tim], [star])
        tr2 = Tractor([tim], [gal])

        disable_galaxy_cache()

        tim.psf = self.psf
        mod = tr1.getModelImage(0)
        mod1 = mod

        im = mod.copy()
        im /= im.sum()
        cenx, ceny = np.sum(im * xx), np.sum(im * yy)
        print('Star model + PsfEx centroid', cenx, ceny)

        self.assertTrue(np.abs(cenx - (cx + dx)) < 0.1)
        self.assertTrue(np.abs(ceny - (cy + dy)) < 0.1)

        if ps is not None:
            plt.clf()
            dimshow(mod)
            plt.title('Star model, PsfEx')
            ps.savefig()

        tim.psf = pixpsf

        mod = tr1.getModelImage(0)

        if ps is not None:
            plt.clf()
            dimshow(mod)
            plt.title('Star model, pixpsf')
            ps.savefig()

        tim.psf = gpsf

        mod = tr1.getModelImage(0)
        mod2 = mod

        if ps is not None:
            plt.clf()
            dimshow(mod)
            plt.title('Star model, gpsf')
            plt.colorbar()
            ps.savefig()

            plt.clf()
            dimshow(mod1 - mod2)
            plt.title('Star model, PsfEx - gpsf')
            plt.colorbar()
            ps.savefig()

        # range ~ -0.15 to +0.25
        self.assertTrue(np.all(np.abs(mod1 - mod2) < 0.25))

        tim.psf = self.psf
        mod = tr2.getModelImage(0)
        mod1 = mod

        im = mod.copy()
        im /= im.sum()
        cenx, ceny = np.sum(im * xx), np.sum(im * yy)
        print('Gal model + PsfEx centroid', cenx, ceny)

        self.assertTrue(np.abs(cenx - (cx + dx)) < 0.1)
        self.assertTrue(np.abs(ceny - (cy + dy)) < 0.1)

        if ps is not None:
            plt.clf()
            dimshow(mod)
            plt.title('Gal model, PsfEx')
            ps.savefig()

        # tim.psf = pixpsf
        # mod = tr2.getModelImage(0)
        # plt.clf()
        # dimshow(mod)
        # plt.title('Gal model, pixpsf')
        # ps.savefig()

        tim.psf = gpsf
        mod = tr2.getModelImage(0)
        mod2 = mod
        # range ~ -0.1 to +0.2
        self.assertTrue(np.all(np.abs(mod1 - mod2) < 0.2))

        if ps is not None:
            plt.clf()
            dimshow(mod)
            plt.title('Gal model, gpsf')
            ps.savefig()

            plt.clf()
            dimshow(mod1 - mod2)
            plt.title('Gal model, PsfEx - gpsf')
            plt.colorbar()
            ps.savefig()
Ejemplo n.º 9
0
def add_tractor_sources(obj_cat, sources, w, shape_method='manual'):
    '''
    Add tractor sources to the sources list.

    Parameters:
    ----------
    obj_cat: astropy Table, objects catalogue.
    sources: list, to which we will add objects.
    w: wcs object.
    shape_method: string, 'manual' or 'decals'. If 'manual', it will adopt the 
                manually measured shapes. If 'decals', it will adopt 'DECaLS' 
                tractor shapes.

    Returns:
    --------
    sources: list of sources.
    '''
    from tractor import NullWCS, NullPhotoCal, ConstantSky
    from tractor.galaxy import GalaxyShape, DevGalaxy, ExpGalaxy, CompositeGalaxy
    from tractor.psf import Flux, PixPos, PointSource, PixelizedPSF, Image, Tractor
    from tractor.ellipses import EllipseE
    obj_type = np.array(list(map(lambda st: st.rstrip(' '), obj_cat['type'])))
    comp_galaxy = obj_cat[obj_type == 'COMP']
    dev_galaxy = obj_cat[obj_type == 'DEV']
    exp_galaxy = obj_cat[obj_type == 'EXP']
    rex_galaxy = obj_cat[obj_type == 'REX']
    psf_galaxy = obj_cat[np.logical_or(obj_type =='PSF', obj_type=='   ')]

    if shape_method is 'manual':
        # Using manually measured shapes
        if sources is None:
            sources = []
        for obj in obj_cat:
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            if obj['type'].rstrip(' ') == 'COMP':
                sources.append(
                    CompositeGalaxy(
                        PixPos(pos_x, pos_y), Flux(0.4 * obj['flux']),
                        GalaxyShape(obj['a_arcsec'] * 0.8, 0.9,
                                    90.0 + obj['theta'] * 180.0 / np.pi),
                        Flux(0.6 * obj['flux']),
                        GalaxyShape(obj['a_arcsec'], obj['b_arcsec'] / obj['a_arcsec'],
                                    90.0 + obj['theta'] * 180.0 / np.pi)))
            elif obj['type'].rstrip(' ') == 'DEV':
                sources.append(
                    DevGalaxy(
                        PixPos(pos_x, pos_y), Flux(obj['flux']),
                        GalaxyShape(obj['a_arcsec'], (obj['b_arcsec'] / obj['a_arcsec']),
                                    (90.0 + obj['theta'] * 180.0 / np.pi))))
            elif obj['type'].rstrip(' ') == 'EXP':
                sources.append(
                    ExpGalaxy(
                        PixPos(pos_x, pos_y), Flux(obj['flux']),
                        GalaxyShape(obj['a_arcsec'], (obj['b_arcsec'] / obj['a_arcsec']),
                                    (90.0 + obj['theta'] * 180.0 / np.pi))))
            elif obj['type'].rstrip(' ') == 'REX':
                sources.append(
                    ExpGalaxy(
                        PixPos(pos_x, pos_y), Flux(obj['flux']),
                        GalaxyShape(obj['a_arcsec'], (obj['b_arcsec'] / obj['a_arcsec']),
                                    (90.0 + obj['theta'] * 180.0 / np.pi))))
            elif obj['type'].rstrip(' ') == 'PSF' or obj['type'].rstrip(' ') == '   ':
                sources.append(PointSource(PixPos(pos_x, pos_y), Flux(obj['flux'])))

        print("Now you have %d sources" % len(sources))

    elif shape_method is 'decals':
        ## Using DECaLS shapes
        if sources is None:
            sources = []
        for obj in comp_galaxy:
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            sources.append(
                CompositeGalaxy(
                    PixPos(pos_x, pos_y), Flux(0.4 * obj['flux']),
                    EllipseE(obj['shapeexp_r'], obj['shapeexp_e1'],
                             obj['shapeexp_e2']), Flux(0.6 * obj['flux']),
                    EllipseE(obj['shapedev_r'], obj['shapedev_e1'],
                             obj['shapedev_e2'])))
        for obj in dev_galaxy:
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            sources.append(
                DevGalaxy(
                    PixPos(pos_x, pos_y), Flux(obj['flux']),
                    EllipseE(obj['shapedev_r'], obj['shapedev_e1'],
                             -obj['shapedev_e2'])))
        for obj in exp_galaxy:
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            sources.append(
                ExpGalaxy(
                    PixPos(pos_x, pos_y), Flux(obj['flux']),
                    EllipseE(obj['shapeexp_r'], obj['shapeexp_e1'],
                             -obj['shapeexp_e2'])))
        for obj in rex_galaxy:
            #if obj['point_source'] > 0.0:
            #            sources.append(PointSource(PixPos(w.wcs_world2pix([[obj['ra'], obj['dec']]],1)[0]),
            #                                               Flux(obj['flux'])))
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            sources.append(
                ExpGalaxy(
                    PixPos(pos_x, pos_y), Flux(obj['flux']),
                    EllipseE(obj['shapeexp_r'], obj['shapeexp_e1'],
                             -obj['shapeexp_e2'])))

        for obj in psf_galaxy:
            pos_x, pos_y = w.wcs_world2pix([[obj['ra'], obj['dec']]], 1)[0]
            sources.append(PointSource(PixPos(pos_x, pos_y), Flux(obj['flux'])))

        print("Now you have %d sources" % len(sources))
    else:
         raise ValueError('Cannot use this shape method') 
    return sources
Ejemplo n.º 10
0
    
if __name__ == '__main__':
    h,w = 100,100
    from tractor.galaxy import ExpGalaxy
    from tractor import Image, GaussianMixturePSF, LinearPhotoCal
    from tractor import PixPos, Flux, EllipseE, Tractor, ModelMask
    import pylab as plt

    # Create a Tractor Image that works in pixel space (WCS not specified).
    tim = Image(data=np.zeros((h,w)), inverr=np.ones((h,w)),
                psf=GaussianMixturePSF(1., 0., 0., 3., 3., 0.),
                photocal=LinearPhotoCal(1.))

    # Create a plain Exp galaxy to generate a postage stamp that we'll try to fit with
    # the MogGalaxy model.
    gal = ExpGalaxy(PixPos(w//2, h//2), Flux(1000.),
                    EllipseE(10., 0.5, 0.3))

    # Get the model
    tractor = Tractor([tim], [gal])
    mod = tractor.getModelImage(0)

    #mog = gal._getAffineProfile(tim, w//2, h//2)
    #print('Exp galaxy profile:', str(mog))

    # Plot the model
    plt.clf()
    plt.imshow(mod, interpolation='nearest', origin='lower')
    plt.savefig('mod.png')

    # Set the tractor Image to the Exp model postage stamp -- this is what we'll try to fit.
    tim.data = mod
Ejemplo n.º 11
0
    # 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)

    # Create Tractor object
    tr = Tractor([tim], cat)