This catalogue comes from dmu0_HSC
.
In the catalogue, we keep:
object_id
as unique object identifier;Note: On ELAIS-N1 the HSC-SSP catalogue does not contain any N816 magnitudes.
We use 2016 as the epoch.
from herschelhelp_internal import git_version
print("This notebook was run with herschelhelp_internal version: \n{}".format(git_version()))
%matplotlib inline
#%config InlineBackend.figure_format = 'svg'
import matplotlib.pyplot as plt
plt.rc('figure', figsize=(10, 6))
plt.style.use('ggplot')
from collections import OrderedDict
import os
from astropy import units as u
from astropy import visualization as vis
from astropy.coordinates import SkyCoord
from astropy.table import Column, Table
import numpy as np
from herschelhelp_internal.flagging import gaia_flag_column
from herschelhelp_internal.masterlist import nb_astcor_diag_plot, nb_plot_mag_ap_evol, \
nb_plot_mag_vs_apcor, remove_duplicates
from herschelhelp_internal.utils import astrometric_correction, mag_to_flux, aperture_correction
OUT_DIR = os.environ.get('TMP_DIR', "./data_tmp")
try:
os.makedirs(OUT_DIR)
except FileExistsError:
pass
RA_COL = "hsc-udeep_ra"
DEC_COL = "hsc-udeep_dec"
# Pristine HSC catalogue
orig_hsc = Table.read("../../dmu0/dmu0_HSC/data/HSC-PDR1_uDeep_COSMOS.fits")
To compute aperture correction we need to dertermine two parametres: the target aperture and the range of magnitudes for the stars that will be used to compute the correction.
Target aperture: To determine the target aperture, we simulate a curve of growth using the provided apertures and draw two figures:
As target aperture, we should use the smallest (i.e. less noisy) aperture for which most of the flux is captures.
Magnitude range: To know what limits in aperture to use when doing the aperture correction, we plot for each magnitude bin the correction that is computed and its RMS. We should then use the wide limits (to use more stars) where the correction is stable and with few dispersion.
bands = ["g", "r", "i", "z", "y", "n921"]
apertures = ["10", "15", "20", "30", "40", "57", "84", "118", "168", "235"]
magnitudes = {}
magnitude_errors ={}
stellarities = {}
for band in bands:
magnitudes[band] = np.array(
[orig_hsc["{}mag_aperture{}".format(band, aperture)] for aperture in apertures]
)
# Some sources have an infinite magnitude
mask = np.isinf(magnitudes[band])
magnitudes[band][mask] = np.nan
try:
magnitude_errors[band] = np.array(
[orig_hsc["{}mag_aperture{}_err".format(band, aperture)] for aperture in apertures]
)
magnitude_errors[band][mask] = np.nan
except KeyError:
print("No error column for a " + band + " band aperture magnitude.")
stellarities[band] = 1 - np.array(orig_hsc["{}classification_extendedness".format(band)])
mag_corr = {}
nb_plot_mag_ap_evol(magnitudes['g'], stellarities['g'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['gmag_aperture20'], orig_hsc['gmag_aperture40'], stellarities['g'])
We will use magnitudes between 18.5 and 20.8
# Aperture correction
mag_corr['g'], num, std = aperture_correction(
orig_hsc['gmag_aperture20'], orig_hsc['gmag_aperture40'],
stellarities['g'],
mag_min=18.5, mag_max=20.8)
print("Aperture correction for g band:")
print("Correction: {}".format(mag_corr['g']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
nb_plot_mag_ap_evol(magnitudes['r'], stellarities['r'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['rmag_aperture20'], orig_hsc['rmag_aperture40'], stellarities['r'])
We use magnitudes between 17.6 and 19.7.
# Aperture correction
mag_corr['r'], num, std = aperture_correction(
orig_hsc['rmag_aperture20'], orig_hsc['rmag_aperture40'],
stellarities['r'],
mag_min=17.6, mag_max=19.7)
print("Aperture correction for r band:")
print("Correction: {}".format(mag_corr['r']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
nb_plot_mag_ap_evol(magnitudes['i'], stellarities['i'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['imag_aperture20'], orig_hsc['imag_aperture40'], stellarities['i'])
We use magnitudes between 18.5 and 19.8.
# Aperture correction
mag_corr['i'], num, std = aperture_correction(
orig_hsc['imag_aperture20'], orig_hsc['imag_aperture40'],
stellarities['i'],
mag_min=18.5, mag_max=19.8)
print("Aperture correction for i band:")
print("Correction: {}".format(mag_corr['i']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
nb_plot_mag_ap_evol(magnitudes['z'], stellarities['z'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['zmag_aperture20'], orig_hsc['zmag_aperture40'], stellarities['z'])
We use magnitudes between 17.5 and 19.8.
# Aperture correction
mag_corr['z'], num, std = aperture_correction(
orig_hsc['zmag_aperture20'], orig_hsc['zmag_aperture40'],
stellarities['z'],
mag_min=17.5, mag_max=19.8)
print("Aperture correction for z band:")
print("Correction: {}".format(mag_corr['z']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
nb_plot_mag_ap_evol(magnitudes['y'], stellarities['y'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['ymag_aperture20'], orig_hsc['ymag_aperture40'], stellarities['y'])
We use magnitudes between 17 and 18.7.
# Aperture correction
mag_corr['y'], num, std = aperture_correction(
orig_hsc['ymag_aperture20'], orig_hsc['ymag_aperture40'],
stellarities['y'],
mag_min=17, mag_max=18.7)
print("Aperture correction for y band:")
print("Correction: {}".format(mag_corr['y']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
nb_plot_mag_ap_evol(magnitudes['n921'], stellarities['n921'], labels=apertures)
We will use aperture 40 as target.
nb_plot_mag_vs_apcor(orig_hsc['n921mag_aperture20'], orig_hsc['n921mag_aperture40'], stellarities['n921'])
We use magnitudes between 17 and 18.7.
# Aperture correction
mag_corr['n921'], num, std = aperture_correction(
orig_hsc['n921mag_aperture20'], orig_hsc['n921mag_aperture40'],
stellarities['n921'],
mag_min=17, mag_max=18.7)
print("Aperture correction for n921 band:")
print("Correction: {}".format(mag_corr['n921']))
print("Number of source used: {}".format(num))
print("RMS: {}".format(std))
HSC does not provide a 0 to 1 stellarity value but a 0/1 extended flag in each band. We are using the same method as UKIDSS (cf this page) to compute a stellarity based on the class in each band:
\begin{equation*} P(star) = \frac{ \prod_{i} P(star)_i }{ \prod_{i} P(star)_i + \prod_{i} P(galaxy)_i } \end{equation*}where $i$ is the band, and with using the same probabilities as UKDISS:
HSC flag | UKIDSS flag | Meaning | P(star) | P(galaxy) | P(noise) | P(saturated) |
---|---|---|---|---|---|---|
-9 | Saturated | 0.0 | 0.0 | 5.0 | 95.0 | |
-3 | Probable galaxy | 25.0 | 70.0 | 5.0 | 0.0 | |
-2 | Probable star | 70.0 | 25.0 | 5.0 | 0.0 | |
0 | -1 | Star | 90.0 | 5.0 | 5.0 | 0.0 |
0 | Noise | 5.0 | 5.0 | 90.0 | 0.0 | |
1 | +1 | Galaxy | 5.0 | 90.0 | 5.0 | 0.0 |
# We are creating an array containing the extended flag in all band.
# Some sources have no flag in some band, there will be NaN in the array.
hsc_ext_flag = np.array([
orig_hsc[colname] for colname in
['gclassification_extendedness',
'rclassification_extendedness',
'iclassification_extendedness',
'zclassification_extendedness',
'yclassification_extendedness',
'n921classification_extendedness']
])
hsc_pstar = 0.9 * (hsc_ext_flag == 0) + 0.05 * (hsc_ext_flag == 1)
hsc_pgal = 0.05 * (hsc_ext_flag == 0) + 0.9 * (hsc_ext_flag == 1)
# We put back the NaN values
hsc_pstar[np.isnan(hsc_ext_flag)] = np.nan
hsc_pgal[np.isnan(hsc_ext_flag)] = np.nan
stellarity = np.nanprod(hsc_pstar, axis=0) / np.nansum(
[np.nanprod(hsc_pgal, axis=0), np.nanprod(hsc_pstar, axis=0)], axis=0)
stellarity = np.round(stellarity, 3)
vis.hist(stellarity, bins='scott');
orig_hsc.add_column(Column(data=stellarity, name="stellarity"))
imported_columns = OrderedDict({
"object_id": "hsc-udeep_id",
"ra": "hsc-udeep_ra",
"dec": "hsc-udeep_dec",
"gmag_aperture20": "m_ap_hsc-udeep_g",
"gmag_aperture20_err": "merr_ap_hsc-udeep_g",
"gmag_kron": "m_hsc-udeep_g",
"gmag_kron_err": "merr_hsc-udeep_g",
"rmag_aperture20": "m_ap_hsc-udeep_r",
"rmag_aperture20_err": "merr_ap_hsc-udeep_r",
"rmag_kron": "m_hsc-udeep_r",
"rmag_kron_err": "merr_hsc-udeep_r",
"imag_aperture20": "m_ap_hsc-udeep_i",
"imag_aperture20_err": "merr_ap_hsc-udeep_i",
"imag_kron": "m_hsc-udeep_i",
"imag_kron_err": "merr_hsc-udeep_i",
"zmag_aperture20": "m_ap_hsc-udeep_z",
"zmag_aperture20_err": "merr_ap_hsc-udeep_z",
"zmag_kron": "m_hsc-udeep_z",
"zmag_kron_err": "merr_hsc-udeep_z",
"ymag_aperture20": "m_ap_hsc-udeep_y",
"ymag_aperture20_err": "merr_ap_hsc-udeep_y",
"ymag_kron": "m_hsc-udeep_y",
"ymag_kron_err": "merr_hsc-udeep_y",
"n921mag_aperture20": "m_ap_hsc-udeep_n921",
"n921mag_aperture20_err": "merr_ap_hsc-udeep_n921",
"n921mag_kron": "m_hsc-udeep_n921",
"n921mag_kron_err": "merr_hsc-udeep_n921",
"stellarity": "hsc-udeep_stellarity"
})
catalogue = orig_hsc[list(imported_columns)]
for column in imported_columns:
catalogue[column].name = imported_columns[column]
epoch = 2017
# Clean table metadata
catalogue.meta = None
# Aperture correction
for band in bands:
catalogue["m_ap_hsc-udeep_{}".format(band)] += mag_corr[band]
# Adding flux and band-flag columns
for col in catalogue.colnames:
if col.startswith('m_'):
errcol = "merr{}".format(col[1:])
flux, error = mag_to_flux(np.array(catalogue[col]), np.array(catalogue[errcol]))
# Fluxes are added in µJy
catalogue.add_column(Column(flux * 1.e6, name="f{}".format(col[1:])))
catalogue.add_column(Column(error * 1.e6, name="f{}".format(errcol[1:])))
# Band-flag column
if 'ap' not in col:
catalogue.add_column(Column(np.zeros(len(catalogue), dtype=bool), name="flag{}".format(col[1:])))
# TODO: Set to True the flag columns for fluxes that should not be used for SED fitting.
catalogue[:10].show_in_notebook()
We remove duplicated objects from the input catalogues.
SORT_COLS = [
'merr_ap_hsc-udeep_i', 'merr_ap_hsc-udeep_r', 'merr_ap_hsc-udeep_z',
'merr_ap_hsc-udeep_y', 'merr_ap_hsc-udeep_g','merr_ap_hsc-udeep_n921']
FLAG_NAME = 'hsc-udeep_flag_cleaned'
nb_orig_sources = len(catalogue)
catalogue = remove_duplicates(
catalogue, RA_COL, DEC_COL,
sort_col= SORT_COLS,
flag_name=FLAG_NAME)
nb_sources = len(catalogue)
print("The initial catalogue had {} sources.".format(nb_orig_sources))
print("The cleaned catalogue has {} sources ({} removed).".format(nb_sources, nb_orig_sources - nb_sources))
print("The cleaned catalogue has {} sources flagged as having been cleaned".format(np.sum(catalogue[FLAG_NAME])))
We match the astrometry to the Gaia one. We limit the Gaia catalogue to sources with a g band flux between the 30th and the 70th percentile. Some quick tests show that this give the lower dispersion in the results.
gaia = Table.read("../../dmu0/dmu0_GAIA/data/GAIA_COSMOS.fits")
gaia_coords = SkyCoord(gaia['ra'], gaia['dec'])
nb_astcor_diag_plot(catalogue[RA_COL], catalogue[DEC_COL],
gaia_coords.ra, gaia_coords.dec)
delta_ra, delta_dec = astrometric_correction(
SkyCoord(catalogue[RA_COL], catalogue[DEC_COL]),
gaia_coords
)
print("RA correction: {}".format(delta_ra))
print("Dec correction: {}".format(delta_dec))
catalogue[RA_COL] += delta_ra.to(u.deg)
catalogue[DEC_COL] += delta_dec.to(u.deg)
nb_astcor_diag_plot(catalogue[RA_COL], catalogue[DEC_COL],
gaia_coords.ra, gaia_coords.dec)
catalogue.add_column(
gaia_flag_column(SkyCoord(catalogue[RA_COL], catalogue[DEC_COL]), epoch, gaia)
)
GAIA_FLAG_NAME = "hsc-udeep_flag_gaia"
catalogue['flag_gaia'].name = GAIA_FLAG_NAME
print("{} sources flagged.".format(np.sum(catalogue[GAIA_FLAG_NAME] > 0)))
catalogue.write("{}/HSC-UDEEP.fits".format(OUT_DIR), overwrite=True)