DES SN 5YR Tutorial Part 4: Hubble Diagram from DES 5YR

57a0b5c408f54b18917a2e1705fed030 Dark Energy Survey Supernova Program

Tutorial Part 4 Hubble Diagram Contact author: Maria Vincenzi

[1]:
import warnings
warnings.filterwarnings("ignore")
[2]:
import os
import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import matplotlib.colors as cols

from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from astropy.cosmology import FlatwCDM, Flatw0waCDM

Best fit cosmologies as reported in our publications (SN only)

[3]:
FlatLCDM_bfit = FlatwCDM(Om0=0.352, H0=70)
FlatwCDM_bfit = FlatwCDM(Om0=0.264, H0=70, w0=-0.8)
Flatw0waCDM_bfit = Flatw0waCDM(Om0=0.495, H0=70, w0=-0.36, wa=-8.8)
Planck_bf = FlatwCDM(Om0=0.315, H0=70)

Let’s load the Hubble Diagram files

[4]:
from dessndr import data, utils
[5]:
HD = pd.read_csv(
    os.path.join(data.DES5YRDR_DATA, '4_DISTANCES_COVMAT/DES-SN5YR_HD+MetaData.csv')
)
HD.drop(labels=['CID'], axis=1, inplace=True)
[6]:
HD.head()
[6]:
CIDint IDSURVEY TYPE zHEL zHELERR zCMB zCMBERR zHD zHDERR VPEC ... PROB_SNIRFV19 PROB_SNNDESCC PROB_SNNJ17 PROB_SNNV19 MU MUERR_FINAL PROBCC_BEAMS biasCor_mu biasCor_muCOVSCALE biasCor_muCOVADD
0 1246275 10 0 0.24651 0.001 0.24605 0.001 0.24605 0.00160 0.0 ... 0.8486 1.0000 0.9999 1.0000 40.5938 0.0968 0.0 0.0341 1.0 0.0050
1 1246281 10 0 0.33600 0.001 0.33549 0.001 0.33549 0.00167 0.0 ... 1.0000 1.0000 0.9999 1.0000 41.2263 0.1360 0.0 -0.0492 1.0 0.0136
2 1246314 10 0 0.38388 0.001 0.38337 0.001 0.38337 0.00171 0.0 ... 0.7823 0.9993 0.9970 0.9998 41.6383 0.2332 0.0 0.0502 1.0 0.0348
3 1246527 10 0 0.32184 0.001 0.32078 0.001 0.32078 0.00166 0.0 ... 1.0000 0.9997 0.9998 1.0000 41.1991 0.1503 0.0 -0.0511 1.0 0.0173
4 1246529 10 0 0.49797 0.001 0.49677 0.001 0.49677 0.00180 0.0 ... 0.9407 0.9996 0.9993 1.0000 42.1471 0.1618 0.0 -0.0485 1.0 0.0095

5 rows × 49 columns

First we are going to remove any constant offset from the Hubble residuals

[7]:
weights = 1./(HD.MUERR_FINAL.values**2)
offset = np.average(
    HD.MU.values - FlatwCDM_bfit.distmod(HD.zHD.values).value,
    weights=weights
)
HD['myMURES'] = HD.MU.values - FlatwCDM_bfit.distmod(HD.zHD.values).value - offset

We are going to split the sample of DES and non-DES samples, also select the probability column to use

[8]:
des5yr= HD[HD.IDSURVEY==10].copy()
lowz= HD[HD.IDSURVEY!=10]
[9]:
Prob_column = "PROB_SNNV19"
[10]:
def MU_weighted_average(df_grouped):
    w = 1./df_grouped.MUERR_FINAL.values**2
    avg_, sum_w = np.average(df_grouped.MU.values, weights=w, returned=True)
    return avg_
[11]:
def MU_weighted_average_err(df_grouped):
    w = 1./df_grouped.MUERR_FINAL.values**2
    avg_, sum_w = np.average(df_grouped.MU.values, weights=w, returned=True)
    avg_err = np.std(df_grouped.MU.values)/np.sqrt(len(df_grouped.MU.values))
    return avg_err
