Tutorial on the algorithm for subhalo-based mock-making¶
This section of the documentation provides detailed notes
for how the SubhaloMockFactory
populates subhalo catalogs with synthetic galaxy populations.
The SubhaloMockFactory
uses composite models built with the SubhaloModelFactory
, which
is documented in the Source code notes on SubhaloModelFactory.
Outline¶
We will start in Basic syntax for making subhalo-based mocks with a high-level overview of the functionality
of the SubhaloMockFactory
class. We provide detailed
notes on the source code of the mock factory in Algorithm for populating subhalo-based mocks.
Basic syntax for making subhalo-based mocks¶
The most common way to interact with
instances of the SubhaloMockFactory
is as an attribute of the composite model you
are using to generate the mock. For example, the code snippet below shows how
the populate_mock
method creates a mock
object to
the composite model, which in this case will be a model based on the
Behroozi et al. (2010) parameterized abundance matching model:
from halotools.empirical_models import PrebuiltSubhaloModelFactory
behroozi10_model = PrebuiltSubhaloModelFactory('behroozi10')
from halotools.sim_manager import CachedHaloCatalog
default_halocat = CachedHaloCatalog()
behroozi10_model.populate_mock(default_halocat)
The final line of code above creates the behroozi10_model.mock
attribute,
an instance of SubhaloMockFactory
.
The SubhaloMockFactory
is responsible for one task: using a Halotools composite model
to populate a simulation with mock galaxies.
When the SubhaloModelFactory.populate_mock
method first creates a model.mock
instance,
the instantiation of SubhaloMockFactory
triggers the pre-processing phase of mock population.
Briefly, this phase does as many tasks in advance of actual mock population as possible
to improve the efficiency of MCMCs (see below for details).
By default, instantiating the mock factory also triggers
the SubhaloMockFactory.populate
method to be called. This is the method that actually creates
the galaxy population. By calling the SubhaloMockFactory.populate
method,
a new galaxy_table
attribute is created and bound to the model.mock
instance.
The galaxy_table
attribute stores an Astropy Table
object with one row
per mock galaxy and one column for every property assigned by the chosen composite model.
Algorithm for populating subhalo-based mocks¶
Pre-processing phase¶
In the preprocess_halo_catalog
, new columns are added to the halo_table
according to any entries in the new_haloprop_func_dict
; any such columns will automatically be included
in the galaxy_table
. See The new_haloprop_func_dict mechanism for further details.
The pre-processing phase concludes with the call to the precompute_galprops
method,
which is the first function that adds columns to the galaxy_table
. For SubhaloModelFactory
composite
models, the spatial positions and velocities of mock galaxies exactly coincide with those of (sub)halos,
and so the x, y, z, vx, vy, vz columns can all be added to the galaxy_table
in advance.
Mock-population phase¶
After pre-processing, the galaxy_table
has been prepared for the assignment of properties that
are computed dynamically, e.g., stellar mass and star formation rate. This phase is controlled by
the populate
method. Because the high-level bookkeeping has already been handled
by the SubhaloModelFactory
class, the source for this phase is quite compact and straightforward.
First, empty columns are added to the galaxy_table
with by the _allocate_memory
method. We do this by looping over every property
in _galprop_dtypes_to_allocate
that has not already been assigned:
Ngals = len(self.galaxy_table)
new_column_generator = (key for key in self.model._galprop_dtypes_to_allocate.names
if key not in self._precomputed_galprop_list)
for key in new_column_generator:
dt = self.model._galprop_dtypes_to_allocate[key]
self.galaxy_table[key] = np.empty(Ngals, dtype = dt)
See The galprop_dtypes_to_allocate mechanism for details about this bookkeeping device.
Once memory has been allocated to the galaxy_table
,
we successively pass this table to each of the functions in the _mock_generation_calling_sequence
:
for method in self.model._mock_generation_calling_sequence:
func = getattr(self.model, method)
func(table = self.galaxy_table)
See The model_feature_calling_sequence mechanism for details. Note how the use of getattr
allows the SubhaloMockFactory
to call the appropriate method without knowing its name. This
high-level feature of python is what allows the factory work with any arbitrary set of component models.