def _galaxy_table_indices(source_halo_id, galaxy_host_halo_id):
    """ For every halo in the source halo catalog, calculate the index
    in the source galaxy catalog of the first appearance of a galaxy that
    occupies the halo, reserving -1 for source halos with no resident galaxies.

    Parameters
    ----------
    source_halo_id : ndarray
        Numpy integer array of shape (num_halos, )

    galaxy_host_halo_id : ndarray
        Numpy integer array of shape (num_gals, )

    Returns
    -------
    indices : ndarray
        Numpy integer array of shape (num_halos, ).
        All values will be in the interval [-1, num_gals)
    """
    uval_gals, indx_uval_gals = np.unique(galaxy_host_halo_id, return_index=True)
    idxA, idxB = crossmatch(source_halo_id, uval_gals)
    num_source_halos = len(source_halo_id)
    indices = np.zeros(num_source_halos) - 1
    indices[idxA] = indx_uval_gals[idxB]
    return indices
Exemple #2
0
def test2_bijective_case():
    """
    Setup:

    * Each source halo belongs to a unique bin.
    * There exists 5 target halos for every source halo.
    * Each source halo is populated with a single galaxy.

    Verify:

    * The target galaxy catalog is a 5x repetition of the source galaxy catalog
    """
    num_source_halos = 10
    num_galaxies = num_source_halos
    num_target_halos = num_source_halos * 5
    nhalo_min = 1

    source_halo_dt_list = [(str('halo_id'), str('i8')),
                           (str('bin_number'), str('i4'))]
    source_halos_dtype = np.dtype(source_halo_dt_list)
    source_halos = np.zeros(num_source_halos, dtype=source_halos_dtype)
    source_halos['halo_id'] = np.arange(num_source_halos).astype(int)
    source_halos['bin_number'] = np.arange(num_source_halos).astype(int)

    source_galaxy_dt_list = [(str('host_halo_id'), str('i8'))]
    source_galaxies_dtype = np.dtype(source_galaxy_dt_list)
    source_galaxies = np.zeros(num_galaxies, dtype=source_galaxies_dtype)
    source_galaxies['host_halo_id'] = np.arange(num_galaxies).astype(int)

    target_halo_dt_list = [(str('bin_number'), str('i4')),
                           (str('halo_id'), str('i8'))]
    target_halos_dtype = np.dtype(target_halo_dt_list)
    target_halos = np.zeros(num_target_halos, dtype=target_halos_dtype)
    target_halos['bin_number'] = np.repeat(source_halos['bin_number'], 5)
    target_halos['halo_id'] = np.arange(num_target_halos).astype(int)

    fake_bins = np.arange(-0.5, num_source_halos + 0.5, 1)
    # indices, matching_target_halo_ids = source_galaxy_selection_indices(source_galaxies['host_halo_id'],
    #         source_halos['halo_id'], source_halos['bin_number'], target_halos['bin_number'],
    #         target_halos['halo_id'], nhalo_min, fake_bins)
    _result = source_galaxy_selection_indices(source_galaxies['host_halo_id'],
                                              source_halos['halo_id'],
                                              source_halos['bin_number'],
                                              target_halos['bin_number'],
                                              target_halos['halo_id'],
                                              nhalo_min, fake_bins)
    indices, target_galaxy_target_halo_ids, target_galaxy_source_halo_ids = _result

    selected_galaxies = source_galaxies[indices]
    assert len(selected_galaxies) == num_target_halos
    assert np.all(selected_galaxies == np.repeat(source_galaxies, 5))

    assert len(target_galaxy_target_halo_ids) == len(selected_galaxies)
    idxA, idxB = crossmatch(target_galaxy_target_halo_ids,
                            target_halos['halo_id'])
    target_halo_bins = target_halos['bin_number'][idxB]
    assert np.all(
        np.histogram(target_halo_bins)[0] == 5 *
        np.histogram(source_halos['bin_number'])[0])
def add_hostid(catalog, halos):
    catalog['hostid'] = catalog['upid']
    cenmask = catalog['upid'] == -1
    catalog['hostid'][cenmask] = catalog['id'][cenmask]

    idxA, idxB = crossmatch(catalog['hostid'], halos['halo_id'])
    catalog['has_matching_host'] = False
    catalog['has_matching_host'][idxA] = True
    return catalog
Exemple #4
0
def match_centrals(simname='Illustris-1',
                   snapnum=135,
                   data_path=PROJECT_DIRECTORY + 'data/value_added_catalogs/'):
    """
    match central galaxies and primary subhaloes between full physics and dmo simulations.

    Returns
    -------
    fp_central_id, dmo_central_id : np.arrays
        arrays of matching subfind halo IDs

    Notes
    -----
    This function requires that host halo matches and halo catalogs have been precomputed.
    The location of the precomputed files is sepcified by ``data_path``.
    """

    # open host halo matching file
    fname = simname + '_' + str(snapnum) + '_host_halo_matches.dat'
    host_halo_match_table = Table.read(data_path + fname, format='ascii')

    # open full physics host halo catalog
    fname = simname + '_' + str(snapnum) + '_host_halo_catalog.dat'
    fp_halo_table = Table.read(data_path + fname, format='ascii')

    # open dmo host halo catalog
    fname = simname + '-Dark' + '_' + str(snapnum) + '_host_halo_catalog.dat'
    dmo_halo_table = Table.read(data_path + fname, format='ascii')

    # match halo catalogs to matches
    idx_1, idy_1 = crossmatch(fp_halo_table['host_halo_id'],
                              host_halo_match_table['host_halo_id'])

    fp_central_id = np.array(fp_halo_table['central_id'][idx_1])
    dmo_host_id = host_halo_match_table['dmo_host_halo_id'][idy_1]

    idx_2, idy_2 = crossmatch(dmo_host_id, dmo_halo_table['host_halo_id'])

    dmo_central_id = np.zeros(len(dmo_host_id)).astype('int') - 1

    dmo_central_id[idx_2] = dmo_halo_table['central_id'][idy_2]

    return fp_central_id, dmo_central_id
Exemple #5
0
def compute_richness(unique_halo_ids, halo_id_of_galaxies):
    """
    """
    unique_halo_ids = np.atleast_1d(unique_halo_ids)
    halo_id_of_galaxies = np.atleast_1d(halo_id_of_galaxies)
    richness_result = np.zeros_like(unique_halo_ids).astype(int)

    vals, counts = np.unique(halo_id_of_galaxies, return_counts=True)
    idxA, idxB = crossmatch(vals, unique_halo_ids)
    richness_result[idxB] = counts[idxA]
    return richness_result
def add_host_keys(catalog, host_keys_to_add=('mvir', 'vmax')):
    """
    """
    idxA, idxB = crossmatch(catalog['hostid'], catalog['id'])
    catalog['host_halo_is_in_catalog'] = False
    catalog['host_halo_is_in_catalog'][idxA] = True

    for key in host_keys_to_add:
        catalog['host_halo_' + key] = catalog[key]
        catalog['host_halo_' + key][idxA] = catalog[key][idxB]

    return catalog
def create_galsampled_dc2(umachine,
                          target_halos,
                          halo_indices,
                          galaxy_indices,
                          Lbox_target=256.):
    """
    """
    dc2 = Table()
    dc2['source_halo_id'] = umachine['hostid'][galaxy_indices]
    dc2['target_halo_id'] = np.repeat(target_halos['halo_id'][halo_indices],
                                      target_halos['richness'][halo_indices])

    idxA, idxB = crossmatch(dc2['target_halo_id'], target_halos['halo_id'])

    msg = "target IDs do not match!"
    assert np.all(dc2['source_halo_id'][idxA] == target_halos['source_halo_id']
                  [idxB]), msg

    target_halo_keys = ('x', 'y', 'z', 'vx', 'vy', 'vz')
    for key in target_halo_keys:
        dc2['target_halo_' + key] = 0.
        dc2['target_halo_' + key][idxA] = target_halos[key][idxB]
    dc2['target_halo_mass'] = 0.
    dc2['target_halo_mass'][idxA] = target_halos['fof_halo_mass'][idxB]

    source_galaxy_keys = ('host_halo_mvir', 'upid', 'host_centric_x',
                          'host_centric_y', 'host_centric_z',
                          'host_centric_vx', 'host_centric_vy',
                          'host_centric_vz', 'obs_sm', 'obs_sfr',
                          'sfr_percentile_fixed_sm')
    for key in source_galaxy_keys:
        dc2[key] = umachine[key][galaxy_indices]

    x_init = dc2['target_halo_x'] + dc2['host_centric_x']
    vx_init = dc2['target_halo_vx'] + dc2['host_centric_vx']
    dc2['x'], dc2['vx'] = enforce_periodicity_of_box(x_init,
                                                     Lbox_target,
                                                     velocity=vx_init)

    y_init = dc2['target_halo_y'] + dc2['host_centric_y']
    vy_init = dc2['target_halo_vy'] + dc2['host_centric_vy']
    dc2['y'], dc2['vy'] = enforce_periodicity_of_box(y_init,
                                                     Lbox_target,
                                                     velocity=vy_init)

    z_init = dc2['target_halo_z'] + dc2['host_centric_z']
    vz_init = dc2['target_halo_vz'] + dc2['host_centric_vz']
    dc2['z'], dc2['vz'] = enforce_periodicity_of_box(z_init,
                                                     Lbox_target,
                                                     velocity=vz_init)

    return dc2
Exemple #8
0
def test_empty_halos_case():
    """
    """
    #  Set up a source halo catalog with 100 halos in each mass bin
    log_mhost_min, log_mhost_max, dlog_mhost = 10.5, 15.5, 0.5
    log_mhost_bins = np.arange(log_mhost_min, log_mhost_max + dlog_mhost,
                               dlog_mhost)
    log_mhost_mids = 0.5 * (log_mhost_bins[:-1] + log_mhost_bins[1:])

    num_source_halos_per_bin = 20
    source_halo_log_mhost = np.tile(log_mhost_mids, num_source_halos_per_bin)
    num_source_halos = len(source_halo_log_mhost)
    source_halo_id = np.arange(num_source_halos).astype(int)
    source_halo_bin_number = halo_bin_indices(log_mhost=(source_halo_log_mhost,
                                                         log_mhost_bins))

    source_halo_richness = np.tile([0, 3], int(num_source_halos / 2))
    source_galaxy_host_halo_id = np.repeat(source_halo_id,
                                           source_halo_richness)
    source_galaxy_host_mass = np.repeat(source_halo_log_mhost,
                                        source_halo_richness)

    num_target_halos_per_source_halo = 11
    target_halo_bin_number = np.repeat(source_halo_bin_number,
                                       num_target_halos_per_source_halo)
    target_halo_log_mhost = np.repeat(source_halo_log_mhost,
                                      num_target_halos_per_source_halo)
    num_target_halos = len(target_halo_bin_number)
    target_halo_ids = np.arange(num_target_halos).astype('i8')

    nhalo_min = 5
    _result = source_galaxy_selection_indices(
        source_galaxy_host_halo_id, source_halo_bin_number, source_halo_id,
        target_halo_bin_number, target_halo_ids, nhalo_min, log_mhost_bins)
    selection_indices, target_galaxy_target_halo_ids, target_galaxy_source_halo_ids = _result

    selected_galaxies_source_halo_mass = source_galaxy_host_mass[
        selection_indices]

    idxA, idxB = crossmatch(target_galaxy_target_halo_ids, target_halo_ids)
    selected_galaxies_target_halo_mass = target_halo_log_mhost[idxB]
    assert np.allclose(selected_galaxies_source_halo_mass,
                       selected_galaxies_target_halo_mass)

    gen = zip(selected_galaxies_source_halo_mass,
              target_galaxy_target_halo_ids, target_galaxy_source_halo_ids)
    for galmass, target_id, source_id in gen:
        source_mask = source_halo_id == source_id
        target_mask = target_halo_ids == target_id
        source_halo_mass = source_halo_log_mhost[source_mask][0]
        target_halo_mass = target_halo_log_mhost[target_mask][0]
        assert source_halo_mass == target_halo_mass == galmass
Exemple #9
0
def test_bin_distribution_recovery():
    log_mhost_min, log_mhost_max, dlog_mhost = 10.5, 15.5, 0.5
    log_mhost_bins = np.arange(log_mhost_min, log_mhost_max + dlog_mhost,
                               dlog_mhost)
    log_mhost_mids = 0.5 * (log_mhost_bins[:-1] + log_mhost_bins[1:])

    num_source_halos_per_bin = 10
    source_halo_log_mhost = np.tile(log_mhost_mids, num_source_halos_per_bin)
    source_halo_bin_number = halo_bin_indices(log_mhost=(source_halo_log_mhost,
                                                         log_mhost_bins))

    num_target_halos_per_source_halo = 11
    target_halo_bin_number = np.repeat(source_halo_bin_number,
                                       num_target_halos_per_source_halo)
    target_halo_log_mhost = np.repeat(source_halo_log_mhost,
                                      num_target_halos_per_source_halo)
    num_target_halos = len(target_halo_bin_number)
    target_halo_ids = np.arange(num_target_halos).astype('i8')

    nhalo_min = 5
    source_halo_selection_indices, matching_target_halo_ids = source_halo_index_selection(
        source_halo_bin_number, target_halo_bin_number, target_halo_ids,
        nhalo_min, log_mhost_bins)

    idxA, idxB = crossmatch(matching_target_halo_ids, target_halo_ids)
    target_mass = target_halo_log_mhost[idxB]
    source_mass = source_halo_log_mhost[source_halo_selection_indices]
    assert np.allclose(target_mass, source_mass)

    source_halo_selection_indices, matching_target_halo_ids = source_halo_index_selection(
        source_halo_bin_number, target_halo_bin_number, target_halo_ids,
        nhalo_min, log_mhost_bins)

    idxA, idxB = crossmatch(matching_target_halo_ids, target_halo_ids)
    target_mass = target_halo_log_mhost[idxB]
    source_mass = source_halo_log_mhost[source_halo_selection_indices]
    assert np.allclose(target_mass, source_mass)
Exemple #10
0
def calc_all_observables(param):

    model.param_dict.update(dict(
        zip(param_names,
            param)))  ##update model.param_dict with pairs (param_names:params)

    try:
        model.mock.populate()
    except:
        model.populate_mock(halocat)

    gc.collect()

    output = []


    pos_gals_d = return_xyz_formatted_array(*(model.mock.galaxy_table[ax] for ax in 'xyz'), \
            velocity=model.mock.galaxy_table['vz'], velocity_distortion_dimension='z',\
                                          period=Lbox)             ##redshift space distorted
    pos_gals_d = np.array(pos_gals_d, dtype=float)
    if args.central:
        mask_cen = model.mock.galaxy_table['gal_type'] == 'centrals'
        pos_gals_d = pos_gals_d[mask_cen]

    if args.Vmax != 0:
        idx_galaxies, idx_halos = crossmatch(
            model.mock.galaxy_table['halo_id'], halocat.halo_table['halo_id'])
        model.mock.galaxy_table['halo_vmax'] = np.zeros(
            len(model.mock.galaxy_table),
            dtype=halocat.halo_table['halo_vmax'].dtype)
        model.mock.galaxy_table['halo_vmax'][
            idx_galaxies] = halocat.halo_table['halo_vmax'][idx_halos]
        mask_Vmax = model.mock.galaxy_table['halo_vmax'] > args.Vmax
        pos_gals_d = pos_gals_d[mask_Vmax]

    # ngals
    output.append(model.mock.galaxy_table['x'].size)

    # wprp
    output.append(wp(pos_gals_d, r_wp, pi_max, period=Lbox))

    # parameter set
    output.append(param)

    return output
    def assign_positions(self, **kwargs):
        """
        assign satellite positions based on subhalo positions.
        """

        if 'table' in kwargs.keys():
            table = kwargs['table']
            halo_id = table['halo_id']
            halo_hostid = table['halo_hostid']
            halo_x = table['halo_x']
            halo_y = table['halo_y']
            halo_z = table['halo_z']
        else:
            halo_x = kwargs['halo_x']
            halo_y = kwargs['halo_y']
            halo_z = kwargs['halo_z']

        # get satellite positions
        x = halo_x * 1.0
        y = halo_y * 1.0
        z = halo_z * 1.0

        # get host halo positions for satellites
        inds1, inds2 = crossmatch(halo_hostid, halo_id)
        halo_x[inds1] = halo_x[inds2]
        halo_y[inds1] = halo_y[inds2]
        halo_z[inds1] = halo_z[inds2]

        if 'table' in kwargs.keys():
            table['x'] = x * 1.0
            table['y'] = y * 1.0
            table['z'] = z * 1.0
            table['halo_x'] = halo_x * 1.0
            table['halo_y'] = halo_y * 1.0
            table['halo_z'] = halo_z * 1.0
            return table
        else:
            return np.vstack((x, y, z)).T, np.vstack(
                (halo_x, halo_y, halo_z)).T
def add_hostpos(umachine, halos):
    """
    """
    idxA, idxB = crossmatch(umachine['hostid'], halos['halo_id'])
    umachine['host_halo_x'] = np.nan
    umachine['host_halo_y'] = np.nan
    umachine['host_halo_z'] = np.nan
    umachine['host_halo_vx'] = np.nan
    umachine['host_halo_vy'] = np.nan
    umachine['host_halo_vz'] = np.nan
    umachine['host_halo_mvir'] = np.nan

    umachine['host_halo_x'][idxA] = halos['x'][idxB]
    umachine['host_halo_y'][idxA] = halos['y'][idxB]
    umachine['host_halo_z'][idxA] = halos['z'][idxB]

    umachine['host_halo_vx'][idxA] = halos['vx'][idxB]
    umachine['host_halo_vy'][idxA] = halos['vy'][idxB]
    umachine['host_halo_vz'][idxA] = halos['vz'][idxB]

    umachine['host_halo_mvir'][idxA] = halos['mvir'][idxB]

    return umachine
Exemple #13
0
    def tabulate(cls,
                 halocat,
                 tpcf,
                 *tpcf_args,
                 mode='auto',
                 Num_ptcl_requirement=sim_defaults.Num_ptcl_requirement,
                 prim_haloprop_key=model_defaults.prim_haloprop_key,
                 prim_haloprop_bins=100,
                 sec_haloprop_key=model_defaults.sec_haloprop_key,
                 sec_haloprop_percentile_bins=None,
                 sats_per_prim_haloprop=3e-12,
                 downsample=1.0,
                 verbose=False,
                 redshift_space_distortions=True,
                 cens_prof_model=None,
                 sats_prof_model=None,
                 project_xyz=False,
                 cosmology_obs=None,
                 num_threads=1,
                 **tpcf_kwargs):
        """
        Tabulates correlation functions for halos such that galaxy correlation
        functions can be calculated rapidly.

        Parameters
        ----------
        halocat : object
            Either an instance of `halotools.sim_manager.CachedHaloCatalog` or
            `halotools.sim_manager.UserSuppliedHaloCatalog`. This halo catalog
            is used to tabubulate correlation functions.

        tpcf : function
            The halotools correlation function for which values are tabulated.
            Positional arguments should be passed after this function.
            Additional keyword arguments for the correlation function are also
            passed through this function.

        *tpcf_args : tuple, optional
            Positional arguments passed to the ``tpcf`` function.

        mode : string, optional
            String describing whether an auto- ('auto') or a cross-correlation
            ('cross') function is going to be tabulated.

        Num_ptcl_requirement : int, optional
            Requirement on the number of dark matter particles in the halo
            catalog. The column defined by the ``prim_haloprop_key`` string
            will have a cut placed on it: all halos with
            halocat.halo_table[prim_haloprop_key] <
            Num_ptcl_requirement*halocat.particle_mass will be thrown out
            immediately after reading the original halo catalog in memory.
            Default value is set in
            `~halotools.sim_defaults.Num_ptcl_requirement`.

        prim_haloprop_key : string, optional
            String giving the column name of the primary halo property
            governing the occupation statistics of gal_type galaxies. Default
            value is specified in the model_defaults module.

        prim_haloprop_bins : int or list, optional
            Integer determining how many (logarithmic) bins in primary halo
            property will be used. If a list or numpy array is provided, these
            will be used as bins directly.

        sec_haloprop_key : string, optional
            String giving the column name of the secondary halo property
            governing the assembly bias. Must be a key in the table passed to
            the methods of `HeavisideAssembiasComponent`. Default value is
            specified in the `~halotools.empirical_models.model_defaults`
            module.

        sec_haloprop_percentile_bins : int, float or None, optional
            If an integer, it determines how many evenly spaced bins in the
            secondary halo property percentiles are going to be used. If a
            float between 0 and 1, it determines the split. If None is
            provided, no binning is applied.

        sats_per_prim_haloprop : float, optional
            Float determing how many satellites sample each halo. For each
            halo, the number is drawn from a Poisson distribution with an
            expectation value of ``sats_per_prim_haloprop`` times the primary
            halo property.

        downsample : float or function, optional
            Fraction between 0 and 1 used to downsample the total sample used
            to tabulate correlation functions. Values below unity can be used
            to reduce the computation time. It should not result in biases but
            the resulting correlation functions will be less accurate. If
            float, the same value is applied to all halos. If function, it
            should return the fraction is a function of the primary halo
            property.

        verbose : boolean, optional
            Boolean determing whether the progress should be displayed.

        redshift_space_distortions : boolean, optional
            Boolean determining whether redshift space distortions should be
            applied to halos/galaxies.

        cens_prof_model : object, optional
            Instance of `halotools.empirical_models.MonteCarloGalProf` that
            determines the phase space coordinates of centrals. If none is
            provided, `halotools.empirical_models.TrivialPhaseSpace` will be
            used.

        sats_prof_model : object, optional
            Instance of `halotools.empirical_models.MonteCarloGalProf` that
            determines the phase space coordinates of satellites. If none is
            provided, `halotools.empirical_models.NFWPhaseSpace` will be used.

        project_xyz : bool, optional
            If True, the coordinates will be projected along all three spatial
            axes. By default, only the projection onto the z-axis is used.

        cosmology_obs : object, optional
            Instance of an astropy `~astropy.cosmology`. This can be used to
            correct coordinates in the simulation for the Alcock-Paczynski (AP)
            effect, i.e. a mismatch between the cosmology of the model
            (simulation) and the cosmology used to interpret observations. Note
            that the cosmology of the simulation is part of the halocat object.
            If None, no correction for the AP effect is applied. Also, a
            correction for the AP effect is only applied for auto-correlation
            functions.

        num_threads : int, optional
            How many threads to use for the tabulation.

        **tpcf_kwargs : dict, optional
                Keyword arguments passed to the ``tpcf`` function.

        Returns
        -------
        halotab : TabCorr
            Object containing all necessary information to calculate
            correlation functions for arbitrary galaxy models.
        """

        if 'period' in tpcf_kwargs:
            print('Warning: TabCorr will pass the keyword argument "period" ' +
                  'to {} based on the Lbox argument of'.format(tpcf.__name__) +
                  ' the halo catalog. The value you provided will be ignored.')
            del tpcf_kwargs['period']

        halotab = cls()

        if cosmology_obs is not None and mode == 'auto':
            rp_stretch = (
                (cosmology_obs.comoving_distance(halocat.redshift) *
                 cosmology_obs.H0) /
                (halocat.cosmology.comoving_distance(halocat.redshift) *
                 halocat.cosmology.H0))
            pi_stretch = (halocat.cosmology.efunc(halocat.redshift) /
                          cosmology_obs.efunc(halocat.redshift))
            lbox_stretch = np.array([rp_stretch, rp_stretch, pi_stretch])
        else:
            lbox_stretch = np.ones(3)

        # First, we tabulate the halo number densities.
        halos = halocat.halo_table
        halos = halos[halos['halo_pid'] == -1]
        halos = halos[halos[prim_haloprop_key] >=
                      (Num_ptcl_requirement + 0.5) * halocat.particle_mass]

        if isinstance(prim_haloprop_bins, int):
            prim_haloprop_bins = np.linspace(
                np.log10(np.amin(halos[prim_haloprop_key])) - 1e-3,
                np.log10(np.amax(halos[prim_haloprop_key])) + 1e-3,
                prim_haloprop_bins + 1)
        elif isinstance(prim_haloprop_bins, (list, np.ndarray)):
            pass
        else:
            raise ValueError('prim_haloprop_bins must be an int, list or ' +
                             'numpy array.')

        if sec_haloprop_percentile_bins is None:
            sec_haloprop_percentile_bins = np.array([-1e-3, 1 + 1e-3])
        elif isinstance(sec_haloprop_percentile_bins, float):
            if not (0 < sec_haloprop_percentile_bins
                    and sec_haloprop_percentile_bins < 1):
                raise ValueError('sec_haloprop_percentile_bins must be ' +
                                 'between 0 and 1.')
            sec_haloprop_percentile_bins = np.array(
                [-1e-3, sec_haloprop_percentile_bins, 1 + 1e-3])
        elif isinstance(sec_haloprop_percentile_bins, int):
            sec_haloprop_percentile_bins = np.linspace(
                -1e-3, 1 + 1e-3, sec_haloprop_percentile_bins + 1)
        else:
            raise ValueError('sec_haloprop_percentile_bins must be an int, ' +
                             'float, list or numpy array.')

        halos[sec_haloprop_key +
              '_percentile'] = (compute_conditional_percentiles(
                  table=halos,
                  prim_haloprop_key=prim_haloprop_key,
                  sec_haloprop_key=sec_haloprop_key))

        halotab.gal_type = Table()

        n_h, prim_haloprop_bins, sec_haloprop_percentile_bins = (
            np.histogram2d(
                np.log10(halos[prim_haloprop_key]),
                halos[sec_haloprop_key + '_percentile'],
                bins=[prim_haloprop_bins, sec_haloprop_percentile_bins]))
        halotab.gal_type['n_h'] = n_h.ravel(order='F')

        grid = np.meshgrid(prim_haloprop_bins, sec_haloprop_percentile_bins)
        halotab.gal_type['log_prim_haloprop_min'] = grid[0][:-1, :-1].ravel()
        halotab.gal_type['log_prim_haloprop_max'] = grid[0][:-1, 1:].ravel()
        halotab.gal_type['sec_haloprop_percentile_min'] = (
            grid[1][:-1, :-1].ravel())
        halotab.gal_type['sec_haloprop_percentile_max'] = (
            grid[1][1:, :-1].ravel())

        halotab.gal_type = vstack([halotab.gal_type, halotab.gal_type])
        halotab.gal_type['gal_type'] = np.concatenate(
            (np.repeat('centrals'.encode('utf8'),
                       len(halotab.gal_type) // 2),
             np.repeat('satellites'.encode('utf8'),
                       len(halotab.gal_type) // 2)))
        halotab.gal_type['prim_haloprop'] = 10**(
            0.5 * (halotab.gal_type['log_prim_haloprop_min'] +
                   halotab.gal_type['log_prim_haloprop_max']))
        halotab.gal_type['sec_haloprop_percentile'] = (
            0.5 * (halotab.gal_type['sec_haloprop_percentile_min'] +
                   halotab.gal_type['sec_haloprop_percentile_max']))

        # Now, we tabulate the correlation functions.
        cens_occ_model = Zheng07Cens(prim_haloprop_key=prim_haloprop_key)
        if cens_prof_model is None:
            cens_prof_model = TrivialPhaseSpace(redshift=halocat.redshift)
        sats_occ_model = Zheng07Sats(prim_haloprop_key=prim_haloprop_key)
        if sats_prof_model is None:
            sats_prof_model = NFWPhaseSpace(redshift=halocat.redshift)

        model = HodModelFactory(centrals_occupation=cens_occ_model,
                                centrals_profile=cens_prof_model,
                                satellites_occupation=sats_occ_model,
                                satellites_profile=sats_prof_model)

        model.param_dict['logMmin'] = 0
        model.param_dict['sigma_logM'] = 0.1
        model.param_dict['alpha'] = 1.0
        model.param_dict['logM0'] = 0
        model.param_dict['logM1'] = -np.log10(sats_per_prim_haloprop)
        model.populate_mock(halocat, Num_ptcl_requirement=Num_ptcl_requirement)

        gals = model.mock.galaxy_table
        idx_gals, idx_halos = crossmatch(gals['halo_id'], halos['halo_id'])
        assert np.all(gals['halo_id'][idx_gals] == halos['halo_id'][idx_halos])
        gals[sec_haloprop_key + '_percentile'] = np.zeros(len(gals))
        gals[sec_haloprop_key +
             '_percentile'][idx_gals] = (halos[sec_haloprop_key +
                                               '_percentile'][idx_halos])

        if verbose:
            print("Number of tracer particles: {0}".format(len(gals)))

        for xyz in ['xyz', 'yzx', 'zxy']:

            if verbose and project_xyz:
                print("Projecting onto {0}-axis...".format(xyz[2]))

            pos_all = (return_xyz_formatted_array(
                x=gals[xyz[0]],
                y=gals[xyz[1]],
                z=gals[xyz[2]],
                velocity=gals['v' +
                              xyz[2]] if redshift_space_distortions else 0,
                velocity_distortion_dimension='z',
                period=halocat.Lbox,
                redshift=halocat.redshift,
                cosmology=halocat.cosmology) * lbox_stretch)

            period = halocat.Lbox * lbox_stretch

            # Get a list of the positions of each sub-population.
            i_prim = np.digitize(np.log10(gals[prim_haloprop_key]),
                                 bins=prim_haloprop_bins,
                                 right=False) - 1
            mask = (i_prim < 0) | (i_prim >= len(prim_haloprop_bins))
            i_sec = np.digitize(gals[sec_haloprop_key + '_percentile'],
                                bins=sec_haloprop_percentile_bins,
                                right=False) - 1
            i_type = np.where(gals['gal_type'] == 'centrals', 0, 1)

            # Throw out those that don't fall into any bin.
            pos_all = pos_all[~mask]

            i = (i_prim + i_sec * (len(prim_haloprop_bins) - 1) + i_type *
                 ((len(prim_haloprop_bins) - 1) *
                  (len(sec_haloprop_percentile_bins) - 1)))

            pos_all = pos_all[np.argsort(i)]
            counts = np.bincount(i, minlength=len(halotab.gal_type))

            assert len(counts) == len(halotab.gal_type)

            pos_bin = []
            for i in range(len(halotab.gal_type)):

                pos = pos_all[np.sum(counts[:i]):np.sum(counts[:i + 1]), :]
                if halotab.gal_type['gal_type'][i] == 'centrals':
                    # Make sure the number of halos are consistent.
                    try:
                        assert len(pos) == int(halotab.gal_type['n_h'][i])
                    except AssertionError:
                        raise RuntimeError('There was an internal error in ' +
                                           'TabCorr. If possible, please ' +
                                           'report this bug in the TabCorr ' +
                                           'GitHub repository.')
                else:
                    if len(pos) == 0 and halotab.gal_type['n_h'][i] != 0:
                        raise RuntimeError(
                            'There was at least one bin without satellite ' +
                            'tracers. Increase sats_per_prim_haloprop.')

                if len(pos) > 0:

                    if isinstance(downsample, float):
                        use = np.random.random(len(pos)) < downsample
                    else:
                        use = (np.random.random(len(pos)) < downsample(
                            halotab.gal_type['prim_haloprop'][i]))

                    # If the down-sampling reduced the number of tracers to at
                    # or below one, force at least 2 tracers to not bias the
                    # clustering estimates.
                    if np.sum(use) <= 1 and len(pos) > 1:
                        use = np.zeros(len(pos), dtype=bool)
                        use[np.random.choice(len(pos), size=2)] = True

                    pos = pos[use]

                pos_bin.append(pos)

            if mode == 'auto':
                combinations = itertools.combinations_with_replacement(
                    range(len(halotab.gal_type)), 2)
            else:
                combinations = range(len(halotab.gal_type))

            if xyz == 'xyz':
                tpcf_matrix, tpcf_shape = compute_tpcf_matrix(
                    mode,
                    pos_bin,
                    tpcf,
                    period,
                    tpcf_args,
                    tpcf_kwargs,
                    combinations,
                    num_threads=num_threads,
                    verbose=verbose)

            if not project_xyz or mode == 'cross':
                break
            elif xyz != 'xyz':
                tpcf_matrix += compute_tpcf_matrix(mode,
                                                   pos_bin,
                                                   tpcf,
                                                   period,
                                                   tpcf_args,
                                                   tpcf_kwargs,
                                                   combinations,
                                                   num_threads=num_threads,
                                                   verbose=verbose)[0]

        if project_xyz and mode == 'auto':
            tpcf_matrix /= 3.0

        if mode == 'auto':
            tpcf_matrix_flat = []
            for i in range(tpcf_matrix.shape[0]):
                tpcf_matrix_flat.append(
                    symmetric_matrix_to_array(tpcf_matrix[i]))
            tpcf_matrix = np.array(tpcf_matrix_flat)

        # Remove entries that don't have any halos.
        use = halotab.gal_type['n_h'] != 0
        halotab.gal_type = halotab.gal_type[use]
        if mode == 'auto':
            use = symmetric_matrix_to_array(np.outer(use, use))
        tpcf_matrix = tpcf_matrix[:, use]

        halotab.gal_type['n_h'] /= np.prod(halocat.Lbox * lbox_stretch)

        halotab.attrs = {}
        halotab.attrs['tpcf'] = tpcf.__name__
        halotab.attrs['mode'] = mode
        halotab.attrs['simname'] = halocat.simname
        halotab.attrs['redshift'] = halocat.redshift
        halotab.attrs['Num_ptcl_requirement'] = Num_ptcl_requirement
        halotab.attrs['prim_haloprop_key'] = prim_haloprop_key
        halotab.attrs['sec_haloprop_key'] = sec_haloprop_key

        halotab.tpcf_args = tpcf_args
        halotab.tpcf_kwargs = tpcf_kwargs
        halotab.tpcf_shape = tpcf_shape
        halotab.tpcf_matrix = tpcf_matrix

        halotab.init = True

        return halotab
Exemple #14
0
    def tabulate(cls,
                 halocat,
                 tpcf,
                 *tpcf_args,
                 mode='auto',
                 Num_ptcl_requirement=sim_defaults.Num_ptcl_requirement,
                 cosmology=sim_defaults.default_cosmology,
                 prim_haloprop_key=model_defaults.prim_haloprop_key,
                 prim_haloprop_bins=100,
                 sec_haloprop_key=model_defaults.sec_haloprop_key,
                 sec_haloprop_percentile_bins=None,
                 sats_per_prim_haloprop=3e-12,
                 downsample=1.0,
                 verbose=False,
                 redshift_space_distortions=True,
                 cens_prof_model=None,
                 sats_prof_model=None,
                 project_xyz=False,
                 cosmology_ref=None,
                 comm=None,
                 **tpcf_kwargs):
        """
        Tabulates correlation functions for halos such that galaxy correlation
        functions can be calculated rapidly.

        Parameters
        ----------
        halocat : object
            Either an instance of `halotools.sim_manager.CachedHaloCatalog` or
            `halotools.sim_manager.UserSuppliedHaloCatalog`. This halo catalog
            is used to tabubulate correlation functions.

        tpcf : function
            The halotools correlation function for which values are tabulated.
            Positional arguments should be passed after this function.
            Additional keyword arguments for the correlation function are also
            passed through this function.

        *tpcf_args : tuple, optional
            Positional arguments passed to the ``tpcf`` function.

        mode : string, optional
            String describing whether an auto- ('auto') or a cross-correlation
            ('cross') function is going to be tabulated.

        Num_ptcl_requirement : int, optional
            Requirement on the number of dark matter particles in the halo
            catalog. The column defined by the ``prim_haloprop_key`` string
            will have a cut placed on it: all halos with
            halocat.halo_table[prim_haloprop_key] <
            Num_ptcl_requirement*halocat.particle_mass will be thrown out
            immediately after reading the original halo catalog in memory.
            Default value is set in
            `~halotools.sim_defaults.Num_ptcl_requirement`.

        cosmology : object, optional
            Instance of an astropy `~astropy.cosmology`. Default cosmology is
            set in `~halotools.sim_manager.sim_defaults`. This might be used to
            calculate phase-space distributions and redshift space distortions.

        prim_haloprop_key : string, optional
            String giving the column name of the primary halo property
            governing the occupation statistics of gal_type galaxies. Default
            value is specified in the model_defaults module.

        prim_haloprop_bins : int or list, optional
            Integer determining how many (logarithmic) bins in primary halo
            property will be used. If a list or numpy array is provided, these
            will be used as bins directly.

        sec_haloprop_key : string, optional
            String giving the column name of the secondary halo property
            governing the assembly bias. Must be a key in the table passed to
            the methods of `HeavisideAssembiasComponent`. Default value is
            specified in the `~halotools.empirical_models.model_defaults`
            module.

        sec_haloprop_percentile_bins : int, float, list or None, optional
            If an integer, it determines how many evenly spaced bins in the
            secondary halo property percentiles are going to be used. If a
            float between 0 and 1, it determines the split. Finally, if a list
            or numpy array, it directly describes the bins that are going to be
            used. If None is provided, no binning is applied.

        sats_per_prim_haloprop : float, optional
            Float determing how many satellites sample each halo. For each
            halo, the number is drawn from a Poisson distribution with an
            expectation value of ``sats_per_prim_haloprop`` times the primary
            halo property.

        downsample : float, optional
            Fraction between 0 and 1 used to downsample the total sample used
            to tabulate correlation functions. Values below unity can be used
            to reduce the computation time. It should not result in biases but
            the resulting correlation functions will be less accurate.

        verbose : boolean, optional
            Boolean determing whether the progress should be displayed.

        redshift_space_distortions : boolean, optional
            Boolean determining whether redshift space distortions should be
            applied to halos/galaxies.

        cens_prof_model : object, optional
            Instance of `halotools.empirical_models.MonteCarloGalProf` that
            determines the phase space coordinates of centrals. If none is
            provided, `halotools.empirical_models.TrivialPhaseSpace` will be
            used.

        sats_prof_model : object, optional
            Instance of `halotools.empirical_models.MonteCarloGalProf` that
            determines the phase space coordinates of satellites. If none is
            provided, `halotools.empirical_models.NFWPhaseSpace` will be used.

        project_xyz : bool, optional
            If True, the coordinates will be projected along all three spatial
            axes. By default, only the projection onto the z-axis is used.

        comm : MPI communicator
            If not None, then will distribute calculation via MPI

        **tpcf_kwargs : dict, optional
                Keyword arguments passed to the ``tpcf`` function.

        Returns
        -------
        halotab : TabCorr
            Object containing all necessary information to calculate
            correlation functions for arbitrary galaxy models.
        """

        if sec_haloprop_percentile_bins is None:
            sec_haloprop_percentile_bins = np.array([0, 1])
        elif isinstance(sec_haloprop_percentile_bins, float):
            sec_haloprop_percentile_bins = np.array(
                [0, sec_haloprop_percentile_bins, 1])

        if 'period' in tpcf_kwargs:
            print('Warning: TabCorr will pass the keyword argument "period" ' +
                  'to {} based on the Lbox argument of'.format(tpcf.__name__) +
                  ' the halo catalog. The value you provided will be ignored.')
            del tpcf_kwargs['period']

        halotab = cls()

        if cosmology_ref is not None and mode == 'auto':
            rp_stretch = (
                (cosmology_ref.comoving_distance(halocat.redshift) *
                 cosmology_ref.H0) /
                (cosmology.comoving_distance(halocat.redshift) * cosmology.H0))
            pi_stretch = (cosmology.efunc(halocat.redshift) /
                          cosmology_ref.efunc(halocat.redshift))
            lbox_stretch = np.array([rp_stretch, rp_stretch, pi_stretch])
        else:
            lbox_stretch = np.ones(3)

        # First, we tabulate the halo number densities.
        halos = halocat.halo_table
        halos = halos[halos['halo_pid'] == -1]
        halos = halos[halos[prim_haloprop_key] >=
                      (Num_ptcl_requirement - 0.5) * halocat.particle_mass]

        if isinstance(prim_haloprop_bins, int):
            prim_haloprop_bins = np.linspace(
                np.log10(np.amin(halos[prim_haloprop_key])) - 1e-3,
                np.log10(np.amax(halos[prim_haloprop_key])) + 1e-3,
                prim_haloprop_bins + 1)
        elif not isinstance(prim_haloprop_bins, (list, np.ndarray)):
            raise ValueError('prim_haloprop_bins must be an int, list or ' +
                             'numpy array.')

        halos[sec_haloprop_key +
              '_percentile'] = (compute_conditional_percentiles(
                  table=halos,
                  prim_haloprop_key=prim_haloprop_key,
                  sec_haloprop_key=sec_haloprop_key))

        halotab.gal_type = Table()

        n_h, prim_haloprop_bins, sec_haloprop_percentile_bins = (
            np.histogram2d(
                np.log10(halos[prim_haloprop_key]),
                halos[sec_haloprop_key + '_percentile'],
                bins=[prim_haloprop_bins, sec_haloprop_percentile_bins]))
        halotab.gal_type['n_h'] = n_h.ravel(order='F') / np.prod(
            halocat.Lbox * lbox_stretch)

        grid = np.meshgrid(prim_haloprop_bins, sec_haloprop_percentile_bins)
        halotab.gal_type['log_prim_haloprop_min'] = grid[0][:-1, :-1].ravel()
        halotab.gal_type['log_prim_haloprop_max'] = grid[0][:-1, 1:].ravel()
        halotab.gal_type['sec_haloprop_percentile_min'] = (
            grid[1][:-1, :-1].ravel())
        halotab.gal_type['sec_haloprop_percentile_max'] = (
            grid[1][1:, :-1].ravel())

        halotab.gal_type = vstack([halotab.gal_type, halotab.gal_type])
        halotab.gal_type['gal_type'] = np.concatenate(
            (np.repeat('centrals'.encode('utf8'),
                       len(halotab.gal_type) // 2),
             np.repeat('satellites'.encode('utf8'),
                       len(halotab.gal_type) // 2)))
        halotab.gal_type['prim_haloprop'] = 10**(
            0.5 * (halotab.gal_type['log_prim_haloprop_min'] +
                   halotab.gal_type['log_prim_haloprop_max']))
        halotab.gal_type['sec_haloprop_percentile'] = (
            0.5 * (halotab.gal_type['sec_haloprop_percentile_min'] +
                   halotab.gal_type['sec_haloprop_percentile_max']))

        # Now, we tabulate the correlation functions.
        cens_occ_model = Zheng07Cens(prim_haloprop_key=prim_haloprop_key)
        if cens_prof_model is None:
            cens_prof_model = TrivialPhaseSpace(redshift=halocat.redshift)
        sats_occ_model = Zheng07Sats(prim_haloprop_key=prim_haloprop_key)
        if sats_prof_model is None:
            sats_prof_model = NFWPhaseSpace(redshift=halocat.redshift)

        model = HodModelFactory(centrals_occupation=cens_occ_model,
                                centrals_profile=cens_prof_model,
                                satellites_occupation=sats_occ_model,
                                satellites_profile=sats_prof_model)

        model.param_dict['logMmin'] = 0
        model.param_dict['sigma_logM'] = 0.1
        model.param_dict['alpha'] = 1.0
        model.param_dict['logM0'] = 0
        model.param_dict['logM1'] = -np.log10(sats_per_prim_haloprop)
        model.populate_mock(halocat, Num_ptcl_requirement=Num_ptcl_requirement)
        gals = model.mock.galaxy_table
        gals = gals[np.random.random(len(gals)) < downsample]

        idx_gals, idx_halos = crossmatch(gals['halo_id'], halos['halo_id'])
        assert np.all(gals['halo_id'][idx_gals] == halos['halo_id'][idx_halos])
        gals[sec_haloprop_key + '_percentile'] = np.zeros(len(gals))
        gals[sec_haloprop_key +
             '_percentile'][idx_gals] = (halos[sec_haloprop_key +
                                               '_percentile'][idx_halos])

        if verbose:
            print("Number of tracer particles: {0}".format(len(gals)))

        for xyz in ['xyz', 'yzx', 'zxy']:
            pos_all = return_xyz_formatted_array(
                x=gals[xyz[0]],
                y=gals[xyz[1]],
                z=gals[xyz[2]],
                velocity=gals['v' +
                              xyz[2]] if redshift_space_distortions else 0,
                velocity_distortion_dimension='z',
                period=halocat.Lbox,
                redshift=halocat.redshift,
                cosmology=cosmology) * lbox_stretch

            pos = []
            n_gals = []
            for i in range(len(halotab.gal_type)):

                mask = ((10**(halotab.gal_type['log_prim_haloprop_min'][i]) <
                         gals[prim_haloprop_key]) &
                        (10**(halotab.gal_type['log_prim_haloprop_max'][i]) >=
                         gals[prim_haloprop_key]) &
                        (halotab.gal_type['sec_haloprop_percentile_min'][i] <
                         gals[sec_haloprop_key + '_percentile']) &
                        (halotab.gal_type['sec_haloprop_percentile_max'][i] >=
                         gals[sec_haloprop_key + '_percentile']) &
                        (halotab.gal_type['gal_type'][i] == gals['gal_type']))

                pos.append(pos_all[mask])
                n_gals.append(np.sum(mask))

            n_gals = np.array(n_gals)
            n_done = 0

            if verbose:
                print("Projecting onto {0}-axis...".format(xyz[2]))

            gal_type_index = np.arange(len(halotab.gal_type))

            if (comm is not None) & (has_mpi):
                size = comm.size
                rank = comm.rank
                gal_type_index = gal_type_index[rank::size]
                print('{}: len(gal_type_index)={}'.format(
                    rank, len(gal_type_index)))
            elif (comm is not None) & (not has_mpi):
                raise (ImportError(
                    "You passed something to the comm argument, but I couldn't import mpi4py"
                ))

            for i in gal_type_index:

                if mode == 'auto':
                    for k in np.arange(i, len(halotab.gal_type)):
                        if len(pos[i]) * len(pos[k]) > 0:

                            if verbose:
                                if comm:
                                    if comm.rank == 0:
                                        n_done += (n_gals[i] * n_gals[k] *
                                                   (2 if k != i else 1))
                                        print_progress(n_done /
                                                       np.sum(n_gals)**2)
                                else:
                                    n_done += (n_gals[i] * n_gals[k] *
                                               (2 if k != i else 1))
                                    print_progress(n_done / np.sum(n_gals)**2)
                            if i == k:
                                xi = tpcf(pos[i],
                                          *tpcf_args,
                                          sample2=pos[k] if k != i else None,
                                          do_auto=True,
                                          do_cross=False,
                                          period=halocat.Lbox * lbox_stretch,
                                          **tpcf_kwargs)
                            else:
                                xi = tpcf(pos[i],
                                          *tpcf_args,
                                          sample2=pos[k] if k != i else None,
                                          do_auto=False,
                                          do_cross=True,
                                          period=halocat.Lbox * lbox_stretch,
                                          **tpcf_kwargs)

                            if 'tpcf_matrix' not in locals():
                                tpcf_matrix = np.zeros(
                                    (len(xi.ravel()), len(halotab.gal_type),
                                     len(halotab.gal_type)))
                                tpcf_shape = xi.shape
                            tpcf_matrix[:, i, k] += xi.ravel()
                            tpcf_matrix[:, k, i] = tpcf_matrix[:, i, k]

                elif mode == 'cross':
                    if len(pos[i]) > 0:

                        if verbose:
                            n_done += n_gals[i]
                            print_progress(n_done / np.sum(n_gals))

                        xi = tpcf(pos[i],
                                  *tpcf_args,
                                  **tpcf_kwargs,
                                  period=halocat.Lbox * lbox_stretch)
                        if tpcf.__name__ == 'delta_sigma':
                            xi = xi[1]
                        if 'tpcf_matrix' not in locals():
                            tpcf_matrix = np.zeros(
                                (len(xi.ravel()), len(halotab.gal_type)))
                            tpcf_shape = xi.shape
                        tpcf_matrix[:, i] = xi.ravel()

            if not project_xyz or mode == 'cross':
                break

        if comm:
            tpcf_matrix = comm.allreduce(tpcf_matrix, op=MPI.SUM)

        if project_xyz and mode == 'auto':
            tpcf_matrix /= 3.0

        if mode == 'auto':
            tpcf_matrix_flat = []
            for i in range(tpcf_matrix.shape[0]):
                tpcf_matrix_flat.append(
                    symmetric_matrix_to_array(tpcf_matrix[i]))
            tpcf_matrix = np.array(tpcf_matrix_flat)

        halotab.attrs = {}
        halotab.attrs['tpcf'] = tpcf.__name__
        halotab.attrs['mode'] = mode
        halotab.attrs['simname'] = halocat.simname
        halotab.attrs['redshift'] = halocat.redshift
        halotab.attrs['Num_ptcl_requirement'] = Num_ptcl_requirement
        halotab.attrs['prim_haloprop_key'] = prim_haloprop_key
        halotab.attrs['sec_haloprop_key'] = sec_haloprop_key

        halotab.tpcf_args = tpcf_args
        halotab.tpcf_kwargs = tpcf_kwargs
        halotab.tpcf_shape = tpcf_shape
        halotab.tpcf_matrix = tpcf_matrix

        halotab.init = True

        return halotab
    def assign_positions(self, **kwargs):
        """
        assign satellite positions based on subhalo radial positions and random angular positions.
        """

        if 'table' in kwargs.keys():
            table = kwargs['table']
            halo_x = table['halo_x']
            halo_y = table['halo_y']
            halo_z = table['halo_z']
            halo_hostid = table['halo_hostid']
            halo_id = table['halo_id']
            b_to_a = table['halo_b_to_a']
            c_to_a = table['halo_c_to_a']
            halo_axisA_x = table['halo_axisA_x']
            halo_axisA_y = table['halo_axisA_y']
            halo_axisA_z = table['halo_axisA_z']
            halo_axisC_x = table['halo_axisC_x']
            halo_axisC_y = table['halo_axisC_y']
            halo_axisC_z = table['halo_axisC_z']
            concentration = table['halo_nfw_conc']
            rvir = table['halo_rvir']
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox
        else:
            halo_x = kwargs['halo_x']
            halo_y = kwargs['halo_y']
            halo_z = kwargs['halo_z']
            halo_hostid = kwargs['halo_hostid']
            halo_id = kwargs['halo_id']
            b_to_a = kwargs['halo_b_to_a']
            c_to_a = kwargs['halo_c_to_a']
            halo_axisA_x = kwargs['halo_axisA_x']
            halo_axisA_y = kwargs['halo_axisA_y']
            halo_axisA_z = kwargs['halo_axisA_z']
            halo_axisC_x = kwargs['halo_axisC_x']
            halo_axisC_y = kwargs['halo_axisC_y']
            halo_axisC_z = kwargs['halo_axisC_z']
            concentration = kwargs['halo_nfw_conc']
            rvir = tabel['halo_rvir']
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox

        Npts = len(halo_x)

        # get host halo properties
        inds1, inds2 = crossmatch(halo_hostid, halo_id)

        # some sub-haloes point to a host that does not exist
        no_host = ~np.in1d(halo_hostid, halo_id)
        if np.sum(no_host) > 0:
            msg = ("There are {0} sub-haloes with no host halo.".format(
                np.sum(no_host)))
            warn(msg)

        host_halo_concentration = np.zeros(Npts)
        host_halo_concentration[inds1] = concentration[inds2]

        host_halo_rvir = np.zeros(Npts)
        host_halo_rvir[inds1] = rvir[inds2]

        host_b_to_a = np.zeros(Npts)
        host_b_to_a[inds1] = b_to_a[inds2]
        host_c_to_a = np.zeros(Npts)
        host_c_to_a[inds1] = c_to_a[inds2]

        major_axis = np.vstack((halo_axisA_x, halo_axisA_y, halo_axisA_z)).T
        minor_axis = np.vstack((halo_axisC_x, halo_axisC_y, halo_axisC_z)).T
        inter_axis = np.cross(major_axis, minor_axis)

        host_major_axis = np.zeros((Npts, 3))
        host_inter_axis = np.zeros((Npts, 3))
        host_minor_axis = np.zeros((Npts, 3))
        host_major_axis[inds1] = major_axis[inds2]
        host_inter_axis[inds1] = inter_axis[inds2]
        host_minor_axis[inds1] = minor_axis[inds2]

        # host x,y,z-position
        halo_x[inds1] = halo_x[inds2]
        halo_y[inds1] = halo_y[inds2]
        halo_z[inds1] = halo_z[inds2]

        # host halo centric positions
        phi = np.random.uniform(0, 2 * np.pi, Npts)
        uran = np.random.rand(Npts) * 2 - 1

        cos_t = uran
        sin_t = np.sqrt((1. - cos_t * cos_t))

        b_to_a, c_to_a = self.anisotropy_bias_response(host_b_to_a,
                                                       host_c_to_a)

        c_to_b = c_to_a / b_to_a

        # temporarily use x-axis as the major axis
        x = 1.0 / c_to_a * sin_t * np.cos(phi)
        y = 1.0 / c_to_b * sin_t * np.sin(phi)
        z = cos_t

        x_correlated_axes = np.vstack((x, y, z)).T

        x_axes = np.tile((1, 0, 0), Npts).reshape((Npts, 3))

        matrices = rotation_matrices_from_basis(host_major_axis,
                                                host_inter_axis,
                                                host_minor_axis)

        # rotate x-axis into the major axis
        #angles = angles_between_list_of_vectors(x_axes, major_axes)
        #rotation_axes = vectors_normal_to_planes(x_axes, major_axes)
        #matrices = rotation_matrices_from_angles(angles, rotation_axes)

        correlated_axes = rotate_vector_collection(matrices, x_correlated_axes)

        x, y, z = correlated_axes[:, 0], correlated_axes[:,
                                                         1], correlated_axes[:,
                                                                             2]

        nfw = NFWPhaseSpace(conc_mass_model='direct_from_halo_catalog', )
        dimensionless_radial_distance = nfw._mc_dimensionless_radial_distance(
            host_halo_concentration)

        x *= dimensionless_radial_distance
        y *= dimensionless_radial_distance
        z *= dimensionless_radial_distance

        x *= host_halo_rvir
        y *= host_halo_rvir
        z *= host_halo_rvir

        a = 1
        b = b_to_a * a
        c = c_to_a * a
        T = (c**2 - b**2) / (c**2 - a**2)
        q = b / a
        s = c / a

        x *= np.sqrt(q * s)
        y *= np.sqrt(q * s)
        z *= np.sqrt(q * s)

        # host-halo centric radial distance
        r = np.sqrt(x * x + y * y + z * z)

        # move back into original cordinate system
        xx = halo_x + x
        yy = halo_y + y
        zz = halo_z + z

        xx[no_host] = halo_x[no_host]
        yy[no_host] = halo_y[no_host]
        zz[no_host] = halo_z[no_host]

        # account for PBCs
        xx, yy, zz = wrap_coordinates(xx, yy, zz, Lbox)

        if 'table' in kwargs.keys():
            # assign satellite galaxy positions
            try:
                mask = (table['gal_type'] == 'satellites')
            except KeyError:
                mask = np.array([True] * len(table))
                msg = (
                    "`gal_type` not indicated in `table`.",
                    "The orientation is being assigned for all galaxies in the `table`."
                )
                print(msg)

            table['x'] = halo_x * 1.0
            table['y'] = halo_y * 1.0
            table['z'] = halo_z * 1.0

            table['x'][mask] = xx[mask]
            table['y'][mask] = yy[mask]
            table['z'][mask] = zz[mask]

            table['r'] = 0.0
            table['r'][mask] = r[mask]

            table['halo_x'][mask] = halo_x[mask]
            table['halo_y'][mask] = halo_y[mask]
            table['halo_z'][mask] = halo_z[mask]

            return table
        else:
            x = xx
            y = yy
            z = zz
            return np.vstack((x, y, z)).T
    def assign_positions(self, **kwargs):
        """
        assign satellite positions based on subhalo radial positions and random angular positions.
        """

        if 'table' in kwargs.keys():
            table = kwargs['table']
            halo_x = table['halo_x']
            halo_y = table['halo_y']
            halo_z = table['halo_z']
            halo_axisA_x = table['halo_axisA_x']
            halo_axisA_y = table['halo_axisA_y']
            halo_axisA_z = table['halo_axisA_z']
            halo_hostid = table['halo_hostid']
            halo_id = table['halo_id']
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox
        else:
            halo_x = kwargs['halo_x']
            halo_y = kwargs['halo_y']
            halo_z = kwargs['halo_z']
            halo_hostid = kwargs['halo_hostid']
            halo_id = kwargs['halo_id']
            try:
                Lbox = kwargs['Lbox']
            except KeyError:
                Lbox = self._Lbox

        # get subhalo positions
        x = halo_x * 1.0
        y = halo_y * 1.0
        z = halo_z * 1.0

        # get host halo positions
        inds1, inds2 = crossmatch(halo_hostid, halo_id)
        # x-position
        halo_x[inds1] = halo_x[inds2]
        # y-position
        halo_y[inds1] = halo_y[inds2]
        # z-position
        halo_z[inds1] = halo_z[inds2]

        # get host halo orientation
        host_halo_axisA_x = halo_axisA_x
        host_halo_axisA_x[inds1] = halo_axisA_x[inds2]
        host_halo_axisA_y = halo_axisA_y
        host_halo_axisA_y[inds1] = halo_axisA_y[inds2]
        host_halo_axisA_z = halo_axisA_z
        host_halo_axisA_z[inds1] = halo_axisA_z[inds2]
        host_halo_mjor_axes = np.vstack(
            (halo_axisA_x, halo_axisA_y, halo_axisA_z)).T

        # calculate radial positions
        vec_r, r = radial_distance(x, y, z, halo_x, halo_y, halo_z, Lbox)

        # rotate radial vectors arond halo major axis
        N = len(x)
        rot_angles = np.random.uniform(0.0, 2 * np.pi, N)
        rot_axes = host_halo_mjor_axes
        rot_m = rotation_matrices_from_angles(rot_angles, rot_axes)

        new_vec_r = rotate_vector_collection(rot_m, vec_r)
        xx = new_vec_r[:, 0]
        yy = new_vec_r[:, 1]
        zz = new_vec_r[:, 2]

        # move back into original cordinate system
        xx = halo_x + xx
        yy = halo_y + yy
        zz = halo_z + zz

        # account for PBCs
        mask = (xx < 0.0)
        xx[mask] = xx[mask] + Lbox[0]
        mask = (xx > Lbox[0])
        xx[mask] = xx[mask] - Lbox[0]
        mask = (yy < 0.0)
        yy[mask] = yy[mask] + Lbox[1]
        mask = (yy > Lbox[1])
        yy[mask] = yy[mask] - Lbox[1]
        mask = (zz < 0.0)
        zz[mask] = zz[mask] + Lbox[2]
        mask = (zz > Lbox[2])
        zz[mask] = zz[mask] - Lbox[2]

        if 'table' in kwargs.keys():
            # assign satellite galaxy positions
            try:
                mask = (table['gal_type'] == 'satellites')
            except KeyError:
                mask = np.array([True] * len(table))
                msg = (
                    "`gal_type` not indicated in `table`.",
                    "The orientation is being assigned for all galaxies in the `table`."
                )
                print(msg)

            table['x'] = halo_x * 1.0
            table['y'] = halo_y * 1.0
            table['z'] = halo_z * 1.0

            table['x'][mask] = xx[mask]
            table['y'][mask] = yy[mask]
            table['z'][mask] = zz[mask]

            table['halo_x'][mask] = halo_x[mask]
            table['halo_y'][mask] = halo_y[mask]
            table['halo_z'][mask] = halo_z[mask]

            return table
        else:
            x = xx
            y = yy
            z = zz
            return np.vstack((x, y, z)).T
    def assign_positions(self, **kwargs):
        """
        assign satellite positions based on subhalo radial positions and random angular positions.
    	"""

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

        # get subhalo positions
        x = halo_x * 1.0
        y = halo_y * 1.0
        z = halo_z * 1.0

        # get host halo positions
        inds1, inds2 = crossmatch(halo_hostid, halo_id)
        # x-position
        halo_x[inds1] = halo_x[inds2]
        # y-position
        halo_y[inds1] = halo_y[inds2]
        # z-position
        halo_z[inds1] = halo_z[inds2]

        # calculate radial positions
        vec_r, r = radial_distance(x, y, z, halo_x, halo_y, halo_z, Lbox)

        # calculate new positions with same radial distance
        # in the coordinatre systems centered on host haloes
        npts = len(x)
        uran = np.random.uniform(0, 1, npts)
        theta = np.arccos(uran * 2.0 - 1.0)
        phi = np.random.uniform(0, 2 * np.pi, npts)
        xx = r * np.sin(theta) * np.cos(phi)
        yy = r * np.sin(theta) * np.sin(phi)
        zz = r * np.cos(theta)

        # move back into original cordinate system
        xx = halo_x + xx
        yy = halo_y + yy
        zz = halo_z + zz

        # account for PBCs
        mask = (xx < 0.0)
        xx[mask] = xx[mask] + Lbox[0]
        mask = (xx > Lbox[0])
        xx[mask] = xx[mask] - Lbox[0]
        mask = (yy < 0.0)
        yy[mask] = yy[mask] + Lbox[1]
        mask = (yy > Lbox[1])
        yy[mask] = yy[mask] - Lbox[1]
        mask = (zz < 0.0)
        zz[mask] = zz[mask] + Lbox[2]
        mask = (zz > Lbox[2])
        zz[mask] = zz[mask] - Lbox[2]

        if 'table' in kwargs.keys():
            # assign satellite galaxy positions
            try:
                mask = (table['gal_type'] == 'satellites')
            except KeyError:
                mask = np.array([True] * len(table))
                msg = (
                    "`gal_type` not indicated in `table`.",
                    "The orientation is being assigned for all galaxies in the `table`."
                )
                print(msg)

            table['x'] = halo_x * 1.0
            table['y'] = halo_y * 1.0
            table['z'] = halo_z * 1.0

            table['x'][mask] = xx[mask]
            table['y'][mask] = yy[mask]
            table['z'][mask] = zz[mask]

            table['halo_x'][mask] = halo_x[mask]
            table['halo_y'][mask] = halo_y[mask]
            table['halo_z'][mask] = halo_z[mask]

            return table
        else:
            x = xx
            y = yy
            z = zz
            return np.vstack((x, y, z)).T
def load_umachine_z0(fname=FNAME, ssfr_q_loc=-11.8, ssfr_q_scale=0.5, seed=43):
    """These data can be downloaded from """
    mock = Table(np.load(fname))

    cenmask = mock["upid"] == -1
    mock["hostid"] = mock["upid"]
    mock["hostid"][cenmask] = mock["id"][cenmask]

    mhost = np.copy(mock["mp"])
    idxA, idxB = crossmatch(mock["upid"][~cenmask], mock["id"])
    mhost_sats = mhost[~cenmask]
    mhost_sats[idxA] = mock["mp"][idxB]

    mhost[~cenmask] = mhost_sats
    mock["logmhost"] = np.log10(mhost)
    mask = mock["sm"] > 10**9.5
    mock = mock[mask]
    mock["logsm"] = np.log10(mock["sm"])
    mock["ssfr"] = mock["sfr"] / mock["sm"]
    mock.remove_column("sm")

    zeromask = mock["ssfr"] == 0
    nzero = np.count_nonzero(zeromask)
    rng = np.random.RandomState(seed)
    random_ssfr_quenched_gals = rng.normal(loc=ssfr_q_loc,
                                           scale=ssfr_q_scale,
                                           size=nzero)
    mock["ssfr"][zeromask] = 10**random_ssfr_quenched_gals
    mock["log_ssfr"] = np.log10(mock["ssfr"])
    mock.remove_column("ssfr")

    mock["x"] = np.mod(mock["pos"][:, 0], 250)
    mock["y"] = np.mod(mock["pos"][:, 1], 250)
    mock["z"] = np.mod(mock["pos"][:, 2], 250)
    cols_to_remove = [
        "flags",
        "uparent_dist",
        "pos",
        "vmp",
        "lvmp",
        "m",
        "descid",
        "v",
        "r",
        "rank1",
        "rank2",
        "ra",
        "rarank",
        "A_UV",
        "icl",
        "obs_sm",
        "obs_sfr",
        "obs_uv",
        "empty",
    ]
    for col in cols_to_remove:
        mock.remove_column(col)
    mock["logmpeak"] = np.log10(mock["mp"])
    mock.remove_column("mp")

    mock["neg_logmhost"] = -mock["logmhost"]
    mock.sort(("neg_logmhost", "hostid", "upid", "logmpeak"))
    mock.remove_column("neg_logmhost")

    return mock
Exemple #19
0
def halocat_to_galaxy_table(halocat):
    """
    transform a Halotools halocat.halo_table into a
    test galaxy_table object, used for testing model componenets

    Returns
    -------
    galaxy_table : astropy.table object
    """

    halo_id = halocat.halo_table['halo_id']
    halo_upid = halocat.halo_table['halo_upid']
    host_id = halocat.halo_table['halo_hostid']

    # create galaxy table
    table = Table([halo_id, halo_upid, host_id], names=('halo_id', 'halo_upid', 'halo_hostid'))

    # add position information
    table['x'] = halocat.halo_table['halo_x']
    table['y'] = halocat.halo_table['halo_y']
    table['z'] = halocat.halo_table['halo_z']
    table['vx'] = halocat.halo_table['halo_vx']
    table['vy'] = halocat.halo_table['halo_vy']
    table['vz'] = halocat.halo_table['halo_vz']

    # add halo mass
    table['halo_mpeak'] = halocat.halo_table['halo_mpeak']

    # add orientation information
    # place holders for now
    table['galaxy_axisA_x'] = 0.0
    table['galaxy_axisA_y'] = 0.0
    table['galaxy_axisA_z'] = 0.0

    table['galaxy_axisB_x'] = 0.0
    table['galaxy_axisB_y'] = 0.0
    table['galaxy_axisB_z'] = 0.0

    table['galaxy_axisC_x'] = 0.0
    table['galaxy_axisC_y'] = 0.0
    table['galaxy_axisC_z'] = 0.0

    # tag centrals vs satellites
    hosts = (halocat.halo_table['halo_upid'] == -1)
    subs = (halocat.halo_table['halo_upid'] != -1)
    table['gal_type'] = 'satellites'
    table['gal_type'][hosts] = 'centrals'
    table['gal_type'][subs] = 'satellites'

    # host halo properties
    inds1, inds2 = crossmatch(halocat.halo_table['halo_hostid'], halocat.halo_table['halo_id'])

    # host halo position
    table['halo_x'] = 0.0
    table['halo_x'][inds1] = halocat.halo_table['halo_x'][inds2]
    table['halo_y'] = 0.0
    table['halo_y'][inds1] = halocat.halo_table['halo_y'][inds2]
    table['halo_z'] = 0.0
    table['halo_z'][inds1] = halocat.halo_table['halo_z'][inds2]

    # host haloo mass
    table['halo_mvir'] = 0.0
    table['halo_mvir'][inds1] = halocat.halo_table['halo_mvir'][inds2]
    table['halo_rvir'] = 0.0
    table['halo_rvir'][inds1] = halocat.halo_table['halo_rvir'][inds2]

    # assign orientations
    #table['halo_axisA_x'] = 0.0
    #table['halo_axisA_x'][inds1] = halocat.halo_table['halo_axisA_x'][inds2]
    #table['halo_axisA_y'] = 0.0
    #table['halo_axisA_y'][inds1] = halocat.halo_table['halo_axisA_y'][inds2]
    #table['halo_axisA_z'] = 0.0
    #table['halo_axisA_z'][inds1] = halocat.halo_table['halo_axisA_z'][inds2]

    table['halo_axisA_x'] = halocat.halo_table['halo_axisA_x']
    table['halo_axisA_y'] = halocat.halo_table['halo_axisA_y']
    table['halo_axisA_z'] = halocat.halo_table['halo_axisA_z']

    return table
def load_orphan_subhalos():
    """
    """
    dirname = "/Users/aphearin/work/sims/bolplanck/orphan_catalog_z0"
    basename = "cross_matched_orphan_catalog.hdf5"

    halo_table = Table.read(os.path.join(dirname, basename), path='data')

    Lbox = 250.
    halo_table['x'] = enforce_periodicity_of_box(halo_table['x'], Lbox)
    halo_table['y'] = enforce_periodicity_of_box(halo_table['y'], Lbox)
    halo_table['z'] = enforce_periodicity_of_box(halo_table['z'], Lbox)

    halo_table['vmax_at_mpeak_percentile'] = np.load(
        os.path.join(dirname, 'vmax_percentile.npy'))
    halo_table['noisy_vmax_at_mpeak_percentile'] = noisy_percentile(
        halo_table['vmax_at_mpeak_percentile'], 0.5)

    halo_table['orphan_mass_loss_percentile'] = -1.
    halo_table['orphan_mass_loss_percentile'][halo_table['orphan']] = np.load(
            os.path.join(dirname, 'orphan_mass_loss_percentile.npy'))
    halo_table['orphan_vmax_at_mpeak_percentile'] = -1.
    halo_table['orphan_vmax_at_mpeak_percentile'][halo_table['orphan']] = np.load(
            os.path.join(dirname, 'orphan_vmax_at_mpeak_percentile.npy'))
    halo_table['orphan_vmax_loss_percentile'] = -1.
    halo_table['orphan_vmax_loss_percentile'][halo_table['orphan']] = np.load(
            os.path.join(dirname, 'orphan_vmax_loss_percentile.npy'))

    halo_table['orphan_fixed_mpeak_mhost_percentile'] = -1.
    halo_table['orphan_fixed_mpeak_mhost_percentile'][halo_table['orphan']] = np.load(
            os.path.join(dirname, 'orphan_fixed_mpeak_mhost_percentile.npy'))

    halo_table['zpeak'] = 1./halo_table['mpeak_scale']-1.

    halo_table['zpeak_no_splashback'] = 0.
    satmask = halo_table['upid'] != -1
    halo_table['zpeak_no_splashback'][satmask] = halo_table['zpeak'][satmask]

    rvir_peak_physical_unity_h = halo_mass_to_halo_radius(halo_table['mpeak'],
                                Planck15, halo_table['zpeak'], 'vir')
    rvir_peak_physical = rvir_peak_physical_unity_h/Planck15.h
    halo_table['rvir_zpeak'] = rvir_peak_physical*1000.

    rvir_peak_no_spl_physical_unity_h = halo_mass_to_halo_radius(halo_table['mpeak'],
                                Planck15, halo_table['zpeak_no_splashback'], 'vir')
    rvir_peak_no_spl_physical = rvir_peak_no_spl_physical_unity_h/Planck15.h
    halo_table['rvir_zpeak_no_splashback'] = rvir_peak_no_spl_physical*1000.

    halo_table['hostid'] = np.nan
    hostmask = halo_table['upid'] == -1
    halo_table['hostid'][hostmask] = halo_table['halo_id'][hostmask]
    halo_table['hostid'][~hostmask] = halo_table['upid'][~hostmask]

    idxA, idxB = crossmatch(halo_table['hostid'], halo_table['halo_id'])
    halo_table['host_mvir'] = np.nan
    halo_table['host_mvir'][idxA] = halo_table['mvir'][idxB]

    halo_table = halo_table[~np.isnan(halo_table['host_mvir'])]

    halo_table['frac_mpeak_remaining'] = halo_table['mvir']/halo_table['mpeak']
    halo_table['frac_vpeak_remaining'] = halo_table['vmax']/halo_table['vmax_at_mpeak']

    return halo_table
def build_output_snapshot_mock(umachine,
                               target_halos,
                               halo_indices,
                               galaxy_indices,
                               Lbox_target=256.):
    """
    """
    dc2 = Table()
    dc2['source_halo_id'] = umachine['hostid'][galaxy_indices]
    dc2['target_halo_id'] = np.repeat(
        target_halos['fof_halo_tag'][halo_indices],
        target_halos['richness'][halo_indices])

    idxA, idxB = crossmatch(dc2['target_halo_id'],
                            target_halos['fof_halo_tag'])

    msg = "target IDs do not match!"
    assert np.all(dc2['source_halo_id'][idxA] == target_halos['source_halo_id']
                  [idxB]), msg

    dc2['target_halo_x'] = 0.
    dc2['target_halo_y'] = 0.
    dc2['target_halo_z'] = 0.
    dc2['target_halo_vx'] = 0.
    dc2['target_halo_vy'] = 0.
    dc2['target_halo_vz'] = 0.

    dc2['target_halo_x'][idxA] = target_halos['fof_halo_center_x'][idxB]
    dc2['target_halo_y'][idxA] = target_halos['fof_halo_center_y'][idxB]
    dc2['target_halo_z'][idxA] = target_halos['fof_halo_center_z'][idxB]

    dc2['target_halo_vx'][idxA] = target_halos['fof_halo_mean_vx'][idxB]
    dc2['target_halo_vy'][idxA] = target_halos['fof_halo_mean_vy'][idxB]
    dc2['target_halo_vz'][idxA] = target_halos['fof_halo_mean_vz'][idxB]

    dc2['target_halo_mass'] = 0.
    dc2['target_halo_mass'][idxA] = target_halos['fof_halo_mass'][idxB]

    source_galaxy_keys = ('host_halo_mvir', 'upid', 'host_centric_x',
                          'host_centric_y', 'host_centric_z',
                          'host_centric_vx', 'host_centric_vy',
                          'host_centric_vz', 'obs_sm', 'obs_sfr',
                          'sfr_percentile_fixed_sm', 'rmag',
                          'sdss_petrosian_gr', 'sdss_petrosian_ri', 'size_kpc')
    for key in source_galaxy_keys:
        dc2[key] = umachine[key][galaxy_indices]

    x_init = dc2['target_halo_x'] + dc2['host_centric_x']
    vx_init = dc2['target_halo_vx'] + dc2['host_centric_vx']
    dc2['x'], dc2['vx'] = enforce_periodicity_of_box(x_init,
                                                     Lbox_target,
                                                     velocity=vx_init)

    y_init = dc2['target_halo_y'] + dc2['host_centric_y']
    vy_init = dc2['target_halo_vy'] + dc2['host_centric_vy']
    dc2['y'], dc2['vy'] = enforce_periodicity_of_box(y_init,
                                                     Lbox_target,
                                                     velocity=vy_init)

    z_init = dc2['target_halo_z'] + dc2['host_centric_z']
    vz_init = dc2['target_halo_vz'] + dc2['host_centric_vz']
    dc2['z'], dc2['vz'] = enforce_periodicity_of_box(z_init,
                                                     Lbox_target,
                                                     velocity=vz_init)
    return dc2
Exemple #22
0
def load_value_added_halocat(simname='bolplanck', redshift=0.0, version_name='halotools_v0p4'):
    """
    adds properties to halotools rockstar halo catalogs

    Returns
    -------
    halocat : Halotools halocat object
    """
    halocat = CachedHaloCatalog(simname=simname, halo_finder='rockstar',
                                redshift=redshift, version_name=version_name)
    halos = halocat.halo_table

    inds1, inds2 = crossmatch(halos['halo_hostid'], halos['halo_id'])
    x = halos['halo_x']
    y = halos['halo_x']
    z = halos['halo_z']
    host_x = np.copy(x)
    host_y = np.copy(y)
    host_z = np.copy(z)
    host_x[inds1] = halos['halo_x'][inds2]
    host_y[inds1] = halos['halo_y'][inds2]
    host_z[inds1] = halos['halo_z'][inds2]

    dx = relative_positions_and_velocities(x, host_x, period=halocat.Lbox[0])
    dy = relative_positions_and_velocities(y, host_y, period=halocat.Lbox[1])
    dz = relative_positions_and_velocities(z, host_z, period=halocat.Lbox[2])
    radius = np.sqrt(dx**2+dy**2+dz**2)
    r = normalized_vectors(np.vstack((dx, dy, dz)).T)
    r = np.nan_to_num(r)

    halos['halo_centric_distance'] = radius
    halos['halo_radial_unit_vector'] = r

    # calculate scaled radial distance (r/r_vir)
    scaled_radius = np.zeros(len(halos))
    # ignore divide by zero in this case
    scaled_radius[inds1] = np.divide(radius[inds1], halos['halo_rvir'][inds2],
                                     out=np.zeros_like(radius[inds1]),
                                     where=halos['halo_rvir'][inds2] != 0)
    halos['halo_r_by_rvir'] = radius

    #define major axis of (sub-)haloes
    halos['halo_major_axis'] = normalized_vectors(np.vstack((halos['halo_axisA_x'],
                                                             halos['halo_axisA_y'],
                                                             halos['halo_axisA_z'])).T)

    #define spin axis of (sub-)haloes
    halos['halo_spin_axis'] = normalized_vectors(np.vstack((halos['halo_jx'],
                                                            halos['halo_jy'],
                                                            halos['halo_jz'])).T)

    # define host orientation vectors for each (sub-)halo
    # major axis
    halos['halo_host_major_axis'] = np.copy(halos['halo_major_axis'])
    halos['halo_host_major_axis'][inds1] = halos['halo_major_axis'][inds2]

    # spin axis
    halos['halo_host_spin_axis'] = np.copy(halos['halo_spin_axis'])
    halos['halo_host_spin_axis'][inds1] = halos['halo_spin_axis'][inds2]

    # major axis
    #theta_ma_1 = angles_between_list_of_vectors(halos['halo_radial_unit_vector'], halos['halo_major_axis'])
    #theta_ma_2 = angles_between_list_of_vectors(halos['halo_host_major_axis'], halos['halo_major_axis'])

    # spin axis
    #theta_ma_3 = angles_between_list_of_vectors(halos['halo_radial_unit_vector'], halos['halo_spin_axis'])
    #theta_ma_4 = angles_between_list_of_vectors(halos['halo_host_spin_axis'], halos['halo_spin_axis'])

    halocat.halo_table = halos

    return halocat
Exemple #23
0
def test_many_galaxies_per_source_halo():
    """ Test case of mutliple source galaxies per source halo
    """
    #  Set up a source halo catalog with 100 halos in each mass bin
    log_mhost_min, log_mhost_max, dlog_mhost = 10.5, 15.5, 0.5
    log_mhost_bins = np.arange(log_mhost_min, log_mhost_max + dlog_mhost,
                               dlog_mhost)
    log_mhost_mids = 0.5 * (log_mhost_bins[:-1] + log_mhost_bins[1:])
    num_distinct_source_halo_masses = len(log_mhost_mids)

    num_source_halos_per_bin = 20
    source_halo_log_mhost = np.tile(log_mhost_mids, num_source_halos_per_bin)
    num_source_halos = len(source_halo_log_mhost)
    source_halo_id = np.arange(num_source_halos).astype(int)
    source_halo_bin_number = halo_bin_indices(log_mhost=(source_halo_log_mhost,
                                                         log_mhost_bins))
    assert len(
        source_halo_bin_number
    ) == num_distinct_source_halo_masses * num_source_halos_per_bin, "Bad setup of source_halos"

    ngals_per_source_halo = 3
    num_source_galaxies = num_source_halos * ngals_per_source_halo
    source_galaxy_host_halo_id = np.repeat(source_halo_id,
                                           ngals_per_source_halo)
    source_galaxy_host_mass = np.repeat(source_halo_log_mhost,
                                        ngals_per_source_halo)
    assert len(source_galaxy_host_mass
               ) == num_source_galaxies, "Bad setup of source_galaxies"

    num_target_halos_per_source_halo = 11
    target_halo_log_mhost = np.repeat(source_halo_log_mhost,
                                      num_target_halos_per_source_halo)
    target_halo_bin_number = halo_bin_indices(log_mhost=(target_halo_log_mhost,
                                                         log_mhost_bins))
    num_target_halos = len(target_halo_bin_number)
    target_halo_ids = np.arange(num_target_halos).astype('i8')

    nhalo_min = 5
    _result = source_galaxy_selection_indices(
        source_galaxy_host_halo_id, source_halo_bin_number, source_halo_id,
        target_halo_bin_number, target_halo_ids, nhalo_min, log_mhost_bins)
    selection_indices, target_galaxy_target_halo_ids, target_galaxy_source_halo_ids = _result

    correct_num_target_galaxies = int(num_target_halos * ngals_per_source_halo)
    assert correct_num_target_galaxies == len(
        target_galaxy_target_halo_ids) == len(selection_indices)

    idxA, idxB = crossmatch(target_galaxy_target_halo_ids, target_halo_ids)
    assert len(idxA) == len(target_galaxy_target_halo_ids)
    target_halo_bins = target_halo_bin_number[idxB]
    A = num_target_halos_per_source_halo * ngals_per_source_halo
    assert np.all(
        np.histogram(target_halo_bins)[0] == A *
        np.histogram(source_halo_bin_number)[0])

    selected_galaxies_target_halo_mass = target_halo_log_mhost[idxB]
    a = halo_bin_indices(log_mhost=(selected_galaxies_target_halo_mass,
                                    log_mhost_bins))
    b = halo_bin_indices(log_mhost=(source_galaxy_host_mass, log_mhost_bins))
    assert np.all(
        np.histogram(a)[0] == num_target_halos_per_source_halo *
        np.histogram(b)[0])

    selected_galaxies_source_halo_mass = source_galaxy_host_mass[
        selection_indices]
    assert np.allclose(selected_galaxies_source_halo_mass,
                       selected_galaxies_target_halo_mass)

    gen = zip(selected_galaxies_source_halo_mass,
              target_galaxy_target_halo_ids, target_galaxy_source_halo_ids)
    for galmass, target_id, source_id in gen:
        source_mask = source_halo_id == source_id
        target_mask = target_halo_ids == target_id
        source_halo_mass = source_halo_log_mhost[source_mask][0]
        target_halo_mass = target_halo_log_mhost[target_mask][0]
        assert source_halo_mass == target_halo_mass == galmass