[12]:
def MURES_weighted_average(df_grouped):
    w = 1./df_grouped.MUERR_FINAL.values**2
    avg_, sum_w = np.average(df_grouped.myMURES.values, weights=w, returned=True)
    return avg_
[13]:
def MURES_weighted_average_err(df_grouped):
    w = 1./df_grouped.MUERR_FINAL.values**2
    avg_, sum_w = np.average(df_grouped.myMURES.values, weights=w, returned=True)
    avg_err = np.std(df_grouped.myMURES.values)/np.sqrt(len(df_grouped.myMURES.values))
    return avg_err

Set color maps and marker colors to match our paper colors

[14]:
lowz_color='#D04A07'
des_color='#236CA7'
norm = cols.Normalize(-1,1)
colors = [[norm(-1.0), '#b4d7e8'], [norm( 1.0), '#236CA7']]
mycmap = cols.LinearSegmentedColormap.from_list("", colors)
[15]:
fig=plt.figure(figsize=(7.5,5.5))

### Hubble Diagram: Upper panel ###

a1 = plt.subplot2grid((3,1),(0,0),rowspan = 2)
plt.errorbar(des5yr.zHD.values, des5yr.MU.values,
             fmt='o', mfc='None', mec='None', ecolor=des_color, alpha=0.2, zorder=0)
im=plt.scatter(des5yr.zHD.values, des5yr.MU.values,
               alpha=0.9, cmap=mycmap, c=des5yr[Prob_column].values, zorder=1)
plt.errorbar(lowz.zHD.values, lowz.MU.values,
             fmt='o', mfc=lowz_color, mec=lowz_color, ecolor=lowz_color, alpha=0.2)

HD_sorted = HD.sort_values(by='zHD')
nitem = len(HD_sorted)/32
HD_sorted['group'] = HD_sorted.groupby(np.arange(len(HD_sorted.index))//nitem,axis=0).ngroup() + 1

# select equally populated redshift bins
mask_des = (HD_sorted.IDSURVEY.values==10) & (HD_sorted.zHD.values>0.1)
des_mean_mu = HD_sorted[mask_des].groupby('group').apply(MU_weighted_average).reset_index(
    name='weighted_average_MU')['weighted_average_MU'].values
des_mean_muerr1 = HD_sorted[mask_des].groupby('group').apply(MU_weighted_average_err).reset_index(
    name='weighted_average_MUERR')['weighted_average_MUERR'].values
plt.errorbar(HD_sorted[mask_des].groupby('group').mean()['zHD'].values, des_mean_mu,
             yerr=des_mean_muerr1,
             fmt='o-', color='k', mfc=des_color, lw=1)

mask_lz = HD_sorted.IDSURVEY.values!=10
low_mean_mu = HD_sorted[mask_lz].groupby('group').apply(MU_weighted_average).reset_index(
    name='weighted_average_MU')['weighted_average_MU'].values
low_mean_muerr = HD_sorted[mask_lz].groupby('group').apply(MU_weighted_average_err).reset_index(
    name='weighted_average_MUERR')['weighted_average_MUERR'].values
plt.errorbar(HD_sorted[mask_lz].groupby('group').mean()['zHD'].values, low_mean_mu,
             yerr=low_mean_muerr,
             fmt='o-', color='k', mfc=lowz_color, lw=1)

plt.xscale('log')
plt.xlim(0.023, 1.2)

a1.set_ylabel(r'Distance modulus $\mu$',fontsize=17)
plt.xticks([0.03,0.1,1],[' ',' ',' '])
plt.ylim(34.6,45)
plt.text(0.025,43.5, r'CfA/CSP + Foundation sample (%i SNe Ia)'%len(lowz), color=lowz_color, fontsize=12)
plt.text(0.025,42.3, 'DES-SN (%s SNe Ia)'%(len(des5yr)), color=des_color, fontsize=12)

cbar_ax = fig.add_axes([0.92, 0.13, 0.03, 0.75])
fig.colorbar(im, cax=cbar_ax, label=r'$P_{Ia}$ from SuperNNova')


### Hubble Residuals (Lowers panel) ###
#######################################

a2 = plt.subplot2grid((3,1),(2,0), rowspan = 1)
plt.errorbar(des5yr.zHD.values, des5yr.myMURES.values,
             fmt='o', mfc=des_color, mec=des_color, ecolor=des_color, alpha=0.05)
im=plt.scatter(des5yr.zHD.values, des5yr.myMURES.values,
               alpha=0.05, cmap=mycmap, c=des5yr[Prob_column].values, zorder=1)
plt.errorbar(lowz.zHD.values, lowz.myMURES.values,
             fmt='o', mfc=lowz_color, mec=lowz_color, ecolor=lowz_color, alpha=0.05)

# select equally populated redshift bins
mask_des = (HD_sorted.IDSURVEY.values==10)&(HD_sorted.zHD.values>0.1)
des_mean_mu = HD_sorted[mask_des].groupby('group').apply(MURES_weighted_average).reset_index(
    name='weighted_average_MU')['weighted_average_MU'].values
des_mean_muerr = HD_sorted[mask_des].groupby('group').apply(MURES_weighted_average_err).reset_index(
    name='weighted_average_MUERR')['weighted_average_MUERR'].values
plt.errorbar(HD_sorted[mask_des].groupby('group').mean()['zHD'].values, des_mean_mu,
             yerr=des_mean_muerr,
             fmt='o', color='k', mfc=des_color, lw=1)

mask_lz = HD_sorted.IDSURVEY.values!=10
low_mean_mu = HD_sorted[mask_lz].groupby('group').apply(MURES_weighted_average).reset_index(
    name='weighted_average_MU')['weighted_average_MU'].values
low_mean_muerr = HD_sorted[mask_lz].groupby('group').apply(MURES_weighted_average_err).reset_index(
    name='weighted_average_MUERR')['weighted_average_MUERR'].values
plt.errorbar(HD_sorted[mask_lz].groupby('group').mean()['zHD'].values, low_mean_mu,
             yerr=low_mean_muerr,
             fmt='o', color='k', mfc=lowz_color, lw=1)

# Plot best fit cosmologies and compare
zz = np.linspace(0.01,1.2,200)
cosmo1_diff = FlatLCDM_bfit.distmod(zz).value - FlatwCDM_bfit.distmod(zz).value
plt.plot(zz, cosmo1_diff-np.mean(cosmo1_diff),
         '-m', lw=3, label='DES-SN5YR'+"\n"+'(best-fit Flat$\Lambda$CDM)')

cosmo_alternative_diff = Flatw0waCDM_bfit.distmod(zz).value-FlatwCDM_bfit.distmod(zz).value
plt.plot(zz, cosmo_alternative_diff-np.mean(cosmo_alternative_diff),
         '-', color='#66ff00', lw=3, label='DES-SN5YR'+"\n"+'(best-fit Flat$w_0 w_a$CDM)')

cosmo_alternative_diff = Planck_bf.distmod(zz).value-FlatwCDM_bfit.distmod(zz).value
plt.plot(zz, cosmo_alternative_diff-np.mean(cosmo_alternative_diff),
         '--', color='#008080', lw=2.5, alpha=0.8, label='Planck 2020'+"\n"+'(best-fit Flat$\Lambda$CDM)')


plt.legend(ncol=3, framealpha=1, loc=(0.001,0.01), fontsize=9)
plt.hlines(0, 0, 1.2, lw=0.7, linestyle='-', color='k')
plt.xticks([0.03,0.1,1],['0.03','0.1','1'])
plt.ylim(-0.17,0.1)
plt.xlim(0.023, 1.2)
plt.xscale('log')
a2.set_xlabel('Redshift',fontsize=20)
a2.set_ylabel('Residuals from\n best fit Flat$w$CDM',fontsize=14)
plt.subplots_adjust(hspace=0.05)
#fig.savefig('HD_5yr_KeyPaper.pdf', bbox_inches='tight')
plt.show()
plt.close(fig)
../_images/tutorial_04-HubbleDiagram_21_0.png