Example #1
0
def decode_targetid(targetid):
    """break a DESI TARGETID into its constituent parts.

    Parameters
    ----------
    :class:`int` or :class:`~numpy.ndarray`
        The TARGETID for DESI, encoded according to the bits listed in
        :meth:`desitarget.targetid_mask`.

    Returns
    -------
    :class:`int` or :class:`~numpy.ndarray`
        The OBJID from Legacy Surveys imaging or the row within
        a Gaia HEALPixel file in $GAIA_DIR/healpix if
        `gaia` is not ``None``.
    :class:`int` or :class:`~numpy.ndarray`
        The BRICKID from Legacy Surveys imaging.
        or the Gaia HEALPixel chunk number for files in
        $GAIA_DIR/healpix if `gaia` is not ``None``.
    :class:`int` or :class:`~numpy.ndarray`
        The RELEASE from Legacy Surveys imaging. Or, if < 1000,
        the secondary target class bit flag number from
        'data/targetmask.yaml'. Or, if < 1000 and `sky` is not
        ``None``, the HEALPixel processing number for SUPP_SKIES.
    :class:`int` or :class:`~numpy.ndarray`
        1 if this object is a mock object (generated from
        mocks, not from real survey data), 0 otherwise
    :class:`int` or :class:`~numpy.ndarray`
        1 if this object is a blank sky object, 0 otherwise
    :class:`int` or :class:`~numpy.ndarray`
        The Gaia Data Release number (e.g. will be 2 for Gaia DR2).
        A value of 1 does NOT mean DR1. Rather it has the specific
        meaning of a DESI first-light commissioning target.

    Notes
    -----
        - if a 1-D array is passed, then an integer is returned.
          Otherwise an array is returned.
        - see also `DocDB 2348`_.
    """
    # ADM the names of the bits with RESERVED removed.
    bitnames = targetid_mask.names()
    if "RESERVED" in bitnames:
        bitnames.remove("RESERVED")

    # ADM retrieve each value by left-shifting by the number of bits
    # ADM that comprise the value, to the left-end of the value, and
    # ADM then right-shifting to the right-end.
    outputs = []
    for bitname in bitnames:
        bitnum = targetid_mask[bitname].bitnum
        val = (targetid & (2**targetid_mask[bitname].nbits - 1 <<
                           targetid_mask[bitname].bitnum)) >> bitnum
        outputs.append(val)

    return outputs
Example #2
0
def encode_targetid(objid=None,
                    brickid=None,
                    release=None,
                    mock=None,
                    sky=None,
                    gaiadr=None):
    """Create the DESI TARGETID from input source and imaging info.

    Parameters
    ----------
    objid : :class:`int` or :class:`~numpy.ndarray`, optional
        The OBJID from Legacy Surveys imaging or the row within
        a Gaia HEALPixel file in $GAIA_DIR/healpix if
        `gaia` is not ``None``.
    brickid : :class:`int` or :class:`~numpy.ndarray`, optional
        The BRICKID from Legacy Surveys imaging.
        or the Gaia HEALPixel chunk number for files in
        $GAIA_DIR/healpix if `gaia` is not ``None``.
    release : :class:`int` or :class:`~numpy.ndarray`, optional
        The RELEASE from Legacy Surveys imaging. Or, if < 1000,
        the secondary target class bit flag number from
        'data/targetmask.yaml'. Or, if < 1000 and `sky` is not
        ``None``, the HEALPixel processing number for SUPP_SKIES.
    mock : :class:`int` or :class:`~numpy.ndarray`, optional
        1 if this object is a mock object (generated from
        mocks, not from real survey data), 0 otherwise
    sky : :class:`int` or :class:`~numpy.ndarray`, optional
        1 if this object is a blank sky object, 0 otherwise
    gaiadr : :class:`int` or :class:`~numpy.ndarray`, optional
        The Gaia Data Release number (e.g. send 2 for Gaia DR2).
        A value of 1 does NOT mean DR1. Rather it has the specific
        meaning of a DESI first-light commissioning target.

    Returns
    -------
    :class:`int` or `~numpy.ndarray`
        The TARGETID for DESI, encoded according to the bits listed in
        :meth:`desitarget.targetid_mask`. If an integer is passed, then
        an integer is returned, otherwise an array is returned.

    Notes
    -----
        - Has maximum flexibility so that mixes of integers and arrays
          can be passed, in case some value like BRICKID or SKY
          is the same for a set of objects. Consider, e.g.:

          print(
              targets.decode_targetid(
                  targets.encode_targetid(objid=np.array([234,12]),
                                          brickid=np.array([234,12]),
                                          release=4000,
                                          sky=[1,0]))
                                          )

        (array([234,12]), array([234,12]), array([4000,4000]),
         array([0,0]), array([1,0]))

        - See also `DocDB 2348`_.
    """
    # ADM a flag that tracks whether the main inputs were integers.
    intpassed = True

    # ADM the names of the bits with RESERVED removed.
    bitnames = targetid_mask.names()
    if "RESERVED" in bitnames:
        bitnames.remove("RESERVED")

    # ADM determine the length of passed values that aren't None.
    # ADM default to an integer (length 1).
    nobjs = 1
    inputs = [objid, brickid, release, mock, sky, gaiadr]
    goodpar = [param is not None for param in inputs]
    firstgoodpar = np.where(goodpar)[0][0]
    if isinstance(inputs[firstgoodpar], np.ndarray):
        nobjs = len(inputs[firstgoodpar])
        intpassed = False

    # ADM set parameters that weren't passed to zerod arrays
    # ADM set integers that were passed to at least 1D arrays
    for i, param in enumerate(inputs):
        if param is None:
            inputs[i] = np.zeros(nobjs, dtype='int64')
        else:
            inputs[i] = np.atleast_1d(param)

    # ADM check passed parameters don't exceed their bit-allowance.
    for param, bitname in zip(inputs, bitnames):
        if not np.all(param < 2**targetid_mask[bitname].nbits):
            msg = 'Invalid range when making targetid: {} '.format(bitname)
            msg += 'cannot exceed {}'.format(2**targetid_mask[bitname].nbits -
                                             1)
            log.critical(msg)
            raise IOError(msg)

    # ADM set up targetid as an array of 64-bit integers.
    targetid = np.zeros(nobjs, ('int64'))
    # ADM populate TARGETID. Shift to type integer 64 to avoid casting.
    for param, bitname in zip(inputs, bitnames):
        targetid |= param.astype('int64') << targetid_mask[bitname].bitnum

    # ADM if the main inputs were integers, return an integer.
    if intpassed:
        return targetid[0]
    return targetid