Exemplo n.º 1
0
gaia = GaiaCatalog().get_catalog_in_wcs(targetwcs)
print('Got Gaia stars:', gaia)
gaia.about()

gaia.G = gaia.phot_g_mean_mag
gaia.pointsource = np.logical_or(
    (gaia.G <= 18.) * (gaia.astrometric_excess_noise < 10.**0.5),
    (gaia.G >= 18.) * (gaia.astrometric_excess_noise < 10.**(0.5 + 1.25 / 4. *
                                                             (gaia.G - 18.))))

gaia.writeto('test-gaia.fits')

gaiacat = []
for g in gaia:
    gaiacat.append(GaiaSource.from_catalog(g, bands))
    print('Created source:', gaiacat[-1])

print()
print()
# Select the largest-parallax source.

gaia.parallax[np.logical_not(np.isfinite(gaia.parallax))] = 0.
i = np.argmax(gaia.parallax)
gsrc = gaia[i]
src = GaiaSource.from_catalog(gsrc, bands)

print('Source:', src)

ra, dec = src.pos.ra, src.pos.dec
Exemplo n.º 2
0
def read_tycho2(survey, targetwcs, bands):
    from astrometry.libkd.spherematch import tree_open, tree_search_radec
    from legacypipe.survey import GaiaSource
    tycho2fn = survey.find_file('tycho2')
    radius = 1.
    ra, dec = targetwcs.radec_center()
    # John added the "isgalaxy" flag 2018-05-10, from the Metz &
    # Geffert (04) catalog.

    # Eddie added the "zguess" column 2019-03-06, by matching with
    # 2MASS and estimating z based on APASS.

    # The "tycho2.kd.fits" file read here was produced by:
    #
    # fitscopy ~schlafly/legacysurvey/tycho-isgalaxyflag-2mass.fits"[col \
    #   tyc1;tyc2;tyc3;ra;dec;sigma_ra;sigma_dec;mean_ra;mean_dec;pm_ra;pm_dec; \
    #   sigma_pm_ra;sigma_pm_dec;epoch_ra;epoch_dec;mag_bt;mag_vt;mag_hp; \
    #   isgalaxy;Jmag;Hmag;Kmag,zguess]" /tmp/tycho2-astrom.fits
    # startree -P -k -n stars -T -i /tmp/tycho2-astrom.fits \
    #  -o /global/project/projectdirs/cosmo/staging/tycho2/tycho2.kd.fits

    kd = tree_open(tycho2fn, 'stars')
    I = tree_search_radec(kd, ra, dec, radius)
    debug(len(I), 'Tycho-2 stars within', radius,
          'deg of RA,Dec (%.3f, %.3f)' % (ra, dec))
    if len(I) == 0:
        return None
    # Read only the rows within range.
    tycho = fits_table(tycho2fn, rows=I)
    del kd
    if 'isgalaxy' in tycho.get_columns():
        tycho.cut(tycho.isgalaxy == 0)
        debug('Cut to', len(tycho), 'Tycho-2 stars on isgalaxy==0')
    else:
        print('Warning: no "isgalaxy" column in Tycho-2 catalog')

    tycho.ref_cat = np.array(['T2'] * len(tycho))
    # tyc1: [1,9537], tyc2: [1,12121], tyc3: [1,3]
    tycho.ref_id = (tycho.tyc1.astype(np.int64) * 1000000 +
                    tycho.tyc2.astype(np.int64) * 10 +
                    tycho.tyc3.astype(np.int64))
    with np.errstate(divide='ignore'):
        # In our Tycho-2 catalog, sigma_pm_* are in *arcsec/yr*, Gaia is in mas/yr.
        tycho.pmra_ivar = 1. / (tycho.sigma_pm_ra * 1000.)**2
        tycho.pmdec_ivar = 1. / (tycho.sigma_pm_dec * 1000.)**2
        tycho.ra_ivar = 1. / tycho.sigma_ra**2
        tycho.dec_ivar = 1. / tycho.sigma_dec**2
    tycho.rename('pm_ra', 'pmra')
    tycho.rename('pm_dec', 'pmdec')
    for c in ['pmra', 'pmdec', 'pmra_ivar', 'pmdec_ivar']:
        X = tycho.get(c)
        X[np.logical_not(np.isfinite(X))] = 0.
    tycho.mag = tycho.mag_vt
    # Patch missing mag values...
    tycho.mag[tycho.mag == 0] = tycho.mag_hp[tycho.mag == 0]
    tycho.mag[tycho.mag == 0] = tycho.mag_bt[tycho.mag == 0]

    # Use zguess
    tycho.mask_mag = tycho.mag
    with np.errstate(invalid='ignore'):
        I = np.flatnonzero(
            np.isfinite(tycho.zguess) * (tycho.zguess + 1. < tycho.mag))
    tycho.mask_mag[I] = tycho.zguess[I]
    # Per discussion in issue #306 -- cut on mag < 13.
    # This drops only 13k/2.5M stars.
    tycho.cut(tycho.mask_mag < 13.)

    tycho.radius = mask_radius_for_mag(tycho.mask_mag)
    tycho.keep_radius = 2. * tycho.radius

    for c in [
            'tyc1', 'tyc2', 'tyc3', 'mag_bt', 'mag_vt', 'mag_hp', 'mean_ra',
            'mean_dec', 'sigma_pm_ra', 'sigma_pm_dec', 'sigma_ra', 'sigma_dec'
    ]:
        tycho.delete_column(c)
    # add Gaia-style columns
    # No parallaxes in Tycho-2
    tycho.parallax = np.zeros(len(tycho), np.float32)
    # Tycho-2 "supplement" stars, from Hipparcos and Tycho-1 catalogs, have
    # ref_epoch = 0.  Fill in with the 1991.25 epoch of those catalogs.
    tycho.epoch_ra[tycho.epoch_ra == 0] = 1991.25
    tycho.epoch_dec[tycho.epoch_dec == 0] = 1991.25
    # Tycho-2 has separate epoch_ra and epoch_dec.
    # Move source to the mean epoch.
    tycho.ref_epoch = (tycho.epoch_ra + tycho.epoch_dec) / 2.
    cosdec = np.cos(np.deg2rad(tycho.dec))
    tycho.ra += (tycho.ref_epoch -
                 tycho.epoch_ra) * tycho.pmra / 3600. / cosdec
    tycho.dec += (tycho.ref_epoch - tycho.epoch_dec) * tycho.pmdec / 3600.
    # Tycho-2 proper motions are in arcsec/yr; Gaia are mas/yr.
    tycho.pmra *= 1000.
    tycho.pmdec *= 1000.
    # We already cut on John's "isgalaxy" flag
    tycho.pointsource = np.ones(len(tycho), bool)
    # phot_g_mean_mag -- for initial brightness of source
    tycho.phot_g_mean_mag = tycho.mag
    tycho.delete_column('epoch_ra')
    tycho.delete_column('epoch_dec')
    tycho.istycho = np.ones(len(tycho), bool)
    tycho.isbright = np.ones(len(tycho), bool)
    tycho.ismedium = np.ones(len(tycho), bool)
    tycho.donotfit = np.zeros(len(tycho), bool)
    tycho.sources = np.empty(len(tycho), object)
    if bands is not None:
        for i, t in enumerate(tycho):
            tycho.sources[i] = GaiaSource.from_catalog(t, bands)
    return tycho
