synthesizer.particle.resample_utils¶
Shared utilities for particle spatial resampling.
Provides kernel-based position sampling from the SPH kernel, array tiling, velocity dispersion helpers, and higher-level engine functions used by both Gas.spatially_resample and Stars.spatially_resample.
Private helpers (_tile_array, _divide_and_tile) handle the low-level numpy mechanics. Public engine functions (resample_coordinates, resample_velocities, resample_smoothing_lengths, resample_by_mode, split_by_mask, validate_required_inputs) form the stable API consumed by the class methods.
Module attributes
Valid string mode names for |
Functions
- synthesizer.particle.resample_utils.add_velocity_dispersion(velocities, dispersion, seed=None)[source]¶
Add Gaussian random velocity dispersion to velocity arrays.
- Parameters:
velocities (np.ndarray or unyt_array) – (N_total, 3) array of velocities.
dispersion (float or unyt_quantity) – Standard deviation of the Gaussian noise.
seed (int, optional) – Random seed for reproducibility.
- Returns:
Velocities with added dispersion.
- Return type:
np.ndarray or unyt_array
- synthesizer.particle.resample_utils.resample_by_mode(arr, mode_spec, resample_factor, rng)[source]¶
Resample a per-particle array according to a named mode.
Applies one of five physically-motivated splitting strategies to arr:
"duplicated"Every child inherits the parent value unchanged. Use for intensive quantities (metallicity, optical depth, flags).
"proportional"The parent value is divided equally: each child gets
value / resample_factor. The total sum is exactly conserved. Use for extensive quantities (mass, dust mass)."normal"Each child is drawn from
Normal(value, σ)independently. By default σ is the population standard deviationnp.std(arr); passmode_spec = ("normal", sigma)to supply a fixed σ instead."lognormal"Like normal but in log-space: each child is drawn from
LogNormal(log(value), σ_log)so values remain positive. By default σ_log =np.std(np.log(arr)); pass("lognormal", sigma_log)to fix it."conserved_normal"Proportional split with additive Gaussian scatter, renormalised so children sum exactly to the parent value. Default σ =
np.std(arr) / resample_factor; pass("conserved_normal", sigma)to fix it.
- Parameters:
arr (np.ndarray or unyt_array) – Per-particle array of length N. Must not be
None; check before calling.mode_spec (str or tuple) – Either a mode name string or a
(mode_name, sigma)tuple.resample_factor (int) – Number of new particles per original.
rng (np.random.Generator) – A seeded
numpy.random.Generatorfor reproducibility.
- Returns:
Resampled array of length
N * resample_factor, with units preserved if arr carries them.- Return type:
np.ndarray or unyt_array
- Raises:
ValueError – If mode_spec is not a recognised mode name or tuple.
- synthesizer.particle.resample_utils.resample_coordinates(coordinates, smoothing_lengths, kernel, resample_factor, seed=None)[source]¶
Resample particle coordinates by adding kernel-sampled offsets.
Each original position is replaced by resample_factor new positions offset by vectors sampled from the SPH kernel.
Note:
@acceptsconverts coordinates and smoothing_lengths to Mpc before this function is called, sosmoothing_lengths.ndviewbelow is always in Mpc. The returned coordinates are therefore also in Mpc, matching the input unit.- Parameters:
coordinates (unyt_array, (N, 3)) – Original particle coordinates.
smoothing_lengths (unyt_array, (N,)) – Per-particle smoothing lengths.
kernel (Kernel) – SPH kernel for position sampling.
resample_factor (int) – Number of new particles per original particle.
seed (int, optional) – Random seed.
- Returns:
Resampled coordinates in the same units as coordinates.
- Return type:
unyt_array, (N * resample_factor, 3)
- synthesizer.particle.resample_utils.resample_smoothing_lengths(smoothing_lengths, resample_factor)[source]¶
Scale smoothing lengths for volume conservation and tile.
Each smoothing length is scaled by
resample_factor ** (-1/3)so that the total kernel volume is conserved across the resampled particles, then tiled resample_factor times. The returned smoothing lengths are thereforeresample_factor ** (1/3)times smaller than the originals with the same total volume.- Parameters:
smoothing_lengths (unyt_array, (N,)) – Original smoothing lengths.
resample_factor (int) – Number of new particles per original.
- Returns:
Resampled smoothing lengths.
- Return type:
unyt_array, (N * resample_factor,)
- synthesizer.particle.resample_utils.resample_velocities(velocities, resample_factor, velocity_dispersion=None, seed=None)[source]¶
Resample velocities: tile each velocity and optionally add dispersion.
- Parameters:
velocities (unyt_array, (N, 3), optional) – Original velocities. Returns
NoneifNoneis passed.resample_factor (int) – Number of new particles per original.
velocity_dispersion (float or unyt_quantity, optional) – Std. dev. of Gaussian velocity noise to add after tiling.
seed (int, optional) – Random seed for the dispersion noise.
- Returns:
Resampled velocities (
Noneif velocities isNone).- Return type:
unyt_array or None
- synthesizer.particle.resample_utils.sample_kernel_positions(kernel, smoothing_lengths, n_samples, seed=None)[source]¶
Sample 3D offsets from an SPH kernel for many particles.
For each particle with smoothing length h, n_samples 3D offsets are sampled from the kernel W(r) treated as a PDF. The radial part is sampled via inverse-CDF from p(q) ∝ 4π q² f(q) where q = r/h and f(q) is the dimensionless kernel. Angles are sampled uniformly on the sphere.
All operations are vectorised across particles × samples.
- Parameters:
kernel (Kernel) – A Kernel instance providing
kernel.ffor the dimensionless kernel function.smoothing_lengths (np.ndarray) – (N,) array of raw smoothing lengths (numeric values in whatever length unit the caller uses — units are not attached).
n_samples (int) – Number of samples per particle.
seed (int, optional) – Random seed for reproducibility.
- Returns:
(N, n_samples, 3) array of raw Cartesian offset vectors in the same units as smoothing_lengths.
- Return type:
np.ndarray
- synthesizer.particle.resample_utils.split_by_mask(mask, **arrays)[source]¶
Split arrays by a boolean mask, preserving input order.
Each array is either indexed by the mask (if it is a 1-D array matching the mask length), or left unchanged if it is a scalar,
None, or a shorter/longer array.Input order is preserved in the returned lists:
m, u = split_by_mask(mask, mass=..., met=..., sfr=...) # m[0] is masked mass, u[0] is unmasked mass, etc.
- Parameters:
mask (array-like) – Boolean mask.
**arrays – Named arrays, scalars, or
Noneto split.
- Returns:
(to_resample, no_resample)— two lists, each of the same length as the number of input arrays, in input order.- Return type:
tuple[list, list]
- synthesizer.particle.resample_utils.validate_mask(mask, nparticles)[source]¶
Validate a boolean mask array and convert to bool ndarray.
- Parameters:
mask (array-like) – Boolean mask of length nparticles.
nparticles (int) – Expected length.
- Returns:
bool array.
- Return type:
np.ndarray
- Raises:
InconsistentArguments – If mask is the wrong length.
- synthesizer.particle.resample_utils.validate_required_inputs(coordinates, smoothing_lengths, kernel)[source]¶
Validate that required arrays for spatial resampling are provided.
- Parameters:
coordinates (unyt_array or None) – The particle coordinates array.
smoothing_lengths (unyt_array or None) – The particle smoothing lengths array.
kernel (Kernel or None) – The SPH kernel for position sampling.
- Raises:
InconsistentArguments – If anything is missing.