In this notebook we use the HELP VO system to explore the properties of a sample of $z\sim5$ ($r$-dropouts) in the ELAIS-N1 data. Using the VO we search for $r$-dropout sources in the HyperSuprimeCam (HSC) data following the selection criteria applied by Ono et al. (2017).
For this sample of $z\sim5$ candidates we then explore their properties in the far-infrared using the HELP XID+ deconfused photometry measurements and make use of the HELP photometric redshift posteriors to construct a cleaner sample if IR-luminous LBG candidates.
This notebook assumes you have PyVO installed and working, if this is your first experience with using the HELP VO service you may consider starting with the other example notebooks to familiarise yourself with the steps.
!pip install pyvo
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import h5py
import pyvo as vo
from IPython import display
Here we define our main query, selecting all our columns of interest and joining the main datatable with the depth maps so that we only include sources from within the HSC optical footprint:
base_query="""
SELECT top 1000000
t.help_id, t.hp_idx, t.ra, t.dec, t.redshift, t.zspec,
t.m_ap_suprime_g, t.m_ap_suprime_r, t.m_ap_suprime_i, t.m_ap_suprime_z, t.m_ap_suprime_y,
t.merr_ap_suprime_g, t.merr_ap_suprime_r, t.merr_ap_suprime_i, t.merr_ap_suprime_z, t.merr_ap_suprime_y,
t.m_ap_irac_i1, t.merr_ap_irac_i1, t.m_ap_irac_i2, t.merr_ap_irac_i2,
t.f_spire_250, t.f_spire_350, t.f_spire_500,
t.ferr_spire_250, t.ferr_spire_350, t.ferr_spire_500,
t.field,
t.cigale_sfr, t.cigale_dustlumin, t.cigale_mstar,
t.cigale_sfr_err, t.cigale_dustlumin_err, t.cigale_mstar_err,
c.ferr_suprime_z_mean, c.ferr_irac_i2_mean
FROM herschelhelp.main AS t
JOIN depth.main AS c
ON (t.field = 'ELAIS-N1') and t.hp_idx = c.hp_idx_o_13 and c.ferr_suprime_i_mean is NOT NULL
"""
Now we define the additional colour criteria that will be added to select the dropout candidates (dropout_criteria
) or a small subset of the full catalog (background_criteria
):
dropout_criteria = """
WHERE
((t.m_ap_suprime_r - t.m_ap_suprime_i) > 1.2) AND
((t.m_ap_suprime_i - t.m_ap_suprime_z) < 0.7) AND
((t.m_ap_suprime_r - t.m_ap_suprime_i) > (1.5*(t.m_ap_suprime_i - t.m_ap_suprime_z) + 1.1)) AND
(abs(t.f_ap_suprime_g/t.ferr_ap_suprime_g) < 2) AND
(abs(t.f_ap_suprime_z/t.ferr_ap_suprime_z) > 5) AND
(abs(t.f_ap_suprime_y/t.ferr_ap_suprime_y) > 4)
"""
background_criteria="""
WHERE
t.hp_idx BETWEEN 188733368 AND 188763368
"""
# ((abs(t.f_spire_250/t.ferr_spire_250) > 2) OR (abs(t.f_spire_350/t.ferr_spire_350) > 2) OR (abs(t.f_spire_500/t.ferr_spire_500) > 2))
Executing the queries and loading into astropy tables...
#Then we execute the query
service = vo.dal.TAPService("https://herschel-vos.phys.sussex.ac.uk/__system__/tap/run/tap")
result_set = service.search(base_query + dropout_criteria)
reference_set = service.search(base_query + background_criteria)
hsc_r_drops = result_set.to_table()
hsc_background = reference_set.to_table()
The forced photometry of XID+ may return many measurements that are consistent with zero, so we'll set our threshold for FIR detection as $2\sigma$ or more in at least two of the SPIRE bands.
fir_det = (((hsc_r_drops['f_spire_250']/hsc_r_drops['ferr_spire_250'] > 2.).astype('int') +
(hsc_r_drops['f_spire_350']/hsc_r_drops['ferr_spire_350'] > 2.).astype('int') +
(hsc_r_drops['f_spire_500']/hsc_r_drops['ferr_spire_500'] > 2.).astype('int')) >= 2)
Lets plots the candidates in the $r$-dropout colour space alongside our background subset of all galaxies to illustrate where everything lies.
Fig, Ax = plt.subplots(1,1, figsize=(5,5))
Ax.plot(hsc_background['m_ap_suprime_i']-hsc_background['m_ap_suprime_z'],
hsc_background['m_ap_suprime_r']-hsc_background['m_ap_suprime_i'], ',', alpha=0.1, label='All HSC')
Ax.plot(hsc_r_drops['m_ap_suprime_i']-hsc_r_drops['m_ap_suprime_z'],
hsc_r_drops['m_ap_suprime_r']-hsc_r_drops['m_ap_suprime_i'],
'o', ms=4, color='indianred', alpha=0.2, label=r'All $r$-drops')
Ax.plot((hsc_r_drops['m_ap_suprime_i']-hsc_r_drops['m_ap_suprime_z'])[fir_det],
(hsc_r_drops['m_ap_suprime_r']-hsc_r_drops['m_ap_suprime_i'])[fir_det],
'o', ms=8, color='firebrick', label=r'FIR Detected $r$-drops')
Leg = Ax.legend(loc='lower right')
Ax.set_xlabel(r'$i_{\rm{HSC}} - z_{\rm{HSC}}$', size=12)
Ax.set_ylabel(r'$r_{\rm{HSC}} - i_{\rm{HSC}}$', size=12)
Ax.set_xlim([-0.5, 2])
Ax.set_ylim([-1, 4])
Now we load the HELP photo-$z$ posteriors to see the estimated redshifts for these candidates taking into account all of the available photometry (including additional near- and mid-infrared where available).
The posterior files are large but as they are HDF5 files, they do not need to be loaded into memory. Here we assume that the relevant file has been downloaded from HeDAM and is stored locally (Alternatively you can download straight to Google Colab). We load in the posteriors for only our $z\sim5$ candidate sources.
# get hdf5 photoz file
!wget http://hedam.lam.fr/HELP/dataproducts/dmu24/dmu24_ELAIS-N1/data/pz_hb_en1.hdf
pz_hdf = h5py.File('pz_hb_en1.hdf', 'r') # Update to relevant local path
pz_help_id = pz_hdf['help_id'][()]
#decode id from bytes_ to string
pz_help_id = np.array([i.decode('UTF-8') for i in pz_help_id])
matches = list(np.array([np.where(idx == pz_help_id) for idx in hsc_r_drops['help_id']]).squeeze())
hsc_r_drops_pz = np.array([pz_hdf['pz'][idx] for idx in matches])
For illustrative purposes, lets stack the posteriors (and re-normalise) for our different subsamples to see the overall redshift distributions.
pz_all = np.nansum(hsc_r_drops_pz, 0) # Sum all posteriors
pz_all /= np.trapz(pz_all, pz_hdf['zgrid']) # Re-normalise
pz_fir = np.nansum(hsc_r_drops_pz[fir_det], 0) # Sum SPIRE detected posteriors
pz_fir /= np.trapz(pz_fir, pz_hdf['zgrid']) # Re-normalise
Fig, Ax = plt.subplots(1, 1, figsize=(6,4))
Ax.plot(pz_hdf['zgrid'], pz_all, lw=3, label=r'All $r$-drops')
Ax.plot(pz_hdf['zgrid'], pz_fir, lw=3, label=r'FIR Detected $r$-drops')
Leg = Ax.legend(loc='upper right')
Ax.set_xlim([0, 7])
Ax.set_title(r'ELAIS-N1 HSC $r$-dropouts - Stacked $P(z)$')
Ax.set_xlabel('z', size=12)
Ax.set_ylabel(r'$P(z)$', size=12)
As we can above, only approximately $\sim50\%$ of the sources are predicted to be at high redshift. This is consistent with the contamination estimates presented in Ono et al. (2017). As expected, the high redshift peak is centred at $z\sim5$ but has a very broad distribution.
The posterior distribution for the FIR detected sources is clearly different, with the majority being consistent with low redshift galaxies (i.e. mis-identification of the Balmer/Lyman break). There is still however clearly some candidates that are consistent with being at high redshift. Lets find out how many of the dropout sources have redshift posteriors consistent with the source being at $z > 3$
pz_gtr3 = (np.trapz(hsc_r_drops_pz[:,462:], pz_hdf['zgrid'][462:], axis=1) > 0.95)
How many SPIRE detected sources remain after enforcing a stricter photo-$z$ requirement?
(pz_gtr3 * fir_det).sum()
pz_stack_gtr3 = np.nansum(hsc_r_drops_pz[pz_gtr3], 0) # Sum all posteriors
pz_stack_gtr3 /= np.trapz(pz_stack_gtr3, pz_hdf['zgrid']) # Re-normalise
pz_fir_gtr3 = np.nansum(hsc_r_drops_pz[fir_det*pz_gtr3], 0) # Sum SPIRE detected posteriors
pz_fir_gtr3 /= np.trapz(pz_fir_gtr3, pz_hdf['zgrid']) # Re-normalise
Fig, Ax = plt.subplots(1, 1, figsize=(6,4))
Ax.plot(pz_hdf['zgrid'], pz_stack_gtr3, lw=3, label=r'$z > 3$ $r$-drops')
Ax.plot(pz_hdf['zgrid'], pz_fir_gtr3, lw=3, label=r'FIR Detected $z > 3 r$-drops')
Leg = Ax.legend(loc='upper left')
Ax.set_xlim([0, 7])
Ax.set_title(r'ELAIS-N1 HSC $r$-dropouts - Stacked $P(z)$')
Ax.set_xlabel('z', size=12)
Ax.set_ylabel(r'$P(z)$', size=12)
Author: Kenneth Duncan
The Herschel Extragalactic Legacy Project, (HELP), is a European Commission Research Executive Agency funded project under the SP1-Cooperation, Collaborative project, Small or medium-scale focused research project, FP7-SPACE-2013-1 scheme, Grant Agreement Number 607254.