Exemple #1
0
                    hspace=0, wspace=0)

# transpose image
dimshow(tim.getImage().T, vmin=-2.*tim.sig1, vmax=10.*tim.sig1)
plt.title('DECaLS ' + tim.name)
ps.savefig()
ax = plt.axis()
plt.plot(stars.iy, stars.ix, 'r.')
plt.axis(ax)
plt.title('Pan-STARRS stars in DECaLS ' + tim.name)
ps.savefig()

iband = ps1cat.ps1band[tim.band]

stars.mag = stars.median[:,iband]
stars.flux = NanoMaggies.magToNanomaggies(stars.mag)

stars.cut(stars.flux > 1.)
print len(stars), 'brighter than 22.5'

stars.cut(np.argsort(stars.mag))



ima = dict(vmin=-2.*tim.sig1, vmax=10.*tim.sig1, ticks=False)

plt.clf()

#R,C = 10,14
#R,C = 9,13
R,C = 10,13
Exemple #2
0
E = C[I]
print(len(E), 'exposures')
E.index = np.arange(len(E))
E.passnum = np.zeros(len(E), np.uint8)
E.depthfraction = np.zeros(len(E), np.float32)

# Compute which pass number each exposure would be called.
zp0 = DecamImage.nominal_zeropoints()
# HACK -- this is copied from obsbot
kx = dict(g = 0.178, r = 0.094, z = 0.060,)
for band in bands:
    B = E[E.filter == band]
    B.cut(np.argsort(B.seeing))

    Nsigma = 5.
    sig = NanoMaggies.magToNanomaggies(target[band]) / Nsigma
    targetiv = 1./sig**2

    for exp in B:
        thisdetiv = 1. / (exp.sig1 / exp.galnorm)**2
        # Which pass number would this image be assigned?
        trans = 10.**(-0.4 * (zp0[band] - exp.ccdzpt
                              - kx[band]*(exp.airmass - 1.)))
        seeing_good = exp.seeing < 1.3
        seeing_fair = exp.seeing < 2.0
        trans_good = trans > 0.9
        trans_fair = trans > 0.7
        if seeing_good and trans_good:
            E.passnum[exp.index] = 1
        elif ((seeing_good and trans_fair) or (seeing_fair and trans_good)):
            E.passnum[exp.index] = 2
Exemple #3
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
Exemple #4
0
def main():
    # I read a DESI DR8 target catalog, cut to ELGs, then took a narrow
    # r-mag slice around the peak of that distribution;
    # desi/target/catalogs/dr8/0.31.1/targets/main/resolve/targets-dr8-hp-1,5,11,50,55,60,83,84,86,89,91,98,119,155,158,174,186,187,190.fits')
    # Then took the median g and z mags
    # And opened the coadd invvar mags for a random brick in that footprint
    # (0701p000) to find the median per-pixel invvars.

    r = 23.0
    g = 23.4
    z = 22.2

    # Selecting EXPs, the peak of the shapeexp_r was ~ 0.75".
    r_e = 0.75

    # Image properties:

    giv = 77000.
    riv = 27000.
    ziv = 8000.

    # PSF sizes were roughly equal, 1.16, 1.17, 1.19"
    # -> sigma = 1.9 DECam pixels
    psf_sigma = 1.9

    H, W = 1000, 1000

    seed = 42
    np.random.seed(seed)

    ra, dec = 70., 1.
    brick = BrickDuck(ra, dec, 'custom-0700p010')
    wcs = wcs_for_brick(brick, W=W, H=H)
    bands = 'grz'

    tims = []
    for band, iv in zip(bands, [giv, riv, ziv]):
        img = np.zeros((H, W), np.float32)
        tiv = np.zeros_like(img) + iv
        s = psf_sigma**2
        psf = GaussianMixturePSF(1., 0., 0., s, s, 0.)
        twcs = ConstantFitsWcs(wcs)
        sky = ConstantSky(0.)
        photocal = LinearPhotoCal(1., band=band)

        tai = TAITime(None, mjd=55700.)

        tim = tractor.Image(data=img,
                            invvar=tiv,
                            psf=psf,
                            wcs=twcs,
                            sky=sky,
                            photocal=photocal,
                            name='fake %s' % band,
                            time=tai)
        tim.skyver = ('1', '1')
        tim.psfver = ('1', '1')
        tim.plver = '1'
        tim.x0 = tim.y0 = 0
        tim.subwcs = wcs
        tim.psfnorm = 1. / (2. * np.sqrt(np.pi) * psf_sigma)
        tim.galnorm = tim.psfnorm
        tim.propid = '2020A-000'
        tim.band = band
        tim.dq = None
        tim.sig1 = 1. / np.sqrt(iv)
        tim.psf_sigma = psf_sigma
        tim.primhdr = fitsio.FITSHDR()

        tims.append(tim)

    # Simulated catalog
    gflux = NanoMaggies.magToNanomaggies(g)
    rflux = NanoMaggies.magToNanomaggies(r)
    zflux = NanoMaggies.magToNanomaggies(z)
    box = 50
    CX, CY = np.meshgrid(np.arange(box // 2, W, box),
                         np.arange(box // 2, H, box))
    ny, nx = CX.shape
    BA, PHI = np.meshgrid(np.linspace(0.1, 1.0, nx), np.linspace(0., 180., ny))
    cat = []
    for cx, cy, ba, phi in zip(CX.ravel(), CY.ravel(), BA.ravel(),
                               PHI.ravel()):
        #print('x,y %.1f,%.1f, ba %.2f, phi %.2f' % (cx, cy, ba, phi))
        r, d = wcs.pixelxy2radec(cx + 1, cy + 1)
        src = ExpGalaxy(RaDecPos(r, d),
                        NanoMaggies(order=bands, g=gflux, r=rflux, z=zflux),
                        EllipseE.fromRAbPhi(r_e, ba, phi))
        cat.append(src)

    from legacypipe.catalog import prepare_fits_catalog
    TT = fits_table()
    TT.bx = CX.ravel()
    TT.by = CY.ravel()
    TT.ba = BA.ravel()
    TT.phi = PHI.ravel()

    tcat = tractor.Catalog(*cat)
    T2 = prepare_fits_catalog(tcat, None, TT, bands, save_invvars=False)
    T2.writeto('sim-cat.fits')

    tr = Tractor(tims, cat)

    for band, tim in zip(bands, tims):
        mod = tr.getModelImage(tim)
        mod += np.random.standard_normal(
            size=tim.shape) * 1. / tim.getInvError()
        fitsio.write('sim-%s.fits' % band, mod, clobber=True)
        tim.data = mod

    ccds = fits_table()
    ccds.filter = np.array([f for f in bands])
    ccds.ccd_cuts = np.zeros(len(ccds), np.int16)
    ccds.imgfn = np.array([tim.name for tim in tims])
    ccds.propid = np.array(['2020A-000'] * len(ccds))
    ccds.fwhm = np.zeros(len(ccds), np.float32) + psf_sigma * 2.35
    ccds.mjd_obs = np.zeros(len(ccds))
    ccds.camera = np.array(['fake'] * len(ccds))

    survey = FakeLegacySurvey(ccds, tims)

    import logging
    verbose = False
    if verbose == 0:
        lvl = logging.INFO
    else:
        lvl = logging.DEBUG
    logging.basicConfig(level=lvl, format='%(message)s', stream=sys.stdout)
    # tractor logging is *soooo* chatty
    logging.getLogger('tractor.engine').setLevel(lvl + 10)

    run_brick(None,
              survey,
              radec=(ra, dec),
              width=W,
              height=H,
              do_calibs=False,
              gaia_stars=False,
              large_galaxies=False,
              tycho_stars=False,
              forceall=True,
              outliers=False)  #, stages=['image_coadds'])
Exemple #5
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