Mock Targets to Mock Properties

The goal of this notebook is to demonstrate how to use the target and truth catalogs generated by select_mock_targets
to pull out additional galaxy properties from the parent mock catalogs (which varies with target class).

John Moustakas
Siena College
2019 November 3


In [1]:
%%html
<style>
  table {margin-left: 0 !important;}
</style>



In [2]:
import os
datadir = '{DESI_ROOT}/datachallenge/test-mockid'.format(**os.environ)

In [3]:
nside, healpix = 128, 104121

Preliminaries

First, we need to build a simple dataset of select_mock_targets outputs by carrying out the following steps:

  1. In an empty directory (here, datadir) grab the nominal select-mock-targets.yaml file. In this file, the nominal mock catalogs are:
Target Mock Catalog
BGS {DESI_ROOT}/mocks/bgs/MXXL/full_sky/v0.0.4/BGS_r20.6.hdf5
ELG {DESI_ROOT}/mocks/DarkSky/v1.0.1/elg_0_inpt.fits
LRG {DESI_ROOT}/mocks/DarkSky/v1.0.1/lrg_0_inpt.fits
QSO {DESI_ROOT}/mocks/DarkSky/v1.0.1/qso_0_inpt.fits
LYA {DESI_ROOT}/mocks/lya_forest/london/v4.2.0/master.fits
MWS_MAIN {DESI_ROOT}/mocks/mws/galaxia/alpha/v0.0.6/healpix
MWS_NEARBY {DESI_ROOT}/mocks/mws/100pc/v0.0.4/mock_100pc.fits
WD {DESI_ROOT}/mocks/mws/wd/v1.0.0/mock_wd.fits
SKY {DESI_ROOT}/mocks/uniformsky/0.2/uniformsky-2048-0.2.fits
  1. Next, launch the code (here, with 4 cores and a couple randomly selected nside=128 healpixels and with no spectra, for speed):
select_mock_targets -c select-mock-targets.yaml --nproc 4 --verbose --seed 1 \  
  --healpixels 104120 104121 --nside 128 --no-spectra --overwrite

Note that this simulation will include contaminants, which we need to handle below.

  1. Finally, join the individual targets and truth catalogs in each healpixel (separately for bright and dark targets) into the top-level directory with:
join_mock_targets --mockdir . --overwrite

If each one of these steps worked then your top-level directory should contain the following files:

% ls -l *
drwxrwxr-x  4 ioannis  staff      128 Oct 21 14:21 1041/
-rw-rw-r--  1 ioannis  staff   630720 Oct 22 12:33 mtl-bright.fits
-rw-rw-r--  1 ioannis  staff  1008000 Oct 22 12:33 mtl-dark.fits
-rw-r--r--@ 1 ioannis  staff     2488 Oct 21 14:16 select-mock-targets.yaml
-rw-rw-r--  1 ioannis  staff   302400 Oct 22 12:33 sky.fits
-rw-rw-r--  1 ioannis  staff   633600 Oct 22 12:33 targets-bright.fits
-rw-rw-r--  1 ioannis  staff   999360 Oct 22 12:33 targets-dark.fits
-rw-rw-r--  1 ioannis  staff   218880 Oct 22 12:33 truth-bright.fits
-rw-rw-r--  1 ioannis  staff   437760 Oct 22 12:33 truth-dark.fits

Basic imports


In [4]:
import os
import numpy as np
import fitsio

In [5]:
from desitarget.io import find_target_files

Read the parent targets and truth catalogs.

You can see that some targets (e.g., BGS, STAR, WD) appear as both bright- and dark-time targets, while others (e.g., ELG, LRG, QSO) appear only as dark-time targets.


In [6]:
for obscon in ('dark', 'bright'):
    for cattype in ('targets', 'truth'):
        catfile = os.path.join(datadir, '{}-{}.fits'.format(cattype, obscon))
        print(fitsio.FITS(catfile))


  file: /Users/ioannis/work/desi/datachallenge/test-mockid/targets-dark.fits
  mode: READONLY
  extnum hdutype         hduname[v]
  0      IMAGE_HDU       
  1      BINARY_TBL      TARGETS

  file: /Users/ioannis/work/desi/datachallenge/test-mockid/truth-dark.fits
  mode: READONLY
  extnum hdutype         hduname[v]
  0      IMAGE_HDU       
  1      BINARY_TBL      TRUTH
  2      BINARY_TBL      TRUTH_BGS
  3      BINARY_TBL      TRUTH_ELG
  4      BINARY_TBL      TRUTH_LRG
  5      BINARY_TBL      TRUTH_QSO
  6      BINARY_TBL      TRUTH_STAR
  7      BINARY_TBL      TRUTH_WD

  file: /Users/ioannis/work/desi/datachallenge/test-mockid/targets-bright.fits
  mode: READONLY
  extnum hdutype         hduname[v]
  0      IMAGE_HDU       
  1      BINARY_TBL      TARGETS

  file: /Users/ioannis/work/desi/datachallenge/test-mockid/truth-bright.fits
  mode: READONLY
  extnum hdutype         hduname[v]
  0      IMAGE_HDU       
  1      BINARY_TBL      TRUTH
  2      BINARY_TBL      TRUTH_BGS
  3      BINARY_TBL      TRUTH_STAR
  4      BINARY_TBL      TRUTH_WD

Mapping mock targets to the parent mock catalog.

Now let's investigate the targets for each target class. The basic idea is that you can use TARGETID to cross-reference targets across the various data tables, and that you can use MOCKID to find the position (i.e., row) of the target in the parent mock catalog.


In [7]:
class2mockfile = dict(
    BGS='{DESI_ROOT}/mocks/bgs/MXXL/full_sky/v0.0.4/BGS_r20.6.hdf5',
    ELG='{DESI_ROOT}/mocks/DarkSky/v1.0.1/elg_0_inpt.fits',
    LRG='{DESI_ROOT}/mocks/DarkSky/v1.0.1/lrg_0_inpt.fits',
    QSO='{DESI_ROOT}/mocks/DarkSky/v1.0.1/qso_0_inpt.fits',
    LYA='{DESI_ROOT}/mocks/lya_forest/london/v4.2.0/master.fits',
    MWS_MAIN='{DESI_ROOT}/mocks/mws/galaxia/alpha/v0.0.6/healpix',
    MWS_NEARBY='{DESI_ROOT}/mocks/mws/100pc/v0.0.4/mock_100pc.fits',
    WD='{DESI_ROOT}/mocks/mws/wd/v1.0.0/mock_wd.fits',
    SKY='{DESI_ROOT}/mocks/uniformsky/0.2/uniformsky-2048-0.2.fits'
)

In [8]:
def read_targets_and_truth(obscon='bright', objtype='BGS', targettype='BGS'):
    from desitarget.targetmask import desi_mask, bgs_mask, mws_mask
    
    # Read the targets.fits catalog
    targfile = find_target_files(datadir, flavor='targets', obscon=obscon, mock=True)
    targ = fitsio.read(targfile, ext='TARGETS')
    print('Read {} targets from {}'.format(len(targ), targfile))
    
    # Read the truth.fits catalog
    truefile = find_target_files(datadir, flavor='truth', obscon=obscon, mock=True)
    true = fitsio.read(truefile, ext='TRUTH')
    print('Read {} truth from {}'.format(len(true), truefile))

    # Read the object-specific metadata table
    objtrue = fitsio.read(truefile, ext='TRUTH_{}'.format(objtype.upper()))
    print('Read {} {} truth from {}'.format(len(objtrue), objtype, truefile))
    
    # Select the appropriate objects using TARGETID and the appropriate 
    # targeting bit. We have to be careful with MWS_MAIN because MWS_WD and
    # MWS_NEARBY have their own mock catalog.
    if targettype == 'BGS':
        keep = (targ['DESI_TARGET'] & desi_mask.mask('BGS_ANY')) != 0
    elif targettype == 'MWS_MAIN':
        keep = ( ((targ['DESI_TARGET'] & desi_mask.mask('MWS_ANY')) != 0) * 
                 ((targ['MWS_TARGET'] & mws_mask.mask('MWS_NEARBY')) == 0) * 
                 ((targ['MWS_TARGET'] & mws_mask.mask('MWS_WD')) == 0) )
    else:
        keep = (targ['DESI_TARGET'] & desi_mask.mask(targettype)) != 0
    
    keep = np.where( keep * (np.isin(targ['TARGETID'], objtrue['TARGETID'])) )[0]
        
    print('Selecting {} objects from targets and truth catalog.'.format(len(keep)))
    targ = targ[keep]
    true = true[keep]
    
    return targ, true, objtrue

BGS, ELG, LRG, QSO, LYA, MWS_NEARBY, WD, SKY

These mocks are are one single mock catalog, so MOCKID will provide the row of each target in the original, unfiltered parent catalog. Here, we demonstrate how to navigate the input and output files using the BGS mock.

For simplicity we show how to compare the input and output celestial coordinates and the redshifts, although obviuosly other properties are available in the parent mock.


In [9]:
def read_bgs_mock():
    import h5py
    mockfile = class2mockfile['BGS'].format(**os.environ)
    print('Reading {}'.format(mockfile))
    with h5py.File(mockfile, mode='r') as f:
        ra  = f['Data/ra'][:].astype('f8') % 360.0 # enforce 0 < ra < 360
        dec = f['Data/dec'][:].astype('f8')
        zobs = f['Data/z_obs'][:].astype('f4')    
    return ra, dec, zobs

In [10]:
%time ra, dec, zobs = read_bgs_mock()


Reading /Users/ioannis/work/desi/mocks/bgs/MXXL/full_sky/v0.0.4/BGS_r20.6.hdf5
CPU times: user 9.39 s, sys: 2.56 s, total: 12 s
Wall time: 12 s

Next, read the BGS truth catalog, clean out contaminants (using the TEMPLATETYPE column), and then pull out the row of each target in the parent mock catalog using the MOCKID column.


In [11]:
targ, true, objtrue = read_targets_and_truth(obscon='bright', objtype='BGS', targettype='BGS')


Read 1354 targets from /Users/ioannis/work/desi/datachallenge/test-mockid/targets-bright.fits
Read 1354 truth from /Users/ioannis/work/desi/datachallenge/test-mockid/truth-bright.fits
Read 612 BGS truth from /Users/ioannis/work/desi/datachallenge/test-mockid/truth-bright.fits
Selecting 612 objects from targets and truth catalog.

In [12]:
indxinmock = true['MOCKID']
assert(np.all(zobs[indxinmock] == true['TRUEZ']))
assert(np.all(zobs[indxinmock] == true['TRUEZ']))
assert(np.all(zobs[indxinmock] == true['TRUEZ']))

MWS_MAIN

Owing to the size, the MWS_MAIN mock is divided into separate healpixels. Now we have to be a little careful because a general target catalog will include not just MWS_MAIN targets, but also MWS_NEARBY and MWS_WD targets, which themselves have their own mock catalogs!


In [13]:
from desitarget.targets import decode_targetid
from desitarget.mock.io import findfile
from desitarget.mock.mockmaker import ReadGalaxia

In [14]:
nside_galaxia = 8
mockfile = class2mockfile['MWS_MAIN'].format(**os.environ)
mockfile_nside = os.path.join(mockfile, str(nside_galaxia))
#mock = ReadGalaxia().readmock(mockfile=mockfile, healpixels=healpix, nside=nside)

In [15]:
targ, true, objtrue = read_targets_and_truth(obscon='bright', objtype='STAR', targettype='MWS_MAIN')


Read 1354 targets from /Users/ioannis/work/desi/datachallenge/test-mockid/targets-bright.fits
Read 1354 truth from /Users/ioannis/work/desi/datachallenge/test-mockid/truth-bright.fits
Read 740 STAR truth from /Users/ioannis/work/desi/datachallenge/test-mockid/truth-bright.fits
Selecting 690 objects from targets and truth catalog.

In [16]:
objid, pixnum, _, _, _, _ = decode_targetid(true['MOCKID'])
assert(len(np.unique(pixnum)) == 1)

In [19]:
galaxiafile = findfile(filetype='mock_allsky_galaxia_desi', 
                       nside=nside_galaxia, pixnum=pixnum[0],
                       basedir=mockfile_nside, ext='fits')
mockdata = fitsio.read(galaxiafile)
assert(np.all(mockdata['RA'][objid] == targ['RA']))

In [ ]: