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
def resolve(targets): """Resolve which targets are primary in imaging overlap regions. Parameters ---------- targets : :class:`~numpy.ndarray` Rec array of targets. Must have columns "RA" and "DEC" and either "RELEASE" or "PHOTSYS". Returns ------- :class:`~numpy.ndarray` The original target list trimmed to only objects from the "northern" photometry in the northern imaging area and objects from "southern" photometry in the southern imaging area. """ # ADM retrieve the photometric system from the RELEASE. from desitarget.io import release_to_photsys, desitarget_resolve_dec if 'PHOTSYS' in targets.dtype.names: photsys = targets["PHOTSYS"] else: photsys = release_to_photsys(targets["RELEASE"]) # ADM a flag of which targets are from the 'N' photometry. from desitarget.cuts import _isonnorthphotsys photn = _isonnorthphotsys(photsys) # ADM grab the declination used to resolve targets. split = desitarget_resolve_dec() # ADM determine which targets are north of the Galactic plane. As # ADM a speed-up, bin in ~1 sq.deg. HEALPixels and determine # ADM which of those pixels are north of the Galactic plane. # ADM We should never be as close as ~1o to the plane. from desitarget.geomask import is_in_gal_box, pixarea2nside nside = pixarea2nside(1) theta, phi = np.radians(90 - targets["DEC"]), np.radians(targets["RA"]) pixnum = hp.ang2pix(nside, theta, phi, nest=True) # ADM find the pixels north of the Galactic plane... allpix = np.arange(hp.nside2npix(nside)) theta, phi = hp.pix2ang(nside, allpix, nest=True) ra, dec = np.degrees(phi), 90 - np.degrees(theta) pixn = is_in_gal_box([ra, dec], [0., 360., 0., 90.], radec=True) # ADM which targets are in pixels north of the Galactic plane. galn = pixn[pixnum] # ADM which targets are in the northern imaging area. arean = (targets["DEC"] >= split) & galn # ADM retain 'N' targets in 'N' area and 'S' in 'S' area. keep = (photn & arean) | (~photn & ~arean) return targets[keep]
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]))
def get_gaia_nside_brick(bricksize=0.25): """Grab the HEALPixel nside that corresponds to a brick. Parameters ---------- bricksize : :class:`float`, optional, defaults to 0.25 Size of the brick, default is the Legacy Surveys standard. Returns ------- :class:`int` The HEALPixel nside number that corresponds to a brick. """ return pixarea2nside(bricksize * bricksize)