Source code for halotools.sim_manager.fake_sim

"""
Module storing the `~halotools.sim_manager.FakeSim` class
used to generate fake simulation data on-the-fly.
Primary use is to test the `~halotools.empirical_models` modules,
particularly with doctests.
"""
import numpy as np
from astropy.utils.misc import NumpyRNGContext

from .user_supplied_halo_catalog import UserSuppliedHaloCatalog
from .user_supplied_ptcl_catalog import UserSuppliedPtclCatalog
from .sim_defaults import default_cosmology

from ..utils import crossmatch

__all__ = ('FakeSim', 'FakeSimHalosNearBoundaries')


[docs] class FakeSim(UserSuppliedHaloCatalog): """ Fake simulation data used in the test suite of `~halotools.empirical_models`. The `FakeSim` object has all the attributes required by Mock Factories such as `~halotools.empirical_models.HodMockFactory` to create a mock galaxy population. The columns of the `halo_table` and `ptcl_table` attributes of `FakeSim` are generated with ``np.random``. Thus mock catalogs built into `FakeSim` will not have physically realistic spatial distributions, mass functions, etc. All the same, `FakeSim` is quite useful for testing purposes, as it permits the testing of `~halotools.sim_manager` and `~halotools.empirical_models` to be completely decoupled. Default behavior is to use a fixed seed in the random number generation, so that an identical instance of `FakeSim` is created for calls with the same arguments. """ def __init__(self, num_massbins=10, num_halos_per_massbin=int(100), num_ptcl=int(2e4), seed=43, redshift=0., cosmology=default_cosmology, **kwargs): """ Parameters ---------- num_massbins : int, optional Number of distinct masses that will appear in the halo catalog. Default is 10. num_halos_per_massbin : int, optional Default is 100 num_ptcl : int, optional Number of dark matter particles. Default is 20000. seed : int, optional Random number seed used to generate the fake halos and particles. Default is 43. cosmology : `astropy.cosmology` instance, optional Default is `halotools.sim_manager.sim_defaults.default_cosmology`. Examples -------- >>> halocat = FakeSim() """ Lbox = 250.0 particle_mass = 1.e8 try: self.simname = kwargs['simname'] except KeyError: self.simname = 'fake' try: self.halo_finder = kwargs['halo_finder'] except KeyError: self.halo_finder = 'fake' try: self.version_name = kwargs['version_name'] except KeyError: self.version_name = 'dummy_version' self.redshift = redshift self.seed = seed self.num_massbins = num_massbins self.num_halos_per_massbin = num_halos_per_massbin self.num_halos = self.num_massbins*self.num_halos_per_massbin approx_num_ptcl = num_ptcl self.num_ptcl_per_dim = int(approx_num_ptcl**(1/3.)) self.num_ptcl = self.num_ptcl_per_dim**3 self.cosmology = cosmology halo_id = np.arange(1e5, 1e5+2*self.num_halos, dtype='i8') with NumpyRNGContext(self.seed): np.random.shuffle(halo_id) halo_id = halo_id[:self.num_halos] with NumpyRNGContext(self.seed): randomizer = np.random.random(self.num_halos) subhalo_fraction = 0.1 upid = np.where(randomizer > subhalo_fraction, -1, 1) host_mask = upid == -1 host_ids = halo_id[host_mask] with NumpyRNGContext(self.seed): upid[~host_mask] = np.random.choice(host_ids, len(upid[~host_mask])) halo_hostid = np.zeros(len(halo_id), dtype='i8') halo_hostid[host_mask] = halo_id[host_mask] halo_hostid[~host_mask] = upid[~host_mask] massbins = np.logspace(10, 16, self.num_massbins) mvir = np.repeat(massbins, self.num_halos_per_massbin, axis=0) mpeak = np.repeat(massbins, self.num_halos_per_massbin, axis=0) logrvirbins = (np.log10(massbins) - 15)/3. rvir = np.repeat(10.**logrvirbins, self.num_halos_per_massbin, axis=0) logvmaxbins = -4.25 + 0.5*(np.log10(massbins) - logrvirbins) vmax = np.repeat(10.**logvmaxbins, self.num_halos_per_massbin, axis=0) vpeak = vmax with NumpyRNGContext(self.seed): spin = np.random.random(self.num_halos) conc = np.random.uniform(4, 15, self.num_halos) rs = rvir/conc zhalf = np.random.uniform(0, 10, self.num_halos) dmdt = np.random.uniform(-1, 10, self.num_halos) x = np.random.uniform(0, Lbox, self.num_halos) y = np.random.uniform(0, Lbox, self.num_halos) z = np.random.uniform(0, Lbox, self.num_halos) vx = np.random.uniform(-500, 500, self.num_halos) vy = np.random.uniform(-500, 500, self.num_halos) vz = np.random.uniform(-500, 500, self.num_halos) px = np.random.uniform(0, Lbox, self.num_ptcl) py = np.random.uniform(0, Lbox, self.num_ptcl) pz = np.random.uniform(0, Lbox, self.num_ptcl) pvx = np.random.uniform(-1000, 1000, self.num_ptcl) pvy = np.random.uniform(-1000, 1000, self.num_ptcl) pvz = np.random.uniform(-1000, 1000, self.num_ptcl) idxA, idxB = crossmatch(halo_hostid, halo_id) halo_mvir_host_halo = np.copy(mvir) halo_mvir_host_halo[idxA] = mvir[idxB] ptclcat = UserSuppliedPtclCatalog( Lbox=Lbox, redshift=redshift, particle_mass=particle_mass, x=px, y=py, z=pz, vx=pvx, vy=pvy, vz=pvz) UserSuppliedHaloCatalog.__init__(self, Lbox=Lbox, particle_mass=particle_mass, redshift=redshift, halo_id=halo_id, halo_x=x, halo_y=y, halo_z=z, halo_vx=vx, halo_vy=vy, halo_vz=vz, halo_upid=upid, halo_hostid=halo_hostid, halo_mvir=mvir, halo_mpeak=mpeak, halo_m200b=mvir, halo_m180b=mvir, halo_rvir=rvir, halo_rs=rs, halo_zhalf=zhalf, halo_nfw_conc=conc, halo_vmax=vmax, halo_vpeak=vpeak, halo_spin=spin, halo_mass_accretion_rate=dmdt, halo_mvir_host_halo=halo_mvir_host_halo, user_supplied_ptclcat=ptclcat )
class FakeSimHalosNearBoundaries(UserSuppliedHaloCatalog): """ Fake simulation data used in the test suite of `~halotools.empirical_models`. The only difference between `FakeSim` and `FakeSimHalosNearBoundaries` is that all halos reside right near the very edge of the box. Useful for unit-testing the treatment of periodic boundary conditions. """ def __init__(self, num_massbins=6, num_halos_per_massbin=int(100), num_ptcl=int(1e4), seed=43, redshift=0., **kwargs): """ Parameters ---------- num_massbins : int, optional Number of distinct masses that will appear in the halo catalog. Default is 6. num_halos_per_massbin : int, optional Default is 1000 num_ptcl : int, optional Number of dark matter particles. Default is 1000. seed : int, optional Random number seed used to generate the fake halos and particles. Default is 43. Examples -------- >>> fakesim = FakeSimHalosNearBoundaries() """ Lbox = 250.0 particle_mass = 1.e8 self.simname = 'fake' self.halo_finder = 'fake' self.version_name = 'dummy_version' self.seed = seed self.num_massbins = num_massbins self.num_halos_per_massbin = num_halos_per_massbin self.num_halos = self.num_massbins*self.num_halos_per_massbin self.num_ptcl = num_ptcl halo_id = np.arange(1e9, 1e9+self.num_halos) with NumpyRNGContext(self.seed): randomizer = np.random.random(self.num_halos) subhalo_fraction = 0.1 upid = np.where(randomizer > subhalo_fraction, -1, 1) host_mask = upid == -1 halo_hostid = np.zeros(len(halo_id)) halo_hostid[host_mask] = halo_id[host_mask] halo_hostid[~host_mask] = upid[~host_mask] massbins = np.logspace(10, 15, self.num_massbins) mvir = np.repeat(massbins, self.num_halos_per_massbin, axis=0) mpeak = np.repeat(massbins, self.num_halos_per_massbin, axis=0) logrvirbins = (np.log10(massbins) - 15)/3. rvir = np.repeat(10.**logrvirbins, self.num_halos_per_massbin, axis=0) logvmaxbins = -4.25 + 0.5*(np.log10(massbins) - logrvirbins) vmax = np.repeat(10.**logvmaxbins, self.num_halos_per_massbin, axis=0) vpeak = vmax with NumpyRNGContext(self.seed): conc = np.random.uniform(4, 15, self.num_halos) rs = rvir/conc zhalf = np.random.uniform(0, 10, self.num_halos) x = np.zeros(self.num_halos) y = np.zeros(self.num_halos) z = np.zeros(self.num_halos) middle_index = int(self.num_halos/2.) with NumpyRNGContext(self.seed): x[:middle_index] = np.random.uniform(0, 0.001, len(x[:middle_index])) x[middle_index:] = np.random.uniform(Lbox-0.001, Lbox, len(x[middle_index:])) y[:middle_index] = np.random.uniform(0, 0.001, len(y[:middle_index])) y[middle_index:] = np.random.uniform(Lbox-0.001, Lbox, len(y[middle_index:])) z[:middle_index] = np.random.uniform(0, 0.001, len(z[:middle_index])) z[middle_index:] = np.random.uniform(Lbox-0.001, Lbox, len(z[middle_index:])) vx = np.random.uniform(-500, 500, self.num_halos) vy = np.random.uniform(-500, 500, self.num_halos) vz = np.random.uniform(-500, 500, self.num_halos) px = np.random.uniform(0, Lbox, self.num_ptcl) py = np.random.uniform(0, Lbox, self.num_ptcl) pz = np.random.uniform(0, Lbox, self.num_ptcl) pvx = np.random.uniform(-1000, 1000, self.num_ptcl) pvy = np.random.uniform(-1000, 1000, self.num_ptcl) pvz = np.random.uniform(-1000, 1000, self.num_ptcl) ptclcat = UserSuppliedPtclCatalog( Lbox=Lbox, redshift=redshift, particle_mass=particle_mass, x=px, y=py, z=pz, vx=pvx, vy=pvy, vz=pvz) UserSuppliedHaloCatalog.__init__(self, Lbox=Lbox, particle_mass=particle_mass, redshift=redshift, halo_id=halo_id, halo_x=x, halo_y=y, halo_z=z, halo_vx=vx, halo_vy=vy, halo_vz=vz, halo_upid=upid, halo_hostid=halo_hostid, halo_mvir=mvir, halo_mpeak=mpeak, halo_rvir=rvir, halo_rs=rs, halo_zhalf=zhalf, halo_nfw_conc=conc, halo_vmax=vmax, halo_vpeak=vpeak, user_supplied_ptclcat=ptclcat )