예제 #1
0
def abundanceMatchSnapshot(proxy,
                           scatter,
                           lf,
                           box_size,
                           minmag=-25.,
                           maxmag=10.,
                           debug=False,
                           figname=None):

    af = AbundanceFunction(lf['mag'],
                           lf['phi'],
                           ext_range=(minmag, maxmag),
                           nbin=2000,
                           faint_end_fit_points=6)

    # check the abundance function
    if debug:
        plt.clf()
        plt.semilogy(lf['mag'], lf['phi'])
        x = np.linspace(minmag, maxmag, 101)
        plt.semilogy(x, af(x))
        plt.savefig('abundance_fcn.png')

    # deconvolution and check results (it's a good idea to always check this)
    remainder = af.deconvolute(scatter * LF_SCATTER_MULT, 40)
    x, nd = af.get_number_density_table()

    if debug:
        plt.clf()
        plt.semilogy(x, np.abs(remainder / nd))
        plt.savefig('nd_remainder.png')

    # get number densities of the halo catalog
    nd_halos = calc_number_densities(proxy, box_size)

    # do abundance matching with some scatter
    catalog_sc = af.match(nd_halos, scatter * LF_SCATTER_MULT)

    if debug:
        plt.clf()
        c, e = np.histogram(catalog_sc[~np.isnan(catalog_sc)],
                            bins=np.linspace(minmag, maxmag, 101))
        c = c / box_size**3 / (e[1:] - e[:-1])
        me = (e[:-1] + e[1:]) / 2
        plt.semilogy(me, c)
        plt.semilogy(me, af(me))
        plt.savefig('lf_in_v_out.png')

    return catalog_sc
예제 #2
0
    def deconvolve_scatter(self, scatter):
        """
        """
        # tabulate stellar mass function
        if self.gal_log_prop is True:
            msample = np.logspace(self.gal_min_mass, self.gal_max_mass, self.gal_nbins)
            nsample = self._stellar_mass_function(msample)
            self.af = AbundanceFunction(np.log10(msample), nsample, faint_end_first=True)
        else:
            msample = np.linspace(self.gal_min_mass, self.gal_max_mass, self.gal_nbins)
            nsample = self._stellar_mass_function(msample)
            self.af = AbundanceFunction(msample, nsample, faint_end_first=True)

        remainder = self.af.deconvolute(scatter, 100)
        return remainder
예제 #3
0
def comp_deconv_steps(lf, scatters, deconv_repeats, m_max=-25):
    """	Generate the projected 2D correlation by abundance matching galaxies
		Parameters:
			lf: The luminosity function. The first column is the magnitudes and the
				second column is the density in units of 1/Mpc^3.
			scatters: The scatters to deconvolve / re-introduce in the am (must
				be a list)
		Returns:
			w_p(r_p) at the r_p values specified by r_p_data.
	"""

    # Initialize abundance function and calculate the number density of the
    # halos in the box
    af = AbundanceFunction(lf[:, 0], lf[:, 1], (-25, -5))

    f, ax = plt.subplots(len(scatters),
                         1,
                         sharex='col',
                         sharey='row',
                         figsize=(13, 16))
    ax[-1].set_xlabel('Magnitude (M - 5 log h)')
    x, nd = af.get_number_density_table()

    # For each scatter and each number of deconvolution steps, plot the
    # dependence of the remainder on the step.
    for s_i in range(len(scatters)):
        scatter = scatters[s_i]
        y_max = 0
        legend = []

        for deconv_repeat in deconv_repeats:
            remainder = af.deconvolute(scatter * LF_SCATTER_MULT,
                                       deconv_repeat) / nd
            ax[s_i].plot(x,
                         remainder,
                         lw=3,
                         c=custom_blues_complement[len(legend)])
            y_max = max(y_max, np.max(remainder[x > m_max]))
            legend.append('Deconvolution Steps = %d' % (deconv_repeat))

        ax[s_i].set_ylabel('(LF (deconv $\Rightarrow$ conv) - LF) / LF')
        ax[s_i].set_xlim([np.max(lf[:, 0]) - 2, m_max])
        ax[s_i].set_ylim([-1.2, y_max * 1.2])
        ax[s_i].set_title('Luminosity Function Remainder %.2f Scatter' %
                          (scatter))

    ax[0].legend(legend)
예제 #4
0
 def __getAbundanceFunc(self, MFobj):
     """
     Returns the abundance matching function object.
     Takes considers only part of MF above log10(6.8)
     """
     IDS = np.where(MFobj[:, 0] > 6.8)
     # Abundances are not logged, whereas masses are logged
     af = AbundanceFunction(MFobj[:, 0][IDS], MFobj[:, 1][IDS], (5, 13), faint_end_first=True)
     return af
