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

Updates to target selection algorithms, mostly for SV #418

Merged
merged 26 commits into from
Nov 10, 2018
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6d76aad
add the capability to set target bits to the SV cuts file, anticipati…
geordie666 Oct 24, 2018
85ede45
upddate code style parser to ignore external packages
geordie666 Oct 24, 2018
8e8b65e
Update the LRG selections for SV
geordie666 Oct 26, 2018
15d285d
update MWS main survey selection
geordie666 Nov 2, 2018
60b2438
update LRG cuts for the main surveys (and refactor)
geordie666 Nov 3, 2018
02173f6
update targeting bits for SV ELG selections
geordie666 Nov 5, 2018
113d89c
update ELG color cut selection for SV
geordie666 Nov 5, 2018
57aacb4
working on SV color cuts for quasars. Also debugged a sign flip in Ma…
geordie666 Nov 5, 2018
238413e
un-debugging sign flip
geordie666 Nov 5, 2018
a007f75
add stricter color cut on WISE for objects on the stellar locus
geordie666 Nov 5, 2018
9552de2
reverting sign flip
geordie666 Nov 5, 2018
5fac972
updating SV cuts for Random Forest quasars
geordie666 Nov 5, 2018
f2e9efc
update the quasar bits to reflect that we now have two QSO target cla…
geordie666 Nov 5, 2018
d357895
set all of the new quasar bits
geordie666 Nov 5, 2018
42a1401
updating some inputs for the quasar selection functions
geordie666 Nov 5, 2018
76956eb
we don't need the quasar selection methods for SV, as all are used wi…
geordie666 Nov 5, 2018
4ecef5e
finalizing SV code for selecting standards
geordie666 Nov 5, 2018
a98acde
debugging
geordie666 Nov 6, 2018
2ee4db1
updating QA for new MWS_BROAD bit name, and to work with SV bits that…
geordie666 Nov 6, 2018
b4dec1f
make sure QA still works with main survey files
geordie666 Nov 7, 2018
e4a3cce
code style
geordie666 Nov 7, 2018
7cb6c88
Merge branch 'master' into ADMcutsSV to pull across @sbailey's Travis…
geordie666 Nov 7, 2018
227399e
updating the changes docs [ci skip]
geordie666 Nov 7, 2018
97e69c9
fixing sphinx failures
geordie666 Nov 7, 2018
e8edca3
minor clean-up of doc strings
geordie666 Nov 7, 2018
9b749cd
Merge branch 'master' into ADMcutsSV
geordie666 Nov 10, 2018
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: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ matrix:
PIP_DEPENDENCIES=$PIP_ALL_DEPENDENCIES
- os: linux
python: 3.5
env: MAIN_CMD='pycodestyle' SETUP_CMD='--count --ignore=W503,W504,E121,E123,E126,E133,E226,E241,E242,E501,E704,E731,E741 py/desitarget'
env: MAIN_CMD='pycodestyle' SETUP_CMD='--count py/desitarget'

include:

Expand Down Expand Up @@ -159,7 +159,7 @@ matrix:
# PEP 8 compliance.
- os: linux
python: 3.5
env: MAIN_CMD='pycodestyle' SETUP_CMD='--count --ignore=W503,W504,E121,E123,E126,E133,E226,E241,E242,E501,E704,E731,E741 py/desitarget'
env: MAIN_CMD='pycodestyle' SETUP_CMD='--count py/desitarget'

install:
- git clone git://github.com/astropy/ci-helpers.git
Expand Down
10 changes: 3 additions & 7 deletions bin/select_sv_targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import numpy as np
import fitsio

from desitarget import io
from desitarget.cuts import select_targets, qso_selection_options
from desitarget.cuts import select_targets
from desitarget.brightmask import mask_targets
from desitarget.QA import _parse_tcnames

Expand All @@ -32,8 +32,6 @@ ap.add_argument("dest",
help="Output target selection file")
ap.add_argument('-m', "--mask",
help="If sent then mask the targets, the name of the mask file should be supplied")
ap.add_argument('--qsoselection',choices=qso_selection_options,default='randomforest',
help="QSO target selection method")
ap.add_argument("--numproc", type=int,
help='number of concurrent processes to use [defaults to {}]'.format(nproc),
default=nproc)
Expand Down Expand Up @@ -71,18 +69,16 @@ if (np.max(data['PMRA']) == 0.) & np.any(data["RELEASE"] < 7000):
)
raise IOError


