Here we will fit the Tinker+ (2017) stellar mass-to-halo mass transformations. We use a digitized version of Figure 10 from Tinker+, fitting to the mean halo mass per stellar mass curve having $\log M_* = 0.18$ dex. (This is the green dashed line in the left side of Figure 10.)
In [1]:
##Set up matplotlib for display in the browser:
%matplotlib inline
import matplotlib as mpl
mpl.rc("savefig", dpi=250)
import matplotlib.pyplot as plt
import numpy as np
from astropy.io import fits, ascii
from astropy.table import Table,Column
The digitized version of Figure 10 (above) was created using WebPlotDigitizer.
In [63]:
# Read the digitized version from CSV [made using http://arohatgi.info/WebPlotDigitizer/]
tinker_data = ascii.read('tinker2017-SMHMrelation.csv',data_start=0,
names=['log_mhalo','log_mstar'])
mhalo_tinker = tinker_data['log_mhalo'].data
mstar_tinker = tinker_data['log_mstar'].data
In [133]:
# Put these in Mhalo/h as the Tinker results are.
h=0.7
hshift = np.log10(h)
add_mstar = np.arange(10.3,10.96,0.05)
#Velander+ (2014): red galaxies
beta=1.36
logM0=12.524+hshift
logMfiducial=10.86
add_mhalo = logM0+beta*(add_mstar-logMfiducial)
Prepend these data onto Tinker data so that we can fit the whole bit.
In [134]:
mstar=np.hstack([add_mstar,mstar_tinker])
mhalo=np.hstack([add_mhalo,mhalo_tinker])
We're going to compare this to the results from Shan+ (2017) and Velander+ (2014). The following creates the relationships from those works.
In [135]:
#Shan+ (2017)
from pyND.gal.halos import smhm_shan
shan_mstar = np.arange(9.5,12.5,0.05)
shan_mhalo = smhm_shan(shan_mstar,0.5)+hshift
#Velander+ (2014): red galaxies
beta=1.36
logM0=np.log10(1.43e13)
logMfiducial=11.3
velander_mhalo = logM0+beta*(shan_mstar-logMfiducial)+hshift
In [136]:
plt.figure(figsize=(12,4));
plt.subplot(121);
plt.plot(mhalo,mstar,'ro',label='Tinker+ (2017)');
plt.plot(shan_mhalo,shan_mstar,'-k',zorder=0,alpha=0.6,label='Shan+ (2017)');
plt.plot(velander_mhalo,shan_mstar,'-g',zorder=0,alpha=0.6,label='Velander+ (2014)');
plt.xlabel(r'$\log \ M_{halo}/h$',fontsize=16);
plt.ylabel(r'$\log \ M_{star}$',fontsize=16);
plt.xlim(12.5,15.) ; plt.ylim(10.9,12.3); #Match Figure 10
plt.legend(loc='lower right');
plt.subplot(122);
plt.plot(mstar,mhalo,'bs',label='Tinker+ (2017)');
plt.plot(shan_mstar,shan_mhalo,'-k',zorder=0,alpha=0.6,label='Shan+ (2017)');
plt.plot(shan_mstar,velander_mhalo,'-g',zorder=0,alpha=0.6,label='Velander+ (2014)');
#plt.plot(shan_mstar,velander_mhalo-0.25,'-g',zorder=0,alpha=0.6,label='Velander+ (2014)');
plt.xlabel(r'$\log \ M_{star}$',fontsize=16);
plt.ylabel(r'$\log \ M_{halo}/h$',fontsize=16);
plt.xlim(10.5,12.3) ; plt.ylim(11.4,14.1);
plt.legend(loc='lower right');
N.B. The halo masses from Tinker need an $h^{-1}$ correction that the others seem not to need.
In [137]:
from astropy.modeling import models, fitting
from pyND.abs import plotzero
fitter = fitting.LevMarLSQFitter()
linfitter = fitting.LinearLSQFitter()
In [152]:
cheb1 = models.Chebyshev1D(degree=5)
cheb_fit = linfitter(cheb1, mstar, mhalo)
In [153]:
plt.figure(figsize=(12,4.5));
plt.subplot(121);
plt.plot(mstar,mhalo,'bs',label='Tinker+ (2017)');
plt.plot(shan_mstar,cheb_fit(shan_mstar),'-r',label='Tinker fit')
plt.plot(shan_mstar,velander_mhalo,'-g',zorder=0,alpha=0.6,label='Velander+ (2014)');
plt.plot(shan_mstar,shan_mhalo,'-k',zorder=0,alpha=0.6,label='Shan+ (2017)');
plt.xlabel(r'$\log \ M_{star}$',fontsize=16);
plt.ylabel(r'$\log \ M_{halo}/h$',fontsize=16);
plt.xlim(10.2,12.3) ; plt.ylim(11.4,14.1);
plt.legend(loc='lower right');
plt.subplot(122);
plt.plot(mstar,cheb_fit(mstar)-mhalo,'bs',label='Tinker fit residuals');
plotzero()
plt.xlabel(r'$\log \ M_{star}$',fontsize=16);
plt.ylabel(r'$\log \ M_{fit} - \log \ M_{halo}$',fontsize=16);
plt.xlim(10.2,12.3) ; plt.ylim(-0.08,0.08);
plt.legend(loc='lower right');
plt.tight_layout();
In [154]:
cheb_fit
cheb_fit.domain
Out[154]:
Out[154]:
When defining this in future code, we can set the parameters of a 5th-order Chebyshev model:
In [155]:
smhm_fit = models.Chebyshev1D(5, c0=12.81806600627276, c1=1.2018634412571902,
c2=0.013199452285390979, c3=0.01775015568831073,
c4=-0.029254096888480078, c5=-0.025509308396318747,
domain=[10.3, 12.19191])
The results of the code can be found in pyND.gal.halos.smhm_tinker.
In [156]:
from pyND.gal import halos
reload(halos);
tinker_mhalo = halos.smhm_tinker(shan_mstar,0.5);
In [157]:
#Behroozi+ (2010)
from pyND.gal.halos import smhm_behroozi
b10_mhalo = smhm_behroozi(shan_mstar,0.5)
In [160]:
plt.figure(figsize=(8,6));
plt.plot(mstar,mhalo-hshift,'bs',label='Tinker+ (2017)');
plt.plot(shan_mstar,tinker_mhalo,'-r',label='halos.smhm_tinker',linewidth=2,zorder=6);
plt.plot(shan_mstar,smhm_fit(shan_mstar)-hshift,'--',color='purple',label='Tinker only');
plt.plot(shan_mstar,shan_mhalo-hshift,'-k',zorder=0,alpha=0.6,label='Shan+ (2017)');
plt.plot(shan_mstar,velander_mhalo-hshift,'--g',zorder=0,alpha=0.6,label='Velander+ (2014)');
plt.plot(shan_mstar,b10_mhalo,':b',zorder=0,alpha=0.6,label='Behroozi+ (2010)');
plt.xlabel(r'$\log \ M_{star}$',fontsize=16);
plt.ylabel(r'$\log \ M_{halo}$',fontsize=16);
plt.xlim(10.,12.3) ; plt.ylim(11.25,14.3);
plt.legend(loc='lower right');
In [161]:
from pyND.gal import halos
reload(halos);
tinker_mhalo = halos.smhm_tinker(shan_mstar,0.5);
rp17_mhalo = halos.smhm_rodriguez(shan_mstar,0.5);
In [162]:
#Behroozi+ (2010)
from pyND.gal.halos import smhm_behroozi
b10_mhalo = smhm_behroozi(shan_mstar,0.5)
In [163]:
plt.figure(figsize=(8,6));
plt.plot(shan_mstar,tinker_mhalo,'-r',label='halos.smhm_tinker',linewidth=2,zorder=6);
plt.plot(shan_mstar,rp17_mhalo,'--',color='purple',label='halos.smhm_rodriguez');
plt.plot(shan_mstar,shan_mhalo-hshift,'-k',zorder=0,alpha=0.6,label='Shan+ (2017)');
plt.plot(shan_mstar,velander_mhalo-hshift,'--g',zorder=0,alpha=0.6,label='Velander+ (2014)');
plt.plot(shan_mstar,b10_mhalo,':b',zorder=0,alpha=0.6,label='Behroozi+ (2010)');
plt.xlabel(r'$\log \ M_{star}$',fontsize=16);
plt.ylabel(r'$\log \ M_{halo}$',fontsize=16);
plt.xlim(10.,12.3) ; plt.ylim(11.25,14.3);
plt.legend(loc='lower right');
In [ ]: