Skip to content

Commit

Permalink
Merge pull request #601 from desihub/mws_sv0_fixes
Browse files Browse the repository at this point in the history
Optimize for MWS-specific tiles in minisv3
  • Loading branch information
apcooper committed Apr 21, 2020
2 parents b73384e + 36b5839 commit b6b13ae
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 31 deletions.
8 changes: 8 additions & 0 deletions doc/changes.rst
Expand Up @@ -5,6 +5,13 @@ desitarget Change Log
0.37.4 (unreleased)
-------------------

* Fixes a typo in the priority of MWS_WD_SV targets [`PR #601`_].
* Fixes calc_priority logic for MWS CMX targets [`PR #601`_].
* Separates special case in calc_priority for CMX into a separate function [`PR #601`_].
* Alter cmx targetmask such taht obsconditionsc can be used to work around MWS/BGS
conflicts on MWS CMX tiles [`PR #601`_].
* Updates test_priorities to deal with new scheme for MWS CMX targets [`PR #601`_].
* Adds SV0_MWS_FAINT bit [`PR #601`_].
* Extra columns and features in the random catalogs [`PR #606`_]:
* Better error messages and defaults for `bin/supplement_randoms`.
* Don't calculate APFLUX quantities if aprad=0 is passed.
Expand All @@ -16,6 +23,7 @@ desitarget Change Log
* Recognize failure modes more quickly (and fail more quickly).
* Write out both "resolve" and "noresolve" (North/South) catalogs.

.. _`PR #601`: https://github.com/desihub/desitarget/pull/601
.. _`issue #597`: https://github.com/desihub/desitarget/issues/597
.. _`PR #606`: https://github.com/desihub/desitarget/pull/606

