LRG Templates

John Moustakas
Siena College
2018 October 5

The goal of this notebook is to use observations of a large number of luminous red galaxies (LRGs) with DECaLS/DR7 grzW1W2 photometry and ancillary spectroscopic redshifts to generate a set of spectroscopic templates suitable for spectroscopic simulations, targeting investigations, and other DESI-related projects.

The parent sample consists of 111,114 LRGs selected by Rongpu Zhou (Pittsburgh) with spectroscopic redshifts from SDSS/Main, (e)BOSS, AGES, DEEP2, GAMA, OzDES, VIPERS, VVDS, and COSMOS (precise medium-band photometric redshifts).

We cull this sample to 75,315 LRGs by applying the following additional cuts:

  • 0.2 < z < 1.2
  • nobs_[g,r,z] >= 3
  • wisemask == False
  • brightstarinblob == False
  • measured flux in all five grzW1W2 bands

To ensure this sample is representative of the parent sample of >3.3M LRGs with precise photometric redshifts, we count the number of photometric LRGs near each LRG with a spectroscopic redshift (in redshift-apparent magnitude-color space) and use this below as a statistical weight.

With this sample in hand, we generate spectral templates using the following procedure:

  1. We use the Bayesian spectral energy distribution (SED) modeling code iSEDfit and the CKC14z simple stellar population models of Conroy et al. to model the observed SEDs of the parent sample of galaxies. The outputs of this code are the best-fitting (maximum likelihood) spectroscopic template and the marginalized posterior distributions on a large number of quantities of interest, stored in the file legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01.fits.

    In addition, we compute K-corrected absolute magnitudes in the DECaLS and BASS+MzLS g-, r-, and z-band bandpasses and store them in the file legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01_kcorr.z0.0.fits. The code that generates these files is desi_legacysurvey_lrg_isedfit.

  1. Next, the notebook below documents how we select a "representative" subset of these galaxies to serve as our LRG template set.
  1. Finally, we generate the templates themselves using the IDL script build_lrg_basis_templates.

In [1]:
import os
import numpy as np

from astropy.table import Table, hstack
from scipy.spatial import cKDTree as KDTree

In [2]:
import matplotlib.pyplot as plt
from corner import corner

In [3]:
plt.style.use('seaborn-talk')
%matplotlib inline

Establish the random and pathnames.


In [4]:
seed = 123
rand = np.random.RandomState(seed)

In [5]:
isedfit_version = 'v2.0'
templates_version = 'v2.1'

In [6]:
isedfit_dir = os.path.join(os.getenv('DESI_ROOT'), 'spectro', 'templates', 'lrg_templates', 'isedfit', isedfit_version)

In [7]:
metadata_outfile = os.path.join(isedfit_dir, 'lrg-templates-isedfit-{}.fits'.format(isedfit_version))

Read the iSEDfit and absolute magnitude catalogs.


In [8]:
def read_isedfit():
    """Read the iSEDfit fitting results."""
    
    parentfile = os.path.join(isedfit_dir, 'lrg_parent.fits.gz')
    isedfile = os.path.join(isedfit_dir, 'legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01.fits.gz')
    kcorrfile = os.path.join(isedfit_dir, 'legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01_kcorr.z0.0.fits.gz')

    print('Reading {}'.format(parentfile))
    parent = Table.read(parentfile)
    print('Reading {}'.format(isedfile))
    ised = Table.read(isedfile)
    print('Reading {}'.format(kcorrfile))
    kcorr = Table.read(kcorrfile)
    
    snrmin = 3.0
    chi2min = 10
    
    keep = np.where(
        (ised['CHI2'] < chi2min) * 
        (np.sum(ised['MAGGIES'] * np.sqrt(ised['IVARMAGGIES']) > snrmin, axis=1) == 5)
    )[0]
    print('Read {} galaxies with chi2 < {} and S/N > {} in all 5 photometric bands.'.format(
        len(keep), chi2min, snrmin))
    
    cat = dict()
    cat['weight'] = len(keep) * parent['COUNT'][keep].data / np.sum(parent['COUNT'][keep].data)
    cat['redshift'] = kcorr['Z'][keep].data
    cat['Mstar'] = ised['MSTAR_50'][keep].data
    cat['Mg'] = kcorr['ABSMAG'][keep, 0].data
    cat['Mr'] = kcorr['ABSMAG'][keep, 1].data
    cat['Mz'] = kcorr['ABSMAG'][keep, 2].data
    cat['gr'] = cat['Mg'] - cat['Mr']
    cat['rz'] = cat['Mr'] - cat['Mz']

    with np.errstate(invalid='ignore'):
        cat['grobs'] = -2.5 * np.log10( ised['MAGGIES'][keep, 0].data / ised['MAGGIES'][keep, 1].data )
        cat['rzobs'] = -2.5 * np.log10( ised['MAGGIES'][keep, 1].data / ised['MAGGIES'][keep, 2].data )
        cat['zW1obs'] = -2.5 * np.log10( ised['MAGGIES'][keep, 2].data / ised['MAGGIES'][keep, 3].data )
     
    #mm = - 2.5 * np.log10(ised['MAGGIES'][keep, 0].data)
    #_ = plt.hist(mm, bins=100)
    
    kcorr.remove_columns(['Z', 'ISEDFIT_ID', 'MAGGIES', 'IVARMAGGIES'])
    out = hstack([ised[keep], kcorr[keep]])
    
    return cat, out

In [9]:
cat, ised = read_isedfit()
ngal = len(ised)


Reading /Users/ioannis/work/desi/spectro/templates/lrg_templates/isedfit/v2.0/lrg_parent.fits.gz
Reading /Users/ioannis/work/desi/spectro/templates/lrg_templates/isedfit/v2.0/legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01.fits.gz
Reading /Users/ioannis/work/desi/spectro/templates/lrg_templates/isedfit/v2.0/legacysurvey_lrg_ckc14z_kroupa01_charlot_sfhgrid01_kcorr.z0.0.fits.gz
Read 48817 galaxies with chi2 < 10 and S/N > 3.0 in all 5 photometric bands.

In [10]:
print(sorted(cat.keys()))


['Mg', 'Mr', 'Mstar', 'Mz', 'gr', 'grobs', 'redshift', 'rz', 'rzobs', 'weight', 'zW1obs']

In [11]:
ised[:2]


Out[11]:
Table length=2
ISEDFIT_IDRADECZMAGGIES [5]IVARMAGGIES [5]BESTMAGGIES [5]CHUNKINDXMODELINDXDELAYEDBURSTTYPECHI2_1TOTALMASSTOTALMASS_ERRMSTARAGESFRAGETAUZMETALAVMUOIIIHBNLYCSFRSFR100B100B1000EWOIIEWOIIIHBEWNIIHANBURSTTRUNCTAUTBURSTDTBURSTFBURSTMSTAR_50AGE_50SFRAGE_50TAU_50ZMETAL_50AV_50MU_50OIIIHB_50SFR_50SFR100_50B100_50B1000_50EWOII_50EWOIIIHB_50EWNIIHA_50MSTAR_AVGAGE_AVGSFRAGE_AVGTAU_AVGZMETAL_AVGAV_AVGMU_AVGOIIIHB_AVGSFR_AVGSFR100_AVGB100_AVGB1000_AVGEWOII_AVGEWOIIIHB_AVGEWNIIHA_AVGMSTAR_ERRAGE_ERRSFRAGE_ERRTAU_ERRZMETAL_ERRAV_ERRMU_ERROIIIHB_ERRSFR_ERRSFR100_ERRB100_ERRB1000_ERREWOII_ERREWOIIIHB_ERREWNIIHA_ERRCHI2_2FLAM_1500CFLUX_3727KCORRECT [3]ABSMAG [3]IVARABSMAG [3]SYNTH_ABSMAG [3]ABSMAG_FILTERLIST [3]
int32float64float64float32float32float32float32int16int16int32int32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32int16float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32bytes11
0145.9106933214981-0.66993890371635560.369256685.069725e-09 .. 7.102788e-082.0459266e+20 .. 3.567438e+175.123763e-09 .. 7.3073075e-08089119.932455337586130000.0987901400.011.3249675.37183674.27835460.548214140.026790530.1007801150.26123187-1.052.577934-0.47493076-1.4258919-3.224153-2.8096416-1.0-1.0-1.00-1.0-1.0-1.0-1.011.3253425.37183674.27835460.42949420.026790530.1007801150.26123187-1.0-0.47455597-1.4255171-3.224153-2.8096416-1.0-1.0-1.011.3239915.2335744.37639670.429618030.0235510580.25241980.3406924-1.0-1.4260209-2.2226713-5.2463737-4.7529306-1.0-1.0-1.00.0439102650.62998180.6226340.149637650.00282235680.22359980.171691690.00.88276340.660506253.08060313.16537140.00.00.09.9324558.01557e-183.4443556e-17-0.25023428 .. 0.10797201-22.282818 .. -23.52427935804.156 .. 41486.633-22.2573 .. -23.544544decam_g.par .. decam_z.par
1145.26691496916993-0.9573229077668040.405937673.6528445e-09 .. 5.560954e-083.4718932e+20 .. 3.883426e+173.854969e-09 .. 5.622779e-080622117.9159555456607100000.01268900500.011.44453057.9281776.68880460.619828940.016427250.325471730.19406769-1.052.102215-1.5808468-2.6522436-4.412614-4.0516644-1.0-1.0-1.00-1.0-1.0-1.0-1.011.4479297.2391016.68880460.244609860.0163039290.275765270.2542269-1.0-3.3289576-3.3289576-11.289713-10.224919-1.0-1.0-1.011.4460547.355166.60618160.37456790.01618810.2930070.2579056-1.0-2.5812752-3.0376954-9.357711-8.683728-1.0-1.0-1.00.0137176510.60130620.309186820.147061840.00075990380.072658960.072231670.00.505159140.242822172.7059142.80077460.00.00.07.91595551.4474227e-182.9058928e-17-0.19238524 .. 0.09691145-22.286253 .. -23.5272441834.586 .. 52586.44-22.2679 .. -23.537163decam_g.par .. decam_z.par

