예제 #1
0
def read_targets_in_box(hpdirname, radecbox=[0., 360., -90., 90.],
                        columns=None):
    """Read in targets in an RA/Dec box.

    Parameters
    ----------
    hpdirname : :class:`str`
        Full path to either a directory containing targets that
        have been partitioned by HEALPixel (i.e. as made by
        `select_targets` with the `bundle_files` option). Or the
        name of a single file of targets.
    radecbox : :class:`list`, defaults to the entire sky
        4-entry list of coordinates [ramin, ramax, decmin, decmax]
        forming the edges of a box in RA/Dec (degrees).
    columns : :class:`list`, optional
        Only read in these target columns.

    Returns
    -------
    :class:`~numpy.ndarray`
        An array of targets in the passed RA/Dec box.
    """
    # ADM we'll need RA/Dec for final cuts, so ensure they're read.
    addedcols = []
    columnscopy = None
    if columns is not None:
        # ADM make a copy of columns, as it's a kwarg we'll modify.
        columnscopy = columns.copy()
        for radec in ["RA", "DEC"]:
            if radec not in columnscopy:
                columnscopy.append(radec)
                addedcols.append(radec)

    # ADM if a directory was passed, do fancy HEALPixel parsing...
    if os.path.isdir(hpdirname):
        # ADM approximate nside for area of passed box.
        nside = pixarea2nside(box_area(radecbox))

        # ADM HEALPixels that touch the box for that nside.
        pixlist = hp_in_box(nside, radecbox)

        # ADM read in targets in these HEALPixels.
        targets = read_targets_in_hp(hpdirname, nside, pixlist,
                                     columns=columnscopy)
    # ADM ...otherwise just read in the targets.
    else:
        targets = fitsio.read(hpdirname, columns=columnscopy)

    # ADM restrict only to targets in the requested RA/Dec box...
    ii = is_in_box(targets, radecbox)
    # ADM ...and remove RA/Dec columns if we added them.
    targets = rfn.drop_fields(targets[ii], addedcols)

    return targets
예제 #2
0
    def test_targets_spatial(self):
        """Test applying RA/Dec/HEALpixel inputs to sweeps recovers same targets
        """
        # ADM only test some of the galaxy cuts for speed. There's a
        # ADM full run through all classes in test_cuts_basic.
        tc = ["LRG", "ELG", "BGS"]
        infiles = self.sweepfiles[2]

        targets = cuts.select_targets(infiles, numproc=1, tcnames=tc)

        # ADM test the RA/Dec box input.
        radecbox = [
            np.min(targets["RA"]) - 0.01,
            np.max(targets["RA"]) + 0.01,
            np.min(targets["DEC"]) - 0.01,
            np.max(targets["DEC"] + 0.01)
        ]
        t1 = cuts.select_targets(infiles,
                                 numproc=1,
                                 tcnames=tc,
                                 radecbox=radecbox)

        # ADM test the RA/Dec/radius cap input.
        centra, centdec = 0.5 * (radecbox[0] + radecbox[1]), 0.5 * (
            radecbox[2] + radecbox[3])
        # ADM 20 degrees should be a large enough radius for the sweeps.
        maxrad = 20.
        radecrad = centra, centdec, maxrad
        t2 = cuts.select_targets(infiles,
                                 numproc=1,
                                 tcnames=tc,
                                 radecrad=radecrad)

        # ADM test the pixel input.
        nside = pixarea2nside(box_area(radecbox))
        pixlist = hp_in_box(nside, radecbox)
        t3 = cuts.select_targets(infiles,
                                 numproc=1,
                                 tcnames=tc,
                                 nside=nside,
                                 pixlist=pixlist)

        # ADM sort each set of targets on TARGETID to compare them.
        targets = targets[np.argsort(targets["TARGETID"])]
        t1 = t1[np.argsort(t1["TARGETID"])]
        t2 = t2[np.argsort(t2["TARGETID"])]
        t3 = t3[np.argsort(t3["TARGETID"])]

        # ADM test the same targets were recovered and that
        # ADM each recovered target has the same bits set.
        for targs in t1, t2, t3:
            for col in "TARGETID", "DESI_TARGET", "BGS_TARGET", "MWS_TARGET":
                self.assertTrue(np.all(targs[col] == targets[col]))
예제 #3
0
def randoms_in_a_brick_from_edges(ramin,
                                  ramax,
                                  decmin,
                                  decmax,
                                  density=100000,
                                  poisson=True):
    """For given brick edges, return random (RA/Dec) positions in the brick

    Parameters
    ----------
    ramin : :class:`float`
        The minimum "edge" of the brick in Right Ascension.
    ramax : :class:`float`
        The maximum "edge" of the brick in Right Ascension.
    decmin : :class:`float`
        The minimum "edge" of the brick in Declination.
    decmax : :class:`float`
        The maximum "edge" of the brick in Declination.
    density : :class:`int`, optional, defaults to 100,000
        The number of random points to return per sq. deg. As a typical brick is
        ~0.25 x 0.25 sq. deg. about (0.0625*density) points will be returned.
    poisson : :class:`boolean`, optional, defaults to True
        Modify the number of random points in the brick so that instead of simply
        being the brick area x the density, it is a number drawn from a Poisson
        distribution with the expectation being the brick area x the density.

    Returns
    -------
    :class:`~numpy.array`
        Right Ascensions of random points in brick
    :class:`~numpy.array`
        Declinations of random points in brick
    """
    # ADM create a unique random seed on the basis of the brick.
    # ADM note this is only unique for bricksize=0.25 for bricks
    # ADM that are more than 0.25 degrees from the poles.
    uniqseed = int(4 * ramin) * 1000 + int(4 * (decmin + 90))
    np.random.seed(uniqseed)

    # ADM generate random points within the brick at the requested density
    # ADM guard against potential wraparound bugs (assuming bricks are typical
    # ADM sizes of 0.25 x 0.25 sq. deg., or not much larger than that
    if ramax - ramin > 350.:
        ramax -= 360.
    spharea = box_area([ramin, ramax, decmin, decmax])

    if poisson:
        nrand = int(np.random.poisson(spharea * density))
    else:
        nrand = int(spharea * density)


#    log.info('Full area covered by brick is {:.5f} sq. deg....t = {:.1f}s'
#              .format(spharea,time()-start))
    ras = np.random.uniform(ramin, ramax, nrand)
    sindecmin, sindecmax = np.sin(np.radians(decmin)), np.sin(
        np.radians(decmax))
    decs = np.degrees(
        np.arcsin(1. - np.random.uniform(1 - sindecmax, 1 - sindecmin, nrand)))

    nrand = len(ras)

    #    log.info('Generated {} randoms in brick with bounds [{:.3f},{:.3f},{:.3f},{:.3f}]...t = {:.1f}s'
    #                 .format(nrand,ramin,ramax,decmin,decmax,time()-start))

    return ras, decs
예제 #4
0
def randoms_in_a_brick_from_name(brickname, drdir, density=100000):
    """For a given brick name, return random (RA/Dec) positions in the brick.

    Parameters
    ----------
    brickname : :class:`str`
        Name of brick in which to generate random points.
    drdir : :class:`str`
       The root directory pointing to a Data Release from the Legacy Surveys
       e.g. /global/project/projectdirs/cosmo/data/legacysurvey/dr7.
    density : :class:`int`, optional, defaults to 100,000
        The number of random points to return per sq. deg. As a typical brick is
        ~0.25 x 0.25 sq. deg. about (0.0625*density) points will be returned.

    Returns
    -------
    :class:`~numpy.array`
        Right Ascensions of random points in brick.
    :class:`~numpy.array`
        Declinations of random points in brick.

    Notes
    -----
        - First version copied shamelessly from Anand Raichoor.
    """
    # ADM read in the survey bricks file to determine the brick boundaries
    hdu = fits.open(drdir + 'survey-bricks.fits.gz')

    brickinfo = hdu[1].data
    wbrick = np.where(brickinfo['brickname'] == brickname)[0]
    if len(wbrick) == 0:
        log.error('Brick {} does not exist'.format(brickname))
    # else:
    #    log.info('Working on brick {}...t = {:.1f}s'.format(brickname,time()-start))

    brick = brickinfo[wbrick][0]
    ramin, ramax, decmin, decmax = brick['ra1'], brick['ra2'], brick[
        'dec1'], brick['dec2']

    # ADM create a unique random seed on the basis of the brick.
    # ADM note this is only unique for bricksize=0.25 for bricks
    # ADM that are more than 0.25 degrees from the poles.
    uniqseed = int(4 * ramin) * 1000 + int(4 * (decmin + 90))
    np.random.seed(uniqseed)

    # ADM generate random points within the brick at the requested density
    # ADM guard against potential wraparound bugs
    if ramax - ramin > 350.:
        ramax -= 360.
    spharea = box_area([ramin, ramax, decmin, decmax])

    nrand = int(spharea * density)
    # log.info('Full area covered by brick {} is {:.5f} sq. deg....t = {:.1f}s'
    #          .format(brickname,spharea,time()-start))
    ras = np.random.uniform(ramin, ramax, nrand)
    sindecmin, sindecmax = np.sin(np.radians(decmin)), np.sin(
        np.radians(decmax))
    decs = np.degrees(
        np.arcsin(1. - np.random.uniform(1 - sindecmax, 1 - sindecmin, nrand)))

    nrand = len(ras)

    #    log.info('Generated {} randoms in brick {} with bounds [{:.3f},{:.3f},{:.3f},{:.3f}]...t = {:.1f}s'
    #                 .format(nrand,brickname,ramin,ramax,decmin,decmax,time()-start))

    return ras, decs