Exemplo n.º 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
Exemplo n.º 4
0
def read_gaia(wcs, bands):
    '''
    *wcs* here should include margin
    '''
    from legacypipe.gaiacat import GaiaCatalog
    from legacypipe.survey import GaiaSource

    gaia = GaiaCatalog().get_catalog_in_wcs(wcs)
    debug('Got', len(gaia), 'Gaia stars nearby')

    gaia.G = gaia.phot_g_mean_mag
    # Sort by brightness (for reference-*.fits output table)
    gaia.cut(np.argsort(gaia.G))

    # Gaia to DECam color transformations for stars
    color = gaia.phot_bp_mean_mag - gaia.phot_rp_mean_mag
    # From Rongpu, 2020-04-12
    # no BP-RP color: use average color
    color[np.logical_not(np.isfinite(color))] = 1.4
    # clip to reasonable range for the polynomial fit
    color = np.clip(color, -0.6, 4.1)
    for b, coeffs in [
        ('g', [
            -0.1178631039, 0.3650113495, 0.5608615360, -0.2850687702,
            -1.0243473939, 1.4378375491, 0.0679401731, -1.1713172509,
            0.9107811975, -0.3374324004, 0.0683946390, -0.0073089582,
            0.0003230170
        ]),
        ('r', [
            0.1139078673, -0.2868955307, 0.0013196434, 0.1029151074,
            0.1196710702, -0.3729031390, 0.1859874242, 0.1370162451,
            -0.1808580848, 0.0803219195, -0.0180218196, 0.0020584707,
            -0.0000953486
        ]),
        ('z', [
            0.4811198057, -0.9990015041, 0.1403990019, 0.2150988888,
            -0.2917655866, 0.1326831887, -0.0259205004, 0.0018548776
        ])
    ]:
        mag = gaia.G.copy()
        for order, c in enumerate(coeffs):
            mag += c * color**order
        gaia.set('decam_mag_%s' % b, mag)
    del color

    #  For possible future use:
    #  BASS/MzLS:
    #  coeffs = dict(
    #  g = [-0.1299895823, 0.3120393968, 0.5989482686, 0.3125882487,
    #      -1.9401592247, 1.1011670449, 2.0741304659, -3.3930306403,
    #      2.1857291197, -0.7674676232, 0.1542300648, -0.0167007725,
    #      0.0007573720],
    #  r = [0.0901464643, -0.2463711147, 0.0094963025, -0.1187138789,
    #      0.4131107392, -0.1832183301, -0.6015486252, 0.9802538471,
    #      -0.6613809948, 0.2426395251, -0.0505867727, 0.0056462458,
    #      -0.0002625789],
    #  z = [0.4862049092, -1.0278704657, 0.1220984456, 0.3000129189,
    #      -0.3770662617, 0.1696090596, -0.0331679127, 0.0023867628])

    # force this source to remain a point source?
    # Long history here, starting DJS, [decam-chatter 5486] Solved! GAIA separation
    #   of point sources from extended sources
    # Updated for Gaia DR2 by Eisenstein,
    # [decam-data 2770] Re: [desi-milkyway 639] GAIA in DECaLS DR7
    # And made far more restrictive following BGS feedback.
    gaia.pointsource = np.logical_or(
        (gaia.G <= 18.) * (gaia.astrometric_excess_noise < 10.**0.5),
        (gaia.G <= 13.))

    # in our catalog files, this is in float32; in the Gaia data model it's
    # a byte, with only values 3 and 31 in DR2.
    gaia.astrometric_params_solved = gaia.astrometric_params_solved.astype(
        np.uint8)

    # Gaia version?
    gaiaver = int(os.getenv('GAIA_CAT_VER', '1'))
    gaia_release = 'G%i' % gaiaver
    gaia.ref_cat = np.array([gaia_release] * len(gaia))
    gaia.ref_id = gaia.source_id
    gaia.pmra_ivar = 1. / gaia.pmra_error**2
    gaia.pmdec_ivar = 1. / gaia.pmdec_error**2
    gaia.parallax_ivar = 1. / gaia.parallax_error**2
    # mas -> deg
    gaia.ra_ivar = 1. / (gaia.ra_error / 1000. / 3600.)**2
    gaia.dec_ivar = 1. / (gaia.dec_error / 1000. / 3600.)**2

    for c in [
            'ra_error', 'dec_error', 'parallax_error', 'pmra_error',
            'pmdec_error'
    ]:
        gaia.delete_column(c)
    for c in [
            'pmra', 'pmdec', 'parallax', 'pmra_ivar', 'pmdec_ivar',
            'parallax_ivar'
    ]:
        X = gaia.get(c)
        X[np.logical_not(np.isfinite(X))] = 0.

    # uniform name w/ Tycho-2
    gaia.zguess = gaia.decam_mag_z
    gaia.mag = gaia.G
    # Take the brighter of G, z to expand masks around red stars.
    gaia.mask_mag = np.minimum(gaia.G, gaia.zguess + 1.)

    # radius to consider affected by this star, for MASKBITS
    gaia.radius = mask_radius_for_mag(gaia.mask_mag)
    # radius for keeping this source in the ref catalog
    # (eg, for halo subtraction)
    gaia.keep_radius = 4. * gaia.radius
    gaia.delete_column('G')
    gaia.isgaia = np.ones(len(gaia), bool)
    gaia.istycho = np.zeros(len(gaia), bool)
    gaia.isbright = (gaia.mask_mag < 13.)
    gaia.ismedium = (gaia.mask_mag < 16.)
    gaia.donotfit = np.zeros(len(gaia), bool)

    # NOTE, must initialize gaia.sources array this way, or else numpy
    # will try to be clever and create a 2-d array, because GaiaSource is
    # iterable.
    gaia.sources = np.empty(len(gaia), object)
    if bands is not None:
        for i, g in enumerate(gaia):
            gaia.sources[i] = GaiaSource.from_catalog(g, bands)
    return gaia