Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalize dedicated secondaries for SV1 to SV2 transition #678

Merged
merged 6 commits into from
Mar 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ desitarget Change Log
0.50.1 (unreleased)
-------------------

* Finalize dedicated secondaries for sv1->sv2 transition [`PR #678`_].
* Deprecates Targets of Opportunity as standard secondary targets.
* ToOs will be handled by a separate ledger-based mechanism.
* Main Survey, secondary, outside-footprint target updates [`PR #677`_]:
* Update priorities for some secondary programs.
* MTL changes to reobserve 0.7 < z < 2.1 QSOs at low priority.
Expand All @@ -26,6 +29,7 @@ desitarget Change Log
.. _`PR #675`: https://github.com/desihub/desitarget/pull/675
.. _`PR #676`: https://github.com/desihub/desitarget/pull/676
.. _`PR #677`: https://github.com/desihub/desitarget/pull/677
.. _`PR #678`: https://github.com/desihub/desitarget/pull/678


0.50.0 (2021-01-29)
Expand Down
4 changes: 2 additions & 2 deletions py/desitarget/data/targetmask.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ scnd_mask:
{obsconditions: DARK|GRAY, filename: 'dr16q', downsample: 1}]

# ADM reserve 60/61 in scnd_mask for Targets of Opportunity in both SV and the Main Survey.
- [BRIGHT_TOO, 60, "Targets of Opportunity", {obsconditions: BRIGHT, filename: 'ToO'}]
- [DARK_TOO, 61, "Targets of Opportunity", {obsconditions: DARK, filename: 'ToO'}]
- [BRIGHT_TOO, 60, "Targets of Opportunity from rolling ledger", {obsconditions: BRIGHT, flavor: 'TOO'}]
- [DARK_TOO, 61, "Targets of Opportunity from rolling ledger", {obsconditions: DARK, flavor: 'TOO'}]

#- Observing conditions
#- These are a bitmask to allow target bits to specify multiple conditions
Expand Down
30 changes: 16 additions & 14 deletions py/desitarget/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -954,20 +954,22 @@ def write_secondary(targdir, data, primhdr=None, scxdir=None, obscon=None,

# ADM and write out the information for each bit.
for name in scnd_mask.names():
# ADM construct the output file name.
fn = "{}.fits".format(scnd_mask[name].filename)
scxfile = os.path.join(scxoutdir, fn)
# ADM retrieve just the data with this bit set.
ii = (scnd_target_init & scnd_mask[name]) != 0
# ADM only proceed to the write stage if there are targets.
if np.sum(ii) > 0:
# ADM to reorder to match the original input order.
order = np.argsort(scnd_order[ii])
# ADM write to file.
write_with_units(scxfile, smalldata[ii][order], extname='TARGETS',
header=hdr)
log.info('Info for {} secondaries written to {}'
.format(np.sum(ii), scxfile))
# ADM Targets of Opportunity are handled separately.
if scnd_mask[name].flavor != 'TOO':
# ADM construct the output file name.
fn = "{}.fits".format(scnd_mask[name].filename)
scxfile = os.path.join(scxoutdir, fn)
# ADM retrieve just the data with this bit set.
ii = (scnd_target_init & scnd_mask[name]) != 0
# ADM only proceed to the write stage if there are targets.
if np.sum(ii) > 0:
# ADM to reorder to match the original input order.
order = np.argsort(scnd_order[ii])
# ADM write to file.
write_with_units(scxfile, smalldata[ii][order],
extname='TARGETS', header=hdr)
log.info('Info for {} secondaries written to {}'
.format(np.sum(ii), scxfile))

# ADM make necessary directories for the file, if they don't exist.
os.makedirs(os.path.dirname(filename), exist_ok=True)
Expand Down
138 changes: 71 additions & 67 deletions py/desitarget/secondary.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ def _check_files(scxdir, scnd_mask):
setdic[subdir] = set(fns)

# ADM check for bit correspondence.
setbitfns = set([scnd_mask[name].filename for name in scnd_mask.names()])
setbitfns = set([scnd_mask[name].filename for name in scnd_mask.names()
if scnd_mask[name].flavor != "TOO"])
if setbitfns != setdic['indata']:
msg = "files in yaml file don't match files in {}\n".format(
dirdic['indata'])
Expand Down Expand Up @@ -294,75 +295,78 @@ def read_files(scxdir, scnd_mask):
scxall = []
# ADM loop through all of the scx bits.
for name in scnd_mask.names():
log.debug('SCND target: {}'.format(name))
# ADM the full file path without the extension.
fn = os.path.join(fulldir, scnd_mask[name].filename)
log.debug(' path: {}'.format(fn))
# ADM if the relevant file is a .txt file, read it in.
if os.path.exists(fn+'.txt'):
try:
scxin = np.loadtxt(fn+'.txt', usecols=[0, 1, 2, 3, 4, 5],
dtype=indatamodel.dtype)
except (ValueError, IndexError):
msg = "First 6 columns don't correspond to {} in {}.txt".format(
indatamodel.dtype, fn)
# ADM perhaps people provided .csv files as .txt files.
# ADM Targets of Opportunity are handled separately.
if scnd_mask[name].flavor != 'TOO':
log.debug('SCND target: {}'.format(name))
# ADM the full file path without the extension.
fn = os.path.join(fulldir, scnd_mask[name].filename)
log.debug(' path: {}'.format(fn))
# ADM if the relevant file is a .txt file, read it in.
if os.path.exists(fn+'.txt'):
try:
scxin = np.loadtxt(fn+'.txt', usecols=[0, 1, 2, 3, 4, 5],
dtype=indatamodel.dtype, delimiter=",")
dtype=indatamodel.dtype)
except (ValueError, IndexError):
log.error(msg)
raise IOError(msg)

# ADM otherwise it's a fits file, read it in.
else:
scxin = fitsio.read(fn+'.fits',
columns=indatamodel.dtype.names)

# ADM ensure this is a properly constructed numpy array.
scxin = np.atleast_1d(scxin)

# ADM assert the data model.
msg = "Data model doesn't match {} in {}".format(indatamodel.dtype, fn)
for col in indatamodel.dtype.names:
assert scxin[col].dtype == indatamodel[col].dtype, msg

# ADM check RA/Dec are reasonable.
outofbounds = ((scxin["RA"] >= 360.) | (scxin["RA"] < 0) |
(scxin["DEC"] > 90) | (scxin["DEC"] < -90))
if np.any(outofbounds):
msg = "RA/Dec outside of range in {}; RA={}, Dec={}".format(
fn, scxin["RA"][outofbounds], scxin["DEC"][outofbounds])
log.error(msg)
raise IOError(msg)

# ADM now checks are done, downsample to the required density.
log.debug("Read {} targets from {}".format(len(scxin), fn))
ds = scnd_mask[name].downsample
if ds < 1:
log.debug("Downsampling to first {}% of file".format(100*ds))
scxin = scxin[:int(len(scxin)*ds)]
log.debug("Working with {} targets for {}".format(len(scxin), name))

# ADM the default is 2015.5 for the REF_EPOCH.
ii = scxin["REF_EPOCH"] == 0
scxin["REF_EPOCH"][ii] = 2015.5

# ADM add the other output columns.
dt = outdatamodel.dtype.descr + suppdatamodel.dtype.descr
scxout = np.zeros(len(scxin), dtype=dt)
for col in indatamodel.dtype.names:
scxout[col] = scxin[col]
scxout["SCND_TARGET"] = scnd_mask[name]
scxout["SCND_TARGET_INIT"] = scnd_mask[name]
scxout["SCND_ORDER"] = np.arange(len(scxin))
scxout["PRIORITY_INIT"] = scnd_mask[name].priorities['UNOBS']
scxout["NUMOBS_INIT"] = scnd_mask[name].numobs
scxout["TARGETID"] = -1
scxout["OBSCONDITIONS"] = \
obsconditions.mask(scnd_mask[name].obsconditions)
scxout["PRIM_MATCH"] = False
scxall.append(scxout)
msg = "First 6 columns don't look like {} in {}.txt".format(
indatamodel.dtype, fn)
# ADM perhaps people provided .csv files as .txt files.
try:
scxin = np.loadtxt(
fn+'.txt', usecols=[0, 1, 2, 3, 4, 5],
dtype=indatamodel.dtype, delimiter=",")
except (ValueError, IndexError):
log.error(msg)
raise IOError(msg)

# ADM otherwise it's a fits file, read it in.
else:
scxin = fitsio.read(fn+'.fits',
columns=indatamodel.dtype.names)

# ADM ensure this is a properly constructed numpy array.
scxin = np.atleast_1d(scxin)

# ADM assert the data model.
msg = "Data model mismatch: {} in {}".format(indatamodel.dtype, fn)
for col in indatamodel.dtype.names:
assert scxin[col].dtype == indatamodel[col].dtype, msg

# ADM check RA/Dec are reasonable.
outofbounds = ((scxin["RA"] >= 360.) | (scxin["RA"] < 0) |
(scxin["DEC"] > 90) | (scxin["DEC"] < -90))
if np.any(outofbounds):
msg = "RA/Dec outside of range in {}; RA={}, Dec={}".format(
fn, scxin["RA"][outofbounds], scxin["DEC"][outofbounds])
log.error(msg)
raise IOError(msg)

# ADM now checks are done, downsample to the required density.
log.debug("Read {} targets from {}".format(len(scxin), fn))
ds = scnd_mask[name].downsample
if ds < 1:
log.debug("Downsampling to first {}% of file".format(100*ds))
scxin = scxin[:int(len(scxin)*ds)]
log.debug("Working with {} targets for {}".format(len(scxin), name))

# ADM the default is 2015.5 for the REF_EPOCH.
ii = scxin["REF_EPOCH"] == 0
scxin["REF_EPOCH"][ii] = 2015.5

# ADM add the other output columns.
dt = outdatamodel.dtype.descr + suppdatamodel.dtype.descr
scxout = np.zeros(len(scxin), dtype=dt)
for col in indatamodel.dtype.names:
scxout[col] = scxin[col]
scxout["SCND_TARGET"] = scnd_mask[name]
scxout["SCND_TARGET_INIT"] = scnd_mask[name]
scxout["SCND_ORDER"] = np.arange(len(scxin))
scxout["PRIORITY_INIT"] = scnd_mask[name].priorities['UNOBS']
scxout["NUMOBS_INIT"] = scnd_mask[name].numobs
scxout["TARGETID"] = -1
scxout["OBSCONDITIONS"] = \
obsconditions.mask(scnd_mask[name].obsconditions)
scxout["PRIM_MATCH"] = False
scxall.append(scxout)

return np.concatenate(scxall)

Expand Down