def _test_table_row(self, targets): """Test cuts work with tables from several I/O libraries """ # ADM only test the ELG cuts for speed. There's a # ADM full run through all classes in test_cuts_basic. tc = ["ELG"] # ADM add the DR7/DR8 data columns if they aren't there yet. # ADM can remove this once DR8 is finalized. if "MASKBITS" not in targets.dtype.names: targets = io.add_dr8_columns(targets) self.assertFalse(cuts._is_row(targets)) self.assertTrue(cuts._is_row(targets[0])) desi, bgs, mws = cuts.apply_cuts(targets, tcnames=tc) self.assertEqual(len(desi), len(targets)) self.assertEqual(len(bgs), len(targets)) self.assertEqual(len(mws), len(targets)) desi, bgs, mws = cuts.apply_cuts(targets[0], tcnames=tc) self.assertTrue(isinstance(desi, numbers.Integral), 'DESI_TARGET mask not an int') self.assertTrue(isinstance(bgs, numbers.Integral), 'BGS_TARGET mask not an int') self.assertTrue(isinstance(mws, numbers.Integral), 'MWS_TARGET mask not an int')
def _test_table_row(self, targets): self.assertFalse(cuts._is_row(targets)) self.assertTrue(cuts._is_row(targets[0])) desi, bgs, mws = cuts.apply_cuts(targets) self.assertEqual(len(desi), len(targets)) self.assertEqual(len(bgs), len(targets)) self.assertEqual(len(mws), len(targets)) desi, bgs, mws = cuts.apply_cuts(targets[0]) self.assertTrue(isinstance(desi, int), 'DESI_TARGET mask not an int') self.assertTrue(isinstance(bgs, int), 'BGS_TARGET mask not an int') self.assertTrue(isinstance(mws, int), 'MWS_TARGET mask not an int')
def _test_table_row(self, targets): self.assertFalse(cuts._is_row(targets)) self.assertTrue(cuts._is_row(targets[0])) desi, bgs, mws = cuts.apply_cuts(targets) self.assertEqual(len(desi), len(targets)) self.assertEqual(len(bgs), len(targets)) self.assertEqual(len(mws), len(targets)) desi, bgs, mws = cuts.apply_cuts(targets[0]) self.assertTrue(isinstance(desi, numbers.Integral), 'DESI_TARGET mask not an int') self.assertTrue(isinstance(bgs, numbers.Integral), 'BGS_TARGET mask not an int') self.assertTrue(isinstance(mws, numbers.Integral), 'MWS_TARGET mask not an int')
def apply_cuts(objects, cmxdir=None, noqso=False): """Commissioning (cmx) target selection, return target mask arrays. Parameters ---------- objects: numpy structured array with UPPERCASE columns needed for target selection, OR a string tractor/sweep filename cmxdir : :class:`str`, optional, defaults to :envvar:`CMX_DIR` Directory to find commmissioning files to which to match, such as the CALSPEC stars. If not specified, the cmx directory is taken to be the value of :envvar:`CMX_DIR`. noqso : :class:`boolean`, optional, defaults to ``False`` If passed, do not run the quasar selection. All QSO bits will be set to zero. Intended use is to speed unit tests. Returns ------- :class:`~numpy.ndarray` commissioning target selection bitmask flags for each object. See desitarget.cmx.cmx_targetmask.cmx_mask for bit definitions. """ # -Check if objects is a filename instead of the actual data if isinstance(objects, str): objects = io.read_tractor(objects) # -Ensure uppercase column names if astropy Table if isinstance(objects, (Table, Row)): for col in list(objects.columns.values()): if not col.name.isupper(): col.name = col.name.upper() # ADM retrieve/check the cmxdir. cmxdir = _get_cmxdir(cmxdir) # ADM As we need the column names. colnames = _get_colnames(objects) photsys_north, photsys_south, obs_rflux, gflux, rflux, zflux, \ w1flux, w2flux, rfiberflux, objtype, release, \ gfluxivar, rfluxivar, zfluxivar, \ gnobs, rnobs, znobs, gfracflux, rfracflux, zfracflux, \ gfracmasked, rfracmasked, zfracmasked, \ gfracin, rfracin, zfracin, gallmask, rallmask, zallmask, \ gsnr, rsnr, zsnr, w1snr, w2snr, dchisq, deltaChi2, maskbits = \ _prepare_optical_wise(objects) # ADM in addition, cmx needs ra and dec. ra, dec = objects["RA"], objects["DEC"] # ADM Currently only coded for objects with Gaia matches # ADM (e.g. DR6 or above). Fail for earlier Data Releases. if np.any(release < 6000): log.critical('Commissioning cuts only coded for DR6 or above') raise ValueError if (np.max(objects['PMRA']) == 0.) & np.any(release < 7000): d = "/project/projectdirs/desi/target/gaia_dr2_match_dr6" log.info("Zero objects have a proper motion.") log.critical( "Did you mean to send the Gaia-matched sweeps in, e.g., {}?". format(d)) raise IOError # Process the Gaia inputs for target selection. gaia, pmra, pmdec, parallax, parallaxovererror, parallaxerr, gaiagmag, gaiabmag, \ gaiarmag, gaiaaen, gaiadupsource, Grr, gaiaparamssolved, gaiabprpfactor, \ gaiasigma5dmax, galb = _prepare_gaia(objects, colnames=colnames) # ADM a couple of extra columns; the observed g/z fluxes. obs_gflux, obs_zflux = objects['FLUX_G'], objects['FLUX_Z'] # ADM initially, every object passes the cuts (is True). # ADM need to guard against the case of a single row being passed. # ADM initially every class has a priority shift of zero. if _is_row(objects): primary = np.bool_(True) priority_shift = np.array(0) else: primary = np.ones_like(objects, dtype=bool) priority_shift = np.zeros_like(objects, dtype=int) # ADM determine if an object passes the default logic for cmx stars. isgood = passesSTD_logic(gfracflux=gfracflux, rfracflux=rfracflux, zfracflux=zfracflux, objtype=objtype, gaia=gaia, pmra=pmra, pmdec=pmdec, aen=gaiaaen, dupsource=gaiadupsource, paramssolved=gaiaparamssolved, primary=primary) # ADM determine if an object is a "dither" star. # ADM and priority shift. std_dither, shift_dither = isSTD_dither(obs_gflux=obs_gflux, obs_rflux=obs_rflux, obs_zflux=obs_zflux, isgood=isgood, primary=primary) # ADM determine if an object is a bright test star. std_test = isSTD_test(obs_gflux=obs_gflux, obs_rflux=obs_rflux, obs_zflux=obs_zflux, isgood=isgood, primary=primary) # ADM determine if an object matched a CALSPEC standard. std_calspec = isSTD_calspec(ra=ra, dec=dec, cmxdir=cmxdir, primary=primary) # ADM determine if an object is SV0_BGS. sv0_bgs = isSV0_BGS(rflux=rflux, objtype=objtype, primary=primary) # ADM determine if an object is SV0_MWS or WD. sv0_mws, sv0_wd = isSV0_MWS(rflux=rflux, obs_rflux=obs_rflux, objtype=objtype, gaiagmag=gaiagmag, gaiabmag=gaiabmag, gaiarmag=gaiarmag, pmra=pmra, pmdec=pmdec, parallax=parallax, parallaxerr=parallaxerr, parallaxovererror=parallaxovererror, photbprpexcessfactor=gaiabprpfactor, astrometricsigma5dmax=gaiasigma5dmax, gaiaaen=gaiaaen, paramssolved=gaiaparamssolved, galb=galb, gaia=gaia, primary=primary) # ADM determine if an object is SV0_LRG. sv0_lrg = isSV0_LRG(gflux=gflux, rflux=rflux, zflux=zflux, w1flux=w1flux, rflux_snr=rsnr, zflux_snr=zsnr, w1flux_snr=w1snr, gflux_ivar=gfluxivar, primary=primary) # ADM determine if an object is SV0_ELG. sv0_elg = isSV0_ELG(primary=primary, gflux=gflux, rflux=rflux, zflux=zflux, gsnr=gsnr, rsnr=rsnr, zsnr=zsnr, maskbits=maskbits) # ADM determine if an object is SV0_QSO. if noqso: # ADM don't run quasar cuts if requested, for speed. sv0_qso = ~primary else: sv0_qso = isSV0_QSO(primary=primary, zflux=zflux, rflux=rflux, gflux=gflux, w1flux=w1flux, w2flux=w2flux, objtype=objtype, dchisq=dchisq, maskbits=maskbits) # ADM run the SV0 STD target types for both faint and bright. # ADM Make sure to pass all of the needed columns! At one point we stopped # ADM passing objtype, which meant no standards were being returned. sv0_std_classes = [] for bright in [False, True]: sv0_std_classes.append( isSV0_STD(primary=primary, zflux=zflux, rflux=rflux, gflux=gflux, gfracflux=gfracflux, rfracflux=rfracflux, zfracflux=zfracflux, gfracmasked=gfracmasked, rfracmasked=rfracmasked, objtype=objtype, zfracmasked=zfracmasked, gnobs=gnobs, rnobs=rnobs, znobs=znobs, gfluxivar=gfluxivar, rfluxivar=rfluxivar, zfluxivar=zfluxivar, gaia=gaia, astrometricexcessnoise=gaiaaen, paramssolved=gaiaparamssolved, pmra=pmra, pmdec=pmdec, parallax=parallax, dupsource=gaiadupsource, gaiagmag=gaiagmag, gaiabmag=gaiabmag, gaiarmag=gaiarmag, bright=bright)) sv0_std_faint, sv0_std_bright = sv0_std_classes # ADM the nominal main survey cuts for standard stars. These are currently # ADM identical to the SV0 cuts, so treat accordingly: std_faint, std_bright = sv0_std_classes # ADM Construct the target flag bits. cmx_target = std_dither * cmx_mask.STD_GAIA cmx_target |= std_test * cmx_mask.STD_TEST cmx_target |= std_calspec * cmx_mask.STD_CALSPEC cmx_target |= sv0_std_faint * cmx_mask.SV0_STD_FAINT cmx_target |= sv0_std_bright * cmx_mask.SV0_STD_BRIGHT cmx_target |= sv0_bgs * cmx_mask.SV0_BGS cmx_target |= sv0_mws * cmx_mask.SV0_MWS cmx_target |= sv0_lrg * cmx_mask.SV0_LRG cmx_target |= sv0_elg * cmx_mask.SV0_ELG cmx_target |= sv0_qso * cmx_mask.SV0_QSO cmx_target |= sv0_wd * cmx_mask.SV0_WD cmx_target |= std_faint * cmx_mask.STD_FAINT cmx_target |= std_bright * cmx_mask.STD_BRIGHT # ADM update the priority with any shifts. # ADM we may need to update this logic if there are other shifts. priority_shift[std_dither] = shift_dither[std_dither] return cmx_target, priority_shift
def apply_cuts(objects, cmxdir=None): """Perform commissioning (cmx) target selection on objects, return target mask arrays Parameters ---------- objects: numpy structured array with UPPERCASE columns needed for target selection, OR a string tractor/sweep filename cmxdir : :class:`str`, optional, defaults to :envvar:`CMX_DIR` Directory in which to find commmissioning files to which to match, such as the CALSPEC stars. If not specified, the cmx directory is taken to be the value of the :envvar:`CMX_DIR` environment variable. Returns ------- :class:`~numpy.ndarray` commissioning target selection bitmask flags for each object See desitarget.cmx.cmx_targetmask.cmx_mask for the definition of each bit """ # -Check if objects is a filename instead of the actual data if isinstance(objects, str): objects = io.read_tractor(objects) # -Ensure uppercase column names if astropy Table if isinstance(objects, (Table, Row)): for col in list(objects.columns.values()): if not col.name.isupper(): col.name = col.name.upper() # ADM retrieve/check the cmxdir. cmxdir = _get_cmxdir(cmxdir) # ADM As we need the column names. colnames = _get_colnames(objects) photsys_north, photsys_south, obs_rflux, gflux, rflux, zflux, \ w1flux, w2flux, rfiberflux, objtype, release, gfluxivar, rfluxivar, zfluxivar, \ gnobs, rnobs, znobs, gfracflux, rfracflux, zfracflux, \ gfracmasked, rfracmasked, zfracmasked, \ gfracin, rfracin, zfracin, gallmask, rallmask, zallmask, \ gsnr, rsnr, zsnr, w1snr, w2snr, dchisq, deltaChi2, brightstarinblob = \ _prepare_optical_wise(objects, colnames=colnames) # ADM in addition, cmx needs ra and dec. ra, dec = objects["RA"], objects["DEC"] # ADM Currently only coded for objects with Gaia matches # ADM (e.g. DR6 or above). Fail for earlier Data Releases. if np.any(release < 6000): log.critical('Commissioning cuts only coded for DR6 or above') raise ValueError if (np.max(objects['PMRA']) == 0.) & np.any(release < 7000): d = "/project/projectdirs/desi/target/gaia_dr2_match_dr6" log.info("Zero objects have a proper motion.") log.critical( "Did you mean to send the Gaia-matched sweeps in, e.g., {}?". format(d)) raise IOError # Process the Gaia inputs for target selection. gaia, pmra, pmdec, parallax, parallaxovererror, parallaxerr, gaiagmag, gaiabmag, \ gaiarmag, gaiaaen, gaiadupsource, Grr, gaiaparamssolved, gaiabprpfactor, \ gaiasigma5dmax, galb = _prepare_gaia(objects, colnames=colnames) # ADM a couple of extra columns; the observed g/z fluxes. obs_gflux, obs_zflux = objects['FLUX_G'], objects['FLUX_Z'] # ADM initially, every object passes the cuts (is True). # ADM need to guard against the case of a single row being passed. # ADM initially every class has a priority shift of zero. if _is_row(objects): primary = np.bool_(True) priority_shift = np.array(0) else: primary = np.ones_like(objects, dtype=bool) priority_shift = np.zeros_like(objects, dtype=int) # ADM determine if an object passes the default logic for cmx stars. isgood = passesSTD_logic(gfracflux=gfracflux, rfracflux=rfracflux, zfracflux=zfracflux, objtype=objtype, gaia=gaia, pmra=pmra, pmdec=pmdec, aen=gaiaaen, dupsource=gaiadupsource, paramssolved=gaiaparamssolved, primary=primary) # ADM determine if an object is a "dither" star. std_dither, shift_dither = isSTD_dither(obs_gflux=obs_gflux, obs_rflux=obs_rflux, obs_zflux=obs_zflux, isgood=isgood, primary=primary) # ADM set up an initial priority shift. # ADM determine if an object is a bright test star. std_test = isSTD_test(obs_gflux=obs_gflux, obs_rflux=obs_rflux, obs_zflux=obs_zflux, isgood=isgood, primary=primary) # ADM determine if an object matched a CALSPEC standard. std_calspec = isSTD_calspec(ra=ra, dec=dec, cmxdir=cmxdir, primary=primary) # ADM determine if an object is SV0_STD_BRIGHT. Resembles first # ADM iteration of SV, but locked in cmx_cuts (and could be altered). sv0_std_bright = isSV0_STD_bright(gflux=gflux, rflux=rflux, zflux=zflux, pmra=pmra, pmdec=pmdec, parallax=parallax, gaiagmag=gaiagmag, isgood=isgood, primary=primary) # ADM determine if an object is SV0_BGS sv0_bgs = isSV0_BGS(rflux=rflux, objtype=objtype, primary=primary) # ADM determine if an object is SV0_MWS sv0_mws = isSV0_MWS(rflux=rflux, obs_rflux=obs_rflux, objtype=objtype, gaiagmag=gaiagmag, gaiabmag=gaiabmag, gaiarmag=gaiarmag, pmra=pmra, pmdec=pmdec, parallax=parallax, parallaxovererror=parallaxovererror, photbprpexcessfactor=gaiabprpfactor, astrometricsigma5dmax=gaiasigma5dmax, galb=galb, gaia=gaia, primary=primary) # ADM Construct the targetflag bits. cmx_target = std_dither * cmx_mask.STD_GAIA cmx_target |= std_test * cmx_mask.STD_TEST cmx_target |= std_calspec * cmx_mask.STD_CALSPEC cmx_target |= sv0_std_bright * cmx_mask.SV0_STD_BRIGHT cmx_target |= sv0_bgs * cmx_mask.SV0_BGS cmx_target |= sv0_mws * cmx_mask.SV0_MWS # ADM update the priority with any shifts. # ADM we may need to update this logic if there are other shifts. priority_shift[std_dither] = shift_dither[std_dither] return cmx_target, priority_shift