Expand Down
18 changes: 15 additions & 3 deletions py/desitarget/cmx/cmx_cuts.py
Expand Up @@ -378,6 +378,9 @@ def isSV0_MWS(rflux=None, obs_rflux=None, objtype=None, paramssolved=None,
:class:`array_like`
``True`` if and only if the object is an early-SV/main survey
MWS_WD target.
:class:`array_like`
``True`` if and only if the object is an early-SV/main survey
SV0_MWS_FAINT target.
Notes
-----
Expand All @@ -394,6 +397,7 @@ def isSV0_MWS(rflux=None, obs_rflux=None, objtype=None, paramssolved=None,
if primary is None:
primary = np.ones_like(rflux, dtype='?')
ismws = primary.copy()
ismws_faint = primary.copy()
isnear = primary.copy()
iswd = primary.copy()

Expand All @@ -402,6 +406,13 @@ def isSV0_MWS(rflux=None, obs_rflux=None, objtype=None, paramssolved=None,
ismws &= gaia
# ADM main targets are point-like.
ismws &= _psflike(objtype)

# APC faint MWS filler for minsv3+ tiles
# APC no constraint on obs_rflux
ismws_faint &= ismws
ismws_faint &= rflux > 10**((22.5-21.0)/2.5)
ismws_faint &= rflux <= 10**((22.5-19.0)/2.5)

# ADM main targets are 16 <= r < 19.
ismws &= rflux > 10**((22.5-19.0)/2.5)
ismws &= rflux <= 10**((22.5-16.0)/2.5)
Expand Down Expand Up @@ -483,7 +494,7 @@ def isSV0_MWS(rflux=None, obs_rflux=None, objtype=None, paramssolved=None,
((gaiaaen < 1.) & (parallaxovererror > 4.) & (pm > 10.)))

# ADM return any object that passes the MWS cuts.
return ismws | isnear, iswd
return ismws | isnear, iswd, ismws_faint


def isSV0_LRG(gflux=None, rflux=None, zflux=None, w1flux=None,
Expand Down Expand Up @@ -2095,8 +2106,8 @@ def apply_cuts(objects, cmxdir=None, noqso=False):
objtype=objtype, primary=primary
)

# ADM determine if an object is SV0_MWS or WD.
sv0_mws, sv0_wd = isSV0_MWS(
# ADM determine if an object is SV0_MWS, WD or SV0_MWS_FAINT.
sv0_mws, sv0_wd, sv0_mws_faint = isSV0_MWS(
rflux=rflux, obs_rflux=obs_rflux, objtype=objtype,
gaiagmag=gaiagmag, gaiabmag=gaiabmag, gaiarmag=gaiarmag,
pmra=pmra, pmdec=pmdec, parallax=parallax,
Expand Down Expand Up @@ -2263,6 +2274,7 @@ def apply_cuts(objects, cmxdir=None, noqso=False):
cmx_target |= mini_sv_elg * cmx_mask.MINI_SV_ELG
cmx_target |= mini_sv_qso * cmx_mask.MINI_SV_QSO
cmx_target |= mini_sv_bgs_bright * cmx_mask.MINI_SV_BGS_BRIGHT
cmx_target |= sv0_mws_faint * cmx_mask.SV0_MWS_FAINT

# ADM update the priority with any shifts.
# ADM we may need to update this logic if there are other shifts.
Expand Down
46 changes: 25 additions & 21 deletions py/desitarget/cmx/data/cmx_targetmask.yaml
Expand Up @@ -3,24 +3,24 @@ cmx_mask:

- [STD_GAIA, 0, "Gaia stars used for dithering (and other) tests", {obsconditions: DARK|GRAY|BRIGHT}]
- [SV0_STD_FAINT, 1, "SV-like STD_FAINT class is set (very early SV selection)", {obsconditions: DARK|GRAY}]
- [SV0_STD_BRIGHT, 2, "SV-like STD_BRIGHT class is set (very early SV selection)", {obsconditions: BRIGHT}]
- [SV0_STD_BRIGHT, 2, "SV-like STD_BRIGHT class is set (very early SV selection)", {obsconditions: BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [STD_TEST, 3, "Very bright stars for early tests", {obsconditions: DARK|GRAY|BRIGHT}]
- [STD_CALSPEC, 4, "Matches to CALSPEC stars", {obsconditions: DARK|GRAY|BRIGHT}]
- [STD_CALSPEC, 4, "Matches to CALSPEC stars", {obsconditions: DARK|GRAY|BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [STD_DITHER, 5, "Gaia stars specifically for dithering tests", {obsconditions: DARK|GRAY|BRIGHT}]
- [SV0_MWS_CLUSTER, 6, "SV-like Open and Globular clusters for the MWS", {obsconditions: DARK|GRAY}]
- [SV0_MWS_CLUSTER_VERYBRIGHT, 7, "Bright SV-like Open and Globular clusters for the MWS", {obsconditions: BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [SV0_MWS_CLUSTER, 6, "SV-like Open and Globular clusters for the MWS", {obsconditions: POOR|TWILIGHT12|TWILIGHT18}]
- [SV0_MWS_CLUSTER_VERYBRIGHT, 7, "Bright SV-like Open and Globular clusters for the MWS", {obsconditions: TWILIGHT12|TWILIGHT18}]

# ADM targeting bits that should resemble at least the initial SV selections ("SV0").
- [SV0_BGS, 8, "SV-like BGS bit is set (very early SV selection)", {obsconditions: BRIGHT}]
- [SV0_MWS, 9, "SV-like MWS bit is set (very early SV selection)", {obsconditions: BRIGHT}]
- [SV0_MWS, 9, "SV-like MWS bit is set (very early SV selection)", {obsconditions: BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [SV0_LRG, 10, "SV-like LRG bit is set (very early SV selection)", {obsconditions: DARK}]
- [SV0_ELG, 11, "SV-like ELG bit is set (very early SV selection)", {obsconditions: DARK|GRAY}]
- [SV0_QSO, 12, "SV-like QSO bit is set (very early SV/RF selection)", {obsconditions: DARK}]
- [SV0_WD, 13, "SV-like WD bit is set (very early MWS_WD selection)", {obsconditions: BRIGHT}]
- [SV0_WD, 13, "SV-like WD bit is set (very early MWS_WD selection)", {obsconditions: BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [SV0_QSO_Z5, 14, "SV-like QSO bit is set (specifically for the QSO_Z5 selection from SV", {obsconditions: DARK}]

# ADM back-up targets for poor conditions.
- [BACKUP_BRIGHT, 16, "Bright Gaia targets for poor conditions", {obsconditions: POOR|TWILIGHT12|TWILIGHT18}]
- [BACKUP_BRIGHT, 16, "Bright Gaia targets for poor conditions", {obsconditions: TWILIGHT12|TWILIGHT18}]
- [BACKUP_FAINT, 17, "Fainter Gaia targets for poor conditions", {obsconditions: POOR|TWILIGHT12|TWILIGHT18}]

# ADM first light targets.
Expand Down Expand Up @@ -54,10 +54,12 @@ cmx_mask:

#- ADM retain bits 49-52 for masking/convenience (to mirror the main survey)

- [MINI_SV_LRG, 53, "LRGs for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [MINI_SV_ELG, 54, "ELGs for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [MINI_SV_QSO, 55, "QSOs (RF) for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [MINI_SV_BGS_BRIGHT, 56, "BGS (bright) for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT|POOR|TWILIGHT12|TWILIGHT18}]
- [MINI_SV_LRG, 53, "LRGs for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT}]
- [MINI_SV_ELG, 54, "ELGs for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT}]
- [MINI_SV_QSO, 55, "QSOs (RF) for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT}]
- [MINI_SV_BGS_BRIGHT, 56, "BGS (bright) for Mini SV tests (NORTH+SOUTH with noresolve)", {obsconditions: DARK|GRAY|BRIGHT}]

- [SV0_MWS_FAINT, 57, "Faint stars for Mini SV tests", {obsconditions: POOR|TWILIGHT12|TWILIGHT18}]

#- Calibration targets. Shared between main/cmx/sv programs.
- [SKY, 32, "Blank sky locations",
Expand Down Expand Up @@ -104,8 +106,8 @@ priorities:
STD_TEST: {UNOBS: 2800, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
STD_CALSPEC: {UNOBS: 3000, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
STD_DITHER: {UNOBS: 2400, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS_CLUSTER: {UNOBS: 1601, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS_CLUSTER_VERYBRIGHT: {UNOBS: 1600, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS_CLUSTER: {UNOBS: 1600, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS_CLUSTER_VERYBRIGHT: {UNOBS: 1601, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_BGS: {UNOBS: 2100, MORE_ZWARN: 2100, MORE_ZGOOD: 1000, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS: {UNOBS: 1500, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_ELG: {UNOBS: 3000, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
Expand Down Expand Up @@ -143,6 +145,7 @@ priorities:
MINI_SV_ELG: {UNOBS: 3001, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
MINI_SV_QSO: {UNOBS: 3420, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
MINI_SV_BGS_BRIGHT: {UNOBS: 2101, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
SV0_MWS_FAINT: {UNOBS: 5, DONE: 2, OBS: 1, DONOTOBSERVE: 0}
BAD_SKY: {UNOBS: 0, OBS: 0, DONE: 0, MORE_ZWARN: 0, MORE_ZGOOD: 0}
#- Standards and sky are treated specially; priorities don't apply
STD_FAINT: -1
Expand All @@ -155,20 +158,20 @@ priorities:
# ADM -1 means that the concept of NUMOBS doesn't apply to this bit
numobs:
cmx_mask:
STD_GAIA: 1
SV0_STD_FAINT: 1
SV0_STD_BRIGHT: 1
STD_GAIA: 100
SV0_STD_FAINT: 100
SV0_STD_BRIGHT: 100
STD_TEST: 1
STD_CALSPEC: 1
STD_CALSPEC: 100
STD_DITHER: 1
SV0_MWS_CLUSTER: 1
SV0_MWS_CLUSTER_VERYBRIGHT: 1
SV0_MWS_CLUSTER: 100
SV0_MWS_CLUSTER_VERYBRIGHT: 100
SV0_BGS: 1
SV0_MWS: 1
SV0_MWS: 100
SV0_ELG: 1
SV0_LRG: 2
SV0_QSO: 4
SV0_WD: 1
SV0_WD: 100
SV0_QSO_Z5: 4
BACKUP_BRIGHT: 1
BACKUP_FAINT: 1
Expand Down Expand Up @@ -200,6 +203,7 @@ numobs:
MINI_SV_LRG: 2
MINI_SV_QSO: 4
MINI_SV_BGS_BRIGHT: 1
SV0_MWS_FAINT: 1
BAD_SKY: 0
#- Standards and sky are treated specially; NUMOBS doesn't apply
STD_FAINT: -1
Expand Down
56 changes: 55 additions & 1 deletion py/desitarget/targets.py
Expand Up @@ -548,7 +548,61 @@ def calc_priority(targets, zcat, obscon):

# ADM Special case: SV-like commissioning targets.
if 'CMX_TARGET' in targets.dtype.names:
for name in ['SV0_' + label for label in ('BGS', 'MWS')]:
priority = _cmx_calc_priority(targets, priority, obscon,
unobs, done, zgood, zwarn, cmx_mask, obsconditions)

return priority


def _cmx_calc_priority(targets, priority, obscon, unobs, done, zgood, zwarn, cmx_mask, obsconditions):
"""Special-case logic for target priorities in CMX.
Parameters
----------
targets : :class:`~numpy.ndarray`
numpy structured array or astropy Table of targets. Must include
the column `CMX_TARGET`.
priority : :class:`~numpy.ndarray`
Initial priority values set, in calc_priorities().
obscon : :class:`str`
A combination of strings that are in the desitarget bitmask yaml
file (specifically in `desitarget.targetmask.obsconditions`), e.g.
"DARK|GRAY". Governs the behavior of how priorities are set based
on "obsconditions" in the desitarget bitmask yaml file.
unobs : :class:`~numpy.ndarray`
Boolean flag on targets indicating state UNOBS.
done : :class:`~numpy.ndarray`
Boolean flag on targets indicating state DONE.
zgood : :class:`~numpy.ndarray`
Boolean flag on targets indicating state ZGOOD.
zwarn : :class:`~numpy.ndarray`
Boolean flag on targets indicating state ZWARN.
cmx_mask : :class:`~desiutil.bitmask.BitMask`
The CMX target bitmask.
obscondtions : :class:`~desiutil.bitmask.BitMask`
The CMX obsconditions bitmask.
Returns
-------
:class:`~numpy.ndarray`
The updated priority values.
Notes
-----
- Intended to be called only from within calc_priority(), where any
pre-processing of the target state flags (uobs, done, zgood, zwarn) is
handled.
"""
# Build a whitelist of targets to update
names_to_update = ['SV0_' + label for label in ('STD_FAINT', 'STD_BRIGHT',
'BGS', 'MWS', 'WD', 'MWS_FAINT',
'MWS_CLUSTER', 'MWS_CLUSTER_VERYBRIGHT')]
names_to_update.extend(['BACKUP_BRIGHT', 'BACKUP_FAINT'])

for name in names_to_update:
pricon = obsconditions.mask(cmx_mask[name].obsconditions)
if (obsconditions.mask(obscon) & pricon) != 0:
ii = (targets['CMX_TARGET'] & cmx_mask[name]) != 0
priority[ii & unobs] = np.maximum(priority[ii & unobs], cmx_mask[name].priorities['UNOBS'])
priority[ii & done] = np.maximum(priority[ii & done], cmx_mask[name].priorities['DONE'])
Expand Down
15 changes: 9 additions & 6 deletions py/desitarget/test/test_priorities.py
Expand Up @@ -195,19 +195,22 @@ def test_cmx_priorities(self):
colnames, masks, _ = main_cmx_or_sv(t)
cmx_mask = masks[0]

# ADM test handling of unobserved SV0_BGS and SV0_MWS.
for name in ["SV0_BGS", "SV0_MWS"]:
# ADM test handling of unobserved SV0_BGS and SV0_MWS
for name, obscon in [("SV0_BGS", "BRIGHT"), ("SV0_MWS", "POOR")]:
t['CMX_TARGET'] = cmx_mask[name]
self.assertTrue(np.all(calc_priority(
t, z, "GRAY|DARK") == cmx_mask[name].priorities['UNOBS']))
t, z, obscon) == cmx_mask[name].priorities['UNOBS']))

# ADM done is Done, regardless of ZWARN.
for name in ["SV0_BGS", "SV0_MWS"]:
for name, obscon in [("SV0_BGS", "BRIGHT"), ("SV0_MWS", "POOR")]:
t['CMX_TARGET'] = cmx_mask[name]
t["PRIORITY_INIT"], t["NUMOBS_INIT"] = initial_priority_numobs(t)
z['NUMOBS'] = [0, 1, 1]

# APC: Use NUMOBS_INIT here to avoid hardcoding NOBS corresponding to "done".
numobs_done = t['NUMOBS_INIT'][0]
z['NUMOBS'] = [0, numobs_done, numobs_done]
z['ZWARN'] = [1, 1, 0]
p = make_mtl(t, "GRAY|DARK", zcat=z)["PRIORITY"]
p = make_mtl(t, obscon, zcat=z)["PRIORITY"]

self.assertEqual(p[0], cmx_mask[name].priorities['UNOBS'])
self.assertEqual(p[1], cmx_mask[name].priorities['DONE'])
Expand Down

0 comments on commit b6b13ae

Please sign in to comment.