Source code for hmf.helpers.sample
"""
Module for dealing with sampled mass functions.
Provides routines for sampling theoretical functions, and for binning sampled data.
"""
import numpy as np
from scipy.interpolate import InterpolatedUnivariateSpline as Spline
from ..mass_function import hmf
def _prepare_mf(log_mmin, **mf_kwargs):
h = hmf.MassFunction(Mmin=log_mmin, **mf_kwargs)
mask = h.ngtm > 0
_icdf = np.log10(h.ngtm[mask] / h.ngtm[0])
icdf = Spline(_icdf[::-1], np.log10(h.m[mask][::-1]), k=3)
return icdf, h
def _choose_halo_masses_num(N, icdf, xmin=0, rng=None):
# Generate random variates from 0 to maxcum
if rng is None:
rng = np.random.default_rng()
x = rng.uniform(low=xmin, high=1.0, size=int(N))
logm = icdf(np.log10(x))
# Generate halo masses from mf distribution
return 10**logm
[docs]
def sample_mf(N, log_mmin, sort=False, rng=None, **mf_kwargs):
"""
Create a sample of halo masses from a theoretical mass function.
Parameters
----------
N : int
Number of samples to draw
log_mmin : float
Log10 of the minimum mass to sample [Msun/h]
sort : bool, optional
Whether to sort (in descending order of mass) the output masses.
mf_kwargs : keywords
Anything passed to :class:`hmf.MassFunction` to create the mass function
which is sampled.
Returns
-------
m : array_like
The masses
hmf : `hmf.MassFunction` instance
The instance used to define the mass function.
Examples
--------
Simplest example:
>>> m,hmf = sample_mf(1e5,11.0)
Or change the mass function:
>>> m,hmf = sample_mf(1e6,10.0,hmf_model="PS",Mmax=17)
"""
icdf, h = _prepare_mf(log_mmin, **mf_kwargs)
m = _choose_halo_masses_num(N, icdf, xmin=h.ngtm.min() / h.ngtm[0], rng=rng)
if sort:
m.sort()
return m[::-1], h
[docs]
def dndm_from_sample(m, V, nm=None, bins=50):
"""
Generate a binned dn/dm from a sample of halo masses.
Parameters
----------
m : array_like
A sample of masses
V : float
Physical volume of the sample
nm : array_like
A multiplicity of each of the masses -- useful for
samples from simulations in which the number of unique masses
is much smaller than the total sample.
bins : int or array
Specifies bins (in log10-space!) for the sample.
See `numpy.histogram` for more details.
Returns
-------
centres : array_like
The centres of the bins.
hist : array_like
The value of dn/dm in each bin.
Notes
-----
The "centres" of the bins are located as the midpoint in log10-space.
If one does not have the volume, it can be calculated as N/n(>mmin).
"""
hist, edges = np.histogram(np.log10(m), bins, weights=nm)
centres = (edges[1:] + edges[:-1]) / 2
dx = centres[1] - centres[0]
hist = hist.astype("float") / (10**centres * float(V) * dx * np.log(10))
if hist[0] == 0:
try:
hist0 = np.where(hist != 0)[0][0]
hist[hist0] = np.nan
except IndexError:
pass
if hist[-1] == 0:
try:
histN = np.where(hist != 0)[0][-1]
hist[histN] = np.nan
except IndexError:
pass
return centres, hist