log.info("running on {} processors".format(ns.numproc))

#ADM if specific bit names were passed, use them, otherwise run all target classes
tcnames = _parse_tcnames(tcstring=ns.tcnames, add_all=False)

targets = select_targets(infiles, numproc=ns.numproc,
qso_selection=ns.qsoselection, tcnames=tcnames, survey=survey)
targets = select_targets(infiles, numproc=ns.numproc, tcnames=tcnames, survey=survey)
if ns.mask:
targets = mask_targets(targets, inmaskfile=ns.mask, nside=nside)

io.write_targets(ns.dest, targets, indir=ns.src, survey=survey,
qso_selection=ns.qsoselection, nside=nside)
qso_selection=survey, nside=nside)

log.info('{} targets written to {}...t={:.1f}s'.format(len(targets), ns.dest, time()-start))
6 changes: 6 additions & 0 deletions doc/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ desitarget Change Log
0.24.1 (unreleased)
-------------------

* More updates to target classes, mainly for SV [`PR #418`_]. Includes:
* First full implementations of `QSO`, `LRG`, `ELG`, and `STD` for SV.
* Update and refactor of `MWS` and `BGS` classes for the main survey.
* Change name of main survey `MWS_MAIN` class to `MWS_BROAD`.
* Augment QA code to handle SV sub-classes such as `ELG_FDR_FAINT`.
* Updates to several target classes [`PR #408`_]. Includes:
* Refactor of the `ELG` and `MWS_MAIN` selection algorithms.
* Update of the `ELG` and `MWS_MAIN` selection cuts.
Expand All @@ -31,6 +36,7 @@ desitarget Change Log
.. _`PR #402`: https://github.com/desihub/desitarget/pull/402
.. _`PR #407`: https://github.com/desihub/desitarget/pull/407
.. _`PR #408`: https://github.com/desihub/desitarget/pull/408
.. _`PR #418`: https://github.com/desihub/desitarget/pull/418

0.24.0 (2018-09-26)
-------------------
Expand Down
94 changes: 62 additions & 32 deletions py/desitarget/QA.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from desiutil.plots import init_sky, plot_sky_binned, plot_healpix_map, prepare_data
from desitarget.targetmask import desi_mask, bgs_mask, mws_mask
from desitarget.cmx.cmx_targetmask import cmx_mask
from desitarget.sv1.sv1_targetmask import desi_mask as sv1_desi_mask
# ADM fake the matplotlib display so it doesn't die on allocated nodes.
import matplotlib
matplotlib.use('Agg')
Expand Down Expand Up @@ -138,7 +139,7 @@ def _prepare_systematics(data, colname):
return outdata


def _load_targdens(tcnames=None, cmx=False):
def _load_targdens(tcnames=None, bit_mask=None):
"""Loads the target info dictionary as in :func:`desimodel.io.load_target_info()` and
extracts the target density information in a format useful for targeting QA plots.

Expand All @@ -147,17 +148,20 @@ def _load_targdens(tcnames=None, cmx=False):
tcnames : :class:`list`
A list of strings, e.g. "['QSO','LRG','ALL'] If passed, return only a dictionary
for those specific bits.
cmx : :class:`boolean`, optional, defaults to ``False``
If passed, load the commissioning bits (with zero density constraints) instead
of the main survey/SV bits.
bit_mask : :class:`~numpy.array`, optional, defaults to ``None``
If passed, load the bit names from this mask (with no associated expected
densities) rather than loading the main survey bits and densities. Must be a
desi mask object, e.g., loaded as `from desitarget.targetmask import desi_mask`.
Any bit names that contain "NORTH" or "SOUTH" or calibration bits will be
removed.

Returns
-------
:class:`dictionary`
A dictionary where the keys are the bit names and the values are the densities.
"""

if cmx is False:
if bit_mask is None:
from desimodel import io
targdict = io.load_target_info()

Expand All @@ -182,18 +186,21 @@ def _load_targdens(tcnames=None, cmx=False):
targdens['BGS_WISE'] = 0.
# targdens['BGS_WISE'] = targdict['ntarget_bgs_wise'] #uncomment and modify for BGS_WISE bit

targdens['MWS_MAIN'] = 0.
targdens['MWS_BROAD'] = 0.
targdens['MWS_MAIN_RED'] = 0.
targdens['MWS_MAIN_BLUE'] = 0.
targdens['MWS_WD'] = 0.
targdens['MWS_NEARBY'] = 0.
else:
targdens = {k: 0. for k in cmx_mask.names()}
# ADM this is the list of words contained in bits that we don't want to consider for QA.
badnames = ["NORTH", "SOUTH", "NO_TARGET", "SECONDARY", "BRIGHT_OBJECT", "SKY"]
names = [name for name in bit_mask.names() if not any(badname in name for badname in badnames)]
targdens = {k: 0. for k in names}

if tcnames is None:
return targdens
else:
# ADM this is a dictionary comprehension
# ADM this is a dictionary comprehension.
return {key: value for key, value in targdens.items() if key in tcnames}


Expand Down Expand Up @@ -1250,7 +1257,8 @@ def _in_desi_footprint(targs):


def make_qa_plots(targs, qadir='.', targdens=None, max_bin_area=1.0, weight=True,
imaging_map_file=None, truths=None, tcnames=None, cmx=False):
imaging_map_file=None, truths=None, tcnames=None,
cmx=False, bit_mask=None):
"""Make DESI targeting QA plots given a passed set of targets.

Parameters
Expand Down Expand Up @@ -1279,9 +1287,12 @@ def make_qa_plots(targs, qadir='.', targdens=None, max_bin_area=1.0, weight=True
tcnames : :class:`list`, defaults to None
A list of strings, e.g. ['QSO','LRG','ALL'] If passed, return only the QA pages
for those specific bits. A useful speed-up when testing.
cmx : :class:`boolean`, optional, defaults to ``False``
If passed, load the commissioning bits (with zero density constraints) instead
of the main survey/SV bits.
cmx : :class:`boolean`, defaults to ``False``
Pass as ``True`` to operate on commissioning bits instead of SV or main survey
bits. Commissioning files have no MWS or BGS columns.
bit_mask : :class:`~numpy.array`, optional, defaults to ``None``
Load the bit names from this passed mask (with zero density constraints)
instead of the main survey bits.

Returns
-------
Expand Down Expand Up @@ -1358,20 +1369,20 @@ def make_qa_plots(targs, qadir='.', targdens=None, max_bin_area=1.0, weight=True

# ADM Current goal target densities for DESI.
if targdens is None:
targdens = _load_targdens(tcnames=tcnames, cmx=cmx)
targdens = _load_targdens(tcnames=tcnames, bit_mask=bit_mask)

# ADM clip the target densities at an upper density to improve plot edges
# ADM by rejecting highly dense outliers.
upclipdict = {k: 5000. for k in targdens}
if cmx:
main_mask = cmx_mask
if bit_mask is not None:
main_mask = bit_mask
else:
main_mask = desi_mask
upclipdict = {'ELG': 4000, 'LRG': 1200, 'QSO': 400, 'ALL': 8000,
'STD_FAINT': 200, 'STD_BRIGHT': 50,
'LRG_1PASS': 1000, 'LRG_2PASS': 500,
'BGS_FAINT': 2500, 'BGS_BRIGHT': 2500, 'BGS_WISE': 2500, 'BGS_ANY': 5000,
'MWS_ANY': 2000, 'MWS_MAIN': 10000, 'MWS_WD': 50, 'MWS_NEARBY': 50,
'MWS_ANY': 2000, 'MWS_BROAD': 10000, 'MWS_WD': 50, 'MWS_NEARBY': 50,
'MWS_MAIN_RED': 4000, 'MWS_MAIN_BLUE': 4000}

for objtype in targdens:
Expand Down Expand Up @@ -1518,17 +1529,21 @@ def make_qa_page(targs, mocks=False, makeplots=True, max_bin_area=1.0, qadir='.'
svcolnames = colnames[['SV' in name or 'CMX' in name for name in colnames]]
# ADM set cmx flag to True if 'CMX_TARGET' is a column and rename that column.
cmx = 'CMX_TARGET' in svcolnames
# ADM use the commissioning mask bits/names if we have a CMX file.
if cmx:
main_mask = cmx_mask
else:
main_mask = desi_mask
targs = rfn.rename_fields(targs, {'CMX_TARGET': 'DESI_TARGET'})
# ADM strip "SVX" off any columns (rfn.rename_fields forgives missing fields).
for field in svcolnames:
svs = field.split('_')[0]
targs = rfn.rename_fields(targs, {field: "_".join(field.split('_')[1:])})

# ADM use the commissioning mask bits/names if we have a CMX file.
# ADM note desi_mask was changed to the SV mask if SV columns exist.
if cmx:
main_mask = cmx_mask
elif svs == 'SV1':
main_mask = sv1_desi_mask
else:
main_mask = desi_mask

# ADM determine the working nside for the passed max_bin_area.
for n in range(1, 25):
nside = 2 ** n
Expand Down Expand Up @@ -1556,7 +1571,11 @@ def make_qa_page(targs, mocks=False, makeplots=True, max_bin_area=1.0, qadir='.'

# ADM Set up the names of the target classes and their goal densities using
# ADM the goal target densities for DESI (read from the DESIMODEL defaults).
targdens = _load_targdens(tcnames=tcnames, cmx=cmx)
if svs == "DESI":
targdens = _load_targdens(tcnames=tcnames)
# ADM if we aren't looking at the main survey, pass the cmx or SV mask instead.
else:
targdens = _load_targdens(tcnames=tcnames, bit_mask=main_mask)

# ADM set up the html file and write preamble to it.
htmlfile = makepath(os.path.join(qadir, 'index.html'))
Expand Down Expand Up @@ -1717,34 +1736,45 @@ def make_qa_page(targs, mocks=False, makeplots=True, max_bin_area=1.0, qadir='.'

# ADM make the QA plots, if requested:
if makeplots:
totarea = make_qa_plots(targs, truths=truths,
qadir=qadir, targdens=targdens, max_bin_area=max_bin_area,
weight=weight, imaging_map_file=imaging_map_file, cmx=cmx)
if svs == "DESI":
totarea = make_qa_plots(targs, truths=truths, qadir=qadir, targdens=targdens,
max_bin_area=max_bin_area, weight=weight,
imaging_map_file=imaging_map_file)
else:
totarea = make_qa_plots(targs, truths=truths, qadir=qadir, targdens=targdens,
max_bin_area=max_bin_area, weight=weight,
imaging_map_file=imaging_map_file,
cmx=cmx, bit_mask=main_mask)

# ADM add a correlation matrix recording the overlaps between different target
# ADM classes as a density.
log.info('Making correlation matrix...t = {:.1f}s'.format(time()-start))
htmlmain.write('<br><h2>Overlaps in target densities (per sq. deg.)</h2>\n')
htmlmain.write('<PRE><span class="inner-pre" style="font-size: 16px">\n')
htmlmain.write('<PRE><span class="inner-pre" style="font-size: 14px">\n')
# ADM only retain classes that are actually in the DESI target bit list.
settargdens = set(main_mask.names()).intersection(set(targdens))
# ADM write out a list of the target categories.
headerlist = list(settargdens)
headerlist.insert(0, " ")
header = " ".join(['{:>11s}'.format(i) for i in headerlist])+'\n\n'
headerlist.sort()
# ADM truncate the bit names at "trunc" characters to pack them more easily.
trunc = 9
truncform = '{:>'+str(trunc)+'s}'
headerwrite = [bitname[:trunc] for bitname in headerlist]
headerwrite.insert(0, " ")
header = " ".join([truncform.format(i) for i in headerwrite])+'\n\n'
htmlmain.write(header)
# ADM for each pair of target classes, determine how many targets per unit area
# ADM have the relevant target bit set for both target classes in the pair.
for i, objtype1 in enumerate(settargdens):
overlaps = [objtype1]
for j, objtype2 in enumerate(settargdens):
for i, objtype1 in enumerate(headerlist):
overlaps = [objtype1[:trunc]]
for j, objtype2 in enumerate(headerlist):
if j < i:
overlaps.append(" ")
else:
dt = targs["DESI_TARGET"]
overlap = np.sum(((dt & main_mask[objtype1]) != 0) & ((dt & main_mask[objtype2]) != 0))/totarea
overlaps.append("{:.1f}".format(overlap))
htmlmain.write(" ".join(['{:>11s}'.format(i) for i in overlaps])+'\n\n')
htmlmain.write(" ".join([truncform.format(i) for i in overlaps])+'\n\n')
# ADM close the matrix text output.
htmlmain.write('</span></PRE>\n\n\n')
log.info('Done with correlation matrix...t = {:.1f}s'.format(time()-start))
Expand Down