예제 #5
0
class DeconvolveSHAM(object):
    """
    class to assign stellar mass, or some other primary galaxy property,
    based on the de-convolution SHAM method, based on Yau-Yun Mao's
    implementation of Peter Behroozi's deconvolution package.
    """
    def __init__(self,
                 stellar_mass_function,
                 prim_haloprop='halo_mpeak',
                 prim_galprop='stellar_mass',
                 scatter=0.0,
                 gal_log_prop=True,
                 gal_min_mass=2.0,
                 gal_max_mass=12.5,
                 gal_nbins=200,
                 **kwargs):
        """
        Parameters
        ----------
        stellar_mass_function : callable object

        prim_haloprop : string, optional
            key indicating halo property used to assign the primary
            galaxy property

        prim_galprop : string, optional
            key indicating primary galaxy property

        gal_log_prop : boolean, optional
            boolean indicating whther the scatter in the primary
            galaxy property is modelled as a log-normal.

        gal_min_mass, gal_max_mass, gal_nbins: float, float, int
            parameters used to bin and span galaxy abundance function.
            If gal_log_prop is True, these should also be logged,
            and the spacing will be even in log.

        redshift : float
             redshit for which the model is applicable
        """

        if 'redshift' in list(kwargs.keys()):
            self.redshift = kwargs['redshift']
        else:
            self.redshift = 0.0

        self.prim_haloprop = prim_haloprop
        self.prim_galprop = prim_galprop
        self._galprop_dtypes_to_allocate = np.dtype([(str(self.prim_galprop), 'f4')])
        self._mock_generation_calling_sequence = ['inherit_halocat_properties', 'assign_stellar_mass']
        self.list_of_haloprops_needed = [prim_haloprop]

        # set default box size.
        if 'Lbox' in kwargs.keys():
            self._Lbox = kwargs['Lbox']
        else:
            self._Lbox = np.inf
        # update Lbox if a halo catalog object is passed.
        self._additional_kwargs_dict = dict(inherit_halocat_properties=['Lbox'])

        # store model parametrs
        self.gal_log_prop = gal_log_prop
        self.param_dict = ({'scatter': scatter})
        self.gal_min_mass = gal_min_mass
        self.gal_max_mass = gal_max_mass
        self.gal_nbins = gal_nbins

        # deconvolve abundance function
        self._stellar_mass_function = stellar_mass_function
        self.deconvolve_scatter(self.param_dict['scatter'])

    def inherit_halocat_properties(self, seed=None, **kwargs):
        """
        Inherit the box size during mock population
        """
        try:
            Lbox = kwargs['Lbox']
            self._Lbox = Lbox
        except KeyError:
            print("Error automatically detecting Lbox.")

    def deconvolve_scatter(self, scatter):
        """
        """
        # tabulate stellar mass function
        if self.gal_log_prop is True:
            msample = np.logspace(self.gal_min_mass, self.gal_max_mass, self.gal_nbins)
            nsample = self._stellar_mass_function(msample)
            self.af = AbundanceFunction(np.log10(msample), nsample, faint_end_first=True)
        else:
            msample = np.linspace(self.gal_min_mass, self.gal_max_mass, self.gal_nbins)
            nsample = self._stellar_mass_function(msample)
            self.af = AbundanceFunction(msample, nsample, faint_end_first=True)

        remainder = self.af.deconvolute(scatter, 100)
        return remainder

    def assign_stellar_mass(self,  **kwargs):
        """
        assign stellar mass
        """

        if 'table' in kwargs.keys():
            table = kwargs['table']
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox
        else:
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox

        Lbox = np.atleast_1d(Lbox)
        if len(Lbox) == 3:
            Lbox = (np.prod(Lbox))**(1.0/3.0)
        else:
            Lbox = Lbox[0]

        nd_halos = calc_number_densities(table[self.prim_haloprop], Lbox)
        mstar = self.af.match(nd_halos, self.param_dict['scatter'])

        if self.gal_log_prop is True:
            mstar = 10.0**mstar
            table[self.prim_galprop] = mstar
        else:
            table[self.prim_galprop] = mstar

        if 'table' in kwargs.keys():
            return table
        else:
            return mstar
예제 #6
0
    def __init__(self,
                 lf_list,
                 halos,
                 af_criteria,
                 box_size,
                 r_p_data,
                 mag_cuts,
                 wp_data_list,
                 wp_cov_list,
                 pimax,
                 nthreads,
                 deconv_repeat,
                 wp_save_path,
                 n_k_tree_cut=None):
        """ Initialize AMLikelihood object. This involves initializing an
			AbundanceFunction object for each luminosity function.
			Parameters:
				lf_list: List of luminosity functions
				halos: Halos dictionairy. halos[af_criteria] should return
					a numpy array of values for the abundance matching
					criteria for the halos.
				af_criteria: A string that will be used to index into halos
					for the abundance matching criteria data.
				box_size: The size of the box being used (length)
				r_p_data: The positions at which to calculate the 2D correlation
					function.
				mag_cuts: The magnitude cuts for w_p(r_p) (must be a list)
				wp_data_list: The list of wp_data corresponding to lf_list 
					to be used for the likelihood function
				wp_cov_list: The list of covariance matrices for w_p. Also
					important for the covariance function.
				pimax: The maximum redshift seperation to use in w_p(r_p) 
					calculation
				nthreads: The number of threads to use for CorrFunc
				deconv_repeat: The number of deconvolution steps to conduct
				wp_save_path: A unique path to which to save the parameter
					values and 2d projected correlation functions.
				n_k_tree_cut: An integer for the number of halos to cut from
					the catalog in the k nearest neighbor step. This will reduce
					accuracy at small scales but speed up computation. If set
					to None this step will not be done.
			Returns:
				Initialized class
		"""
        # Save dictionairy parameter along with box size object
        # pre-sort halos to speed up computations
        self.halos = halos[np.argsort(halos[af_criteria])]
        self.af_criteria = af_criteria
        self.box_size = box_size
        self.r_p_data = r_p_data
        self.mag_cuts = mag_cuts
        self.wp_data_list = wp_data_list
        self.wp_cov_list = wp_cov_list
        self.pimax = pimax
        self.nthreads = nthreads
        self.deconv_repeat = deconv_repeat
        # Generate list of abundance matching functions
        self.af_list = []
        for lf in lf_list:
            af = AbundanceFunction(lf[:, 0], lf[:, 1], (-25, -5))
            self.af_list.append(af)

        # Generate rbins so that the average falls at r_p_data
        rbins = np.zeros(len(r_p_data) + 1)
        rbins[1:-1] = 0.5 * (r_p_data[:-1] + r_p_data[1:])
        rbins[0] = 2 * r_p_data[0] - rbins[1]
        rbins[-1] = 2 * r_p_data[-1] - rbins[-2]
        self.rbins = rbins
        self.wp_save_path = wp_save_path

        # K nearest neighbors calculation for the cut. This only needs
        # to be done once since the cut is not dependent on the AM
        # parameters.
        # This code does not work! I need to reimplement this with weighting
        # and a mapping from original halos to the reduced catalog.
        # if n_k_tree_cut is not None:
        # 	neigh_pos = np.transpose(np.vstack([
        # 		self.halos['px'],self.halos['py']]))
        # 	# Epsilon in case some galaxies are cataloges as being at the edge
        # 	# of the box.
        # 	epsilon = 1e-12
        # 	# Set up the tree
        # 	tree = cKDTree(neigh_pos,boxsize=box_size+epsilon)
        # 	# Query the 2nd nearest neighbor.
        # 	dist, locs = tree.query(neigh_pos,k=2)
        # 	keep = np.argsort(dist[:,1])[n_k_tree_cut:]
        # 	# A bool array to use for indexing
        # 	self.wp_keep = np.zeros(len(halos),dtype=bool)
        # 	self.wp_keep[keep] = True

        # else:
        self.wp_keep = None

        self.ll_dict = {}
예제 #7
0
def generate_wp(lf_list,
                halos,
                af_criteria,
                r_p_data,
                box_size,
                mag_cuts,
                pimax=40.0,
                nthreads=1,
                scatters=None,
                deconv_repeat=20,
                verbose=False):
    """	Generate the projected 2D correlation by abundance matching galaxies
		Parameters:
			lf_list: A list of luminosity functions for each mag_cut. The first 
				column is the magnitudes and thesecond column is the density in 
				units of 1/Mpc^3.
			halos: A catalog of the halos in the n-body sim that can be indexed
				into using the quantity name.
			af_criteria: The galaxy property (i.e. vpeak) to use for abundance 
				matching.
			r_p_data: The positions at which to calculate the 2D correlation
				function.
			box_size: The size of the box (box length not volume)
			mag_cuts: The magnitude cuts for w_p(r_p) (must be a list)
			pimax: The maximum redshift seperation to use in w_p(r_p) calculation
			nthreads: The number of threads to use for CorrFunc
			scatters: The scatters to deconvolve / re-introduce in the am (must
				be a list)
			deconv_repeat: The number of deconvolution steps to conduct
			verbose: If set to true, will generate plots for visual inspection
				of am outputs.
		Returns:
			w_p(r_p) at the r_p values specified by r_p_data.
	"""
    # Repeat once for each magnitude cut
    wp_binneds = []
    for mag_cut_i in range(len(mag_cuts)):
        mag_cut = mag_cuts[mag_cut_i]
        lf = lf_list[mag_cut_i]

        # Initialize abundance function and calculate the number density of the
        # halos in the box
        af = AbundanceFunction(lf[:, 0], lf[:, 1], (-25, -5))
        nd_halos = calc_number_densities(halos[af_criteria], box_size)
        if scatters is not None:
            remainders = []
            for scatter in scatters:
                remainders.append(
                    af.deconvolute(scatter * LF_SCATTER_MULT, deconv_repeat))

        # If verbose output the match between abundance function and input data
        if verbose:
            matplotlib.rcParams.update({'font.size': 18})
            plt.figure(figsize=(10, 8))
            plt.plot(lf[:, 0], lf[:, 1], lw=7, c=custom_blues[1])
            x = np.linspace(np.min(lf[:, 0]) - 2, np.max(lf[:, 0]) + 2, 101)
            plt.semilogy(x, af(x), lw=3, c=custom_blues[4])
            plt.xlim([np.max(lf[:, 0]) + 2, np.min(lf[:, 0])])
            plt.ylim([1e-5, 1])
            plt.xlabel('Magnitude (M - 5 log h)')
            plt.ylabel('Number Density (1/ (Mpc^3 h))')
            plt.legend(['Input', 'Fit'])
            plt.title('Luminosity Function')
            plt.yscale('log')
            plt.show()

        # Plot remainder to ensure the deconvolution returned reasonable results
        if verbose and scatters is not None:
            f, ax = plt.subplots(2,
                                 1,
                                 sharex='col',
                                 sharey='row',
                                 figsize=(15, 12),
                                 gridspec_kw={'height_ratios': [2, 1]})

            x, nd = af.get_number_density_table()
            ax[0].plot(x, nd, lw=3, c=custom_blues[4])
            legend = []
            for scatter in scatters:
                ax[0].plot(af._x_deconv[float(scatter * LF_SCATTER_MULT)],
                           nd,
                           lw=3,
                           c=custom_blues_complement[2 * len(legend)])
                legend.append('Scatter = %.2f' % (scatter))
            ax[0].set_xlim([np.max(lf[:, 0]) + 2, np.min(lf[:, 0])])
            ax[0].set_ylim([1e-5, 1])
            ax[0].set_ylabel('Number Density (1/ (Mpc^3 h))')
            ax[0].legend(['Fit'] + legend)
            ax[0].set_title('Deconvolved Luminosity Function')
            ax[0].set_yscale('log')
            ax[1].set_xlabel('Magnitude (M - 5 log h)')
            ax[1].set_ylabel('(LF (deconv $\Rightarrow$ conv) - LF) / LF')
            ax[1].set_xlim([np.max(lf[:, 0]) + 2, np.min(lf[:, 0])])
            y_max = 0
            for r_i in range(len(remainders)):
                remainder = remainders[r_i] / nd
                ax[1].plot(x,
                           remainder,
                           lw=3,
                           c=custom_blues_complement[2 * r_i])
                y_max = max(y_max, np.max(remainder[x > np.min(lf[:, 0])]))
            ax[1].set_ylim([-1.2, y_max * 1.2])
            plt.show()

        # Conduct the abundance matching
        catalogs = []
        if scatters is not None:
            for scatter in scatters:
                catalogs.append(
                    af.match(nd_halos,
                             scatter * LF_SCATTER_MULT,
                             do_rematch=False))
        else:
            catalogs = [af.match(nd_halos)]

        wp_scatts = []
        for catalog in catalogs:
            # A luminosity cutoff to use for the correlation function.
            sub_catalog = catalog < mag_cut
            print('Scatter %.2f catalog has %d galaxies' %
                  (scatters[len(wp_scatts)], np.sum(sub_catalog)))
            x = halos['px'][sub_catalog]
            y = halos['py'][sub_catalog]
            z = halos['pz'][sub_catalog]

            # Generate rbins so that the average falls at r_p_data
            rbins = np.zeros(len(r_p_data) + 1)
            rbins[1:-1] = 0.5 * (r_p_data[:-1] + r_p_data[1:])
            rbins[0] = 2 * r_p_data[0] - rbins[1]
            rbins[-1] = 2 * r_p_data[-1] - rbins[-2]

            # Calculate the projected correlation function
            wp_results = wp(box_size,
                            pimax,
                            nthreads,
                            rbins,
                            x,
                            y,
                            z,
                            verbose=False,
                            output_rpavg=True)

            # Extract the results
            wp_binned = np.zeros(len(wp_results))
            for i in range(len(wp_results)):
                wp_binned[i] = wp_results[i][3]
            wp_scatts.append(wp_binned)
        wp_binneds.append(wp_scatts)

    return wp_binneds
예제 #8
0
import os
from urllib import urlopen, urlretrieve
import numpy as np
from AbundanceMatching import AbundanceFunction, LF_SCATTER_MULT

test_file = urlretrieve('http://slac.stanford.edu/~yymao/tmp/am_deconv_test.npz')[0]
tests = np.load(test_file)

M, phi_log = np.loadtxt(urlopen('http://arxiv.org/src/1304.7778v2/anc/LF_SerExp.dat'), usecols=(0,1)).T
phi = (10.**phi_log)*0.4/(0.7**3)

af = AbundanceFunction(M, phi, ext_range=(-30.0, -5.0))

for scatter in (0.05, 0.1, 0.15, 0.2, 0.25):
    scatter *= LF_SCATTER_MULT
    af.deconvolute(scatter)


    assert np.allclose(af._x_deconv[scatter], tests['{0:g}'.format(scatter)], rtol=0.001)

    # assert (af._x_deconv[scatter] == tests['{0:g}'.format(scatter)]).all()
    # diff = (af._x_deconv[scatter] == tests['{0:g}'.format(scatter)])
    # for val in diff:
    #   if val != 0:
    #       print(val)
    # ineq = np.where(diff != 0)[0]
    # print(len(diff[ineq]), len(diff))

os.remove(test_file)

moster13_halocat_keys = ('halo_upid', 'halo_mpeak', 'halo_scale_factor_mpeak',
        'halo_x', 'halo_y', 'halo_z', 'halo_zpeak', 'halo_vmax_mpeak', 'halo_mvir',
        'halo_scale_factor_firstacc', 'halo_mvir_firstacc', 'halo_halfmass_scale_factor',
        'halo_vx', 'halo_vy', 'halo_vz', 'halo_rvir_zpeak', 'halo_vmax_at_mpeak_percentile',
        'halo_mvir_host_halo', 'halo_spin', 'halo_uran')

smf_dirname = "/Users/aphearin/work/UniverseMachine/code/UniverseMachine/obs"
smf_basename = "moustakas_z0.01_z0.20.smf"
smf_fname = os.path.join(smf_dirname, smf_basename)
smf = np.loadtxt(smf_fname)
log10_sm_table_h0p7 = 0.5*(smf[:, 0] + smf[:, 1])
dn_dlog10_sm_h0p7 = smf[:, 2]
sham_ext_range = (8, 12.75)
moustakas_af = AbundanceFunction(log10_sm_table_h0p7, dn_dlog10_sm_h0p7,
        sham_ext_range, faint_end_first=True)


def load_baseline_halocat(simname='bolplanck', redshift=0, fixed_seed=411):
    halocat = CachedHaloCatalog(simname=simname, redshift=redshift)

    halocat.halo_table['halo_zpeak'] = 1./halocat.halo_table['halo_scale_factor_mpeak'] - 1.

    rvir_peak_physical_unity_h = halo_mass_to_halo_radius(halocat.halo_table['halo_mpeak'],
                                halocat.cosmology, halocat.halo_table['halo_zpeak'], 'vir')
    rvir_peak_physical = rvir_peak_physical_unity_h/halocat.cosmology.h
    halocat.halo_table['halo_rvir_zpeak'] = rvir_peak_physical*1000.

    nhalos = len(halocat.halo_table)
    with NumpyRNGContext(fixed_seed):
        halocat.halo_table['halo_uran'] = np.random.rand(nhalos)
예제 #10
0
def test_deconv():
    af = AbundanceFunction(*_lf.T, ext_range=(-25, -16))
    af.deconvolute(0.2 * LF_SCATTER_MULT, 20)
예제 #11
0
def test_AbundanceFunction():
    AbundanceFunction(*_lf.T, ext_range=(-25, -16))