Visualize the sample in the rest-frame and the observed frame.


In [12]:
zlim, Mrlim, grlim, rzlim = (0.2, 1.1), (-21, -25), (0.2, 1.2), (0.2, 0.8)

In [13]:
def qa_rest():
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 10))
    
    ax1.hexbin(cat['redshift'], cat['Mr'], mincnt=1, bins='log', 
               C=cat['weight'], reduce_C_function=np.sum,
               cmap=plt.cm.get_cmap('RdYlBu'))
    ax1.set_ylim(Mrlim)
    ax1.set_xlim(zlim)
    ax1.set_xlabel('Redshift')
    ax1.set_ylabel(r'$M_{0.0r}$')
    
    ax2.hexbin(cat['redshift'], cat['gr'], mincnt=1, bins='log', 
               C=cat['weight'], reduce_C_function=np.sum,           
               cmap=plt.cm.get_cmap('RdYlBu'))
    ax2.set_xlim(zlim)
    ax2.set_ylim(grlim)
    ax2.set_xlabel('Redshift')
    ax2.set_ylabel(r'$^{0.0}(g - r)$')
    
    ax3.hexbin(cat['rz'], cat['gr'], mincnt=1, bins='log', 
               C=cat['weight'], reduce_C_function=np.sum,               
               cmap=plt.cm.get_cmap('RdYlBu'))
    ax3.set_xlabel(r'$^{0.0}(r - z)$')
    ax3.set_ylabel(r'$^{0.0}(g - r)$')
    ax3.set_ylim(grlim)
    ax3.set_xlim(rzlim)
    
    hb = ax4.hexbin(cat['Mr'], cat['gr'], mincnt=1, bins='log', 
                    C=cat['weight'], reduce_C_function=np.sum,                    
                    cmap=plt.cm.get_cmap('RdYlBu'))
    ax4.set_xlabel(r'$M_{0.0r}$')
    ax4.set_ylabel(r'$^{0.0}(g - r)$')
    ax4.set_xlim(Mrlim)
    ax4.set_ylim(grlim)
   
    cax = fig.add_axes([0.88, 0.15, 0.02, 0.7])
    fig.colorbar(hb, cax=cax, label=r'$\log_{10}$ (Weighted Number of Galaxies)')

    for aa in (ax1, ax2, ax3, ax4):
        aa.grid(True)
    
    plt.subplots_adjust(wspace=0.2, right=0.85)

In [14]:
qa_rest()


Now let's look at observed color-color space.


In [15]:
grobslim, rzobslim = (0.5, 3), (0.8, 2.2)

In [16]:
def qa_obs():
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
    ax1.hexbin(cat['rzobs'], cat['grobs'], mincnt=1, bins='log', 
               C=cat['weight'], reduce_C_function=np.sum,
               cmap=plt.cm.get_cmap('RdYlBu'))
    ax1.set_xlabel(r'$(r - z)_{\rm obs}$')
    ax1.set_ylabel(r'$(g - r)_{\rm obs}$')
    
    hb = ax2.hexbin(cat['rzobs'], cat['zW1obs'], mincnt=1, bins='log', 
                    C=cat['weight'], reduce_C_function=np.sum,                    
                    cmap=plt.cm.get_cmap('RdYlBu'))
    cb = plt.colorbar(hb)
    cb.set_label(r'$\log_{10}$ (Number of Galaxies)')

    ax2.set_ylabel(r'$(r - z)_{\rm obs}$')
    ax2.set_xlabel(r'$(z - W1)_{\rm obs}$')
    ax1.set_xlim(0.7, 2.3)
    ax1.set_ylim(0.3, 3.0)
    ax2.set_xlim(0.7, 2.3)
    ax2.set_ylim(0.2, 2.5)
    
    for aa in (ax1, ax2):
        aa.grid(True)

In [17]:
qa_obs()


Choose N templates with probability equal to the statistical weight.

The question is: what minimum set templates can be used to describe this population of LRGs. This problem is NP hard, although there are methods for solving it (see, e.g., the SetCoverPy algorithm).

Here we simply choose the desired number of templates and choose them with probability equal to the (known) statistical weight.


In [18]:
ntemplates = 3000

In [19]:
iarch = rand.choice(ngal, ntemplates, p=cat['weight']/np.sum(cat['weight']))
resp = ngal * cat['weight'] / np.sum(cat['weight'])
print('Selected {} templates from {} galaxies.'.format(ntemplates, ngal))


Selected 3000 templates from 48817 galaxies.

Visualize the results.


In [20]:
def _markers():
    size = 50 * (1+(resp - resp.min()) / resp.ptp())
    shade = (cat['gr'][iarch] - cat['gr'][iarch].min()) / cat['gr'][iarch].ptp()
    col = plt.cm.coolwarm(shade)
    return size, col

In [21]:
def qa_templates():
    """Generate a color-color plot with the symbol size scaled by the responsibility.
    
    """
    
    size, col = _markers()
    fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(3, 2, figsize=(15, 15))

    ax1.scatter(cat['rzobs'], cat['grobs'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax1.scatter(cat['rzobs'][iarch], cat['grobs'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax1.set_xlabel(r'$(r - z)_{\rm obs}$')
    ax1.set_ylabel(r'$(g - r)_{\rm obs}$')

    ax2.scatter(cat['zW1obs'], cat['rzobs'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax2.scatter(cat['zW1obs'][iarch], cat['rzobs'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax2.set_ylabel(r'$(r - z)_{\rm obs}$')
    ax2.set_xlabel(r'$(z - W1)_{\rm obs}$')

    ax3.scatter(cat['rz'], cat['gr'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax3.scatter(cat['rz'][iarch], cat['gr'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax3.set_xlabel(r'$^{0.0}(r - z)$')
    ax3.set_ylabel(r'$^{0.0}(g - r)$')
    ax3.set_ylim(grlim)
    ax3.set_xlim(rzlim)
    
    ax4.scatter(cat['Mr'], cat['gr'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax4.scatter(cat['Mr'][iarch], cat['gr'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax4.set_xlabel(r'$M_{0.0r}$')
    ax4.set_ylabel(r'$^{0.0}(g - r)$')
    ax4.set_xlim(Mrlim)
    ax4.set_ylim(grlim)
    
    ax5.scatter(cat['redshift'], cat['Mr'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax5.scatter(cat['redshift'][iarch], cat['Mr'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax5.set_xlabel('Redshift')
    ax5.set_ylabel(r'$M_{0.0r}$')
    ax5.set_xlim(zlim)
    ax5.set_ylim(Mrlim)

    ax6.scatter(cat['redshift'], cat['gr'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax6.scatter(cat['redshift'][iarch], cat['gr'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax6.set_xlabel('Redshift')
    ax6.set_ylabel(r'$^{0.0}(g - r)$')
    ax6.set_xlim(zlim)
    ax6.set_ylim(grlim)
    
    for aa in (ax1, ax2, ax3, ax4, ax5, ax6):
        aa.grid(True)    
    
    fig.subplots_adjust(wspace=0.2, hspace=0.3)

Symbol size is proportional to "responsibility" (nperbin) and color is proportional to rest-frame g-r color.


In [22]:
qa_templates()


Some additional diagnostics of the templates.

SFR100 is the star formation rate (SFR) averaged over the previous 100 Myr. Note that templates with higher SFRs are somewhat over-represented in the template set because we choose templates with equal probability, not weighted by the number of galaxies in each cell.


In [23]:
def qa_template_properties():
    size, col = _markers()
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))
    
    ax1.hist(ised['MSTAR_50'], weights=cat['weight'], density=True, bins=30, label='Full Sample')
    ax1.hist(ised['MSTAR_50'][iarch], density=True, bins=30, alpha=0.5,
            label='Templates')
    ax1.set_xlabel(r'$\log_{10}\ (M\ /\ M_{\odot})$')
    ax1.set_ylabel('Relative Fraction')
    ax1.set_xlim((10, 12.5))
    ax1.yaxis.set_ticks([])
    
    ax2.hist(ised['SFR100_50'], weights=cat['weight'], density=True, bins=30, label='Full Sample')
    ax2.hist(ised['SFR100_50'][iarch], density=True, bins=30, alpha=0.5,
            label='Templates')    
    ax2.set_xlabel(r'$\log_{10}\ (SFR_{100}\ /\ M_{\odot}\ {\rm yr}^{-1})$')
    ax2.set_xlim((-4.5, 2))
    ax2.yaxis.set_ticks([])
    ax2.legend(loc='upper right')
    
    ax3.scatter(cat['redshift'], ised['MSTAR_50'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax3.scatter(cat['redshift'][iarch], ised['MSTAR_50'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax3.set_xlabel('Redshift')
    ax3.set_ylabel(r'$\log_{10}\ (M\ /\ M_{\odot})$')
    ax3.set_xlim(zlim)
    ax3.set_ylim((10, 12.5))

    ax4.scatter(cat['redshift'], ised['SFR100_50'], s=10, c='lightgray', alpha=0.5, edgecolor='k')
    ax4.scatter(cat['redshift'][iarch], ised['SFR100_50'][iarch], c=col, marker='o', s=size, 
                alpha=0.9, edgecolor='k')
    ax4.set_xlabel('Redshift')
    ax4.set_ylabel(r'$\log_{10}\ (SFR_{100}\ /\ M_{\odot}\ {\rm yr}^{-1})$')
    ax4.set_xlim(zlim)
    ax4.set_ylim((-4.5, 2))
    
    plt.subplots_adjust(wspace=0.25, hspace=0.2)

In [24]:
qa_template_properties()


Write out the metadata.


In [25]:
print('Writing {}'.format(metadata_outfile))
ised[iarch].write(metadata_outfile, overwrite=True)


Writing /Users/ioannis/work/desi/spectro/templates/lrg_templates/isedfit/v2.0/lrg-templates-isedfit-v2.0.fits

Visualize the resulting templates.

The spectra have to built in IDL using the script build_lrg_basis_templates, which we assume has happend.


In [26]:
from desisim.io import read_basis_templates

In [27]:
flux, wave, meta = read_basis_templates('LRG')
nt = len(meta)
print('Number of templates = {}'.format(nt))


INFO:io.py:945:read_basis_templates: Reading /Users/ioannis/work/desi/spectro/templates/basis_templates/v3.0/lrg_templates_v2.1.fits
Number of templates = 3000

In [28]:
meta


Out[28]:
Table length=3000
TEMPLATEIDISEDFIT_IDRADECZMAGGIES [5]IVARMAGGIES [5]DECAM_GDECAM_RDECAM_ZBASS_GBASS_RMZLS_ZW1W2LOGMSTARLOGSFRLOGSFR100AV_ISMAGESFRAGEHBETA_CONTINUUMD4000
int32int32float64float64float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32float32
014308317.28758340035530.91520709557930590.575536437.972503e-10 .. 2.000799e-088.7857446e+20 .. 4.830902e+1722.66920.93382319.59066822.74028820.9619119.5832918.63775319.15560511.211722-2.167968-2.80018880.0609843625.86437035.02941372.0643107e-111.6995952
16302937.100651046884720.53390412527897781.00954282.0029509e-10 .. 4.6390962e-085.826188e+20 .. 3.6956383e+1724.01098422.31252720.24192824.04295222.33207320.22835718.1805418.43335311.702727-1.006077-1.66183150.448999943.09632282.34424162.2838396e-111.6094583
211866219.4956142678262-0.57665422807125160.634001268.981776e-10 .. 2.8964967e-083.211496e+20 .. 5.210364e+1722.570821.04694619.65868622.63160721.0742419.64873118.5357219.04493111.202787-0.9402332-1.71957040.0298248424.0512833.0147242.978929e-111.5835352
3621304.7653596099070824.2026798082775680.797076945.2210397e-10 .. 1.9286603e-081.0311402e+21 .. 5.2523856e+1723.35470421.63339619.94293623.42044821.64884419.93540818.61138219.09843311.341495-0.64599437-1.46485150.104758185.3163114.22690152.5956636e-111.5417281
46578734.560545980217256-5.3235017998178010.78434.5852577e-10 .. 1.2257585e-082.0829844e+21 .. 5.502523e+1723.35184322.00318320.47114423.39503522.03016320.46475419.21575419.69080711.0522140.018286357-0.81497590.11673185.307163.8516563.019276e-111.4374952
55177332.7482841873600140.9018367939272380.887711055.2659094e-10 .. 3.8629594e-088.406131e+20 .. 4.804199e+1723.09662821.7899119.9910523.12535921.81336419.98341818.27764918.5205811.5562861.05307090.29403181.14185883.04019052.0474532.203437e-111.3127472
65517415.60087017038711.35597236692837430.82683292.5802366e-10 .. 2.2940018e-081.0467417e+21 .. 4.0458015e+1723.9310321.83872420.00486824.01511821.8569919.99706818.59117319.08803211.458709-2.4667184-2.909010.00245502245.81656655.73288062.0702532e-111.6876205
76552633.90964818324741-5.5754124380319240.93062.1922102e-10 .. 9.901794e-094.4948677e+21 .. 5.6964296e+1724.04391522.52959820.77665124.07288722.5454420.76898219.50839619.81381811.013869-2.239731-2.98838780.313639251.97949551.70585295.1149755e-111.3335259
873951150.008263588339822.215634998822780.61417.4363954e-10 .. 1.9810663e-081.2732329e+21 .. 4.1535928e+1722.8376721.13711519.79105822.91552421.16424819.78321318.67116219.14569311.090778-1.0622345-1.87675060.067105712.77005772.32632643.464815e-111.5887774
97368185.36750666796337-2.2636157739187180.3732871.996705e-09 .. 4.3963805e-085.8462303e+20 .. 4.1641893e+1721.74490420.04741519.01783821.78798920.05922119.01080917.9633118.1908111.2241630.58189404-0.181743441.12575985.83045054.00452149.362642e-121.5323036
.....................................................................
299073990150.792228891550852.23732988834214730.81842.318164e-10 .. 1.793427e-084.8919844e+21 .. 4.2461957e+1724.15918522.32786420.38227524.21690222.34277720.37407918.78030419.23466511.310621-0.38453978-1.24226320.111267893.88727833.03858782.4021325e-111.7487397
299122883122.7815488967421728.492127808004660.428438931.5304684e-09 .. 2.5530367e-085.4077662e+20 .. 4.0212456e+1722.03026220.22315219.195522.0912220.23661419.19018718.49302918.88090311.096132-2.341464-2.9299580.1077199357.09576375.69913771.5746708e-111.8392756
299241250189.646742474662423.98836918532640.611181861.3191981e-09 .. 3.1875615e-084.6536103e+20 .. 4.9270106e+1722.18867520.49405719.11286222.26461820.52126119.10515218.03041318.55025111.458446-1.6614087-2.2466730.186714783.60611683.45427582.4630683e-111.5907521
29935328027.766188036270474-1.4987602689254320.85685162.4340555e-10 .. 2.749211e-085.414718e+20 .. 4.9584353e+1724.03996321.84375619.9407524.11622621.85665119.9322718.38788818.83669511.534645-1.7860395-2.47645520.0609843625.86437035.02941372.0643098e-111.6995988
299469247222.39996019285322.3169182805414210.398033.098831e-09 .. 3.8434113e-082.3402093e+20 .. 4.3339086e+1721.20750219.5419718.6288821.25787719.5561118.62491418.11429618.49050311.213557-1.8505651-2.6379310.0609843625.86437035.02941372.0643081e-111.699594
2995157553.9866876281826458-0.92018657447781760.53997291.0938573e-09 .. 2.1443578e-081.5591631e+21 .. 5.5265547e+1722.29614320.64410219.47395522.36396620.66987819.46802518.62116219.10336711.093754-2.6537263-3.1320690.067349563.58242823.49919652.7171184e-111.597029
29965717112.18222612253922-1.9576893968990741.00668291.3071251e-10 .. 3.091691e-081.3870197e+21 .. 4.0430132e+1724.62370122.25205620.249524.69745822.27388620.23536318.44011718.77962311.57945-2.3196013-2.72781250.0435119235.04092174.7928342.2445061e-111.6591516
299726036205.359676562175855.0096484890864010.62125091.2023884e-09 .. 3.80116e-082.9178644e+20 .. 4.617538e+1722.20123120.46949419.01307122.28170420.4965319.00398417.90245218.43220911.525951-1.950322-2.45184520.154867965.27529674.39779142.1054004e-111.6588396
29985829243.62206965050327-3.2698120522674861.00072014.088124e-10 .. 2.9457961e-081.4991613e+21 .. 5.5802758e+1723.56995822.0970220.25711323.60257722.11225120.2456518.5349118.80400811.5018390.54390925-0.29319760.559195044.99630743.6964482.3046369e-111.4029887
29995569720.2875770800960032.7044543199519291.03813063.6454526e-10 .. 4.9587058e-088.491864e+20 .. 3.798291e+1723.6577822.03958120.06318723.68841422.05898720.05099918.02156618.24284611.7731210.5486822-0.32808490.63307233.50782422.65428832.2781851e-111.4495274

In [29]:
def plot_subset(nplot=25, ncol=5):
    """Plot a random sampling of the basis templates."""
    nspec, npix = flux.shape
    nrow = np.ceil(nplot / ncol).astype('int')
    these = rand.choice(nspec, nplot, replace=False)
    fig, ax = plt.subplots(nrow, ncol, figsize=(2.2*ncol, 2.2*nrow), sharey=True, sharex=True)
    for thisax, indx in zip(ax.flat, these):
        thisax.plot(wave, flux[indx, :])
        thisax.text(0.95, 0.93, '{:0d}'.format(indx), ha='right', 
             va='top', transform=thisax.transAxes, fontsize=11)
        thisax.xaxis.set_major_locator(plt.MaxNLocator(3))
        thisax.set_xscale('log')
        thisax.set_yscale('log')
    fig.subplots_adjust(wspace=0.05, hspace=0.05)

In [30]:
plot_subset()


Finally, compare the colors of the templates to the data.

This test brings this analysis full circle.


In [31]:
def zgrid_colors():
    """Compute the colors of the templates on a fixed redshift grid."""
    from speclite import filters
    filt = filters.load_filters('decam2014-g', 'decam2014-r', 'decam2014-z', 'wise2010-W1')
    
    zmin, zmax, dz = 0.2, 1.2, 0.1
    #zmin, zmax, dz = 0.0, 1.0, 0.1
    nz = np.round( (zmax - zmin) / dz ).astype('i2')
    print('Number of redshift points = {}'.format(nz))

    cc = dict(
        redshift = np.linspace(zmin, zmax, nz),
        gr = np.zeros( (nt, nz) ),
        rz = np.zeros( (nt, nz) ),
        zW1 = np.zeros( (nt, nz), )
    )    
    
    for iz, red in enumerate(cc['redshift']):
        zwave = wave.astype('float') * (1 + red)
        phot = filt.get_ab_maggies(flux, zwave, mask_invalid=False)
        cc['gr'][:, iz] = -2.5 * np.log10( phot['decam2014-g'] / phot['decam2014-r'] )
        cc['rz'][:, iz] = -2.5 * np.log10( phot['decam2014-r'] / phot['decam2014-z'] )
        cc['zW1'][:, iz] = -2.5 * np.log10( phot['decam2014-z'] / phot['wise2010-W1'] )
    
    return cc

In [32]:
%time cc = zgrid_colors()


Number of redshift points = 10
CPU times: user 8.64 s, sys: 6.18 s, total: 14.8 s
Wall time: 14.9 s

In [33]:
grrange = (0.0, 3.0)
rzrange = (0.0, 2.5)
zW1range = (-1, 4)
ntspace = 20 # spacing between model curves

In [34]:
def grz(pngfile=None):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

    hb = ax1.hexbin(cat['rzobs'], cat['grobs'], bins='log', 
                   mincnt=1, extent=rzrange+grrange,
                   C=cat['weight'], reduce_C_function=np.sum,                    
                   cmap=plt.cm.get_cmap('RdYlBu'))
    ax1.set_xlabel(r'$(r - z)_{\rm obs}$')
    ax1.set_ylabel(r'$(g - r)_{\rm obs}$')
    ax1.set_xlim(rzrange)
    ax1.set_ylim(grrange)
    ax1.text(0.05, 0.9, 'Data', ha='left', va='bottom',
             transform=ax1.transAxes, fontsize=14)
    ax1.grid(True)

    #cb = fig.colorbar(hb, ax=ax1)
    #cb.set_label(r'log$_{10}$ (Number of Galaxies)')
    
    for tt in np.arange(0, nt, ntspace):
        ax2.plot(cc['rz'][tt, :], cc['gr'][tt, :], marker='s', 
                 markersize=5, ls='-', alpha=0.5)
        
    for tt in np.arange(0, nt, ntspace):
        ax2.scatter(cc['rz'][tt, 0], cc['gr'][tt, 0], marker='o', 
                   facecolors='none', s=80, edgecolors='k',
                   linewidth=2)
        
    ax2.text(0.1, 0.1, 'z=0.2', ha='left', va='bottom',
             transform=ax2.transAxes, fontsize=14)
    ax2.text(0.05, 0.9, 'Models (z=0.2-1.2, dz=0.1)', ha='left', va='bottom',
             transform=ax2.transAxes, fontsize=14)
    
    ax2.set_xlim(rzrange)
    ax2.set_ylim(grrange)
    ax2.set_xlabel(r'$(r - z)_{\rm obs}$')
    ax2.set_ylabel(r'$(g - r)_{\rm obs}$')
    ax2.yaxis.set_label_position('right')
    ax2.yaxis.tick_right()
    ax2.grid(True)
    
    plt.subplots_adjust(wspace=0.05)
    
    if pngfile:
        fig.savefig(pngfile)

In [35]:
grz()



In [36]:
def rzW1(pngfile=None):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

    hb = ax1.hexbin(cat['zW1obs'], cat['rzobs'], bins='log', 
                    mincnt=1, extent=rzrange+grrange,
                    C=cat['weight'], reduce_C_function=np.sum,                                        
                    cmap=plt.cm.get_cmap('RdYlBu'))

    ax1.set_ylabel(r'$(r - z)_{\rm obs}$')
    ax1.set_xlabel(r'$(z - W1)_{\rm obs}$')
    ax1.set_xlim(zW1range)
    ax1.set_ylim(rzrange)
    ax1.text(0.05, 0.9, 'Data', ha='left', va='bottom',
             transform=ax1.transAxes, fontsize=14)
    ax1.grid(True)

    #cb = fig.colorbar(hb, ax=ax1)
    #cb.set_label(r'log$_{10}$ (Number of Galaxies)')
    
    for tt in np.arange(0, nt, ntspace):
        ax2.plot(cc['zW1'][tt, :], cc['rz'][tt, :], marker='s', 
                markersize=5, ls='-', alpha=0.5)
        
    for tt in np.arange(0, nt, ntspace):
        ax2.scatter(cc['zW1'][tt, 0], cc['rz'][tt, 0], marker='o', 
                   facecolors='none', s=80, edgecolors='k',
                   linewidth=2)
        
    ax2.text(0.03, 0.3, 'z=0.2', ha='left', va='bottom',
             transform=ax2.transAxes, fontsize=14)
    ax2.text(0.05, 0.9, 'Models (z=0.2-1.2, dz=0.1)', ha='left', va='bottom',
             transform=ax2.transAxes, fontsize=14)
    
    ax2.set_xlim(zW1range)
    ax2.set_ylim(rzrange)
    ax2.set_xlabel(r'$(z - W1)_{\rm obs}$')
    ax2.set_ylabel(r'$(r - z)_{\rm obs}$')
    ax2.yaxis.set_label_position('right')
    ax2.yaxis.tick_right()
    ax2.grid(True)
    
    plt.subplots_adjust(wspace=0.05)
    
    if pngfile:
        fig.savefig(pngfile)

In [37]:
rzW1()



In [ ]: